diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 00be607506..35c07d38b6 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -31973,10 +31973,7 @@ static int eccToPKCS8(ecc_key* key, byte* output, word32* outLen, ret = wc_BuildEccKeyDer(key, tmpDer, &sz, includePublic, 0); if (ret < 0) { - #ifndef WOLFSSL_NO_MALLOC - XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + goto exit; } tmpDerSz = (word32)ret; @@ -31984,42 +31981,36 @@ static int eccToPKCS8(ecc_key* key, byte* output, word32* outLen, ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID, curveOID, oidSz); if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { - #ifndef WOLFSSL_NO_MALLOC - XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + goto exit; } if (output == NULL) { - #ifndef WOLFSSL_NO_MALLOC - XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif *outLen = pkcs8Sz; - return WC_NO_ERR_TRACE(LENGTH_ONLY_E); - + ret = WC_NO_ERR_TRACE(LENGTH_ONLY_E); + goto exit; } else if (*outLen < pkcs8Sz) { - #ifndef WOLFSSL_NO_MALLOC - XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key"); - return BUFFER_E; + ret = BUFFER_E; + goto exit; } ret = wc_CreatePKCS8Key(output, &pkcs8Sz, tmpDer, tmpDerSz, algoID, curveOID, oidSz); if (ret < 0) { - #ifndef WOLFSSL_NO_MALLOC - XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + goto exit; } + *outLen = (word32)ret; + +exit: + /* tmpDer holds a plaintext copy of the ECC private key - always zeroize + * it before releasing (or before the stack buffer goes out of scope). */ + ForceZero(tmpDer, ECC_BUFSIZE); #ifndef WOLFSSL_NO_MALLOC XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - *outLen = (word32)ret; return ret; } diff --git a/wolfcrypt/src/wc_mldsa.c b/wolfcrypt/src/wc_mldsa.c index 3e08dad88a..73b7a9b118 100644 --- a/wolfcrypt/src/wc_mldsa.c +++ b/wolfcrypt/src/wc_mldsa.c @@ -7927,6 +7927,12 @@ static int mldsa_make_key_from_seed(wc_MlDsaKey* key, const byte* seed) } #ifndef WC_MLDSA_CACHE_PRIV_VECTORS + /* Zeroize the private vectors s1, s2 and t before freeing. These occupy + * the front of the buffer; any matrix A that follows is public (expanded + * from the public seed) and need not be cleared. */ + if (s1 != NULL) { + ForceZero(s1, (word32)params->s1Sz + 2U * (word32)params->s2Sz); + } XFREE(s1, key->heap, DYNAMIC_TYPE_MLDSA); #endif return ret; @@ -7945,6 +7951,7 @@ static int mldsa_make_key_from_seed(wc_MlDsaKey* key, const byte* seed) unsigned int r; unsigned int s; byte kl[2]; + unsigned int allocSz = 0; #ifdef WOLFSSL_MLDSA_DYNAMIC_KEYS ret = mldsa_alloc_priv_buf(key); @@ -7959,8 +7966,6 @@ static int mldsa_make_key_from_seed(wc_MlDsaKey* key, const byte* seed) /* Allocate memory for large intermediates. */ if (ret == 0) { - unsigned int allocSz; - /* s1-l, s2-k, t-k, a-1 */ allocSz = (unsigned int)params->s1Sz + params->s2Sz + params->s2Sz + (unsigned int)MLDSA_REJ_NTT_POLY_H_SIZE + @@ -8158,6 +8163,15 @@ static int mldsa_make_key_from_seed(wc_MlDsaKey* key, const byte* seed) key->pubKeySet = 1; } + /* Zeroize the whole buffer before freeing. It holds the private vectors + * s1, s2 and t at the front; the rejection-sampling / matrix A region in + * the middle is public, but the trailing t64 accumulator (POLY64 builds) + * holds A o NTT(s1) - from which s1 is recoverable - so it must be + * cleared too. As the secret material is not contiguous, zeroize the + * entire allocation rather than a sub-range. */ + if (s1 != NULL) { + ForceZero(s1, allocSz); + } XFREE(s1, key->heap, DYNAMIC_TYPE_MLDSA); return ret; #endif @@ -8584,7 +8598,14 @@ static int mldsa_sign_with_seed_mu(wc_MlDsaKey* key, ForceZero(priv_rand_seed, sizeof(priv_rand_seed)); if (y != NULL) { - ForceZero(y, allocSz); + word32 zeroSz = allocSz; +#ifndef WC_MLDSA_CACHE_MATRIX_A + /* The public matrix A is appended at the end of the buffer and is + * expanded from the public seed - it need not be zeroized. The + * preceding vectors (y, w0, s1, s2, t0, ...) are secret dependent. */ + zeroSz -= (word32)params->aSz; +#endif + ForceZero(y, zeroSz); } XFREE(y, key->heap, DYNAMIC_TYPE_MLDSA); return ret;