LMS: comments, SMALL_STACK, cleanup, etc.

pull/6564/head
jordan 2023-07-14 11:27:59 -05:00
parent 4c125ece77
commit a747e7773c
5 changed files with 302 additions and 137 deletions

View File

@ -7851,12 +7851,18 @@ static void bench_lms_sign_verify(enum wc_LmsParm parm)
byte priv[HSS_MAX_PRIVATE_KEY_LEN]; 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, NULL, INVALID_DEVID);
if (ret) { if (ret) {
printf("wc_LmsKey_Init failed: %d\n", ret); printf("wc_LmsKey_Init failed: %d\n", ret);
goto exit_lms_sign_verify; goto exit_lms_sign_verify;
} }
ret = wc_LmsKey_SetLmsParm(&key, parm);
if (ret) {
printf("wc_LmsKey_SetLmsParm failed: %d\n", ret);
goto exit_lms_sign_verify;
}
switch (parm) { switch (parm) {
case WC_LMS_PARM_L2_H10_W2: case WC_LMS_PARM_L2_H10_W2:
XMEMCPY(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));

View File

@ -74,7 +74,9 @@ static bool LmsGenerateRand(void * output, size_t length)
return true; return true;
} }
/* Write callback passed into hash-sigs hss lib. */ /* Write callback passed into hash-sigs hss lib.
*
* Returns true on success. */
static bool LmsWritePrivKey(unsigned char *private_key, static bool LmsWritePrivKey(unsigned char *private_key,
size_t len_private_key, void *lmsKey) size_t len_private_key, void *lmsKey)
{ {
@ -86,20 +88,19 @@ static bool LmsWritePrivKey(unsigned char *private_key,
return false; return false;
} }
if (key->state != WC_LMS_STATE_INITED && key->state != WC_LMS_STATE_OK) { if (key->state != WC_LMS_STATE_PARMSET && key->state != WC_LMS_STATE_OK) {
/* The key had an error the last time it was used, and we /* The LmsKey is not ready for writing. */
* can't guarantee its state. */ WOLFSSL_MSG("error: LmsWritePrivKey: LMS key not in writeable state");
WOLFSSL_MSG("error: LmsWritePrivKey: LMS key not in good state");
return false; return false;
} }
if (key->write_private_key == NULL) { if (key->write_private_key == NULL) {
WOLFSSL_MSG("error: LmsWritePrivKey: LMS key write callback not set"); WOLFSSL_MSG("error: LmsWritePrivKey: LMS key write callback not set");
key->state = WC_LMS_STATE_NOT_INITED; key->state = WC_LMS_STATE_BAD;
return false; return false;
} }
/* Use write callback. */ /* Use write callback that saves private key to non-volatile storage. */
ret = key->write_private_key(private_key, len_private_key, key->context); ret = key->write_private_key(private_key, len_private_key, key->context);
if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) { if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) {
@ -112,7 +113,9 @@ static bool LmsWritePrivKey(unsigned char *private_key,
return true; return true;
} }
/* Read callback passed into hash-sigs hss lib. */ /* Read callback passed into hash-sigs hss lib.
*
* Returns true on success. */
static bool LmsReadPrivKey(unsigned char *private_key, static bool LmsReadPrivKey(unsigned char *private_key,
size_t len_private_key, void *lmsKey) size_t len_private_key, void *lmsKey)
{ {
@ -124,20 +127,19 @@ static bool LmsReadPrivKey(unsigned char *private_key,
return false; return false;
} }
if (key->state != WC_LMS_STATE_INITED && key->state != WC_LMS_STATE_OK) { if (key->state != WC_LMS_STATE_PARMSET && key->state != WC_LMS_STATE_OK) {
/* The key had an error the last time it was used, and we /* The LmsKey is not ready for reading. */
* can't guarantee its state. */ WOLFSSL_MSG("error: LmsReadPrivKey: LMS key not in readable state");
WOLFSSL_MSG("error: LmsReadPrivKey: LMS key not in good state");
return false; return false;
} }
if (key->read_private_key == NULL) { if (key->read_private_key == NULL) {
WOLFSSL_MSG("error: LmsReadPrivKey: LMS key read callback not set"); WOLFSSL_MSG("error: LmsReadPrivKey: LMS key read callback not set");
key->state = WC_LMS_STATE_NOT_INITED; key->state = WC_LMS_STATE_BAD;
return false; return false;
} }
/* Use read callback. */ /* Use read callback that reads private key from non-volatile storage. */
ret = key->read_private_key(private_key, len_private_key, key->context); ret = key->read_private_key(private_key, len_private_key, key->context);
if (ret != WC_LMS_RC_READ_TO_MEMORY) { if (ret != WC_LMS_RC_READ_TO_MEMORY) {
@ -223,45 +225,83 @@ const char * wc_LmsKey_RcToStr(enum wc_LmsRc lmsEc)
return "LMS_RC_INVALID"; return "LMS_RC_INVALID";
} }
int wc_LmsKey_Init(LmsKey * key, enum wc_LmsParm lmsParm) /* Init an LMS key.
*
* Call this before setting the parms of an LMS key.
*
* Returns 0 on success.
* */
int wc_LmsKey_Init(LmsKey * key, void * heap, int devId)
{ {
if (key == NULL) { if (key == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
(void) heap;
(void) devId;
ForceZero(key, sizeof(LmsKey));
/* Set the max number of worker threads that hash-sigs can spawn. */
hss_init_extra_info(&key->info);
hss_extra_info_set_threads(&key->info, EXT_LMS_MAX_THREADS);
key->working_key = NULL;
key->write_private_key = NULL;
key->read_private_key = NULL;
key->context = NULL;
key->state = WC_LMS_STATE_INITED;
return 0;
}
/* Set the wc_LmsParm of an LMS key.
*
* Use this if you wish to set a key with a predefined parameter set,
* such as WC_LMS_PARM_L2_H10_W8.
*
* Key must be inited before calling this.
*
* Returns 0 on success.
* */
int wc_LmsKey_SetLmsParm(LmsKey * key, enum wc_LmsParm lmsParm)
{
if (key == NULL) {
return BAD_FUNC_ARG;
}
/* If NONE is passed, default to the lowest predefined set. */
switch (lmsParm) { switch (lmsParm) {
case WC_LMS_PARM_NONE: case WC_LMS_PARM_NONE:
return wc_LmsKey_Init_ex(key, 1, 15, 2, NULL, INVALID_DEVID);
case WC_LMS_PARM_L1_H15_W2: case WC_LMS_PARM_L1_H15_W2:
return wc_LmsKey_Init_ex(key, 1, 15, 2, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 1, 15, 2);
case WC_LMS_PARM_L1_H15_W4: case WC_LMS_PARM_L1_H15_W4:
return wc_LmsKey_Init_ex(key, 1, 15, 4, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 1, 15, 4);
case WC_LMS_PARM_L2_H10_W2: case WC_LMS_PARM_L2_H10_W2:
return wc_LmsKey_Init_ex(key, 2, 10, 2, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 2, 10, 2);
case WC_LMS_PARM_L2_H10_W4: case WC_LMS_PARM_L2_H10_W4:
return wc_LmsKey_Init_ex(key, 2, 10, 4, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 2, 10, 4);
case WC_LMS_PARM_L2_H10_W8: case WC_LMS_PARM_L2_H10_W8:
return wc_LmsKey_Init_ex(key, 2, 10, 8, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 2, 10, 8);
case WC_LMS_PARM_L3_H5_W2: case WC_LMS_PARM_L3_H5_W2:
return wc_LmsKey_Init_ex(key, 3, 5, 2, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 3, 5, 2);
case WC_LMS_PARM_L3_H5_W4: case WC_LMS_PARM_L3_H5_W4:
return wc_LmsKey_Init_ex(key, 3, 5, 4, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 3, 5, 4);
case WC_LMS_PARM_L3_H5_W8: case WC_LMS_PARM_L3_H5_W8:
return wc_LmsKey_Init_ex(key, 3, 5, 8, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 3, 5, 8);
case WC_LMS_PARM_L3_H10_W4: case WC_LMS_PARM_L3_H10_W4:
return wc_LmsKey_Init_ex(key, 3, 10, 4, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 3, 10, 4);
case WC_LMS_PARM_L4_H5_W8: case WC_LMS_PARM_L4_H5_W8:
return wc_LmsKey_Init_ex(key, 4, 5, 8, NULL, INVALID_DEVID); return wc_LmsKey_SetParameters(key, 4, 5, 8);
default: default:
WOLFSSL_MSG("error: invalid LMS parameter set"); WOLFSSL_MSG("error: invalid LMS parameter set");
@ -271,46 +311,47 @@ int wc_LmsKey_Init(LmsKey * key, enum wc_LmsParm lmsParm)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
int wc_LmsKey_Init_ex(LmsKey * key, int levels, int height, /* Set the parameters of an LMS key.
int winternitz, void* heap, int devId) *
* Use this if you wish to set specific parameters not found in the
* wc_LmsParm predefined sets. See comments in lms.h for allowed
* parameters.
*
* Key must be inited before calling this.
*
* Returns 0 on success.
* */
int wc_LmsKey_SetParameters(LmsKey * key, int levels, int height,
int winternitz)
{ {
int ret = 0;
int i = 0; int i = 0;
param_set_t lm = LMS_SHA256_N32_H5; param_set_t lm = LMS_SHA256_N32_H5;
param_set_t ots = LMOTS_SHA256_N32_W8; param_set_t ots = LMOTS_SHA256_N32_W1;
(void) heap;
(void) devId;
key->state = WC_LMS_STATE_NOT_INITED;
if (key == NULL) { if (key == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
ForceZero(key, sizeof(LmsKey)); if (key->state != WC_LMS_STATE_INITED) {
WOLFSSL_MSG("error: LmsKey needs init");
/* Verify inputs make sense. Values of 0 may be passed to signify return -1;
* using minimum defaults. */
if (levels == 0) {
levels = MIN_HSS_LEVELS;
} }
else if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS) {
/* Verify inputs make sense.
*
* Note: there does not seem to be a define for min or
* max Winternitz integer in hash-sigs lib or RFC8554. */
if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS) {
WOLFSSL_MSG("error: invalid level parameter"); WOLFSSL_MSG("error: invalid level parameter");
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
if (height == 0) { if (height < MIN_MERKLE_HEIGHT || height > MAX_MERKLE_HEIGHT) {
height = MIN_MERKLE_HEIGHT;
}
else if (height < MIN_MERKLE_HEIGHT || height > MAX_MERKLE_HEIGHT) {
WOLFSSL_MSG("error: invalid height parameter"); WOLFSSL_MSG("error: invalid height parameter");
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
if (winternitz == 0) {
winternitz = 2;
}
switch (height) { switch (height) {
case 5: case 5:
lm = LMS_SHA256_N32_H5; lm = LMS_SHA256_N32_H5;
@ -357,19 +398,17 @@ int wc_LmsKey_Init_ex(LmsKey * key, int levels, int height,
key->lm_ots_type[i] = ots; key->lm_ots_type[i] = ots;
} }
/* Set the max number of worker threads that hash-sigs can spawn. */ /* Move the state to parms set.
hss_init_extra_info(&key->info); * Key is ready for MakeKey or Reload. */
hss_extra_info_set_threads(&key->info, EXT_LMS_MAX_THREADS); key->state = WC_LMS_STATE_PARMSET;
key->working_key = NULL; return 0;
key->write_private_key = NULL;
key->read_private_key = NULL;
key->context = NULL;
key->state = WC_LMS_STATE_INITED;
return ret;
} }
/* Frees the LMS key from memory.
*
* This does not affect the private key saved to non-volatile storage.
* */
void wc_LmsKey_Free(LmsKey* key) void wc_LmsKey_Free(LmsKey* key)
{ {
if (key == NULL) { if (key == NULL) {
@ -383,12 +422,91 @@ void wc_LmsKey_Free(LmsKey* key)
ForceZero(key, sizeof(LmsKey)); ForceZero(key, sizeof(LmsKey));
key->state = WC_LMS_STATE_NOT_INITED; key->state = WC_LMS_STATE_FREED;
return; return;
} }
int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng) /* Set the write private key callback to the LMS key structure.
*
* The callback must be able to write/update the private key to
* non-volatile storage.
*
* Returns 0 on success.
* */
int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb write_cb)
{
if (key == NULL || write_cb == NULL) {
return BAD_FUNC_ARG;
}
/* Changing the write callback of an already working key is forbidden. */
if (key->state == WC_LMS_STATE_OK) {
WOLFSSL_MSG("error: wc_LmsKey_SetWriteCb: key in use");
return -1;
}
key->write_private_key = write_cb;
return 0;
}
/* Set the read private key callback to the LMS key structure.
*
* The callback must be able to read the private key from
* non-volatile storage.
*
* Returns 0 on success.
* */
int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb read_cb)
{
if (key == NULL || read_cb == NULL) {
return BAD_FUNC_ARG;
}
/* Changing the read callback of an already working key is forbidden. */
if (key->state == WC_LMS_STATE_OK) {
WOLFSSL_MSG("error: wc_LmsKey_SetReadCb: key in use");
return -1;
}
key->read_private_key = read_cb;
return 0;
}
/* Sets the context to be used by write and read callbacks.
*
* E.g. this could be a filename if the callbacks write/read to file.
*
* Returns 0 on success.
* */
int wc_LmsKey_SetContext(LmsKey * key, void * context)
{
if (key == NULL || context == NULL) {
return BAD_FUNC_ARG;
}
/* Setting context of an already working key is forbidden. */
if (key->state == WC_LMS_STATE_OK) {
WOLFSSL_MSG("error: wc_LmsKey_SetContext: key in use");
return -1;
}
key->context = context;
return 0;
}
/* Make the LMS private/public key pair. The key must have its parameters
* set before calling this.
*
* Write/read callbacks, and context data, must be set prior.
* Key must have parameters set.
*
* Returns 0 on success.
* */
int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
{ {
bool result = true; bool result = true;
@ -396,7 +514,7 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
if (key->state != WC_LMS_STATE_INITED) { if (key->state != WC_LMS_STATE_PARMSET) {
WOLFSSL_MSG("error: LmsKey not ready for generation"); WOLFSSL_MSG("error: LmsKey not ready for generation");
return -1; return -1;
} }
@ -427,6 +545,9 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
* DYNAMIC_TYPE_TMP_BUFFER); * DYNAMIC_TYPE_TMP_BUFFER);
*/ */
/* First generate the private key using the parameters and callbacks.
* If successful, private key will be saved to non-volatile storage,
* and the public key will be in memory. */
result = hss_generate_private_key(LmsGenerateRand, key->levels, result = hss_generate_private_key(LmsGenerateRand, key->levels,
key->lm_type, key->lm_ots_type, key->lm_type, key->lm_ots_type,
LmsWritePrivKey, key, LmsWritePrivKey, key,
@ -439,6 +560,8 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
return -1; return -1;
} }
/* Once generated, now we must load the private key so we have
* an hss working key for signing operations. */
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);
@ -448,48 +571,25 @@ int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
return -1; return -1;
} }
/* This should not happen, but check just in case. */
if (wc_LmsKey_SigsLeft(key) == 0) {
WOLFSSL_MSG("error: generated LMS key signatures exhausted");
key->state = WC_LMS_STATE_NOSIGS;
return -1;
}
key->state = WC_LMS_STATE_OK; key->state = WC_LMS_STATE_OK;
return 0; return 0;
} }
int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb write_cb) /* Reload a key that has been prepared with the appropriate parms and
{ * data. Use this if you wish to resume signing with an existing key.
if (key == NULL || write_cb == NULL) { *
return BAD_FUNC_ARG; * Write/read callbacks, and context data, must be set prior.
} * Key must have parameters set.
*
key->write_private_key = write_cb; * Returns 0 on success. */
return 0;
}
int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb read_cb)
{
if (key == NULL || read_cb == NULL) {
return BAD_FUNC_ARG;
}
key->read_private_key = read_cb;
return 0;
}
/* Sets the context to be used by write and read callbacks.
* E.g. this could be a filename if the callbacks write/read to file. */
int wc_LmsKey_SetContext(LmsKey * key, void * context)
{
if (key == NULL || context == NULL) {
return BAD_FUNC_ARG;
}
key->context = context;
return 0;
}
/* Reload a key that has been prepared with the appropriate read callbacks
* or data. */
int wc_LmsKey_Reload(LmsKey * key) int wc_LmsKey_Reload(LmsKey * key)
{ {
bool result = true; bool result = true;
@ -498,7 +598,7 @@ int wc_LmsKey_Reload(LmsKey * key)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
if (key->state != WC_LMS_STATE_INITED) { if (key->state != WC_LMS_STATE_PARMSET) {
WOLFSSL_MSG("error: LmsKey not ready for reload"); WOLFSSL_MSG("error: LmsKey not ready for reload");
return -1; return -1;
} }
@ -533,6 +633,13 @@ int wc_LmsKey_Reload(LmsKey * key)
return -1; return -1;
} }
/* Double check the key actually has signatures left. */
if (wc_LmsKey_SigsLeft(key) == 0) {
WOLFSSL_MSG("error: reloaded LMS key signatures exhausted");
key->state = WC_LMS_STATE_NOSIGS;
return -1;
}
key->state = WC_LMS_STATE_OK; key->state = WC_LMS_STATE_OK;
return 0; return 0;
@ -540,7 +647,7 @@ int wc_LmsKey_Reload(LmsKey * key)
/* Given a levels, height, winternitz parameter set, determine /* Given a levels, height, winternitz parameter set, determine
* the private key length */ * the private key length */
int wc_LmsKey_GetPrivLen(LmsKey * key, word32 * len) int wc_LmsKey_GetPrivLen(LmsKey * key, word32 * len)
{ {
if (key == NULL || len == NULL) { if (key == NULL || len == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@ -554,7 +661,7 @@ int wc_LmsKey_GetPrivLen(LmsKey * key, word32 * len)
/* Given a levels, height, winternitz parameter set, determine /* Given a levels, height, winternitz parameter set, determine
* the public key length */ * the public key length */
int wc_LmsKey_GetPubLen(LmsKey * key, word32 * len) int wc_LmsKey_GetPubLen(LmsKey * key, word32 * len)
{ {
if (key == NULL || len == NULL) { if (key == NULL || len == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@ -566,9 +673,14 @@ int wc_LmsKey_GetPubLen(LmsKey * key, word32 * len)
return 0; return 0;
} }
/* Export a generated public key. Use this to prepare a signature verification /* Export a generated public key and parameter set from one LmsKey
* key that is pub only. */ * to another. Use this to prepare a signature verification LmsKey
int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc) * that is pub only.
*
* Though the public key is all that is used to verify signatures,
* the parameter set is needed to calculate the signature length
* before hand. */
int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc)
{ {
if (keyDst == NULL || keySrc == NULL) { if (keyDst == NULL || keySrc == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@ -582,7 +694,9 @@ int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc)
sizeof(keySrc->lm_ots_type)); sizeof(keySrc->lm_ots_type));
keyDst->levels = keySrc->levels; keyDst->levels = keySrc->levels;
keyDst->state = keySrc->state;
/* Mark this key as verify only, to prevent misuse. */
keyDst->state = WC_LMS_STATE_VERIFYONLY;
return 0; return 0;
} }
@ -591,8 +705,8 @@ int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc)
* the signature length. * the signature length.
* *
* Call this before wc_LmsKey_Sign so you know the length of * Call this before wc_LmsKey_Sign so you know the length of
* the required sig buffer. */ * the required signature buffer. */
int wc_LmsKey_GetSigLen(LmsKey * key, word32 * len) int wc_LmsKey_GetSigLen(LmsKey * key, word32 * len)
{ {
if (key == NULL || len == NULL) { if (key == NULL || len == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@ -679,18 +793,18 @@ int wc_LmsKey_Verify(LmsKey * key, const byte * sig, word32 sigSz,
return 0; return 0;
} }
int wc_LmsKey_SigsLeft(LmsKey * key)
{
/* Returns 1 if there are signatures remaining.
* Returns 0 if available signatures are exhausted.
*
* Note: the number of remaining signatures is hidden behind an opaque
* pointer in the hash-sigs lib. We could add a counter here that is
* decremented on every signature. The number of available signatures
* grows as
* N = 2 ** (levels * height)
* so it would need to be a big integer. */
/* Returns 1 if there are signatures remaining.
* Returns 0 if available signatures are exhausted.
*
* Note: the number of remaining signatures is hidden behind an opaque
* pointer in the hash-sigs lib. We could add a counter here that is
* decremented on every signature. The number of available signatures
* grows as
* N = 2 ** (levels * height)
* so it would need to be a big integer. */
int wc_LmsKey_SigsLeft(LmsKey * key)
{
if (key == NULL) { if (key == NULL) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }

View File

@ -34840,6 +34840,10 @@ static int lms_read_key_mem(byte * priv, word32 privSz, void *context)
return WC_LMS_RC_READ_TO_MEMORY; return WC_LMS_RC_READ_TO_MEMORY;
} }
/* LMS signature sizes are a function of their parameters. This
* test has a signature of 8688 bytes. */
#define WC_TEST_LMS_SIG_LEN (8688)
WOLFSSL_TEST_SUBROUTINE int lms_test(void) WOLFSSL_TEST_SUBROUTINE int lms_test(void)
{ {
int ret; int ret;
@ -34847,13 +34851,22 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
LmsKey signingKey; LmsKey signingKey;
LmsKey verifyKey; LmsKey verifyKey;
WC_RNG rng; WC_RNG rng;
byte sig[8688];
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 priv[HSS_MAX_PRIVATE_KEY_LEN];
unsigned char old_priv[HSS_MAX_PRIVATE_KEY_LEN]; unsigned char old_priv[HSS_MAX_PRIVATE_KEY_LEN];
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
byte * sig = XMALLOC(WC_TEST_LMS_SIG_LEN, HEAP_HINT,
DYNAMIC_TYPE_TMP_BUFFER);
if (sig == NULL) {
return WC_TEST_RET_ENC_ERRNO;
}
#else
byte sig[WC_TEST_LMS_SIG_LEN];
#endif
XMEMSET(priv, 0, sizeof(priv));
XMEMSET(old_priv, 0, sizeof(old_priv)); XMEMSET(old_priv, 0, sizeof(old_priv));
#ifndef HAVE_FIPS #ifndef HAVE_FIPS
@ -34863,7 +34876,7 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
#endif #endif
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); } if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
/* /* This test:
* levels: 1 * levels: 1
* height: 5 * height: 5
* winternitz: 1 * winternitz: 1
@ -34871,7 +34884,14 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
* max sigs: 2 ** (1 * 5) = 32 * max sigs: 2 ** (1 * 5) = 32
* signature length: 8688 * signature length: 8688
*/ */
ret = wc_LmsKey_Init_ex(&signingKey, 1, 5, 1, NULL, INVALID_DEVID);
ret = wc_LmsKey_Init(&signingKey, NULL, INVALID_DEVID);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
ret = wc_LmsKey_Init(&verifyKey, NULL, INVALID_DEVID);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
ret = wc_LmsKey_SetParameters(&signingKey, 1, 5, 1);
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); ret = wc_LmsKey_SetWriteCb(&signingKey, lms_write_key_mem);
@ -34894,8 +34914,8 @@ WOLFSSL_TEST_SUBROUTINE int lms_test(void)
ret = wc_LmsKey_GetSigLen(&verifyKey, &sigSz); ret = wc_LmsKey_GetSigLen(&verifyKey, &sigSz);
if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); } if (ret != 0) { return WC_TEST_RET_ENC_EC(ret); }
if (sigSz != sizeof(sig)) { if (sigSz != WC_TEST_LMS_SIG_LEN) {
printf("error: got %d, expected %zu\n", sigSz, sizeof(sig)); printf("error: got %d, expected %d\n", sigSz, WC_TEST_LMS_SIG_LEN);
return WC_TEST_RET_ENC_EC(sigSz); return WC_TEST_RET_ENC_EC(sigSz);
} }

View File

@ -73,7 +73,10 @@ enum wc_LmsRc {
* of available signatures is the same. * of available signatures is the same.
* */ * */
/* Predefined LMS/HSS parameter sets for convenience. */ /* Predefined LMS/HSS parameter sets for convenience.
*
* Not predefining a set with Winternitz=1, because the signatures
* will be large. */
enum wc_LmsParm { enum wc_LmsParm {
WC_LMS_PARM_NONE = 0, WC_LMS_PARM_NONE = 0,
WC_LMS_PARM_L1_H15_W2 = 1, /* 1 level Merkle tree of 15 height. */ WC_LMS_PARM_L1_H15_W2 = 1, /* 1 level Merkle tree of 15 height. */
@ -88,22 +91,24 @@ enum wc_LmsParm {
WC_LMS_PARM_L4_H5_W8 = 10, /* 4 level Merkle tree of 5 height. */ WC_LMS_PARM_L4_H5_W8 = 10, /* 4 level Merkle tree of 5 height. */
}; };
/* enum wc_LmsState is to help track the state of an LMS/HSS Key. */
enum wc_LmsState { enum wc_LmsState {
WC_LMS_STATE_OK = 0, WC_LMS_STATE_FREED, /* Key has been freed from memory. */
WC_LMS_STATE_NOT_INITED = 1, WC_LMS_STATE_INITED, /* Key has been inited, ready to set parms.*/
WC_LMS_STATE_INITED = 2, WC_LMS_STATE_PARMSET, /* Parms are set, ready to MakeKey or Reload. */
WC_LMS_STATE_BAD = 3, /* Can't guarantee key's state. */ WC_LMS_STATE_OK, /* Able to sign signatures and verify. */
WC_LMS_STATE_NOSIGS = 4, /* Signatures exhausted. */ WC_LMS_STATE_VERIFYONLY, /* A public only LmsKey. */
WC_LMS_STATE_BAD, /* Can't guarantee key's state. */
WC_LMS_STATE_NOSIGS /* Signatures exhausted. */
}; };
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Need an update_key_cb setting function. WOLFSSL_API int wc_LmsKey_Init(LmsKey * key, void * heap, int devId);
* Also maybe a generate rand cb setter. */ WOLFSSL_API int wc_LmsKey_SetLmsParm(LmsKey * key, enum wc_LmsParm lmsParm);
WOLFSSL_API int wc_LmsKey_Init(LmsKey * key, enum wc_LmsParm lmsParm); WOLFSSL_API int wc_LmsKey_SetParameters(LmsKey * key, int levels,
WOLFSSL_API int wc_LmsKey_Init_ex(LmsKey * key, int levels, int height, int winternitz);
int height, int winternitz, void* heap, int devId);
WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key, WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key,
write_private_key_cb write_cb); write_private_key_cb write_cb);
WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key, WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key,

View File

@ -1,3 +1,23 @@
/* wc_lms.h
*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#error "Contact wolfSSL to get the implementation of this file" #error "Contact wolfSSL to get the implementation of this file"