/* wc_xmss.h
 *
 * Copyright (C) 2006-2026 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 3 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
 */

/*!
    \file wolfssl/wolfcrypt/wc_xmss.h
 */

/* Based on:
 *  o RFC 8391 - XMSS: eXtended Merkle Signature Scheme
 *  o [HDSS] "Hash-based Digital Signature Schemes", Buchmann, Dahmen and Szydlo
 *    from "Post Quantum Cryptography", Springer 2009.
 */

#ifndef WC_XMSS_H
#define WC_XMSS_H

#include <wolfssl/wolfcrypt/types.h>

#ifdef WOLFSSL_HAVE_XMSS

#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/sha512.h>
#include <wolfssl/wolfcrypt/sha3.h>


/* When raw hash access APIs are disabled or unavailable (WOLFSSL_NO_HASH_RAW),
 * fall back to using the full hash API calls. */
#if defined(WOLFSSL_NO_HASH_RAW) && !defined(WC_XMSS_FULL_HASH)
    #define WC_XMSS_FULL_HASH
#endif

/* Note on XMSS/XMSS^MT pub/priv key sizes:
 *   - The XMSS/XMSS^MT pub key has a defined format and size.
 *   - The XMSS/XMSS^MT private key is implementation and parameter
 *     specific. It does not have a standardized format or size.
 *
 * The XMSS/XMSS^MT public and secret key format and length is:
 *   PK = OID || root || SEED;
 *   PK_len = 4 + 2 * n
 *
 *   SK = OID || (implementation defined)
 *   SK_len = 4 + (implementation defined)
 *
 * where n is the number of bytes in the hash function, which is 32
 * in this SHA256 implementation.
 *
 * However the private key is implementation specific. For example,
 * in xmss-reference the private key size varies from 137 bytes to
 * 1377 bytes between slow and fast implementations with param name
 * "XMSSMT-SHA2_20/2_256".
 *
 * References:
 *   - RFC 8391
 *   - Table 2 of Kampanakis, Fluhrer, IACR, 2017.
 * */

#define XMSS_SHA256_PUBLEN (68)

/* Supported XMSS/XMSS^MT parameter set names:
 * We are supporting all SHA256 parameter sets with n=32 and
 * Winternitz=16, from RFC 8391 and NIST SP 800-208.
 *
 *         ----------------------------------------------------------
 *         | Name                     OID         n   w  len  h   d  |
 * XMSS:   | "XMSS-SHA2_10_256"       0x00000001  32  16  67  10  1  |
 *         | "XMSS-SHA2_16_256"       0x00000002  32  16  67  16  1  |
 *         | "XMSS-SHA2_20_256"       0x00000003  32  16  67  20  1  |
 *         |                                                         |
 * XMSSMT: | "XMSSMT-SHA2_20/2_256"   0x00000001  32  16  67  20  2  |
 *         | "XMSSMT-SHA2_20/4_256"   0x00000002  32  16  67  20  4  |
 *         | "XMSSMT-SHA2_40/2_256"   0x00000003  32  16  67  40  2  |
 *         | "XMSSMT-SHA2_40/4_256"   0x00000004  32  16  67  40  4  |
 *         | "XMSSMT-SHA2_40/8_256"   0x00000005  32  16  67  40  8  |
 *         | "XMSSMT-SHA2_60/3_256"   0x00000006  32  16  67  60  3  |
 *         | "XMSSMT-SHA2_60/6_256"   0x00000007  32  16  67  60  6  |
 *         | "XMSSMT-SHA2_60/12_256"  0x00000008  32  16  67  60  12 |
 *         ----------------------------------------------------------
 *
 * Note that some XMSS and XMSSMT names do have overlapping OIDs.
 *
 * References:
 *   1. NIST SP 800-208
 *   2. RFC 8391
 * */

#define XMSS_NAME_LEN       (16) /* strlen("XMSS-SHA2_10_256") */
#define XMSSMT_NAME_MIN_LEN (20) /* strlen("XMSSMT-SHA2_20/2_256") */
#define XMSSMT_NAME_MAX_LEN (21) /* strlen("XMSSMT-SHA2_60/12_256") */

#if defined(HAVE_FIPS)
    #undef WOLFSSL_WC_XMSS_NO_SHA512
    #define WOLFSSL_WC_XMSS_NO_SHA512
    #undef WOLFSSL_WC_XMSS_NO_SHAKE128
    #define WOLFSSL_WC_XMSS_NO_SHAKE128
    #undef WOLFSSL_WC_XMSS_MAX_HASH_SIZE
    #define WOLFSSL_WC_XMSS_MIN_HASH_SIZE       192
    #define WOLFSSL_WC_XMSS_MAX_HASH_SIZE       256
#endif

#if !defined(NO_SHA256) && !defined(WOLFSSL_WC_XMSS_NO_SHA256)
    #define WC_XMSS_SHA256
#endif
#if defined(WOLFSSL_SHA512) && !defined(WOLFSSL_WC_XMSS_NO_SHA512)
    #define WC_XMSS_SHA512
#endif
#if defined(WOLFSSL_SHAKE128) && !defined(WOLFSSL_WC_XMSS_NO_SHAKE128)
    #define WC_XMSS_SHAKE128
#endif
#if defined(WOLFSSL_SHAKE256) && !defined(WOLFSSL_WC_XMSS_NO_SHAKE256)
    #define WC_XMSS_SHAKE256
#endif

#ifndef WOLFSSL_WC_XMSS_MIN_HASH_SIZE
    #define WOLFSSL_WC_XMSS_MIN_HASH_SIZE       192
#endif
#ifndef WOLFSSL_WC_XMSS_MAX_HASH_SIZE
    #define WOLFSSL_WC_XMSS_MAX_HASH_SIZE       512
#endif
#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE > WOLFSSL_WC_XMSS_MAX_HASH_SIZE
    #error "XMSS minimum hash size is greater than maximum hash size"
#endif

#ifndef WOLFSSL_XMSS_MIN_HEIGHT
    #define WOLFSSL_XMSS_MIN_HEIGHT             10
#endif
#ifndef WOLFSSL_XMSS_MAX_HEIGHT
    #define WOLFSSL_XMSS_MAX_HEIGHT             60
#endif
#if WOLFSSL_XMSS_MIN_HEIGHT > WOLFSSL_XMSS_MAX_HEIGHT
    #error "XMSS minimum height is greater than maximum height"
#endif

/* Return codes returned by private key callbacks. */
enum wc_XmssRc {
  WC_XMSS_RC_NONE,
  WC_XMSS_RC_BAD_ARG,            /* Bad arg in read or write callback. */
  WC_XMSS_RC_WRITE_FAIL,         /* Write or update private key failed. */
  WC_XMSS_RC_READ_FAIL,          /* Read private key failed. */
  WC_XMSS_RC_SAVED_TO_NV_MEMORY, /* Wrote private key to nonvolatile storage. */
  WC_XMSS_RC_READ_TO_MEMORY      /* Read private key from storage. */
};

/* enum wc_XmssState is to help track the state of an XMSS Key. */
enum wc_XmssState {
    WC_XMSS_STATE_FREED,      /* Key has been freed from memory. */
    WC_XMSS_STATE_INITED,     /* Key has been inited, ready to set params.*/
    WC_XMSS_STATE_PARMSET,    /* Params are set, ready to MakeKey or Reload. */
    WC_XMSS_STATE_OK,         /* Able to sign signatures and verify. */
    WC_XMSS_STATE_VERIFYONLY, /* A public only XmssKey. */
    WC_XMSS_STATE_BAD,        /* Can't guarantee key's state. */
    WC_XMSS_STATE_NOSIGS      /* Signatures exhausted. */
};

/* Private key write and read callbacks. */
typedef enum wc_XmssRc (*wc_xmss_write_private_key_cb)(const byte* priv, word32 privSz,
    void* context);
typedef enum wc_XmssRc (*wc_xmss_read_private_key_cb)(byte* priv, word32 privSz,
    void* context);

#if (defined(WC_XMSS_SHA512) || defined(WC_XMSS_SHAKE256)) && \
        (WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512)
    #define WC_XMSS_MAX_N               64U
    #define WC_XMSS_MAX_PADDING_LEN     64U
#else
    #define WC_XMSS_MAX_N               32U
    #define WC_XMSS_MAX_PADDING_LEN     32U
#endif
#define WC_XMSS_MAX_MSG_PRE_LEN     \
    (WC_XMSS_MAX_PADDING_LEN + 3U * WC_XMSS_MAX_N)
#define WC_XMSS_MAX_TREE_HEIGHT     20U
#define WC_XMSS_MAX_CSUM_BYTES       4U
#define WC_XMSS_MAX_WOTS_LEN        (8U * WC_XMSS_MAX_N / 4U + 3U)
#define WC_XMSS_MAX_WOTS_SIG_LEN    (WC_XMSS_MAX_WOTS_LEN * WC_XMSS_MAX_N)
#define WC_XMSS_MAX_STACK_LEN       \
    ((WC_XMSS_MAX_TREE_HEIGHT + 1U) * WC_XMSS_MAX_N)
#define WC_XMSS_MAX_D               12U
#define WC_XMSS_MAX_BDS_STATES      (2U * WC_XMSS_MAX_D - 1U)
#define WC_XMSS_MAX_TREE_HASH       \
    ((2U * WC_XMSS_MAX_D - 1U) * WC_XMSS_MAX_TREE_HEIGHT)
#define WC_XMSS_MAX_BDS_K           0U

#define WC_XMSS_ADDR_LEN            32U

#define WC_XMSS_HASH_PRF_MAX_DATA_LEN               \
    (WC_XMSS_MAX_PADDING_LEN + 2U * WC_XMSS_MAX_N + WC_XMSS_ADDR_LEN)
#define WC_XMSS_HASH_MAX_DATA_LEN                   \
    (WC_XMSS_MAX_PADDING_LEN + 3U * WC_XMSS_MAX_N)


#define WC_XMSS_SHA256_N            32U
#define WC_XMSS_SHA256_PADDING_LEN  32U
#define WC_XMSS_SHA256_WOTS_LEN     67U

#define XMSS_OID_LEN                   4U

#define XMSS_MAX_HASH_LEN              WC_SHA256_DIGEST_SIZE

#define XMSS_RETAIN_LEN(k, n)   \
    (((word32)((k) != 0)) * (((word32)1U << (k)) - (word32)(k) - 1U) *  \
     (word32)(n))

/* XMMS Algorithm OIDs
 * Note: values are used in mathematical calculations in OID to parames. */
#define WC_XMSS_OID_SHA2_10_256        0x01
#define WC_XMSS_OID_SHA2_16_256        0x02
#define WC_XMSS_OID_SHA2_20_256        0x03
#define WC_XMSS_OID_SHA2_10_512        0x04
#define WC_XMSS_OID_SHA2_16_512        0x05
#define WC_XMSS_OID_SHA2_20_512        0x06
#define WC_XMSS_OID_SHAKE_10_256       0x07
#define WC_XMSS_OID_SHAKE_16_256       0x08
#define WC_XMSS_OID_SHAKE_20_256       0x09
#define WC_XMSS_OID_SHAKE_10_512       0x0a
#define WC_XMSS_OID_SHAKE_16_512       0x0b
#define WC_XMSS_OID_SHAKE_20_512       0x0c
#define WC_XMSS_OID_SHA2_10_192        0x0d
#define WC_XMSS_OID_SHA2_16_192        0x0e
#define WC_XMSS_OID_SHA2_20_192        0x0f
#define WC_XMSS_OID_SHAKE256_10_256    0x10
#define WC_XMSS_OID_SHAKE256_16_256    0x11
#define WC_XMSS_OID_SHAKE256_20_256    0x12
#define WC_XMSS_OID_SHAKE256_10_192    0x13
#define WC_XMSS_OID_SHAKE256_16_192    0x14
#define WC_XMSS_OID_SHAKE256_20_192    0x15
#define WC_XMSS_OID_FIRST              WC_XMSS_OID_SHA2_10_256
#define WC_XMSS_OID_LAST               WC_XMSS_OID_SHAKE256_20_192

/* XMMS^MT Algorithm OIDs
 * Note: values are used in mathematical calculations in OID to parames. */
#define WC_XMSSMT_OID_SHA2_20_2_256        0x01
#define WC_XMSSMT_OID_SHA2_20_4_256        0x02
#define WC_XMSSMT_OID_SHA2_40_2_256        0x03
#define WC_XMSSMT_OID_SHA2_40_4_256        0x04
#define WC_XMSSMT_OID_SHA2_40_8_256        0x05
#define WC_XMSSMT_OID_SHA2_60_3_256        0x06
#define WC_XMSSMT_OID_SHA2_60_6_256        0x07
#define WC_XMSSMT_OID_SHA2_60_12_256       0x08
#define WC_XMSSMT_OID_SHA2_20_2_512        0x09
#define WC_XMSSMT_OID_SHA2_20_4_512        0x0a
#define WC_XMSSMT_OID_SHA2_40_2_512        0x0b
#define WC_XMSSMT_OID_SHA2_40_4_512        0x0c
#define WC_XMSSMT_OID_SHA2_40_8_512        0x0d
#define WC_XMSSMT_OID_SHA2_60_3_512        0x0e
#define WC_XMSSMT_OID_SHA2_60_6_512        0x0f
#define WC_XMSSMT_OID_SHA2_60_12_512       0x10
#define WC_XMSSMT_OID_SHAKE_20_2_256       0x11
#define WC_XMSSMT_OID_SHAKE_20_4_256       0x12
#define WC_XMSSMT_OID_SHAKE_40_2_256       0x13
#define WC_XMSSMT_OID_SHAKE_40_4_256       0x14
#define WC_XMSSMT_OID_SHAKE_40_8_256       0x15
#define WC_XMSSMT_OID_SHAKE_60_3_256       0x16
#define WC_XMSSMT_OID_SHAKE_60_6_256       0x17
#define WC_XMSSMT_OID_SHAKE_60_12_256      0x18
#define WC_XMSSMT_OID_SHAKE_20_2_512       0x19
#define WC_XMSSMT_OID_SHAKE_20_4_512       0x1a
#define WC_XMSSMT_OID_SHAKE_40_2_512       0x1b
#define WC_XMSSMT_OID_SHAKE_40_4_512       0x1c
#define WC_XMSSMT_OID_SHAKE_40_8_512       0x1d
#define WC_XMSSMT_OID_SHAKE_60_3_512       0x1e
#define WC_XMSSMT_OID_SHAKE_60_6_512       0x1f
#define WC_XMSSMT_OID_SHAKE_60_12_512      0x20
#define WC_XMSSMT_OID_SHA2_20_2_192        0x21
#define WC_XMSSMT_OID_SHA2_20_4_192        0x22
#define WC_XMSSMT_OID_SHA2_40_2_192        0x23
#define WC_XMSSMT_OID_SHA2_40_4_192        0x24
#define WC_XMSSMT_OID_SHA2_40_8_192        0x25
#define WC_XMSSMT_OID_SHA2_60_3_192        0x26
#define WC_XMSSMT_OID_SHA2_60_6_192        0x27
#define WC_XMSSMT_OID_SHA2_60_12_192       0x28
#define WC_XMSSMT_OID_SHAKE256_20_2_256    0x29
#define WC_XMSSMT_OID_SHAKE256_20_4_256    0x2a
#define WC_XMSSMT_OID_SHAKE256_40_2_256    0x2b
#define WC_XMSSMT_OID_SHAKE256_40_4_256    0x2c
#define WC_XMSSMT_OID_SHAKE256_40_8_256    0x2d
#define WC_XMSSMT_OID_SHAKE256_60_3_256    0x2e
#define WC_XMSSMT_OID_SHAKE256_60_6_256    0x2f
#define WC_XMSSMT_OID_SHAKE256_60_12_256   0x30
#define WC_XMSSMT_OID_SHAKE256_20_2_192    0x31
#define WC_XMSSMT_OID_SHAKE256_20_4_192    0x32
#define WC_XMSSMT_OID_SHAKE256_40_2_192    0x33
#define WC_XMSSMT_OID_SHAKE256_40_4_192    0x34
#define WC_XMSSMT_OID_SHAKE256_40_8_192    0x35
#define WC_XMSSMT_OID_SHAKE256_60_3_192    0x36
#define WC_XMSSMT_OID_SHAKE256_60_6_192    0x37
#define WC_XMSSMT_OID_SHAKE256_60_12_192   0x38
#define WC_XMSSMT_OID_FIRST            WC_XMSSMT_OID_SHA2_20_2_256
#define WC_XMSSMT_OID_LAST             WC_XMSSMT_OID_SHAKE256_60_12_192


/* Type for hash address. */
typedef word32 HashAddress[8];

/* XMSS/XMSS^MT fixed parameters. */
typedef struct XmssParams {
    /* Hash algorithm to use. */
    word8  hash;
    /* Size of hash output. */
    word8  n;
    /* Number of bytes of padding before rest of hash data. */
    word8  pad_len;
    /* Number of values to chain = 2 * n + 3. */
    word8  wots_len;
    /* Number of bytes in each WOTS+ signature. */
    word16 wots_sig_len;
    /* Full height of tree. */
    word8  h;
    /* Height of tree each subtree. */
    word8  sub_h;
    /* Number of subtrees = h / sub_h. */
    word8  d;
    /* Number of bytes to encode index into in private/secret key. */
    word8  idx_len;
    /* Number of bytes in a signature. */
    word32 sig_len;
    /* Number of bytes in a secret/private key. */
    word32 sk_len;
    /* Number of bytes in a public key. */
    word8  pk_len;
    /* BDS parameter for fast C implementation. */
    word8  bds_k;
} XmssParams;

#ifndef XMSS_MAX_ID_LEN
#define XMSS_MAX_ID_LEN              32
#endif
#ifndef XMSS_MAX_LABEL_LEN
#define XMSS_MAX_LABEL_LEN           32
#endif

struct XmssKey {
    /* Public key. */
    unsigned char        pk[2 * WC_XMSS_MAX_N];
    /* OID that identifies parameters. */
    word32               oid;
    /* Indicates whether the parameters are for XMSS^MT. */
    int                  is_xmssmt;
    /* XMSS/XMSS^MT parameters. */
    const XmssParams*    params;
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
    /* Secret/private key. */
    unsigned char*       sk;
    /* Length of secret key. */
    word32               sk_len;
    /* Callback to write/update key. */
    wc_xmss_write_private_key_cb write_private_key;
    /* Callback to read key. */
    wc_xmss_read_private_key_cb  read_private_key;
    /* Context arg passed to callbacks. */
    void*                context;
#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
    /* Dynamic memory hint. */
    void*                heap;
    /* State of key. */
    enum wc_XmssState    state;
#ifdef WOLF_CRYPTO_CB
    /* Device Identifier. */
    int                  devId;
    /* Per-device opaque context, populated by the callback. */
    void*                devCtx;
#endif
#ifdef WOLF_PRIVATE_KEY_ID
    /* Optional device-side key identifier. */
    byte                 id[XMSS_MAX_ID_LEN];
    int                  idLen;
    /* Optional device-side key label. */
    char                 label[XMSS_MAX_LABEL_LEN];
    int                  labelLen;
#endif
};

#ifndef WC_XMSSKEY_TYPE_DEFINED
    typedef struct XmssKey XmssKey;
    #define WC_XMSSKEY_TYPE_DEFINED
#endif

typedef struct XmssState {
    const XmssParams* params;
    void* heap;

    /* Digest is assumed to be at the end. */
    union {
    #ifdef WC_XMSS_SHA256
       wc_Sha256 sha256;
    #endif
    #ifdef WC_XMSS_SHA512
       wc_Sha512 sha512;
    #endif
    #if defined(WC_XMSS_SHAKE128) || defined(WC_XMSS_SHAKE256)
       wc_Shake shake;
    #endif
    } digest;
#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) && \
    !defined(WC_XMSS_FULL_HASH)
    ALIGN16 word32 dgst_state[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
#endif
    ALIGN16 byte prf_buf[WC_XMSS_HASH_PRF_MAX_DATA_LEN];
    ALIGN16 byte buf[WC_XMSS_HASH_MAX_DATA_LEN];
    ALIGN16 byte pk[WC_XMSS_MAX_WOTS_SIG_LEN];
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
    ALIGN16 byte stack[WC_XMSS_MAX_STACK_LEN];
#else
    ALIGN16 byte stack[WC_XMSS_ADDR_LEN];
#endif
    byte encMsg[WC_XMSS_MAX_WOTS_LEN];
    HashAddress addr;

    int ret;
} XmssState;

#ifdef __cplusplus
    extern "C" {
#endif

WOLFSSL_API int  wc_XmssKey_Init(XmssKey* key, void* heap, int devId);
#ifdef WOLF_PRIVATE_KEY_ID
WOLFSSL_API int  wc_XmssKey_InitId(XmssKey* key, const unsigned char* id,
    int len, void* heap, int devId);
WOLFSSL_API int  wc_XmssKey_InitLabel(XmssKey* key, const char* label,
    void* heap, int devId);
#endif
WOLFSSL_API int  wc_XmssKey_SetParamStr(XmssKey* key, const char* str);
WOLFSSL_API int  wc_XmssKey_GetParamStr(const XmssKey* key, const char** str);
#ifndef WOLFSSL_XMSS_VERIFY_ONLY
WOLFSSL_API int  wc_XmssKey_SetWriteCb(XmssKey* key,
    wc_xmss_write_private_key_cb write_cb);
WOLFSSL_API int  wc_XmssKey_SetReadCb(XmssKey* key,
    wc_xmss_read_private_key_cb read_cb);
WOLFSSL_API int  wc_XmssKey_SetContext(XmssKey* key, void* context);
WOLFSSL_API int  wc_XmssKey_MakeKey(XmssKey* key, WC_RNG* rng);
WOLFSSL_API int  wc_XmssKey_Reload(XmssKey* key);
WOLFSSL_API int  wc_XmssKey_GetPrivLen(const XmssKey* key, word32* len);
WOLFSSL_API int  wc_XmssKey_Sign(XmssKey* key, byte* sig, word32* sigSz,
    const byte* msg, int msgSz);
WOLFSSL_API int  wc_XmssKey_SigsLeft(XmssKey* key);
WOLFSSL_API int  wc_XmssKey_PublicKeyToDer(const XmssKey* key, byte* output,
    word32 outLen, int withAlg);
#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
WOLFSSL_API void wc_XmssKey_Free(XmssKey* key);
WOLFSSL_API int  wc_XmssKey_GetSigLen(const XmssKey* key, word32* len);
WOLFSSL_API int  wc_XmssKey_GetPubLen(const XmssKey* key, word32* len);
WOLFSSL_API int  wc_XmssKey_ExportPub(XmssKey* keyDst, const XmssKey* keySrc);
WOLFSSL_API int  wc_XmssKey_ExportPub_ex(XmssKey* keyDst, const XmssKey* keySrc,
    void* heap, int devId);
WOLFSSL_API int  wc_XmssKey_ExportPubRaw(const XmssKey* key, byte* out,
    word32* outLen);
WOLFSSL_API int  wc_XmssKey_ImportPubRaw(XmssKey* key, const byte* in,
    word32 inLen);
WOLFSSL_API int  wc_XmssKey_ImportPubRaw_ex(XmssKey* key, const byte* in,
    word32 inLen, int is_xmssmt);
WOLFSSL_API int  wc_XmssKey_Verify(XmssKey* key, const byte* sig, word32 sigSz,
    const byte* msg, int msgSz);

WOLFSSL_LOCAL int wc_xmssmt_keygen(XmssState *state, const unsigned char* seed,
    unsigned char *sk, unsigned char *pk);
WOLFSSL_LOCAL int wc_xmss_keygen(XmssState *state, const unsigned char* seed,
    unsigned char *sk, unsigned char *pk);

WOLFSSL_LOCAL int wc_xmssmt_sign(XmssState *state, const unsigned char *m,
    word32 mlen, unsigned char *sk, unsigned char *sm);
WOLFSSL_LOCAL int wc_xmss_sign(XmssState *state, const unsigned char *m,
    word32 mlen, unsigned char *sk, unsigned char *sm);

WOLFSSL_LOCAL int wc_xmss_sigsleft(const XmssParams* params, unsigned char* sk);

WOLFSSL_LOCAL int wc_xmssmt_verify(XmssState *state, const unsigned char *m,
    word32 mlen, const unsigned char *sm, const unsigned char *pk);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* WOLFSSL_HAVE_XMSS */
#endif /* WC_XMSS_H */
