mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Add XMSS-SM3 signature
This commit is contained in:
@@ -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" {
|
||||
|
||||
@@ -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 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 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
|
||||
|
||||
1899
src/xmss.c
1899
src/xmss.c
File diff suppressed because it is too large
Load Diff
638
tests/xmsstest.c
638
tests/xmsstest.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 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.
|
||||
@@ -11,10 +11,32 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/hex.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/endian.h>
|
||||
#include <gmssl/xmss.h>
|
||||
|
||||
|
||||
|
||||
static int test_xmss_adrs(void)
|
||||
{
|
||||
xmss_adrs_t adrs;
|
||||
|
||||
|
||||
adrs_set_layer_address(adrs, 0);
|
||||
adrs_set_tree_address(adrs, 1);
|
||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
||||
adrs_set_ots_address(adrs, 0);
|
||||
adrs_set_chain_address(adrs, 1);
|
||||
adrs_set_hash_address(adrs, 12);
|
||||
adrs_set_key_and_mask(adrs, 0);
|
||||
|
||||
xmss_adrs_print(stderr, 0, 0, "ADRS", adrs);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// copy this static function from src/sm3_xmss.c
|
||||
static void hash256_prf_init(HASH256_CTX *hash256_ctx, const uint8_t key[32])
|
||||
{
|
||||
@@ -26,24 +48,26 @@ static void hash256_prf_init(HASH256_CTX *hash256_ctx, const uint8_t key[32])
|
||||
hash256_update(hash256_ctx, key, 32);
|
||||
}
|
||||
|
||||
static int test_sm3_wots_derive_sk(void)
|
||||
#if defined(ENABLE_XMSS_CROSSCHECK) && defined(ENABLE_SHA2)
|
||||
static int test_wots_derive_sk(void)
|
||||
{
|
||||
uint8_t wots_secret[32] = {0};
|
||||
uint8_t seed[32] = {0};
|
||||
uint8_t adrs[32] = {0};
|
||||
hash256_t wots_sk[67];
|
||||
hash256_t test_sk[67];
|
||||
hash256_t secret = {0};
|
||||
hash256_t seed = {0};
|
||||
xmss_adrs_t adrs = {0};
|
||||
wots_key_t wots_sk;
|
||||
wots_key_t test_sk;
|
||||
size_t len;
|
||||
|
||||
// sha256 test 1
|
||||
memset(wots_secret, 0, 32);
|
||||
memset(seed, 0, 32);
|
||||
memset(adrs, 0, 32);
|
||||
memset(secret, 0, sizeof(secret));
|
||||
memset(seed, 0, sizeof(seed));
|
||||
memset(adrs, 0, sizeof(adrs));
|
||||
hex_to_bytes("0cb52ea67abd5da0328099db02de310e4ab01ac39d0bbeb71e97eb7e83c467b5", 64, test_sk[0], &len);
|
||||
hex_to_bytes("382c16f94b77905d4a6f78e1f38faf5ef914ac42324e356aeede056d356a5eeb", 64, test_sk[1], &len);
|
||||
hex_to_bytes("ab08e768529903e533c9bf8b3ea8c69d36aedcee5ac78801f92d23ef758cfe03", 64, test_sk[66], &len);
|
||||
|
||||
sm3_wots_derive_sk(wots_secret, seed, adrs, wots_sk);
|
||||
wots_derive_sk(secret, seed, adrs, wots_sk);
|
||||
|
||||
if (memcmp(wots_sk[0], test_sk[0], 32)
|
||||
|| memcmp(wots_sk[1], test_sk[1], 32)
|
||||
|| memcmp(wots_sk[66], test_sk[66], 32)) {
|
||||
@@ -52,14 +76,15 @@ static int test_sm3_wots_derive_sk(void)
|
||||
}
|
||||
|
||||
// sha256 test 2
|
||||
memset(wots_secret, 0x12, 32);
|
||||
memset(seed, 0xab, 32);
|
||||
memset(adrs, 0, 32);
|
||||
memset(secret, 0x12, sizeof(secret));
|
||||
memset(seed, 0xab, sizeof(seed));
|
||||
memset(adrs, 0, sizeof(adrs));
|
||||
hex_to_bytes("1a50a39a53e6ef2480db612cef9456d0f33222f934c58bcba9d04fa91108faf6", 64, test_sk[0], &len);
|
||||
hex_to_bytes("e45dad76c1b23975e898a365b8c73d13695a887ba2ba2377f840d3a3b7bf806c", 64, test_sk[1], &len);
|
||||
hex_to_bytes("aaad735aa51662b8a48258561fb857b3f2b12a5802593522145b3b68355abf3b", 64, test_sk[66], &len);
|
||||
|
||||
sm3_wots_derive_sk(wots_secret, seed, adrs, wots_sk);
|
||||
wots_derive_sk(secret, seed, adrs, wots_sk);
|
||||
|
||||
if (memcmp(wots_sk[0], test_sk[0], 32)
|
||||
|| memcmp(wots_sk[1], test_sk[1], 32)
|
||||
|| memcmp(wots_sk[66], test_sk[66], 32)) {
|
||||
@@ -71,28 +96,27 @@ static int test_sm3_wots_derive_sk(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_sm3_wots_derive_pk(void)
|
||||
static int test_wots_sk_to_pk(void)
|
||||
{
|
||||
uint8_t wots_secret[32] = {0};
|
||||
uint8_t seed[32] = {0};
|
||||
uint8_t adrs[32] = {0};
|
||||
hash256_t wots_sk[67];
|
||||
hash256_t wots_pk[67];
|
||||
hash256_t test_pk[67];
|
||||
HASH256_CTX prf_seed_ctx;
|
||||
hash256_t secret = {0};
|
||||
hash256_t seed = {0};
|
||||
xmss_adrs_t adrs = {0};
|
||||
wots_key_t wots_sk;
|
||||
wots_key_t wots_pk;
|
||||
wots_key_t test_pk;
|
||||
size_t len;
|
||||
|
||||
// sha256 test 2
|
||||
memset(wots_secret, 0x12, 32);
|
||||
memset(seed, 0xab, 32);
|
||||
memset(adrs, 0, 32);
|
||||
memset(secret, 0x12, sizeof(secret));
|
||||
memset(seed, 0xab, sizeof(seed));
|
||||
memset(adrs, 0, sizeof(adrs));
|
||||
hex_to_bytes("0c74a626695831994961641c487b70da83cd2aba2ba5c63c38ce72479b8a0ab9", 64, test_pk[0], &len);
|
||||
hex_to_bytes("acf6be724d4b074d67330559ec24b3d42c9b9d87fa103e7f6be402ec3a2d41c1", 64, test_pk[1], &len);
|
||||
hex_to_bytes("98691d83a657840d4b6f410e25fcd9a6480670ac9c090d3b79bc904ba7e131aa", 64, test_pk[66], &len);
|
||||
|
||||
sm3_wots_derive_sk(wots_secret, seed, adrs, wots_sk);
|
||||
hash256_prf_init(&prf_seed_ctx, seed);
|
||||
sm3_wots_derive_pk(wots_sk, &prf_seed_ctx, adrs, wots_pk);
|
||||
wots_derive_sk(secret, seed, adrs, wots_sk);
|
||||
|
||||
wots_sk_to_pk(wots_sk, seed, adrs, wots_pk);
|
||||
|
||||
if (memcmp(wots_pk[0], test_pk[0], 32)
|
||||
|| memcmp(wots_pk[1], test_pk[1], 32)
|
||||
@@ -105,24 +129,66 @@ static int test_sm3_wots_derive_pk(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_sm3_wots_do_sign(void)
|
||||
static int test_wots_derive_root(void)
|
||||
{
|
||||
uint8_t wots_secret[32] = {0};
|
||||
uint8_t seed[32] = {0};
|
||||
uint8_t adrs[32] = {0};
|
||||
uint8_t dgst[32] = {0};
|
||||
hash256_t wots_sk[67];
|
||||
hash256_t wots_pk[67];
|
||||
hash256_t wots_sig[67];
|
||||
hash256_t test_sig[67];
|
||||
hash256_t sig_pk[67];
|
||||
HASH256_CTX prf_seed_ctx;
|
||||
hash256_t secret;
|
||||
hash256_t seed;
|
||||
xmss_adrs_t adrs;
|
||||
hash256_t root;
|
||||
hash256_t wots_0_root;
|
||||
hash256_t wots_1023_root;
|
||||
size_t len;
|
||||
|
||||
memset(secret, 0x12, sizeof(hash256_t));
|
||||
memset(seed, 0xab, sizeof(hash256_t));
|
||||
hex_to_bytes("7A968C5F9AE4D2B781872B4E6EE851D55CC02F0AB9196701580D6F503D35DB68", 64, wots_0_root, &len);
|
||||
hex_to_bytes("939E10CD44769D4D9853F7CF5612D6D83B3AA140A8867CCF34A1DBCC66FC4333", 64, wots_1023_root, &len);
|
||||
|
||||
// wots index is 0
|
||||
adrs_set_layer_address(adrs, 0);
|
||||
adrs_set_tree_address(adrs, 0);
|
||||
adrs_set_ots_address(adrs, 0);
|
||||
|
||||
wots_derive_root(secret, seed, adrs, root);
|
||||
|
||||
if (memcmp(root, wots_0_root, sizeof(hash256_t)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// wots index is 1023
|
||||
adrs_set_layer_address(adrs, 0);
|
||||
adrs_set_tree_address(adrs, 0);
|
||||
adrs_set_ots_address(adrs, 1023);
|
||||
|
||||
wots_derive_root(secret, seed, adrs, root);
|
||||
|
||||
if (memcmp(root, wots_1023_root, sizeof(hash256_t)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_wots_sign(void)
|
||||
{
|
||||
hash256_t secret = {0};
|
||||
hash256_t seed = {0};
|
||||
xmss_adrs_t adrs = {0};
|
||||
hash256_t dgst = {0};
|
||||
wots_key_t wots_sk;
|
||||
wots_key_t wots_pk;
|
||||
wots_sig_t wots_sig;
|
||||
wots_sig_t test_sig;
|
||||
wots_key_t sig_pk;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
memset(wots_secret, 0x12, 32);
|
||||
memset(seed, 0xab, 32);
|
||||
memset(adrs, 0, 32);
|
||||
memset(secret, 0x12, sizeof(secret));
|
||||
memset(seed, 0xab, sizeof(seed));
|
||||
memset(adrs, 0, sizeof(adrs));
|
||||
for (i = 0; i < 32; i++) {
|
||||
dgst[i] = i; // try different dgst, check base_w and checksum
|
||||
}
|
||||
@@ -131,21 +197,23 @@ static int test_sm3_wots_do_sign(void)
|
||||
hex_to_bytes("75d2cfddd6ca9773fb9d0d17efe5c731c1a44f4b31352e26767623abf52911f9", 64, test_sig[15], &len);
|
||||
hex_to_bytes("aaad735aa51662b8a48258561fb857b3f2b12a5802593522145b3b68355abf3b", 64, test_sig[66], &len);
|
||||
|
||||
sm3_wots_derive_sk(wots_secret, seed, adrs, wots_sk);
|
||||
hash256_prf_init(&prf_seed_ctx, seed);
|
||||
sm3_wots_derive_pk(wots_sk, &prf_seed_ctx, adrs, wots_pk);
|
||||
sm3_wots_do_sign(wots_sk, &prf_seed_ctx, adrs, dgst, wots_sig);
|
||||
wots_derive_sk(secret, seed, adrs, wots_sk);
|
||||
|
||||
if (memcmp(wots_sig[0], test_sig[0], 32)
|
||||
|| memcmp(wots_sig[1], test_sig[1], 32)
|
||||
|| memcmp(wots_sig[15], test_sig[15], 32)
|
||||
|| memcmp(wots_sig[66], test_sig[66], 32)) {
|
||||
wots_sk_to_pk(wots_sk, seed, adrs, wots_pk);
|
||||
|
||||
wots_sign(wots_sk, seed, adrs, dgst, wots_sig);
|
||||
|
||||
if (memcmp(wots_sig[0], test_sig[0], sizeof(hash256_t))
|
||||
|| memcmp(wots_sig[1], test_sig[1], sizeof(hash256_t))
|
||||
|| memcmp(wots_sig[15], test_sig[15], sizeof(hash256_t))
|
||||
|| memcmp(wots_sig[66], test_sig[66], sizeof(hash256_t))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm3_wots_sig_to_pk(wots_sig, dgst, &prf_seed_ctx, adrs, sig_pk);
|
||||
if (memcmp(sig_pk ,wots_pk, 32 * 67)) {
|
||||
wots_sig_to_pk(wots_sig, seed, adrs, dgst, sig_pk);
|
||||
|
||||
if (memcmp(sig_pk ,wots_pk, sizeof(wots_key_t))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -154,23 +222,66 @@ static int test_sm3_wots_do_sign(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_xmss_derive_root(void)
|
||||
static int test_xmss_build_tree(void)
|
||||
{
|
||||
uint8_t xmss_secret[32];
|
||||
uint8_t seed[32];
|
||||
hash256_t xmss_secret;
|
||||
hash256_t seed;
|
||||
xmss_adrs_t adrs;
|
||||
int height = 10;
|
||||
hash256_t *tree = malloc(32 * (1<<height) * 2);
|
||||
uint8_t xmss_root[32];
|
||||
uint8_t test_root[32];
|
||||
hash256_t xmss_root;
|
||||
hash256_t test_root;
|
||||
size_t len;
|
||||
|
||||
memset(xmss_secret, 0x12, 32);
|
||||
memset(seed, 0xab, 32);
|
||||
memset(xmss_secret, 0x12, sizeof(hash256_t));
|
||||
memset(seed, 0xab, sizeof(hash256_t));
|
||||
hex_to_bytes("f0415ed807c8f8c2ee8ca3a00178bff37e1ccb2836e02607d06131c9341e52ca", 64, test_root, &len);
|
||||
|
||||
xmss_derive_root(xmss_secret, height, seed, tree, xmss_root);
|
||||
adrs_set_layer_address(adrs, 0);
|
||||
adrs_set_tree_address(adrs, 0);
|
||||
xmss_build_tree(xmss_secret, seed, adrs, height, tree);
|
||||
|
||||
if (memcmp(xmss_root, test_root, 32)) {
|
||||
memcpy(xmss_root, tree[(1 << (height + 1)) - 2], sizeof(hash256_t));
|
||||
if (memcmp(xmss_root, test_root, sizeof(hash256_t))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int test_xmss_key_generate(void)
|
||||
{
|
||||
uint32_t xmss_type = XMSS_HASH256_10_256;
|
||||
XMSS_KEY key;
|
||||
size_t count;
|
||||
size_t i;
|
||||
|
||||
if (xmss_key_generate(&key, xmss_type) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
xmss_public_key_print(stderr, 0, 0, "xmss_public_key", &key);
|
||||
xmss_private_key_print(stderr, 0, 0, "xmss_private_key", &key);
|
||||
|
||||
if (xmss_key_remaining_signs(&key, &count) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "xmss_key_remaining_signs: %zu\n", count);
|
||||
if (count != 1024) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
key.index += 4;
|
||||
if (xmss_key_remaining_signs(&key, &count) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "xmss_key_remaining_signs: %zu\n", count);
|
||||
if (count != 1020) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -179,75 +290,241 @@ static int test_xmss_derive_root(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int test_xmss_do_sign(void)
|
||||
static int test_xmss_key_to_bytes(void)
|
||||
{
|
||||
uint8_t xmss_secret[32];
|
||||
uint8_t xmss_root[32];
|
||||
int h = 4;
|
||||
uint8_t dgst[32];
|
||||
uint8_t seed[32];
|
||||
uint8_t adrs[32] = {0};
|
||||
hash256_t wots_sig[67];
|
||||
hash256_t *auth_path = malloc(32 * h);
|
||||
hash256_t *tree = malloc(32 * (1<<h) * 2);
|
||||
uint32_t index = 0;
|
||||
uint8_t i;
|
||||
uint32_t xmss_type = XMSS_HASH256_10_256;
|
||||
XMSS_KEY key;
|
||||
XMSS_KEY pub;
|
||||
uint8_t buf[XMSS_PUBLIC_KEY_SIZE + XMSS_PRIVATE_KEY_SIZE];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
memset(xmss_secret, 0x12, 32);
|
||||
memset(seed, 0xab, 32);
|
||||
for (i = 0; i < 32; i++) {
|
||||
dgst[i] = i;
|
||||
if (xmss_key_generate(&key, xmss_type) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
xmss_derive_root(xmss_secret, h, seed, tree, xmss_root);
|
||||
if (xmss_public_key_to_bytes(&key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "xmss_public_key_size : %zu\n", len);
|
||||
if (len != XMSS_PUBLIC_KEY_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (index = 0; index < (1<<h); index++) {
|
||||
uint8_t root_from_sig[32];
|
||||
xmss_do_sign(xmss_secret, index, seed, adrs, h, tree, dgst, wots_sig, auth_path);
|
||||
xmss_sig_to_root(wots_sig, index, auth_path, seed, adrs, h, dgst, root_from_sig);
|
||||
if (memcmp(xmss_root, root_from_sig, 32) != 0) {
|
||||
printf("xmss_sig_to_root failed\n");
|
||||
if (xmss_private_key_to_bytes(&key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "xmss_private_key_size : %zu\n", len - XMSS_PUBLIC_KEY_SIZE);
|
||||
if (len != XMSS_PUBLIC_KEY_SIZE + XMSS_PRIVATE_KEY_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xmss_public_key_from_bytes(&pub, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(&key, &pub, sizeof(XMSS_PUBLIC_KEY)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (xmss_private_key_from_bytes(&pub, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// FIXME: compare trees
|
||||
/*
|
||||
if (memcmp(&key, &pub, sizeof(XMSS_KEY)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
if (len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// XMSS_SM3_10_256 2500 bytes
|
||||
// XMSS_SM3_16_256 2692 bytes
|
||||
// XMSS_SM3_20_256 2820 bytes
|
||||
|
||||
struct {
|
||||
uint32_t xmss_type;
|
||||
size_t siglen;
|
||||
} xmss_siglens[] = {
|
||||
{ XMSS_HASH256_10_256, 2500 },
|
||||
{ XMSS_HASH256_16_256, 2692 },
|
||||
{ XMSS_HASH256_20_256, 2820 },
|
||||
};
|
||||
|
||||
static int test_xmss_signature_size(void)
|
||||
{
|
||||
size_t siglen;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(xmss_siglens)/sizeof(xmss_siglens[0]); i++) {
|
||||
if (xmss_signature_size(xmss_siglens[i].xmss_type, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (siglen != xmss_siglens[i].siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_xmss_sign(void)
|
||||
{
|
||||
#if defined(ENABLE_SHA2) && defined(ENABLE_XMSS_CROSSCHECK)
|
||||
uint32_t oid = XMSS_SHA256_10;
|
||||
#else
|
||||
uint32_t oid = XMSS_SM3_10;
|
||||
#endif
|
||||
static const uint8_t hash256_two[] = {
|
||||
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, 0x02,
|
||||
};
|
||||
uint8_t msg[100] = {0};
|
||||
uint32_t xmss_type = XMSS_HASH256_10_256;
|
||||
size_t height = 10;
|
||||
uint32_t index = 1011;
|
||||
hash256_t hash256_index = {0};
|
||||
XMSS_KEY key;
|
||||
XMSS_SIGNATURE sig;
|
||||
xmss_adrs_t adrs;
|
||||
hash256_t root;
|
||||
HASH256_CTX ctx;
|
||||
hash256_t dgst;
|
||||
size_t h;
|
||||
|
||||
|
||||
if (xmss_key_generate(&key, xmss_type) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// xmss_sig.index
|
||||
// xmss_sig.random
|
||||
// xmss_sig.wots_sig
|
||||
// xmss_sig.auth_path
|
||||
|
||||
sig.index = index;
|
||||
|
||||
memset(sig.random, 0, 32);
|
||||
|
||||
// wots_sk => sig.wots_sig
|
||||
adrs_set_layer_address(adrs, 0);
|
||||
adrs_set_tree_address(adrs, 0);
|
||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
|
||||
adrs_set_ots_address(adrs, index);
|
||||
wots_derive_sk(key.secret, key.public_key.seed, adrs, sig.wots_sig);
|
||||
|
||||
// check wots_root
|
||||
wots_derive_root(key.secret, key.public_key.seed, adrs, root);
|
||||
if (memcmp(root, key.tree[index], sizeof(hash256_t)) != 0) {
|
||||
xmss_key_cleanup(&key);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
build_auth_path(key.tree, height, index, sig.auth_path);
|
||||
|
||||
|
||||
|
||||
PUTU32(hash256_index + 28, index);
|
||||
hash256_init(&ctx);
|
||||
hash256_update(&ctx, hash256_two, sizeof(hash256_t));
|
||||
hash256_update(&ctx, sig.random, sizeof(hash256_t));
|
||||
hash256_update(&ctx, key.public_key.root, sizeof(hash256_t));
|
||||
hash256_update(&ctx, hash256_index, sizeof(hash256_t));
|
||||
hash256_update(&ctx, msg, sizeof(msg));
|
||||
hash256_finish(&ctx, dgst);
|
||||
|
||||
wots_sign(sig.wots_sig, key.public_key.seed, adrs, dgst, sig.wots_sig);
|
||||
|
||||
// verify
|
||||
|
||||
// wots_sig => wots_root
|
||||
wots_sig_to_pk(sig.wots_sig, key.public_key.seed, adrs, dgst, sig.wots_sig);
|
||||
|
||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_LTREE);
|
||||
adrs_set_ltree_address(adrs, index);
|
||||
wots_build_ltree(sig.wots_sig, key.public_key.seed, adrs, root);
|
||||
|
||||
// wots_root, index, auth_path => xmss_root
|
||||
adrs_set_type(adrs, XMSS_ADRS_TYPE_HASHTREE);
|
||||
adrs_set_padding(adrs, 0);
|
||||
adrs_set_key_and_mask(adrs, 0);
|
||||
for (h = 0; h < height; h++) {
|
||||
int right = index & 1;
|
||||
index >>= 1;
|
||||
adrs_set_tree_height(adrs, h);
|
||||
adrs_set_tree_index(adrs, index);
|
||||
if (right)
|
||||
randomized_tree_hash(sig.auth_path[h], root, key.public_key.seed, adrs, root);
|
||||
else randomized_tree_hash(root, sig.auth_path[h], key.public_key.seed, adrs, root);
|
||||
}
|
||||
|
||||
if (memcmp(root, key.public_key.root, sizeof(hash256_t)) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int test_xmss_sign_init(void)
|
||||
{
|
||||
uint32_t xmss_type = XMSS_HASH256_10_256;
|
||||
XMSS_KEY key;
|
||||
XMSS_SIGN_CTX sign_ctx;
|
||||
uint8_t sig[sizeof(XMSS_SIGNATURE)];
|
||||
uint8_t sig[XMSS_SIGNATURE_MAX_SIZE];
|
||||
size_t siglen;
|
||||
uint8_t msg[100] = {0};
|
||||
int i;
|
||||
|
||||
xmss_key_generate(&key, oid);
|
||||
xmss_key_print(stderr, 0, 0, "XMSS Key", &key);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
xmss_sign_init(&sign_ctx, &key);
|
||||
xmss_sign_update(&sign_ctx, msg, sizeof(msg));
|
||||
xmss_sign_finish(&sign_ctx, &key, sig, &siglen);
|
||||
|
||||
(key.index)++;
|
||||
|
||||
xmss_signature_print(stderr, 0, 0, "XMSS Signature", sig, siglen);
|
||||
|
||||
xmss_verify_init(&sign_ctx, &key, sig, siglen);
|
||||
xmss_verify_update(&sign_ctx, msg, sizeof(msg));
|
||||
if (xmss_verify_finish(&sign_ctx, &key, sig, siglen) != 1) {
|
||||
if (xmss_key_generate(&key, xmss_type) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xmss_sign_init(&sign_ctx, &key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (xmss_sign_update(&sign_ctx, msg, sizeof(msg)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (xmss_sign_finish(&sign_ctx, sig, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xmss_verify_init(&sign_ctx, &key, sig, siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (xmss_verify_update(&sign_ctx, msg, sizeof(msg)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (xmss_verify_finish(&sign_ctx) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
xmss_key_cleanup(&key);
|
||||
|
||||
@@ -255,14 +532,149 @@ static int test_xmss_sign(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct {
|
||||
uint32_t xmssmt_type;
|
||||
size_t indexlen;
|
||||
size_t siglen;
|
||||
} xmssmt_consts[] = {
|
||||
{ XMSSMT_HASH256_20_2_256, 3, 4963 },
|
||||
{ XMSSMT_HASH256_20_4_256, 3, 9251 },
|
||||
{ XMSSMT_HASH256_40_2_256, 5, 5605 },
|
||||
{ XMSSMT_HASH256_40_4_256, 5, 9893 },
|
||||
{ XMSSMT_HASH256_40_8_256, 5, 18469 },
|
||||
{ XMSSMT_HASH256_60_3_256, 8, 8392 },
|
||||
{ XMSSMT_HASH256_60_6_256, 8, 14824 },
|
||||
{ XMSSMT_HASH256_60_12_256, 8, 27688 },
|
||||
};
|
||||
|
||||
static int test_xmssmt_index_to_bytes(void)
|
||||
{
|
||||
uint64_t index = 0;
|
||||
size_t indexlen;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(xmssmt_consts)/sizeof(xmssmt_consts[0]); i++) {
|
||||
indexlen = 0;
|
||||
if (xmssmt_index_to_bytes(index, xmssmt_consts[i].xmssmt_type, NULL, &indexlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (indexlen != xmssmt_consts[i].indexlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_xmssmt_signature_size(void)
|
||||
{
|
||||
size_t siglen;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(xmssmt_consts)/sizeof(xmssmt_consts[0]); i++) {
|
||||
if (xmssmt_signature_size(xmssmt_consts[i].xmssmt_type, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (siglen != xmssmt_consts[i].siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_xmssmt_signature_print(void)
|
||||
{
|
||||
XMSSMT_SIGNATURE xmssmt_sig;
|
||||
size_t layer, i;
|
||||
|
||||
// set xmssmt_sig
|
||||
memset(&xmssmt_sig, 0, sizeof(xmssmt_sig));
|
||||
xmssmt_sig.index = 1;
|
||||
rand_bytes(xmssmt_sig.random, 32);
|
||||
|
||||
for (layer = 0; layer < XMSSMT_MAX_LAYERS; layer++) {
|
||||
for (i = 0; i < 67; i++) {
|
||||
xmssmt_sig.wots_sigs[layer][i][0] = 0x0a;
|
||||
xmssmt_sig.wots_sigs[layer][i][1] = 0xff & layer;
|
||||
xmssmt_sig.wots_sigs[layer][i][2] = 0xff & i;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < XMSSMT_MAX_HEIGHT; i++) {
|
||||
xmssmt_sig.auth_path[i][0] = 0x0b;
|
||||
xmssmt_sig.auth_path[i][1] = 0xff & i;
|
||||
}
|
||||
|
||||
// print
|
||||
for (i = 0; i < sizeof(xmssmt_consts)/sizeof(xmssmt_consts[0]); i++) {
|
||||
xmssmt_signature_print_ex(stderr, 0, 0, "xmssmt_signature", &xmssmt_sig, xmssmt_consts[i].xmssmt_type);
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_xmssmt_signature_to_bytes(void)
|
||||
{
|
||||
uint32_t xmssmt_type = XMSSMT_HASH256_20_2_256;
|
||||
XMSSMT_SIGNATURE xmssmt_sig;
|
||||
uint8_t buf[XMSSMT_SIGNATURE_MAX_SIZE];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
memset(&xmssmt_sig, 0, sizeof(xmssmt_sig));
|
||||
|
||||
//xmssmt_signature_print_ex(stderr, 0, 0, "xmssmt_signature", &xmssmt_sig, xmssmt_type);
|
||||
|
||||
if (xmssmt_signature_to_bytes(&xmssmt_sig, xmssmt_type, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
xmssmt_signature_print(stderr, 0, 0, "xmssmt_signature", buf, len, xmssmt_type);
|
||||
|
||||
if (xmssmt_signature_from_bytes(&xmssmt_sig, xmssmt_type, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len) {
|
||||
fprintf(stderr, "xmssmt_signature_len: %zu\n", len);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_sm3_wots_derive_sk() != 1) goto err;
|
||||
if (test_sm3_wots_derive_pk() != 1) goto err;
|
||||
if (test_sm3_wots_do_sign() != 1) goto err;
|
||||
if (test_xmss_derive_root() != 1) goto err;
|
||||
if (test_xmss_do_sign() != 1) goto err;
|
||||
#if defined(ENABLE_LMS_CROSSCHECK) && defined(ENABLE_SHA2)
|
||||
if (test_wots_derive_sk() != 1) goto err;
|
||||
if (test_wots_sk_to_pk() != 1) goto err;
|
||||
if (test_wots_sign() != 1) goto err;
|
||||
if (test_wots_derive_root() != 1) goto err;
|
||||
if (test_xmss_build_tree() != 1) goto err;
|
||||
#endif
|
||||
if (test_xmss_adrs() != 1) goto err;
|
||||
if (test_xmss_key_generate() != 1) goto err;
|
||||
if (test_xmss_key_to_bytes() != 1) goto err;
|
||||
if (test_xmss_signature_size() != 1) goto err;
|
||||
if (test_xmss_sign() != 1) goto err;
|
||||
if (test_xmss_sign_init() != 1) goto err;
|
||||
if (test_xmssmt_index_to_bytes() != 1) goto err;
|
||||
if (test_xmssmt_signature_size() != 1) goto err;
|
||||
if (test_xmssmt_signature_to_bytes() != 1) goto err;
|
||||
if (test_xmssmt_signature_print() != 1) goto err;
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 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,58 +17,58 @@
|
||||
#include <gmssl/xmss.h>
|
||||
|
||||
|
||||
static const char *usage = "-oid oid [-out file] [-pubout file]\n";
|
||||
static const char *usage = "-xmss_type type -out file [-pubout file] [-verbose]\n";
|
||||
|
||||
static const char *help =
|
||||
static const char *options =
|
||||
"Options\n"
|
||||
" -oid oid XMSS algorithm OID\n"
|
||||
" XMSS_SM3_10\n"
|
||||
" XMSS_SM3_16\n"
|
||||
" XMSS_SM3_20\n"
|
||||
" -xmss_type type XMSS Algorithm Type\n"
|
||||
" "XMSS_HASH256_10_256_NAME"\n"
|
||||
" "XMSS_HASH256_16_256_NAME"\n"
|
||||
" "XMSS_HASH256_20_256_NAME"\n"
|
||||
" -out file Output private key\n"
|
||||
" -pubout file Output public key\n"
|
||||
" -verbose Print public key\n"
|
||||
"\n";
|
||||
|
||||
int xmsskeygen_main(int argc, char **argv)
|
||||
{
|
||||
int ret = 1;
|
||||
char *prog = argv[0];
|
||||
char *oid = NULL;
|
||||
uint32_t oid_val = 0;
|
||||
char *xmss_type = NULL;
|
||||
int xmss_type_val = 0;
|
||||
char *outfile = NULL;
|
||||
char *puboutfile = NULL;
|
||||
FILE *outfp = stdout;
|
||||
int verbose = 0;
|
||||
FILE *outfp = NULL;
|
||||
FILE *puboutfp = stdout;
|
||||
XMSS_KEY key;
|
||||
uint8_t *out = NULL;
|
||||
uint8_t *pubout = NULL;
|
||||
size_t outlen, puboutlen;
|
||||
uint8_t out[XMSS_PRIVATE_KEY_SIZE];
|
||||
uint8_t pubout[XMSS_PUBLIC_KEY_SIZE];
|
||||
uint8_t *pout = out;
|
||||
uint8_t *ppubout = pubout;
|
||||
size_t outlen = 0, puboutlen = 0;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc < 1) {
|
||||
fprintf(stderr, "usage: %s %s\n", prog, help);
|
||||
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (argc > 0) {
|
||||
if (!strcmp(*argv, "-help")) {
|
||||
printf("usage: %s %s\n", prog, usage);
|
||||
printf("%s\n", help);
|
||||
printf("usage: gmssl %s %s\n", prog, usage);
|
||||
printf("%s\n", options);
|
||||
ret = 0;
|
||||
goto end;
|
||||
} else if (!strcmp(*argv, "-oid")) {
|
||||
} else if (!strcmp(*argv, "-xmss_type")) {
|
||||
if (--argc < 1) goto bad;
|
||||
oid = *(++argv);
|
||||
if (strcmp(oid, "XMSS_SM3_10") == 0) {
|
||||
oid_val = XMSS_SM3_10;
|
||||
} else if (strcmp(oid, "XMSS_SM3_16") == 0) {
|
||||
oid_val = XMSS_SM3_16;
|
||||
} else if (strcmp(oid, "XMSS_SM3_20") == 0) {
|
||||
oid_val = XMSS_SM3_20;
|
||||
} else {
|
||||
fprintf(stderr, "%s: invalid XMSS algor ID `%s`\n", prog, oid);
|
||||
xmss_type = *(++argv);
|
||||
if (!(xmss_type_val = xmss_type_from_name(xmss_type))) {
|
||||
fprintf(stderr, "%s: invalid xmss_type `%s`\n", prog, xmss_type);
|
||||
goto end;
|
||||
}
|
||||
} else if (!strcmp(*argv, "-out")) {
|
||||
@@ -85,6 +85,8 @@ int xmsskeygen_main(int argc, char **argv)
|
||||
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
} else if (!strcmp(*argv, "-verbose")) {
|
||||
verbose = 1;
|
||||
} else {
|
||||
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
|
||||
goto end;
|
||||
@@ -97,46 +99,36 @@ bad:
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (!oid) {
|
||||
fprintf(stderr, "%s: `-oid` option required\n", prog);
|
||||
if (!xmss_type) {
|
||||
fprintf(stderr, "%s: `-xmss_type` option required\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (!outfp) {
|
||||
fprintf(stderr, "%s: `-out` option required\n", prog);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
if (xmss_key_generate(&key, oid_val) != 1) {
|
||||
if (xmss_key_generate(&key, xmss_type_val) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xmss_key_to_bytes(&key, NULL, &outlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (!(out = malloc(outlen))) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (xmss_key_to_bytes(&key, out, &outlen) != 1) {
|
||||
error_print();
|
||||
if (verbose) {
|
||||
xmss_public_key_print(stderr, 0, 0, "xmss_public_key", &key);
|
||||
}
|
||||
|
||||
if (xmss_public_key_to_bytes(&key, NULL, &puboutlen) != 1) {
|
||||
if (xmss_private_key_to_bytes(&key, &pout, &outlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (!(pubout = malloc(puboutlen))) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (xmss_public_key_to_bytes(&key, pubout, &puboutlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (fwrite(out, 1, outlen, outfp) != outlen) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (xmss_public_key_to_bytes(&key, &ppubout, &puboutlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (fwrite(pubout, 1, puboutlen, puboutfp) != puboutlen) {
|
||||
error_print();
|
||||
goto end;
|
||||
@@ -144,15 +136,8 @@ bad:
|
||||
|
||||
ret = 0;
|
||||
end:
|
||||
gmssl_secure_clear(&key, sizeof(key));
|
||||
if (out) {
|
||||
xmss_key_cleanup(&key);
|
||||
gmssl_secure_clear(out, outlen);
|
||||
free(out);
|
||||
}
|
||||
if (pubout) {
|
||||
gmssl_secure_clear(pubout, puboutlen);
|
||||
free(pubout);
|
||||
}
|
||||
if (outfile && outfp) fclose(outfp);
|
||||
if (puboutfile && puboutfp) fclose(puboutfp);
|
||||
return ret;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 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.
|
||||
@@ -13,17 +13,17 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/file.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/xmss.h>
|
||||
|
||||
static const char *usage = "-key file [-in file] [-out file]\n";
|
||||
static const char *usage = "-key file [-in file] [-out file] [-verbose]\n";
|
||||
|
||||
static const char *help =
|
||||
static const char *options =
|
||||
"Options\n"
|
||||
" -key file Input private key file\n"
|
||||
" -in file Input data file (if not using stdin)\n"
|
||||
" -out file Output signature file\n"
|
||||
" -verbose Print public key and signature\n"
|
||||
"\n";
|
||||
|
||||
int xmsssign_main(int argc, char **argv)
|
||||
@@ -33,43 +33,42 @@ int xmsssign_main(int argc, char **argv)
|
||||
char *keyfile = NULL;
|
||||
char *infile = NULL;
|
||||
char *outfile = NULL;
|
||||
int verbose = 0;
|
||||
FILE *keyfp = NULL;
|
||||
FILE *infp = stdin;
|
||||
FILE *outfp = stdout;
|
||||
uint8_t *keybuf = NULL;
|
||||
size_t keylen;
|
||||
uint8_t keybuf[XMSS_PRIVATE_KEY_SIZE];
|
||||
size_t keylen = XMSS_PRIVATE_KEY_SIZE;
|
||||
const uint8_t *cp = keybuf;
|
||||
uint8_t *p = keybuf;
|
||||
XMSS_KEY key;
|
||||
XMSS_SIGN_CTX sign_ctx;
|
||||
uint8_t *sigbuf = NULL;
|
||||
XMSS_SIGN_CTX ctx;
|
||||
uint8_t sig[XMSS_SIGNATURE_MAX_SIZE];
|
||||
size_t siglen;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc < 1) {
|
||||
fprintf(stderr, "usage: %s %s\n", prog, usage);
|
||||
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (argc > 0) {
|
||||
if (!strcmp(*argv, "-help")) {
|
||||
printf("usage: %s %s\n", prog, usage);
|
||||
printf("%s\n", help);
|
||||
printf("%s\n", options);
|
||||
ret = 0;
|
||||
goto end;
|
||||
} else if (!strcmp(*argv, "-key")) {
|
||||
if (--argc < 1) goto bad;
|
||||
keyfile = *(++argv);
|
||||
/*
|
||||
if (!(keyfp = fopen(keyfile, "rb"))) {
|
||||
if (!(keyfp = fopen(keyfile, "rb+"))) {
|
||||
fprintf(stderr, "%s: open '%s' failure: %s\n", prog, keyfile, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
*/
|
||||
if (file_read_all(keyfile, &keybuf, &keylen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
} else if (!strcmp(*argv, "-in")) {
|
||||
if (--argc < 1) goto bad;
|
||||
infile = *(++argv);
|
||||
@@ -84,6 +83,8 @@ int xmsssign_main(int argc, char **argv)
|
||||
fprintf(stderr, "%s: open '%s' failure: %s\n", prog, outfile, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
} else if (!strcmp(*argv, "-verbose")) {
|
||||
verbose = 1;
|
||||
} else {
|
||||
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
|
||||
goto end;
|
||||
@@ -101,15 +102,38 @@ bad:
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (fread(keybuf, 1, keylen, keyfp) != keylen) {
|
||||
fprintf(stderr, "%s: read private key failure\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (xmss_private_key_from_bytes(&key, &cp, &keylen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (keylen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xmss_key_from_bytes(&key, keybuf, keylen) != 1) {
|
||||
if (verbose) {
|
||||
xmss_public_key_print(stderr, 0, 0, "lms_public_key", &key);
|
||||
}
|
||||
|
||||
if (xmss_sign_init(&ctx, &key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (xmss_sign_init(&sign_ctx, &key) != 1) {
|
||||
// write updated key back to file
|
||||
// TODO: write back `q` only
|
||||
if (xmss_private_key_to_bytes(&key, &p, &keylen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
rewind(keyfp);
|
||||
if (fwrite(keybuf, 1, keylen, keyfp) != keylen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
@@ -118,46 +142,30 @@ bad:
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
if (xmss_sign_update(&sign_ctx, buf, len) != 1) {
|
||||
if (xmss_sign_update(&ctx, buf, len) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (xmss_sign_finish(&sign_ctx, &key, NULL, &siglen) != 1) {
|
||||
if (xmss_sign_finish(&ctx, sig, &siglen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(sigbuf = malloc(siglen))) {
|
||||
fprintf(stderr, "%s: malloc failure\n", prog);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (xmss_sign_finish(&sign_ctx, &key, sigbuf, &siglen) != 1) {
|
||||
if (fwrite(sig, 1, siglen, outfp) != siglen) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (fwrite(sigbuf, 1, siglen, outfp) != siglen) {
|
||||
error_print();
|
||||
goto end;
|
||||
if (verbose) {
|
||||
xmss_signature_print(stderr, 0, 0, "lms_signature", sig, siglen);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
gmssl_secure_clear(&key, sizeof(key));
|
||||
gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx));
|
||||
if (sigbuf) {
|
||||
gmssl_secure_clear(sigbuf, siglen);
|
||||
free(sigbuf);
|
||||
}
|
||||
if (keybuf) {
|
||||
gmssl_secure_clear(keybuf, keylen);
|
||||
free(keybuf);
|
||||
}
|
||||
//if (keyfp) fclose(keyfp);
|
||||
xmss_key_cleanup(&key);
|
||||
gmssl_secure_clear(keybuf, sizeof(keybuf));
|
||||
gmssl_secure_clear(&ctx, sizeof(ctx));
|
||||
if (keyfp) fclose(keyfp);
|
||||
if (infp && infp != stdin) fclose(infp);
|
||||
if (outfp && outfp != stdout) fclose(outfp);
|
||||
return ret;
|
||||
|
||||
@@ -108,13 +108,13 @@ bad:
|
||||
fprintf(stderr, "%s: read public key failure\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (xmss_public_key_from_bytes(&key, cp, pubkeylen) != 1) {
|
||||
if (xmss_public_key_from_bytes(&key, &cp, &pubkeylen) != 1) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: invalid public key data\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (verbose) {
|
||||
xmss_key_print(stderr, 0, 0, "xmss_public_key", &key);
|
||||
xmss_public_key_print(stderr, 0, 0, "xmss_public_key", &key);
|
||||
}
|
||||
|
||||
// read signature even if signature not compatible with the public key
|
||||
@@ -141,7 +141,7 @@ bad:
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if ((vr = xmss_verify_finish(&ctx, &key, sig, siglen)) < 0) {
|
||||
if ((vr = xmss_verify_finish(&ctx)) < 0) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user