Skip to content

Commit 8e150a2

Browse files
committed
Update LMS and XMSS key advance test
1 parent 460a871 commit 8e150a2

1 file changed

Lines changed: 62 additions & 39 deletions

File tree

wolfcrypt/test/test.c

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -55912,10 +55912,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5591255912
word32 bufSz = 0;
5591355913
#ifdef WOLFSSL_NO_MALLOC
5591455914
static byte sk[2048];
55915-
static byte old_sk[2048];
5591655915
#else
5591755916
byte * sk = NULL;
55918-
byte * old_sk = NULL;
5591955917
#endif
5592055918
const char * msg = "XMSS post quantum signature test";
5592155919
word32 msgSz = (word32) XSTRLEN(msg);
@@ -55930,8 +55928,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5593055928
#endif
5593155929
#ifdef WOLFSSL_NO_MALLOC
5593255930
static byte sig[4096];
55931+
static byte old_sig[4096];
5593355932
#else
5593455933
byte * sig = NULL;
55934+
byte * old_sig = NULL;
5593555935
#endif
5593655936
int ret2 = -1;
5593755937
int ret = WC_TEST_RET_ENC_NC;
@@ -55968,13 +55968,17 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5596855968
ret = wc_XmssKey_GetSigLen(&signingKey, &sigSz);
5596955969
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
5597055970

55971-
/* Allocate signature array. */
55971+
/* Allocate signature buffers (current and previous iteration). */
5597255972
#ifdef WOLFSSL_NO_MALLOC
55973+
5597355974
if (sigSz > sizeof(sig))
5597455975
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
5597555976
#else
5597655977
sig = (byte *)XMALLOC(sigSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5597755978
if (sig == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); }
55979+
55980+
old_sig = (byte *)XMALLOC(sigSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
55981+
if (old_sig == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); }
5597855982
#endif
5597955983

5598055984
bufSz = sigSz;
@@ -55986,20 +55990,17 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5598655990
fprintf(stderr, "sigSz: %d\n", sigSz);
5598755991
#endif
5598855992

55989-
/* Allocate current and old secret keys.*/
55993+
/* Allocate the secret key buffer used by the software write/read
55994+
* callbacks. */
5599055995
#ifdef WOLFSSL_NO_MALLOC
5599155996
if (skSz > sizeof(sk))
5599255997
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
5599355998
#else
5599455999
sk = (unsigned char *)XMALLOC(skSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5599556000
if (sk == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); }
55996-
55997-
old_sk = (unsigned char *)XMALLOC(skSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
55998-
if (old_sk == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); }
5599956001
#endif
5600056002

5600156003
XMEMSET(sk, 0, skSz);
56002-
XMEMSET(old_sk, 0, skSz);
5600356004
XMEMSET(sig, 0, sigSz);
5600456005

5600556006
ret = wc_XmssKey_SetWriteCb(&signingKey, xmss_write_key_mem);
@@ -56019,20 +56020,25 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5601956020
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
5602056021

5602156022
/* Repeat a few times to check that:
56022-
* 1. The secret key is mutated on each sign.
56023+
* 1. Each Sign advances state (so signing the same message yields a
56024+
* different signature than the previous iteration).
5602356025
* 2. We can verify each new signature.
5602456026
* Only do a few times, because the full signature space
5602556027
* for this parameter set is huge. */
5602656028
for (i = 0; i < 10; ++i) {
56027-
XMEMCPY(old_sk, sk, skSz);
56028-
5602956029
ret = wc_XmssKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
5603056030
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
5603156031
if (sigSz != bufSz) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
5603256032

56033-
/* Old secret key and current secret key should not match. */
56034-
ret = XMEMCMP(old_sk, sk, skSz);
56035-
if (ret == 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
56033+
/* XMSS is deterministic given (SK_state, msg); a stuck leaf would
56034+
* produce an identical signature. This check is agnostic to whether
56035+
* the private state lives in user memory (software path) or on a
56036+
* cryptocb device. */
56037+
if (i > 0) {
56038+
ret = XMEMCMP(old_sig, sig, sigSz);
56039+
if (ret == 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
56040+
}
56041+
XMEMCPY(old_sig, sig, sigSz);
5603656042

5603756043
ret = wc_XmssKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz);
5603856044
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
@@ -56061,11 +56067,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5606156067
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5606256068
sig = NULL;
5606356069

56070+
XFREE(old_sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56071+
old_sig = NULL;
56072+
5606456073
XFREE(sk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5606556074
sk = NULL;
56066-
56067-
XFREE(old_sk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56068-
old_sk = NULL;
5606956075
#endif /* !WOLFSSL_NO_MALLOC */
5607056076

5607156077
wc_XmssKey_Free(&signingKey);
@@ -56590,31 +56596,34 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5659056596
word32 msgSz = (word32) XSTRLEN(msg);
5659156597
#ifndef WOLFSSL_WC_LMS_SERIALIZE_STATE
5659256598
unsigned char priv[HSS_MAX_PRIVATE_KEY_LEN];
56593-
unsigned char old_priv[HSS_MAX_PRIVATE_KEY_LEN];
5659456599
#else
5659556600
static unsigned char priv[64 * 1024 + HSS_MAX_PRIVATE_KEY_LEN];
56596-
static unsigned char old_priv[64 * 1024 + HSS_MAX_PRIVATE_KEY_LEN];
5659756601
#endif
5659856602
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
5659956603
byte * sig = (byte*)XMALLOC(WC_TEST_LMS_SIG_LEN, HEAP_HINT,
5660056604
DYNAMIC_TYPE_TMP_BUFFER);
56605+
byte * old_sig = (byte*)XMALLOC(WC_TEST_LMS_SIG_LEN, HEAP_HINT,
56606+
DYNAMIC_TYPE_TMP_BUFFER);
5660156607
#else
5660256608
byte sig[WC_TEST_LMS_SIG_LEN];
56609+
byte old_sig[WC_TEST_LMS_SIG_LEN];
5660356610
#endif
5660456611
const byte * kid;
5660556612
word32 kidSz;
5660656613

5660756614
WOLFSSL_ENTER("lms_test");
5660856615

5660956616
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
56610-
if (sig == NULL) {
56617+
if ((sig == NULL) || (old_sig == NULL)) {
56618+
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56619+
XFREE(old_sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5661156620
return WC_TEST_RET_ENC_ERRNO;
5661256621
}
5661356622
#endif
5661456623

5661556624
XMEMSET(priv, 0, sizeof(priv));
56616-
XMEMSET(old_priv, 0, sizeof(old_priv));
5661756625
XMEMSET(sig, 0, WC_TEST_LMS_SIG_LEN);
56626+
XMEMSET(old_sig, 0, WC_TEST_LMS_SIG_LEN);
5661856627
XMEMSET(&rng, 0, sizeof(rng));
5661956628
XMEMSET(&signingKey, 0, sizeof(signingKey));
5662056629
XMEMSET(&verifyKey, 0, sizeof(verifyKey));
@@ -56659,8 +56668,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5665956668
ret = wc_LmsKey_MakeKey(&signingKey, &rng);
5666056669
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
5666156670

56662-
XMEMCPY(old_priv, priv, sizeof(priv));
56663-
5666456671
ret = wc_LmsKey_GetKid(NULL, NULL, NULL);
5666556672
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
5666656673
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
@@ -56702,21 +56709,32 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5670256709
/* Test wc_LmsKey_Sign input validation. */
5670356710
{
5670456711
word32 smallSz = 1;
56705-
wc_lms_write_private_key_cb saved_write_cb;
5670656712

56707-
/* Undersized sig buffer should return BUFFER_E. */
56713+
/* Undersized sig buffer should return BUFFER_E. This check runs in
56714+
* wc_LmsKey_Sign before the cryptocb dispatch, so it applies in both
56715+
* software and HSM modes. */
5670856716
ret = wc_LmsKey_Sign(&signingKey, sig, &smallSz, (byte *) msg, msgSz);
5670956717
if (ret != WC_NO_ERR_TRACE(BUFFER_E)) {
5671056718
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
5671156719
}
5671256720

56713-
/* NULL write callback should return BAD_FUNC_ARG. */
56714-
saved_write_cb = signingKey.write_private_key;
56715-
signingKey.write_private_key = NULL;
56716-
ret = wc_LmsKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
56717-
signingKey.write_private_key = saved_write_cb;
56718-
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) {
56719-
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
56721+
#ifdef WOLF_CRYPTO_CB
56722+
/* The NULL-WriteCb -> BAD_FUNC_ARG check in wc_LmsKey_Sign sits after
56723+
* the cryptocb dispatch; an HSM-backed Sign succeeds without ever
56724+
* reaching it. Only exercise this on the pure software path. */
56725+
if (devId == INVALID_DEVID)
56726+
#endif
56727+
{
56728+
wc_lms_write_private_key_cb saved_write_cb;
56729+
56730+
/* NULL write callback should return BAD_FUNC_ARG. */
56731+
saved_write_cb = signingKey.write_private_key;
56732+
signingKey.write_private_key = NULL;
56733+
ret = wc_LmsKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
56734+
signingKey.write_private_key = saved_write_cb;
56735+
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) {
56736+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
56737+
}
5672056738
}
5672156739

5672256740
ret = 0;
@@ -56730,17 +56748,21 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5673056748
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
5673156749
}
5673256750

56733-
/* Sign with key. The private key will be updated on every signature. */
56751+
/* Sign with key. State advances on every signature. */
5673456752
ret = wc_LmsKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
5673556753
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
5673656754

56737-
/* The updated private key should not match the old one. */
56738-
if (XMEMCMP(old_priv, priv, sizeof(priv)) == 0) {
56739-
printf("error: current priv key should not match old: %d\n", i);
56740-
ERROR_OUT(WC_TEST_RET_ENC_I(i), out);
56755+
/* LMS/HSS is deterministic given (state, msg); a stuck leaf would
56756+
* produce an identical signature. This check is agnostic to whether
56757+
* the private state lives in user memory (software path) or on a
56758+
* cryptocb device. */
56759+
if (i > 0) {
56760+
if (XMEMCMP(old_sig, sig, sigSz) == 0) {
56761+
printf("error: current signature should not match old: %d\n", i);
56762+
ERROR_OUT(WC_TEST_RET_ENC_I(i), out);
56763+
}
5674156764
}
56742-
56743-
XMEMCPY(old_priv, priv, sizeof(priv));
56765+
XMEMCPY(old_sig, sig, sigSz);
5674456766

5674556767
ret = wc_LmsKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz);
5674656768
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
@@ -56780,6 +56802,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5678056802

5678156803
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
5678256804
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56805+
XFREE(old_sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5678356806
#endif
5678456807

5678556808
return ret;

0 commit comments

Comments
 (0)