#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#ifdef WOLFSSL_HAVE_XMSS
#include <wolfssl/wolfcrypt/wc_xmss.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
static int wc_xmss_digest_init(XmssState* state)
{
int ret;
word8 hash = state->params->hash;
#ifdef WC_XMSS_SHA256
if (hash == WC_HASH_TYPE_SHA256) {
ret = wc_InitSha256(&state->digest.sha256);
}
else
#endif
#ifdef WC_XMSS_SHA512
if (hash == WC_HASH_TYPE_SHA512) {
ret = wc_InitSha512(&state->digest.sha512);
}
else
#endif
#ifdef WC_XMSS_SHAKE128
if (hash == WC_HASH_TYPE_SHAKE128) {
ret = wc_InitShake128(&state->digest.shake, NULL, INVALID_DEVID);
}
else
#endif
#ifdef WC_XMSS_SHAKE256
if (hash == WC_HASH_TYPE_SHAKE256) {
ret = wc_InitShake256(&state->digest.shake, NULL, INVALID_DEVID);
}
else
#endif
{
ret = NOT_COMPILED_IN;
}
return ret;
}
static void wc_xmss_digest_free(XmssState* state)
{
word8 hash = state->params->hash;
#ifdef WC_XMSS_SHA256
if (hash == WC_HASH_TYPE_SHA256) {
wc_Sha256Free(&state->digest.sha256);
}
else
#endif
#ifdef WC_XMSS_SHA512
if (hash == WC_HASH_TYPE_SHA512) {
wc_Sha512Free(&state->digest.sha512);
}
else
#endif
#ifdef WC_XMSS_SHAKE128
if (hash == WC_HASH_TYPE_SHAKE128) {
wc_Shake128_Free(&state->digest.shake);
}
else
#endif
#ifdef WC_XMSS_SHAKE256
if (hash == WC_HASH_TYPE_SHAKE256) {
wc_Shake256_Free(&state->digest.shake);
}
else
#endif
{
}
}
static WC_INLINE int wc_xmss_state_init(XmssState* state,
const XmssParams* params)
{
state->params = params;
state->ret = 0;
return wc_xmss_digest_init(state);
}
static WC_INLINE void wc_xmss_state_free(XmssState* state)
{
wc_xmss_digest_free(state);
}
typedef struct wc_XmssString {
#ifdef WOLFSSL_NAMES_STATIC
const char str[32];
#else
const char* str;
#endif
word32 oid;
XmssParams params;
} wc_XmssString;
#ifndef WOLFSSL_WC_XMSS_SMALL
#define XMSS_BDS_NUMS_SZ 4
#define XMSS_TREEHASH_SZ 4
#define XMSS_SK_LEN(n, h, d, s, i, k) \
(((i) + 4 * (n)) + \
(2 * (d) - 1) * (((s) + 1) * (n) + \
(s) + 1 + \
(s) * (n) + \
((s) >> 1) * (n) + \
((s) - (k)) * XMSS_TREEHASH_SZ + \
((s) - (k)) * (n) + \
XMSS_RETAIN_LEN(k, n) + \
XMSS_BDS_NUMS_SZ) + \
((d) - 1) * (n) * ((n) * 2 + 3))
#else
#define XMSS_SK_LEN(n, h, d, s, i, k) \
((i) + 4 * (n))
#endif
#ifndef WOLFSSL_XMSS_LARGE_SECRET_KEY
#define XMSS_K(k, kl) (k)
#else
#define XMSS_K(k, kl) (kl)
#endif
#define XMSS_PARAMS(hash, n, p, h, d, i, k, kl) \
{ hash, n, p, (n) * 2 + 3, (n) * ((n) * 2 + 3), h, (h) / (d), (d), (i), \
(i) + (n) + (d) * (((n) * 2 + 3) * (n)) + (h) * (n), \
XMSS_SK_LEN(n, h, d, ((h) / (d)), i, XMSS_K(k, kl)), (n) * 2, \
XMSS_K(k, kl) }
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20
static const wc_XmssString wc_xmss_alg[] = {
#ifdef WC_XMSS_SHA256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256
#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10
{ "XMSS-SHA2_10_256", WC_XMSS_OID_SHA2_10_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 10, 1, 4, 0, 4), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16
{ "XMSS-SHA2_16_256", WC_XMSS_OID_SHA2_16_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 16, 1, 4, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSS-SHA2_20_256", WC_XMSS_OID_SHA2_20_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 20, 1, 4, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHA512
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 512 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512
#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10
{ "XMSS-SHA2_10_512", WC_XMSS_OID_SHA2_10_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 10, 1, 4, 0, 4), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16
{ "XMSS-SHA2_16_512", WC_XMSS_OID_SHA2_16_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 16, 1, 4, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSS-SHA2_20_512", WC_XMSS_OID_SHA2_20_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 20, 1, 4, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHAKE128
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256
#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10
{ "XMSS-SHAKE_10_256", WC_XMSS_OID_SHAKE_10_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 10, 1, 4, 0, 4), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16
{ "XMSS-SHAKE_16_256", WC_XMSS_OID_SHAKE_16_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 16, 1, 4, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSS-SHAKE_20_256", WC_XMSS_OID_SHAKE_20_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 20, 1, 4, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHAKE256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 512 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512
#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10
{ "XMSS-SHAKE_10_512", WC_XMSS_OID_SHAKE_10_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 10, 1, 4, 0, 4), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16
{ "XMSS-SHAKE_16_512", WC_XMSS_OID_SHAKE_16_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 16, 1, 4, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSS-SHAKE_20_512", WC_XMSS_OID_SHAKE_20_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 20, 1, 4, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHA256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192
#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10
{ "XMSS-SHA2_10_192", WC_XMSS_OID_SHA2_10_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 10, 1, 4, 0, 4), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16
{ "XMSS-SHA2_16_192", WC_XMSS_OID_SHA2_16_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 16, 1, 4, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSS-SHA2_20_192", WC_XMSS_OID_SHA2_20_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 20, 1, 4, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHAKE256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256
#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10
{ "XMSS-SHAKE256_10_256", WC_XMSS_OID_SHAKE256_10_256,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 10, 1, 4, 0, 4), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16
{ "XMSS-SHAKE256_16_256", WC_XMSS_OID_SHAKE256_16_256,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 16, 1, 4, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSS-SHAKE256_20_256", WC_XMSS_OID_SHAKE256_20_256,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 20, 1, 4, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHAKE256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192
#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10
{ "XMSS-SHAKE256_10_192", WC_XMSS_OID_SHAKE256_10_192,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 10, 1, 4, 0, 4), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16
{ "XMSS-SHAKE256_16_192", WC_XMSS_OID_SHAKE256_16_192,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 16, 1, 4, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSS-SHAKE256_20_192", WC_XMSS_OID_SHAKE256_20_192,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 20, 1, 4, 0, 0), },
#endif
#endif
#endif
};
#define WC_XMSS_ALG_LEN (sizeof(wc_xmss_alg) / sizeof(*wc_xmss_alg))
#endif
static int wc_xmss_str_to_params(const char *s, word32* oid,
const XmssParams** params)
{
int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20
unsigned int i;
ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
for (i = 0; i < WC_XMSS_ALG_LEN; i++) {
if (XSTRCMP(s, wc_xmss_alg[i].str) == 0) {
*oid = wc_xmss_alg[i].oid;
*params = &wc_xmss_alg[i].params;
ret = 0;
break;
}
}
#else
(void)s;
(void)oid;
(void)params;
ret = NOT_COMPILED_IN;
#endif
return ret;
}
#if WOLFSSL_XMSS_MAX_HEIGHT >= 20
static const wc_XmssString wc_xmssmt_alg[] = {
#ifdef WC_XMSS_SHA256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSSMT-SHA2_20/2_256", WC_XMSSMT_OID_SHA2_20_2_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 20, 2, 3, 2, 4), },
{ "XMSSMT-SHA2_20/4_256", WC_XMSSMT_OID_SHA2_20_4_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 20, 4, 3, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40
{ "XMSSMT-SHA2_40/2_256", WC_XMSSMT_OID_SHA2_40_2_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 40, 2, 5, 2, 4), },
{ "XMSSMT-SHA2_40/4_256", WC_XMSSMT_OID_SHA2_40_4_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 40, 4, 5, 2, 4), },
{ "XMSSMT-SHA2_40/8_256", WC_XMSSMT_OID_SHA2_40_8_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 40, 8, 5, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60
{ "XMSSMT-SHA2_60/3_256", WC_XMSSMT_OID_SHA2_60_3_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 60, 3, 8, 2, 4), },
{ "XMSSMT-SHA2_60/6_256", WC_XMSSMT_OID_SHA2_60_6_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 60, 6, 8, 2, 4), },
{ "XMSSMT-SHA2_60/12_256", WC_XMSSMT_OID_SHA2_60_12_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 60, 12, 8, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHA512
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 512 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSSMT-SHA2_20/2_512", WC_XMSSMT_OID_SHA2_20_2_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 20, 2, 3, 2, 4), },
{ "XMSSMT-SHA2_20/4_512", WC_XMSSMT_OID_SHA2_20_4_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 20, 4, 3, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40
{ "XMSSMT-SHA2_40/2_512", WC_XMSSMT_OID_SHA2_40_2_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 40, 2, 5, 2, 4), },
{ "XMSSMT-SHA2_40/4_512", WC_XMSSMT_OID_SHA2_40_4_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 40, 4, 5, 2, 4), },
{ "XMSSMT-SHA2_40/8_512", WC_XMSSMT_OID_SHA2_40_8_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 40, 8, 5, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60
{ "XMSSMT-SHA2_60/3_512", WC_XMSSMT_OID_SHA2_60_3_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 60, 3, 8, 2, 4), },
{ "XMSSMT-SHA2_60/6_512", WC_XMSSMT_OID_SHA2_60_6_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 60, 6, 8, 2, 4), },
{ "XMSSMT-SHA2_60/12_512", WC_XMSSMT_OID_SHA2_60_12_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 60, 12, 8, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHAKE128
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSSMT-SHAKE_20/2_256", WC_XMSSMT_OID_SHAKE_20_2_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 20, 2, 3, 2, 4), },
{ "XMSSMT-SHAKE_20/4_256", WC_XMSSMT_OID_SHAKE_20_4_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 20, 4, 3, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40
{ "XMSSMT-SHAKE_40/2_256", WC_XMSSMT_OID_SHAKE_40_2_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 40, 2, 5, 2, 4), },
{ "XMSSMT-SHAKE_40/4_256", WC_XMSSMT_OID_SHAKE_40_4_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 40, 4, 5, 2, 4), },
{ "XMSSMT-SHAKE_40/8_256", WC_XMSSMT_OID_SHAKE_40_8_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 40, 8, 5, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60
{ "XMSSMT-SHAKE_60/3_256", WC_XMSSMT_OID_SHAKE_60_3_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 60, 3, 8, 2, 4), },
{ "XMSSMT-SHAKE_60/6_256", WC_XMSSMT_OID_SHAKE_60_6_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 60, 6, 8, 2, 4), },
{ "XMSSMT-SHAKE_60/12_256", WC_XMSSMT_OID_SHAKE_60_12_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 60, 12, 8, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHAKE256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 512 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSSMT-SHAKE_20/2_512", WC_XMSSMT_OID_SHAKE_20_2_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 20, 2, 3, 2, 4), },
{ "XMSSMT-SHAKE_20/4_512", WC_XMSSMT_OID_SHAKE_20_4_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 20, 4, 3, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40
{ "XMSSMT-SHAKE_40/2_512", WC_XMSSMT_OID_SHAKE_40_2_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 40, 2, 5, 2, 4), },
{ "XMSSMT-SHAKE_40/4_512", WC_XMSSMT_OID_SHAKE_40_4_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 40, 4, 5, 2, 4), },
{ "XMSSMT-SHAKE_40/8_512", WC_XMSSMT_OID_SHAKE_40_8_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 40, 8, 5, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60
{ "XMSSMT-SHAKE_60/3_512", WC_XMSSMT_OID_SHAKE_60_3_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 60, 3, 8, 2, 4), },
{ "XMSSMT-SHAKE_60/6_512", WC_XMSSMT_OID_SHAKE_60_6_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 60, 6, 8, 2, 4), },
{ "XMSSMT-SHAKE_60/12_512", WC_XMSSMT_OID_SHAKE_60_12_512 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 60, 12, 8, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHA256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSSMT-SHA2_20/2_192", WC_XMSSMT_OID_SHA2_20_2_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 20, 2, 3, 2, 4), },
{ "XMSSMT-SHA2_20/4_192", WC_XMSSMT_OID_SHA2_20_4_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 20, 4, 3, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40
{ "XMSSMT-SHA2_40/2_192", WC_XMSSMT_OID_SHA2_40_2_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 40, 2, 5, 2, 4), },
{ "XMSSMT-SHA2_40/4_192", WC_XMSSMT_OID_SHA2_40_4_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 40, 4, 5, 2, 4), },
{ "XMSSMT-SHA2_40/8_192", WC_XMSSMT_OID_SHA2_40_8_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 40, 8, 5, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60
{ "XMSSMT-SHA2_60/3_192", WC_XMSSMT_OID_SHA2_60_3_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 60, 3, 8, 2, 4), },
{ "XMSSMT-SHA2_60/6_192", WC_XMSSMT_OID_SHA2_60_6_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 60, 6, 8, 2, 4), },
{ "XMSSMT-SHA2_60/12_192", WC_XMSSMT_OID_SHA2_60_12_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 60, 12, 8, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHAKE256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSSMT-SHAKE256_20/2_256", WC_XMSSMT_OID_SHAKE256_20_2_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 20, 2, 3, 2, 4), },
{ "XMSSMT-SHAKE256_20/4_256", WC_XMSSMT_OID_SHAKE256_20_4_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 20, 4, 3, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40
{ "XMSSMT-SHAKE256_40/2_256", WC_XMSSMT_OID_SHAKE256_40_2_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 40, 2, 5, 2, 4), },
{ "XMSSMT-SHAKE256_40/4_256", WC_XMSSMT_OID_SHAKE256_40_4_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 40, 4, 5, 2, 4), },
{ "XMSSMT-SHAKE256_40/8_256", WC_XMSSMT_OID_SHAKE256_40_8_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 40, 8, 5, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60
{ "XMSSMT-SHAKE256_60/3_256", WC_XMSSMT_OID_SHAKE256_60_3_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 60, 3, 8, 2, 4), },
{ "XMSSMT-SHAKE256_60/6_256", WC_XMSSMT_OID_SHAKE256_60_6_256 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 60, 6, 8, 2, 4), },
{ "XMSSMT-SHAKE256_60/12_256", WC_XMSSMT_OID_SHAKE256_60_12_256,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 60, 12, 8, 0, 0), },
#endif
#endif
#endif
#ifdef WC_XMSS_SHAKE256
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192
#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20
{ "XMSSMT-SHAKE256_20/2_192", WC_XMSSMT_OID_SHAKE256_20_2_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 20, 2, 3, 2, 4), },
{ "XMSSMT-SHAKE256_20/4_192", WC_XMSSMT_OID_SHAKE256_20_4_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 20, 4, 3, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40
{ "XMSSMT-SHAKE256_40/2_192", WC_XMSSMT_OID_SHAKE256_40_2_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 40, 2, 5, 2, 4), },
{ "XMSSMT-SHAKE256_40/4_192", WC_XMSSMT_OID_SHAKE256_40_4_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 40, 4, 5, 2, 4), },
{ "XMSSMT-SHAKE256_40/8_192", WC_XMSSMT_OID_SHAKE256_40_8_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 40, 8, 5, 0, 0), },
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60
{ "XMSSMT-SHAKE256_60/3_192", WC_XMSSMT_OID_SHAKE256_60_3_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 60, 3, 8, 2, 4), },
{ "XMSSMT-SHAKE256_60/6_192", WC_XMSSMT_OID_SHAKE256_60_6_192 ,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 60, 6, 8, 2, 4), },
{ "XMSSMT-SHAKE256_60/12_192", WC_XMSSMT_OID_SHAKE256_60_12_192,
XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 60, 12, 8, 0, 0), },
#endif
#endif
#endif
};
#define WC_XMSSMT_ALG_LEN (sizeof(wc_xmssmt_alg) / sizeof(*wc_xmssmt_alg))
#endif
static int wc_xmssmt_str_to_params(const char *s, word32* oid,
const XmssParams** params)
{
int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
#if WOLFSSL_XMSS_MAX_HEIGHT >= 20
unsigned int i;
ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN);
for (i = 0; i < WC_XMSSMT_ALG_LEN; i++) {
if (XSTRCMP(s, wc_xmssmt_alg[i].str) == 0) {
*oid = wc_xmssmt_alg[i].oid;
*params = &wc_xmssmt_alg[i].params;
ret = 0;
break;
}
}
#else
(void)s;
(void)oid;
(void)params;
ret = NOT_COMPILED_IN;
#endif
return ret;
}
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
static int wc_xmsskey_alloc_sk(XmssKey* key)
{
int ret = 0;
if (key == NULL) {
ret = BAD_FUNC_ARG;
}
else if (key->sk != NULL) {
WOLFSSL_MSG("error: XMSS secret key already exists");
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
ret = wc_XmssKey_GetPrivLen(key, &key->sk_len);
}
if (ret == 0) {
key->sk = (unsigned char *)XMALLOC(key->sk_len, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (key->sk == NULL) {
WOLFSSL_MSG("error: malloc XMSS key->sk failed");
ret = MEMORY_E;
}
}
if (ret == 0) {
ForceZero(key->sk, key->sk_len);
}
return ret;
}
static WC_INLINE int wc_xmsskey_signupdate(XmssKey* key, byte* sig,
const byte* msg, int msgLen)
{
int ret = 0;
enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
key->state = WC_XMSS_STATE_BAD;
cb_rc = key->read_private_key(key->sk, key->sk_len, key->context);
if (cb_rc != WC_XMSS_RC_READ_TO_MEMORY) {
WOLFSSL_MSG("error: XMSS read_private_key failed");
ret = IO_FAILED_E;
}
if (ret == 0) {
WC_DECLARE_VAR(state, XmssState, 1, 0);
WC_ALLOC_VAR_EX(state, XmssState, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER,
ret=MEMORY_E);
if (WC_VAR_OK(state))
{
ret = wc_xmss_state_init(state, key->params);
if (ret == 0) {
#ifndef WOLFSSL_WC_XMSS_SMALL
if (key->is_xmssmt) {
ret = wc_xmssmt_sign(state, msg, msgLen, key->sk, sig);
}
else {
ret = wc_xmss_sign(state, msg, msgLen, key->sk, sig);
}
#else
ret = wc_xmssmt_sign(state, msg, msgLen, key->sk, sig);
#endif
if (ret == WC_NO_ERR_TRACE(KEY_EXHAUSTED_E)) {
key->state = WC_XMSS_STATE_NOSIGS;
WOLFSSL_MSG("error: no XMSS signatures remaining");
}
else if (ret != 0) {
ForceZero(sig, key->params->sig_len);
WOLFSSL_MSG("error: XMSS sign failed");
}
wc_xmss_state_free(state);
}
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
}
if (ret == 0) {
cb_rc = key->write_private_key(key->sk, key->sk_len, key->context);
if (cb_rc != WC_XMSS_RC_SAVED_TO_NV_MEMORY) {
ForceZero(sig, key->params->sig_len);
WOLFSSL_MSG("error: XMSS write_private_key failed");
ret = IO_FAILED_E;
}
}
if (ret == 0) {
key->state = WC_XMSS_STATE_OK;
}
ForceZero(key->sk, key->sk_len);
return ret;
}
#endif
int wc_XmssKey_Init(XmssKey* key, void* heap, int devId)
{
int ret = 0;
(void) heap;
(void) devId;
if (key == NULL) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
ForceZero(key, sizeof(XmssKey));
key->state = WC_XMSS_STATE_INITED;
}
return ret;
}
int wc_XmssKey_SetParamStr(XmssKey* key, const char* str)
{
int ret = 0;
word32 oid = 0;
int is_xmssmt = 0;
if ((key == NULL) || (str == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->state != WC_XMSS_STATE_INITED)) {
WOLFSSL_MSG("error: XMSS key needs init");
ret = BAD_STATE_E;
}
if (ret == 0) {
is_xmssmt = (XMEMCMP(str, "XMSS-", 5) != 0);
if (is_xmssmt) {
ret = wc_xmssmt_str_to_params(str, &oid, &key->params);
}
else {
ret = wc_xmss_str_to_params(str, &oid, &key->params);
}
if (ret != 0) {
WOLFSSL_MSG("error: xmssmt_str_to_params failed");
ret = BAD_FUNC_ARG;
}
}
if (ret == 0) {
key->oid = oid;
key->is_xmssmt = is_xmssmt;
key->state = WC_XMSS_STATE_PARMSET;
}
return ret;
}
void wc_XmssKey_Free(XmssKey* key)
{
if (key != NULL) {
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
if (key->sk != NULL) {
ForceZero(key->sk, key->sk_len);
XFREE(key->sk, NULL, DYNAMIC_TYPE_TMP_BUFFER);
key->sk = NULL;
key->sk_len = 0;
}
#endif
ForceZero(key, sizeof(XmssKey));
key->state = WC_XMSS_STATE_FREED;
}
}
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
int wc_XmssKey_SetWriteCb(XmssKey* key, wc_xmss_write_private_key_cb write_cb)
{
int ret = 0;
if ((key == NULL) || (write_cb == NULL)) {
ret = BAD_FUNC_ARG;
}
else if (key->state == WC_XMSS_STATE_OK) {
WOLFSSL_MSG("error: wc_XmssKey_SetWriteCb: key in use");
ret = BAD_STATE_E;
}
else {
key->write_private_key = write_cb;
}
return ret;
}
int wc_XmssKey_SetReadCb(XmssKey* key, wc_xmss_read_private_key_cb read_cb)
{
int ret = 0;
if ((key == NULL) || (read_cb == NULL)) {
ret = BAD_FUNC_ARG;
}
else if (key->state == WC_XMSS_STATE_OK) {
WOLFSSL_MSG("error: wc_XmssKey_SetReadCb: key in use");
ret = BAD_STATE_E;
}
else {
key->read_private_key = read_cb;
}
return ret;
}
int wc_XmssKey_SetContext(XmssKey* key, void* context)
{
int ret = 0;
if ((key == NULL) || (context == NULL)) {
ret = BAD_FUNC_ARG;
}
else if (key->state == WC_XMSS_STATE_OK) {
WOLFSSL_MSG("error: wc_XmssKey_SetContext: key in use");
ret = BAD_STATE_E;
}
else {
key->context = context;
}
return ret;
}
int wc_XmssKey_MakeKey(XmssKey* key, WC_RNG* rng)
{
int ret = 0;
enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
#ifdef WOLFSSL_SMALL_STACK
unsigned char* seed = NULL;
#else
unsigned char seed[3 * WC_XMSS_MAX_N];
#endif
if ((key == NULL) || (rng == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->state != WC_XMSS_STATE_PARMSET)) {
WOLFSSL_MSG("error: XmssKey not ready for generation");
ret = BAD_STATE_E;
}
if ((ret == 0) && (key->write_private_key == NULL)) {
WOLFSSL_MSG("error: XmssKey write callback is not set");
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->context == NULL)) {
WOLFSSL_MSG("error: XmssKey context is not set");
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
ret = wc_xmsskey_alloc_sk(key);
}
#ifdef WOLFSSL_SMALL_STACK
if (ret == 0) {
seed = (unsigned char*)XMALLOC(3 * key->params->n, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (seed == NULL) {
ret = MEMORY_E;
}
}
#endif
if (ret == 0) {
ret = wc_RNG_GenerateBlock(rng, seed, 3 * key->params->n);
}
if (ret == 0) {
WC_DECLARE_VAR(state, XmssState, 1, 0);
WC_ALLOC_VAR_EX(state, XmssState, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER,
ret=MEMORY_E);
if (WC_VAR_OK(state))
{
ret = wc_xmss_state_init(state, key->params);
if (ret == 0) {
#ifndef WOLFSSL_WC_XMSS_SMALL
if (key->is_xmssmt) {
ret = wc_xmssmt_keygen(state, seed, key->sk, key->pk);
}
else {
ret = wc_xmss_keygen(state, seed, key->sk, key->pk);
}
#else
ret = wc_xmssmt_keygen(state, seed, key->sk, key->pk);
#endif
if (ret != 0) {
WOLFSSL_MSG("error: XMSS keygen failed");
key->state = WC_XMSS_STATE_BAD;
}
wc_xmss_state_free(state);
}
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
}
if (ret == 0) {
cb_rc = key->write_private_key(key->sk, key->sk_len, key->context);
ForceZero(key->sk, key->sk_len);
if (cb_rc != WC_XMSS_RC_SAVED_TO_NV_MEMORY) {
WOLFSSL_MSG("error: XMSS write to NV storage failed");
key->state = WC_XMSS_STATE_BAD;
ret = IO_FAILED_E;
}
}
if (ret == 0) {
key->state = WC_XMSS_STATE_OK;
}
WC_FREE_VAR_EX(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
int wc_XmssKey_Reload(XmssKey* key)
{
int ret = 0;
enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
if (key == NULL) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->state != WC_XMSS_STATE_PARMSET)) {
WOLFSSL_MSG("error: XmssKey not ready for reload");
ret = BAD_STATE_E;
}
if ((ret == 0) && ((key->write_private_key == NULL) ||
(key->read_private_key == NULL))) {
WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->context == NULL)) {
WOLFSSL_MSG("error: XmssKey context is not set");
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
ret = wc_xmsskey_alloc_sk(key);
}
if (ret == 0) {
cb_rc = key->read_private_key(key->sk, key->sk_len, key->context);
ForceZero(key->sk, key->sk_len);
if (cb_rc != WC_XMSS_RC_READ_TO_MEMORY) {
WOLFSSL_MSG("error: XMSS read from NV storage failed");
key->state = WC_XMSS_STATE_BAD;
ret = IO_FAILED_E;
}
}
if (ret == 0) {
key->state = WC_XMSS_STATE_OK;
}
return ret;
}
int wc_XmssKey_GetPrivLen(const XmssKey* key, word32* len)
{
int ret = 0;
if ((key == NULL) || (len == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && ((key->state != WC_XMSS_STATE_OK) &&
(key->state != WC_XMSS_STATE_PARMSET))) {
ret = BAD_STATE_E;
}
if (ret == 0) {
*len = XMSS_OID_LEN + (word32)key->params->sk_len;
}
return ret;
}
int wc_XmssKey_Sign(XmssKey* key, byte* sig, word32* sigLen, const byte* msg,
int msgLen)
{
int ret = 0;
if ((key == NULL) || (sig == NULL) || (sigLen == NULL) || (msg == NULL) ||
(msgLen <= 0)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->state == WC_XMSS_STATE_NOSIGS)) {
WOLFSSL_MSG("error: XMSS signatures exhausted");
ret = BAD_STATE_E;
}
if ((ret == 0) && (key->state != WC_XMSS_STATE_OK)) {
WOLFSSL_MSG("error: can't sign, XMSS key not in good state");
ret = BAD_STATE_E;
}
if ((ret == 0) && (*sigLen < key->params->sig_len)) {
WOLFSSL_MSG("error: XMSS sig buffer too small");
ret = BUFFER_E;
}
if ((ret == 0) && ((key->write_private_key == NULL) ||
(key->read_private_key == NULL))) {
WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->context == NULL)) {
WOLFSSL_MSG("error: XmssKey context is not set");
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
*sigLen = key->params->sig_len;
ret = wc_xmsskey_signupdate(key, sig, msg, msgLen);
}
return ret;
}
int wc_XmssKey_SigsLeft(XmssKey* key)
{
int ret;
if (key == NULL) {
ret = 0;
}
else if (key->state == WC_XMSS_STATE_NOSIGS) {
WOLFSSL_MSG("error: XMSS signatures exhausted");
ret = 0;
}
else if (key->state != WC_XMSS_STATE_OK) {
WOLFSSL_MSG("error: can't sign, XMSS key not in good state");
ret = 0;
}
else if (key->read_private_key(key->sk, key->sk_len, key->context) !=
WC_XMSS_RC_READ_TO_MEMORY) {
WOLFSSL_MSG("error: XMSS read_private_key failed");
ret = 0;
}
else {
ret = wc_xmss_sigsleft(key->params, key->sk);
}
return ret;
}
#endif
int wc_XmssKey_GetPubLen(const XmssKey* key, word32* len)
{
int ret = 0;
if ((key == NULL) || (len == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
*len = XMSS_OID_LEN + key->params->pk_len;
}
return ret;
}
int wc_XmssKey_ExportPub(XmssKey* keyDst, const XmssKey* keySrc)
{
int ret = 0;
if ((keyDst == NULL) || (keySrc == NULL)) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
ForceZero(keyDst, sizeof(XmssKey));
XMEMCPY(keyDst->pk, keySrc->pk, sizeof(keySrc->pk));
keyDst->oid = keySrc->oid;
keyDst->is_xmssmt = keySrc->is_xmssmt;
keyDst->params = keySrc->params;
}
if (ret == 0) {
keyDst->state = WC_XMSS_STATE_VERIFYONLY;
}
return 0;
}
int wc_XmssKey_ExportPubRaw(const XmssKey* key, byte* out, word32* outLen)
{
int ret = 0;
word32 pubLen = 0;
if ((key == NULL) || (out == NULL) || (outLen == NULL)) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
ret = wc_XmssKey_GetPubLen(key, &pubLen);
}
if ((ret == 0) && (*outLen < pubLen)) {
ret = BUFFER_E;
}
if (ret == 0) {
int i = 0;
for (; i < XMSS_OID_LEN; i++) {
out[XMSS_OID_LEN - i - 1] = (key->oid >> (8 * i)) & 0xFF;
}
XMEMCPY(out + XMSS_OID_LEN, key->pk, pubLen - XMSS_OID_LEN);
*outLen = pubLen;
}
return ret;
}
int wc_XmssKey_ImportPubRaw(XmssKey* key, const byte* in, word32 inLen)
{
int ret = 0;
word32 pubLen = 0;
if ((key == NULL) || (in == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->state != WC_XMSS_STATE_PARMSET)) {
WOLFSSL_MSG("error: XMSS key not ready for import");
ret = BAD_STATE_E;
}
if (ret == 0) {
ret = wc_XmssKey_GetPubLen(key, &pubLen);
}
if ((ret == 0) && (inLen != pubLen)) {
ret = BUFFER_E;
}
if (ret == 0) {
XMEMCPY(key->pk, in + XMSS_OID_LEN, pubLen - XMSS_OID_LEN);
key->state = WC_XMSS_STATE_VERIFYONLY;
}
return ret;
}
int wc_XmssKey_GetSigLen(const XmssKey* key, word32* len)
{
int ret = 0;
if ((key == NULL) || (len == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->state != WC_XMSS_STATE_OK) &&
(key->state != WC_XMSS_STATE_PARMSET)) {
ret = BAD_STATE_E;
}
if (ret == 0) {
*len = key->params->sig_len;
}
return ret;
}
int wc_XmssKey_Verify(XmssKey* key, const byte* sig, word32 sigLen,
const byte* m, int mLen)
{
int ret = 0;
if ((key == NULL) || (sig == NULL) || (m == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (key->state != WC_XMSS_STATE_OK) &&
(key->state != WC_XMSS_STATE_VERIFYONLY)) {
WOLFSSL_MSG("error: XMSS key not ready for verification");
ret = BAD_STATE_E;
}
if ((ret == 0) && (sigLen < key->params->sig_len)) {
ret = BUFFER_E;
}
if (ret == 0) {
WC_DECLARE_VAR(state, XmssState, 1, 0);
WC_ALLOC_VAR_EX(state, XmssState, 1, NULL, DYNAMIC_TYPE_TMP_BUFFER,
ret=MEMORY_E);
if (WC_VAR_OK(state))
{
ret = wc_xmss_state_init(state, key->params);
if (ret == 0) {
ret = wc_xmssmt_verify(state, m, mLen, sig, key->pk);
wc_xmss_state_free(state);
}
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
}
return ret;
}
#endif