Update XMSS

This commit is contained in:
Zhi Guan
2026-01-04 22:37:38 +08:00
parent 65be2ce54b
commit 83ef4e88bf
3 changed files with 192 additions and 310 deletions

View File

@@ -26,69 +26,21 @@ extern "C" {
#endif
// 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 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"
# define HASH256_CTX SHA256_CTX
# define hash256_init sha256_init
# define hash256_update sha256_update
# define hash256_finish sha256_finish
#else
# 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"
# define HASH256_CTX SM3_CTX
# define hash256_init sm3_init
# define hash256_update sm3_update
# define hash256_finish sm3_finish
#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
// ADRS scheme
enum {
XMSS_ADRS_TYPE_OTS = 0,
@@ -101,47 +53,10 @@ enum {
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
typedef uint8_t xmss_adrs_t[32];
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 }
uint32_t type; // = XMSS_ADRS_TYPE_OTS
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]
@@ -151,7 +66,7 @@ typedef struct {
typedef struct {
uint32_t layer_address;
uint64_t tree_address;
uint32_t type; // = 1
uint32_t type; // = XMSS_ADRS_TYPE_LTREE
uint32_t ltree_address;
uint32_t tree_height;
uint32_t tree_index;
@@ -161,49 +76,50 @@ typedef struct {
typedef struct {
uint32_t layer_address;
uint64_t tree_address;
uint32_t type; // = 2
uint32_t type; // = XMSS_ADRS_TYPE_HASHTREE
uint32_t padding; // = 0
uint32_t tree_height;
uint32_t tree_index;
uint32_t key_and_mask;
} XMSS_ADRS_HASHTREE;
typedef uint8_t xmss_adrs_t[32];
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_copy_chain_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_hash_address(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_key_and_mask(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], uint32_t key_and_mask);
void adrs_set_layer_address(xmss_adrs_t adrs, uint32_t layer);
void adrs_set_tree_address(xmss_adrs_t adrs, uint64_t tree_addr);
void adrs_set_type(xmss_adrs_t adrs, uint32_t type);
void adrs_set_ots_address(xmss_adrs_t adrs, uint32_t address);
void adrs_set_ltree_address(xmss_adrs_t adrs, uint32_t address);
void adrs_set_padding(xmss_adrs_t adrs, uint32_t padding);
void adrs_set_chain_address(xmss_adrs_t adrs, uint32_t address);
void adrs_set_tree_height(xmss_adrs_t adrs, uint32_t height);
void adrs_set_hash_address(xmss_adrs_t adrs, uint32_t address);
void adrs_set_tree_index(xmss_adrs_t adrs, uint32_t index);
void adrs_set_key_and_mask(xmss_adrs_t adrs, uint32_t key_and_mask);
int xmss_adrs_print(FILE *fp, int fmt, int ind, const char *label, const hash256_t adrs);
// WOTS+ with SM3/SHA256
#define WOTS_WINTERNITZ_W 16 // rfc 8391 named algors only support w = 2^4 = 16
#define WOTS_NUM_CHAINS 67
typedef hash256_t wots_key_t[WOTS_NUM_CHAINS];
typedef hash256_t wots_sig_t[WOTS_NUM_CHAINS];
typedef hash256_t wots_key_t[67];
typedef hash256_t wots_sig_t[67];
void wots_derive_sk(const hash256_t secret,
const hash256_t seed, const xmss_adrs_t adrs,
wots_key_t sk);
@@ -229,11 +145,59 @@ int wots_verify(const hash256_t wots_root,
const hash256_t seed, const xmss_adrs_t adrs,
const hash256_t dgst, const wots_sig_t sig);
size_t xmss_tree_num_nodes(size_t height);
// 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, // height = 10, sigs = 2^10
XMSS_SM3_16_256 = 0x10000002, // height = 16, sigs = 2^16
XMSS_SM3_20_256 = 0x10000003, // height = 20, sigs = 2^20
};
#define XMSS_MAX_HEIGHT 20
// Crosscheck with data from xmss-reference (SHA-256), except the XMSS signature.
#if defined(ENABLE_XMSS_CROSSCHECK) && defined(ENABLE_SHA2)
# 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 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
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);
size_t xmss_num_tree_nodes(size_t height);
void xmss_build_tree(const hash256_t secret,
const hash256_t seed, const xmss_adrs_t adrs,
size_t height, hash256_t *tree); // tree[xmss_tree_num_nodes(height)]
size_t height, hash256_t *tree); // tree[xmss_num_tree_nodes(height)]
void xmss_build_auth_path(const hash256_t *tree, size_t height,
uint32_t index, hash256_t *auth_path); // auth_path[height]
void xmss_build_root(const hash256_t wots_root, uint32_t index,
@@ -260,7 +224,6 @@ typedef struct {
#define XMSS_PRIVATE_KEY_SIZE (XMSS_PUBLIC_KEY_SIZE + 32 + 32 + 4) // = 136
int xmss_key_generate(XMSS_KEY *key, uint32_t xmss_type);
int xmss_key_remaining_signs(const XMSS_KEY *key, size_t *count);
void xmss_key_cleanup(XMSS_KEY *key);
@@ -272,7 +235,6 @@ 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);
typedef struct {
uint32_t index; // < 2^(XMSS_MAX_HEIGHT) = 2^20, always encode to 4 bytes
uint8_t random[32];
@@ -286,7 +248,6 @@ typedef struct {
#define XMSS_SIGNATURE_MIN_SIZE (4 + 32 + 32*67 + 32 * XMSS_MIN_HEIGHT) // = 2500 bytes
#define XMSS_SIGNATURE_MAX_SIZE (4 + 32 + 32*67 + 32 * XMSS_MAX_HEIGHT) // = 2820 bytes
int xmss_signature_size(uint32_t xmss_type, 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);
@@ -306,71 +267,19 @@ int xmss_verify_update(XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int xmss_verify_finish(XMSS_SIGN_CTX *ctx);
#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 {
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
XMSSMT_SM3_20_2_256 = 0x00000001,
XMSSMT_SM3_20_4_256 = 0x00000002,
XMSSMT_SM3_40_2_256 = 0x00000003,
XMSSMT_SM3_40_4_256 = 0x00000004,
XMSSMT_SM3_40_8_256 = 0x00000005,
XMSSMT_SM3_60_3_256 = 0x00000006,
XMSSMT_SM3_60_6_256 = 0x00000007,
XMSSMT_SM3_60_12_256 = 0x00000008,
};
// from rfc 8391 table 8
enum {
// from RFC 8391 table 8
XMSSMT_RESERVED = 0x00000000,
XMSSMT_SHA2_20_2_256 = 0x00000001,
XMSSMT_SHA2_20_4_256 = 0x00000002,
@@ -380,37 +289,53 @@ enum {
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,
};
#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
char *xmssmt_type_name(uint32_t xmssmt_type);
uint32_t xmssmt_type_from_name(const char *name);
#define XMSSMT_MAX_HEIGHT 60
#define XMSSMT_MAX_LAYERS 12
int xmssmt_type_to_height_and_layers(uint32_t xmssmt_type, size_t *height, size_t *layers);
size_t xmssmt_num_trees_nodes(size_t height, size_t layers);
typedef struct {
uint32_t xmssmt_type;
@@ -429,33 +354,43 @@ typedef struct {
wots_sig_t wots_sigs[XMSSMT_MAX_LAYERS - 1];
} XMSSMT_KEY;
/*
XMSSMT_SM3_20_2_256: 133,287 bytes
XMSSMT_SM3_20_4_256: 14,631 bytes
XMSSMT_SM3_40_2_256: 134,219,945 bytes
XMSSMT_SM3_40_4_256: 268,585 bytes
XMSSMT_SM3_40_8_256: 31,273 bytes
XMSSMT_SM3_60_3_256: 201,330,924 bytes
XMSSMT_SM3_60_6_256: 403,884 bytes
XMSSMT_SM3_60_12_256: 47,916 bytes
*/
int xmssmt_private_key_size(uint32_t xmssmt_type, size_t *len);
int xmssmt_key_build_auth_path(const XMSSMT_KEY *key, hash256_t *auth_path);
int xmssmt_build_auth_path(const hash256_t *tree, size_t height, size_t layers, uint64_t index, hash256_t *auth_path);
int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type);
int xmssmt_key_update(XMSSMT_KEY *key);
int xmssmt_public_key_to_bytes(const XMSSMT_KEY *key, uint8_t **out, size_t *outlen);
int xmssmt_public_key_from_bytes(XMSSMT_KEY *key, const uint8_t **in, size_t *inlen);
int xmssmt_public_key_print(FILE *fp, int fmt, int ind, const char *label, const XMSSMT_KEY *key);
int xmssmt_private_key_to_bytes(const XMSSMT_KEY *key, uint8_t **out, size_t *outlen);
int xmssmt_private_key_from_bytes(XMSSMT_KEY *key, const uint8_t **in, size_t *inlen);
int xmssmt_private_key_print(FILE *fp, int fmt, int ind, const char *label, const XMSSMT_KEY *key);
void xmssmt_key_cleanup(XMSSMT_KEY *key);
typedef struct {
uint64_t index;
hash256_t random;
hash256_t wots_sigs[XMSSMT_MAX_LAYERS][67];
wots_sig_t wots_sigs[XMSSMT_MAX_LAYERS];
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);
#define XMSSMT_SIGNATURE_MAX_SIZE \
(sizeof(uint64_t) + sizeof(hash256_t) + sizeof(wots_sig_t)*XMSSMT_MAX_LAYERS + sizeof(hash256_t)*XMSSMT_MAX_HEIGHT) // = 27688 bytes
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);
@@ -474,12 +409,11 @@ 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_init(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const uint8_t *sig, 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
}
#endif

View File

@@ -22,21 +22,6 @@
#include <gmssl/xmss.h>
// TODO: not here
static uint8_t bn256_zero[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const uint8_t bn256_one[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
};
static const uint8_t hash256_two[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -174,30 +159,6 @@ void adrs_set_key_and_mask(uint8_t adrs[32], uint32_t key_and_mask) {
PUTU32(adrs + 4*7, key_and_mask);
}
int xmss_adrs_print(FILE *fp, int fmt, int ind, const char *label, const hash256_t adrs)
{
uint32_t layer_address;
@@ -273,9 +234,6 @@ int xmss_adrs_print(FILE *fp, int fmt, int ind, const char *label, const hash256
return 1;
}
void wots_derive_sk(const hash256_t secret,
const hash256_t seed, const xmss_adrs_t ots_adrs,
wots_key_t sk)
@@ -313,6 +271,7 @@ void wots_chain(const hash256_t x,
const hash256_t seed, const xmss_adrs_t ots_adrs,
int start, int steps, hash256_t pk)
{
const hash256_t hash256_zero = {0};
HASH256_CTX ctx;
uint8_t adrs[32];
int i;
@@ -355,7 +314,7 @@ void wots_chain(const hash256_t x,
// tmp = f(key, tmp xor bitmask)
gmssl_memxor(pk, pk, bitmask, 32);
hash256_init(&ctx);
hash256_update(&ctx, bn256_zero, 32);
hash256_update(&ctx, hash256_zero, 32);
hash256_update(&ctx, key, 32);
hash256_update(&ctx, pk, 32);
hash256_finish(&ctx, pk);
@@ -457,6 +416,12 @@ static void randomized_tree_hash(const hash256_t left_child, const hash256_t rig
const hash256_t seed, const xmss_adrs_t tree_adrs,
hash256_t parent)
{
static const uint8_t hash256_one[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
};
HASH256_CTX ctx;
xmss_adrs_t adrs;
hash256_t key;
@@ -499,7 +464,7 @@ static void randomized_tree_hash(const hash256_t left_child, const hash256_t rig
gmssl_memxor(bm_0, bm_0, left_child, sizeof(hash256_t));
gmssl_memxor(bm_1, bm_1, right_child, sizeof(hash256_t));
hash256_init(&ctx);
hash256_update(&ctx, bn256_one, sizeof(hash256_t));
hash256_update(&ctx, hash256_one, sizeof(hash256_t));
hash256_update(&ctx, key, sizeof(hash256_t));
hash256_update(&ctx, bm_0, sizeof(hash256_t));
hash256_update(&ctx, bm_1, sizeof(hash256_t));
@@ -1196,9 +1161,6 @@ int xmss_sign_init(XMSS_SIGN_CTX *ctx, XMSS_KEY *key)
return 1;
}
int xmss_sign_update(XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
{
if (data && datalen) {
@@ -1388,14 +1350,14 @@ int xmssmt_type_to_height_and_layers(uint32_t xmssmt_type, size_t *height, size_
return 1;
}
size_t xmss_tree_num_nodes(size_t height)
size_t xmss_num_tree_nodes(size_t height)
{
return (1 << (height + 1)) - 1;
}
size_t xmssmt_trees_num_nodes(size_t height, size_t layers)
size_t xmssmt_num_trees_nodes(size_t height, size_t layers)
{
return xmss_tree_num_nodes(height/layers) * layers;
return xmss_num_tree_nodes(height/layers) * layers;
}
int xmssmt_public_key_to_bytes(const XMSSMT_KEY *key, uint8_t **out, size_t *outlen)
@@ -1475,7 +1437,7 @@ int xmssmt_private_key_to_bytes(const XMSSMT_KEY *key, uint8_t **out, size_t *ou
hash256_to_bytes(key->secret, out, outlen);
hash256_to_bytes(key->sk_prf, out, outlen);
treeslen = sizeof(hash256_t) * xmssmt_trees_num_nodes(height, layers);
treeslen = sizeof(hash256_t) * xmssmt_num_trees_nodes(height, layers);
if (out && *out) {
memcpy(*out, key->trees, treeslen);
*out += treeslen;
@@ -1524,7 +1486,7 @@ int xmssmt_private_key_from_bytes(XMSSMT_KEY *key, const uint8_t **in, size_t *i
error_print();
return -1;
}
treeslen = sizeof(hash256_t) * xmssmt_trees_num_nodes(height, layers);
treeslen = sizeof(hash256_t) * xmssmt_num_trees_nodes(height, layers);
if (!(key->trees = malloc(treeslen))) {
error_print();
return -1;
@@ -1590,7 +1552,7 @@ int xmssmt_key_update(XMSSMT_KEY *key)
wots_derive_sk(key->secret, key->public_key.seed, adrs, key->wots_sigs[layer]);
xmss_root = tree[tree_root_offset(height/layers)];
wots_sign(key->wots_sigs[layer], key->public_key.seed, adrs, xmss_root, key->wots_sigs[layer]);
tree += xmss_tree_num_nodes(height/layers);
tree += xmss_num_tree_nodes(height/layers);
}
key->index++;
@@ -1598,7 +1560,17 @@ int xmssmt_key_update(XMSSMT_KEY *key)
return 1;
}
void xmssmt_key_cleanup(XMSSMT_KEY *key)
{
if (key) {
gmssl_secure_clear(key->secret, sizeof(hash256_t));
gmssl_secure_clear(key->sk_prf, sizeof(hash256_t));
if (key->trees) {
free(key->trees);
}
memset(key, 0, sizeof(XMSSMT_KEY));
}
}
int xmssmt_key_generate_ex(XMSSMT_KEY *key, uint32_t xmssmt_type,
const hash256_t seed, const hash256_t secret, const hash256_t sk_prf)
@@ -1641,7 +1613,7 @@ int xmssmt_key_generate_ex(XMSSMT_KEY *key, uint32_t xmssmt_type,
key->index = 0;
// malloc tress
if (!(key->trees = malloc(xmssmt_trees_num_nodes(height, layers) * sizeof(hash256_t)))) {
if (!(key->trees = malloc(xmssmt_num_trees_nodes(height, layers) * sizeof(hash256_t)))) {
error_print();
return -1;
}
@@ -1658,7 +1630,7 @@ int xmssmt_key_generate_ex(XMSSMT_KEY *key, uint32_t xmssmt_type,
xmss_root = tree[tree_root_offset(height/layers)];
tree += xmss_tree_num_nodes(height/layers);
tree += xmss_num_tree_nodes(height/layers);
// sign xmss_root with higher layer
if (layer < layers - 1) {
@@ -1670,7 +1642,7 @@ int xmssmt_key_generate_ex(XMSSMT_KEY *key, uint32_t xmssmt_type,
/*
hash256_t *tree2 = key->trees + xmss_tree_num_nodes(height/layers) * layer;
hash256_t *tree2 = key->trees + xmss_num_tree_nodes(height/layers) * layer;
hash256_t xmss_root2 = tree2[tree_root_offset(height/layers)];
@@ -1713,7 +1685,7 @@ int xmssmt_key_generate_ex(XMSSMT_KEY *key, uint32_t xmssmt_type,
adrs_set_tree_index(adrs, tree_index);
wots_pk_to_root(wots_pk, key->public_key.seed, adrs, root);
tree += xmss_tree_num_nodes(height/layers);
tree += xmss_num_tree_nodes(height/layers);
if (memcmp(root, tree[0], 32) != 0) {
error_print();
@@ -1754,33 +1726,22 @@ int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type)
return 1;
}
// change API as xmss_build_auth_path
int xmssmt_key_build_auth_path(const XMSSMT_KEY *key, hash256_t *auth_path)
// not checked
int xmssmt_build_auth_path(const hash256_t *tree, size_t height, size_t layers, uint64_t index, hash256_t *auth_path)
{
size_t height;
size_t layers;
uint64_t index;
const hash256_t *tree;
size_t i;
if (!key || !auth_path) {
if (!tree || !auth_path) {
error_print();
return -1;
}
if (xmssmt_type_to_height_and_layers(key->public_key.xmssmt_type, &height, &layers) != 1) {
error_print();
return -1;
}
index = key->index;
tree = key->trees;
for (i = 0; i < layers; i++) {
uint64_t local_index = index & ((1 << (height/layers)) - 1);
xmss_build_auth_path(tree, height/layers, local_index, auth_path);
auth_path += height/layers;
index >>= height/layers;
tree += xmss_tree_num_nodes(height/layers);
tree += xmss_num_tree_nodes(height/layers);
}
return 1;
@@ -1829,7 +1790,7 @@ int xmssmt_private_key_print(FILE *fp, int fmt, int ind, const char *label, cons
char label[64];
snprintf(label, sizeof(label), "xmss_root[%zu]", i);
format_bytes(fp, fmt, ind, label, tree[tree_root_offset(height/layers)], 32);
tree += xmss_tree_num_nodes(height/layers);
tree += xmss_num_tree_nodes(height/layers);
}
return 1;
@@ -1922,7 +1883,7 @@ int xmssmt_signature_size(uint32_t xmssmt_type, size_t *siglen)
return -1;
}
*siglen += sizeof(hash256_t);
*siglen += XMSS_WOTS_SIGNATURE_SIZE * layers;
*siglen += sizeof(wots_sig_t) * layers;
*siglen += sizeof(hash256_t) * height;
return 1;
}
@@ -2036,13 +1997,13 @@ int xmssmt_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, con
format_print(fp, fmt, ind, "redurced_xmss_signature[%zu]\n", layer);
format_print(fp, fmt, ind+4, "wots_sig\n");
for (i = 0; i < 67; i++) {
format_print(fp, fmt, ind+4, "%d ", i);
format_print(fp, fmt, ind+8, "%d", i);
format_bytes(fp, fmt, 0, "", sig->wots_sigs[layer][i], 32);
}
format_print(fp, fmt, ind+4, "auth_path\n");
for (i = 0; i < height/layers; i++) {
format_print(fp, fmt, ind+8, "%d ", i);
format_print(fp, fmt, ind+8, "%d", i);
format_bytes(fp, fmt, 0, "", sig->auth_path[(height/layers) * layer + i], 32);
}
}
@@ -2112,19 +2073,6 @@ int xmssmt_signature_print(FILE *fp, int fmt, int ind, const char *label, const
return 1;
}
int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key)
{
size_t height;
@@ -2167,7 +2115,7 @@ int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key)
for (layer = 0; layer < layers; layer++) {
hash256_t *tree;
hash256_t *auth_path;
tree = key->trees + xmss_tree_num_nodes(height/layers) * layer;
tree = key->trees + xmss_num_tree_nodes(height/layers) * layer;
tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
auth_path = ctx->xmssmt_sig.auth_path + (height/layers) * layer;
xmss_build_auth_path(tree, height/layers, tree_index, auth_path);

View File

@@ -958,7 +958,7 @@ static int test_xmssmt_sign(void)
// build auth_path
for (layer = 0; layer < layers; layer++) {
uint32_t tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
hash256_t *tree = key->trees + xmss_tree_num_nodes(height/layers) * layer;
hash256_t *tree = key->trees + xmss_num_tree_nodes(height/layers) * layer;
hash256_t *auth_path = ctx->xmssmt_sig.auth_path + (height/layers) * layer;
xmss_build_auth_path(tree, height/layers, tree_index, auth_path);
}