forked from wolfSSL/wolfssl
LMS/HSS: cleanup, and safer write/read callbacks
This commit is contained in:
2
INSTALL
2
INSTALL
@ -276,7 +276,7 @@ We also have vcpkg ports for wolftpm, wolfmqtt and curl.
|
||||
$ git clone https://github.com/cisco/hash-sigs.git src
|
||||
$ cd src
|
||||
|
||||
In sha256.h, set USE_OPENSSl to 0:
|
||||
In sha256.h, set USE_OPENSSL to 0:
|
||||
#define USE_OPENSSL 0
|
||||
|
||||
Now build:
|
||||
|
@ -7818,6 +7818,23 @@ static const byte lms_pub_L4_H5_W8[60] =
|
||||
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)
|
||||
{
|
||||
LmsKey key;
|
||||
@ -7831,6 +7848,7 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
|
||||
int times = 0;
|
||||
int count = 0;
|
||||
double start = 0.0F;
|
||||
byte priv[HSS_MAX_PRIVATE_KEY_LEN];
|
||||
const char * str = wc_LmsKey_ParmToStr(parm);
|
||||
|
||||
ret = wc_LmsKey_Init(&key, parm);
|
||||
@ -7841,32 +7859,32 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
|
||||
|
||||
switch (parm) {
|
||||
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));
|
||||
break;
|
||||
|
||||
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));
|
||||
break;
|
||||
|
||||
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));
|
||||
break;
|
||||
|
||||
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));
|
||||
break;
|
||||
|
||||
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));
|
||||
break;
|
||||
|
||||
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));
|
||||
break;
|
||||
|
||||
@ -7880,6 +7898,24 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
|
||||
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
|
||||
* key before using it. Reloading the private key is the bottleneck
|
||||
* 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);
|
||||
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;
|
||||
|
@ -83,27 +83,20 @@ static bool LmsWritePrivKey(unsigned char *private_key,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (key->write_private_key != NULL) {
|
||||
/* Use write callback. */
|
||||
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;
|
||||
}
|
||||
if (key->write_private_key == NULL) {
|
||||
WOLFSSL_MSG("error: LmsWritePrivKey: LMS key write callback not set");
|
||||
key->state = WC_LMS_STATE_NOT_INITED;
|
||||
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));
|
||||
XMEMCPY(key->priv, private_key, len_private_key);
|
||||
/* Use write callback. */
|
||||
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;
|
||||
@ -128,26 +121,20 @@ static bool LmsReadPrivKey(unsigned char *private_key,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (key->read_private_key != NULL) {
|
||||
/* 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;
|
||||
}
|
||||
if (key->read_private_key == NULL) {
|
||||
WOLFSSL_MSG("error: LmsReadPrivKey: LMS key read callback not set");
|
||||
key->state = WC_LMS_STATE_NOT_INITED;
|
||||
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;
|
||||
@ -362,11 +349,6 @@ int wc_LmsKey_Init_ex(LmsKey * key, int levels, int height,
|
||||
|
||||
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->write_private_key = NULL;
|
||||
key->read_private_key = NULL;
|
||||
@ -407,6 +389,16 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
key->write_private_key = wf;
|
||||
key->write_private_key = write_cb;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
key->read_private_key = rf;
|
||||
key->read_private_key = read_cb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -499,6 +491,16 @@ int wc_LmsKey_Reload(LmsKey * key)
|
||||
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,
|
||||
0, NULL, 0, &key->info);
|
||||
|
||||
|
@ -34823,6 +34823,23 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t kyber_test(void)
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
int ret;
|
||||
@ -34834,6 +34851,7 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
|
||||
word32 sigSz = 0;
|
||||
const char * msg = "LMS HSS post quantum signature test";
|
||||
word32 msgSz = (word32) XSTRLEN(msg);
|
||||
unsigned char priv[HSS_MAX_PRIVATE_KEY_LEN];
|
||||
unsigned char old_priv[HSS_MAX_PRIVATE_KEY_LEN];
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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); }
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
if (ret != 0) { return WC_TEST_RET_ENC_I(i); }
|
||||
|
@ -50,7 +50,6 @@ struct LmsKey {
|
||||
unsigned levels; /* Number of tree levels. */
|
||||
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. */
|
||||
unsigned char priv[HSS_MAX_PRIVATE_KEY_LEN];
|
||||
unsigned char pub[HSS_MAX_PUBLIC_KEY_LEN];
|
||||
hss_working_key * working_key;
|
||||
write_private_key_cb write_private_key; /* Callback to write/update key. */
|
||||
|
@ -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_ex(LmsKey * key, int levels,
|
||||
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_SetReadCb(LmsKey * key, read_private_key_cb rf);
|
||||
WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key,
|
||||
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 void wc_LmsKey_Free(LmsKey * key);
|
||||
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 /* WOLFSSL_HAVE_LMS */
|
||||
|
||||
#endif /* WOLF_CRYPT_LMS_H */
|
||||
|
||||
|
Reference in New Issue
Block a user