1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

Test the ML-DSA key caches after small-mem key regeneration

This commit is contained in:
Emma Stensland
2026-09-30 10:18:06 -06:00
committed by Paul Adelsbach
parent 265e5e5fba
commit c102b31fde
3 changed files with 102 additions and 4 deletions

View File

@@ -175,12 +175,12 @@
"LDFLAGS=-fsanitize=undefined",
"CPPFLAGS=-DWOLFSSL_MLDSA_SIGN_SMALL_MEM -DWOLFSSL_MLDSA_VERIFY_SMALL_MEM -DWOLFSSL_MLDSA_MAKE_KEY_SMALL_MEM -DWOLFSSL_MLDSA_TEST_REJ_NTT_FAIL -DWOLFSSL_MLDSA_CHECK_INVNTT_BOUND"]},
{"name": "ubsan-mldsa-small-smallmem-poly64", "minutes": 2.4,
"comment": "As ubsan-mldsa-small-smallmem, with the 64-bit t64 accumulator layout",
"comment": "As ubsan-mldsa-small-smallmem, with the 64-bit t64 accumulator layout; WC_MLDSA_CACHE_MATRIX_A makes CheckKey allocate matrix A after small-mem key generation",
"configure": ["--disable-shared", "--disable-intelasm",
"--enable-dilithium=yes,small",
"CFLAGS=-fsanitize=undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer",
"LDFLAGS=-fsanitize=undefined",
"CPPFLAGS=-DWOLFSSL_MLDSA_SIGN_SMALL_MEM -DWOLFSSL_MLDSA_VERIFY_SMALL_MEM -DWOLFSSL_MLDSA_MAKE_KEY_SMALL_MEM -DWOLFSSL_MLDSA_SMALL_MEM_POLY64 -DWOLFSSL_MLDSA_TEST_REJ_NTT_FAIL -DWOLFSSL_MLDSA_CHECK_INVNTT_BOUND"]},
"CPPFLAGS=-DWOLFSSL_MLDSA_SIGN_SMALL_MEM -DWOLFSSL_MLDSA_VERIFY_SMALL_MEM -DWOLFSSL_MLDSA_MAKE_KEY_SMALL_MEM -DWOLFSSL_MLDSA_SMALL_MEM_POLY64 -DWOLFSSL_MLDSA_TEST_REJ_NTT_FAIL -DWOLFSSL_MLDSA_CHECK_INVNTT_BOUND -DWC_MLDSA_CACHE_MATRIX_A"]},
{"name": "ubsan-mldsa-sign-precalc", "minutes": 2.4,
"comment": "Runs the WOLFSSL_MLDSA_SIGN_SMALL_MEM_PRECALC scratch layout, and the non-SMALL key generation and verify small-mem paths, at the default alignment of 0, where MLDSA_REJ_NTT_POLY_H_SIZE is odd",
"configure": ["--disable-shared", "--disable-intelasm", "--enable-dilithium",
@@ -325,8 +325,10 @@
"configure": ["--enable-cryptonly", "--enable-mldsa",
"CPPFLAGS=-DWC_MLDSA_CACHE_MATRIX_A -DWOLFSSL_MLDSA_SIGN_SMALL_MEM_PRECALC_A=1"]},
{"name": "mldsa-cache-small-keygen", "minutes": 2,
"comment": "Every key cache alongside the small memory key generation, which must drop the caches of the key it replaces",
"configure": ["--enable-cryptonly", "--enable-mldsa",
"comment": "Every key cache alongside the small memory key generation, which must drop the caches of the key it replaces; under UBSan",
"configure": ["--enable-cryptonly", "--enable-mldsa", "--disable-shared",
"CFLAGS=-fsanitize=undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer",
"LDFLAGS=-fsanitize=undefined",
"CPPFLAGS=-DWC_MLDSA_CACHE_PRIV_VECTORS -DWC_MLDSA_CACHE_PUB_VECTORS -DWOLFSSL_MLDSA_MAKE_KEY_SMALL_MEM"]},
{"name": "mldsa-no-check-key-small-mem", "minutes": 2,
"comment": "Key pair checking compiled out alongside the small memory key generation and the smallest memory signer, which leaves the whole vector helpers with no caller",

View File

@@ -1520,6 +1520,13 @@ int test_mldsa_check_key(void)
ExpectIntEQ(wc_MlDsaKey_SetParams(checkKey, WC_ML_DSA_87), 0);
#endif
ExpectIntEQ(wc_MlDsaKey_MakeKey(checkKey, &rng), 0);
/* A freshly generated key checks out. Small-mem key generation never
* caches A, so this also covers CheckKey allocating the matrix cache. */
ExpectIntEQ(wc_MlDsaKey_CheckKey(checkKey), 0);
/* Regenerating into the same object must not reuse the A that CheckKey
* just cached for the previous key. */
ExpectIntEQ(wc_MlDsaKey_MakeKey(checkKey, &rng), 0);
ExpectIntEQ(wc_MlDsaKey_CheckKey(checkKey), 0);
ExpectIntEQ(wc_MlDsaKey_ExportKey(NULL, NULL, NULL, NULL, NULL),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
@@ -7906,6 +7913,93 @@ int test_mldsa_make_key_from_seed(void)
return EXPECT_RESULT();
}
/* Regenerating a key into the same object must not sign or verify with the
* vectors cached for the previous key. */
int test_mldsa_make_key_twice(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_HAVE_MLDSA) && defined(WC_MLDSA_HAVE_NATIVE) && \
defined(WOLFSSL_MLDSA_PUBLIC_KEY) && \
!defined(WOLFSSL_MLDSA_NO_MAKE_KEY) && !defined(WOLFSSL_MLDSA_NO_SIGN) && \
!defined(WOLFSSL_MLDSA_NO_VERIFY)
wc_MlDsaKey* key;
wc_MlDsaKey* verifyKey;
WC_RNG rng;
byte* sig;
byte* pub;
word32 sigLen;
word32 pubLen;
byte msg[] = "make key twice";
int res;
int i;
XMEMSET(&rng, 0, sizeof(rng));
key = (wc_MlDsaKey*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(key);
verifyKey = (wc_MlDsaKey*)XMALLOC(sizeof(*verifyKey), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(verifyKey);
sig = (byte*)XMALLOC(MLDSA_MAX_SIG_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(sig);
pub = (byte*)XMALLOC(MLDSA_MAX_PUB_KEY_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
ExpectNotNull(pub);
if (key != NULL) {
XMEMSET(key, 0, sizeof(*key));
}
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_MlDsaKey_Init(key, NULL, INVALID_DEVID), 0);
#ifndef WOLFSSL_NO_ML_DSA_44
ExpectIntEQ(wc_MlDsaKey_SetParams(key, WC_ML_DSA_44), 0);
#elif !defined(WOLFSSL_NO_ML_DSA_65)
ExpectIntEQ(wc_MlDsaKey_SetParams(key, WC_ML_DSA_65), 0);
#else
ExpectIntEQ(wc_MlDsaKey_SetParams(key, WC_ML_DSA_87), 0);
#endif
/* The first pass fills the caches; the second must not reuse them. */
for (i = 0; i < 2; i++) {
ExpectIntEQ(wc_MlDsaKey_MakeKey(key, &rng), 0);
sigLen = MLDSA_MAX_SIG_SIZE;
ExpectIntEQ(wc_MlDsaKey_SignCtx(key, NULL, 0, sig, &sigLen, msg,
sizeof(msg), &rng), 0);
/* Same object: uses any cached public vector. */
res = 0;
ExpectIntEQ(wc_MlDsaKey_VerifyCtx(key, sig, sigLen, NULL, 0, msg,
sizeof(msg), &res), 0);
ExpectIntEQ(res, 1);
/* Fresh object with only the new public key: catches a signature
* made from cached private vectors of the previous key. */
pubLen = MLDSA_MAX_PUB_KEY_SIZE;
ExpectIntEQ(wc_MlDsaKey_ExportPubRaw(key, pub, &pubLen), 0);
if (verifyKey != NULL) {
XMEMSET(verifyKey, 0, sizeof(*verifyKey));
}
ExpectIntEQ(wc_MlDsaKey_Init(verifyKey, NULL, INVALID_DEVID), 0);
ExpectIntEQ(wc_MlDsaKey_SetParams(verifyKey,
(key != NULL) ? key->level : 0), 0);
ExpectIntEQ(wc_MlDsaKey_ImportPubRaw(verifyKey, pub, pubLen), 0);
res = 0;
ExpectIntEQ(wc_MlDsaKey_VerifyCtx(verifyKey, sig, sigLen, NULL, 0,
msg, sizeof(msg), &res), 0);
ExpectIntEQ(res, 1);
wc_MlDsaKey_Free(verifyKey);
}
wc_MlDsaKey_Free(key);
wc_FreeRng(&rng);
XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(verifyKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return EXPECT_RESULT();
}
int test_mldsa_sig_kats(void)
{
EXPECT_DECLS;

View File

@@ -39,6 +39,7 @@ int test_mldsa_public_der_decode(void);
int test_mldsa_der(void);
int test_mldsa_oneasymkey_version(void);
int test_mldsa_make_key_from_seed(void);
int test_mldsa_make_key_twice(void);
int test_mldsa_sig_kats(void);
int test_mldsa_sign_ctx_kats(void);
int test_mldsa_verify_ctx_kats(void);
@@ -87,6 +88,7 @@ int test_mldsa_make_key_rej_ntt_fail(void);
TEST_DECL_GROUP("mldsa", test_mldsa_der), \
TEST_DECL_GROUP("mldsa", test_mldsa_oneasymkey_version), \
TEST_DECL_GROUP("mldsa", test_mldsa_make_key_from_seed), \
TEST_DECL_GROUP("mldsa", test_mldsa_make_key_twice), \
TEST_DECL_GROUP("mldsa", test_mldsa_sig_kats), \
TEST_DECL_GROUP("mldsa", test_mldsa_sign_ctx_kats), \
TEST_DECL_GROUP("mldsa", test_mldsa_verify_ctx_kats), \