mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-10-24 04:09:07 +03:00
Let an LMS/XMSS key named by id verify on a device without Reload
wc_LmsKey_Verify and wc_XmssKey_Verify accepted only a key in the OK or VERIFYONLY state before calling the device. A key from InitId or InitLabel with its parameters set is in PARMSET, and only Reload moves it on. A verify-only build compiles Reload out, so such a key could never verify, on any device. Accept PARMSET before the device call for a key named by id, label or device context. wolfHSM names a key cached on the HSM only by devCtx, with no id. Any other key in PARMSET has no public key anywhere and still gets BAD_STATE_E without reaching the device. Software still refuses an id key after the device declines, because a key in PARMSET never has a public key and the existing pubSet check returns BAD_STATE_E. test_wc_LmsKey_id_verify and test_wc_XmssKey_id_verify verify with such a key through a device, by id and by device context. They check that a key with neither gets BAD_STATE_E without the device being called, and that the id key fails without a device: BAD_STATE_E, or NO_VALID_DEVID in a callback-only build with no software verify. Both run in verify-only builds, so the guard of the verify callback they share now covers those builds.
This commit is contained in:
committed by
Paul Adelsbach
parent
007ee17cdf
commit
8ebafb02bd
@@ -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 <wolfssl/wolfcrypt/wc_lms.h>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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), \
|
||||
|
||||
@@ -57,6 +57,16 @@
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,16 @@
|
||||
#include <wolfssl/wolfcrypt/cryptocb.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user