#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#if defined(WOLFSSL_HAVE_LMS) && defined(HAVE_LIBLMS)
#include <wolfssl/wolfcrypt/ext_lms.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifndef WOLFSSL_LMS_VERIFY_ONLY
#define EXT_LMS_MAX_THREADS (4)
static THREAD_LS_T WC_RNG * LmsRng = NULL;
static bool LmsGenerateRand(void * output, size_t length)
{
int ret = 0;
if (output == NULL || LmsRng == NULL) {
return false;
}
if (length == 0) {
return true;
}
ret = wc_RNG_GenerateBlock(LmsRng, output, (word32) length);
if (ret) {
WOLFSSL_MSG("error: LmsGenerateRand failed");
return false;
}
return true;
}
static bool LmsWritePrivKey(unsigned char *private_key,
size_t len_private_key, void *lmsKey)
{
LmsKey * key = (LmsKey *) lmsKey;
enum wc_LmsRc ret = WC_LMS_RC_NONE;
if (private_key == NULL || key == NULL || len_private_key <= 0) {
WOLFSSL_MSG("error: LmsWritePrivKey: invalid args");
return false;
}
if (key->state != WC_LMS_STATE_PARMSET && key->state != WC_LMS_STATE_OK) {
WOLFSSL_MSG("error: LmsWritePrivKey: LMS key not in writeable state");
return false;
}
if (key->write_private_key == NULL) {
WOLFSSL_MSG("error: LmsWritePrivKey: LMS key write callback not set");
key->state = WC_LMS_STATE_BAD;
return false;
}
ret = key->write_private_key(private_key, (word32)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;
}
static bool LmsReadPrivKey(unsigned char *private_key,
size_t len_private_key, void *lmsKey)
{
LmsKey * key = (LmsKey *) lmsKey;
enum wc_LmsRc ret = WC_LMS_RC_NONE;
if (private_key == NULL || key == NULL || len_private_key <= 0) {
WOLFSSL_MSG("error: LmsReadPrivKey: invalid args");
return false;
}
if (key->state != WC_LMS_STATE_PARMSET && key->state != WC_LMS_STATE_OK) {
WOLFSSL_MSG("error: LmsReadPrivKey: LMS key not in readable state");
return false;
}
if (key->read_private_key == NULL) {
WOLFSSL_MSG("error: LmsReadPrivKey: LMS key read callback not set");
key->state = WC_LMS_STATE_BAD;
return false;
}
ret = key->read_private_key(private_key, (word32)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;
}
#endif
const char * wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm)
{
switch (lmsParm) {
case WC_LMS_PARM_NONE:
return "LMS/HSS NONE";
case WC_LMS_PARM_L1_H5_W1:
return "LMS/HSS L1_H5_W1";
case WC_LMS_PARM_L1_H5_W2:
return "LMS/HSS L1_H5_W2";
case WC_LMS_PARM_L1_H5_W4:
return "LMS/HSS L1_H5_W4";
case WC_LMS_PARM_L1_H5_W8:
return "LMS/HSS L1_H5_W8";
case WC_LMS_PARM_L1_H10_W2:
return "LMS/HSS L1_H10_W2";
case WC_LMS_PARM_L1_H10_W4:
return "LMS/HSS L1_H10_W4";
case WC_LMS_PARM_L1_H10_W8:
return "LMS/HSS L1_H10_W8";
case WC_LMS_PARM_L1_H15_W2:
return "LMS/HSS L1_H15_W2";
case WC_LMS_PARM_L1_H15_W4:
return "LMS/HSS L1_H15_W4";
case WC_LMS_PARM_L1_H15_W8:
return "LMS/HSS L1_H15_W8";
case WC_LMS_PARM_L1_H20_W2:
return "LMS/HSS L1_H20_W2";
case WC_LMS_PARM_L1_H20_W4:
return "LMS/HSS L1_H20_W4";
case WC_LMS_PARM_L1_H20_W8:
return "LMS/HSS L1_H20_W8";
case WC_LMS_PARM_L2_H5_W2:
return "LMS/HSS L2_H5_W2";
case WC_LMS_PARM_L2_H5_W4:
return "LMS/HSS L2_H5_W4";
case WC_LMS_PARM_L2_H5_W8:
return "LMS/HSS L2_H5_W8";
case WC_LMS_PARM_L2_H10_W2:
return "LMS/HSS L2_H10_W2";
case WC_LMS_PARM_L2_H10_W4:
return "LMS/HSS L2_H10_W4";
case WC_LMS_PARM_L2_H10_W8:
return "LMS/HSS L2_H10_W8";
case WC_LMS_PARM_L2_H15_W2:
return "LMS/HSS L2_H15_W2";
case WC_LMS_PARM_L2_H15_W4:
return "LMS/HSS L2_H15_W4";
case WC_LMS_PARM_L2_H15_W8:
return "LMS/HSS L2_H15_W8";
case WC_LMS_PARM_L2_H20_W2:
return "LMS/HSS L2_H20_W2";
case WC_LMS_PARM_L2_H20_W4:
return "LMS/HSS L2_H20_W4";
case WC_LMS_PARM_L2_H20_W8:
return "LMS/HSS L2_H20_W8";
case WC_LMS_PARM_L3_H5_W2:
return "LMS/HSS L3_H5_W2";
case WC_LMS_PARM_L3_H5_W4:
return "LMS/HSS L3_H5_W4";
case WC_LMS_PARM_L3_H5_W8:
return "LMS/HSS L3_H5_W8";
case WC_LMS_PARM_L3_H10_W4:
return "LMS/HSS L3_H10_W4";
case WC_LMS_PARM_L3_H10_W8:
return "LMS/HSS L3_H10_W8";
case WC_LMS_PARM_L4_H5_W2:
return "LMS/HSS L4_H5_W2";
case WC_LMS_PARM_L4_H5_W4:
return "LMS/HSS L4_H5_W4";
case WC_LMS_PARM_L4_H5_W8:
return "LMS/HSS L4_H5_W8";
case WC_LMS_PARM_L4_H10_W4:
return "LMS/HSS L4_H10_W4";
case WC_LMS_PARM_L4_H10_W8:
return "LMS/HSS L4_H10_W8";
default:
WOLFSSL_MSG("error: invalid LMS parameter");
break;
}
return "LMS_INVALID";
}
const char * wc_LmsKey_RcToStr(enum wc_LmsRc lmsEc)
{
switch (lmsEc) {
case WC_LMS_RC_NONE:
return "LMS_RC_NONE";
case WC_LMS_RC_BAD_ARG:
return "LMS_RC_BAD_ARG";
case WC_LMS_RC_WRITE_FAIL:
return "LMS_RC_WRITE_FAIL";
case WC_LMS_RC_READ_FAIL:
return "LMS_RC_READ_FAIL";
case WC_LMS_RC_SAVED_TO_NV_MEMORY:
return "LMS_RC_SAVED_TO_NV_MEMORY";
case WC_LMS_RC_READ_TO_MEMORY:
return "LMS_RC_READ_TO_MEMORY";
default:
WOLFSSL_MSG("error: invalid LMS error code");
break;
}
return "LMS_RC_INVALID";
}
int wc_LmsKey_Init(LmsKey * key, void * heap, int devId)
{
if (key == NULL) {
return BAD_FUNC_ARG;
}
(void) heap;
(void) devId;
ForceZero(key, sizeof(LmsKey));
#ifndef WOLFSSL_LMS_VERIFY_ONLY
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;
#endif
key->state = WC_LMS_STATE_INITED;
return 0;
}
int wc_LmsKey_SetLmsParm(LmsKey * key, enum wc_LmsParm lmsParm)
{
if (key == NULL) {
return BAD_FUNC_ARG;
}
switch (lmsParm) {
case WC_LMS_PARM_NONE:
case WC_LMS_PARM_L1_H5_W1:
return wc_LmsKey_SetParameters(key, 1, 5, 1);
case WC_LMS_PARM_L1_H5_W2:
return wc_LmsKey_SetParameters(key, 1, 5, 2);
case WC_LMS_PARM_L1_H5_W4:
return wc_LmsKey_SetParameters(key, 1, 5, 4);
case WC_LMS_PARM_L1_H5_W8:
return wc_LmsKey_SetParameters(key, 1, 5, 8);
case WC_LMS_PARM_L1_H10_W2:
return wc_LmsKey_SetParameters(key, 1, 10, 2);
case WC_LMS_PARM_L1_H10_W4:
return wc_LmsKey_SetParameters(key, 1, 10, 4);
case WC_LMS_PARM_L1_H10_W8:
return wc_LmsKey_SetParameters(key, 1, 10, 8);
case WC_LMS_PARM_L1_H15_W2:
return wc_LmsKey_SetParameters(key, 1, 15, 2);
case WC_LMS_PARM_L1_H15_W4:
return wc_LmsKey_SetParameters(key, 1, 15, 4);
case WC_LMS_PARM_L1_H15_W8:
return wc_LmsKey_SetParameters(key, 1, 15, 8);
case WC_LMS_PARM_L1_H20_W2:
return wc_LmsKey_SetParameters(key, 1, 20, 2);
case WC_LMS_PARM_L1_H20_W4:
return wc_LmsKey_SetParameters(key, 1, 20, 4);
case WC_LMS_PARM_L1_H20_W8:
return wc_LmsKey_SetParameters(key, 1, 20, 8);
case WC_LMS_PARM_L2_H5_W2:
return wc_LmsKey_SetParameters(key, 2, 5, 2);
case WC_LMS_PARM_L2_H5_W4:
return wc_LmsKey_SetParameters(key, 2, 5, 4);
case WC_LMS_PARM_L2_H5_W8:
return wc_LmsKey_SetParameters(key, 2, 5, 8);
case WC_LMS_PARM_L2_H10_W2:
return wc_LmsKey_SetParameters(key, 2, 10, 2);
case WC_LMS_PARM_L2_H10_W4:
return wc_LmsKey_SetParameters(key, 2, 10, 4);
case WC_LMS_PARM_L2_H10_W8:
return wc_LmsKey_SetParameters(key, 2, 10, 8);
case WC_LMS_PARM_L2_H15_W2:
return wc_LmsKey_SetParameters(key, 2, 15, 2);
case WC_LMS_PARM_L2_H15_W4:
return wc_LmsKey_SetParameters(key, 2, 15, 4);
case WC_LMS_PARM_L2_H15_W8:
return wc_LmsKey_SetParameters(key, 2, 15, 8);
case WC_LMS_PARM_L2_H20_W2:
return wc_LmsKey_SetParameters(key, 2, 20, 2);
case WC_LMS_PARM_L2_H20_W4:
return wc_LmsKey_SetParameters(key, 2, 20, 4);
case WC_LMS_PARM_L2_H20_W8:
return wc_LmsKey_SetParameters(key, 2, 20, 8);
case WC_LMS_PARM_L3_H5_W2:
return wc_LmsKey_SetParameters(key, 3, 5, 2);
case WC_LMS_PARM_L3_H5_W4:
return wc_LmsKey_SetParameters(key, 3, 5, 4);
case WC_LMS_PARM_L3_H5_W8:
return wc_LmsKey_SetParameters(key, 3, 5, 8);
case WC_LMS_PARM_L3_H10_W4:
return wc_LmsKey_SetParameters(key, 3, 10, 4);
case WC_LMS_PARM_L3_H10_W8:
return wc_LmsKey_SetParameters(key, 3, 10, 8);
case WC_LMS_PARM_L4_H5_W2:
return wc_LmsKey_SetParameters(key, 4, 5, 2);
case WC_LMS_PARM_L4_H5_W4:
return wc_LmsKey_SetParameters(key, 4, 5, 4);
case WC_LMS_PARM_L4_H5_W8:
return wc_LmsKey_SetParameters(key, 4, 5, 8);
case WC_LMS_PARM_L4_H10_W4:
return wc_LmsKey_SetParameters(key, 4, 10, 4);
case WC_LMS_PARM_L4_H10_W8:
return wc_LmsKey_SetParameters(key, 4, 10, 8);
default:
WOLFSSL_MSG("error: invalid LMS parameter set");
break;
}
return BAD_FUNC_ARG;
}
int wc_LmsKey_SetParameters(LmsKey * key, int levels, int height,
int winternitz)
{
int i = 0;
param_set_t lm = LMS_SHA256_N32_H5;
param_set_t ots = LMOTS_SHA256_N32_W1;
if (key == NULL) {
return BAD_FUNC_ARG;
}
if (key->state != WC_LMS_STATE_INITED) {
WOLFSSL_MSG("error: LmsKey needs init");
return -1;
}
if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS) {
WOLFSSL_MSG("error: invalid level parameter");
return BAD_FUNC_ARG;
}
if (height < MIN_MERKLE_HEIGHT || height > MAX_MERKLE_HEIGHT) {
WOLFSSL_MSG("error: invalid height parameter");
return BAD_FUNC_ARG;
}
switch (height) {
case 5:
lm = LMS_SHA256_N32_H5;
break;
case 10:
lm = LMS_SHA256_N32_H10;
break;
case 15:
lm = LMS_SHA256_N32_H15;
break;
case 20:
lm = LMS_SHA256_N32_H20;
break;
case 25:
lm = LMS_SHA256_N32_H25;
break;
default:
WOLFSSL_MSG("error: invalid height parameter");
return BAD_FUNC_ARG;
}
switch (winternitz) {
case 1:
ots = LMOTS_SHA256_N32_W1;
break;
case 2:
ots = LMOTS_SHA256_N32_W2;
break;
case 4:
ots = LMOTS_SHA256_N32_W4;
break;
case 8:
ots = LMOTS_SHA256_N32_W8;
break;
default:
WOLFSSL_MSG("error: invalid winternitz parameter");
return BAD_FUNC_ARG;
}
key->levels = levels;
for (i = 0; i < levels; ++i) {
key->lm_type[i] = lm;
key->lm_ots_type[i] = ots;
}
key->state = WC_LMS_STATE_PARMSET;
return 0;
}
int wc_LmsKey_GetParameters(const LmsKey * key, int * levels, int * height,
int * winternitz)
{
if (key == NULL || levels == NULL || height == NULL || winternitz == NULL) {
return BAD_FUNC_ARG;
}
if (key->levels < MIN_HSS_LEVELS || key->levels > MAX_HSS_LEVELS) {
WOLFSSL_MSG("error: LmsKey invalid level parameter");
return -1;
}
*levels = key->levels;
switch (key->lm_type[0]) {
case LMS_SHA256_N32_H5:
*height = 5;
break;
case LMS_SHA256_N32_H10:
*height = 10;
break;
case LMS_SHA256_N32_H15:
*height = 15;
break;
case LMS_SHA256_N32_H20:
*height = 20;
break;
case LMS_SHA256_N32_H25:
*height = 25;
break;
default:
WOLFSSL_MSG("error: LmsKey invalid height parameter");
return -1;
}
switch (key->lm_ots_type[0]) {
case LMOTS_SHA256_N32_W1:
*winternitz = 1;
break;
case LMOTS_SHA256_N32_W2:
*winternitz = 2;
break;
case LMOTS_SHA256_N32_W4:
*winternitz = 4;
break;
case LMOTS_SHA256_N32_W8:
*winternitz = 8;
break;
default:
WOLFSSL_MSG("error: LmsKey invalid winternitz parameter");
return -1;
}
return 0;
}
void wc_LmsKey_Free(LmsKey* key)
{
if (key == NULL) {
return;
}
#ifndef WOLFSSL_LMS_VERIFY_ONLY
if (key->working_key != NULL) {
hss_free_working_key(key->working_key);
key->working_key = NULL;
}
#endif
ForceZero(key, sizeof(LmsKey));
key->state = WC_LMS_STATE_FREED;
return;
}
#ifndef WOLFSSL_LMS_VERIFY_ONLY
int wc_LmsKey_SetWriteCb(LmsKey * key, wc_lms_write_private_key_cb write_cb)
{
if (key == NULL || write_cb == NULL) {
return BAD_FUNC_ARG;
}
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;
}
int wc_LmsKey_SetReadCb(LmsKey * key, wc_lms_read_private_key_cb read_cb)
{
if (key == NULL || read_cb == NULL) {
return BAD_FUNC_ARG;
}
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;
}
int wc_LmsKey_SetContext(LmsKey * key, void * context)
{
if (key == NULL || context == NULL) {
return BAD_FUNC_ARG;
}
if (key->state == WC_LMS_STATE_OK) {
WOLFSSL_MSG("error: wc_LmsKey_SetContext: key in use");
return -1;
}
key->context = context;
return 0;
}
int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
{
bool result = true;
if (key == NULL || rng == NULL) {
return BAD_FUNC_ARG;
}
if (key->state != WC_LMS_STATE_PARMSET) {
WOLFSSL_MSG("error: LmsKey not ready for generation");
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;
result = hss_generate_private_key(LmsGenerateRand, key->levels,
key->lm_type, key->lm_ots_type,
LmsWritePrivKey, key,
key->pub, sizeof(key->pub),
NULL, 0, &key->info);
if (!result) {
WOLFSSL_MSG("error: hss_generate_private_key failed");
key->state = WC_LMS_STATE_BAD;
return -1;
}
key->working_key = hss_load_private_key(LmsReadPrivKey, key,
0, NULL, 0, &key->info);
if (key->working_key == NULL) {
WOLFSSL_MSG("error: hss_load_private_key failed");
key->state = WC_LMS_STATE_BAD;
return -1;
}
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;
return 0;
}
int wc_LmsKey_Reload(LmsKey * key)
{
bool result = true;
if (key == NULL) {
return BAD_FUNC_ARG;
}
if (key->state != WC_LMS_STATE_PARMSET) {
WOLFSSL_MSG("error: LmsKey not ready for reload");
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);
if (key->working_key == NULL) {
WOLFSSL_MSG("error: hss_load_private_key failed");
key->state = WC_LMS_STATE_BAD;
return -1;
}
result = hss_get_parameter_set(&key->levels, key->lm_type,
key->lm_ots_type, LmsReadPrivKey, key);
if (!result) {
WOLFSSL_MSG("error: hss_get_parameter_set failed");
key->state = WC_LMS_STATE_BAD;
hss_free_working_key(key->working_key);
key->working_key = NULL;
return -1;
}
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;
return 0;
}
int wc_LmsKey_GetPrivLen(const LmsKey * key, word32 * len)
{
if (key == NULL || len == NULL) {
return BAD_FUNC_ARG;
}
*len = (word32) hss_get_private_key_len(key->levels, key->lm_type,
key->lm_ots_type);
return 0;
}
int wc_LmsKey_Sign(LmsKey* key, byte * sig, word32 * sigSz, const byte * msg,
int msgSz)
{
bool result = true;
size_t len = 0;
if (key == NULL || sig == NULL || sigSz == NULL || msg == NULL) {
return BAD_FUNC_ARG;
}
if (msgSz <= 0) {
return BAD_FUNC_ARG;
}
if (key->state == WC_LMS_STATE_NOSIGS) {
WOLFSSL_MSG("error: LMS signatures exhausted");
return -1;
}
else if (key->state != WC_LMS_STATE_OK) {
WOLFSSL_MSG("error: can't sign, LMS key not in good state");
return -1;
}
len = hss_get_signature_len(key->levels, key->lm_type, key->lm_ots_type);
if (len == 0) {
WOLFSSL_MSG("error: hss_get_signature_len failed");
key->state = WC_LMS_STATE_BAD;
return -1;
}
if ((size_t)*sigSz < len) {
WOLFSSL_MSG("error: LMS sig buffer too small");
return BUFFER_E;
}
if (key->write_private_key == NULL) {
WOLFSSL_MSG("error: LmsKey write/read callbacks are not set");
return BAD_FUNC_ARG;
}
if (key->context == NULL) {
WOLFSSL_MSG("error: LmsKey context is not set");
return BAD_FUNC_ARG;
}
result = hss_generate_signature(key->working_key, LmsWritePrivKey,
key, (const void *) msg, msgSz,
sig, len, &key->info);
if (!result) {
if (wc_LmsKey_SigsLeft(key) == 0) {
WOLFSSL_MSG("error: LMS signatures exhausted");
key->state = WC_LMS_STATE_NOSIGS;
return -1;
}
WOLFSSL_MSG("error: hss_generate_signature failed");
key->state = WC_LMS_STATE_BAD;
return -1;
}
*sigSz = (word32) len;
return 0;
}
int wc_LmsKey_SigsLeft(LmsKey * key)
{
if (key == NULL) {
return BAD_FUNC_ARG;
}
if (hss_extra_info_test_last_signature(&key->info)) {
return 0;
}
return 1;
}
#endif
int wc_LmsKey_GetPubLen(const LmsKey * key, word32 * len)
{
if (key == NULL || len == NULL) {
return BAD_FUNC_ARG;
}
*len = (word32) hss_get_public_key_len(key->levels, key->lm_type,
key->lm_ots_type);
return 0;
}
int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc)
{
if (keyDst == NULL || keySrc == NULL) {
return BAD_FUNC_ARG;
}
ForceZero(keyDst, sizeof(LmsKey));
XMEMCPY(keyDst->pub, keySrc->pub, sizeof(keySrc->pub));
XMEMCPY(keyDst->lm_type, keySrc->lm_type, sizeof(keySrc->lm_type));
XMEMCPY(keyDst->lm_ots_type, keySrc->lm_ots_type,
sizeof(keySrc->lm_ots_type));
keyDst->levels = keySrc->levels;
keyDst->state = WC_LMS_STATE_VERIFYONLY;
return 0;
}
int wc_LmsKey_ExportPubRaw(const LmsKey * key, byte * out, word32 * outLen)
{
int ret = 0;
word32 pubLen = 0;
if (key == NULL || out == NULL || outLen == NULL) {
return BAD_FUNC_ARG;
}
ret = wc_LmsKey_GetPubLen(key, &pubLen);
if (ret != 0) {
WOLFSSL_MSG("error: wc_LmsKey_GetPubLen failed");
return -1;
}
if (*outLen < pubLen) {
return BUFFER_E;
}
XMEMCPY(out, key->pub, pubLen);
*outLen = pubLen;
return 0;
}
int wc_LmsKey_ImportPubRaw(LmsKey * key, const byte * in, word32 inLen)
{
int ret = 0;
word32 pubLen = 0;
if (key == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
ret = wc_LmsKey_GetPubLen(key, &pubLen);
if (ret != 0) {
WOLFSSL_MSG("error: wc_LmsKey_GetPubLen failed");
return -1;
}
if (inLen != pubLen) {
return BUFFER_E;
}
XMEMCPY(key->pub, in, pubLen);
return 0;
}
int wc_LmsKey_GetSigLen(const LmsKey * key, word32 * len)
{
if (key == NULL || len == NULL) {
return BAD_FUNC_ARG;
}
*len = (word32) hss_get_signature_len(key->levels, key->lm_type,
key->lm_ots_type);
return 0;
}
int wc_LmsKey_Verify(LmsKey * key, const byte * sig, word32 sigSz,
const byte * msg, int msgSz)
{
bool result = true;
if (key == NULL || sig == NULL || msg == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_LMS_VERIFY_ONLY
result = hss_validate_signature(key->pub, (const void *) msg, msgSz, sig,
sigSz, NULL);
#else
result = hss_validate_signature(key->pub, (const void *) msg, msgSz, sig,
sigSz, &key->info);
#endif
if (!result) {
WOLFSSL_MSG("error: hss_validate_signature failed");
return -1;
}
return 0;
}
int wc_LmsKey_GetKid(LmsKey * key, const byte ** kid, word32* kidSz)
{
if ((key == NULL) || (kid == NULL) || (kidSz == NULL)) {
return BAD_FUNC_ARG;
}
return NOT_COMPILED_IN;
}
const byte * wc_LmsKey_GetKidFromPrivRaw(const byte * priv, word32 privSz)
{
if ((priv == NULL) || (privSz < 16)) {
return NULL;
}
return priv - 16;
}
#endif