Add XMSS-SM3 signature

This commit is contained in:
Zhi Guan
2025-12-18 18:35:15 +08:00
parent 4791a30466
commit a03f5132cd
7 changed files with 2434 additions and 821 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
* Copyright 2014-2025 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
@@ -17,6 +17,8 @@
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -26,57 +26,221 @@ extern "C" {
#endif
// TODO: cache ADRS in SIGN_CTX
// Crosscheck with data from xmss-reference (SHA-256), except the XMSS signature.
#if defined(ENABLE_XMSS_CROSSCHECK) && defined(ENABLE_SHA2)
# define HASH256_CTX SHA256_CTX
# define hash256_init sha256_init
# define hash256_update sha256_update
# define hash256_finish sha256_finish
# define hash256_digest sha256_digest
# define LMS_HASH256_10 XMSS_SHA256_10
# define LMS_HASH256_16 XMSS_SHA256_16
# define LMS_HASH256_20 XMSS_SHA256_20
# define HASH256_CTX SHA256_CTX
# define hash256_init sha256_init
# define hash256_update sha256_update
# define hash256_finish sha256_finish
# define XMSS_HASH256_10_256 XMSS_SHA2_10_256
# define XMSS_HASH256_16_256 XMSS_SHA2_16_256
# define XMSS_HASH256_20_256 XMSS_SHA2_20_256
# define XMSS_HASH256_10_256_NAME "XMSS_SHA2_10_256"
# define XMSS_HASH256_16_256_NAME "XMSS_SHA2_16_256"
# define XMSS_HASH256_20_256_NAME "XMSS_SHA2_20_256"
#else
# define HASH256_CTX SM3_CTX
# define hash256_init sm3_init
# define hash256_update sm3_update
# define hash256_finish sm3_finish
# define hash256_digest sm3_digest
# define LMS_HASH256_10 XMSS_SM3_10
# define LMS_HASH256_16 XMSS_SM3_16
# define LMS_HASH256_20 XMSS_SM3_20
# define HASH256_CTX SM3_CTX
# define hash256_init sm3_init
# define hash256_update sm3_update
# define hash256_finish sm3_finish
# define XMSS_HASH256_10_256 XMSS_SM3_10_256
# define XMSS_HASH256_16_256 XMSS_SM3_16_256
# define XMSS_HASH256_20_256 XMSS_SM3_20_256
# define XMSS_HASH256_10_256_NAME "XMSS_SM3_10_256"
# define XMSS_HASH256_16_256_NAME "XMSS_SM3_16_256"
# define XMSS_HASH256_20_256_NAME "XMSS_SM3_20_256"
#endif
// from RFC 8391 table 6
enum {
WOTSP_RESERVED = 0x00000000,
WOTSP_SHA2_256 = 0x00000001,
WOTSP_SHA2_512 = 0x00000002,
WOTSP_SHAKE_256 = 0x00000003,
WOTSP_SHAKE_512 = 0x00000004,
};
// from RFC 8391 table 7
enum {
XMSS_RESERVED = 0x00000000,
XMSS_SHA2_10_256 = 0x00000001,
XMSS_SHA2_16_256 = 0x00000002,
XMSS_SHA2_20_256 = 0x00000003,
XMSS_SHA2_10_512 = 0x00000004,
XMSS_SHA2_16_512 = 0x00000005,
XMSS_SHA2_20_512 = 0x00000006,
XMSS_SHAKE_10_256 = 0x00000007,
XMSS_SHAKE_16_256 = 0x00000008,
XMSS_SHAKE_20_256 = 0x00000009,
XMSS_SHAKE_10_512 = 0x0000000A,
XMSS_SHAKE_16_512 = 0x0000000B,
XMSS_SHAKE_20_512 = 0x0000000C,
};
enum {
XMSS_SM3_10_256 = 0x10000001, // xmss tree height = 10, total 2^10 = 1 * 1024 sigs
XMSS_SM3_16_256 = 0x10000002, // xmss tree height = 16, total 2^16 = 64 * 1024 sigs
XMSS_SM3_20_256 = 0x10000003, // xmss tree height = 20, total 2^20 = 1024 * 1024 sigs
};
#define XMSS_ADRS_LAYER_ADDRESS 0
#define XMSS_ADRS_TREE_ADDRESS 0
enum {
XMSS_ADRS_TYPE_OTS = 0,
XMSS_ADRS_TYPE_LTREE = 1,
XMSS_ADRS_TYPE_HASHTREE = 2,
};
enum {
XMSS_ADRS_GENERATE_KEY = 0,
XMSS_ADRS_GENERATE_BITMASK = 1,
};
char *xmss_type_name(uint32_t xmss_type);
uint32_t xmss_type_from_name(const char *name);
int xmss_type_to_height(uint32_t xmss_type, size_t *height);
// rfc 8391 named algors only support w = 2^4 = 16
#define XMSS_WOTS_WINTERNITZ_W 16
#define WOTS_NUM_CHAINS 67
#define XMSS_WOTS_SIGNATURE_SIZE (sizeof(hash256_t) * WOTS_NUM_CHAINS)
#define XMSS_MIX_HEIGHT 16
#define XMSS_MAX_HEIGHT 20
// TODO:
// * change uint8[32] to hash256_t
// * key_to_bytes, from_bytes, use **out, *outlen style
// * support private key/ public key functions
typedef uint8_t xmss_adrs_t[32];
// Derive wots+ sk from a secret seed use the spec of xmss-reference.
void sm3_wots_derive_sk(const uint8_t secret[32],
const uint8_t seed[32], const uint8_t in_adrs[32],
hash256_t sk[67]); // change number 67 to a DEFINE
void sm3_wots_derive_pk(const hash256_t sk[67],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
hash256_t pk[67]);
void sm3_wots_do_sign(const hash256_t sk[67],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
const uint8_t dgst[32], hash256_t sig[67]);
void sm3_wots_sig_to_pk(const hash256_t sig[67], const uint8_t dgst[32],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
hash256_t pk[67]);
typedef struct {
uint32_t layer_address; // layer index of multi-tree, 0 for lowest layer (and xmss, and OTS ADRS)
uint64_t tree_address; // tree index of a layer, 0 for the left most (and xmss), in [0, 2^(h*(layers-1))-1]
uint32_t type; // in { XMSS_ADRS_TYPE_OTS, XMSS_ADRS_TYPE_LTREE, XMSS_ADRS_TYPE_HASHTREE }
void xmss_derive_root(const uint8_t xmss_secret[32], int height,
const uint8_t seed[32],
hash256_t *tree, uint8_t xmss_root[32]);
uint32_t ots_address; // index of a leaf (wots+ public key) of a layer-0 xmss tree, in [0, 2^h-1]
uint32_t chain_address; // index of wots+ chain, in [0, 67) when w = 16
uint32_t hash_address; // index of hash calls in a wots+ chain, in [0, w-1]
uint32_t key_and_mask; // in { XMSS_ADRS_GENERATE_KEY, XMSS_ADRS_GENERATE_BITMASK }
} XMSS_ADRS_OTS;
typedef struct {
uint32_t layer_address;
uint64_t tree_address;
uint32_t type; // = 1
uint32_t ltree_address;
uint32_t tree_height;
uint32_t tree_index;
uint32_t key_and_mask;
} XMSS_ADRS_LTREE;
typedef struct {
uint32_t layer_address;
uint64_t tree_address;
uint32_t type; // = 2
uint32_t padding; // = 0
uint32_t tree_height;
uint32_t tree_index;
uint32_t key_and_mask;
} XMSS_ADRS_HASHTREE;
void adrs_copy_layer_address(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_tree_address(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_type(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_ots_address(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_chain_address(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_hash_address(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_key_and_mask(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_ltree_address(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_tree_height(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_tree_index(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_copy_padding(xmss_adrs_t dst, const xmss_adrs_t src);
void adrs_set_layer_address(uint8_t adrs[32], uint32_t layer);
void adrs_set_tree_address(uint8_t adrs[32], uint64_t tree_addr);
void adrs_set_type(uint8_t adrs[32], uint32_t type);
void adrs_set_ots_address(uint8_t adrs[32], uint32_t address);
void adrs_set_chain_address(uint8_t adrs[32], uint32_t address);
void adrs_set_hash_address(uint8_t adrs[32], uint32_t address);
void adrs_set_ltree_address(uint8_t adrs[32], uint32_t address);
void adrs_set_padding(uint8_t adrs[32], uint32_t padding);
void adrs_set_tree_height(uint8_t adrs[32], uint32_t height);
void adrs_set_tree_index(uint8_t adrs[32], uint32_t index);
void adrs_set_key_and_mask(uint8_t adrs[32], uint8_t key_and_mask);
int xmss_adrs_print(FILE *fp, int fmt, int ind, const char *label, const hash256_t adrs);
typedef hash256_t wots_key_t[67];
typedef hash256_t wots_sig_t[67];
void wots_chain(const hash256_t x,
const hash256_t seed, const xmss_adrs_t adrs,
int start, int steps, hash256_t pk);
void wots_sk_to_pk(const wots_key_t sk,
const hash256_t seed, const xmss_adrs_t adrs,
wots_key_t pk);
void wots_sign(const wots_key_t sk,
const hash256_t seed, const xmss_adrs_t adrs,
const hash256_t dgst, wots_sig_t sig);
void wots_sig_to_pk(const wots_sig_t sig,
const hash256_t seed, const xmss_adrs_t adrs,
const hash256_t dgst, wots_key_t pk);
void wots_build_ltree(const wots_key_t pk,
const hash256_t seed, const xmss_adrs_t adrs,
hash256_t wots_root);
void wots_derive_sk(const hash256_t secret,
const hash256_t seed, const xmss_adrs_t adrs,
wots_key_t sk);
void wots_derive_root(const hash256_t secret,
const hash256_t seed, const xmss_adrs_t adrs,
hash256_t wots_root);
void xmss_build_tree(const hash256_t secret,
const hash256_t seed, const xmss_adrs_t adrs,
size_t height, hash256_t *tree);
void xmss_do_sign(const uint8_t xmss_secret[32], int index,
const uint8_t seed[32], const uint8_t in_adrs[32], int height,
const hash256_t *tree,
@@ -84,60 +248,55 @@ void xmss_do_sign(const uint8_t xmss_secret[32], int index,
hash256_t wots_sig[67],
hash256_t *auth_path);
void xmss_sig_to_root(const hash256_t wots_sig[67], int index, const hash256_t *auth_path,
const uint8_t seed[32], const uint8_t in_adrs[32], int height,
void xmss_sig_to_root(const hash256_t wots_sig[67],
const uint8_t seed[32], const uint8_t in_adrs[32],
const uint8_t dgst[32],
const hash256_t *auth_path, int height,
uint8_t xmss_root[32]);
enum {
XMSS_SM3_10 = 0x10000001,
XMSS_SM3_16 = 0x10000002,
XMSS_SM3_20 = 0x10000003,
XMSS_SHA256_10 = 0x00000001,
XMSS_SHA256_16 = 0x00000002,
XMSS_SHA256_20 = 0x00000003,
};
// delete this func
int xmss_height_from_oid(uint32_t *height, uint32_t id);
typedef struct {
uint32_t xmss_type;
uint8_t seed[32];
uint8_t root[32];
} XMSS_PUBLIC_KEY;
// PK = OID || root || SEED
// SK = idx || wots_sk || SK_PRF || root || SEED;
typedef struct {
uint32_t oid;
uint8_t seed[32];
uint8_t root[32];
XMSS_PUBLIC_KEY public_key;
// private key
uint8_t secret[32];
uint8_t prf_key[32];
uint32_t index; // change this to int, update every signing
hash256_t *tree;
uint8_t sk_prf[32]; // secret key for prf
uint32_t index;
hash256_t *tree; // merkle tree with wots+ public keys as leafs
} XMSS_KEY;
// TODO: support hash256_t tree[1]
#define XMSS_PUBLIC_KEY_SIZE (4 + 32 + 32) // = 68
#define XMSS_PRIVATE_KEY_SIZE (XMSS_PUBLIC_KEY_SIZE + 32 + 32 + 4) // = 136
// TODO: add public_key, private_key funcs
// TODO: key_update func
// TODO: build tree in private_key_from_bytes
int xmss_key_match_public_key(const XMSS_KEY *key, const XMSS_KEY *pub);
int xmss_key_generate(XMSS_KEY *key, uint32_t oid);
int xmss_key_print(FILE *fp, int fmt, int ind, const char *label, const XMSS_KEY *key);
int xmss_key_get_height(const XMSS_KEY *key, uint32_t *height);
int xmss_key_to_bytes(const XMSS_KEY *key, uint8_t *out, size_t *outlen);
int xmss_key_from_bytes(XMSS_KEY *key, const uint8_t *in, size_t inlen);
int xmss_public_key_to_bytes(const XMSS_KEY *key, uint8_t *out, size_t *outlen);
int xmss_public_key_from_bytes(XMSS_KEY *key, const uint8_t *in, size_t inlen);
int xmss_key_remaining_signs(const XMSS_KEY *key, size_t *count);
int xmss_public_key_to_bytes(const XMSS_KEY *key, uint8_t **out, size_t *outlen);
int xmss_public_key_from_bytes(XMSS_KEY *key, const uint8_t **in, size_t *inlen);
int xmss_public_key_print(FILE *fp, int fmt, int ind, const char *label, const XMSS_KEY *key);
int xmss_private_key_to_bytes(const XMSS_KEY *key, uint8_t **out, size_t *outlen);
int xmss_private_key_from_bytes(XMSS_KEY *key, const uint8_t **in, size_t *inlen);
int xmss_private_key_print(FILE *fp, int fmt, int ind, const char *label, const XMSS_KEY *key);
void xmss_key_cleanup(XMSS_KEY *key);
typedef struct {
uint8_t index[4];
uint32_t index; // < 2^(XMSS_MAX_HEIGHT) = 2^20, always encode to 4 bytes
uint8_t random[32];
hash256_t wots_sig[67];
hash256_t auth_path[XMSS_MAX_HEIGHT];
@@ -154,25 +313,217 @@ typedef struct {
int xmss_signature_size(uint32_t oid, size_t *siglen);
// TODO: impl this
int xmss_key_get_signature_size(const XMSS_KEY *key, size_t siglen);
int xmss_key_get_signature_size(const XMSS_KEY *key, size_t *siglen);
int xmss_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *in, size_t inlen);
int xmss_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const XMSS_SIGNATURE *sig);
typedef struct {
uint8_t random[32];
XMSS_PUBLIC_KEY xmss_public_key;
XMSS_SIGNATURE xmss_sig;
HASH256_CTX hash256_ctx;
// TODO: cache signing key
} XMSS_SIGN_CTX;
void randomized_tree_hash(const hash256_t left_child, const hash256_t right_child,
const hash256_t seed, const xmss_adrs_t tree_adrs,
hash256_t parent);
// TODO: change the API to LMS/HSS style
// TODO: remove const before XMSS_KEY in sign_init
int xmss_sign_init(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key);
void build_auth_path(const hash256_t *tree, int height, int index, hash256_t *path);
int xmss_sign_init(XMSS_SIGN_CTX *ctx, XMSS_KEY *key);
int xmss_sign_update(XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int xmss_sign_finish(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key, uint8_t *sigbuf, size_t *siglen);
int xmss_sign_finish(XMSS_SIGN_CTX *ctx, uint8_t *sigbuf, size_t *siglen);
int xmss_verify_init(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key, const uint8_t *sigbuf, size_t siglen);
int xmss_verify_update(XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int xmss_verify_finish(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key, const uint8_t *sigbuf, size_t siglen);
int xmss_verify_finish(XMSS_SIGN_CTX *ctx);
// TODO: optimize, define XMSSMT_TYPE_HASH256 and XMSSMT_TYPE_PARAMS
#if defined(ENABLE_XMSS_CROSSCHECK) && defined(ENABLE_SHA2)
#define XMSSMT_HASH256_20_2_256 XMSSMT_SHA2_20_2_256
#define XMSSMT_HASH256_20_4_256 XMSSMT_SHA2_20_4_256
#define XMSSMT_HASH256_40_2_256 XMSSMT_SHA2_40_2_256
#define XMSSMT_HASH256_40_4_256 XMSSMT_SHA2_40_4_256
#define XMSSMT_HASH256_40_8_256 XMSSMT_SHA2_40_8_256
#define XMSSMT_HASH256_60_3_256 XMSSMT_SHA2_60_3_256
#define XMSSMT_HASH256_60_6_256 XMSSMT_SHA2_60_6_256
#define XMSSMT_HASH256_60_12_256 XMSSMT_SHA2_60_12_256
#define XMSSMT_HASH256_20_2_256_NAME "XMSSMT_SHA2_20_2_256"
#define XMSSMT_HASH256_20_4_256_NAME "XMSSMT_SHA2_20_4_256"
#define XMSSMT_HASH256_40_2_256_NAME "XMSSMT_SHA2_40_2_256"
#define XMSSMT_HASH256_40_4_256_NAME "XMSSMT_SHA2_40_4_256"
#define XMSSMT_HASH256_40_8_256_NAME "XMSSMT_SHA2_40_8_256"
#define XMSSMT_HASH256_60_3_256_NAME "XMSSMT_SHA2_60_3_256"
#define XMSSMT_HASH256_60_6_256_NAME "XMSSMT_SHA2_60_6_256"
#define XMSSMT_HASH256_60_12_256_NAME "XMSSMT_SHA2_60_12_256"
#else
#define XMSSMT_HASH256_20_2_256 XMSSMT_SM3_20_2_256
#define XMSSMT_HASH256_20_4_256 XMSSMT_SM3_20_4_256
#define XMSSMT_HASH256_40_2_256 XMSSMT_SM3_40_2_256
#define XMSSMT_HASH256_40_4_256 XMSSMT_SM3_40_4_256
#define XMSSMT_HASH256_40_8_256 XMSSMT_SM3_40_8_256
#define XMSSMT_HASH256_60_3_256 XMSSMT_SM3_60_3_256
#define XMSSMT_HASH256_60_6_256 XMSSMT_SM3_60_6_256
#define XMSSMT_HASH256_60_12_256 XMSSMT_SM3_60_12_256
#define XMSSMT_HASH256_20_2_256_NAME "XMSSMT_SM3_20_2_256"
#define XMSSMT_HASH256_20_4_256_NAME "XMSSMT_SM3_20_4_256"
#define XMSSMT_HASH256_40_2_256_NAME "XMSSMT_SM3_40_2_256"
#define XMSSMT_HASH256_40_4_256_NAME "XMSSMT_SM3_40_4_256"
#define XMSSMT_HASH256_40_8_256_NAME "XMSSMT_SM3_40_8_256"
#define XMSSMT_HASH256_60_3_256_NAME "XMSSMT_SM3_60_3_256"
#define XMSSMT_HASH256_60_6_256_NAME "XMSSMT_SM3_60_6_256"
#define XMSSMT_HASH256_60_12_256_NAME "XMSSMT_SM3_60_12_256"
#endif
#define XMSSMT_MAX_HEIGHT 60
#define XMSSMT_MIN_LAYERS 2
#define XMSSMT_MAX_LAYERS 12
//#define XMSSMT_MIN_XMSS_HEIGHT 5
//#define XMSSMT_MAX_XMSS_HEIGHT 20
enum { // layers height sigs private
XMSSMT_SM3_20_2_256 = 0x00000001, // 2 10 1024*1024 (2^11 - 1) * 2
XMSSMT_SM3_20_4_256 = 0x00000002, // 4 5
XMSSMT_SM3_40_2_256 = 0x00000003, // 2 20
XMSSMT_SM3_40_4_256 = 0x00000004, // 4 10
XMSSMT_SM3_40_8_256 = 0x00000005, // 8 5
XMSSMT_SM3_60_3_256 = 0x00000006, // 3 20
XMSSMT_SM3_60_6_256 = 0x00000007, // 6 10
XMSSMT_SM3_60_12_256 = 0x00000008, // 12 5
};
enum {
// from RFC 8391 table 8
XMSSMT_RESERVED = 0x00000000,
XMSSMT_SHA2_20_2_256 = 0x00000001,
XMSSMT_SHA2_20_4_256 = 0x00000002,
XMSSMT_SHA2_40_2_256 = 0x00000003,
XMSSMT_SHA2_40_4_256 = 0x00000004,
XMSSMT_SHA2_40_8_256 = 0x00000005,
XMSSMT_SHA2_60_3_256 = 0x00000006,
XMSSMT_SHA2_60_6_256 = 0x00000007,
XMSSMT_SHA2_60_12_256 = 0x00000008,
XMSSMT_SHA2_20_2_512 = 0x00000009,
XMSSMT_SHA2_20_4_512 = 0x0000000A,
XMSSMT_SHA2_40_2_512 = 0x0000000B,
XMSSMT_SHA2_40_4_512 = 0x0000000C,
XMSSMT_SHA2_40_8_512 = 0x0000000D,
XMSSMT_SHA2_60_3_512 = 0x0000000E,
XMSSMT_SHA2_60_6_512 = 0x0000000F,
XMSSMT_SHA2_60_12_512 = 0x00000010,
XMSSMT_SHAKE_20_2_256 = 0x00000011,
XMSSMT_SHAKE_20_4_256 = 0x00000012,
XMSSMT_SHAKE_40_2_256 = 0x00000013,
XMSSMT_SHAKE_40_4_256 = 0x00000014,
XMSSMT_SHAKE_40_8_256 = 0x00000015,
XMSSMT_SHAKE_60_3_256 = 0x00000016,
XMSSMT_SHAKE_60_6_256 = 0x00000017,
XMSSMT_SHAKE_60_12_256 = 0x00000018,
XMSSMT_SHAKE_20_2_512 = 0x00000019,
XMSSMT_SHAKE_20_4_512 = 0x0000001A,
XMSSMT_SHAKE_40_2_512 = 0x0000001B,
XMSSMT_SHAKE_40_4_512 = 0x0000001C,
XMSSMT_SHAKE_40_8_512 = 0x0000001D,
XMSSMT_SHAKE_60_3_512 = 0x0000001E,
XMSSMT_SHAKE_60_6_512 = 0x0000001F,
XMSSMT_SHAKE_60_12_512 = 0x00000020,
};
char *xmssmt_type_name(uint32_t xmssmt_type);
uint32_t xmssmt_type_from_name(const char *name);
int xmssmt_type_to_height_and_layers(uint32_t xmssmt_type, size_t *height, size_t *layers);
typedef struct {
uint32_t xmssmt_type;
hash256_t seed;
hash256_t root;
} XMSSMT_PUBLIC_KEY;
typedef struct {
XMSSMT_PUBLIC_KEY public_key;
hash256_t secret;
hash256_t sk_prf;
uint64_t index; // in [0, 2^60 - 1]
//hash256_t *trees;
//XMSS_SIGNATURE xmss_sigs[XMSSMT_MAX_LAYERS - 1];
} XMSSMT_KEY;
int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type);
typedef struct {
uint64_t index;
hash256_t random;
hash256_t wots_sigs[XMSSMT_MAX_LAYERS][67];
hash256_t auth_path[XMSSMT_MAX_HEIGHT];
} XMSSMT_SIGNATURE;
#define XMSSMT_SIGNATURE_MAX_SIZE \
(sizeof(uint64_t) + 32 + sizeof(wots_sig_t) * XMSSMT_MAX_LAYERS + sizeof(hash256_t) * XMSSMT_MAX_HEIGHT)
int xmssmt_index_to_bytes(uint64_t index, uint32_t xmssmt_type, uint8_t **out, size_t *outlen);
int xmssmt_index_from_bytes(uint64_t *index, uint32_t xmssmt_type, const uint8_t **in, size_t *inlen);
int xmssmt_signature_size(uint32_t xmssmt_type, size_t *siglen);
int xmssmt_signature_to_bytes(const XMSSMT_SIGNATURE *sig, uint32_t xmssmt_type, uint8_t **out, size_t *outlen);
int xmssmt_signature_from_bytes(XMSSMT_SIGNATURE *sig, uint32_t xmssmt_type, const uint8_t **in, size_t *inlen);
int xmssmt_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const XMSSMT_SIGNATURE *sig, uint32_t xmssmt_type);
int xmssmt_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen, uint32_t xmssmt_type);
typedef struct {
XMSS_SIGN_CTX xmss_sign_ctx;
// TODO: more...
} XMSSMT_SIGN_CTX;
int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key);
int xmssmt_sign_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int xmssmt_sign_finish(XMSSMT_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen);
int xmssmt_sign_finish_ex(XMSSMT_SIGN_CTX *ctx, XMSSMT_SIGNATURE *sig);
int xmssmt_verify_init_ex(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const XMSSMT_SIGNATURE *sig);
int xmssmt_verify_init(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const uint8_t *sigbuf, size_t siglen);
int xmssmt_verify_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int xmssmt_verify_finish(XMSSMT_SIGN_CTX *ctx);
#ifdef __cplusplus