From 83ef4e88bf7b49d2d7220e8a2a8ace8cc1618488 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sun, 4 Jan 2026 22:37:38 +0800 Subject: [PATCH] Update XMSS --- include/gmssl/xmss.h | 370 ++++++++++++++++++------------------------- src/xmss.c | 130 +++++---------- tests/xmsstest.c | 2 +- 3 files changed, 192 insertions(+), 310 deletions(-) diff --git a/include/gmssl/xmss.h b/include/gmssl/xmss.h index 331ce505..b00322f7 100644 --- a/include/gmssl/xmss.h +++ b/include/gmssl/xmss.h @@ -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 diff --git a/src/xmss.c b/src/xmss.c index 4dd203b8..5f955c97 100644 --- a/src/xmss.c +++ b/src/xmss.c @@ -22,21 +22,6 @@ #include -// 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); diff --git a/tests/xmsstest.c b/tests/xmsstest.c index 7b9fed75..2d2a49be 100644 --- a/tests/xmsstest.c +++ b/tests/xmsstest.c @@ -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); }