From 1bee35d67063af42e55af1e1368957a52966d0af Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 23 Oct 2026 23:53:34 -0500 Subject: [PATCH 1/9] wolfcrypt/test/test.c: smallstack refactors for test routines: * cert_asn1_test() * cert_load_bad() * cert_test() * fill_signer_twice_test() * cert_dup_ext_test() * cert_crit_unknown_ext_test() * ed25519_test_cert() * ed25519_test_make_cert() * ed448_test_cert() * ed448_test_make_cert() * mlkem_certgen_test() Also hardens cleanup paths in cert_test() and fill_signer_twice_test() against FreeDecodedCert() on never-initialized or already-freed state. --- wolfcrypt/test/test.c | 209 ++++++++++++++++++++++++++---------------- 1 file changed, 130 insertions(+), 79 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index af94bccc7f2..7476b692473 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -38689,10 +38689,13 @@ static wc_test_ret_t cert_asn1_test(void) { wc_test_ret_t ret; int len[3]; - DecodedCert cert; + WC_DECLARE_VAR(cert, DecodedCert, 1, HEAP_HINT); byte certData[114]; byte* badCert = NULL; + WC_ALLOC_VAR_EX(cert, DecodedCert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + return WC_TEST_RET_ENC_ERRNO); + len[2] = add_data(certData, 0, minSerial, (byte)sizeof(minSerial)); len[2] = add_data(certData, len[2], minSigAlg, (byte)sizeof(minSigAlg)); len[2] = add_data(certData, len[2], minName, (byte)sizeof(minName)); @@ -38705,9 +38708,9 @@ static wc_test_ret_t cert_asn1_test(void) len[0] = add_seq(certData, 0, certData, len[1]); /* Minimal good certificate */ - InitDecodedCert(&cert, certData, len[0], 0); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); - FreeDecodedCert(&cert); + InitDecodedCert(cert, certData, len[0], 0); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); + FreeDecodedCert(cert); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -38725,9 +38728,9 @@ static wc_test_ret_t cert_asn1_test(void) /* Put data into allocated buffer to allow access error checking. */ badCert = (byte*)XMALLOC(len[0], HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XMEMCPY(badCert, certData, len[0]); - InitDecodedCert(&cert, badCert, len[0], 0); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); - FreeDecodedCert(&cert); + InitDecodedCert(cert, badCert, len[0], 0); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); + FreeDecodedCert(cert); if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); } @@ -38737,19 +38740,22 @@ static wc_test_ret_t cert_asn1_test(void) done: XFREE(badCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } static wc_test_ret_t cert_load_bad(const char* fname, byte* tmp, int err) { wc_test_ret_t ret; - DecodedCert cert; + WC_DECLARE_VAR(cert, DecodedCert, 1, HEAP_HINT); XFILE file; size_t bytes; if ((fname == NULL) || (tmp == NULL)) { ERROR_OUT(WC_TEST_RET_ENC_NC, done); } + WC_ALLOC_VAR_EX(cert, DecodedCert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); file = XFOPEN(fname, "rb"); if (!file) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); @@ -38759,15 +38765,16 @@ static wc_test_ret_t cert_load_bad(const char* fname, byte* tmp, int err) if (bytes == 0) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); } - InitDecodedCert(&cert, tmp, (word32)bytes, 0); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); - FreeDecodedCert(&cert); + InitDecodedCert(cert, tmp, (word32)bytes, 0); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); + FreeDecodedCert(cert); if (ret != err) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); } ret = 0; done: + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -38808,7 +38815,7 @@ static wc_test_ret_t cert_bad_asn1_test(void) WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) { #if !defined(NO_FILESYSTEM) - DecodedCert cert; + WC_DECLARE_VAR(cert, DecodedCert, 1, HEAP_HINT); byte* tmp; size_t bytes; XFILE file; @@ -38819,6 +38826,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return WC_TEST_RET_ENC_ERRNO; + /* Calloc so that FreeDecodedCert() at done: is a no-op on paths that + * don't reach InitDecodedCert(). + */ + WC_CALLOC_VAR_EX(cert, DecodedCert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); /* Certificate with Name Constraints extension. */ file = XFOPEN(certExtNc, "rb"); @@ -38829,11 +38841,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) XFCLOSE(file); if (bytes == 0) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); - InitDecodedCert(&cert, tmp, (word32)bytes, 0); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + InitDecodedCert(cert, tmp, (word32)bytes, 0); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - FreeDecodedCert(&cert); + FreeDecodedCert(cert); + XMEMSET(cert, 0, sizeof(*cert)); /* Certificate with Inhibit Any Policy extension. RFC 5280 4.2.1.14 requires * it to be critical and wolfSSL does not process it, so it is rejected. */ @@ -38845,8 +38858,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) XFCLOSE(file); if (bytes == 0) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); - InitDecodedCert(&cert, tmp, (word32)bytes, 0); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + InitDecodedCert(cert, tmp, (word32)bytes, 0); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); #ifndef WOLFSSL_NO_ASN_STRICT if (ret != WC_NO_ERR_TRACE(ASN_CRIT_EXT_E)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -38855,7 +38868,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); #endif - FreeDecodedCert(&cert); + FreeDecodedCert(cert); + XMEMSET(cert, 0, sizeof(*cert)); /* Certificate with Netscape Certificate Type extension. */ file = XFOPEN(certExtNct, "rb"); @@ -38866,8 +38880,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) XFCLOSE(file); if (bytes == 0) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); - InitDecodedCert(&cert, tmp, (word32)bytes, 0); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + InitDecodedCert(cert, tmp, (word32)bytes, 0); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); #ifndef IGNORE_NETSCAPE_CERT_TYPE if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -38879,7 +38893,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_test(void) #endif done: - FreeDecodedCert(&cert); + FreeDecodedCert(cert); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif /* !NO_FILESYSTEM */ @@ -39156,7 +39171,7 @@ static wc_test_ret_t cert_no_malloc_test(void) * ownership, so a second call doesn't copy stale NULL pointers. */ static wc_test_ret_t fill_signer_twice_test(void) { - DecodedCert cert; + WC_DECLARE_VAR(cert, DecodedCert, 1, HEAP_HINT); Signer* signer1 = NULL; Signer* signer2 = NULL; DerBuffer* der = NULL; @@ -39170,6 +39185,11 @@ static wc_test_ret_t fill_signer_twice_test(void) tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return WC_TEST_RET_ENC_ERRNO; + /* Calloc so that FreeDecodedCert() at done: is a no-op on paths that + * don't reach InitDecodedCert(). + */ + WC_CALLOC_VAR_EX(cert, DecodedCert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); /* Load a DER certificate. */ file = XFOPEN(certExtNc, "rb"); @@ -39188,13 +39208,13 @@ static wc_test_ret_t fill_signer_twice_test(void) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); XMEMCPY(der->buffer, tmp, bytes); - InitDecodedCert(&cert, tmp, (word32)bytes, 0); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + InitDecodedCert(cert, tmp, (word32)bytes, 0); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); /* After parsing, pubKeyStored should be set and publicKey non-NULL. */ - if (!cert.pubKeyStored || cert.publicKey == NULL) { + if (!cert->pubKeyStored || cert->publicKey == NULL) { ERROR_OUT(WC_TEST_RET_ENC_NC, done); } @@ -39203,7 +39223,7 @@ static wc_test_ret_t fill_signer_twice_test(void) if (signer1 == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); - ret = FillSigner(signer1, &cert, CA_TYPE, der); + ret = FillSigner(signer1, cert, CA_TYPE, der); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -39213,18 +39233,18 @@ static wc_test_ret_t fill_signer_twice_test(void) } /* After FillSigner, cert->publicKey should be NULL. */ - if (cert.publicKey != NULL) { + if (cert->publicKey != NULL) { ERROR_OUT(WC_TEST_RET_ENC_NC, done); } /* BUG CHECK: pubKeyStored should have been cleared to 0. * If it is still set, a second FillSigner would copy a NULL pointer. */ - if (cert.pubKeyStored != 0) { + if (cert->pubKeyStored != 0) { ERROR_OUT(WC_TEST_RET_ENC_NC, done); } /* Also check subjectCNStored is cleared. */ - if (cert.subjectCNStored != 0) { + if (cert->subjectCNStored != 0) { ERROR_OUT(WC_TEST_RET_ENC_NC, done); } @@ -39233,7 +39253,7 @@ static wc_test_ret_t fill_signer_twice_test(void) if (signer2 == NULL) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); - ret = FillSigner(signer2, &cert, CA_TYPE, der); + ret = FillSigner(signer2, cert, CA_TYPE, der); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -39243,7 +39263,8 @@ static wc_test_ret_t fill_signer_twice_test(void) } done: - FreeDecodedCert(&cert); + FreeDecodedCert(cert); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (signer1 != NULL) FreeSigner(signer1, HEAP_HINT); if (signer2 != NULL) @@ -43758,12 +43779,15 @@ static const byte dupKeyUsageCert[] = { WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_dup_ext_test(void) { wc_test_ret_t ret; - DecodedCert cert; + WC_DECLARE_VAR(cert, DecodedCert, 1, HEAP_HINT); - InitDecodedCert(&cert, dupKeyUsageCert, (word32)sizeof(dupKeyUsageCert), + WC_ALLOC_VAR_EX(cert, DecodedCert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + return WC_TEST_RET_ENC_ERRNO); + InitDecodedCert(cert, dupKeyUsageCert, (word32)sizeof(dupKeyUsageCert), NULL); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); - FreeDecodedCert(&cert); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); + FreeDecodedCert(cert); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (ret == 0) /* expected rejection, got accept */ return WC_TEST_RET_ENC_NC; if (ret != WC_NO_ERR_TRACE(ASN_OBJECT_ID_E)) @@ -43777,12 +43801,15 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_dup_ext_test(void) WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cert_crit_unknown_ext_test(void) { wc_test_ret_t ret; - DecodedCert cert; + WC_DECLARE_VAR(cert, DecodedCert, 1, HEAP_HINT); - InitDecodedCert(&cert, critUnknownExtCert, + WC_ALLOC_VAR_EX(cert, DecodedCert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + return WC_TEST_RET_ENC_ERRNO); + InitDecodedCert(cert, critUnknownExtCert, (word32)sizeof(critUnknownExtCert), NULL); - ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); - FreeDecodedCert(&cert); + ret = ParseCert(cert, CERT_TYPE, NO_VERIFY, NULL); + FreeDecodedCert(cert); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (ret == 0) /* expected rejection, got accept */ return WC_TEST_RET_ENC_NC; if (ret != WC_NO_ERR_TRACE(ASN_CRIT_EXT_E)) @@ -60781,7 +60808,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve25519_test(void) #ifdef WOLFSSL_TEST_CERT static wc_test_ret_t ed25519_test_cert(void) { - DecodedCert cert[2]; + WC_DECLARE_VAR(cert, DecodedCert, 2, HEAP_HINT); DecodedCert* serverCert = NULL; DecodedCert* caCert = NULL; #ifdef HAVE_ED25519_VERIFY @@ -60798,6 +60825,8 @@ static wc_test_ret_t ed25519_test_cert(void) if (tmp == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); } + WC_ALLOC_VAR_EX(cert, DecodedCert, 2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); #ifdef USE_CERT_BUFFERS_256 XMEMCPY(tmp, ca_ed25519_cert, sizeof_ca_ed25519_cert); @@ -60872,6 +60901,7 @@ static wc_test_ret_t ed25519_test_cert(void) FreeDecodedCert(caCert); if (serverCert != NULL) FreeDecodedCert(serverCert); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -60879,15 +60909,13 @@ static wc_test_ret_t ed25519_test_cert(void) static wc_test_ret_t ed25519_test_make_cert(void) { WC_RNG rng; - Cert cert; - DecodedCert decode; + WC_DECLARE_VAR(cert, Cert, 1, HEAP_HINT); + WC_DECLARE_VAR(decode, DecodedCert, 1, HEAP_HINT); ed25519_key key; ed25519_key* privKey = NULL; wc_test_ret_t ret = 0; byte* tmp = NULL; - wc_InitCert_ex(&cert, HEAP_HINT, devId); - #ifndef HAVE_FIPS ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); #else @@ -60896,23 +60924,30 @@ static wc_test_ret_t ed25519_test_make_cert(void) if (ret != 0) return WC_TEST_RET_ENC_EC(ret); + WC_ALLOC_VAR_EX(cert, Cert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); + WC_ALLOC_VAR_EX(decode, DecodedCert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); + + wc_InitCert_ex(cert, HEAP_HINT, devId); + wc_ed25519_init(&key); privKey = &key; wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, privKey); - cert.daysValid = 365 * 2; - cert.selfSigned = 1; - XMEMCPY(&cert.issuer, &certDefaultName, sizeof(CertName)); - XMEMCPY(&cert.subject, &certDefaultName, sizeof(CertName)); - cert.isCA = 0; + cert->daysValid = 365 * 2; + cert->selfSigned = 1; + XMEMCPY(&cert->issuer, &certDefaultName, sizeof(CertName)); + XMEMCPY(&cert->subject, &certDefaultName, sizeof(CertName)); + cert->isCA = 0; #ifdef WOLFSSL_CERT_EXT - ret = wc_SetKeyUsage(&cert, certKeyUsage); + ret = wc_SetKeyUsage(cert, certKeyUsage); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + ret = wc_SetSubjectKeyIdFromPublicKey_ex(cert, ED25519_TYPE, privKey); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + ret = wc_SetAuthKeyIdFromPublicKey_ex(cert, ED25519_TYPE, privKey); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); #endif @@ -60921,18 +60956,18 @@ static wc_test_ret_t ed25519_test_make_cert(void) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); } - cert.sigType = CTC_ED25519; - ret = wc_MakeCert_ex(&cert, tmp, FOURK_BUF, ED25519_TYPE, privKey, &rng); + cert->sigType = CTC_ED25519; + ret = wc_MakeCert_ex(cert, tmp, FOURK_BUF, ED25519_TYPE, privKey, &rng); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - ret = wc_SignCert_ex(cert.bodySz, cert.sigType, tmp, FOURK_BUF, + ret = wc_SignCert_ex(cert->bodySz, cert->sigType, tmp, FOURK_BUF, ED25519_TYPE, privKey, &rng); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - InitDecodedCert(&decode, tmp, (word32)ret, HEAP_HINT); - ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); - FreeDecodedCert(&decode); + InitDecodedCert(decode, tmp, (word32)ret, HEAP_HINT); + ret = ParseCert(decode, CERT_TYPE, NO_VERIFY, 0); + FreeDecodedCert(decode); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -60940,6 +60975,8 @@ static wc_test_ret_t ed25519_test_make_cert(void) XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_ed25519_free(privKey); wc_FreeRng(&rng); + WC_FREE_VAR_EX(decode, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } #endif /* WOLFSSL_TEST_CERT */ @@ -63022,7 +63059,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t curve448_test(void) #ifdef WOLFSSL_TEST_CERT static wc_test_ret_t ed448_test_cert(void) { - DecodedCert cert[2]; + WC_DECLARE_VAR(cert, DecodedCert, 2, HEAP_HINT); DecodedCert* serverCert = NULL; DecodedCert* caCert = NULL; #ifdef HAVE_ED448_VERIFY @@ -63039,6 +63076,8 @@ static wc_test_ret_t ed448_test_cert(void) if (tmp == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); } + WC_ALLOC_VAR_EX(cert, DecodedCert, 2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); #ifdef USE_CERT_BUFFERS_256 XMEMCPY(tmp, ca_ed448_cert, sizeof_ca_ed448_cert); @@ -63113,6 +63152,7 @@ static wc_test_ret_t ed448_test_cert(void) FreeDecodedCert(caCert); if (serverCert != NULL) FreeDecodedCert(serverCert); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -63120,15 +63160,13 @@ static wc_test_ret_t ed448_test_cert(void) static wc_test_ret_t ed448_test_make_cert(void) { WC_RNG rng; - Cert cert; - DecodedCert decode; + WC_DECLARE_VAR(cert, Cert, 1, HEAP_HINT); + WC_DECLARE_VAR(decode, DecodedCert, 1, HEAP_HINT); ed448_key key; ed448_key* privKey = NULL; wc_test_ret_t ret = 0; byte* tmp = NULL; - wc_InitCert_ex(&cert, HEAP_HINT, devId); - #ifndef HAVE_FIPS ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); #else @@ -63137,23 +63175,30 @@ static wc_test_ret_t ed448_test_make_cert(void) if (ret != 0) return WC_TEST_RET_ENC_EC(ret); + WC_ALLOC_VAR_EX(cert, Cert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); + WC_ALLOC_VAR_EX(decode, DecodedCert, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done)); + + wc_InitCert_ex(cert, HEAP_HINT, devId); + wc_ed448_init(&key); privKey = &key; wc_ed448_make_key(&rng, ED448_KEY_SIZE, privKey); - cert.daysValid = 365 * 2; - cert.selfSigned = 1; - XMEMCPY(&cert.issuer, &certDefaultName, sizeof(CertName)); - XMEMCPY(&cert.subject, &certDefaultName, sizeof(CertName)); - cert.isCA = 0; + cert->daysValid = 365 * 2; + cert->selfSigned = 1; + XMEMCPY(&cert->issuer, &certDefaultName, sizeof(CertName)); + XMEMCPY(&cert->subject, &certDefaultName, sizeof(CertName)); + cert->isCA = 0; #ifdef WOLFSSL_CERT_EXT - ret = wc_SetKeyUsage(&cert, certKeyUsage); + ret = wc_SetKeyUsage(cert, certKeyUsage); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED448_TYPE, privKey); + ret = wc_SetSubjectKeyIdFromPublicKey_ex(cert, ED448_TYPE, privKey); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED448_TYPE, privKey); + ret = wc_SetAuthKeyIdFromPublicKey_ex(cert, ED448_TYPE, privKey); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); #endif @@ -63162,18 +63207,18 @@ static wc_test_ret_t ed448_test_make_cert(void) ERROR_OUT(WC_TEST_RET_ENC_ERRNO, done); } - cert.sigType = CTC_ED448; - ret = wc_MakeCert_ex(&cert, tmp, FOURK_BUF, ED448_TYPE, privKey, &rng); + cert->sigType = CTC_ED448; + ret = wc_MakeCert_ex(cert, tmp, FOURK_BUF, ED448_TYPE, privKey, &rng); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - ret = wc_SignCert_ex(cert.bodySz, cert.sigType, tmp, FOURK_BUF, ED448_TYPE, - privKey, &rng); + ret = wc_SignCert_ex(cert->bodySz, cert->sigType, tmp, FOURK_BUF, + ED448_TYPE, privKey, &rng); if (ret < 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); - InitDecodedCert(&decode, tmp, (word32)ret, HEAP_HINT); - ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); - FreeDecodedCert(&decode); + InitDecodedCert(decode, tmp, (word32)ret, HEAP_HINT); + ret = ParseCert(decode, CERT_TYPE, NO_VERIFY, 0); + FreeDecodedCert(decode); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -63181,6 +63226,8 @@ static wc_test_ret_t ed448_test_make_cert(void) XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_ed448_free(privKey); wc_FreeRng(&rng); + WC_FREE_VAR_EX(decode, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(cert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } #endif /* WOLFSSL_TEST_CERT */ @@ -69676,7 +69723,7 @@ static wc_test_ret_t mlkem_certgen_test(void) wc_test_ret_t ret = 0; int i; WC_RNG rng; - ecc_key ca[1]; + WC_DECLARE_VAR(ca, ecc_key, 1, HEAP_HINT); int rngInit = 0; int caInit = 0; static const struct { @@ -69697,6 +69744,9 @@ static wc_test_ret_t mlkem_certgen_test(void) { -1, 0, NULL } }; + WC_ALLOC_VAR_EX(ca, ecc_key, 1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER, + return WC_TEST_RET_ENC_ERRNO); + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); if (ret == 0) rngInit = 1; @@ -69721,6 +69771,7 @@ static wc_test_ret_t mlkem_certgen_test(void) if (caInit) wc_ecc_free(ca); + WC_FREE_VAR_EX(ca, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (rngInit) wc_FreeRng(&rng); From 19e71c8f4be4e62b2d11a93dffcdf3796bafc750 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 23 Oct 2026 23:54:12 -0500 Subject: [PATCH 2/9] m4/ax_vcs_checkout.m4: fix VCS detection to check in $srcdir rather than the build dir, which may be out-of-tree. Note, this fixes out-of-tree builds to activate -Werror with version-controlled sources. --- m4/ax_vcs_checkout.m4 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/m4/ax_vcs_checkout.m4 b/m4/ax_vcs_checkout.m4 index 63d5e9bea5d..ef9c00d4667 100644 --- a/m4/ax_vcs_checkout.m4 +++ b/m4/ax_vcs_checkout.m4 @@ -45,19 +45,22 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#serial 6.1 +#serial 6.2 # # Added tweak for git. The base repo's .git is a directory. Any worktree's # .git is a file. Use -e to check for either dir or file. +# 6.2 adds ${srcdir} to the tests, so that detection works as expected in +# out-of-tree builds. + AC_DEFUN([AX_VCS_SYSTEM], [AC_PREREQ([2.63])dnl AC_CACHE_CHECK([for vcs system], [ac_cv_vcs_system], [ac_cv_vcs_system="none" - AS_IF([test -d ".bzr"],[ac_cv_vcs_system="bazaar"]) - AS_IF([test -d ".svn"],[ac_cv_vcs_system="svn"]) - AS_IF([test -d ".hg"],[ac_cv_vcs_system="mercurial"]) - AS_IF([test -e ".git"],[ac_cv_vcs_system="git"]) + AS_IF([test -d "${srcdir}/.bzr"],[ac_cv_vcs_system="bazaar"]) + AS_IF([test -d "${srcdir}/.svn"],[ac_cv_vcs_system="svn"]) + AS_IF([test -d "${srcdir}/.hg"],[ac_cv_vcs_system="mercurial"]) + AS_IF([test -e "${srcdir}/.git"],[ac_cv_vcs_system="git"]) ]) AC_DEFINE_UNQUOTED([VCS_SYSTEM],["$ac_cv_vcs_system"],[VCS system]) ]) From 0c5094ce1823e50befb31e659273188aef122e55 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 23 Oct 2026 23:54:26 -0500 Subject: [PATCH 3/9] .github/workflows/smallStackSize.yml: add coverage using --enable-testcert --enable-all-quantum-crypto, and consolidate the asm entries using --enable-all-asm. --- .github/workflows/smallStackSize.yml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/smallStackSize.yml b/.github/workflows/smallStackSize.yml index cead8ac9964..dd5236712a0 100644 --- a/.github/workflows/smallStackSize.yml +++ b/.github/workflows/smallStackSize.yml @@ -82,17 +82,9 @@ jobs: "--enable-faultharden", "CPPFLAGS=-DWOLFSSL_MLDSA_SIGN_SMALL_MEM -DWOLFSSL_MLDSA_VERIFY_SMALL_MEM -DWOLFSSL_MLDSA_MAKE_KEY_SMALL_MEM"]}, {"name": "noasm-allcrypto-pq", - "configure": ["--disable-asm", "--enable-all-crypto", - "--enable-mlkem", "--enable-lms", "--enable-xmss", "--enable-mldsa"]}, - {"name": "intelasm", - "configure": ["--enable-intelasm", "--enable-sp-asm"]}, - {"name": "intelasm-pq", - "configure": ["--enable-intelasm", "--enable-sp-asm", - "--enable-mlkem", "--enable-lms", "--enable-xmss", "--enable-mldsa"]}, - {"name": "intelasm-allcrypto-pq", - "configure": ["--enable-intelasm", "--enable-sp-asm", - "--enable-all-crypto", "--enable-mlkem", "--enable-lms", - "--enable-xmss", "--enable-mldsa"]} + "configure": ["--disable-asm", "--enable-all-crypto", "--enable-testcert", "--enable-all-quantum-crypto"]}, + {"name": "all-asm-allcrypto-pq", + "configure": ["--enable-all-asm", "--enable-all-crypto", "--enable-testcert", "--enable-all-quantum-crypto"]} ]} EOF .github/scripts/parallel-make-check.py \ From 4abe76dcd970a7f9363afce151bcc1a8a73274dc Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 23 Oct 2026 23:54:37 -0500 Subject: [PATCH 4/9] wolfcrypt/src/aes.c: fix uninitvar around nonce in wc_AesGcmSetKey(). --- wolfcrypt/src/aes.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 6384ff7aa8b..fca02cf3377 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -9224,6 +9224,7 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) int ret; byte iv[WC_AES_BLOCK_SIZE]; byte nonce[WC_AES_BLOCK_SIZE]; + const byte* setKeyIv = iv; #ifdef WOLFSSL_IMX6_CAAM_BLOB byte local[32]; @@ -9266,9 +9267,9 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) /* Keep a nonce cached by wc_AesGcmSetIV() or wc_AesGcmSetExtIV(). */ if (aes->nonceSz != 0) { XMEMCPY(nonce, aes->reg, sizeof(nonce)); + setKeyIv = nonce; } - ret = wc_AesSetKey(aes, key, len, (aes->nonceSz != 0) ? nonce : iv, - AES_ENCRYPTION); + ret = wc_AesSetKey(aes, key, len, setKeyIv, AES_ENCRYPTION); #ifndef WOLFSSL_NO_AES_TAG_ASSOCIATION /* new key, so the tag length of the old one no longer applies */ if (ret == 0) { From e6698e866ecf6acdb010413eda8ff87c4e236906 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Sat, 24 Oct 2026 00:04:37 -0500 Subject: [PATCH 5/9] wolfcrypt/src/random.c: fix uninitvar around digest in Hash_gen(), and fix identicalConditionAfterEarlyExit around seed in wc_InitRngNonce_UserSeed(). --- wolfcrypt/src/random.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 96f078b9007..aa805e711be 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1720,6 +1720,7 @@ static WARN_UNUSED_RESULT int Hash_gen(DRBG_internal* drbg, byte* out, wc_MemZero_Add("Hash_gen data", data, DRBG_SEED_LEN); #ifndef WOLFSSL_SMALL_STACK_CACHE /* cached digest is the caller's drbg->digest_scratch, already registered */ + XMEMSET(digest, 0, WC_SHA256_DIGEST_SIZE); wc_MemZero_Add("Hash_gen digest", digest, WC_SHA256_DIGEST_SIZE); #endif #endif @@ -4305,8 +4306,6 @@ int wc_InitRngNonce_UserSeed(WC_RNG* rng, return BAD_FUNC_ARG; if (rng == NULL) return BAD_FUNC_ARG; - if (seed == NULL && seedSz != 0) - return BAD_FUNC_ARG; if (nonce == NULL && nonceSz != 0) return BAD_FUNC_ARG; if (perso == NULL && persoSz != 0) @@ -4314,6 +4313,8 @@ int wc_InitRngNonce_UserSeed(WC_RNG* rng, #ifdef HAVE_HASHDRBG if (seedSz < UserSeedSzFloor(flags)) return BAD_LENGTH_E; +#else + (void)seedSz; #endif #ifndef WC_RNG_HAVE_RBGC /* argument-legal calls must be refused if provenance tracking (RBGC) isn't From 59f56c1db2d2697b1155127c1c7f9cf58a195be3 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Sat, 24 Oct 2026 00:04:48 -0500 Subject: [PATCH 6/9] wolfssl/wolfcrypt/mem_track.h: fix invalidPrintfArgType_sint in TrackMalloc(), TrackFree(), and ShowMemoryTracker(). --- wolfssl/wolfcrypt/mem_track.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wolfssl/wolfcrypt/mem_track.h b/wolfssl/wolfcrypt/mem_track.h index 8792b178ecd..6b77c2b1693 100644 --- a/wolfssl/wolfcrypt/mem_track.h +++ b/wolfssl/wolfcrypt/mem_track.h @@ -177,7 +177,7 @@ static WC_INLINE void* TrackMalloc(size_t sz) #ifdef WOLFSSL_DEBUG_MEMORY #ifdef WOLFSSL_DEBUG_MEMORY_PRINT - wc_mem_printf("Alloc: %p -> %u at %s:%d\n", + wc_mem_printf("Alloc: %p -> %u at %s:%u\n", header->thisMemory, (word32)sz, func, line); #else (void)func; @@ -298,7 +298,7 @@ static WC_INLINE void TrackFree(void* ptr) #ifdef WOLFSSL_DEBUG_MEMORY #ifdef WOLFSSL_DEBUG_MEMORY_PRINT - wc_mem_printf("Free: %p -> %u at %s:%d\n", ptr, (word32)sz, func, line); + wc_mem_printf("Free: %p -> %u at %s:%u\n", ptr, (word32)sz, func, line); #else (void)func; (void)line; @@ -438,7 +438,7 @@ static WC_INLINE void ShowMemoryTracker(void) header != NULL; header = header->next) { #ifdef WOLFSSL_DEBUG_MEMORY - wc_mem_printf("Leak: Ptr %p, Size %u, Func %s, Line %d\n", + wc_mem_printf("Leak: Ptr %p, Size %u, Func %s, Line %u\n", (byte*)header + sizeof(memHint), (unsigned int)header->thisSize, header->func, header->line); #else From 4f8fa3d212b5e39d1a47bc7cc7080fd8b6878906 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Sat, 24 Oct 2026 00:28:23 -0500 Subject: [PATCH 7/9] wolfcrypt/src/wc_xmss_impl.c: fixes for -Wsign-conversion. --- wolfcrypt/src/wc_xmss_impl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/wc_xmss_impl.c b/wolfcrypt/src/wc_xmss_impl.c index bb35da38167..9aadbcc6313 100644 --- a/wolfcrypt/src/wc_xmss_impl.c +++ b/wolfcrypt/src/wc_xmss_impl.c @@ -2503,7 +2503,7 @@ static void wc_xmss_n_way_fused_get(XmssState* state, word32 lanes, word32 l, * the state that way too. */ for (i = 0; i < 4; i++) { word64 v = state->n_way_state[i * lanes + l]; - int k; + word32 k; for (k = 0; k < 8; k++) { out[i * 8 + k] = (byte)(v >> (8 * k)); @@ -2516,7 +2516,7 @@ static void wc_xmss_n_way_fused_get(XmssState* state, word32 lanes, word32 l, if (state->params->n == XMSS_SHA512_64_N) { for (i = 0; i < 8; i++) { word64 v = state->n_way_st512[i * lanes + l]; - int k; + word32 k; for (k = 0; k < 8; k++) { out[i * 8 + k] = (byte)(v >> ((7 - k) * 8)); @@ -2556,7 +2556,7 @@ static void wc_xmss_n_way_fused_set(XmssState* state, word32 lanes, word32 l, int k; for (k = 7; k >= 0; k--) { - t = (t << 8) | (word64)v[i * 8 + k]; + t = (t << 8) | (word64)v[i * 8 + (word32)k]; } state->n_way_state[i * lanes + l] = t; } @@ -2567,7 +2567,7 @@ static void wc_xmss_n_way_fused_set(XmssState* state, word32 lanes, word32 l, if (state->params->n == XMSS_SHA512_64_N) { for (i = 0; i < 8; i++) { word64 t = 0; - int k; + word32 k; for (k = 0; k < 8; k++) { t = (t << 8) | (word64)v[i * 8 + k]; @@ -2643,13 +2643,13 @@ static void wc_xmss_n_way_fused_step(XmssState* state, const byte* addr, for (i = 0; i < 2U * XMSS_SHA256_32_N / 8U; i++) { pfx[i] = 0; for (k = 7; k >= 0; k--) { - pfx[i] = (pfx[i] << 8) | (word64)state->prf_buf[i * 8 + k]; + pfx[i] = (pfx[i] << 8) | (word64)state->prf_buf[i * 8 + (word32)k]; } } for (i = 0; i < (WC_XMSS_ADDR_LEN / 8); i++) { adrs[i] = 0; for (k = 7; k >= 0; k--) { - adrs[i] = (adrs[i] << 8) | (word64)addr[i * 8 + k]; + adrs[i] = (adrs[i] << 8) | (word64)addr[i * 8 + (word32)k]; } } /* The kernel masks out the two bytes that vary between lanes; the From 6319ff4e347652742d38a28a040be77f3a3cf529 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Sat, 24 Oct 2026 00:28:52 -0500 Subject: [PATCH 8/9] wolfcrypt/src/pkcs12.c: fix -Wnonnull (fortified memcpy) in wc_i2d_PKCS12() in WOLFSSL_NO_MALLOC builds: gate the trailing signData copy on local sdBuf rather than re-reading pkcs12->signData, which conservative aliasing treats as mutable across the intervening calls, licensing a path where sdBuf is constant NULL (XMALLOC()) with the guard true. --- wolfcrypt/src/pkcs12.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 054f1b90702..4ac324a05c9 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -1095,7 +1095,7 @@ int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz) XMEMCPY(&buf[idx], pkcs12->safe->data, pkcs12->safe->dataSz); idx += pkcs12->safe->dataSz; - if (pkcs12->signData != NULL) { + if (sdBuf != NULL) { XMEMCPY(&buf[idx], sdBuf, sdBufSz); } From d768f3d188aa820e7b92ca83d9ec6d91fc96f2da Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Sat, 24 Oct 2026 00:29:14 -0500 Subject: [PATCH 9/9] src/internal.c: fix -Wmaybe-uninitialized around keySz in DoClientKeyExchange(), in the rsa_kea and static_ecdh paths -- gcc can't prove DecodePrivateKey() writes *sigLen on every zero-return path, and a deterministic zero length beats stack garbage if one ever exists. --- src/internal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal.c b/src/internal.c index 95b71ddbfd1..e4585216985 100644 --- a/src/internal.c +++ b/src/internal.c @@ -46731,7 +46731,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], #ifndef NO_RSA case rsa_kea: { - word32 keySz; + word32 keySz = 0; ssl->buffers.keyType = rsa_sa_algo; ret = DecodePrivateKey(ssl, &keySz); @@ -46820,7 +46820,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], if (ssl->specs.static_ecdh && ssl->ecdhCurveOID != ECC_X25519_OID && ssl->ecdhCurveOID != ECC_X448_OID) { - word32 keySz; + word32 keySz = 0; ssl->buffers.keyType = ecc_dsa_sa_algo; ret = DecodePrivateKey(ssl, &keySz);