#ifndef WC_LMS_H
#define WC_LMS_H
#include <wolfssl/wolfcrypt/types.h>
#if defined(WOLFSSL_HAVE_LMS) && defined(WOLFSSL_WC_LMS)
#include <wolfssl/wolfcrypt/lms.h>
#include <wolfssl/wolfcrypt/sha256.h>
#if defined(WOLFSSL_NO_HASH_RAW) && !defined(WC_LMS_FULL_HASH)
#define WC_LMS_FULL_HASH
#endif
#ifdef WOLFSSL_LMS_MAX_LEVELS
#define LMS_MAX_LEVELS WOLFSSL_LMS_MAX_LEVELS
#else
#define LMS_MAX_LEVELS 4
#endif
#if (LMS_MAX_LEVELS < 1) || (LMS_MAX_LEVELS > 4)
#error "LMS parameters only support heights 1-4."
#endif
#if LMS_MAX_LEVELS == 1 && !defined(WOLFSSL_LMS_NO_SIGN_SMOOTHING)
#define WOLFSSL_LMS_NO_SIGN_SMOOTHING
#endif
#ifdef WOLFSSL_LMS_MAX_HEIGHT
#define LMS_MAX_HEIGHT WOLFSSL_LMS_MAX_HEIGHT
#else
#define LMS_MAX_HEIGHT 20
#endif
#if (LMS_MAX_HEIGHT < 5) || (LMS_MAX_HEIGHT > 20)
#error "LMS parameters only support heights 5-20."
#endif
#define LMS_I_LEN 16
#define LMS_L_LEN 4
#define LMS_Q_LEN 4
#define LMS_P_LEN 2
#define LMS_W_LEN 1
#define LMS_TYPE_LEN 4
#define WC_SHA256_192_DIGEST_SIZE 24
#define LMS_MAX_NODE_LEN WC_SHA256_DIGEST_SIZE
#define LMS_SEED_LEN WC_SHA256_DIGEST_SIZE
#define LMS_MAX_P 265
#ifndef WOLFSSL_LMS_ROOT_LEVELS
#ifdef WOLFSSL_LMS_LARGE_CACHES
#define LMS_ROOT_LEVELS 7
#else
#define LMS_ROOT_LEVELS 5
#endif
#else
#define LMS_ROOT_LEVELS WOLFSSL_LMS_ROOT_LEVELS
#endif
#if LMS_ROOT_LEVELS <= 0
#error "LMS_ROOT_LEVELS must be greater than 0."
#endif
#define LMS_ROOT_COUNT ((1 << (LMS_ROOT_LEVELS)) - 1)
#ifndef WOLFSSL_LMS_CACHE_BITS
#ifdef WOLFSSL_LMS_LARGE_CACHES
#define LMS_CACHE_BITS 7
#else
#define LMS_CACHE_BITS 5
#endif
#else
#define LMS_CACHE_BITS WOLFSSL_LMS_CACHE_BITS
#endif
#if LMS_CACHE_BITS < 0
#error "LMS_CACHE_BITS must be greater than or equal to 0."
#endif
#define LMS_LEAF_CACHE (1 << LMS_CACHE_BITS)
#define HSS_MAX_LEVELS 8
#define HSS_Q_LEN 8
#define HSS_COMPRESS_PARAM_SET_LEN 1
#define HSS_PRIV_KEY_PARAM_SET_LEN \
(HSS_COMPRESS_PARAM_SET_LEN * HSS_MAX_LEVELS)
#define LMS_PRIV_LEN(hLen) \
(LMS_Q_LEN + (hLen) + LMS_I_LEN)
#define LMS_PUBKEY_LEN(hLen) \
(LMS_TYPE_LEN + LMS_TYPE_LEN + LMS_I_LEN + (hLen))
#define LMS_SIG_LEN(h, p, hLen) \
(LMS_Q_LEN + LMS_TYPE_LEN + (hLen) + (p) * (hLen) + LMS_TYPE_LEN + \
(h) * (hLen))
#define HSS_PUBLIC_KEY_LEN(hLen) (LMS_L_LEN + LMS_PUBKEY_LEN(hLen))
#define HSS_PRIVATE_KEY_LEN(hLen) \
(HSS_Q_LEN + HSS_PRIV_KEY_PARAM_SET_LEN + (hLen) + LMS_I_LEN)
#define HSS_MAX_PRIVATE_KEY_LEN HSS_PRIVATE_KEY_LEN(LMS_MAX_NODE_LEN)
#define HSS_MAX_PUBLIC_KEY_LEN HSS_PUBLIC_KEY_LEN(LMS_MAX_NODE_LEN)
#define HSS_MAX_SIG_LEN \
(LMS_TYPE_LEN + \
LMS_MAX_LEVELS * (LMS_Q_LEN + LMS_TYPE_LEN + LMS_TYPE_LEN + \
LMS_MAX_NODE_LEN * (1 + LMS_MAX_P + LMS_MAX_HEIGHT)) + \
(LMS_MAX_LEVELS - 1) * LMS_PUBKEY_LEN(LMS_MAX_NODE_LEN))
#define LMS_MAX_BUFFER_LEN \
(LMS_I_LEN + LMS_Q_LEN + LMS_P_LEN + LMS_W_LEN + 2 * LMS_MAX_NODE_LEN)
#define LMS_PRIV_KEY_LEN(l, hLen) \
((l) * LMS_PRIV_LEN(hLen))
#define LMS_STACK_CACHE_LEN(h, hLen) \
(((h) + 1) * (hLen))
#define LMS_ROOT_CACHE_LEN(rl, hLen) \
(((1 << (rl)) - 1) * (hLen))
#define LMS_LEAF_CACHE_LEN(cb, hLen) \
((1 << (cb)) * (hLen))
#define LMS_PRIV_STATE_LEN(h, rl, cb, hLen) \
(((h) * (hLen)) + \
LMS_STACK_CACHE_LEN(h, hLen) + 4 + \
LMS_ROOT_CACHE_LEN(rl, hLen) + \
LMS_LEAF_CACHE_LEN(cb, hLen) + 4 + 4)
#ifndef WOLFSSL_WC_LMS_SMALL
#define LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb, hLen) \
((l) * LMS_PRIV_STATE_LEN(h, rl, cb, hLen))
#else
#define LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb, hLen) 0
#endif
#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING
#define LMS_PRIV_SMOOTH_LEN(l, h, rl, cb, hLen) \
(LMS_PRIV_KEY_LEN(l, hLen) + \
((l) - 1) * LMS_PRIV_STATE_LEN(h, rl, cb, hLen))
#else
#define LMS_PRIV_SMOOTH_LEN(l, h, rl, cb, hLen) 0
#endif
#ifndef WOLFSSL_LMS_NO_SIG_CACHE
#define LMS_PRIV_Y_TREE_LEN(p, hLen) \
((hLen) + (p) * (hLen))
#define LMS_PRIV_Y_LEN(l, p, hLen) \
(((l) - 1) * ((hLen) + (p) * (hLen)))
#else
#define LMS_PRIV_Y_LEN(l, p, hLen) 0
#endif
#ifndef WOLFSSL_WC_LMS_SMALL
#define LMS_PRIV_DATA_LEN(l, h, p, rl, cb, hLen) \
(LMS_PRIV_KEY_LEN(l, hLen) + \
LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb, hLen) + \
LMS_PRIV_SMOOTH_LEN(l, h, rl, cb, hLen) + \
LMS_PRIV_Y_LEN(l, p, hLen))
#else
#define LMS_PRIV_DATA_LEN(l, h, p, rl, cb, hLen) \
LMS_PRIV_KEY_LEN(l, hLen)
#endif
#define LMS_SHA256 0x0000
#define LMS_SHA256_192 0x1000
#define LMS_HASH_MASK 0xf000
#define LMS_H_W_MASK 0x0fff
#define LMS_SHA256_M32_H5 0x05
#define LMS_SHA256_M32_H10 0x06
#define LMS_SHA256_M32_H15 0x07
#define LMS_SHA256_M32_H20 0x08
#define LMS_SHA256_M32_H25 0x09
#define LMOTS_SHA256_N32_W1 0x01
#define LMOTS_SHA256_N32_W2 0x02
#define LMOTS_SHA256_N32_W4 0x03
#define LMOTS_SHA256_N32_W8 0x04
#define LMS_SHA256_M24_H5 (0x0a | LMS_SHA256_192)
#define LMS_SHA256_M24_H10 (0x0b | LMS_SHA256_192)
#define LMS_SHA256_M24_H15 (0x0c | LMS_SHA256_192)
#define LMS_SHA256_M24_H20 (0x0d | LMS_SHA256_192)
#define LMS_SHA256_M24_H25 (0x0e | LMS_SHA256_192)
#define LMOTS_SHA256_N24_W1 (0x05 | LMS_SHA256_192)
#define LMOTS_SHA256_N24_W2 (0x06 | LMS_SHA256_192)
#define LMOTS_SHA256_N24_W4 (0x07 | LMS_SHA256_192)
#define LMOTS_SHA256_N24_W8 (0x08 | LMS_SHA256_192)
typedef struct LmsParams {
word8 levels;
word8 height;
word8 width;
word8 ls;
word16 p;
word16 lmsType;
word16 lmOtsType;
word16 sig_len;
word16 hash_len;
#ifndef WOLFSSL_WC_LMS_SMALL
word8 rootLevels;
word8 cacheBits;
#endif
} LmsParams;
typedef struct wc_LmsParamsMap {
enum wc_LmsParm id;
#ifdef WOLFSSL_NAMES_STATIC
const char str[32];
#else
const char* str;
#endif
LmsParams params;
} wc_LmsParamsMap;
typedef struct LmsState {
ALIGN16 byte buffer[LMS_MAX_BUFFER_LEN];
#ifdef WOLFSSL_SMALL_STACK
ALIGN16 byte a[LMS_MAX_P];
#endif
const LmsParams* params;
wc_Sha256 hash;
wc_Sha256 hash_k;
} LmsState;
#ifndef WOLFSSL_WC_LMS_SMALL
typedef struct LmsStack {
byte* stack;
word32 offset;
} LmsStack;
typedef struct HssLeafCache {
byte* cache;
word32 idx;
word32 offset;
} HssLeafCache;
typedef struct LmsPrivState {
byte* auth_path;
LmsStack stack;
byte* root;
HssLeafCache leaf;
} LmsPrivState;
#endif
typedef struct HssPrivKey {
byte* priv;
#ifndef WOLFSSL_WC_LMS_SMALL
LmsPrivState state[LMS_MAX_LEVELS];
#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING
byte* next_priv;
LmsPrivState next_state[LMS_MAX_LEVELS - 1];
#endif
#ifndef WOLFSSL_LMS_NO_SIG_CACHE
byte* y;
#endif
word8 inited:1;
#endif
} HssPrivKey;
struct LmsKey {
ALIGN16 byte pub[HSS_PUBLIC_KEY_LEN(LMS_MAX_NODE_LEN)];
#ifndef WOLFSSL_LMS_VERIFY_ONLY
ALIGN16 byte priv_raw[HSS_MAX_PRIVATE_KEY_LEN];
byte* priv_data;
HssPrivKey priv;
wc_lms_write_private_key_cb write_private_key;
wc_lms_read_private_key_cb read_private_key;
void* context;
void* heap;
#endif
const LmsParams* params;
enum wc_LmsState state;
#ifdef WOLF_CRYPTO_CB
int devId;
#endif
};
int wc_hss_make_key(LmsState* state, WC_RNG* rng, byte* priv_raw,
HssPrivKey* priv_key, byte* priv_data, byte* pub);
int wc_hss_reload_key(LmsState* state, const byte* priv_raw,
HssPrivKey* priv_key, byte* priv_data, byte* pub_root);
int wc_hss_sign(LmsState* state, byte* priv_raw, HssPrivKey* priv_key,
byte* priv_data, const byte* msg, word32 msgSz, byte* sig);
int wc_hss_sigsleft(const LmsParams* params, const byte* priv_raw);
int wc_hss_verify(LmsState* state, const byte* pub, const byte* msg,
word32 msgSz, const byte* sig);
#endif
#endif