Skip to content

Commit 583dbaf

Browse files
authored
Merge pull request #10488 from padelsbach/lms-xmss-test-sig-cmp
Update LMS and XMSS key advance test
2 parents 145a4fa + 8e150a2 commit 583dbaf

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
@@ -55982,10 +55982,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5598255982
word32 bufSz = 0;
5598355983
#ifdef WOLFSSL_NO_MALLOC
5598455984
static byte sk[2048];
55985-
static byte old_sk[2048];
5598655985
#else
5598755986
byte * sk = NULL;
55988-
byte * old_sk = NULL;
5598955987
#endif
5599055988
const char * msg = "XMSS post quantum signature test";
5599155989
word32 msgSz = (word32) XSTRLEN(msg);
@@ -56000,8 +55998,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5600055998
#endif
5600155999
#ifdef WOLFSSL_NO_MALLOC
5600256000
static byte sig[4096];
56001+
static byte old_sig[4096];
5600356002
#else
5600456003
byte * sig = NULL;
56004+
byte * old_sig = NULL;
5600556005
#endif
5600656006
int ret2 = -1;
5600756007
int ret = WC_TEST_RET_ENC_NC;
@@ -56038,13 +56038,17 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5603856038
ret = wc_XmssKey_GetSigLen(&signingKey, &sigSz);
5603956039
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
5604056040

56041-
/* Allocate signature array. */
56041+
/* Allocate signature buffers (current and previous iteration). */
5604256042
#ifdef WOLFSSL_NO_MALLOC
56043+
5604356044
if (sigSz > sizeof(sig))
5604456045
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
5604556046
#else
5604656047
sig = (byte *)XMALLOC(sigSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5604756048
if (sig == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); }
56049+
56050+
old_sig = (byte *)XMALLOC(sigSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56051+
if (old_sig == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); }
5604856052
#endif
5604956053

5605056054
bufSz = sigSz;
@@ -56056,20 +56060,17 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5605656060
fprintf(stderr, "sigSz: %d\n", sigSz);
5605756061
#endif
5605856062

56059-
/* Allocate current and old secret keys.*/
56063+
/* Allocate the secret key buffer used by the software write/read
56064+
* callbacks. */
5606056065
#ifdef WOLFSSL_NO_MALLOC
5606156066
if (skSz > sizeof(sk))
5606256067
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
5606356068
#else
5606456069
sk = (unsigned char *)XMALLOC(skSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5606556070
if (sk == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); }
56066-
56067-
old_sk = (unsigned char *)XMALLOC(skSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56068-
if (old_sk == NULL) { ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out); }
5606956071
#endif
5607056072

5607156073
XMEMSET(sk, 0, skSz);
56072-
XMEMSET(old_sk, 0, skSz);
5607356074
XMEMSET(sig, 0, sigSz);
5607456075

5607556076
ret = wc_XmssKey_SetWriteCb(&signingKey, xmss_write_key_mem);
@@ -56089,20 +56090,25 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5608956090
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
5609056091

5609156092
/* Repeat a few times to check that:
56092-
* 1. The secret key is mutated on each sign.
56093+
* 1. Each Sign advances state (so signing the same message yields a
56094+
* different signature than the previous iteration).
5609356095
* 2. We can verify each new signature.
5609456096
* Only do a few times, because the full signature space
5609556097
* for this parameter set is huge. */
5609656098
for (i = 0; i < 10; ++i) {
56097-
XMEMCPY(old_sk, sk, skSz);
56098-
5609956099
ret = wc_XmssKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
5610056100
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
5610156101
if (sigSz != bufSz) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
5610256102

56103-
/* Old secret key and current secret key should not match. */
56104-
ret = XMEMCMP(old_sk, sk, skSz);
56105-
if (ret == 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
56103+
/* XMSS is deterministic given (SK_state, msg); a stuck leaf would
56104+
* produce an identical signature. This check is agnostic to whether
56105+
* the private state lives in user memory (software path) or on a
56106+
* cryptocb device. */
56107+
if (i > 0) {
56108+
ret = XMEMCMP(old_sig, sig, sigSz);
56109+
if (ret == 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
56110+
}
56111+
XMEMCPY(old_sig, sig, sigSz);
5610656112

5610756113
ret = wc_XmssKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz);
5610856114
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
@@ -56131,11 +56137,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t xmss_test(void)
5613156137
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5613256138
sig = NULL;
5613356139

56140+
XFREE(old_sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56141+
old_sig = NULL;
56142+
5613456143
XFREE(sk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5613556144
sk = NULL;
56136-
56137-
XFREE(old_sk, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56138-
old_sk = NULL;
5613956145
#endif /* !WOLFSSL_NO_MALLOC */
5614056146

5614156147
wc_XmssKey_Free(&signingKey);
@@ -56660,31 +56666,34 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5666056666
word32 msgSz = (word32) XSTRLEN(msg);
5666156667
#ifndef WOLFSSL_WC_LMS_SERIALIZE_STATE
5666256668
unsigned char priv[HSS_MAX_PRIVATE_KEY_LEN];
56663-
unsigned char old_priv[HSS_MAX_PRIVATE_KEY_LEN];
5666456669
#else
5666556670
static unsigned char priv[64 * 1024 + HSS_MAX_PRIVATE_KEY_LEN];
56666-
static unsigned char old_priv[64 * 1024 + HSS_MAX_PRIVATE_KEY_LEN];
5666756671
#endif
5666856672
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
5666956673
byte * sig = (byte*)XMALLOC(WC_TEST_LMS_SIG_LEN, HEAP_HINT,
5667056674
DYNAMIC_TYPE_TMP_BUFFER);
56675+
byte * old_sig = (byte*)XMALLOC(WC_TEST_LMS_SIG_LEN, HEAP_HINT,
56676+
DYNAMIC_TYPE_TMP_BUFFER);
5667156677
#else
5667256678
byte sig[WC_TEST_LMS_SIG_LEN];
56679+
byte old_sig[WC_TEST_LMS_SIG_LEN];
5667356680
#endif
5667456681
const byte * kid;
5667556682
word32 kidSz;
5667656683

5667756684
WOLFSSL_ENTER("lms_test");
5667856685

5667956686
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
56680-
if (sig == NULL) {
56687+
if ((sig == NULL) || (old_sig == NULL)) {
56688+
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56689+
XFREE(old_sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5668156690
return WC_TEST_RET_ENC_ERRNO;
5668256691
}
5668356692
#endif
5668456693

5668556694
XMEMSET(priv, 0, sizeof(priv));
56686-
XMEMSET(old_priv, 0, sizeof(old_priv));
5668756695
XMEMSET(sig, 0, WC_TEST_LMS_SIG_LEN);
56696+
XMEMSET(old_sig, 0, WC_TEST_LMS_SIG_LEN);
5668856697
XMEMSET(&rng, 0, sizeof(rng));
5668956698
XMEMSET(&signingKey, 0, sizeof(signingKey));
5669056699
XMEMSET(&verifyKey, 0, sizeof(verifyKey));
@@ -56729,8 +56738,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5672956738
ret = wc_LmsKey_MakeKey(&signingKey, &rng);
5673056739
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); }
5673156740

56732-
XMEMCPY(old_priv, priv, sizeof(priv));
56733-
5673456741
ret = wc_LmsKey_GetKid(NULL, NULL, NULL);
5673556742
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
5673656743
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
@@ -56772,21 +56779,32 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5677256779
/* Test wc_LmsKey_Sign input validation. */
5677356780
{
5677456781
word32 smallSz = 1;
56775-
wc_lms_write_private_key_cb saved_write_cb;
5677656782

56777-
/* Undersized sig buffer should return BUFFER_E. */
56783+
/* Undersized sig buffer should return BUFFER_E. This check runs in
56784+
* wc_LmsKey_Sign before the cryptocb dispatch, so it applies in both
56785+
* software and HSM modes. */
5677856786
ret = wc_LmsKey_Sign(&signingKey, sig, &smallSz, (byte *) msg, msgSz);
5677956787
if (ret != WC_NO_ERR_TRACE(BUFFER_E)) {
5678056788
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
5678156789
}
5678256790

56783-
/* NULL write callback should return BAD_FUNC_ARG. */
56784-
saved_write_cb = signingKey.write_private_key;
56785-
signingKey.write_private_key = NULL;
56786-
ret = wc_LmsKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
56787-
signingKey.write_private_key = saved_write_cb;
56788-
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) {
56789-
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
56791+
#ifdef WOLF_CRYPTO_CB
56792+
/* The NULL-WriteCb -> BAD_FUNC_ARG check in wc_LmsKey_Sign sits after
56793+
* the cryptocb dispatch; an HSM-backed Sign succeeds without ever
56794+
* reaching it. Only exercise this on the pure software path. */
56795+
if (devId == INVALID_DEVID)
56796+
#endif
56797+
{
56798+
wc_lms_write_private_key_cb saved_write_cb;
56799+
56800+
/* NULL write callback should return BAD_FUNC_ARG. */
56801+
saved_write_cb = signingKey.write_private_key;
56802+
signingKey.write_private_key = NULL;
56803+
ret = wc_LmsKey_Sign(&signingKey, sig, &sigSz, (byte *) msg, msgSz);
56804+
signingKey.write_private_key = saved_write_cb;
56805+
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) {
56806+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
56807+
}
5679056808
}
5679156809

5679256810
ret = 0;
@@ -56800,17 +56818,21 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5680056818
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
5680156819
}
5680256820

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

56807-
/* The updated private key should not match the old one. */
56808-
if (XMEMCMP(old_priv, priv, sizeof(priv)) == 0) {
56809-
printf("error: current priv key should not match old: %d\n", i);
56810-
ERROR_OUT(WC_TEST_RET_ENC_I(i), out);
56825+
/* LMS/HSS is deterministic given (state, msg); a stuck leaf would
56826+
* produce an identical signature. This check is agnostic to whether
56827+
* the private state lives in user memory (software path) or on a
56828+
* cryptocb device. */
56829+
if (i > 0) {
56830+
if (XMEMCMP(old_sig, sig, sigSz) == 0) {
56831+
printf("error: current signature should not match old: %d\n", i);
56832+
ERROR_OUT(WC_TEST_RET_ENC_I(i), out);
56833+
}
5681156834
}
56812-
56813-
XMEMCPY(old_priv, priv, sizeof(priv));
56835+
XMEMCPY(old_sig, sig, sigSz);
5681456836

5681556837
ret = wc_LmsKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz);
5681656838
if (ret != 0) { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); }
@@ -56850,6 +56872,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t lms_test(void)
5685056872

5685156873
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
5685256874
XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
56875+
XFREE(old_sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
5685356876
#endif
5685456877

5685556878
return ret;

0 commit comments

Comments
 (0)