Update XMSS

This commit is contained in:
Zhi Guan
2026-01-04 10:04:53 +08:00
parent f5f3b6a5b2
commit 14e4edede7
3 changed files with 1037 additions and 221 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2025 The GmSSL Project. All Rights Reserved.
* Copyright 2014-2026 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.
@@ -27,9 +27,6 @@ extern "C" {
// 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
@@ -145,11 +142,9 @@ 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 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;
@@ -157,24 +152,19 @@ 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;
@@ -200,7 +190,7 @@ 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);
void adrs_set_key_and_mask(uint8_t adrs[32], uint32_t key_and_mask);
int xmss_adrs_print(FILE *fp, int fmt, int ind, const char *label, const hash256_t adrs);
@@ -214,10 +204,12 @@ int xmss_adrs_print(FILE *fp, int fmt, int ind, const char *label, const hash256
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);
void wots_chain(const hash256_t x,
const hash256_t seed, const xmss_adrs_t adrs,
int start, int steps, hash256_t pk);
int start, int steps, hash256_t y);
void wots_sk_to_pk(const wots_key_t sk,
const hash256_t seed, const xmss_adrs_t adrs,
wots_key_t pk);
@@ -227,72 +219,58 @@ void wots_sign(const wots_key_t sk,
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,
void wots_pk_to_root(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);
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);
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,
const uint8_t dgst[32],
hash256_t wots_sig[67],
hash256_t *auth_path);
size_t height, hash256_t *tree); // tree[xmss_tree_num_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,
const hash256_t seed, const xmss_adrs_t adrs,
const hash256_t *auth_path, size_t height,
hash256_t xmss_root);
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]);
typedef struct {
uint32_t xmss_type;
uint8_t seed[32];
uint8_t root[32];
hash256_t seed;
hash256_t root;
} XMSS_PUBLIC_KEY;
// PK = OID || root || SEED
// SK = idx || wots_sk || SK_PRF || root || SEED;
#define XMSS_PUBLIC_KEY_SIZE (4 + 32 + 32) // = 68
typedef struct {
XMSS_PUBLIC_KEY public_key;
// private key
uint8_t secret[32];
uint8_t sk_prf[32]; // secret key for prf
hash256_t secret;
hash256_t sk_prf;
uint32_t index;
hash256_t *tree; // merkle tree with wots+ public keys as leafs
hash256_t *tree; // hash256_t[2^(h + 1) - 1]
} 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
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_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);
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 {
@@ -302,19 +280,12 @@ typedef struct {
hash256_t auth_path[XMSS_MAX_HEIGHT];
} XMSS_SIGNATURE;
// XMSS_SM3_10_256 2500 bytes
// XMSS_SM3_16_256 2692 bytes
// XMSS_SM3_20_256 2820 bytes
#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 oid, size_t *siglen);
// TODO: impl this
int xmss_key_get_signature_size(const XMSS_KEY *key, size_t *siglen);
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);
@@ -326,38 +297,14 @@ typedef struct {
HASH256_CTX hash256_ctx;
} 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);
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, 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);
// TODO: optimize, define XMSSMT_TYPE_HASH256 and XMSSMT_TYPE_PARAMS
#if defined(ENABLE_XMSS_CROSSCHECK) && defined(ENABLE_SHA2)
@@ -411,7 +358,7 @@ int xmss_verify_finish(XMSS_SIGN_CTX *ctx);
//#define XMSSMT_MIN_XMSS_HEIGHT 5
//#define XMSSMT_MAX_XMSS_HEIGHT 20
enum { // layers height sigs private
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
@@ -433,7 +380,6 @@ 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,
@@ -442,7 +388,6 @@ enum {
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,
@@ -451,7 +396,6 @@ enum {
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,
@@ -474,17 +418,28 @@ typedef struct {
hash256_t root;
} XMSSMT_PUBLIC_KEY;
#define XMSSMT_PUBLIC_KEY_SIZE (4 + sizeof(hash256_t) + sizeof(hash256_t)) // = 68 bytes
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];
hash256_t *trees;
wots_sig_t wots_sigs[XMSSMT_MAX_LAYERS - 1];
} XMSSMT_KEY;
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_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type);
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);
typedef struct {
@@ -501,7 +456,6 @@ typedef struct {
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);
@@ -509,10 +463,10 @@ int xmssmt_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, con
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_PUBLIC_KEY xmssmt_public_key;
XMSSMT_SIGNATURE xmssmt_sig;
HASH256_CTX hash256_ctx;
} XMSSMT_SIGN_CTX;
int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key);