diff --git a/src/internal.c b/src/internal.c index 8a72a675d8..53cc8d0b36 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8669,6 +8669,9 @@ void FreeKeyExchange(WOLFSSL* ssl) { /* Cleanup signature buffer */ if (ssl->buffers.sig.buffer) { + /* May transiently hold the client's DH private exponent in the + * TLS 1.2 diffie_hellman_kea / dhe_psk_kea paths. */ + ForceZero(ssl->buffers.sig.buffer, ssl->buffers.sig.length); XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE); ssl->buffers.sig.buffer = NULL; ssl->buffers.sig.length = 0; diff --git a/src/pk.c b/src/pk.c index e4cfe897d9..8b0dbe705d 100644 --- a/src/pk.c +++ b/src/pk.c @@ -4743,6 +4743,7 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) int ret = 1; word32 pubSz = 0; word32 privSz = 0; + word32 privAllocSz = 0; int localRng = 0; WC_RNG* rng = NULL; WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0); @@ -4792,9 +4793,12 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) else { privSz = pubSz; } - /* Allocate public and private key arrays. */ + /* Allocate public and private key arrays. Preserve the allocation + * size because wc_DhGenerateKeyPair updates privSz in-place. */ + privAllocSz = privSz; pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY); + priv = (unsigned char*)XMALLOC(privAllocSz, NULL, + DYNAMIC_TYPE_PRIVATE_KEY); if (pub == NULL || priv == NULL) { WOLFSSL_ERROR_MSG("Unable to malloc memory"); ret = 0; @@ -4846,7 +4850,10 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) } /* Dispose of allocated data. */ XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY); + if (priv != NULL) { + ForceZero(priv, privAllocSz); + XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY); + } return ret; } diff --git a/src/sniffer.c b/src/sniffer.c index f46da14654..8218131435 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -2459,11 +2459,15 @@ static void FreeSetupKeysArgs(WOLFSSL* ssl, void* pArgs) args->key->type = WC_PK_TYPE_NONE; args->key->initPriv = 0; args->key->initPub = 0; + /* Scrub the raw DH private exponent (and any other key material + * embedded in the union) before release. wc_FreeDhKey above only + * clears the mp_int DhKey, not the separate privKey byte array. + * Use ForceZero (rather than XMEMSET) so the wipe cannot be + * elided by the optimizer. */ + ForceZero(args->key, sizeof(*args->key)); #ifdef WOLFSSL_ASYNC_CRYPT XFREE(args->key, NULL, DYNAMIC_TYPE_SNIFFER_KEY); args->key = NULL; -#else - XMEMSET(args->key, 0, sizeof(args->key)); #endif } diff --git a/src/tls.c b/src/tls.c index f2f60cddfb..8777c4566e 100644 --- a/src/tls.c +++ b/src/tls.c @@ -9063,6 +9063,9 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) if (WOLFSSL_NAMED_GROUP_IS_FFDHE(current->group)) { #ifndef NO_DH wc_FreeDhKey((DhKey*)current->key); + if (current->privKey != NULL && current->privKeyLen > 0) { + ForceZero(current->privKey, current->privKeyLen); + } #endif } else if (current->group == WOLFSSL_ECC_X25519) {