From 30b93391fa4034721b8bcf6ba13bbe20303cbcbb Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Oct 2026 17:08:13 -0500 Subject: [PATCH 01/28] linuxkm/Kbuild: fix+improve handling for CONFIG_MITIGATION_RETPOLINE, CONFIG_MITIGATION_RETHUNK, and CONFIG_OBJTOOL; use inline/kept thunks and globally disable objtool wherever needed and not otherwise; accommodate/error for clang as needed. Note this fixes a preexisting swap flub re RETPOLINE and RETHUNK. Also tabify some whitespace. --- linuxkm/Kbuild | 103 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 25 deletions(-) diff --git a/linuxkm/Kbuild b/linuxkm/Kbuild index ff73672e8a7..a6acbfb784a 100644 --- a/linuxkm/Kbuild +++ b/linuxkm/Kbuild @@ -147,7 +147,18 @@ endif ccflags-y = $(WOLFSSL_CFLAGS) $(WOLFSSL_CFLAGS_NO_VECTOR_INSNS) +# Retpoline mitigation for Spectre v2 was added in 4.15, but under knob +# CONFIG_RETPOLINE, and return thunk mitigation for retbleed was added +# in 5.19, but under knob CONFIG_RETHUNK. The current knob names were +# merged in 6.9; alias to current names so one set of conditionals +# serves both. +CONFIG_MITIGATION_RETPOLINE ?= $(CONFIG_RETPOLINE) +CONFIG_MITIGATION_RETHUNK ?= $(CONFIG_RETHUNK) + ifeq "$(ENABLED_LINUXKM_PIE)" "yes" + ifdef CONFIG_CFI_CLANG + $(error CONFIG_CFI_CLANG is not compatible with ENABLED_LINUXKM_PIE.) + endif # note, we need -fno-stack-protector to avoid references to # "__stack_chk_fail" from the wolfCrypt container. PIE_FLAGS := -DWC_CONTAINERIZE_THIS -fno-stack-protector -fno-toplevel-reorder @@ -206,44 +217,86 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes" ifeq "$(KERNEL_ARCH_X86)" "yes" PIE_FLAGS += -mcmodel=small - # eliminate external references to __x86_return_thunk and - # __x86_indirect_thunk_foo implementations. _all_ references must be - # eliminated, not just those in PIE objects, otherwise some kernels will + # eliminate external references to __x86_return_thunk (via + # -mfunction-return=thunk-inline) and __x86_indirect_thunk_foo (via + # -mindirect-branch=thunk-inline). _all_ references must be eliminated, + # not just those in PIE objects, otherwise some kernels will # false-positively complain about unpatched thunks. - ifeq "$(CONFIG_MITIGATION_RETPOLINE)" "y" - PIE_SUPPORT_FLAGS += -mfunction-return=thunk-inline - else - PIE_SUPPORT_FLAGS += -mfunction-return=keep - endif - ifeq "$(CONFIG_MITIGATION_RETHUNK)" "y" - PIE_SUPPORT_FLAGS += -mindirect-branch=thunk-inline - else - PIE_SUPPORT_FLAGS += -mindirect-branch=keep - endif + + NO_EXTERNAL_THUNKS := y OBJECT_FILES_NON_STANDARD := y endif ifeq "$(KERNEL_ARCH)" "arm" - PIE_FLAGS += -fno-unwind-tables + PIE_FLAGS += -fno-unwind-tables endif ifeq "$(KERNEL_ARCH)" "mips" - PIE_FLAGS += -mabicalls + PIE_FLAGS += -mabicalls endif - ccflags-y += $(PIE_SUPPORT_FLAGS) $(WOLFCRYPT_PIE_FILES): ccflags-y += $(PIE_FLAGS) $(WOLFCRYPT_PIE_FILES): ccflags-remove-y += -pg \ - $(call cc-option,-ftrivial-auto-var-init=zero) + $(call cc-option,-ftrivial-auto-var-init=zero) +endif + +# An explicit FORCE_GLOBAL_OBJTOOL_OFF is refused outright with clang -- the +# thunk repair below is gcc-only. +ifdef CONFIG_CC_IS_CLANG + ifdef FORCE_GLOBAL_OBJTOOL_OFF + $(error FORCE_GLOBAL_OBJTOOL_OFF is not supported with clang.) + endif endif -# On some kernels/configs, objtool runs and warns on the linked libwolfssl.o, -# ignoring the below "OBJECT_FILES_NON_STANDARD := y" annotations. This -# mechanism, activated with "make KBUILD_EXTRA_FLAGS=FORCE_GLOBAL_OBJTOOL_OFF=1", -# inhibits objtool completely. This may be necessary on modules compiled with -# assembly accelerations and/or ENABLED_LINUXKM_PIE. +# Similar to scripts/Makefile.lib delay-objtool: disable objtool on the kernels +# that run it on the linked object, ignoring OBJECT_FILES_NON_STANDARD. (Parse +# order prevents testing delay-objtool itself here: Makefile.build includes this +# file before Makefile.lib.) Auto-disablement is a gcc-only remedy, unavailable +# on clang, and objtool is mandatory to CONFIG_LTO_CLANG in any case. +ifndef CONFIG_CC_IS_CLANG + ifneq ($(or $(CONFIG_X86_KERNEL_IBT),$(CONFIG_KLP_BUILD)),) + ifeq "$(ENABLED_LINUXKM_PIE)" "yes" + FORCE_GLOBAL_OBJTOOL_OFF := y + else ifeq "$(ENABLED_ASM)" "yes" + FORCE_GLOBAL_OBJTOOL_OFF := y + endif + endif +endif + +# objtool disablement can be manually activated with "make +# KBUILD_EXTRA_FLAGS=FORCE_GLOBAL_OBJTOOL_OFF=1" ifdef FORCE_GLOBAL_OBJTOOL_OFF undefine CONFIG_OBJTOOL + # On <5.19, the knob is named CONFIG_STACK_VALIDATION. + undefine CONFIG_STACK_VALIDATION + NO_EXTERNAL_THUNKS := y endif +ifdef NO_EXTERNAL_THUNKS + ifeq "$(KERNEL_ARCH_X86)" "yes" + ifdef CONFIG_CC_IS_CLANG + # clang has no inline-thunk codegen (-mfunction-return accepts + # only keep/thunk-extern, and -mindirect-branch is a gcc-only + # spelling), so external thunk references are ineliminable when + # the mitigations are configured. + ifneq "$(CONFIG_MITIGATION_RETHUNK)$(CONFIG_MITIGATION_RETPOLINE)" "" + $(error NO_EXTERNAL_THUNKS requires gcc when retpoline/rethunk is configured.) + endif + else + ifeq "$(CONFIG_MITIGATION_RETHUNK)" "y" + PIE_SUPPORT_FLAGS += -mfunction-return=thunk-inline + else + PIE_SUPPORT_FLAGS += -mfunction-return=keep + endif + ifeq "$(CONFIG_MITIGATION_RETPOLINE)" "y" + PIE_SUPPORT_FLAGS += -mindirect-branch=thunk-inline -mindirect-branch-register + else + PIE_SUPPORT_FLAGS += -mindirect-branch=keep + endif + endif + endif +endif + +ccflags-y += $(PIE_SUPPORT_FLAGS) + ifdef KERNEL_EXTRA_CFLAGS_REMOVE ccflags-remove-y += $(KERNEL_EXTRA_CFLAGS_REMOVE) endif @@ -354,9 +407,9 @@ RENAME_PIE_TEXT_AND_DATA_SECTIONS := \ cd "$(obj)" || exit $$?; \ for file in $(WOLFCRYPT_PIE_FILES); do \ $(OBJCOPY) $$($(READELF) --sections --wide "$$file" | \ - $(AWK) ' \ + $(AWK) ' \ { \ - if (match($$0, "^ *\\[ *[0-9]+\\] +\\.(text|rodata|data|bss)(\\.[^ ]+)? ", a)) \ + if (match($$0, "^ *\\[ *[0-9]+\\] +\\.(text|rodata|data|bss)(\\.[^ ]+)? ", a)) \ { \ printf("--rename-section .%s%s=.%s_wolfcrypt ", \ a[1], a[2], a[1]); \ @@ -366,7 +419,7 @@ RENAME_PIE_TEXT_AND_DATA_SECTIONS := \ printf("--rename-section .%s.%s=.%s_wolfcrypt ", a[1], a[2], a[2]); \ } \ }') "$$file" || exit $$?; \ - done; \ + done; \ { $(READELF) --sections --syms --wide $(WOLFCRYPT_PIE_FILES) | \ $(AWK) -v obj="$(obj)" ' \ /^File:/ { \ From 24e6f6a4e30d9d35e466a2449e46903eeb3fabb9 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Oct 2026 17:08:23 -0500 Subject: [PATCH 02/28] wolfcrypt/benchmark/benchmark.c: refactor key init/free in bench_frodokem_keygen(), bench_frodokem_encap(), and bench_frodokem(), to fix uninited-key free ops. Also initialize devIds in bench_frodokem(). --- wolfcrypt/benchmark/benchmark.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index f9f8b4c45a4..8e1702512da 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -12888,12 +12888,11 @@ static void bench_frodokem_keygen(int type, const char* name, int keySize, do { /* while free pending slots in queue, submit ops */ for (times = 0; times < agreeTimes || pending > 0; times++) { - wc_FrodoKemKey_Free(key); ret = wc_FrodoKemKey_Init(key, type, HEAP_HINT, INVALID_DEVID); if (ret != 0) goto exit; - ret = wc_FrodoKemKey_MakeKey(key, &gRng); + wc_FrodoKemKey_Free(key); if (ret != 0) goto exit; RECORD_MULTI_VALUE_STATS(); @@ -12923,6 +12922,7 @@ static void bench_frodokem_keygen(int type, const char* name, int keySize, static void bench_frodokem_encap(int type, const char* name, int keySize, FrodoKemKey* key1, FrodoKemKey* key2) { +#ifndef WOLFSSL_FRODOKEM_NO_MAKE_KEY int ret = 0, times, count, pending = 0; double start; const char**desc = bench_desc_words[lng_index]; @@ -12939,6 +12939,14 @@ static void bench_frodokem_encap(int type, const char* name, int keySize, WC_ALLOC_VAR(ss, byte, FRODOKEM_MAX_LENSEC, HEAP_HINT); WC_ALLOC_VAR(pub, byte, FRODOKEM_MAX_PUBLIC_KEY_SIZE, HEAP_HINT); + ret = wc_FrodoKemKey_Init(key1, type, HEAP_HINT, INVALID_DEVID); + if (ret != 0) + goto exit; + + ret = wc_FrodoKemKey_MakeKey(key1, &gRng); + if (ret != 0) + goto exit; + ret = wc_FrodoKemKey_PublicKeySize(key1, &pubLen); if (ret != 0) { goto exit; @@ -13018,6 +13026,9 @@ static void bench_frodokem_encap(int type, const char* name, int keySize, exit: + wc_FrodoKemKey_Free(key2); + wc_FrodoKemKey_Free(key1); + WC_FREE_VAR(ct, HEAP_HINT); WC_FREE_VAR(ss, HEAP_HINT); WC_FREE_VAR(pub, HEAP_HINT); @@ -13026,6 +13037,13 @@ static void bench_frodokem_encap(int type, const char* name, int keySize, printf("error: bench_frodokem_encap() failed with code %d.\n", ret); return; +#else + (void)type; + (void)name; + (void)keySize; + (void)key1; + (void)key2; +#endif /* !WOLFSSL_FRODOKEM_NO_MAKE_KEY */ } #endif @@ -13096,10 +13114,14 @@ void bench_frodokem(int type) } #endif - /* Zero the key objects so the wc_FrodoKemKey_Free calls below are safe even - * if a benchmark helper returns before initializing its key. */ + /* Zero the key objects so wc_FrodoKemKey_Free calls are safe even + * if a benchmark helper cleans up before initializing its key. */ XMEMSET(key1, 0, sizeof(*key1)); XMEMSET(key2, 0, sizeof(*key2)); +#ifdef WOLF_CRYPTO_CB + key1->devId = INVALID_DEVID; + key2->devId = INVALID_DEVID; +#endif for (v = 0; v < sizeof(mods) / sizeof(mods[0]); v++) { int mod = mods[v]; @@ -13119,9 +13141,6 @@ void bench_frodokem(int type) #endif } - wc_FrodoKemKey_Free(key2); - wc_FrodoKemKey_Free(key1); - WC_FREE_VAR_EX(key1, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); WC_FREE_VAR_EX(key2, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } From 847da6f2e98c0d4a4b0bef5e22c0f63add677fbf Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Oct 2026 17:08:38 -0500 Subject: [PATCH 03/28] wolfssl/wolfcrypt/wc_compat.h, wolfssl/wolfcrypt/memory.h: in wc_AesGcmEncrypt_compat_shim(), wipe tag and output to match wc_AesGcmEncrypt() (ISO-19790). --- wolfssl/wolfcrypt/memory.h | 6 ++-- wolfssl/wolfcrypt/wc_compat.h | 57 +++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index 91200566acb..d7a35203478 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -331,8 +331,10 @@ WOLFSSL_LOCAL void wc_MemZero_Add(const char* name, const void* addr, WOLFSSL_LOCAL void wc_MemZero_Check(void* addr, size_t len); #endif -#ifndef WOLFSSL_NO_FORCE_ZERO -WOLFSSL_API void wc_ForceZero(void *mem, size_t len); +#ifdef WOLFSSL_NO_FORCE_ZERO + #define wc_ForceZero ForceZero +#else + WOLFSSL_API void wc_ForceZero(void *mem, size_t len); #endif #ifndef WOLFSSL_NO_CONST_CMP diff --git a/wolfssl/wolfcrypt/wc_compat.h b/wolfssl/wolfcrypt/wc_compat.h index 2bfa5de687d..b6de0f97065 100644 --- a/wolfssl/wolfcrypt/wc_compat.h +++ b/wolfssl/wolfcrypt/wc_compat.h @@ -69,6 +69,16 @@ #define wc_AesGcmEncrypt wc_AesGcmEncrypt_compat_shim + /* Reachable (via types.h) before memory.h's body when an application + * includes memory.h first: its include guard defers the body, so declare + * the exported zeroizer here for the inline shims below. Redeclaration + * with identical tokens is harmless. */ + #ifdef WOLFSSL_NO_FORCE_ZERO + #define wc_ForceZero ForceZero + #else + WOLFSSL_API void wc_ForceZero(void *mem, size_t len); + #endif + #ifdef WOLFSSL_AESGCM_STREAM static WC_INLINE int wc_AesGcmEncrypt_compat_shim(Aes* aes, byte* out, const byte* in, word32 sz, @@ -84,12 +94,24 @@ return BAD_FUNC_ARG; #endif ret = wc_AesGcmInit(aes, NULL /* key */, 0 /* len */, iv, ivSz); - if (ret) - return ret; - ret = wc_AesGcmEncryptUpdate(aes, out, in, sz, authIn, authInSz); - if (ret) - return ret; - return wc_AesGcmEncryptFinal(aes, authTag, authTagSz); + if (ret == 0) + ret = wc_AesGcmEncryptUpdate(aes, out, in, sz, authIn, authInSz); + if (ret == 0) + ret = wc_AesGcmEncryptFinal(aes, authTag, authTagSz); + if (ret != 0) { + /* Match the native one-shot's failure contract: no ciphertext and no + * tag escape a failed operation, whichever stage failed. On the + * Init/Update failure paths authTag was never written, so there this + * is contract uniformity rather than leak repair. */ + if (out != NULL) + wc_ForceZero(out, sz); + if (authTag != NULL) + wc_ForceZero(authTag, + authTagSz > WC_AES_BLOCK_SIZE + ? WC_AES_BLOCK_SIZE + : authTagSz); + } + return ret; } #else /* ! WOLFSSL_AESGCM_STREAM */ @@ -109,13 +131,22 @@ return BAD_LENGTH_E; ret = wc_AesGcmSetExtIV(aes, iv, ivSz); - if (ret != 0) - return ret; - ret = wc_AesGcmEncrypt_ex(aes, out, in, sz, scratch, ivSz, authTag, - authTagSz, authIn, authInSz); - if (ret != 0) - return ret; - return wc_AesGcmSetExtIV(aes, iv, ivSz); + if (ret == 0) + ret = wc_AesGcmEncrypt_ex(aes, out, in, sz, scratch, ivSz, authTag, + authTagSz, authIn, authInSz); + if (ret == 0) + ret = wc_AesGcmSetExtIV(aes, iv, ivSz); + if (ret != 0) { + /* Match above ISO-19790 wipe--this arm airdropped into old-FIPS. */ + if (out != NULL) + wc_ForceZero(out, sz); + if (authTag != NULL) + wc_ForceZero(authTag, + authTagSz > WC_AES_BLOCK_SIZE + ? WC_AES_BLOCK_SIZE + : authTagSz); + } + return ret; } #endif /* ! WOLFSSL_AESGCM_STREAM */ #endif /* HAVE_FIPS && HAVE_AESGCM && */ From bb0805acc0d0b700f1cec2976f8f3b844af3dce8 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 30 Oct 2026 17:08:48 -0500 Subject: [PATCH 04/28] wolfcrypt/test/test.c: don't define SLHDSA_TEST_CERT if WOLFSSL_NO_MALLOC (not compatible). --- wolfcrypt/test/test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index bdbb2748ba9..732eec1bf60 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -78552,6 +78552,7 @@ static wc_test_ret_t slhdsa_init_fail_free_test(void) #define SLHDSA_TEST_CERT_SHA2_128S #endif #if !defined(NO_ASN) && !defined(NO_CERTS) && \ + !defined(WOLFSSL_NO_MALLOC) && \ (defined(SLHDSA_TEST_CERT_SHAKE128S) || \ defined(SLHDSA_TEST_CERT_SHA2_128S)) #define SLHDSA_TEST_CERT From 748c3d4947978b961df6805527d08fcdb089fb9b Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:36:15 -0600 Subject: [PATCH 05/28] wolfcrypt/src/rng_bank.c: fix error-path memory leak in wc_rng_bank_init_nonce(), and add old-FIPS code paths in wc_InitRng_BankRef_local() and wc_BankRef_Release(). --- wolfcrypt/src/rng_bank.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/rng_bank.c b/wolfcrypt/src/rng_bank.c index 4901857162b..790640955a4 100644 --- a/wolfcrypt/src/rng_bank.c +++ b/wolfcrypt/src/rng_bank.c @@ -309,8 +309,19 @@ WOLFSSL_API int wc_rng_bank_init_nonce( wc_RNG_lock_put(&ctx->root_rng, 0); #endif - if (ret != 0) + if (ret != 0) { +#if defined(WC_RNG_HAVE_LOCK) && defined(WC_RNG_BANK_HAVE_ROOT_RNG) + /* A root init that failed under WC_RNG_INIT_FLAG_LOCK_INITIALLY (e.g. + * instantiation refused in FIPS error state) dies holding the root's + * lock with no owner to release it -- root_rng_locked is only set on + * success. Release it unconditionally, or the fini below refuses + * with BUSY_E at its root-lock check and ctx->rngs is leaked, with + * every subsequent fini refused the same way. */ + if (! root_rng_locked) + wc_RNG_lock_put_unconditional(&ctx->root_rng); +#endif (void)wc_rng_bank_fini(ctx); + } return ret; } @@ -3112,8 +3123,12 @@ static int wc_InitRng_BankRef_local(struct wc_rng_bank *bank, WC_RNG **rng) { XMEMSET(*rng, 0, sizeof(**rng)); (*rng)->heap = bank->heap; - (*rng)->flags |= WC_RNG_FLAG_BANKREF; (*rng)->bankref = bank; +#if defined(HAVE_FIPS) && FIPS_VERSION3_LT(7,0,0) + (*rng)->status = WC_DRBG_BANKREF; +#else + (*rng)->flags |= WC_RNG_FLAG_BANKREF; +#endif ret = 0; @@ -3144,8 +3159,13 @@ WOLFSSL_API int wc_BankRef_Release(WC_RNG *rng) int ret = 0; if (rng == NULL) return BAD_FUNC_ARG; +#if defined(HAVE_FIPS) && FIPS_VERSION3_LT(7,0,0) + if (rng->status != WC_DRBG_BANKREF) + return WRONG_TYPE_OBJECT_E; +#else if (! (rng->flags & WC_RNG_FLAG_BANKREF)) return WRONG_TYPE_OBJECT_E; +#endif if (rng->bankref == NULL) return BAD_FUNC_ARG; wolfSSL_RefDec(&rng->bankref->refcount, &isZero, &ret); @@ -3157,7 +3177,11 @@ WOLFSSL_API int wc_BankRef_Release(WC_RNG *rng) (void)isZero; #endif rng->heap = NULL; +#if defined(HAVE_FIPS) && FIPS_VERSION3_LT(7,0,0) + rng->status = WC_DRBG_NOT_INIT; +#else rng->flags &= ~WC_RNG_FLAG_BANKREF; +#endif rng->bankref = NULL; return ret; } From 69aa86b6250f8b05d48d4c1263ae1bf66767f3e3 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:41:34 -0600 Subject: [PATCH 06/28] src/pk.c, wolfcrypt/src/evp.c, wolfssl/internal.h: rename {wolfssl_dsa_do_sign,wolfssl_dsa_do_verify} to {wolfssl_local_dsa_do_sign,wolfssl_local_dsa_do_verify} to avoid check-for-bad-symbols carp about confusable names (wolfSSL_DSA_do_sign() and wolfSSL_DSA_do_verify() are incumbent public functions). --- src/pk.c | 12 ++++++------ wolfcrypt/src/evp.c | 14 +++++++------- wolfssl/internal.h | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/pk.c b/src/pk.c index 8b91ff04268..19f1ca89179 100644 --- a/src/pk.c +++ b/src/pk.c @@ -1605,7 +1605,7 @@ WOLFSSL_DSA_SIG* wolfSSL_d2i_DSA_SIG(WOLFSSL_DSA_SIG **sig, #endif /* !HAVE_SELFTEST */ -int wolfssl_dsa_do_sign(const unsigned char* d, int dLen, +int wolfssl_local_dsa_do_sign(const unsigned char* d, int dLen, unsigned char* sigRet, WOLFSSL_DSA* dsa) { int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR); @@ -1686,7 +1686,7 @@ int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, { WOLFSSL_ENTER("wolfSSL_DSA_do_sign"); - return wolfssl_dsa_do_sign(d, WC_SHA_DIGEST_SIZE, sigRet, dsa); + return wolfssl_local_dsa_do_sign(d, WC_SHA_DIGEST_SIZE, sigRet, dsa); } #ifndef HAVE_SELFTEST @@ -1704,7 +1704,7 @@ WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest, return NULL; } - if (wolfssl_dsa_do_sign(digest, inLen, sigBin, dsa) != 1) { + if (wolfssl_local_dsa_do_sign(digest, inLen, sigBin, dsa) != 1) { WOLFSSL_MSG("wolfSSL_DSA_do_sign error"); return NULL; } @@ -1725,7 +1725,7 @@ WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest, } #endif -int wolfssl_dsa_do_verify(const unsigned char* d, int dLen, unsigned char* sig, +int wolfssl_local_dsa_do_verify(const unsigned char* d, int dLen, unsigned char* sig, WOLFSSL_DSA* dsa, int *dsacheck) { int ret; @@ -1777,7 +1777,7 @@ int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig, { WOLFSSL_ENTER("wolfSSL_DSA_do_verify"); - return wolfssl_dsa_do_verify(d, WC_SHA_DIGEST_SIZE, sig, dsa, dsacheck); + return wolfssl_local_dsa_do_verify(d, WC_SHA_DIGEST_SIZE, sig, dsa, dsacheck); } @@ -1854,7 +1854,7 @@ int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, if (wolfSSL_BN_bn2bin(sig->s, sigBinPtr) == -1) return 0; - if ((wolfssl_dsa_do_verify(digest, digest_len, sigBin, dsa, &dsacheck) + if ((wolfssl_local_dsa_do_verify(digest, digest_len, sigBin, dsa, &dsacheck) != 1) || dsacheck != 1) { return 0; } diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 1828f4d94b6..952e4d785e5 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -3510,12 +3510,12 @@ int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, } if ((int)*siglen < bytes) return WOLFSSL_FAILURE; - /* wolfssl_dsa_do_sign() takes the length as an int, and wolfCrypt + /* wolfssl_local_dsa_do_sign() takes the length as an int, and wolfCrypt * rejects anything longer than this anyway. */ if (tbslen > WC_MAX_DIGEST_SIZE) return WOLFSSL_FAILURE; - ret = wolfssl_dsa_do_sign(tbs, (int)tbslen, sig, ctx->pkey->dsa); - /* wolfssl_dsa_do_sign() can return WOLFSSL_FATAL_ERROR */ + ret = wolfssl_local_dsa_do_sign(tbs, (int)tbslen, sig, ctx->pkey->dsa); + /* wolfssl_local_dsa_do_sign() can return WOLFSSL_FATAL_ERROR */ if (ret != WOLFSSL_SUCCESS) return ret; if (bytes == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) @@ -3645,11 +3645,11 @@ int wolfSSL_EVP_PKEY_verify(WOLFSSL_EVP_PKEY_CTX *ctx, const unsigned char *sig, bytes = wolfSSL_BN_num_bytes(ctx->pkey->dsa->q); if (bytes <= 0 || siglen < (size_t)bytes * 2) return WOLFSSL_FAILURE; - /* wolfssl_dsa_do_verify() takes the length as an int, and wolfCrypt + /* wolfssl_local_dsa_do_verify() takes the length as an int, and wolfCrypt * rejects anything longer than this anyway. */ if (tbslen > WC_MAX_DIGEST_SIZE) return WOLFSSL_FAILURE; - if (wolfssl_dsa_do_verify(tbs, (int)tbslen, (unsigned char *)sig, + if (wolfssl_local_dsa_do_verify(tbs, (int)tbslen, (unsigned char *)sig, ctx->pkey->dsa, &dsacheck) != WOLFSSL_SUCCESS || dsacheck != 1) return WOLFSSL_FAILURE; return WOLFSSL_SUCCESS; @@ -4668,8 +4668,8 @@ int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, { return WOLFSSL_FAILURE; } - ret = wolfssl_dsa_do_sign(md, (int)mdsize, sigret, pkey->dsa); - /* wolfssl_dsa_do_sign() can return WOLFSSL_FATAL_ERROR */ + ret = wolfssl_local_dsa_do_sign(md, (int)mdsize, sigret, pkey->dsa); + /* wolfssl_local_dsa_do_sign() can return WOLFSSL_FATAL_ERROR */ if (ret != WOLFSSL_SUCCESS) return ret; *siglen = (unsigned int)(bytes * 2); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index f7a631539a2..08e5c8d207d 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -8207,9 +8207,9 @@ WOLFSSL_LOCAL int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side); WOLFSSL_LOCAL int SetDsaInternal(WOLFSSL_DSA* dsa); WOLFSSL_LOCAL int SetDsaExternal(WOLFSSL_DSA* dsa); #ifndef NO_DSA -WOLFSSL_LOCAL int wolfssl_dsa_do_sign(const unsigned char* d, int dLen, +WOLFSSL_LOCAL int wolfssl_local_dsa_do_sign(const unsigned char* d, int dLen, unsigned char* sigRet, WOLFSSL_DSA* dsa); -WOLFSSL_LOCAL int wolfssl_dsa_do_verify(const unsigned char* d, int dLen, +WOLFSSL_LOCAL int wolfssl_local_dsa_do_verify(const unsigned char* d, int dLen, unsigned char* sig, WOLFSSL_DSA* dsa, int* dsacheck); #endif WOLFSSL_LOCAL int SetRsaExternal(WOLFSSL_RSA* rsa); From 688ca85c9004834f546155aaea35ff78985ba868 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:44:49 -0600 Subject: [PATCH 07/28] wolfssl/wolfcrypt/error-crypt.h: add WOLFSSL_DEBUG_NO_TRACE_ERROR_CODES_THIS_FILE to the gate in the WOLFSSL_DEBUG_TRACE_ERROR_CODES setup block, to allow whole-file suppression for debugging convenience. --- wolfssl/wolfcrypt/error-crypt.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index df07b63fdc0..547e1c512d2 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -398,7 +398,8 @@ WOLFSSL_ABI WOLFSSL_API const char* wc_GetErrorString(int error); (defined(BUILDING_WOLFSSL) || \ defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES_ALWAYS)) && \ (!defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES_PER_FILE) || \ - defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES_THIS_FILE)) + defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES_THIS_FILE)) && \ + !defined(WOLFSSL_DEBUG_NO_TRACE_ERROR_CODES_THIS_FILE) #include #define WC_NO_ERR_TRACE(label) (CONST_NUM_ERR_ ## label) From 5f4cbd2a9e6fa28b11beb31077b0d12eaa60543e Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:46:27 -0600 Subject: [PATCH 08/28] wolfssl/wolfcrypt/wc_compat.h, : add suppression for readability-redundant-declaration to compat wc_ForceZero() prototype. --- wolfssl/wolfcrypt/wc_compat.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wolfssl/wolfcrypt/wc_compat.h b/wolfssl/wolfcrypt/wc_compat.h index b6de0f97065..f290f4243c2 100644 --- a/wolfssl/wolfcrypt/wc_compat.h +++ b/wolfssl/wolfcrypt/wc_compat.h @@ -74,8 +74,10 @@ * the exported zeroizer here for the inline shims below. Redeclaration * with identical tokens is harmless. */ #ifdef WOLFSSL_NO_FORCE_ZERO + #undef wc_ForceZero #define wc_ForceZero ForceZero #else + /* NOLINTNEXTLINE(readability-redundant-declaration) */ WOLFSSL_API void wc_ForceZero(void *mem, size_t len); #endif From 764875ad045d5ba282f51db8b9ff10a8563995af Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:47:44 -0600 Subject: [PATCH 09/28] tests/api/test_aes.c: add old-FIPS gating to test_wc_AesGcm_PrimitiveFailureCleanup() (for v6). --- tests/api/test_aes.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/api/test_aes.c b/tests/api/test_aes.c index 8e98a163a40..4a0a9913bce 100644 --- a/tests/api/test_aes.c +++ b/tests/api/test_aes.c @@ -14828,10 +14828,6 @@ int test_wc_AesGcm_PrimitiveFailureCleanup(void) const byte zeros[5 * WC_AES_BLOCK_SIZE] = {0}; byte tag[WC_AES_BLOCK_SIZE]; int ret; -#ifdef WOLFSSL_AESGCM_STREAM - byte in[17] = {0}; - byte out[17]; -#endif XMEMSET(&aes, 0, sizeof(aes)); ExpectIntEQ(wc_AesInit(&aes, NULL, INVALID_DEVID), 0); @@ -14846,21 +14842,26 @@ int test_wc_AesGcm_PrimitiveFailureCleanup(void) return TEST_SKIPPED; /* backend does not use the portable primitive */ } ExpectBufEQ(tag, zeros, sizeof(tag)); -#ifdef WOLFSSL_AESGCM_STREAM - ExpectIntEQ(wc_AesGcmEncryptInit(&aes, key, sizeof(key), iv, sizeof(iv)), 0); - /* Retain fifteen bytes of keystream, then fail generating the next block. */ - ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, out, in, 1, NULL, 0), 0); - aes.rounds = 0; - ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, out, in, sizeof(in), NULL, 0), - WC_NO_ERR_TRACE(KEYUSAGE_E)); - ExpectBufEQ(aes.streamData, zeros, sizeof(zeros)); - ExpectIntEQ(aes.nonceSet, 0); - ExpectIntEQ(aes.over, 0); - /* A failed stream must require reinitialization. */ - ExpectIntLT(wc_AesGcmEncryptUpdate(&aes, out, in, 1, NULL, 0), 0); - ExpectIntEQ(wc_AesGcmEncryptInit(&aes, key, sizeof(key), iv, sizeof(iv)), 0); - ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, out, in, sizeof(in), NULL, 0), 0); - ExpectIntEQ(wc_AesGcmEncryptFinal(&aes, tag, sizeof(tag)), 0); +#if defined(WOLFSSL_AESGCM_STREAM) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + { + byte in[17] = {0}; + byte out[17]; + ExpectIntEQ(wc_AesGcmEncryptInit(&aes, key, sizeof(key), iv, sizeof(iv)), 0); + /* Retain fifteen bytes of keystream, then fail generating the next block. */ + ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, out, in, 1, NULL, 0), 0); + aes.rounds = 0; + ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, out, in, sizeof(in), NULL, 0), + WC_NO_ERR_TRACE(KEYUSAGE_E)); + ExpectBufEQ(aes.streamData, zeros, sizeof(zeros)); + ExpectIntEQ(aes.nonceSet, 0); + ExpectIntEQ(aes.over, 0); + /* A failed stream must require reinitialization. */ + ExpectIntLT(wc_AesGcmEncryptUpdate(&aes, out, in, 1, NULL, 0), 0); + ExpectIntEQ(wc_AesGcmEncryptInit(&aes, key, sizeof(key), iv, sizeof(iv)), 0); + ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, out, in, sizeof(in), NULL, 0), 0); + ExpectIntEQ(wc_AesGcmEncryptFinal(&aes, tag, sizeof(tag)), 0); + } #endif wc_AesFree(&aes); #else From 65e9392998a676cde31127205fd3609d24f46d65 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:49:10 -0600 Subject: [PATCH 10/28] tests/api/test_ossl_rand.c: in test_wolfSSL_RAND_bytes(), use _exit(), not exit(), to avoid uninformative LSAN reports on the child process when it exits. --- tests/api/test_ossl_rand.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/api/test_ossl_rand.c b/tests/api/test_ossl_rand.c index 6152bf0965a..fcca4a146ff 100644 --- a/tests/api/test_ossl_rand.c +++ b/tests/api/test_ossl_rand.c @@ -231,7 +231,9 @@ int test_wolfSSL_RAND_bytes(void) ok = (RAND_bytes(randbuf, sizeof(randbuf)) == 1); n_written = write(pipefds[1], randbuf, sizeof(randbuf)); close(pipefds[1]); - exit((ok && n_written == sizeof(randbuf)) ? 0 : 1); + /* Must terminate via _exit() to avoid provoking LSAN via the atexit + * handlers. */ + _exit((ok && n_written == sizeof(randbuf)) ? 0 : 1); } else if (pid > 0) { /* Parent process. */ From bb8dcb79e444ecc0ec688623dfef75a0b0765344 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:50:41 -0600 Subject: [PATCH 11/28] tests/api/test_sha512.c: add WC_MAYBE_UNUSED attribute to sha512_dev_cb() to accommodate strange unsupported (but linted) config combinations like FIPS+cryptocb. --- tests/api/test_sha512.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/api/test_sha512.c b/tests/api/test_sha512.c index 7e09fdc6d7c..e44aac331d9 100644 --- a/tests/api/test_sha512.c +++ b/tests/api/test_sha512.c @@ -909,7 +909,7 @@ typedef struct { * SHA-512 callback; that callback fills a recognisable digest and deliberately * leaves the SHA-512 IV in the caller's state, forcing the dispatcher to reset * the state back to the variant IV. */ -static int sha512_dev_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) +static WC_MAYBE_UNUSED int sha512_dev_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) { Sha512DevCbCtx* cbCtx = (Sha512DevCbCtx*)ctx; int i; From fe708cda4e9ed70f6a617d9818e926486a8c32d4 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:53:11 -0600 Subject: [PATCH 12/28] tests/api/test_kdf.c: add !old-FIPS gate to test_wc_SshKdfReuse() (true positive leak reports due to internal API misuse); also add WC_MAYBE_UNUSED attribute to test_kdf_cryptocb() to to accommodate strange unsupported (but linted) config combinations like FIPS+cryptocb. --- tests/api/test_kdf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/api/test_kdf.c b/tests/api/test_kdf.c index 86ce87f6d36..4ba02505107 100644 --- a/tests/api/test_kdf.c +++ b/tests/api/test_kdf.c @@ -64,7 +64,7 @@ * dispatch-taken-and-succeeds), both within this one registered devId. */ static int test_kdf_cryptocb_force_fail = 0; -static int test_kdf_cryptocb(int cbDevId, wc_CryptoInfo* info, void* ctx) +static WC_MAYBE_UNUSED int test_kdf_cryptocb(int cbDevId, wc_CryptoInfo* info, void* ctx) { (void)ctx; if (cbDevId != TEST_KDF_CRYPTOCB_DEVID) @@ -939,7 +939,13 @@ int test_wc_KdfFeatureCoverage(void) int test_wc_SshKdfReuse(void) { EXPECT_DECLS; -#if defined(WOLFSSL_WOLFSSH) && !defined(NO_HMAC) + /* Note, must skip on old FIPS with _SMALL_STACK_CACHE, due to leak in + * wc_SSH_KDF() via _HashInit() over already-initialized hash, fixed by + * 827807d2efd. */ +#if defined(WOLFSSL_WOLFSSH) && !defined(NO_HMAC) && \ + (!defined(HAVE_FIPS) || \ + FIPS_VERSION3_GE(7,0,0) || \ + !defined(WOLFSSL_SMALL_STACK_CACHE)) static const struct { byte hashId; const char* expected; From 97b3befe1ac55648060dc5baf2d3891ce51842a6 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 14:53:58 -0600 Subject: [PATCH 13/28] tests/api/test_ossl_x509_str.c: add missing OPENSSL_ALL gating to test_crl_date_cb_ok_calls. --- tests/api/test_ossl_x509_str.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/api/test_ossl_x509_str.c b/tests/api/test_ossl_x509_str.c index 41b67bbbf0d..367f39a76f9 100644 --- a/tests/api/test_ossl_x509_str.c +++ b/tests/api/test_ossl_x509_str.c @@ -391,14 +391,18 @@ int test_wolfSSL_X509_verify_cert_crl_date_override(void) static int test_crl_date_cb_waive[2]; static int test_crl_date_cb_seen[4]; static int test_crl_date_cb_calls; +#ifdef OPENSSL_ALL static int test_crl_date_cb_ok_calls; +#endif static int test_crl_date_verify_cb(int ok, X509_STORE_CTX* ctx) { int err = X509_STORE_CTX_get_error(ctx); if (ok) { +#ifdef OPENSSL_ALL test_crl_date_cb_ok_calls++; +#endif return ok; } if (test_crl_date_cb_calls < 4) @@ -417,7 +421,9 @@ static int test_crl_date_verify(X509_STORE* store, X509* cert, int waive0, test_crl_date_cb_waive[0] = waive0; test_crl_date_cb_waive[1] = waive1; test_crl_date_cb_calls = 0; +#ifdef OPENSSL_ALL test_crl_date_cb_ok_calls = 0; +#endif XMEMSET(test_crl_date_cb_seen, 0, sizeof(test_crl_date_cb_seen)); if ((storeCtx != NULL) && (X509_STORE_CTX_init(storeCtx, store, cert, NULL) == From 77a77f39ba5db73c5e205c7017f8aef93a6e1cb8 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 15:01:02 -0600 Subject: [PATCH 14/28] wolfcrypt/test/test.c: * tweak RESEED_CTR() definition for gcc-6.5.0 compatibility (always-true comparison warning noise) by making it a trivial inline function rather than a macro when possible; * inhibit WC_RNG_BANK_FLAG_NO_VECTOR_OPS subtest in random_bank_test() when WC_SVR_USE_NATIVE_REG_BUFS; * refactor PRIVATE_KEY_UNLOCK()...PRIVATE_KEY_LOCK() wraps from scenario-wide to tight around the crypto API calls that need them; fix retval handling in mlkem_*_test(). --- wolfcrypt/test/test.c | 482 ++++++++++++++++++++++++++++-------------- 1 file changed, 321 insertions(+), 161 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 732eec1bf60..7e30af55ad6 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -3038,9 +3038,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #if defined(HAVE_HKDF) && !defined(NO_HMAC) - PRIVATE_KEY_UNLOCK(); ret = hkdf_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("HMAC-KDF test failed!\n", ret); else @@ -3049,9 +3047,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif /* !NO_HMAC */ #ifdef WOLFSSL_WOLFSSH - PRIVATE_KEY_UNLOCK(); ret = sshkdf_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("SSH-KDF test failed!\n", ret); else @@ -3060,9 +3056,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #if defined(WOLFSSL_HAVE_PRF) && !defined(NO_HMAC) && \ defined(WOLFSSL_SHA384) && !defined(WOLFSSL_NO_TLS12) - PRIVATE_KEY_UNLOCK(); ret = prf_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("PRF test failed!\n", ret); else @@ -3071,9 +3065,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #if defined(WOLFSSL_HAVE_PRF) && defined(HAVE_HKDF) && !defined(NO_HMAC) && \ defined(WOLFSSL_BASE16) && !defined(WOLFSSL_NO_TLS12) - PRIVATE_KEY_UNLOCK(); ret = tls12_kdf_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("TLSv1.2 KDF test failed!\n", ret); else @@ -3082,9 +3074,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ /* WOLFSSL_BASE16 && !WOLFSSL_NO_TLS12 */ #if defined(WOLFSSL_TLS13) && !defined(NO_HMAC) - PRIVATE_KEY_UNLOCK(); ret = tls13_kdf_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("TLSv1.3 KDF test failed!\n", ret); else @@ -3102,9 +3092,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ defined(HAVE_CURVE448)) && \ defined(HAVE_AESGCM) - PRIVATE_KEY_UNLOCK(); ret = hpke_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("HPKE test failed!\n", ret); else @@ -3112,9 +3100,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #if defined(WC_SRTP_KDF) - PRIVATE_KEY_UNLOCK(); ret = srtpkdf_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("SRTP KDF test failed!\n", ret); else @@ -3398,9 +3384,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifndef NO_DH - PRIVATE_KEY_UNLOCK(); ret = dh_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("DH test failed!\n", ret); @@ -3423,9 +3407,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifndef NO_PWDBASED - PRIVATE_KEY_UNLOCK(); ret = pwdbased_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("PWDBASED test failed!\n", ret); else @@ -3480,9 +3462,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #if defined(HAVE_ECC) - PRIVATE_KEY_UNLOCK(); ret = ecc_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("ECC test failed!\n", ret); else @@ -3605,9 +3585,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #if defined(HAVE_ED25519) && \ (!defined(WOLF_CRYPTO_CB_ONLY_ED25519) || defined(WOLFSSL_SWDEV)) - PRIVATE_KEY_UNLOCK(); ret = ed25519_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("ED25519 test failed!\n", ret); else @@ -3623,9 +3601,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifdef HAVE_ED448 - PRIVATE_KEY_UNLOCK(); ret = ed448_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("ED448 test failed!\n", ret); else @@ -3633,9 +3609,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifdef WOLFSSL_HAVE_MLKEM - PRIVATE_KEY_UNLOCK(); ret = mlkem_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("MLKEM test failed!\n", ret); else @@ -3650,9 +3624,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifdef WOLFSSL_HAVE_MLDSA - PRIVATE_KEY_UNLOCK(); ret = mldsa_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("ML-DSA test failed!\n", ret); else @@ -3660,9 +3632,7 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifdef HAVE_FALCON - PRIVATE_KEY_UNLOCK(); ret = falcon_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("Falcon test failed!\n", ret); else @@ -3780,18 +3750,14 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ else TEST_PASS("PKCS7signed test passed!\n"); - PRIVATE_KEY_UNLOCK(); ret = pkcs7enveloped_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("PKCS7enveloped test failed!\n", ret); else TEST_PASS("PKCS7enveloped test passed!\n"); #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) - PRIVATE_KEY_UNLOCK(); ret = pkcs7authenveloped_test(); - PRIVATE_KEY_LOCK(); if (ret != 0) TEST_FAIL("PKCS7authenveloped test failed!\n", ret); else @@ -29606,11 +29572,19 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t XChaCha20Poly1305_test(void) #define RNG_STATS_EXPECT_SAME_DELTA(rng, f1, f2, fail_action) WC_DO_NOTHING #endif /* WC_RNG_DEBUG_STATS */ -#if !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) - #define RESEED_CTR(rng) (((rng) != NULL) ? (rng)->reseedCtr : \ - ~((wc_drbg_reseed_ctr_t)0)) - #define RESEED_CTR_LVAL(rng) ((rng)->reseedCtr) +#ifdef WC_DRBG_RESEED_CTR_TYPE_DEFINED + #if !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + static WC_INLINE wc_drbg_reseed_ctr_t RESEED_CTR(WC_RNG *rng) { + return ((rng) != NULL) ? (rng)->reseedCtr : ~((wc_drbg_reseed_ctr_t)0); + } + #define RESEED_CTR_LVAL(rng) ((rng)->reseedCtr) + #else + static WC_INLINE wc_drbg_reseed_ctr_t RESEED_CTR(WC_RNG *rng) { + return ((rng) != NULL) ? ((struct DRBG_internal *)(rng)->drbg)->reseedCtr : ~((wc_drbg_reseed_ctr_t)0); + } + #define RESEED_CTR_LVAL(rng) (((struct DRBG_internal *)(rng)->drbg)->reseedCtr) + #endif #else #define RESEED_CTR(rng) (((rng) != NULL) ? \ ((struct DRBG_internal *)(rng)->drbg)->reseedCtr : ~0U) @@ -32701,7 +32675,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) defined(HAVE_FIPS) && \ FIPS_VERSION3_LT(7,0,0) && \ !defined(DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON) && \ - defined(WC_SVR_HAVE_FLAGS) + defined(WC_SVR_HAVE_FLAGS) && \ + !defined(WC_SVR_USE_NATIVE_REG_BUFS) #ifdef WOLFSSL_DRBG_SHA512 if (rng_inst->rng.drbgType == WC_DRBG_SHA512) { @@ -32714,7 +32689,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) if (((struct DRBG_internal *)rng_inst->rng.drbg)->sha256.sha_method != 7 /* SHA256_C */) ERROR_OUT(WC_TEST_RET_ENC_I(((struct DRBG_internal *)rng_inst->rng.drbg)->sha256.sha_method), out); } -#endif /* USE_INTEL_SPEEDUP && ... && !DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_ON */ +#endif /* USE_INTEL_SPEEDUP && ... && !WC_SVR_USE_NATIVE_REG_BUFS */ ret = wc_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(rng_inst), outbuf1, sizeof(outbuf1)); if (ret != 0) @@ -49090,8 +49065,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs12_pbkdf_test(void) wc_test_ret_t ret; WOLFSSL_ENTER("pkcs12_pbkdf_test"); + PRIVATE_KEY_UNLOCK(); ret = wc_PKCS12_PBKDF(derived, passwd, sizeof(passwd), salt, 8, iterations, kLen, WC_SHA256, id); + PRIVATE_KEY_LOCK(); if (ret < 0) return WC_TEST_RET_ENC_EC(ret); @@ -49099,13 +49076,17 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs12_pbkdf_test(void) return WC_TEST_RET_ENC_NC; iterations = 1000; + PRIVATE_KEY_UNLOCK(); ret = wc_PKCS12_PBKDF(derived, passwd2, sizeof(passwd2), salt2, 8, iterations, kLen, WC_SHA256, id); + PRIVATE_KEY_LOCK(); if (ret < 0) return WC_TEST_RET_ENC_EC(ret); + PRIVATE_KEY_UNLOCK(); ret = wc_PKCS12_PBKDF_ex(derived, passwd2, sizeof(passwd2), salt2, 8, iterations, kLen, WC_SHA256, id, HEAP_HINT); + PRIVATE_KEY_LOCK(); if (ret < 0) return WC_TEST_RET_ENC_EC(ret); @@ -49134,9 +49115,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void) wc_test_ret_t ret; WOLFSSL_ENTER("pbkdf2_test"); + PRIVATE_KEY_UNLOCK(); ret = wc_PBKDF2_ex(derived, (byte*)passwd, (int)XSTRLEN(passwd), salt, (int)sizeof(salt), iterations, kLen, WC_SHA256, HEAP_HINT, devId); + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49149,9 +49132,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pbkdf2_test(void) int cur_pbkdf_limit = wc_PBKDF_max_iterations_set(iterations - 1); if (cur_pbkdf_limit <= 0) return WC_TEST_RET_ENC_EC(cur_pbkdf_limit); + PRIVATE_KEY_UNLOCK(); ret = wc_PBKDF2_ex(derived, (byte*)passwd, (int)XSTRLEN(passwd), salt, (int)sizeof(salt), iterations, kLen, WC_SHA256, HEAP_HINT, devId); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); ret = wc_PBKDF_max_iterations_set(-1); @@ -49498,6 +49483,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) L = (int)sizeof(okm1); #ifndef NO_SHA + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) ret = wc_HKDF_ex(WC_SHA, ikm1, (word32)sizeof(ikm1), NULL, 0, NULL, 0, okm1, (word32)L, HEAP_HINT, devId); @@ -49505,6 +49491,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) ret = wc_HKDF(WC_SHA, ikm1, (word32)sizeof(ikm1), NULL, 0, NULL, 0, okm1, (word32)L); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49514,6 +49501,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ L = (int)sizeof(okm1); + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) ret = wc_HKDF_ex(WC_SHA, ikm1, 11, salt1, (word32)sizeof(salt1), info1, (word32)sizeof(info1), okm1, (word32)L, HEAP_HINT, devId); @@ -49521,6 +49509,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) ret = wc_HKDF(WC_SHA, ikm1, 11, salt1, (word32)sizeof(salt1), info1, (word32)sizeof(info1), okm1, (word32)L); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49530,6 +49519,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #endif /* !NO_SHA */ #ifndef NO_SHA256 + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) ret = wc_HKDF_ex(WC_SHA256, ikm1, (word32)sizeof(ikm1), NULL, 0, NULL, 0, okm1, (word32)L, HEAP_HINT, devId); @@ -49537,6 +49527,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) ret = wc_HKDF(WC_SHA256, ikm1, (word32)sizeof(ikm1), NULL, 0, NULL, 0, okm1, (word32)L); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49545,6 +49536,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) ret = wc_HKDF_ex(WC_SHA256, ikm1, (word32)sizeof(ikm1), salt1, (word32)sizeof(salt1), info1, (word32)sizeof(info1), okm1, @@ -49554,6 +49546,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) (word32)sizeof(salt1), info1, (word32)sizeof(info1), okm1, (word32)L); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49563,15 +49556,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #endif /* !NO_SHA256 */ #ifndef NO_SHA + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) ret = wc_HKDF_Extract_ex(WC_SHA, NULL, 0, ikm1, (word32)sizeof(ikm1), prk, HEAP_HINT, devId); #else ret = wc_HKDF_Extract(WC_SHA, NULL, 0, ikm1, (word32)sizeof(ikm1), prk); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) ret = wc_HKDF_Expand_ex(WC_SHA, prk, WC_SHA_DIGEST_SIZE, NULL, 0, okm1, (word32)L, HEAP_HINT, devId); @@ -49579,6 +49575,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) ret = wc_HKDF_Expand(WC_SHA, prk, WC_SHA_DIGEST_SIZE, NULL, 0, okm1, (word32)L); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49587,15 +49584,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) ret = wc_HKDF_Extract_ex(WC_SHA, salt1, (word32)sizeof(salt1), ikm1, 11, prk, HEAP_HINT, devId); #else ret = wc_HKDF_Extract(WC_SHA, salt1, (word32)sizeof(salt1), ikm1, 11, prk); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) ret = wc_HKDF_Expand_ex(WC_SHA, prk, WC_SHA_DIGEST_SIZE, info1, (word32)sizeof(info1), okm1, (word32)L, HEAP_HINT, devId); @@ -49603,6 +49603,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) ret = wc_HKDF_Expand(WC_SHA, prk, WC_SHA_DIGEST_SIZE, info1, (word32)sizeof(info1), okm1, (word32)L); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49612,15 +49613,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #endif /* !NO_SHA */ #ifndef NO_SHA256 + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) ret = wc_HKDF_Extract_ex(WC_SHA256, NULL, 0, ikm1, (word32)sizeof(ikm1), prk, HEAP_HINT, devId); #else ret = wc_HKDF_Extract(WC_SHA256, NULL, 0, ikm1, (word32)sizeof(ikm1), prk); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) ret = wc_HKDF_Expand_ex(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, NULL, 0, okm1, (word32)L, HEAP_HINT, devId); @@ -49628,6 +49632,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) ret = wc_HKDF_Expand(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, NULL, 0, okm1, (word32)L); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49636,6 +49641,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) ret = wc_HKDF_Extract_ex(WC_SHA256, salt1, (word32)sizeof(salt1), ikm1, (word32)sizeof(ikm1), prk, HEAP_HINT, devId); @@ -49643,9 +49649,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) ret = wc_HKDF_Extract(WC_SHA256, salt1, (word32)sizeof(salt1), ikm1, (word32)sizeof(ikm1), prk); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); + PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_SELFTEST) ret = wc_HKDF_Expand_ex(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, info1, (word32)sizeof(info1), okm1, (word32)L, HEAP_HINT, devId); @@ -49653,6 +49661,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) ret = wc_HKDF_Expand(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, info1, (word32)sizeof(info1), okm1, (word32)L); #endif + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -49665,21 +49674,29 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void) #if !defined(NO_SHA256) && !defined(HAVE_SELFTEST) && \ (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) /* wc_HKDF_Extract bad arg: NULL out */ + PRIVATE_KEY_UNLOCK(); ret = wc_HKDF_Extract(WC_SHA256, NULL, 0, ikm1, (word32)sizeof(ikm1), NULL); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); /* wc_HKDF_Extract bad arg: NULL inKey with non-zero inKeySz */ + PRIVATE_KEY_UNLOCK(); ret = wc_HKDF_Extract(WC_SHA256, NULL, 0, NULL, 5, okm1); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); /* wc_HKDF_Expand bad arg: NULL out */ + PRIVATE_KEY_UNLOCK(); ret = wc_HKDF_Expand(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, NULL, 0, NULL, (word32)L); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); /* wc_HKDF_Expand bad arg: NULL inKey with non-zero inKeySz */ + PRIVATE_KEY_UNLOCK(); ret = wc_HKDF_Expand(WC_SHA256, NULL, WC_SHA256_DIGEST_SIZE, NULL, 0, okm1, (word32)L); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); #endif /* !NO_SHA256 && !HAVE_SELFTEST */ @@ -49828,10 +49845,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sshkdf_test(void) /* sId - Session ID, eKey - Expected Key, cKey - Calculated Key */ for (i = 0, tv = sshKdfTestVectors; i < tc; i++, tv++) { + PRIVATE_KEY_UNLOCK(); result = wc_SSH_KDF(tv->hashId, tv->keyId, cKey, tv->expectedKeySz, tv->k, tv->kSz, tv->h, tv->hSz, tv->sessionId, tv->sessionIdSz); + PRIVATE_KEY_LOCK(); if (result != 0) { printf("KDF: Could not derive key.\n"); @@ -49887,9 +49906,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t prf_test(void) int lblsdL = LBSL; int hash_type = sha384_mac; + PRIVATE_KEY_UNLOCK(); ret = wc_PRF(dig, (word32)digL, secret, (word32)secL, lablSd, (word32)lblsdL, hash_type, HEAP_HINT, devId); + PRIVATE_KEY_LOCK(); if (ret != 0) { printf("Failed w/ code: %d\n", ret); return WC_TEST_RET_ENC_EC(ret); @@ -49943,9 +49964,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t tls12_kdf_test(void) if (ret != 0) return ret; + PRIVATE_KEY_UNLOCK(); ret = wc_PRF_TLS(result, msSz, pms, pmsSz, (const byte*)label, (word32)XSTRLEN(label), seed, seedSz, 1, sha256_mac, NULL, devId); + PRIVATE_KEY_LOCK(); if (ret != 0) { if (ret == WC_NO_ERR_TRACE(FIPS_PRIVATE_KEY_LOCKED_E)) { printf(" wc_PRF_TLSv12: Private key locked.\n"); @@ -50522,6 +50545,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t tls13_kdf_test(void) const Tls13KdfTestVector* tv = NULL; WOLFSSL_ENTER("tls13_kdf_test"); + PRIVATE_KEY_UNLOCK(); for (i = 0, tv = tls13KdfTestVectors; i < tc; i++, tv++) { byte output[WC_MAX_DIGEST_SIZE]; byte secret[WC_MAX_DIGEST_SIZE]; @@ -50652,6 +50676,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t tls13_kdf_test(void) (unsigned long)hashAlgSz); if (ret != 0) break; } + PRIVATE_KEY_LOCK(); return ret; } @@ -52106,6 +52131,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srtpkdf_test(void) WOLFSSL_ENTER("srtpkdf_test"); + PRIVATE_KEY_UNLOCK(); + for (i = 0; (ret == 0) && (i < SRTP_TV_CNT); i++) { #ifndef WOLFSSL_AES_128 if (tv[i].keySz == AES_128_KEY_SIZE) { @@ -52396,6 +52423,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t srtpkdf_test(void) out: + PRIVATE_KEY_LOCK(); + #ifdef SRTP_KDF_LONG_KEY WC_FREE_VAR(keyELong, HEAP_HINT); WC_FREE_VAR(keyALong, HEAP_HINT); @@ -53604,6 +53633,7 @@ static wc_test_ret_t ecc_test_cdh_vectors(WC_RNG* rng) /* compute ECC Cofactor shared secret */ x = sizeof(sharedA); + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -53611,6 +53641,7 @@ static wc_test_ret_t ecc_test_cdh_vectors(WC_RNG* rng) if (ret == 0) ret = wc_ecc_shared_secret(priv_key, pub_key, sharedA, &x); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); TEST_SLEEP(); @@ -53748,7 +53779,9 @@ static wc_test_ret_t ecc_test_make_pub(WC_RNG* rng) #ifdef HAVE_ECC_KEY_EXPORT x = ECC_BUFSIZE; + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_private_only(key, exportBuf, &x); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -53860,7 +53893,9 @@ static wc_test_ret_t ecc_test_make_pub(WC_RNG* rng) #if defined(HAVE_ECC_DHE) && defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) /* now test private only key with creating a shared secret */ x = ECC_BUFSIZE; + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_private_only(key, exportBuf, &x); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -53903,6 +53938,7 @@ static wc_test_ret_t ecc_test_make_pub(WC_RNG* rng) #endif x = ECC_BUFSIZE; + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -53910,6 +53946,7 @@ static wc_test_ret_t ecc_test_make_pub(WC_RNG* rng) if (ret == 0) ret = wc_ecc_shared_secret(key, pub, exportBuf, &x); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); wc_ecc_free(pub); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -54310,6 +54347,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif #endif x = ECC_SHARED_SIZE; + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &userA->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -54317,11 +54355,13 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (ret == 0) ret = wc_ecc_shared_secret(userA, userB, sharedA, &x); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); TEST_SLEEP(); y = ECC_SHARED_SIZE; + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &userB->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -54329,6 +54369,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (ret == 0) ret = wc_ecc_shared_secret(userB, userA, sharedB, &y); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -54345,6 +54386,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif wc_ecc_set_flags(userB, WC_ECC_FLAG_COFACTOR); x = ECC_SHARED_SIZE; + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &userA->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -54352,11 +54394,13 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (ret == 0) ret = wc_ecc_shared_secret(userA, userB, sharedA, &x); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); TEST_SLEEP(); y = ECC_SHARED_SIZE; + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &userB->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -54364,6 +54408,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (ret == 0) ret = wc_ecc_shared_secret(userB, userA, sharedB, &y); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -54403,6 +54448,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif !defined(WOLFSSL_MICROCHIP_TA100) #ifdef HAVE_ECC_DHE y = ECC_SHARED_SIZE; + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &userB->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -54410,6 +54456,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (ret == 0) ret = wc_ecc_shared_secret(userB, pubKey, sharedB, &y); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -54442,6 +54489,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif #ifdef HAVE_ECC_DHE y = ECC_SHARED_SIZE; + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &userB->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -54449,6 +54497,7 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif if (ret == 0) ret = wc_ecc_shared_secret(userB, pubKey, sharedB, &y); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -54573,7 +54622,9 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif !defined(WC_TEST_SKIP_ECC_PRIVATE_EXPORT) && \ !defined(WOLFSSL_MICROCHIP_TA100) x = ECC_KEY_EXPORT_BUF_SIZE; + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_private_only(userA, exportBuf, &x); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); #elif defined(HAVE_ECC_KEY_EXPORT) @@ -55057,7 +55108,9 @@ static wc_test_ret_t ecc_exp_imp_test(ecc_key* key) wc_ecc_init_ex(keyImp, HEAP_HINT, devId); privLen = sizeof(priv); + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_private_only(key, priv, &privLen); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); pubLen = sizeof(pub); @@ -55112,8 +55165,10 @@ static wc_test_ret_t ecc_exp_imp_test(ecc_key* key) /* test export private and public raw */ pubLenX = pubLenY = privLen = 32; + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_private_raw(key, pub, &pubLenX, &pub[32], &pubLenY, priv, &privLen); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -55259,16 +55314,24 @@ static wc_test_ret_t ecc_ssh_test(ecc_key* key, WC_RNG* rng) word32 outLen = sizeof(out); /* Parameter Validation testing. */ + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_shared_secret_ssh(NULL, &key->pubkey, out, &outLen); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_shared_secret_ssh(key, NULL, out, &outLen); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, NULL, &outLen); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, out, NULL); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return WC_TEST_RET_ENC_EC(ret); @@ -55284,6 +55347,7 @@ static wc_test_ret_t ecc_ssh_test(ecc_key* key, WC_RNG* rng) /* Use API. */ ret = 0; + PRIVATE_KEY_UNLOCK(); do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -55291,6 +55355,7 @@ static wc_test_ret_t ecc_ssh_test(ecc_key* key, WC_RNG* rng) if (ret == 0) ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, out, &outLen); } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -56246,7 +56311,9 @@ static int ecc_sm2_test_curve(WC_RNG* rng, int testVerifyCount) #if defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) x = ECC_KEY_EXPORT_BUF_SIZE; + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_private_only(userA, exportBuf, &x); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); #elif defined(HAVE_ECC_KEY_EXPORT) @@ -57089,10 +57156,12 @@ static wc_test_ret_t ecc_test_nonblock_dhe(int curveId, word32 curveSz, } count = 0; if (ret == 0) { + PRIVATE_KEY_UNLOCK(); do { ret = wc_ecc_shared_secret(&keyA, &keyB, secretA, &secretSzA); count++; } while (ret == FP_WOULDBLOCK); + PRIVATE_KEY_LOCK(); if (ret < 0) ret = WC_TEST_RET_ENC_EC(ret); } @@ -57100,9 +57169,11 @@ static wc_test_ret_t ecc_test_nonblock_dhe(int curveId, word32 curveSz, fprintf(stderr, "ECC non-block shared secret: %d times\n", count); #endif if (ret == 0) { + PRIVATE_KEY_UNLOCK(); do { ret = wc_ecc_shared_secret(&keyB, &keyA, secretB, &secretSzB); } while (ret == FP_WOULDBLOCK); + PRIVATE_KEY_LOCK(); if (ret < 0) ret = WC_TEST_RET_ENC_EC(ret); } @@ -57575,10 +57646,14 @@ static wc_test_ret_t ecc_se050_onlykeyid_test(WC_RNG* rng) ret = wc_ecc_set_rng(&swKey, rng); if (ret != 0) { ret = WC_TEST_RET_ENC_EC(ret); goto ecdh_done; } + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_shared_secret(&swKey, &peer, secretSw, &secretSwSz); + PRIVATE_KEY_LOCK(); if (ret != 0) { ret = WC_TEST_RET_ENC_EC(ret); goto ecdh_done; } + PRIVATE_KEY_UNLOCK(); ret = wc_ecc_shared_secret(&hwKey, &peer, secretHw, &secretHwSz); + PRIVATE_KEY_LOCK(); if (ret != 0) { ret = WC_TEST_RET_ENC_EC(ret); goto ecdh_done; } /* The peer was and must remain a software key (keyIdSet == 0) */ @@ -57672,7 +57747,9 @@ static wc_test_ret_t ecc_no_sw_test(void) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + PRIVATE_KEY_UNLOCK(); ret = (wc_test_ret_t)wc_ecc_shared_secret(privKey, pubKey, out, &outLen); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(NOT_COMPILED_IN)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -61424,7 +61501,9 @@ static wc_test_ret_t ed25519_export_key_no_pub_test(void) /* wc_ed25519_export_key() must propagate the missing-public-key error. */ if (res == 0) { + PRIVATE_KEY_UNLOCK(); ret = wc_ed25519_export_key(&key, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(PUBLIC_KEY_E)) { res = WC_TEST_RET_ENC_NC; } @@ -62138,7 +62217,10 @@ static wc_test_ret_t ed25519_kat_test(ed25519_key* key, ed25519_key* key2) if (wc_ed25519_import_public_ex(exportPKey, exportPSz, key2, 1) != 0) ERROR_OUT(WC_TEST_RET_ENC_I(i), exit_ed25519_kat); - if (wc_ed25519_export_private_only(key, exportSKey, &exportSSz) != 0) + PRIVATE_KEY_UNLOCK(); + ret = wc_ed25519_export_private_only(key, exportSKey, &exportSSz); + PRIVATE_KEY_LOCK(); + if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_I(i), exit_ed25519_kat); if (wc_ed25519_import_private_key(exportSKey, exportSSz, @@ -63738,7 +63820,9 @@ static wc_test_ret_t ed448_export_key_no_pub_test(void) /* wc_ed448_export_key() must propagate the missing-public-key error. */ if (res == 0) { + PRIVATE_KEY_UNLOCK(); ret = wc_ed448_export_key(&key, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(PUBLIC_KEY_E)) { res = WC_TEST_RET_ENC_NC; } @@ -64511,7 +64595,11 @@ static wc_test_ret_t ed448_kat_test(ed448_key* key, ed448_key* key2) break; } - if (wc_ed448_export_private_only(key, exportSKey, &exportSSz) != 0) { + PRIVATE_KEY_UNLOCK(); + ret = wc_ed448_export_private_only(key, exportSKey, + &exportSSz); + PRIVATE_KEY_LOCK(); + if (ret != 0) { ret = WC_TEST_RET_ENC_I(i); break; } @@ -69336,11 +69424,15 @@ static wc_test_ret_t mlkem_seed_consistency_test(void) goto out_seed; } ret = wc_MlKemKey_MakeKeyWithRandom(key, seed, (int)sizeof(seed)); - if (ret == SEED_OK) + if (ret == SEED_OK) { ret = wc_MlKemKey_PrivateKeySize(key, &expandedSz); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + else + ret = WC_TEST_RET_ENC_EC(ret); if (ret != 0) { wc_MlKemKey_Free(key); - ret = WC_TEST_RET_ENC_EC(ret); goto out_seed; } expanded = (byte*)XMALLOC(expandedSz, HEAP_HINT, @@ -69350,7 +69442,9 @@ static wc_test_ret_t mlkem_seed_consistency_test(void) ret = WC_TEST_RET_ENC_ERRNO; goto out_seed; } + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_EncodePrivateKey(key, expanded, expandedSz); + PRIVATE_KEY_LOCK(); wc_MlKemKey_Free(key); if (ret != 0) { ret = WC_TEST_RET_ENC_EC(ret); @@ -69424,17 +69518,23 @@ static wc_test_ret_t mlkem_seed_consistency_test(void) goto out_seed; } idx = 0; + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_PrivateKeyDecode(key, der, n, &idx); - - if (((j == 0) || (j == 2)) && (ret != 0)) { - wc_MlKemKey_Free(key); - ret = WC_TEST_RET_ENC_EC(ret); /* valid, must decode */ - goto out_seed; + PRIVATE_KEY_LOCK(); + if ((j == 0) || (j == 2)) { + if (ret != 0) { + ret = WC_TEST_RET_ENC_EC(ret); + wc_MlKemKey_Free(key); + goto out_seed; + } } - if (((j == 1) || (j == 3)) && (ret == 0)) { - wc_MlKemKey_Free(key); - ret = WC_TEST_RET_ENC_NC; /* invalid, must not decode */ - goto out_seed; + else { + if (ret == 0) { + wc_MlKemKey_Free(key); + ret = WC_TEST_RET_ENC_NC; /* invalid, must not decode */ + goto out_seed; + } + ret = 0; /* refusal was the pass condition */ } if (j == 2) { /* the seed alone must reproduce the expanded key exactly */ @@ -69445,7 +69545,11 @@ static wc_test_ret_t mlkem_seed_consistency_test(void) ret = WC_TEST_RET_ENC_ERRNO; goto out_seed; } + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_EncodePrivateKey(key, again, expandedSz); + PRIVATE_KEY_LOCK(); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); if (ret == 0 && XMEMCMP(again, expanded, expandedSz) != 0) ret = WC_TEST_RET_ENC_NC; XMEMSET(again, 0, expandedSz); @@ -69456,7 +69560,6 @@ static wc_test_ret_t mlkem_seed_consistency_test(void) } } wc_MlKemKey_Free(key); - ret = 0; XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); der = NULL; @@ -69534,15 +69637,24 @@ static wc_test_ret_t mlkem_asn1_test(void) if (ret == 0) { keyInit = 1; ret = wc_MlKemKey_MakeKey(key, &rng); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); } + else + ret = WC_TEST_RET_ENC_EC(ret); /* The generated key produces the ciphertext every decode is measured * against. */ - if (ret == 0) + if (ret == 0) { ret = wc_MlKemKey_CipherTextSize(key, &ctLen); - if (ret == 0) + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { ret = wc_MlKemKey_Encapsulate(key, ct, ss, &rng); - + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } if (ret == 0) { pubLen = wc_MlKemKey_PublicKeyToDer(key, NULL, 0, 1); if (pubLen <= 0) @@ -69583,7 +69695,8 @@ static wc_test_ret_t mlkem_asn1_test(void) /* A DER naming a different parameter set must be refused. */ if (ret == 0) { - if (wc_MlKemKey_Init(key, wrongLevel, HEAP_HINT, devId) == 0) { + ret = wc_MlKemKey_Init(key, wrongLevel, HEAP_HINT, devId); + if (ret == 0) { idx = 0; if (wc_MlKemKey_PublicKeyDecode(key, pubDer, (word32)pubLen, &idx) == 0) { @@ -69591,6 +69704,8 @@ static wc_test_ret_t mlkem_asn1_test(void) } wc_MlKemKey_Free(key); } + else + ret = WC_TEST_RET_ENC_EC(ret); } /* Initialised without a parameter set, each decode names it. */ if (ret == 0) { @@ -69600,10 +69715,14 @@ static wc_test_ret_t mlkem_asn1_test(void) idx = 0; ret = wc_MlKemKey_PublicKeyDecode(key, pubDer, (word32)pubLen, &idx); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); if ((ret == 0) && (key->type != levels[i])) ret = WC_TEST_RET_ENC_NC; wc_MlKemKey_Free(key); } + else + ret = WC_TEST_RET_ENC_EC(ret); } if (ret == 0) { ret = wc_MlKemKey_Init(key, WC_ML_KEM_TYPE_UNSET, HEAP_HINT, @@ -69612,10 +69731,14 @@ static wc_test_ret_t mlkem_asn1_test(void) idx = 0; ret = wc_MlKemKey_PrivateKeyDecode(key, privDer, (word32)privLen, &idx); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); if ((ret == 0) && (key->type != levels[i])) ret = WC_TEST_RET_ENC_NC; wc_MlKemKey_Free(key); } + else + ret = WC_TEST_RET_ENC_EC(ret); } /* The PKCS#8 round trip must recover the original decapsulation key. */ @@ -69623,15 +69746,23 @@ static wc_test_ret_t mlkem_asn1_test(void) ret = wc_MlKemKey_Init(key, levels[i], HEAP_HINT, devId); if (ret == 0) keyInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); } if (ret == 0) { idx = 0; ret = wc_MlKemKey_PrivateKeyDecode(key, privDer, (word32)privLen, &idx); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); } if (ret == 0) { XMEMSET(ssDec, 0, sizeof(ssDec)); + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_Decapsulate(key, ssDec, ct, ctLen); + PRIVATE_KEY_LOCK(); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); } if (ret == 0) { if (XMEMCMP(ss, ssDec, WC_ML_KEM_SS_SZ) != 0) @@ -69648,14 +69779,21 @@ static wc_test_ret_t mlkem_asn1_test(void) ret = wc_MlKemKey_Init(key, levels[i], HEAP_HINT, devId); if (ret == 0) keyInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); } if (ret == 0) { idx = 0; ret = wc_MlKemKey_PublicKeyDecode(key, pubDer, (word32)pubLen, &idx); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); } - if (ret == 0) + if (ret == 0) { ret = wc_MlKemKey_Encapsulate(key, ct, ss, &rng); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } if (keyInit) { wc_MlKemKey_Free(key); keyInit = 0; @@ -69664,15 +69802,23 @@ static wc_test_ret_t mlkem_asn1_test(void) ret = wc_MlKemKey_Init(key, levels[i], HEAP_HINT, devId); if (ret == 0) keyInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); } if (ret == 0) { idx = 0; ret = wc_MlKemKey_PrivateKeyDecode(key, privDer, (word32)privLen, &idx); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); } if (ret == 0) { XMEMSET(ssDec, 0, sizeof(ssDec)); + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_Decapsulate(key, ssDec, ct, ctLen); + PRIVATE_KEY_LOCK(); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); } if (ret == 0) { if (XMEMCMP(ss, ssDec, WC_ML_KEM_SS_SZ) != 0) @@ -69766,77 +69912,71 @@ static wc_test_ret_t mlkem_cert_test(WC_RNG* rng) key = (MlKemKey*)XMALLOC(sizeof(MlKemKey), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); spki = (byte*)XMALLOC(spkiSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL || spki == NULL) { - ret = WC_TEST_RET_ENC_ERRNO; - goto free_vector; - } + if (key == NULL || spki == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, free_vector); /* Pull the SubjectPublicKeyInfo straight out of the certificate. */ ret = wc_GetSubjectPubKeyInfoDerFromCert(vectors[i].cert, vectors[i].certSz, spki, &spkiSz); - if (ret == 0) { - ret = wc_MlKemKey_Init(key, vectors[i].level, HEAP_HINT, devId); - if (ret == 0) - keyInit = 1; - } + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); + ret = wc_MlKemKey_Init(key, vectors[i].level, HEAP_HINT, devId); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); + keyInit = 1; /* Decoding only succeeds when the SPKI names this parameter set. */ - if (ret == 0) { - idx = 0; - ret = wc_MlKemKey_PublicKeyDecode(key, spki, spkiSz, &idx); - } - if (ret == 0) - ret = wc_MlKemKey_PublicKeySize(key, &pubSz); - if (ret == 0) { - pubA = (byte*)XMALLOC(pubSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - pubB = (byte*)XMALLOC(pubSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (pubA == NULL || pubB == NULL) { - ret = WC_TEST_RET_ENC_ERRNO; - goto free_vector; - } - } - if (ret == 0) - ret = wc_MlKemKey_EncodePublicKey(key, pubA, pubSz); + idx = 0; + ret = wc_MlKemKey_PublicKeyDecode(key, spki, spkiSz, &idx); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); + ret = wc_MlKemKey_PublicKeySize(key, &pubSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); + pubA = (byte*)XMALLOC(pubSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pubB = (byte*)XMALLOC(pubSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (pubA == NULL || pubB == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, free_vector); + ret = wc_MlKemKey_EncodePublicKey(key, pubA, pubSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); #ifdef MLKEM_CERT_TEST_KEM /* Encapsulate to the certificate key, decapsulate below. */ - if (ret == 0) - ret = wc_MlKemKey_CipherTextSize(key, &ctSz); - if (ret == 0) { - ct = (byte*)XMALLOC(ctSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (ct == NULL) - ret = WC_TEST_RET_ENC_ERRNO; - } - if (ret == 0) - ret = wc_MlKemKey_Encapsulate(key, ct, ssA, rng); -#endif - if (keyInit) { - wc_MlKemKey_Free(key); - keyInit = 0; - } + ret = wc_MlKemKey_CipherTextSize(key, &ctSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); + ct = (byte*)XMALLOC(ctSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (ct == NULL) + ERROR_OUT(WC_TEST_RET_ENC_ERRNO, free_vector); + ret = wc_MlKemKey_Encapsulate(key, ct, ssA, rng); if (ret != 0) - goto free_vector; + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); +#endif + wc_MlKemKey_Free(key); + keyInit = 0; ret = wc_MlKemKey_Init(key, vectors[i].level, HEAP_HINT, devId); - if (ret == 0) - keyInit = 1; - if (ret == 0) { - idx = 0; - ret = wc_MlKemKey_PrivateKeyDecode(key, vectors[i].key, - vectors[i].keySz, &idx); - } + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); + keyInit = 1; + idx = 0; + ret = wc_MlKemKey_PrivateKeyDecode(key, vectors[i].key, + vectors[i].keySz, &idx); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); /* The private key must reproduce the certificate's public key. */ - if (ret == 0) - ret = wc_MlKemKey_EncodePublicKey(key, pubB, pubSz); - if (ret == 0) { - if (XMEMCMP(pubA, pubB, pubSz) != 0) - ret = WC_TEST_RET_ENC_NC; - } + ret = wc_MlKemKey_EncodePublicKey(key, pubB, pubSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); + if (XMEMCMP(pubA, pubB, pubSz) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, free_vector); #ifdef MLKEM_CERT_TEST_KEM - if (ret == 0) - ret = wc_MlKemKey_Decapsulate(key, ssB, ct, ctSz); - if (ret == 0) { - if (XMEMCMP(ssA, ssB, sizeof(ssA)) != 0) - ret = WC_TEST_RET_ENC_NC; - } + PRIVATE_KEY_UNLOCK(); + ret = wc_MlKemKey_Decapsulate(key, ssB, ct, ctSz); + PRIVATE_KEY_LOCK(); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), free_vector); + if (XMEMCMP(ssA, ssB, sizeof(ssA)) != 0) + ERROR_OUT(WC_TEST_RET_ENC_NC, free_vector); #endif free_vector: @@ -70153,48 +70293,67 @@ static wc_test_ret_t mlkem_decode_pub_test(void) ret = wc_MlKemKey_Init(a, WC_ML_KEM_768, HEAP_HINT, INVALID_DEVID); a_inited = (ret == 0); - if (ret == 0) { - ret = wc_MlKemKey_Init(b, WC_ML_KEM_768, HEAP_HINT, INVALID_DEVID); - b_inited = (ret == 0); - } - if (ret == 0) - ret = wc_RNG_GenerateBlock(&rng, rnd, sizeof(rnd)); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_Init(b, WC_ML_KEM_768, HEAP_HINT, INVALID_DEVID); + b_inited = (ret == 0); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_RNG_GenerateBlock(&rng, rnd, sizeof(rnd)); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); /* Same key twice; a's public key hash is not computed yet. */ - if (ret == 0) - ret = wc_MlKemKey_MakeKeyWithRandom(a, rnd, sizeof(rnd)); - if (ret == SEED_OK) - ret = wc_MlKemKey_MakeKeyWithRandom(b, rnd, sizeof(rnd)); - if (ret == SEED_OK) - ret = wc_MlKemKey_PublicKeySize(b, &pubSz); - if (ret == 0) - ret = wc_MlKemKey_CipherTextSize(b, &ctSz); - if (ret == 0) - ret = wc_MlKemKey_EncodePublicKey(b, pub, pubSz); - if (ret == 0) - ret = wc_MlKemKey_Encapsulate(b, ct, ss, &rng); - if (ret == 0) - ret = wc_MlKemKey_DecodePublicKey(a, pub, pubSz); - if (ret == 0) - ret = wc_MlKemKey_Decapsulate(a, ssA, ct, ctSz); + ret = wc_MlKemKey_MakeKeyWithRandom(a, rnd, sizeof(rnd)); + if (ret != SEED_OK) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_MakeKeyWithRandom(b, rnd, sizeof(rnd)); + if (ret != SEED_OK) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_PublicKeySize(b, &pubSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_CipherTextSize(b, &ctSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_EncodePublicKey(b, pub, pubSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_Encapsulate(b, ct, ss, &rng); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_DecodePublicKey(a, pub, pubSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + PRIVATE_KEY_UNLOCK(); + ret = wc_MlKemKey_Decapsulate(a, ssA, ct, ctSz); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); if (XMEMCMP(ss, ssA, sizeof(ss)) != 0) ERROR_OUT(WC_TEST_RET_ENC_NC, out); ret = wc_MlKemKey_MakeKey(b, &rng); - if (ret == 0) - ret = wc_MlKemKey_EncodePublicKey(b, pub, pubSz); - if (ret == 0) - ret = wc_MlKemKey_Encapsulate(b, ct, ss, &rng); - if (ret == 0) - ret = wc_MlKemKey_DecodePublicKey(a, pub, pubSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_EncodePublicKey(b, pub, pubSz); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_Encapsulate(b, ct, ss, &rng); + if (ret != 0) + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = wc_MlKemKey_DecodePublicKey(a, pub, pubSz); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + /* a now holds only a decoded public key: decapsulation must be refused + * by the library proper. Unlock so the FIPS wrapper's private-key gate + * doesn't preempt the BAD_STATE_E this probe exists to observe. */ + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_Decapsulate(a, ssA, ct, ctSz); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_STATE_E)) - ERROR_OUT(WC_TEST_RET_ENC_NC, out); - ret = 0; + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); + ret = 0; /* refusal was the pass condition */ out: if (a_inited) @@ -70385,9 +70544,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t mlkem_test(void) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_I(i), out); + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_EncodePrivateKey(key, priv, testData[i][1]); + PRIVATE_KEY_LOCK(); if (ret != 0) - ERROR_OUT(WC_TEST_RET_ENC_I(i), out); + ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); wc_MlKemKey_Free(key); ret = wc_MlKemKey_Init(key, testData[i][0], HEAP_HINT, devId); @@ -70427,7 +70588,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t mlkem_test(void) #if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \ !defined(WOLFSSL_MLKEM_NO_DECAPSULATE) + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_Decapsulate(key, ss_dec, ct, testData[i][3]); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_I(i), out); @@ -70435,7 +70598,9 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t mlkem_test(void) ERROR_OUT(WC_TEST_RET_ENC_I(i), out); #endif + PRIVATE_KEY_UNLOCK(); ret = wc_MlKemKey_EncodePrivateKey(key, priv2, testData[i][1]); + PRIVATE_KEY_LOCK(); if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_I(i), out); @@ -75002,8 +75167,10 @@ static wc_test_ret_t test_mldsa_decode_level(const byte* rawKey, #endif #ifdef WOLFSSL_MLDSA_PRIVATE_KEY if (!isPublicOnlyKey) { + PRIVATE_KEY_UNLOCK(); ret = wc_MlDsaKey_PrivateKeyToDer(key, der, MLDSA_MAX_PRV_KEY_DER_SIZE); + PRIVATE_KEY_LOCK(); if (ret < 0) ret = WC_TEST_RET_ENC_EC(ret); } @@ -104121,10 +104288,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) ret = random_test(); #endif /* WC_NO_RNG */ #if !defined(NO_RSA) - PRIVATE_KEY_UNLOCK(); if (ret == 0) ret = rsa_test(); - PRIVATE_KEY_LOCK(); #endif #if defined(WOLF_CRYPTO_CB_ONLY_RSA) && !defined(WOLFSSL_SWDEV) PRIVATE_KEY_UNLOCK(); @@ -104478,10 +104643,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) ret = dh_cryptocb_test(devId, &myCtx); #endif /* !NO_DH && HAVE_FFDHE_2048 && !WC_NO_RNG */ #if defined(HAVE_ECC) - PRIVATE_KEY_UNLOCK(); if (ret == 0) ret = ecc_test(); - PRIVATE_KEY_LOCK(); /* Confirm the new ECC pubkey callbacks were routed through the device and * not silently handled in software. The check-pubkey callback is only * exercised when wc_ecc_check_key is built (HAVE_ECC_CHECK_KEY) and the @@ -104513,7 +104676,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) int haveZeroKey = 0; WC_ALLOC_VAR(zeroKey, ecc_key, 1, HEAP_HINT); - PRIVATE_KEY_UNLOCK(); if (!WC_VAR_OK(zeroKey)) ret = MEMORY_E; else @@ -104543,7 +104705,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) if (haveZeroKey) wc_ecc_free(zeroKey); WC_FREE_VAR(zeroKey, HEAP_HINT); - PRIVATE_KEY_LOCK(); } #endif /* WOLFSSL_NO_ECC_SW is excluded: wc_CryptoCb_EccMakePub() is called from @@ -104588,7 +104749,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) WC_ALLOC_VAR(srcKey, ecc_key, 1, HEAP_HINT); WC_ALLOC_VAR(resKey, ecc_key, 1, HEAP_HINT); WC_ALLOC_VAR(eccRng, WC_RNG, 1, HEAP_HINT); - PRIVATE_KEY_UNLOCK(); if (!WC_VAR_OK(srcKey) || !WC_VAR_OK(resKey) || !WC_VAR_OK(eccRng)) ret = MEMORY_E; else @@ -104697,7 +104857,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) WC_FREE_VAR(srcKey, HEAP_HINT); WC_FREE_VAR(resKey, HEAP_HINT); WC_FREE_VAR(eccRng, HEAP_HINT); - PRIVATE_KEY_LOCK(); } #endif #endif @@ -105344,10 +105503,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) #endif #if defined(HAVE_ED25519) && \ (!defined(WOLF_CRYPTO_CB_ONLY_ED25519) || defined(WOLFSSL_SWDEV)) - PRIVATE_KEY_UNLOCK(); if (ret == 0) ret = ed25519_test(); - PRIVATE_KEY_LOCK(); #endif #if defined(WOLF_CRYPTO_CB_ONLY_ED25519) && !defined(WOLFSSL_SWDEV) PRIVATE_KEY_UNLOCK(); @@ -105532,8 +105689,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) #endif #endif #if defined(HAVE_HKDF) && !defined(NO_HMAC) - if (ret == 0) + if (ret == 0) { + PRIVATE_KEY_UNLOCK(); ret = hkdf_test(); + PRIVATE_KEY_LOCK(); + } #if !defined(NO_SHA256) && !defined(HAVE_SELFTEST) && \ !defined(HAVE_FIPS) if (ret == 0) From aaaa9562747f0dfa741ed7f96e53e7787feac809 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 15:33:19 -0600 Subject: [PATCH 15/28] wolfssl/wolfcrypt/types.h: assert "CHAR_BIT must be a positive multiple of 8." before defining WC_OCTETS_PER_BYTE and WC_PACKED_CELLS. --- wolfssl/wolfcrypt/types.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 0a33992fc4b..bcae15817a9 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -346,6 +346,9 @@ typedef const char wcchar[]; * octets per cell, low octet first. Convert at the boundary with * wc_UnpackOctets()/wc_PackOctets(), declared only where a cell is wider than * an octet - elsewhere the two layouts coincide and there is nothing to do. */ +#if (CHAR_BIT <= 0) || (CHAR_BIT % 8 != 0) + #error CHAR_BIT must be a positive multiple of 8. +#endif #define WC_OCTETS_PER_BYTE ((word32)(CHAR_BIT / 8)) /* Cells needed to hold octetSz octets packed. Divides before adding the * round-up so a near-WORD32_MAX octetSz cannot wrap. octetSz is evaluated From 7fe0a0685341bfea423432817ee88a314de4f851 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 16:37:28 -0600 Subject: [PATCH 16/28] wolfcrypt/test/test.c: PRIVATE_KEY_{UNLOCK,LOCK} wraps for private key API calls in dh_*_test() (FIPS v5 coverage). --- wolfcrypt/test/test.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 7e30af55ad6..9ae0d15d54c 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -44179,22 +44179,34 @@ static wc_test_ret_t dh_fips_generate_test(WC_RNG *rng) #endif /* Parameter Validation testing. */ + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(NULL, rng, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_gen_test); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, NULL, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_gen_test); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, NULL, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_gen_test); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, priv, NULL, pub, &pubSz); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_gen_test); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, priv, &privSz, NULL, &pubSz); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_gen_test); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, priv, &privSz, pub, NULL); + PRIVATE_KEY_LOCK(); if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_gen_test); @@ -44217,7 +44229,9 @@ static wc_test_ret_t dh_fips_generate_test(WC_RNG *rng) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_gen_test); /* Use API. */ + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); #endif @@ -44287,7 +44301,9 @@ static wc_test_ret_t dh_fips_generate_test(WC_RNG *rng) privSz = sizeof(priv); pubSz = sizeof(pub); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); #endif @@ -44398,7 +44414,9 @@ static wc_test_ret_t dh_generate_test(WC_RNG *rng) privSz = sizeof(priv); pubSz = sizeof(pub); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(smallKey, rng, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &smallKey->asyncDev, WC_ASYNC_FLAG_NONE); #endif @@ -44598,28 +44616,36 @@ static wc_test_ret_t dh_ffdhe_test(WC_RNG *rng, int name) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); #endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key2, rng, priv2, &privSz2, pub2, &pubSz2); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key2->asyncDev, WC_ASYNC_FLAG_NONE); #endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + PRIVATE_KEY_UNLOCK(); ret = wc_DhAgree(key, agree, &agreeSz, priv, privSz, pub2, pubSz2); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); #endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + PRIVATE_KEY_UNLOCK(); ret = wc_DhAgree(key2, agree2, &agreeSz2, priv2, privSz2, pub, pubSz); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key2->asyncDev, WC_ASYNC_FLAG_NONE); #endif @@ -44641,6 +44667,7 @@ static wc_test_ret_t dh_ffdhe_test(WC_RNG *rng, int name) if (nb_ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(nb_ret), done); + PRIVATE_KEY_UNLOCK(); do { nb_ret = wc_DhAgree(key, agree2, &nbAgreeSz, priv, privSz, pub2, pubSz2); @@ -44658,6 +44685,7 @@ static wc_test_ret_t dh_ffdhe_test(WC_RNG *rng, int name) } #endif } while (nb_ret == WC_NO_ERR_TRACE(MP_WOULDBLOCK) || + PRIVATE_KEY_LOCK(); nb_ret == WC_NO_ERR_TRACE(WC_PENDING_E)); if (nb_ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(nb_ret), done); @@ -44725,7 +44753,9 @@ static wc_test_ret_t dh_ffdhe_test(WC_RNG *rng, int name) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, priv, &privSz, pub, &pubSz); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); #endif @@ -44735,7 +44765,9 @@ static wc_test_ret_t dh_ffdhe_test(WC_RNG *rng, int name) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); } + PRIVATE_KEY_UNLOCK(); ret = wc_DhAgree(key, agree, &agreeSz, priv, privSz, pub2, pubSz2); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); #endif @@ -44807,28 +44839,36 @@ static wc_test_ret_t dh_keyagree_test(DhKey* key, DhKey* key2, WC_RNG* rng, word32 agreeSz = agreeBufSz; word32 agreeSz2 = agreeBufSz2; + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key, rng, priv, privSz, pub, pubSz); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); #endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_dh_keyagree); + PRIVATE_KEY_UNLOCK(); ret = wc_DhGenerateKeyPair(key2, rng, priv2, privSz2, pub2, pubSz2); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key2->asyncDev, WC_ASYNC_FLAG_NONE); #endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_dh_keyagree); + PRIVATE_KEY_UNLOCK(); ret = wc_DhAgree(key, agree, &agreeSz, priv, *privSz, pub2, *pubSz2); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE); #endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_dh_keyagree); + PRIVATE_KEY_UNLOCK(); ret = wc_DhAgree(key2, agree2, &agreeSz2, priv2, *privSz2, pub, *pubSz); + PRIVATE_KEY_LOCK(); #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key2->asyncDev, WC_ASYNC_FLAG_NONE); #endif From 5266c5cab46791b3a693be6f9ae92f8323f24651 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 16:38:28 -0600 Subject: [PATCH 17/28] wolfssl/wolfcrypt/wc_compat.h: add a prototype for ForceZero() in WOLFSSL_NO_FORCE_ZERO code path. --- wolfssl/wolfcrypt/wc_compat.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wolfssl/wolfcrypt/wc_compat.h b/wolfssl/wolfcrypt/wc_compat.h index f290f4243c2..4a0ec45b796 100644 --- a/wolfssl/wolfcrypt/wc_compat.h +++ b/wolfssl/wolfcrypt/wc_compat.h @@ -74,6 +74,11 @@ * the exported zeroizer here for the inline shims below. Redeclaration * with identical tokens is harmless. */ #ifdef WOLFSSL_NO_FORCE_ZERO + /* The application-supplied zeroizer -- same tokens as misc.h, which + * no include path can have parsed yet (misc.h includes types.h, + * which reaches this header first). */ + /* NOLINTNEXTLINE(readability-redundant-declaration) */ + void ForceZero(void* mem, size_t len); #undef wc_ForceZero #define wc_ForceZero ForceZero #else From 18cccae8bbc6da223740be386341c0e18399154f Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 17:34:21 -0600 Subject: [PATCH 18/28] wolfcrypt/test/test.c: fix refactor flub (PRIVATE_KEY_LOCK() placement) in dh_ffdhe_test(). --- wolfcrypt/test/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9ae0d15d54c..93b1ef79814 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -44685,8 +44685,8 @@ static wc_test_ret_t dh_ffdhe_test(WC_RNG *rng, int name) } #endif } while (nb_ret == WC_NO_ERR_TRACE(MP_WOULDBLOCK) || - PRIVATE_KEY_LOCK(); nb_ret == WC_NO_ERR_TRACE(WC_PENDING_E)); + PRIVATE_KEY_LOCK(); if (nb_ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(nb_ret), done); From 95e484ab2bbb94c7ff132b9bdaedd88e6c769012 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 18:26:36 -0600 Subject: [PATCH 19/28] wolfcrypt/test/test.c: in mlkem_asn1_test(), fix calculation of wrongLevel for the mismatched _PublicKeyDecode() refusal test. --- wolfcrypt/test/test.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 93b1ef79814..dd3179e831a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -69627,6 +69627,7 @@ static wc_test_ret_t mlkem_asn1_test(void) WC_RNG rng; int rngInit = 0; int i; + int nlevels; static const int levels[] = { #if defined(WOLFSSL_WC_ML_KEM_512) && !defined(WOLFSSL_NO_ML_KEM) WC_ML_KEM_512, @@ -69640,6 +69641,9 @@ static wc_test_ret_t mlkem_asn1_test(void) -1 }; + /* count the number of valid levels compiled in: */ + for (nlevels = 0; levels[nlevels] != -1; ++nlevels); + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); @@ -69658,8 +69662,10 @@ static wc_test_ret_t mlkem_asn1_test(void) word32 ctLen = 0; int pubLen = 0; int privLen = 0; - int wrongLevel = (levels[i] == WC_ML_KEM_512) ? WC_ML_KEM_1024 : - WC_ML_KEM_512; + /* Always a compiled-in set, so wc_MlKemKey_Init(wrongLevel) below is + * expected to succeed. In a single-set build it aliases levels[i] and + * the cross-set refusal check is skipped. */ + int wrongLevel = levels[(i + 1) % nlevels]; int keyInit = 0; key = (MlKemKey*)XMALLOC(sizeof(MlKemKey), HEAP_HINT, @@ -69733,8 +69739,9 @@ static wc_test_ret_t mlkem_asn1_test(void) keyInit = 0; } - /* A DER naming a different parameter set must be refused. */ - if (ret == 0) { + /* A DER naming a different parameter set must be refused. Needs a + * second compiled-in set to name -- single-set builds have none. */ + if ((ret == 0) && (nlevels > 1)) { ret = wc_MlKemKey_Init(key, wrongLevel, HEAP_HINT, devId); if (ret == 0) { idx = 0; From 784db73bc18588aa9df2b6650e69f3f2d6049233 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 22:25:17 -0600 Subject: [PATCH 20/28] wolfcrypt/src/pkcs7.c and wolfcrypt/src/hpke.c: add internal PRIVATE_KEY_UNLOCK()/LOCK() pairs for FIPS-gated KDF/KEM calls whose output is consumed internally: in wc_PKCS7_GenerateKEK_PWRI() around the wc_PBKDF2() KEK derivation (reached from both wc_PKCS7_AddRecipient_PWRI() and PWRI decode), and in wc_HpkeInitSealContext() and wc_HpkeInitOpenContext() around wc_HpkeSetupBaseSender()/-Receiver(), matching the existing arrangement in wc_HpkeSealBase()/wc_HpkeOpenBase(). Both paths returned FIPS_PRIVATE_KEY_LOCKED_E in FIPS builds; untested previously because configure omits PKCS7 and HPKE from FIPS builds unless explicitly enabled. --- wolfcrypt/src/hpke.c | 20 ++++++++++++++++++-- wolfcrypt/src/pkcs7.c | 4 ++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/hpke.c b/wolfcrypt/src/hpke.c index 759e37a6d2a..8bbc06c9819 100644 --- a/wolfcrypt/src/hpke.c +++ b/wolfcrypt/src/hpke.c @@ -961,6 +961,8 @@ static int wc_HpkeSetupBaseSender(Hpke* hpke, HpkeBaseContext* context, int wc_HpkeInitSealContext(Hpke* hpke, HpkeBaseContext* context, void* ephemeralKey, void* receiverKey, byte* info, word32 infoSz) { + int ret; + if (hpke == NULL || context == NULL || ephemeralKey == NULL || receiverKey == NULL || (info == NULL && infoSz != 0)) { return BAD_FUNC_ARG; @@ -969,8 +971,14 @@ int wc_HpkeInitSealContext(Hpke* hpke, HpkeBaseContext* context, /* zero out all fields */ XMEMSET(context, 0, sizeof(HpkeBaseContext)); - return wc_HpkeSetupBaseSender(hpke, context, ephemeralKey, receiverKey, + /* the derived secrets are consumed internally -- do the FIPS + * private-key unlock for the caller, as wc_HpkeSealBase() does. */ + PRIVATE_KEY_UNLOCK(); + ret = wc_HpkeSetupBaseSender(hpke, context, ephemeralKey, receiverKey, info, infoSz); + PRIVATE_KEY_LOCK(); + + return ret; } /* encrypt a message using an hpke base context, return 0 or error. @@ -1403,13 +1411,21 @@ int wc_HpkeInitOpenContext(Hpke* hpke, HpkeBaseContext* context, void* receiverKey, const byte* pubKey, word16 pubKeySz, byte* info, word32 infoSz) { + int ret; + if (hpke == NULL || context == NULL || receiverKey == NULL || pubKey == NULL || (info == NULL && infoSz != 0)) { return BAD_FUNC_ARG; } - return wc_HpkeSetupBaseReceiver(hpke, context, receiverKey, pubKey, + /* the derived secrets are consumed internally -- do the FIPS + * private-key unlock for the caller, as wc_HpkeOpenBase() does. */ + PRIVATE_KEY_UNLOCK(); + ret = wc_HpkeSetupBaseReceiver(hpke, context, receiverKey, pubKey, pubKeySz, info, infoSz); + PRIVATE_KEY_LOCK(); + + return ret; } /* decrypt a message using a setup hpke context, return 0 or error */ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index c917fd8ab84..ced0ee4e6d6 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -10930,8 +10930,12 @@ static int wc_PKCS7_GenerateKEK_PWRI(wc_PKCS7* pkcs7, byte* passwd, word32 pLen, case PBKDF2_OID: + /* The KEK is consumed internally to wrap/unwrap the CEK -- do + * the FIPS private-key unlock for the caller. */ + PRIVATE_KEY_UNLOCK(); ret = wc_PBKDF2(out, passwd, (int)pLen, salt, (int)saltSz, iterations, (int)outSz, prfOID); + PRIVATE_KEY_LOCK(); if (ret != 0) { return ret; } From b5296c4e077bf81f616baa7a60b0a0177d2d59af Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 2 Nov 2026 23:32:39 -0600 Subject: [PATCH 21/28] .wolfssl_known_macro_extras: garbage collect and fix lexical order. --- .wolfssl_known_macro_extras | 47 ++++--------------------------------- 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 6ebc459788e..72ccf9baaa7 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -574,8 +574,6 @@ NO_TLSX_PSKKEM_PLAIN_ANNOUNCE NO_VAES_SUPPORT NO_VERIFY_OID NO_WC_DHGENERATEPUBLIC -NO_WC_SHE_GETUID -NO_WC_SHE_IMPORT_M123 NO_WC_SHE_LOADKEY NO_WC_SSIZE_TYPE NO_WOLFSSL_ALLOC_ALIGN @@ -846,11 +844,11 @@ WC_HASH_CUSTOM_MAX_DIGEST_SIZE WC_HASH_CUSTOM_MIN_DIGEST_SIZE WC_HAVE_FIPS_INDICATOR WC_INIT_ERROR_WHEN_CONTENDED +WC_LINUXKM_FORCE_SVR_DYNAMIC_AUDITING WC_LINUXKM_NO_ENTROPY_DAEMON WC_LINUXKM_NO_SVR_DYNAMIC_AUDITING WC_LINUXKM_NO_USE_HEAP_WRAPPERS WC_LINUXKM_SPIN_IN_ATOMIC -WC_LINUXKM_FORCE_SVR_DYNAMIC_AUDITING WC_MLDSA_NO_ASM WC_MLKEM_KERNEL_ASM WC_MPFS_ATHENA_NO_BASE_ADDR @@ -861,8 +859,6 @@ WC_NO_RNG_SIMPLE WC_NO_STATIC_ASSERT WC_NO_VERBOSE_RNG WC_PKCS11_FIND_WITH_ID_ONLY -WC_PKCS12_PBKDF_USING_MP_API -WC_PUF_HELPER_COMPACT WC_PUF_SHA3 WC_RNG_BANK_NO_DAEMON_SUPPORT WC_RNG_BANK_NO_DEFAULT_SUPPORT @@ -889,7 +885,6 @@ WC_RSA_NO_FERMAT_CHECK WC_RTL8735B_NO_DERIVE_CACHE WC_RWLOCK_OPS_INLINE WC_SHA2_SMALL_STACK -WC_SHE_SW_DEFAULT WC_SKIP_INCLUDED_C_FILES WC_SLHDSA_KERNEL_ASM WC_SLHDSA_NO_ASM @@ -935,12 +930,8 @@ WOLFSSL_ALTERNATIVE_DOWNGRADE WOLFSSL_ALT_NAMES_NO_REV WOLFSSL_APACHE_MYNEWT WOLFSSL_ARM32_BUILD -WOLFSSL_ARM32_PRIVILEGE_MODE WOLFSSL_ARMASM_NEON_NO_TABLE_LOOKUP -WOLFSSL_ARMASM_SHA3_NO_NEON -WOLFSSL_ARMASM_SHA512_NO_NEON WOLFSSL_ARM_ARCH_NEON_64BIT -WOLFSSL_ASCON_UNROLL WOLFSSL_ASN_EXTRA WOLFSSL_ATECC508 WOLFSSL_ATECC508A_NOSOFTECC @@ -981,18 +972,13 @@ WOLFSSL_CRL_ALLOW_MISSING_CDP WOLFSSL_CRYPTOCELL WOLFSSL_CRYPTOCELL_AES WOLFSSL_DEBUG_TRACE_ERROR_CODES_SUPPORT -WOLFSSL_DILITHIUM_VERIFY_SMALLEST_MEM WOLFSSL_DISABLE_EARLY_SANITY_CHECKS WOLFSSL_DRBG_SHA256 -WOLFSSL_DTLS13_ECHO_LEGACY_SESSION_ID -WOLFSSL_DTLS13_NO_HRR_ON_RESUME WOLFSSL_DTLS_DISALLOW_FUTURE -WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT WOLFSSL_DUMP_MEMIO_STREAM WOLFSSL_DUP_CERTPOL WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY -WOLFSSL_ECC_BLIND_K WOLFSSL_ECC_GEN_REJECT_SAMPLING WOLFSSL_ECC_NO_SMALL_STACK WOLFSSL_ECC_SIGALG_PARAMS_NULL_ALLOWED @@ -1007,7 +993,6 @@ WOLFSSL_ESPWROOM32 WOLFSSL_EVP_PRINT WOLFSSL_EXPORT_INT WOLFSSL_EXPORT_SPC_SZ -WOLFSSL_EXTRA WOLFSSL_FALCON_NO_NTT_DSP WOLFSSL_FALCON_SIGN_STATS WOLFSSL_FORCE_OCSP_NONCE_CHECK @@ -1057,17 +1042,12 @@ WOLFSSL_MANUALLY_SELECT_DEVICE_CONFIG WOLFSSL_MCDC_ALLOC_SWEEP WOLFSSL_MDK5 WOLFSSL_MICROCHIP_AESGCM -WOLFSSL_MLDSA_ALLOW_WEAK_PREHASH -WOLFSSL_MLDSA_CHECK_INVNTT_BOUND -WOLFSSL_MLDSA_SIGN_SMALLEST_MEM -WOLFSSL_MLDSA_TEST_REJ_NTT_FAIL WOLFSSL_MLDSA_VERIFY_ALLOW_MALLOC WOLFSSL_MLDSA_VERIFY_PRECOMP_A WOLFSSL_MLKEM_ASM_TEST WOLFSSL_MLKEM_INVNTT_UNROLL WOLFSSL_MLKEM_NO_MALLOC WOLFSSL_MLKEM_NTT_UNROLL -WOLFSSL_ML_KEM_USE_OLD_IDS WOLFSSL_MONT_RED_CT WOLFSSL_MP_COND_COPY WOLFSSL_MP_INVMOD_CONSTANT_TIME @@ -1075,18 +1055,15 @@ WOLFSSL_MULTICIRCULATE_ALTNAMELIST WOLFSSL_MX2_CONF_INCLUDE WOLFSSL_NETX_DUO WOLFSSL_NEW_PRIME_CHECK -WOLFSSL_NONBLOCK_OCSP WOLFSSL_NOSHA3_384 WOLFSSL_NOT_WINDOWS_API WOLFSSL_NO_AES_KEY_SET_CHECK WOLFSSL_NO_BIO_ADDR_IN -WOLFSSL_NO_CA_NAMES WOLFSSL_NO_CHACHA20_POLY1305_FUSED WOLFSSL_NO_CHACHA20_POLY1305_FUSED_IFMA WOLFSSL_NO_CHACHA20_POLY1305_SHORT WOLFSSL_NO_CHACHA20_POLY1305_SMALL_ASM WOLFSSL_NO_CLIENT_CERT_ERROR -WOLFSSL_NO_COPY_CERT WOLFSSL_NO_COPY_KEY WOLFSSL_NO_CRL_DATE_CHECK WOLFSSL_NO_CRL_NEXT_DATE @@ -1096,10 +1073,7 @@ WOLFSSL_NO_DECODE_EXTRA WOLFSSL_NO_DEL_HANDLE WOLFSSL_NO_DER_TO_PEM WOLFSSL_NO_DH186 -WOLFSSL_NO_DILITHIUM_LEGACY_GATES WOLFSSL_NO_DILITHIUM_LEGACY_NAMES -WOLFSSL_NO_DTLS_SIZE_CHECK -WOLFSSL_NO_ECC_SW WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK WOLFSSL_NO_ETM_ALERT WOLFSSL_NO_FCHMOD @@ -1117,7 +1091,6 @@ WOLFSSL_NO_LMS_SHAKE256_256 WOLFSSL_NO_OCSP_DATE_CHECK WOLFSSL_NO_OCSP_OPTIONAL_CERTS WOLFSSL_NO_RSA_KEY_CHECK -WOLFSSL_NO_RSA_SW WOLFSSL_NO_SERVER_GROUPS_EXT WOLFSSL_NO_SESSION_STATS WOLFSSL_NO_SHA256_N_WAY @@ -1128,7 +1101,6 @@ WOLFSSL_NO_SIGALG WOLFSSL_NO_SIGNER_DER_CERT WOLFSSL_NO_SOCKADDR_UN WOLFSSL_NO_STRICT_CIPHER_SUITE -WOLFSSL_NO_TICKET_EXPIRE WOLFSSL_NO_TRUSTED_CERTS_VERIFY WOLFSSL_NO_WORD64_OPS WOLFSSL_NO_XOR_OPS @@ -1145,7 +1117,6 @@ WOLFSSL_NXP_ELE_NO_TRNG_CHECK WOLFSSL_NXP_ELE_USE_DEVID WOLFSSL_NXP_HWPUF WOLFSSL_NXP_LPC55S6X -WOLFSSL_OCSP_SCREEN_RESPONDER WOLFSSL_OLDTLS_AEAD_CIPHERSUITES WOLFSSL_OLD_SET_CURVES_LIST WOLFSSL_OLD_TIMINGPADVERIFY @@ -1208,7 +1179,6 @@ WOLFSSL_SEC_QORIQ_NO_PKHA WOLFSSL_SEC_QORIQ_NO_RSA WOLFSSL_SEC_QORIQ_SWAP_REGS WOLFSSL_SERVER_EXAMPLE -WOLFSSL_SESSION_CACHE_REF_WARNED WOLFSSL_SETTINGS_FILE WOLFSSL_SGX_CPUID_AVX512_VAES WOLFSSL_SHA256_ALT_CH_MAJ @@ -1237,10 +1207,6 @@ WOLFSSL_STSAFE_TAKES_SLOT WOLFSSL_TELIT_M2MB WOLFSSL_TEMPLATE_EXAMPLE WOLFSSL_THREADED_CRYPT -WOLFSSL_TI_AM64X_R5 -WOLFSSL_TI_AM64X_RNG_CTR_DRBG -WOLFSSL_TI_AM64X_NO_AES -WOLFSSL_TI_AM64X_NO_SHA WOLFSSL_TICKET_DECRYPT_NO_CREATE WOLFSSL_TICKET_ENC_AES128_GCM WOLFSSL_TICKET_ENC_AES256_CBC @@ -1250,11 +1216,13 @@ WOLFSSL_TICKET_ENC_CHACHA20_POLY1305 WOLFSSL_TICKET_ENC_HMAC_SHA384 WOLFSSL_TICKET_ENC_HMAC_SHA512 WOLFSSL_TINY_TLS13_NO_DEFAULT_CURVE +WOLFSSL_TI_AM64X_NO_AES +WOLFSSL_TI_AM64X_NO_SHA +WOLFSSL_TI_AM64X_R5 +WOLFSSL_TI_AM64X_RNG_CTR_DRBG WOLFSSL_TI_CURRTIME WOLFSSL_TLS13_DRAFT WOLFSSL_TLS13_IGNORE_AEAD_LIMITS -WOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC -WOLFSSL_TLS13_NULL_CIPHER_IN_DEFAULT WOLFSSL_TLS13_TICKET_BEFORE_FINISHED WOLFSSL_TLS13_TICKET_CHECK_PSK_MODES WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY @@ -1275,7 +1243,6 @@ WOLFSSL_VALIDATE_MLDSA_KEYGEN WOLFSSL_VALIDATE_MLKEM_KEYGEN WOLFSSL_VALIDATE_SLHDSA_KEYGEN WOLFSSL_VAULTIC_DEBUG -WOLFSSL_VERBOSE_LOGGING WOLFSSL_VERSAL_GEN2_ASU_CCM_ALIGN_DECLINE WOLFSSL_VERSAL_GEN2_ASU_CTR_WRAP_HW_FIXED WOLFSSL_VERSAL_GEN2_ASU_DEBUG @@ -1300,7 +1267,6 @@ WOLFSSL_X509_KEY_GEN WOLFSSL_X509_PEM WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE WOLFSSL_X509_STORE_CERTS -WOLFSSL_X509_TINY WOLFSSL_X509_TRUSTED_CERTIFICATE_CALLBACK WOLFSSL_X509_VERIFY_ONLY WOLFSSL_XFREE_NO_NULLNESS_CHECK @@ -1312,10 +1278,7 @@ WOLFSSL_ZEPHYR_MAIN_ARGS WOLFSSL_nRF5x_SDK_15_2 WOLF_ALLOW_BUILTIN WOLF_CONF_ASN_TIME -WOLF_CRYPTO_CB_ASYNC_POLL -WOLF_CRYPTO_CB_KEYGEN_SW_FALLBACK WOLF_CRYPTO_CB_ONLY_SHA -WOLF_CRYPTO_CB_SHAKE_XOF WOLF_CRYPTO_DEV WOLF_NO_TRAILING_ENUM_COMMAS WindowsCE From 66336a9cbdddec3c2b84ace825921a372ae445cf Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 3 Nov 2026 14:14:32 -0600 Subject: [PATCH 22/28] wolfcrypt/test/test.c: add several missing PRIVATE_KEY_{UNLOCK,LOCK}() wraps: * in dh_agree_ct_test(), add point-of-use PRIVATE_KEY_UNLOCK()/PRIVATE_KEY_LOCK() around the wc_DhAgree_ct() calls, and in dh_key_import_export_test(), around the wc_DhExportKeyPair() call. No current FIPS flavor gates these, but the wraps are harmless and future-proof the tests against a flavor that restores DH to inside-boundary status, or activates these subtests on FIPS Date: Tue, 3 Nov 2026 14:19:46 -0600 Subject: [PATCH 23/28] wolfcrypt/src/rng_bank.c: error handling fixes: * in wc_rng_bank_init_nonce(), use wc_RNG_lock_put_unconditional() to unlock the root_rng if it was locked, and don't unlock it otherwise; * in wc_rng_bank_root_rng_init(), if RNG init fails and the caller didn't request _PRESERVE_LOCK, wipe the root_rng, restoring it to its condition after the whole-context wipe at the start of wc_rng_bank_init_nonce() -- with this fix, wc_rng_bank_root_rng_init() always leaves bank->root_rng in a known and sensible state that the caller can rely on, regardless of retval. --- wolfcrypt/src/rng_bank.c | 48 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/wolfcrypt/src/rng_bank.c b/wolfcrypt/src/rng_bank.c index 790640955a4..fdda3d0f1aa 100644 --- a/wolfcrypt/src/rng_bank.c +++ b/wolfcrypt/src/rng_bank.c @@ -200,7 +200,7 @@ WOLFSSL_API int wc_rng_bank_init_nonce( * WC_RNG_BANK_FLAG_RBGC) -- it can be used for other purposes, such as * pool replenishment, as in the linuxkm entropy daemon. */ ret = wc_rng_bank_root_rng_init(ctx, nonce, nonceSz, perso, persoSz, - #if defined(WC_RNG_HAVE_LOCK) && defined(WC_RNG_INIT_FLAG_LOCK_INITIALLY) + #ifdef WC_RNG_HAVE_LOCK WC_RNG_INIT_FLAG_LOCK_INITIALLY #else WC_RNG_INIT_FLAG_NONE @@ -306,22 +306,11 @@ WOLFSSL_API int wc_rng_bank_init_nonce( #ifdef WC_RNG_HAVE_LOCK if (root_rng_locked) - wc_RNG_lock_put(&ctx->root_rng, 0); + wc_RNG_lock_put_unconditional(&ctx->root_rng); #endif - if (ret != 0) { -#if defined(WC_RNG_HAVE_LOCK) && defined(WC_RNG_BANK_HAVE_ROOT_RNG) - /* A root init that failed under WC_RNG_INIT_FLAG_LOCK_INITIALLY (e.g. - * instantiation refused in FIPS error state) dies holding the root's - * lock with no owner to release it -- root_rng_locked is only set on - * success. Release it unconditionally, or the fini below refuses - * with BUSY_E at its root-lock check and ctx->rngs is leaked, with - * every subsequent fini refused the same way. */ - if (! root_rng_locked) - wc_RNG_lock_put_unconditional(&ctx->root_rng); -#endif + if (ret != 0) (void)wc_rng_bank_fini(ctx); - } return ret; } @@ -1599,6 +1588,8 @@ WOLFSSL_API int wc_rng_bank_root_rng_init(struct wc_rng_bank *bank, const byte *perso, word32 persoSz, word32 flags) { + int ret; + if (bank == NULL) return BAD_FUNC_ARG; @@ -1616,22 +1607,35 @@ WOLFSSL_API int wc_rng_bank_root_rng_init(struct wc_rng_bank *bank, #endif #if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0) - return wc_InitRngNonce_ex2(&bank->root_rng, - nonce, nonceSz, - perso, persoSz, - bank->heap, bank->devId, flags + ret = wc_InitRngNonce_ex2(&bank->root_rng, + nonce, nonceSz, + perso, persoSz, + bank->heap, bank->devId, flags #if defined(WC_RNG_HAVE_LOCK) && defined(WC_RNG_INIT_FLAG_LOCK_REQUIRED) - | WC_RNG_INIT_FLAG_LOCK_REQUIRED + | WC_RNG_INIT_FLAG_LOCK_REQUIRED #endif - ); + ); #else (void)perso; (void)persoSz; if (flags != 0) return NOT_COMPILED_IN; - return wc_InitRngNonce_ex(&bank->root_rng, nonce, nonceSz, - bank->heap, bank->devId); + ret = wc_InitRngNonce_ex(&bank->root_rng, nonce, nonceSz, + bank->heap, bank->devId); #endif + + /* If lock state preservation wasn't requested, make sure the rng is zeroed, + * otherwise access to it during bank cleanup is UB. */ + if (ret != 0) { +#ifdef WC_RNG_INIT_FLAG_PRESERVE_LOCK + if (! (flags & WC_RNG_INIT_FLAG_PRESERVE_LOCK)) +#endif + { + XMEMSET(&bank->root_rng, 0, sizeof(bank->root_rng)); + } + } + + return ret; } WOLFSSL_API WC_RNG *wc_rng_bank_root_rng_get(struct wc_rng_bank *bank) From 88e9b9bbb2b103333c504572199d500177caf04b Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 3 Nov 2026 17:03:30 -0600 Subject: [PATCH 24/28] wolfssl/wolfcrypt/memory.h: add prototype for WOLFSSL_NO_FORCE_ZERO ForceZero(), matching the one in wc_compat.h, to assure warning-free availability regardless of include order. --- wolfssl/wolfcrypt/memory.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index d7a35203478..363eb8721ec 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -332,8 +332,12 @@ WOLFSSL_LOCAL void wc_MemZero_Check(void* addr, size_t len); #endif #ifdef WOLFSSL_NO_FORCE_ZERO + /* NOLINTNEXTLINE(readability-redundant-declaration) */ + void ForceZero(void* mem, size_t len); + #undef wc_ForceZero #define wc_ForceZero ForceZero #else + /* NOLINTNEXTLINE(readability-redundant-declaration) */ WOLFSSL_API void wc_ForceZero(void *mem, size_t len); #endif From ddd69f2fcb61f37d2e75d868add1dd6d75eb5a10 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 3 Nov 2026 17:05:14 -0600 Subject: [PATCH 25/28] tests/api/test_ossl_rand.c: in test_wolfSSL_RAND_bytes() in child process, call wolfSSL_RAND_Cleanup() before _exit() to avoid valgrind-detected leaks of globalRNG allocations. --- tests/api/test_ossl_rand.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/api/test_ossl_rand.c b/tests/api/test_ossl_rand.c index fcca4a146ff..2e5e33aedbb 100644 --- a/tests/api/test_ossl_rand.c +++ b/tests/api/test_ossl_rand.c @@ -231,6 +231,10 @@ int test_wolfSSL_RAND_bytes(void) ok = (RAND_bytes(randbuf, sizeof(randbuf)) == 1); n_written = write(pipefds[1], randbuf, sizeof(randbuf)); close(pipefds[1]); + /* Free the child's copy of the global RNG, inherited from the + * pre-fork RAND_seed() -- _exit() cleans up nothing, and valgrind + * tracks the child. */ + wolfSSL_RAND_Cleanup(); /* Must terminate via _exit() to avoid provoking LSAN via the atexit * handlers. */ _exit((ok && n_written == sizeof(randbuf)) ? 0 : 1); From 588d8815e18629eac7aead69c0f3350bf950060d Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 3 Nov 2026 17:24:50 -0600 Subject: [PATCH 26/28] wolfcrypt/test/test.c: in FIPS v6, call PRIVATE_KEY_UNLOCK() for wc_ecc_export_x963_ex(); fix unused-store warning in ed448_kat_test(); add missing PRIVATE_KEY_UNLOCK()s in mlkem_asn1_test(). --- wolfcrypt/test/test.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index ea49617d64b..e9d5c2947b3 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -53928,7 +53928,15 @@ static wc_test_ret_t ecc_test_make_pub(WC_RNG* rng) #ifdef HAVE_ECC_KEY_EXPORT /* exporting the public part should now work */ x = ECC_BUFSIZE; +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + /* in FIPS v6, but only v6, wc_ecc_export_x963_ex_fips() checks + * privateKeyReadEnable. */ + PRIVATE_KEY_UNLOCK(); +#endif ret = wc_ecc_export_x963_ex(key, exportBuf, &x, 0); +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_LOCK(); +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); #endif /* HAVE_ECC_KEY_EXPORT */ @@ -54474,7 +54482,13 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif #ifdef HAVE_ECC_KEY_EXPORT x = ECC_KEY_EXPORT_BUF_SIZE; +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_UNLOCK(); +#endif ret = wc_ecc_export_x963_ex(userA, exportBuf, &x, 0); +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_LOCK(); +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -54514,7 +54528,13 @@ static wc_test_ret_t ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerif #ifdef HAVE_COMP_KEY /* try compressed export / import too */ x = ECC_KEY_EXPORT_BUF_SIZE; +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_UNLOCK(); +#endif ret = wc_ecc_export_x963_ex(userA, exportBuf, &x, 1); +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_LOCK(); +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); wc_ecc_free(pubKey); @@ -56256,7 +56276,13 @@ static int ecc_sm2_test_curve(WC_RNG* rng, int testVerifyCount) #ifdef HAVE_ECC_KEY_EXPORT x = ECC_KEY_EXPORT_BUF_SIZE; +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_UNLOCK(); +#endif ret = wc_ecc_export_x963_ex(userA, exportBuf, &x, 0); +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_LOCK(); +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); @@ -56278,7 +56304,13 @@ static int ecc_sm2_test_curve(WC_RNG* rng, int testVerifyCount) #ifdef HAVE_COMP_KEY /* try compressed export / import too */ x = ECC_KEY_EXPORT_BUF_SIZE; +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_UNLOCK(); +#endif ret = wc_ecc_export_x963_ex(userA, exportBuf, &x, 1); +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_LOCK(); +#endif if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), done); wc_ecc_free(pubKey); @@ -64628,8 +64660,6 @@ static wc_test_ret_t ed448_kat_test(ed448_key* key, ed448_key* key2) } #endif - ret = 0; - do { if (wc_ed448_export_public(key, exportPKey, &exportPSz) != 0) { ret = WC_TEST_RET_ENC_I(i); @@ -69750,7 +69780,9 @@ static wc_test_ret_t mlkem_asn1_test(void) ret = WC_TEST_RET_ENC_EC(pubLen); } if (ret == 0) { + PRIVATE_KEY_UNLOCK(); privLen = wc_MlKemKey_PrivateKeyToDer(key, NULL, 0); + PRIVATE_KEY_LOCK(); if (privLen <= 0) ret = WC_TEST_RET_ENC_EC(privLen); } @@ -69761,8 +69793,10 @@ static wc_test_ret_t mlkem_asn1_test(void) ret = WC_TEST_RET_ENC_ERRNO; } if (ret == 0) { + PRIVATE_KEY_UNLOCK(); privLen = wc_MlKemKey_PrivateKeyToDer(key, privDer, (word32)privLen); + PRIVATE_KEY_LOCK(); if (privLen <= 0) ret = WC_TEST_RET_ENC_EC(privLen); } From 3ad471c6dc45bacef4ac20f022b83bfa1dcd0acc Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 3 Nov 2026 18:17:17 -0600 Subject: [PATCH 27/28] wolfcrypt/src/hpke.c: in wc_HpkeSerializePublicKey(), on FIPS v6, call PRIVATE_KEY_UNLOCK() for wc_ecc_export_x963_ex(). --- wolfcrypt/src/hpke.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wolfcrypt/src/hpke.c b/wolfcrypt/src/hpke.c index 8bbc06c9819..a4b0caa3b2d 100644 --- a/wolfcrypt/src/hpke.c +++ b/wolfcrypt/src/hpke.c @@ -370,7 +370,16 @@ int wc_HpkeSerializePublicKey(Hpke* hpke, void* key, byte* out, word16* outSz) case DHKEM_P384_HKDF_SHA384: case DHKEM_P521_HKDF_SHA512: /* export x963 uncompressed */ +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + /* in FIPS v6, but only v6, wc_ecc_export_x963_ex_fips() checks + * privateKeyReadEnable. */ + PRIVATE_KEY_UNLOCK(); +#endif ret = wc_ecc_export_x963_ex((ecc_key*)key, out, &tmpOutSz, 0); +#if FIPS_VERSION3_GE(6,0,0) && FIPS_VERSION3_LT(7,0,0) + PRIVATE_KEY_LOCK(); +#endif + break; #endif #if defined(HAVE_CURVE25519) && !defined(NO_SHA256) From 1b6fa872e202c5aba5b8a520a65614a0ab0eb6c8 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 3 Nov 2026 18:27:20 -0600 Subject: [PATCH 28/28] wolfssl/wolfcrypt/wc_compat.h: in wc_AesGcmEncrypt_compat_shim(), don't wipe buffers when WC_PENDING_E, and don't wipe output buffer when it's equal to the input buffer. --- wolfssl/wolfcrypt/wc_compat.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wolfssl/wolfcrypt/wc_compat.h b/wolfssl/wolfcrypt/wc_compat.h index 4a0ec45b796..d8bf4bd379e 100644 --- a/wolfssl/wolfcrypt/wc_compat.h +++ b/wolfssl/wolfcrypt/wc_compat.h @@ -105,12 +105,12 @@ ret = wc_AesGcmEncryptUpdate(aes, out, in, sz, authIn, authInSz); if (ret == 0) ret = wc_AesGcmEncryptFinal(aes, authTag, authTagSz); - if (ret != 0) { + if ((ret != 0) && (ret != WC_NO_ERR_TRACE(WC_PENDING_E))) { /* Match the native one-shot's failure contract: no ciphertext and no * tag escape a failed operation, whichever stage failed. On the * Init/Update failure paths authTag was never written, so there this * is contract uniformity rather than leak repair. */ - if (out != NULL) + if ((out != NULL) && (out != in)) wc_ForceZero(out, sz); if (authTag != NULL) wc_ForceZero(authTag, @@ -143,9 +143,9 @@ authTagSz, authIn, authInSz); if (ret == 0) ret = wc_AesGcmSetExtIV(aes, iv, ivSz); - if (ret != 0) { + if ((ret != 0) && (ret != WC_NO_ERR_TRACE(WC_PENDING_E))) { /* Match above ISO-19790 wipe--this arm airdropped into old-FIPS. */ - if (out != NULL) + if ((out != NULL) && (out != in)) wc_ForceZero(out, sz); if (authTag != NULL) wc_ForceZero(authTag,