Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
b60019f
Zeroize EdDSA scalars and KDF blocks; reject non-canonical Ed448 keys
jackctj117 Sep 9, 2026
b0ab8eb
Zeroize temporary SSPs in the FIPS v7 boundary
jackctj117 Sep 9, 2026
40b4981
Zeroize remaining temporaries and failure paths
jackctj117 Sep 9, 2026
daa8e9b
SHA Free: release msg and W before the callback-path wipe
jackctj117 Sep 10, 2026
0be88ba
Address review: keep destructors off caller-owned contexts, fix entro…
jackctj117 Sep 10, 2026
ff7a795
Use ForceZero where XMEMSET wiped sensitive data
jackctj117 Sep 10, 2026
b1e61de
NoiseSrc: ForceZero the health-test state on free
jackctj117 Sep 11, 2026
126044a
SHA-3 Free: wipe state only; RSA even-mod test expects the wiped buffer
jackctj117 Sep 15, 2026
46bded1
RSA even-mod test: only expect the wiped buffer from FIPS v7 or non-F…
jackctj117 Sep 22, 2026
ab22392
SHA-3: keep the C Keccak round scratch in the context
jackctj117 Oct 1, 2026
09fa6f7
ML-KEM: add basemul products into r without staging them
jackctj117 Oct 1, 2026
10de57e
ForceZero: use volatile stores where no data barrier backs the wipe
jackctj117 Oct 6, 2026
09bf95c
SHA-1, SHA-256: keep the C transform message schedule in the context
jackctj117 Oct 6, 2026
85b9a44
openssl compat: size the SHA and SHA-224 contexts from the native str…
jackctj117 Oct 7, 2026
a8a55f7
mcapi: grow the SHA and SHA-256 context holders
jackctj117 Oct 7, 2026
c56f8a7
SHA-1: wipe the GetHash copy; SHA-256: wipe the many-registers stack W
jackctj117 Oct 7, 2026
fe9456d
SHA-3: ForceZero in InitSha3, wipe KMAC key staging and keyed sponge
jackctj117 Oct 7, 2026
11220d4
EdDSA and X25519/X448: wipe ladder, scalar and key temporaries
jackctj117 Oct 7, 2026
3dfc04c
rsa: wipe the PSS salt, the OAEP unpad temp and the keygen blind
jackctj117 Oct 7, 2026
afc37ca
dh: wipe the previous private key in wc_DhKeyCopy and the nb context
jackctj117 Oct 7, 2026
10e7278
ecc: wipe the unblinded scalar copy, ladder state and nb context
jackctj117 Oct 7, 2026
d1b776b
HMAC, HKDF: wipe key on SetKey failure, inner digest, partial OKM
jackctj117 Oct 7, 2026
6c06a1e
KDF, PBKDF: wipe partial derived output on failure
jackctj117 Oct 7, 2026
28c39b9
SE050 hash: wipe the buffered message and the SHA-512 context
jackctj117 Oct 7, 2026
cd41592
ML-KEM: wipe hash state on failure and the old key before re-keying
jackctj117 Oct 7, 2026
a8c90d3
ML-DSA: wipe rho', rejected candidates and keys left by failures
jackctj117 Oct 7, 2026
397d67b
AES: wipe GCM, CFB and XTS temporaries, finished streams and failed keys
jackctj117 Oct 7, 2026
07ff724
random: uninstantiate the DRBG after any failed instantiate
jackctj117 Oct 7, 2026
5e7dac3
random, wolfentropy: wipe seed, stir and output temporaries
jackctj117 Oct 7, 2026
b17a4bf
SLH-DSA: wipe secret hash state and scratch once per operation
jackctj117 Oct 7, 2026
447da79
LMS: wipe the private key on failed keygen, reload and sign
jackctj117 Oct 7, 2026
da225ca
ML-KEM: wipe the implicit-rejection flag in decapsulation
jackctj117 Oct 7, 2026
6b5101c
HMAC: clear the key when async hardware key setup fails
jackctj117 Oct 8, 2026
3d7a339
AES-GCM, CMAC, ECIES, X9.63: wipe expected tags, H copies and KDF blocks
jackctj117 Oct 8, 2026
7721535
EdDSA, X25519: wipe the projective points of the scalar multiplication
jackctj117 Oct 8, 2026
0982e40
RSA, ML-DSA, entropy: clear padding flags, rejected hint count, raw s…
jackctj117 Oct 8, 2026
5dad1d1
Drop changes outside the FIPS boundary
jackctj117 Oct 8, 2026
5d73720
AES: drop wc_GmacFree
jackctj117 Oct 8, 2026
8850f57
ECC, X25519, DH, RSA: leave the caller's non-blocking context alone a…
jackctj117 Oct 8, 2026
c7f70dd
ML-KEM: read the key type only after encapsulate's checks pass
jackctj117 Oct 8, 2026
9306081
SHA-256: keep one context layout under WC_SHA2_NO_SMALL_STACK
jackctj117 Oct 8, 2026
afccfc7
wolfentropy: drop the out-of-boundary entropy source changes
jackctj117 Oct 8, 2026
6acca4f
ML-KEM, ML-DSA: fix wipe helper guards and SHA-3 scratch layout
jackctj117 Oct 8, 2026
ca21dd5
SHA-256: keep W on the stack in kernel builds
jackctj117 Oct 9, 2026
834aa36
RSA: leave the caller's output alone when public encrypt fails
jackctj117 Oct 9, 2026
1af6717
RSA: wipe the OAEP block in out when public encrypt fails
jackctj117 Oct 9, 2026
827807d
Fix remaining FIPS v7 C zeroization gaps
jackctj117 Oct 12, 2026
b2fd466
Drop zeroization outside the FIPS v7 services
jackctj117 Oct 14, 2026
387faeb
Fix the zeroization gaps from the round-2 review
jackctj117 Oct 14, 2026
4b427b2
tests: cover the round-2 zeroization fixes
jackctj117 Oct 14, 2026
2c0e1cf
tests: guard the new zeroization tests for builds that swap the sources
jackctj117 Oct 14, 2026
c228159
ecc: free the old key contents before an import re-inits them
jackctj117 Oct 14, 2026
b4e0e1b
ecc: do not read the key before an import re-inits it
jackctj117 Oct 15, 2026
920170c
Wipe HMAC and SHAKE object state at Free, not per Final or absorb
jackctj117 Oct 19, 2026
2950254
random: drop the Hash_gen digest wipes duplicated by the rebase
jackctj117 Oct 20, 2026
1708a7f
aes: restore the 4-bit GHASH multiply from master
jackctj117 Oct 20, 2026
aadd47a
Add WOLFSSL_CHECK_MEM_ZERO coverage for the new SSP wipes
jackctj117 Oct 20, 2026
f09453e
sha3: drop the KMAC Final wipe so a reused object stays keyed
jackctj117 Oct 21, 2026
d464f6a
sha3: restore plain zeroing in InitSha3
jackctj117 Oct 21, 2026
7f261dd
rng_bank: restore master's scratch clear in the pre-v7 reseed path
jackctj117 Oct 21, 2026
517eb2b
SHA-3: drop the Keccak round scratch from the context
jackctj117 Oct 21, 2026
5b9dee9
SHA-1 and SHA-256: keep the message schedule on the stack and wipe it…
jackctj117 Oct 26, 2026
ac30b2b
ForceZero: escape the buffer through an out-of-line sink instead of v…
jackctj117 Oct 26, 2026
eae3ac9
SLH-DSA: cast the FORS signature wipe length to size_t
jackctj117 Oct 26, 2026
be71ea1
SLH-DSA: compile the secret hash wipe helpers without SHAKE
jackctj117 Oct 26, 2026
6199ab1
wolfcrypt/src/random.c: harden NextStirPurge() sentinel handling, com…
douzzer Oct 27, 2026
3e235ae
wolfssl/wolfcrypt/wc_port.h: add WC_RESTRICT.
douzzer Oct 27, 2026
166c7c8
ML-DSA: don't destroy an exact-alias source in raw private import
douzzer Oct 27, 2026
bc84b67
SHA-2: caller-owned transform scratch buffer, wiped once per public call
douzzer Oct 28, 2026
7889674
tests/api/test_frodokem.c: in frodokem_kats[] definition, use WC_STAT…
douzzer Oct 28, 2026
cf64372
wolfcrypt/src/aes.c, wolfcrypt/src/ed25519.c, wolfcrypt/src/sha.c: ze…
douzzer Oct 28, 2026
1b01509
wolfcrypt/src/sha256.c: use WC_SHA256_TSCRATCH_SIZE. not sizeof(Sha25…
douzzer Oct 28, 2026
2911a85
wolfcrypt/src/aes.c, wolfcrypt/src/wc_mlkem_poly.c, wolfcrypt/src/wc_…
douzzer Oct 28, 2026
4ec705f
mcapi/crypto.h: revert changes (none needed versus the branch base).
douzzer Oct 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions linuxkm/lkcapi_sha_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -932,10 +932,20 @@ struct wc_swallow_the_semicolon
* substantively implemented.
*/
#ifndef WC_SHA256_W_SIZE
#define WC_SHA256_W_SIZE (sizeof(word32) * WC_SHA256_BLOCK_SIZE)
#ifdef WC_SHA256_TSCRATCH_SIZE
/* The transform reads W as its full caller-owned scratch. */
#define WC_SHA256_W_SIZE WC_SHA256_TSCRATCH_SIZE
#else /* old FIPS */
#define WC_SHA256_W_SIZE (sizeof(word32) * WC_SHA256_BLOCK_SIZE)
#endif
#endif
#ifndef WC_SHA512_W_SIZE
#define WC_SHA512_W_SIZE ((sizeof(word64) * 16) + WC_SHA512_BLOCK_SIZE)
#ifdef WC_SHA512_TSCRATCH_SIZE
#define WC_SHA512_W_SIZE \
(WC_SHA512_TSCRATCH_SIZE + WC_SHA512_BLOCK_SIZE)
#else /* old FIPS */
#define WC_SHA512_W_SIZE ((sizeof(word64) * 16) + WC_SHA512_BLOCK_SIZE)
#endif
#endif

#define WC_LINUXKM_SHA2_IMPLEMENT(name, s_name, digest_size, block_size, \
Expand Down
56 changes: 56 additions & 0 deletions tests/api/test_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -14667,3 +14667,59 @@ int test_wc_AesEcb_RetCodeChecked(void)

#endif /* WOLF_CRYPTO_CB && !NO_AES && HAVE_AES_ECB && WOLFSSL_AES_128 &&
* !WOLF_CRYPTO_CB_ONLY_AES && (WOLFSSL_AES_COUNTER || HAVE_AESGCM) */

/* Exercise the portable block primitive's real KEYUSAGE_E path after GCM
* setup. No callback or test-only failure hook is needed. */
int test_wc_AesGcm_PrimitiveFailureCleanup(void)
{
EXPECT_DECLS;
#if !defined(NO_AES) && defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128) && \
defined(WOLFSSL_NO_ASM) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \
!defined(HAVE_SELFTEST)
Aes aes;
const byte key[16] = {0};
const byte iv[12] = {0};
const byte aad[16] = {0};
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);
ExpectIntEQ(wc_AesGcmSetKey(&aes, key, sizeof(key)), 0);
XMEMSET(tag, 0xa5, sizeof(tag));
aes.rounds = 0;
/* Empty plaintext reaches GHASH before the first AES block operation. */
ret = wc_AesGcmEncrypt(&aes, NULL, NULL, 0, iv, sizeof(iv), tag,
sizeof(tag), aad, sizeof(aad));
if (ret != WC_NO_ERR_TRACE(KEYUSAGE_E)) {
wc_AesFree(&aes);
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);
#endif
wc_AesFree(&aes);
#else
return TEST_SKIPPED;
#endif
return EXPECT_RESULT();
}
2 changes: 2 additions & 0 deletions tests/api/test_aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ int test_wc_AesGcmStream_MidStreamState(void);
int test_wc_AesGcmStream_ReinitAfterFinal(void);
int test_wc_AesGcmStream_BadAuthTag(void);
int test_wc_AesGcmDecrypt_WipeOnAuthFail(void);
int test_wc_AesGcm_PrimitiveFailureCleanup(void);
int test_wc_AesKeyWrapVectors(void);
int test_wc_AesKeyWrapDecisionCoverage(void);
int test_wc_AesGcmDecisionCoverage(void);
Expand Down Expand Up @@ -241,6 +242,7 @@ int test_wc_CryptoCb_AesDirect(void);
TEST_DECL_GROUP("aes", test_wc_AesGcmStream_ReinitAfterFinal), \
TEST_DECL_GROUP("aes", test_wc_AesGcmStream_BadAuthTag), \
TEST_DECL_GROUP("aes", test_wc_AesGcmDecrypt_WipeOnAuthFail), \
TEST_DECL_GROUP("aes", test_wc_AesGcm_PrimitiveFailureCleanup), \
TEST_DECL_GROUP("aes", test_wc_AesKeyWrapVectors), \
TEST_DECL_GROUP("aes", test_wc_AesKeyWrapDecisionCoverage), \
TEST_DECL_GROUP("aes", test_wc_AesGcmDecisionCoverage), \
Expand Down
19 changes: 19 additions & 0 deletions tests/api/test_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,25 @@ int test_wc_ecc_import_private_key(void)
x963KeySz, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_ecc_import_private_key(NULL, privKeySz, x963Key, x963KeySz,
&keyImp), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#if (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) && \
!defined(HAVE_SELFTEST) && !defined(WOLFSSL_CRYPTOCELL) && \
!defined(WOLFSSL_SE050) && !defined(WOLFSSL_SILABS_SE_ACCEL) && \
!defined(WOLFSSL_KCAPI_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) && \
!(defined(WOLF_CRYPTO_CB_SETKEY) && defined(WOLF_CRYPTO_CB_FIND))
/* Rejecting a private scalar must also revoke private-key capability.
* The device set-key path imports into a temporary key first, so a
* rejected scalar never touches this key and its type stays as it was.
* Use a fresh key: importing over a live one is not a supported path. */
wc_ecc_free(&keyImp);
ExpectIntEQ(wc_ecc_init(&keyImp), 0);
XMEMSET(privKey, 0, privKeySz);
ExpectIntEQ(wc_ecc_import_private_key(privKey, privKeySz, x963Key,
x963KeySz, &keyImp), WC_NO_ERR_TRACE(ECC_PRIV_KEY_E));
ExpectIntEQ(keyImp.type, ECC_PUBLICKEY);
ExpectIntEQ(wc_ecc_import_private_key(privKey, privKeySz, NULL, 0,
&keyImp), WC_NO_ERR_TRACE(ECC_PRIV_KEY_E));
ExpectIntEQ(keyImp.type, 0);
#endif
PRIVATE_KEY_LOCK();

DoExpectIntEQ(wc_FreeRng(&rng), 0);
Expand Down
2 changes: 1 addition & 1 deletion tests/api/test_frodokem.c
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ static const FrodoKemKat frodokem_kats[] = {
FKAT_640_AES FKAT_976_AES FKAT_1344_AES
FKAT_E640_SHAKE FKAT_E976_SHAKE FKAT_E1344_SHAKE
FKAT_E640_AES FKAT_E976_AES FKAT_E1344_AES
{ 0 } /* sentinel so the array is never empty */
WC_STATIC_STRUCT_INITIALIZER /* sentinel so the array is never empty */
};

#define FRODOKEM_KAT_CNT \
Expand Down
86 changes: 86 additions & 0 deletions tests/api/test_kdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -929,3 +929,89 @@ int test_wc_KdfFeatureCoverage(void)
#endif /* !HAVE_FIPS && !HAVE_SELFTEST */
return EXPECT_RESULT();
} /* END test_wc_KdfFeatureCoverage */

/* RFC 4253 section 7.2 fixtures computed independently with Python hashlib:
* K = a5 * 32 (positive mpint with a leading zero), H = 39 * 32,
* session_id = 17 * 32, key ID = A. K1 = HASH(mpint(K)||H||A||session_id),
* Kn = HASH(mpint(K)||H||K1||...||K(n-1)). The 133-byte output exercises
* repeated Final/reuse and the partial last block for every supported hash.
*/
int test_wc_SshKdfReuse(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_WOLFSSH) && !defined(NO_HMAC)
static const struct {
byte hashId;
const char* expected;
} vectors[] = {
#if !defined(NO_SHA)
{ WC_SHA,
"\x1c\x9f\x61\x4a\x3b\xa5\x27\x49\x39\xc0\x53\x1d\x22\xe5\xf3\xa2"
"\xe4\x07\xd3\x28\x19\xe0\xc7\xa4\x82\x83\x16\x15\x5c\x0c\x31\xe5"
"\x78\xe4\xe8\x24\x70\x0e\xf8\x66\xe2\x66\x9b\x3a\xac\x26\xa1\x2c"
"\xd4\x5e\xb7\x58\xeb\xbf\xaf\x6f\xb9\x09\xa2\x25\xe8\xf9\x3c\x1f"
"\x23\x3c\x08\xfc\x4e\x78\x5c\x35\x10\x51\x4c\x0a\x6e\x85\xf5\x94"
"\xcc\xaf\x3d\xf8\xb5\x61\x79\xd4\x3c\x9e\x3c\x18\xa0\x19\x55\x54"
"\xce\x85\x86\xbc\x6e\x74\x30\x4a\xf6\x00\x5a\x08\x15\x70\xeb\x35"
"\xb1\x20\xc4\xca\xd7\xc3\x66\xe9\xe0\x83\x38\x61\x34\x39\x36\x2a"
"\xda\xaa\x28\xbb\x22"
},
#endif
#if !defined(NO_SHA256)
{ WC_SHA256,
"\x34\xb2\x16\x40\xeb\x59\x97\x50\x70\x19\x97\x5c\x8c\xc0\x0c\xfb"
"\x1a\xef\x39\xcc\x7a\x25\x8a\x6c\x33\xb0\x7b\xe4\xe9\x0f\x81\xfa"
"\x20\xed\x94\xb1\xe1\x26\x97\x58\x1d\xe8\x94\x04\xb9\x7e\x52\x03"
"\x79\x8a\xf1\x91\x38\x62\x15\x65\xd2\x5e\x9e\xa7\x96\x70\x51\x75"
"\x3d\x8a\x11\x41\x77\xdd\x7a\x33\x32\x12\x78\x69\xcd\xfc\x69\x55"
"\xed\xa9\xdd\x87\xea\xef\xe1\x0b\x28\xb6\x71\x72\xdb\xc8\x9d\x08"
"\x45\xbc\x2d\x85\x9c\x4c\xa0\x33\x80\x99\xcc\x1f\x9f\x23\x82\x68"
"\x32\xbf\xad\x27\x1d\x0c\xfe\x43\xa4\xf9\xbc\xb6\xd6\xee\x6a\x70"
"\xf9\xdf\x8f\xa1\xe3"
},
#endif
#if defined(WOLFSSL_SHA384)
{ WC_SHA384,
"\x82\x6a\xb6\x8b\x6d\x81\x42\xa2\x85\x12\x32\x61\x8c\xaf\xf4\x3b"
"\xad\xad\x88\x2d\x7f\x9d\xea\x63\x75\x40\x66\xe9\x9f\xb3\x42\x1e"
"\x26\x30\x4e\xb2\x99\xda\xe3\x56\x2e\x5a\xde\x44\xc7\x8d\x3d\x59"
"\x45\xf9\xe1\x5c\xe8\x8b\x01\x55\xc9\x87\xb7\x95\x74\x32\x9b\xe8"
"\xcc\x12\x69\x25\xba\x88\x43\x5f\x27\x78\xc3\x35\x18\x6e\x3d\x32"
"\x36\x74\xa0\x44\xd8\x84\xb6\x2a\x1b\xdf\x01\x23\x7f\x62\x38\xb8"
"\xca\x9e\x55\x08\xf6\x3b\x60\xce\x1b\x2b\xe1\x0c\xdb\x15\x90\x54"
"\x16\x3b\x04\xbb\x71\x98\x6d\x20\xc9\x9e\xd6\x3b\xf2\xd1\x8f\xf4"
"\xbb\x0d\xaf\x6a\xf1"
},
#endif
#if defined(WOLFSSL_SHA512)
{ WC_SHA512,
"\xb9\xcb\x49\xf0\x5f\xac\x25\xca\x6d\x9a\xfa\x68\x87\x57\xa2\x17"
"\x2a\x61\xcc\x56\xea\x71\x0f\xef\x07\xac\xb1\x7e\x7e\xaf\x54\x8f"
"\x15\x3b\x12\x9f\xbd\x6f\x79\xc9\x89\x14\xe6\x40\x43\x07\x27\x01"
"\x93\x1d\xda\xc8\x4b\x8b\xeb\xdf\x6a\xa3\xf8\xed\x8a\x8d\x9d\x49"
"\xc4\x5d\x90\xdd\x56\xd3\x64\x83\x5a\x63\x47\x3a\x69\xf9\x11\xaf"
"\x50\x7f\x3b\x18\xbc\x37\xec\xf9\xdd\xad\x98\x80\xab\x58\xb5\xd3"
"\x72\x6e\x2c\xce\xae\x7f\xde\x5e\x4f\xb9\xf5\x57\x5a\x65\x2d\x88"
"\xb0\xc8\xc9\x74\x9e\x75\xec\x51\xb9\x23\x64\x26\xb8\x7c\x05\x74"
"\xa2\xe7\x3d\x30\xf8"
},
#endif
{ 0, NULL }
};
static const word32 lengths[] = { 1, 32, 64, 96, 128, 133 };
byte k[32], h[32], sessionId[32], key[133];
word32 i, j;

XMEMSET(k, 0xa5, sizeof(k));
XMEMSET(h, 0x39, sizeof(h));
XMEMSET(sessionId, 0x17, sizeof(sessionId));
for (i = 0; vectors[i].expected != NULL; i++) {
for (j = 0; j < sizeof(lengths) / sizeof(lengths[0]); j++) {
ExpectIntEQ(wc_SSH_KDF(vectors[i].hashId, 'A', key, lengths[j],
k, sizeof(k), h, sizeof(h), sessionId, sizeof(sessionId)), 0);
ExpectBufEQ(key, vectors[i].expected, lengths[j]);
}
}
#endif
return EXPECT_RESULT();
}
4 changes: 3 additions & 1 deletion tests/api/test_kdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@

int test_wc_KdfDecisionCoverage(void);
int test_wc_KdfFeatureCoverage(void);
int test_wc_SshKdfReuse(void);

#define TEST_KDF_DECLS \
TEST_DECL_GROUP("kdf", test_wc_KdfDecisionCoverage), \
TEST_DECL_GROUP("kdf", test_wc_KdfFeatureCoverage)
TEST_DECL_GROUP("kdf", test_wc_KdfFeatureCoverage), \
TEST_DECL_GROUP("kdf", test_wc_SshKdfReuse)

#endif /* WOLFCRYPT_TEST_KDF_H */
78 changes: 78 additions & 0 deletions tests/api/test_mlkem.c
Original file line number Diff line number Diff line change
Expand Up @@ -5599,3 +5599,81 @@ int test_wc_mlkem_make_key_id_dev(void)
#endif
return EXPECT_RESULT();
}

/* FIPS 203 3.3: retain the key and designated output, but no hash or PRF
* intermediates, when a complete ML-KEM operation returns. */
int test_wc_mlkem_operation_cleanup(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_MLKEM) && defined(WC_MLKEM_HAVE_NATIVE) && \
!defined(WOLFSSL_NO_ML_KEM) && !defined(PSOC6_HASH_SHA3) && \
!defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \
!defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
static const int types[] = {
#ifndef WOLFSSL_NO_ML_KEM_512
WC_ML_KEM_512,
#endif
#ifndef WOLFSSL_NO_ML_KEM_768
WC_ML_KEM_768,
#endif
#ifndef WOLFSSL_NO_ML_KEM_1024
WC_ML_KEM_1024,
#endif
-1
};
static const byte zero[sizeof(wc_Sha3)] = {0};
MlKemKey* key = NULL;
byte seeds[WC_ML_KEM_MAKEKEY_RAND_SZ];
byte ct[WC_ML_KEM_MAX_CIPHER_TEXT_SIZE];
byte ss[WC_ML_KEM_SS_SZ];
byte recovered[WC_ML_KEM_SS_SZ];
word32 ctSz = 0;
int t, repeat, op, h;

key = (MlKemKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
XMEMSET(seeds, 0x71, sizeof(seeds));
PRIVATE_KEY_UNLOCK();
for (t = 0; EXPECT_SUCCESS() && types[t] != -1; t++) {
ExpectIntEQ(wc_MlKemKey_Init(key, types[t], NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_MlKemKey_CipherTextSize(key, &ctSz), 0);
for (repeat = 0; EXPECT_SUCCESS() && repeat < 2; repeat++) {
for (op = 0; EXPECT_SUCCESS() && op < 5; op++) {
if (op == 0) {
ExpectIntEQ(wc_MlKemKey_MakeKeyWithRandom(key, seeds,
sizeof(seeds)), SEED_OK);
}
else if (op == 1) {
ExpectIntEQ(wc_MlKemKey_EncapsulateWithRandom(key, ct, ss,
seeds, WC_ML_KEM_ENC_RAND_SZ), SEED_OK);
}
else if (op == 2) {
ExpectIntEQ(wc_MlKemKey_Decapsulate(key, recovered, ct,
ctSz), 0);
ExpectBufEQ(ss, recovered, sizeof(ss));
}
else if (op == 3) {
ExpectIntEQ(wc_MlKemKey_Decapsulate(key, recovered, ct,
ctSz - 1), WC_NO_ERR_TRACE(BUFFER_E));
}
else {
ct[32] ^= 1;
ExpectIntEQ(wc_MlKemKey_Decapsulate(key, recovered, ct,
ctSz), 0);
}
for (h = 0; h < 2; h++) {
const wc_Sha3* hash = h == 0 ? &key->hash : &key->prf;
ExpectBufEQ(hash->s, zero, sizeof(hash->s));
ExpectBufEQ(hash->t, zero, sizeof(hash->t));
ExpectIntEQ(hash->i, 0);
}
}
}
wc_MlKemKey_Free(key);
}
PRIVATE_KEY_LOCK();
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
4 changes: 3 additions & 1 deletion tests/api/test_mlkem.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ int test_wc_mlkem_decode_pubkey_refused_save(void);
int test_wc_mlkem_decode_reused_key(void);
int test_wc_mlkem_decode_alloc_fail(void);
int test_wc_mlkem_make_key_id_dev(void);
int test_wc_mlkem_operation_cleanup(void);

#define TEST_MLKEM_DECLS \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_make_key_kats), \
Expand All @@ -67,6 +68,7 @@ int test_wc_mlkem_make_key_id_dev(void);
TEST_DECL_GROUP("mlkem", test_wc_mlkem_decode_pubkey_refused_save), \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_decode_reused_key), \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_decode_alloc_fail), \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_make_key_id_dev)
TEST_DECL_GROUP("mlkem", test_wc_mlkem_make_key_id_dev), \
TEST_DECL_GROUP("mlkem", test_wc_mlkem_operation_cleanup)

#endif /* WOLFCRYPT_TEST_MLKEM_H */
Loading
Loading