LMS/HSS: cleanup, and safer write/read callbacks

This commit is contained in:
jordan
2023-07-07 15:30:50 -05:00
parent 67bef21185
commit 55bbd5865c
6 changed files with 127 additions and 69 deletions

View File

@@ -276,7 +276,7 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl.
$ git clone https://github.com/cisco/hash-sigs.git src $ git clone https://github.com/cisco/hash-sigs.git src
$ cd src $ cd src
In sha256.h, set USE_OPENSSl to 0: In sha256.h, set USE_OPENSSL to 0:
#define USE_OPENSSL 0 #define USE_OPENSSL 0
Now build: Now build:

View File

@@ -7818,6 +7818,23 @@ static const byte lms_pub_L4_H5_W8[60] =
0x74,0x24,0x12,0xC8 0x74,0x24,0x12,0xC8
}; };
static int lms_write_key_mem(const byte * priv, word32 privSz, void *context)
{
/* WARNING: THIS IS AN INSECURE WRITE CALLBACK THAT SHOULD ONLY
* BE USED FOR TESTING PURPOSES! Production applications should
* write only to non-volatile storage. */
XMEMCPY(context, priv, privSz);
return WC_LMS_RC_SAVED_TO_NV_MEMORY;
}
static int lms_read_key_mem(byte * priv, word32 privSz, void *context)
{
/* WARNING: THIS IS AN INSECURE READ CALLBACK THAT SHOULD ONLY
* BE USED FOR TESTING PURPOSES! */
XMEMCPY(priv, context, privSz);
return WC_LMS_RC_READ_TO_MEMORY;
}
static void bench_lms_sign_verify(enum wc_LmsParm parm) static void bench_lms_sign_verify(enum wc_LmsParm parm)
{ {
LmsKey key; LmsKey key;
@@ -7831,6 +7848,7 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
int times = 0; int times = 0;
int count = 0; int count = 0;
double start = 0.0F; double start = 0.0F;
byte priv[HSS_MAX_PRIVATE_KEY_LEN];
const char * str = wc_LmsKey_ParmToStr(parm); const char * str = wc_LmsKey_ParmToStr(parm);
ret = wc_LmsKey_Init(&key, parm); ret = wc_LmsKey_Init(&key, parm);
@@ -7841,32 +7859,32 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
switch (parm) { switch (parm) {
case WC_LMS_PARM_L2_H10_W2: case WC_LMS_PARM_L2_H10_W2:
XMEMCPY(key.priv, lms_priv_L2_H10_W2, sizeof(lms_priv_L2_H10_W2)); XMEMCPY(priv, lms_priv_L2_H10_W2, sizeof(lms_priv_L2_H10_W2));
XMEMCPY(key.pub, lms_pub_L2_H10_W2, sizeof(lms_pub_L2_H10_W2)); XMEMCPY(key.pub, lms_pub_L2_H10_W2, sizeof(lms_pub_L2_H10_W2));
break; break;
case WC_LMS_PARM_L2_H10_W4: case WC_LMS_PARM_L2_H10_W4:
XMEMCPY(key.priv, lms_priv_L2_H10_W4, sizeof(lms_priv_L2_H10_W4)); XMEMCPY(priv, lms_priv_L2_H10_W4, sizeof(lms_priv_L2_H10_W4));
XMEMCPY(key.pub, lms_pub_L2_H10_W4, sizeof(lms_pub_L2_H10_W4)); XMEMCPY(key.pub, lms_pub_L2_H10_W4, sizeof(lms_pub_L2_H10_W4));
break; break;
case WC_LMS_PARM_L3_H5_W4: case WC_LMS_PARM_L3_H5_W4:
XMEMCPY(key.priv, lms_priv_L3_H5_W4, sizeof(lms_priv_L3_H5_W4)); XMEMCPY(priv, lms_priv_L3_H5_W4, sizeof(lms_priv_L3_H5_W4));
XMEMCPY(key.pub, lms_pub_L3_H5_W4, sizeof(lms_pub_L3_H5_W4)); XMEMCPY(key.pub, lms_pub_L3_H5_W4, sizeof(lms_pub_L3_H5_W4));
break; break;
case WC_LMS_PARM_L3_H5_W8: case WC_LMS_PARM_L3_H5_W8:
XMEMCPY(key.priv, lms_priv_L3_H5_W8, sizeof(lms_priv_L3_H5_W8)); XMEMCPY(priv, lms_priv_L3_H5_W8, sizeof(lms_priv_L3_H5_W8));
XMEMCPY(key.pub, lms_pub_L3_H5_W8, sizeof(lms_pub_L3_H5_W8)); XMEMCPY(key.pub, lms_pub_L3_H5_W8, sizeof(lms_pub_L3_H5_W8));
break; break;
case WC_LMS_PARM_L3_H10_W4: case WC_LMS_PARM_L3_H10_W4:
XMEMCPY(key.priv, lms_priv_L3_H10_W4, sizeof(lms_priv_L3_H10_W4)); XMEMCPY(priv, lms_priv_L3_H10_W4, sizeof(lms_priv_L3_H10_W4));
XMEMCPY(key.pub, lms_pub_L3_H10_W4, sizeof(lms_pub_L3_H10_W4)); XMEMCPY(key.pub, lms_pub_L3_H10_W4, sizeof(lms_pub_L3_H10_W4));
break; break;
case WC_LMS_PARM_L4_H5_W8: case WC_LMS_PARM_L4_H5_W8:
XMEMCPY(key.priv, lms_priv_L4_H5_W8, sizeof(lms_priv_L4_H5_W8)); XMEMCPY(priv, lms_priv_L4_H5_W8, sizeof(lms_priv_L4_H5_W8));
XMEMCPY(key.pub, lms_pub_L4_H5_W8, sizeof(lms_pub_L4_H5_W8)); XMEMCPY(key.pub, lms_pub_L4_H5_W8, sizeof(lms_pub_L4_H5_W8));
break; break;
@@ -7880,6 +7898,24 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
goto exit_lms_sign_verify; goto exit_lms_sign_verify;
} }
ret = wc_LmsKey_SetWriteCb(&key, lms_write_key_mem);
if (ret) {
fprintf(stderr, "error: wc_LmsKey_SetWriteCb failed: %d\n", ret);
goto exit_lms_sign_verify;
}
ret = wc_LmsKey_SetReadCb(&key, lms_read_key_mem);
if (ret) {
fprintf(stderr, "error: wc_LmsKey_SetReadCb failed: %d\n", ret);
goto exit_lms_sign_verify;
}
ret = wc_LmsKey_SetContext(&key, (void *) priv);
if (ret) {
fprintf(stderr, "error: wc_LmsKey_SetContext failed: %d\n", ret);
goto exit_lms_sign_verify;
}
/* Even with saved priv/pub keys, we must still reload the private /* Even with saved priv/pub keys, we must still reload the private
* key before using it. Reloading the private key is the bottleneck * key before using it. Reloading the private key is the bottleneck
* for larger heights. Only print load time in debug builds. */ * for larger heights. Only print load time in debug builds. */
@@ -7933,12 +7969,6 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
printf("wc_LmsKey_Sign failed: %d\n", ret); printf("wc_LmsKey_Sign failed: %d\n", ret);
goto exit_lms_sign_verify; goto exit_lms_sign_verify;
} }
/*ret = wc_LmsKey_Verify(&key, sig, sigSz, (byte *) msg, msgSz);
if (ret) {
printf("wc_LmsKey_Verify failed: %d\n", ret);
goto exit_lms_sign_verify;
}*/
} }
count += times; count += times;

View File

@@ -83,27 +83,20 @@ static bool LmsWritePrivKey(unsigned char *private_key,
return false; return false;
} }
if (key->write_private_key != NULL) { if (key->write_private_key == NULL) {
/* Use write callback. */ WOLFSSL_MSG("error: LmsWritePrivKey: LMS key write callback not set");
ret = key->write_private_key(private_key, len_private_key, key->context); key->state = WC_LMS_STATE_NOT_INITED;
return false;
if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) {
WOLFSSL_MSG("error: LmsKey write_private_key failed");
WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
key->state = WC_LMS_STATE_BAD;
return false;
}
} }
else {
/* Save to memory. */
if (len_private_key > sizeof(key->priv)) {
WOLFSSL_MSG("error: LmsWritePrivKey: private key too large");
key->state = WC_LMS_STATE_BAD;
return false;
}
XMEMSET(key->priv, 0, sizeof(key->priv)); /* Use write callback. */
XMEMCPY(key->priv, private_key, len_private_key); ret = key->write_private_key(private_key, len_private_key, key->context);
if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) {
WOLFSSL_MSG("error: LmsKey write_private_key failed");
WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
key->state = WC_LMS_STATE_BAD;
return false;
} }
return true; return true;
@@ -128,26 +121,20 @@ static bool LmsReadPrivKey(unsigned char *private_key,
return false; return false;
} }
if (key->read_private_key != NULL) { if (key->read_private_key == NULL) {
/* Use read callback. */ WOLFSSL_MSG("error: LmsReadPrivKey: LMS key read callback not set");
ret = key->read_private_key(private_key, len_private_key, key->context); key->state = WC_LMS_STATE_NOT_INITED;
return false;
if (ret != WC_LMS_RC_READ_TO_MEMORY) {
WOLFSSL_MSG("error: LmsKey read_private_key failed");
WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
key->state = WC_LMS_STATE_BAD;
return false;
}
} }
else {
/* Read from memory. */
if (len_private_key > sizeof(key->priv)) {
WOLFSSL_MSG("error: LmsReadPrivKey: private key too large");
key->state = WC_LMS_STATE_BAD;
return false;
}
XMEMCPY(private_key, key->priv, len_private_key); /* Use read callback. */
ret = key->read_private_key(private_key, len_private_key, key->context);
if (ret != WC_LMS_RC_READ_TO_MEMORY) {
WOLFSSL_MSG("error: LmsKey read_private_key failed");
WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
key->state = WC_LMS_STATE_BAD;
return false;
} }
return true; return true;
@@ -362,11 +349,6 @@ int wc_LmsKey_Init_ex(LmsKey * key, int levels, int height,
hss_init_extra_info(&key->info); hss_init_extra_info(&key->info);
/* The hash-sigs lib API will accept either:
* 1. private key callbacks with context pointer, or
* 2. context that points at private key.
* Do the 2nd by default, unless user sets the callbacks through API. */
key->working_key = NULL; key->working_key = NULL;
key->write_private_key = NULL; key->write_private_key = NULL;
key->read_private_key = NULL; key->read_private_key = NULL;
@@ -407,6 +389,16 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
return -1; return -1;
} }
if (key->write_private_key == NULL || key->read_private_key == NULL) {
WOLFSSL_MSG("error: LmsKey write/read callbacks are not set");
return -1;
}
if (key->context == NULL) {
WOLFSSL_MSG("error: LmsKey context is not set");
return -1;
}
LmsRng = rng; LmsRng = rng;
/* todo: The has-sigs lib allows you to save variable length auxiliary /* todo: The has-sigs lib allows you to save variable length auxiliary
@@ -449,24 +441,24 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
return 0; return 0;
} }
int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb wf) int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb write_cb)
{ {
if (key == NULL || wf == NULL) { if (key == NULL || write_cb == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
key->write_private_key = wf; key->write_private_key = write_cb;
return 0; return 0;
} }
int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb rf) int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb read_cb)
{ {
if (key == NULL || rf == NULL) { if (key == NULL || read_cb == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
key->read_private_key = rf; key->read_private_key = read_cb;
return 0; return 0;
} }
@@ -499,6 +491,16 @@ int wc_LmsKey_Reload(LmsKey * key)
return -1; return -1;
} }
if (key->write_private_key == NULL || key->read_private_key == NULL) {
WOLFSSL_MSG("error: LmsKey write/read callbacks are not set");
return -1;
}
if (key->context == NULL) {
WOLFSSL_MSG("error: LmsKey context is not set");
return -1;
}
key->working_key = hss_load_private_key(LmsReadPrivKey, key, key->working_key = hss_load_private_key(LmsReadPrivKey, key,
0, NULL, 0, &key->info); 0, NULL, 0, &key->info);

View File

@@ -34823,6 +34823,23 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void)
#ifdef WOLFSSL_HAVE_LMS #ifdef WOLFSSL_HAVE_LMS
static int lms_write_key_mem(const byte * priv, word32 privSz, void *context)
{
/* WARNING: THIS IS AN INSECURE WRITE CALLBACK THAT SHOULD ONLY
* BE USED FOR TESTING PURPOSES! Production applications should
* write only to non-volatile storage. */
XMEMCPY(context, priv, privSz);
return WC_LMS_RC_SAVED_TO_NV_MEMORY;
}
static int lms_read_key_mem(byte * priv, word32 privSz, void *context)
{
/* WARNING: THIS IS AN INSECURE READ CALLBACK THAT SHOULD ONLY
* BE USED FOR TESTING PURPOSES! */
XMEMCPY(priv, context, privSz);
return WC_LMS_RC_READ_TO_MEMORY;
}
WOLFSSL_TEST_SUBROUTINE int lms_test(void) WOLFSSL_TEST_SUBROUTINE int lms_test(void)
{ {
int ret; int ret;
@@ -34834,6 +34851,7 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
word32 sigSz = 0; word32 sigSz = 0;
const char * msg = "LMS HSS post quantum signature test"; const char * msg = "LMS HSS post quantum signature test";
word32 msgSz = (word32) XSTRLEN(msg); word32 msgSz = (word32) XSTRLEN(msg);
unsigned char priv[HSS_MAX_PRIVATE_KEY_LEN];
unsigned char old_priv[HSS_MAX_PRIVATE_KEY_LEN]; unsigned char old_priv[HSS_MAX_PRIVATE_KEY_LEN];
XMEMSET(old_priv, 0, sizeof(old_priv)); XMEMSET(old_priv, 0, sizeof(old_priv));
@@ -34856,10 +34874,19 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
ret = wc_LmsKey_Init_ex(&signingKey, 1, 5, 1, NULL, INVALID_DEVID); ret = wc_LmsKey_Init_ex(&signingKey, 1, 5, 1, NULL, INVALID_DEVID);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); } if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
ret = wc_LmsKey_SetWriteCb(&signingKey, lms_write_key_mem);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
ret = wc_LmsKey_SetReadCb(&signingKey, lms_read_key_mem);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
ret = wc_LmsKey_SetContext(&signingKey, (void *) priv);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
ret = wc_LmsKey_MakeKey(&signingKey, &rng); ret = wc_LmsKey_MakeKey(&signingKey, &rng);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); } if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
XMEMCPY(old_priv, signingKey.priv, sizeof(signingKey.priv)); XMEMCPY(old_priv, priv, sizeof(priv));
ret = wc_LmsKey_ExportPub(&verifyKey, &signingKey); ret = wc_LmsKey_ExportPub(&verifyKey, &signingKey);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); } if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
@@ -34885,12 +34912,12 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
if (ret != 0) { return WC_TEST_RET_ENC_I(i); } if (ret != 0) { return WC_TEST_RET_ENC_I(i); }
/* The updated private key should not match the old one. */ /* The updated private key should not match the old one. */
if (XMEMCMP(old_priv, signingKey.priv, sizeof(signingKey.priv)) == 0) { if (XMEMCMP(old_priv, priv, sizeof(priv)) == 0) {
printf("error: current priv key should not match old: %zu\n", i); printf("error: current priv key should not match old: %zu\n", i);
return WC_TEST_RET_ENC_I(i); return WC_TEST_RET_ENC_I(i);
} }
XMEMCPY(old_priv, signingKey.priv, sizeof(signingKey.priv)); XMEMCPY(old_priv, priv, sizeof(priv));
ret = wc_LmsKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz); ret = wc_LmsKey_Verify(&verifyKey, sig, sigSz, (byte *) msg, msgSz);
if (ret != 0) { return WC_TEST_RET_ENC_I(i); } if (ret != 0) { return WC_TEST_RET_ENC_I(i); }

View File

@@ -50,7 +50,6 @@ struct LmsKey {
unsigned levels; /* Number of tree levels. */ unsigned levels; /* Number of tree levels. */
param_set_t lm_type[MAX_HSS_LEVELS]; /* Height parm per level. */ param_set_t lm_type[MAX_HSS_LEVELS]; /* Height parm per level. */
param_set_t lm_ots_type[MAX_HSS_LEVELS]; /* Winternitz parm per level. */ param_set_t lm_ots_type[MAX_HSS_LEVELS]; /* Winternitz parm per level. */
unsigned char priv[HSS_MAX_PRIVATE_KEY_LEN];
unsigned char pub[HSS_MAX_PUBLIC_KEY_LEN]; unsigned char pub[HSS_MAX_PUBLIC_KEY_LEN];
hss_working_key * working_key; hss_working_key * working_key;
write_private_key_cb write_private_key; /* Callback to write/update key. */ write_private_key_cb write_private_key; /* Callback to write/update key. */

View File

@@ -104,8 +104,10 @@ enum wc_LmsState {
WOLFSSL_API int wc_LmsKey_Init(LmsKey * key, enum wc_LmsParm lmsParm); WOLFSSL_API int wc_LmsKey_Init(LmsKey * key, enum wc_LmsParm lmsParm);
WOLFSSL_API int wc_LmsKey_Init_ex(LmsKey * key, int levels, WOLFSSL_API int wc_LmsKey_Init_ex(LmsKey * key, int levels,
int height, int winternitz, void* heap, int devId); int height, int winternitz, void* heap, int devId);
WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb wf); WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key,
WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb rf); write_private_key_cb write_cb);
WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key,
read_private_key_cb read_cb);
WOLFSSL_API int wc_LmsKey_SetContext(LmsKey * key, void * context); WOLFSSL_API int wc_LmsKey_SetContext(LmsKey * key, void * context);
WOLFSSL_API void wc_LmsKey_Free(LmsKey * key); WOLFSSL_API void wc_LmsKey_Free(LmsKey * key);
WOLFSSL_API int wc_LmsKey_MakeKey(LmsKey * key, WC_RNG * rng); WOLFSSL_API int wc_LmsKey_MakeKey(LmsKey * key, WC_RNG * rng);
@@ -126,6 +128,4 @@ WOLFSSL_API const char * wc_LmsKey_RcToStr(enum wc_LmsRc lmsRc);
#endif #endif
#endif /* WOLFSSL_HAVE_LMS */ #endif /* WOLFSSL_HAVE_LMS */
#endif /* WOLF_CRYPT_LMS_H */ #endif /* WOLF_CRYPT_LMS_H */