diff --git a/tests/api/test_lms_xmss.c b/tests/api/test_lms_xmss.c index f12545992c..4a995ebfc1 100644 --- a/tests/api/test_lms_xmss.c +++ b/tests/api/test_lms_xmss.c @@ -60,7 +60,8 @@ /* LMS tests */ /*----------------------------------------------------------------------------*/ -#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) +#if defined(WOLFSSL_HAVE_LMS) && (!defined(WOLFSSL_LMS_VERIFY_ONLY) || \ + (defined(WOLF_CRYPTO_CB) && defined(WOLF_PRIVATE_KEY_ID))) #include @@ -73,6 +74,9 @@ static int test_lms_set_params(LmsKey* key) return wc_LmsKey_SetParameters(key, 1, 5, 8); #endif } +#endif + +#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY) #ifdef TEST_LMS_SW_AVAILABLE /* Per-process temp file: parallel unit.test runs (e.g. CI shards sharing a @@ -393,11 +397,12 @@ static int test_lms_xmss_cryptocb(int devIdArg, wc_CryptoInfo* info, void* ctx) } #endif -/* Must be the exact union of the two verify test guards below. */ +/* Must be the exact union of the guards of the tests that register it. */ #if defined(WOLF_CRYPTO_CB) && \ - ((defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)) || \ - (defined(WOLFSSL_HAVE_XMSS) && !defined(WOLFSSL_XMSS_VERIFY_ONLY) && \ - defined(TEST_XMSS_H10_AVAILABLE))) + ((defined(WOLFSSL_HAVE_LMS) && \ + (!defined(WOLFSSL_LMS_VERIFY_ONLY) || defined(WOLF_PRIVATE_KEY_ID))) || \ + (defined(WOLFSSL_HAVE_XMSS) && defined(TEST_XMSS_H10_AVAILABLE) && \ + (!defined(WOLFSSL_XMSS_VERIFY_ONLY) || defined(WOLF_PRIVATE_KEY_ID)))) /* Number of stateful signature verifications the accelerator below answered. */ static int test_lms_xmss_verify_calls; @@ -677,6 +682,80 @@ int test_wc_LmsKey_id_sigsleft(void) return EXPECT_RESULT(); } +/* + * Test that an LMS key named by id verifies on its device with only its + * parameters set, as a verify-only build has no Reload to call. + */ +int test_wc_LmsKey_id_verify(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_HAVE_LMS) && defined(WOLF_CRYPTO_CB) && \ + defined(WOLF_PRIVATE_KEY_ID) + LmsKey key; + const byte id[] = { 0x01, 0x02, 0x03, 0x04 }; + byte msg[] = "test message for LMS signing"; + byte* sig = NULL; + word32 sigSz = 0; + + XMEMSET(&key, 0, sizeof(key)); + test_lms_xmss_verify_calls = 0; + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_LMS_XMSS_CRYPTOCB_DEVID, + test_lms_xmss_verify_cryptocb, NULL), 0); + ExpectIntEQ(wc_LmsKey_InitId(&key, id, (int)sizeof(id), NULL, + TEST_LMS_XMSS_CRYPTOCB_DEVID), 0); + ExpectIntEQ(test_lms_set_params(&key), 0); + ExpectIntEQ(wc_LmsKey_GetSigLen(&key, &sigSz), 0); + ExpectNotNull(sig = (byte*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); + if (sig != NULL) { + XMEMSET(sig, 0, sigSz); + ExpectIntEQ(wc_LmsKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), 0); + ExpectIntEQ(test_lms_xmss_verify_calls, 1); + } + wc_LmsKey_Free(&key); + + /* A key with no id, label or device context needs a public key. */ + ExpectIntEQ(wc_LmsKey_Init(&key, NULL, TEST_LMS_XMSS_CRYPTOCB_DEVID), 0); + ExpectIntEQ(test_lms_set_params(&key), 0); + if (sig != NULL) { + ExpectIntEQ(wc_LmsKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), + WC_NO_ERR_TRACE(BAD_STATE_E)); + ExpectIntEQ(test_lms_xmss_verify_calls, 1); + } + wc_LmsKey_Free(&key); + + /* A device context names the key as an id does. */ + ExpectIntEQ(wc_LmsKey_Init(&key, NULL, TEST_LMS_XMSS_CRYPTOCB_DEVID), 0); + ExpectIntEQ(test_lms_set_params(&key), 0); + key.devCtx = msg; + if (sig != NULL) { + ExpectIntEQ(wc_LmsKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), 0); + ExpectIntEQ(test_lms_xmss_verify_calls, 2); + } + key.devCtx = NULL; + wc_LmsKey_Free(&key); + + /* Without a device the same key has no public key to verify with. */ + ExpectIntEQ(wc_LmsKey_InitId(&key, id, (int)sizeof(id), NULL, + INVALID_DEVID), 0); + ExpectIntEQ(test_lms_set_params(&key), 0); + if (sig != NULL) { + #if defined(WOLF_CRYPTO_CB_ONLY_LMS) && !defined(WOLFSSL_SWDEV) + ExpectIntEQ(wc_LmsKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), + WC_NO_ERR_TRACE(NO_VALID_DEVID)); + #else + ExpectIntEQ(wc_LmsKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), + WC_NO_ERR_TRACE(BAD_STATE_E)); + #endif + } + + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_LmsKey_Free(&key); + wc_CryptoCb_UnRegisterDevice(TEST_LMS_XMSS_CRYPTOCB_DEVID); +#endif + return EXPECT_RESULT(); +} + /* Must be the exact union of the guards of the tests that register it. */ #if defined(WOLF_CRYPTO_CB) && \ ((defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_VERIFY_ONLY)) || \ @@ -1225,6 +1304,79 @@ int test_wc_XmssKey_id_sigsleft(void) return EXPECT_RESULT(); } +/* + * Same scenario as test_wc_LmsKey_id_verify, for XMSS. + */ +int test_wc_XmssKey_id_verify(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_HAVE_XMSS) && defined(WOLF_CRYPTO_CB) && \ + defined(TEST_XMSS_H10_AVAILABLE) && defined(WOLF_PRIVATE_KEY_ID) + XmssKey key; + const byte id[] = { 0x01, 0x02, 0x03, 0x04 }; + byte msg[] = "test message for XMSS signing"; + byte* sig = NULL; + word32 sigSz = 0; + + XMEMSET(&key, 0, sizeof(key)); + test_lms_xmss_verify_calls = 0; + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_LMS_XMSS_CRYPTOCB_DEVID, + test_lms_xmss_verify_cryptocb, NULL), 0); + ExpectIntEQ(wc_XmssKey_InitId(&key, id, (int)sizeof(id), NULL, + TEST_LMS_XMSS_CRYPTOCB_DEVID), 0); + ExpectIntEQ(wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256"), 0); + ExpectIntEQ(wc_XmssKey_GetSigLen(&key, &sigSz), 0); + ExpectNotNull(sig = (byte*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); + if (sig != NULL) { + XMEMSET(sig, 0, sigSz); + ExpectIntEQ(wc_XmssKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), 0); + ExpectIntEQ(test_lms_xmss_verify_calls, 1); + } + wc_XmssKey_Free(&key); + + /* A key with no id, label or device context needs a public key. */ + ExpectIntEQ(wc_XmssKey_Init(&key, NULL, TEST_LMS_XMSS_CRYPTOCB_DEVID), 0); + ExpectIntEQ(wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256"), 0); + if (sig != NULL) { + ExpectIntEQ(wc_XmssKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), + WC_NO_ERR_TRACE(BAD_STATE_E)); + ExpectIntEQ(test_lms_xmss_verify_calls, 1); + } + wc_XmssKey_Free(&key); + + /* A device context names the key as an id does. */ + ExpectIntEQ(wc_XmssKey_Init(&key, NULL, TEST_LMS_XMSS_CRYPTOCB_DEVID), 0); + ExpectIntEQ(wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256"), 0); + key.devCtx = msg; + if (sig != NULL) { + ExpectIntEQ(wc_XmssKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), 0); + ExpectIntEQ(test_lms_xmss_verify_calls, 2); + } + key.devCtx = NULL; + wc_XmssKey_Free(&key); + + /* Without a device the same key has no public key to verify with. */ + ExpectIntEQ(wc_XmssKey_InitId(&key, id, (int)sizeof(id), NULL, + INVALID_DEVID), 0); + ExpectIntEQ(wc_XmssKey_SetParamStr(&key, "XMSS-SHA2_10_256"), 0); + if (sig != NULL) { + #if defined(WOLF_CRYPTO_CB_ONLY_XMSS) && !defined(WOLFSSL_SWDEV) + ExpectIntEQ(wc_XmssKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), + WC_NO_ERR_TRACE(NO_VALID_DEVID)); + #else + ExpectIntEQ(wc_XmssKey_Verify(&key, sig, sigSz, msg, sizeof(msg)), + WC_NO_ERR_TRACE(BAD_STATE_E)); + #endif + } + + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_XmssKey_Free(&key); + wc_CryptoCb_UnRegisterDevice(TEST_LMS_XMSS_CRYPTOCB_DEVID); +#endif + return EXPECT_RESULT(); +} + #if defined(WOLF_CRYPTO_CB_ONLY_XMSS) && !defined(WOLFSSL_SWDEV) && \ !defined(WOLFSSL_XMSS_VERIFY_ONLY) && defined(TEST_XMSS_H10_AVAILABLE) static enum wc_XmssRc test_xmss_read_fail(byte* priv, word32 privSz, diff --git a/tests/api/test_lms_xmss.h b/tests/api/test_lms_xmss.h index 2e40e51d4c..63f8873a11 100644 --- a/tests/api/test_lms_xmss.h +++ b/tests/api/test_lms_xmss.h @@ -34,12 +34,14 @@ int test_wc_LmsKey_reload_fail_sigsleft(void); int test_wc_LmsKey_makekey_fail_sigsleft(void); int test_wc_LmsKey_keygen_no_sigsleft(void); int test_wc_LmsKey_id_sigsleft(void); +int test_wc_LmsKey_id_verify(void); int test_wc_LmsKey_cb_only_no_device(void); int test_wc_XmssKey_reload_devid(void); int test_wc_XmssKey_reload_no_pub(void); int test_wc_XmssKey_reload_devid_verify(void); int test_wc_XmssKey_keygen_sign_declined(void); int test_wc_XmssKey_id_sigsleft(void); +int test_wc_XmssKey_id_verify(void); int test_wc_XmssKey_cb_only_no_device(void); int test_rfc9802_lms_x509_verify(void); int test_rfc9802_xmss_x509_verify(void); @@ -62,12 +64,14 @@ int test_wc_XmssFeatureCoverage(void); TEST_DECL_GROUP("lms", test_wc_LmsKey_makekey_fail_sigsleft), \ TEST_DECL_GROUP("lms", test_wc_LmsKey_keygen_no_sigsleft), \ TEST_DECL_GROUP("lms", test_wc_LmsKey_id_sigsleft), \ + TEST_DECL_GROUP("lms", test_wc_LmsKey_id_verify), \ TEST_DECL_GROUP("lms", test_wc_LmsKey_cb_only_no_device), \ TEST_DECL_GROUP("xmss", test_wc_XmssKey_reload_devid), \ TEST_DECL_GROUP("xmss", test_wc_XmssKey_reload_no_pub), \ TEST_DECL_GROUP("xmss", test_wc_XmssKey_reload_devid_verify), \ TEST_DECL_GROUP("xmss", test_wc_XmssKey_keygen_sign_declined), \ TEST_DECL_GROUP("xmss", test_wc_XmssKey_id_sigsleft), \ + TEST_DECL_GROUP("xmss", test_wc_XmssKey_id_verify), \ TEST_DECL_GROUP("xmss", test_wc_XmssKey_cb_only_no_device), \ TEST_DECL_GROUP("lms", test_rfc9802_lms_x509_verify), \ TEST_DECL_GROUP("xmss", test_rfc9802_xmss_x509_verify), \ diff --git a/wolfcrypt/src/wc_lms.c b/wolfcrypt/src/wc_lms.c index 1e335962d7..b3977a94ba 100644 --- a/wolfcrypt/src/wc_lms.c +++ b/wolfcrypt/src/wc_lms.c @@ -57,6 +57,16 @@ #include #endif +/* A key named by id, label or device context is held by a device. */ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_PRIVATE_KEY_ID) + #define LMS_KEY_ON_DEVICE(key) (((key)->devCtx != NULL) || \ + ((key)->idLen > 0) || ((key)->labelLen > 0)) +#elif defined(WOLF_CRYPTO_CB) + #define LMS_KEY_ON_DEVICE(key) ((key)->devCtx != NULL) +#else + #define LMS_KEY_ON_DEVICE(key) 0 +#endif + /* Calculate u. Appendix B. Works for w of 1, 2, 4, or 8. * @@ -2077,11 +2087,11 @@ int wc_LmsKey_Verify(LmsKey* key, const byte* sig, word32 sigSz, static const byte lms_empty_msg[] = {0}; msg = lms_empty_msg; } - /* Check state. */ + /* Check state. A key named by id may have only its parameters set. */ if ((ret == 0) && (key->state != WC_LMS_STATE_OK) && - (key->state != WC_LMS_STATE_VERIFYONLY)) { - /* LMS key not ready for verification. Param str must be - * set first, and Reload() called. */ + (key->state != WC_LMS_STATE_VERIFYONLY) && + ((key->state != WC_LMS_STATE_PARMSET) || + !LMS_KEY_ON_DEVICE(key))) { WOLFSSL_MSG("error: LMS key not ready for verification"); ret = BAD_STATE_E; } diff --git a/wolfcrypt/src/wc_xmss.c b/wolfcrypt/src/wc_xmss.c index e2dcbb9966..37d0876996 100644 --- a/wolfcrypt/src/wc_xmss.c +++ b/wolfcrypt/src/wc_xmss.c @@ -56,6 +56,16 @@ #include #endif +/* A key named by id, label or device context is held by a device. */ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_PRIVATE_KEY_ID) + #define XMSS_KEY_ON_DEVICE(key) (((key)->devCtx != NULL) || \ + ((key)->idLen > 0) || ((key)->labelLen > 0)) +#elif defined(WOLF_CRYPTO_CB) + #define XMSS_KEY_ON_DEVICE(key) ((key)->devCtx != NULL) +#else + #define XMSS_KEY_ON_DEVICE(key) 0 +#endif + #ifndef WOLF_CRYPTO_CB_ONLY_XMSS /*************************** * DIGEST init and free. @@ -2105,11 +2115,11 @@ int wc_XmssKey_Verify(XmssKey* key, const byte* sig, word32 sigLen, static const byte xmss_empty_msg[] = {0}; m = xmss_empty_msg; } - /* Validate state. */ + /* Validate state. A key named by id may have only its parameters set. */ if ((ret == 0) && (key->state != WC_XMSS_STATE_OK) && - (key->state != WC_XMSS_STATE_VERIFYONLY)) { - /* XMSS key not ready for verification. Param str must be - * set first, and Reload() called. */ + (key->state != WC_XMSS_STATE_VERIFYONLY) && + ((key->state != WC_XMSS_STATE_PARMSET) || + !XMSS_KEY_ON_DEVICE(key))) { WOLFSSL_MSG("error: XMSS key not ready for verification"); ret = BAD_STATE_E; }