Update XMSS-SM3

XMSS is in developing, not fully tested
This commit is contained in:
Zhi Guan
2025-12-08 10:24:00 +08:00
parent d3dd07e885
commit bae8f54667
11 changed files with 573 additions and 276 deletions

View File

@@ -54,7 +54,7 @@ option(ENABLE_SM4_CBC_MAC "Enable SM4-CBC-MAC" ON)
option(ENABLE_SM2_EXTS "Enable SM2 Extensions" OFF) option(ENABLE_SM2_EXTS "Enable SM2 Extensions" OFF)
option(ENABLE_LMS_HSS "Enable LMS/HSS signature" ON) option(ENABLE_LMS_HSS "Enable LMS/HSS signature" ON)
option(ENABLE_SM3_XMSS "Enable SM3-XMSS signature" OFF) option(ENABLE_XMSS "Enable XMSS/XMSS^MT signature" OFF)
option(ENABLE_SHA1 "Enable SHA1" ON) option(ENABLE_SHA1 "Enable SHA1" ON)
@@ -432,16 +432,17 @@ if (ENABLE_LMS_HSS)
endif() endif()
if (ENABLE_SM3_XMSS) if (ENABLE_XMSS)
message(STATUS "ENABLE_SM3_XMSS is ON") message(STATUS "ENABLE_XMSS is ON")
add_definitions(-DENABLE_SM3_XMSS) add_definitions(-DENABLE_XMSS)
list(APPEND src src/sm3_xmss.c) list(APPEND src src/xmss.c)
list(APPEND tools tools/xmsskeygen.c tools/xmsssign.c tools/xmssverify.c)
list(APPEND tests xmss)
option(ENABLE_SM3_XMSS_CROSSCHECK "Enable XMSS SHA-256 cross-check" OFF) option(ENABLE_XMSS_CROSSCHECK "Enable XMSS SHA-256 cross-check" ON)
if (ENABLE_SM3_XMSS_CROSSCHECK) if (ENABLE_XMSS_CROSSCHECK)
message(STATUS "ENABLE_SM3_XMSS_CROSSCHECK is ON") message(STATUS "ENABLE_XMSS_CROSSCHECK is ON")
add_definitions(-DENABLE_SM3_XMSS_CROSSCHECK) add_definitions(-DENABLE_XMSS_CROSSCHECK)
list(APPEND tests sm3_xmss)
endif() endif()
endif() endif()

28
include/gmssl/hash256.h Normal file
View File

@@ -0,0 +1,28 @@
/*
* 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef GMSSL_HASH256_H
#define GMSSL_HASH256_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint8_t hash256_t[32];
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -10,28 +10,22 @@
#ifndef GMSSL_LMS_H #ifndef GMSSL_LMS_H
#define GMSSL_LMS_H #define GMSSL_LMS_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <gmssl/sm3.h> #include <gmssl/sm3.h>
#include <gmssl/hash256.h>
#ifdef ENABLE_SHA2 #ifdef ENABLE_SHA2
#include <gmssl/sha2.h> #include <gmssl/sha2.h>
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef uint8_t hash256_t[32];
#define HSS_MAX_LEVELS 5 #define HSS_MAX_LEVELS 5
#define LMS_MAX_HEIGHT 25 #define LMS_MAX_HEIGHT 25

View File

@@ -1,127 +0,0 @@
/*
* Copyright 2014-2023 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef GMSSL_SM3_XMSS_H
#define GMSSL_SM3_XMSS_H
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <gmssl/sm3.h>
#ifdef ENABLE_SHA2
#include <gmssl/sha2.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Crosscheck with data from xmss-reference (SHA-256), except the XMSS signature.
#if defined(ENABLE_SM3_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
#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
#endif
typedef uint8_t hash256_bytes_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_bytes_t sk[67]);
void sm3_wots_derive_pk(const hash256_bytes_t sk[67],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
hash256_bytes_t pk[67]);
void sm3_wots_do_sign(const hash256_bytes_t sk[67],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
const uint8_t dgst[32], hash256_bytes_t sig[67]);
void sm3_wots_sig_to_pk(const hash256_bytes_t sig[67], const uint8_t dgst[32],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
hash256_bytes_t pk[67]);
void sm3_xmss_derive_root(const uint8_t xmss_secret[32], int height,
const uint8_t seed[32],
hash256_bytes_t *tree, uint8_t xmss_root[32]);
void sm3_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_bytes_t *tree,
const uint8_t dgst[32],
hash256_bytes_t wots_sig[67],
hash256_bytes_t *auth_path);
void sm3_xmss_sig_to_root(const hash256_bytes_t wots_sig[67], int index, const hash256_bytes_t *auth_path,
const uint8_t seed[32], const uint8_t in_adrs[32], int height,
const uint8_t dgst[32],
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,
};
int sm3_xmss_height_from_oid(uint32_t *height, uint32_t id);
typedef struct {
uint32_t oid;
uint8_t seed[32];
uint8_t root[32];
uint8_t secret[32];
uint8_t prf_key[32];
uint32_t index;
hash256_bytes_t *tree;
} SM3_XMSS_KEY;
int sm3_xmss_key_generate(SM3_XMSS_KEY *key, uint32_t oid);
int sm3_xmss_key_print(FILE *fp, int fmt, int ind, const char *label, const SM3_XMSS_KEY *key);
int sm3_xmss_key_get_height(const SM3_XMSS_KEY *key, uint32_t *height);
int sm3_xmss_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *outlen);
int sm3_xmss_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t inlen);
int sm3_xmss_public_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *outlen);
int sm3_xmss_public_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t inlen);
void sm3_xmss_key_cleanup(SM3_XMSS_KEY *key);
typedef struct {
uint8_t index[4];
uint8_t random[32];
hash256_bytes_t wots_sig[67];
hash256_bytes_t auth_path[20];
} SM3_XMSS_SIGNATURE;
int sm3_xmss_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *in, size_t inlen);
typedef struct {
uint8_t random[32];
HASH256_CTX hash256_ctx;
} SM3_XMSS_SIGN_CTX;
int sm3_xmss_sign_init(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key);
int sm3_xmss_sign_update(SM3_XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int sm3_xmss_sign_finish(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, uint8_t *sigbuf, size_t *siglen);
int sm3_xmss_verify_init(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, const uint8_t *sigbuf, size_t siglen);
int sm3_xmss_verify_update(SM3_XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
int sm3_xmss_verify_finish(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, const uint8_t *sigbuf, size_t siglen);
#ifdef __cplusplus
}
#endif
#endif

181
include/gmssl/xmss.h Normal file
View File

@@ -0,0 +1,181 @@
/*
* 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef GMSSL_XMSS_H
#define GMSSL_XMSS_H
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <gmssl/sm3.h>
#include <gmssl/hash256.h>
#ifdef ENABLE_SHA2
#include <gmssl/sha2.h>
#endif
#ifdef __cplusplus
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 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
#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
#endif
#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
// 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]);
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]);
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);
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,
const uint8_t dgst[32],
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);
// 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];
uint8_t secret[32];
uint8_t prf_key[32];
uint32_t index; // change this to int, update every signing
hash256_t *tree;
} XMSS_KEY;
#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_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);
void xmss_key_cleanup(XMSS_KEY *key);
typedef struct {
uint8_t index[4];
uint8_t random[32];
hash256_t wots_sig[67];
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_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *in, size_t inlen);
typedef struct {
uint8_t random[32];
HASH256_CTX hash256_ctx;
// TODO: cache signing key
} XMSS_SIGN_CTX;
// 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);
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_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);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -18,7 +18,7 @@
#include <gmssl/hex.h> #include <gmssl/hex.h>
#include <gmssl/rand.h> #include <gmssl/rand.h>
#include <gmssl/error.h> #include <gmssl/error.h>
#include <gmssl/sm3_xmss.h> #include <gmssl/xmss.h>
#define uint32_from_bytes(ptr) \ #define uint32_from_bytes(ptr) \
@@ -134,6 +134,8 @@ static void hash256_prf_keygen_init(HASH256_CTX *hash256_ctx, const uint8_t key[
hash256_update(hash256_ctx, key, 32); hash256_update(hash256_ctx, key, 32);
} }
// compute wots+ chain, start from the secret x or a signature, output the final value
// 最终的这个结果应该不是PK啊
static void wots_chain(const uint8_t x[32], int start, int steps, static void wots_chain(const uint8_t x[32], int start, int steps,
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32], uint8_t pk[32]) const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32], uint8_t pk[32])
{ {
@@ -173,7 +175,7 @@ static void wots_chain(const uint8_t x[32], int start, int steps,
memcpy(pk, state, 32); memcpy(pk, state, 32);
} }
void sm3_wots_derive_sk(const uint8_t secret[32], const uint8_t seed[32], const uint8_t in_adrs[32], hash256_bytes_t sk[67]) 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])
{ {
HASH256_CTX prf_keygen_ctx; HASH256_CTX prf_keygen_ctx;
HASH256_CTX prf_ctx; HASH256_CTX prf_ctx;
@@ -196,9 +198,9 @@ void sm3_wots_derive_sk(const uint8_t secret[32], const uint8_t seed[32], const
} }
} }
void sm3_wots_derive_pk(const hash256_bytes_t sk[67], void sm3_wots_derive_pk(const hash256_t sk[67],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32], const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
hash256_bytes_t pk[67]) hash256_t pk[67])
{ {
uint8_t adrs[32]; uint8_t adrs[32];
int i; int i;
@@ -238,9 +240,9 @@ static void base_w_and_checksum(const uint8_t dgst[32], uint8_t msg[67])
msg[66] = csum_bytes[1] >> 4; msg[66] = csum_bytes[1] >> 4;
} }
void sm3_wots_do_sign(const hash256_bytes_t sk[67], void sm3_wots_do_sign(const hash256_t sk[67],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32], const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
const uint8_t dgst[32], hash256_bytes_t sig[67]) const uint8_t dgst[32], hash256_t sig[67])
{ {
uint8_t adrs[32]; uint8_t adrs[32];
uint8_t msg[67]; uint8_t msg[67];
@@ -256,9 +258,9 @@ void sm3_wots_do_sign(const hash256_bytes_t sk[67],
} }
} }
void sm3_wots_sig_to_pk(const hash256_bytes_t sig[67], const uint8_t dgst[32], 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], const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
hash256_bytes_t pk[67]) hash256_t pk[67])
{ {
uint8_t adrs[32]; uint8_t adrs[32];
uint8_t msg[67]; uint8_t msg[67];
@@ -311,11 +313,11 @@ static void randomized_hash(const uint8_t left[32], const uint8_t right[32],
hash256_finish(&hash256_ctx, out); hash256_finish(&hash256_ctx, out);
} }
static void build_ltree(const hash256_bytes_t in_pk[67], static void build_ltree(const hash256_t in_pk[67],
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32], const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
uint8_t wots_root[32]) uint8_t wots_root[32])
{ {
hash256_bytes_t pk[67]; hash256_t pk[67];
uint8_t adrs[32]; uint8_t adrs[32];
uint32_t tree_height = 0; uint32_t tree_height = 0;
int len = 67; int len = 67;
@@ -344,9 +346,9 @@ static void build_ltree(const hash256_bytes_t in_pk[67],
// len(tree) = 2^h - 1 // len(tree) = 2^h - 1
// root = tree[len(tree) - 1] = tree[2^h - 2] // root = tree[len(tree) - 1] = tree[2^h - 2]
static void build_hash_tree(const hash256_bytes_t *leaves, int height, static void build_hash_tree(const hash256_t *leaves, int height,
const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32], const HASH256_CTX *prf_seed_ctx, const uint8_t in_adrs[32],
hash256_bytes_t *tree) hash256_t *tree)
{ {
uint8_t adrs[32]; uint8_t adrs[32];
int n = 1 << height; int n = 1 << height;
@@ -368,9 +370,9 @@ static void build_hash_tree(const hash256_bytes_t *leaves, int height,
} }
} }
void sm3_xmss_derive_root(const uint8_t xmss_secret[32], int height, void xmss_derive_root(const uint8_t xmss_secret[32], int height,
const uint8_t seed[32], const uint8_t seed[32],
hash256_bytes_t *tree, uint8_t xmss_root[32]) hash256_t *tree, uint8_t xmss_root[32])
{ {
HASH256_CTX prf_keygen_ctx; HASH256_CTX prf_keygen_ctx;
HASH256_CTX prf_seed_ctx; HASH256_CTX prf_seed_ctx;
@@ -383,8 +385,8 @@ void sm3_xmss_derive_root(const uint8_t xmss_secret[32], int height,
// generate all the wots pk[] // generate all the wots pk[]
for (i = 0; i < (uint32_t)(1<<height); i++) { for (i = 0; i < (uint32_t)(1<<height); i++) {
//HASH256_CTX prf_ctx = prf_keygen_ctx; //HASH256_CTX prf_ctx = prf_keygen_ctx;
hash256_bytes_t wots_sk[67]; hash256_t wots_sk[67];
hash256_bytes_t wots_pk[67]; hash256_t wots_pk[67];
// xmss_secret => wots_sk[0..67] => wots_pk[0..67] // xmss_secret => wots_sk[0..67] => wots_pk[0..67]
// follow github.com/XMSS/xmss-reference // follow github.com/XMSS/xmss-reference
@@ -405,7 +407,7 @@ void sm3_xmss_derive_root(const uint8_t xmss_secret[32], int height,
memcpy(xmss_root, tree + (1 << (height + 1)) - 2, 32); memcpy(xmss_root, tree + (1 << (height + 1)) - 2, 32);
} }
static void build_auth_path(const hash256_bytes_t *tree, int height, int index, hash256_bytes_t *path) static void build_auth_path(const hash256_t *tree, int height, int index, hash256_t *path)
{ {
int h; int h;
for (h = 0; h < height; h++) { for (h = 0; h < height; h++) {
@@ -415,16 +417,16 @@ static void build_auth_path(const hash256_bytes_t *tree, int height, int index,
} }
} }
void sm3_xmss_do_sign(const uint8_t xmss_secret[32], int index, 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 uint8_t seed[32], const uint8_t in_adrs[32], int height,
const hash256_bytes_t *tree, const hash256_t *tree,
const uint8_t dgst[32], const uint8_t dgst[32],
hash256_bytes_t wots_sig[67], hash256_t wots_sig[67],
hash256_bytes_t *auth_path) hash256_t *auth_path)
{ {
HASH256_CTX prf_seed_ctx; HASH256_CTX prf_seed_ctx;
uint8_t adrs[32]; uint8_t adrs[32];
hash256_bytes_t wots_sk[67]; hash256_t wots_sk[67];
hash256_prf_init(&prf_seed_ctx, seed); hash256_prf_init(&prf_seed_ctx, seed);
memcpy(adrs, in_adrs, 32); memcpy(adrs, in_adrs, 32);
@@ -439,14 +441,14 @@ void sm3_xmss_do_sign(const uint8_t xmss_secret[32], int index,
build_auth_path(tree, height, index, auth_path); build_auth_path(tree, height, index, auth_path);
} }
void sm3_xmss_sig_to_root(const hash256_bytes_t wots_sig[67], int index, const hash256_bytes_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, const uint8_t seed[32], const uint8_t in_adrs[32], int height,
const uint8_t dgst[32], const uint8_t dgst[32],
uint8_t xmss_root[32]) uint8_t xmss_root[32])
{ {
HASH256_CTX prf_seed_ctx; HASH256_CTX prf_seed_ctx;
uint8_t adrs[32]; uint8_t adrs[32];
hash256_bytes_t wots_pk[67]; hash256_t wots_pk[67];
uint8_t *node = xmss_root; uint8_t *node = xmss_root;
int h; int h;
@@ -475,7 +477,7 @@ void sm3_xmss_sig_to_root(const hash256_bytes_t wots_sig[67], int index, const h
} }
} }
int sm3_xmss_height_from_oid(uint32_t *height, uint32_t id) int xmss_height_from_oid(uint32_t *height, uint32_t id)
{ {
switch (id) { switch (id) {
case XMSS_SM3_10: *height = 10; break; case XMSS_SM3_10: *height = 10; break;
@@ -491,11 +493,27 @@ int sm3_xmss_height_from_oid(uint32_t *height, uint32_t id)
return 1; return 1;
} }
int sm3_xmss_key_generate(SM3_XMSS_KEY *key, uint32_t oid) int xmss_oid_to_height(uint32_t oid, size_t *height)
{
switch (oid) {
case XMSS_SM3_10: *height = 10; break;
case XMSS_SM3_16: *height = 16; break;
case XMSS_SM3_20: *height = 20; break;
case XMSS_SHA256_10: *height = 10; break;
case XMSS_SHA256_16: *height = 16; break;
case XMSS_SHA256_20: *height = 20; break;
default:
error_print();
return -1;
}
return 1;
}
int xmss_key_generate(XMSS_KEY *key, uint32_t oid)
{ {
uint32_t height; uint32_t height;
if (sm3_xmss_height_from_oid(&height, oid) != 1) { if (xmss_height_from_oid(&height, oid) != 1) {
error_print(); error_print();
return -1; return -1;
} }
@@ -509,12 +527,12 @@ int sm3_xmss_key_generate(SM3_XMSS_KEY *key, uint32_t oid)
error_print(); error_print();
return -1; return -1;
} }
sm3_xmss_derive_root(key->secret, height, key->seed, key->tree, key->root); xmss_derive_root(key->secret, height, key->seed, key->tree, key->root);
return 1; return 1;
} }
void sm3_xmss_key_cleanup(SM3_XMSS_KEY *key) void xmss_key_cleanup(XMSS_KEY *key)
{ {
if (key->tree) { if (key->tree) {
free(key->tree); free(key->tree);
@@ -522,7 +540,7 @@ void sm3_xmss_key_cleanup(SM3_XMSS_KEY *key)
gmssl_secure_clear(key, sizeof(*key)); gmssl_secure_clear(key, sizeof(*key));
} }
int sm3_xmss_key_print(FILE *fp, int fmt, int ind, const char *label, const SM3_XMSS_KEY *key) int xmss_key_print(FILE *fp, int fmt, int ind, const char *label, const XMSS_KEY *key)
{ {
format_print(fp, fmt, ind, "%s\n", label); format_print(fp, fmt, ind, "%s\n", label);
ind += 4; ind += 4;
@@ -535,16 +553,18 @@ int sm3_xmss_key_print(FILE *fp, int fmt, int ind, const char *label, const SM3_
return 1; return 1;
} }
int sm3_xmss_key_get_height(const SM3_XMSS_KEY *key, uint32_t *height)
int xmss_key_get_height(const XMSS_KEY *key, uint32_t *height)
{ {
if (sm3_xmss_height_from_oid(height, key->oid) != 1) { if (xmss_height_from_oid(height, key->oid) != 1) {
error_print(); error_print();
return -1; return -1;
} }
return 1; return 1;
} }
int sm3_xmss_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *outlen) // save the full tree, should use a flag to choose cache tree or not
int xmss_key_to_bytes(const XMSS_KEY *key, uint8_t *out, size_t *outlen)
{ {
uint32_t height; uint32_t height;
size_t tree_size; size_t tree_size;
@@ -555,7 +575,7 @@ int sm3_xmss_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *outlen)
return -1; return -1;
} }
if (sm3_xmss_height_from_oid(&height, key->oid) != 1) { if (xmss_height_from_oid(&height, key->oid) != 1) {
error_print(); error_print();
return -1; return -1;
} }
@@ -583,7 +603,7 @@ int sm3_xmss_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *outlen)
return 1; return 1;
} }
int sm3_xmss_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t inlen) int xmss_key_from_bytes(XMSS_KEY *key, const uint8_t *in, size_t inlen)
{ {
uint32_t height; uint32_t height;
size_t tree_size; size_t tree_size;
@@ -596,7 +616,7 @@ int sm3_xmss_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t inlen)
p = in; p = in;
key->oid = uint32_from_bytes(p); p += 4; key->oid = uint32_from_bytes(p); p += 4;
if (sm3_xmss_height_from_oid(&height, key->oid) != 1) { if (xmss_height_from_oid(&height, key->oid) != 1) {
error_print(); error_print();
return -1; return -1;
} }
@@ -624,7 +644,7 @@ int sm3_xmss_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t inlen)
return 1; return 1;
} }
int sm3_xmss_public_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *outlen) int xmss_public_key_to_bytes(const XMSS_KEY *key, uint8_t *out, size_t *outlen)
{ {
uint32_t height; uint32_t height;
uint8_t *p; uint8_t *p;
@@ -634,7 +654,7 @@ int sm3_xmss_public_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *
return -1; return -1;
} }
if (sm3_xmss_height_from_oid(&height, key->oid) != 1) { if (xmss_height_from_oid(&height, key->oid) != 1) {
error_print(); error_print();
return -1; return -1;
} }
@@ -654,7 +674,7 @@ int sm3_xmss_public_key_to_bytes(const SM3_XMSS_KEY *key, uint8_t *out, size_t *
} }
// FIXME: check input length // FIXME: check input length
int sm3_xmss_public_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t inlen) int xmss_public_key_from_bytes(XMSS_KEY *key, const uint8_t *in, size_t inlen)
{ {
uint32_t height; uint32_t height;
const uint8_t *p; const uint8_t *p;
@@ -665,7 +685,7 @@ int sm3_xmss_public_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t
} }
p = in; p = in;
key->oid = uint32_from_bytes(p); p += 4; key->oid = uint32_from_bytes(p); p += 4;
if (sm3_xmss_height_from_oid(&height, key->oid) != 1) { if (xmss_height_from_oid(&height, key->oid) != 1) {
error_print(); error_print();
return -1; return -1;
} }
@@ -674,10 +694,10 @@ int sm3_xmss_public_key_from_bytes(SM3_XMSS_KEY *key, const uint8_t *in, size_t
return 1; return 1;
} }
int sm3_xmss_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *in, size_t inlen) int xmss_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *in, size_t inlen)
{ {
uint32_t index; uint32_t index;
SM3_XMSS_SIGNATURE *sig = (SM3_XMSS_SIGNATURE *)in; XMSS_SIGNATURE *sig = (XMSS_SIGNATURE *)in;
int i; int i;
format_print(fp, fmt, ind, "%s\n", label); format_print(fp, fmt, ind, "%s\n", label);
@@ -693,7 +713,7 @@ int sm3_xmss_signature_print(FILE *fp, int fmt, int ind, const char *label, cons
} }
format_print(fp, fmt, ind, "auth_path\n"); format_print(fp, fmt, ind, "auth_path\n");
assert(sizeof(SM3_XMSS_SIGNATURE) == 4 + 32 * (68 + 20)); assert(sizeof(XMSS_SIGNATURE) == 4 + 32 * (68 + 20));
inlen -= 4 + 32 * 68; inlen -= 4 + 32 * 68;
for (i = 0; i < 20 && inlen >= 32; i++) { for (i = 0; i < 20 && inlen >= 32; i++) {
format_print(fp, fmt, ind+4, "%d ", i); format_print(fp, fmt, ind+4, "%d ", i);
@@ -704,7 +724,31 @@ int sm3_xmss_signature_print(FILE *fp, int fmt, int ind, const char *label, cons
return 1; return 1;
} }
int sm3_xmss_sign_init(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key)
// (4 + n + (len + h) * n)
int xmss_signature_size(uint32_t oid, size_t *siglen)
{
size_t height;
if (!siglen) {
error_print();
return -1;
}
if (xmss_oid_to_height(oid, &height) != 1) {
error_print();
return -1;
}
*siglen = 4 // OID
+ 32 // random
+ 32 * 67 // WOTS signature size
+ 32 * height // path
;
return 1;
}
int xmss_sign_init(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key)
{ {
HASH256_CTX prf_ctx; HASH256_CTX prf_ctx;
uint8_t hash_id[32] = {0}; uint8_t hash_id[32] = {0};
@@ -727,7 +771,7 @@ int sm3_xmss_sign_init(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key)
return 1; return 1;
} }
int sm3_xmss_sign_update(SM3_XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) int xmss_sign_update(XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
{ {
if (data && datalen) { if (data && datalen) {
hash256_update(&ctx->hash256_ctx, data, datalen); hash256_update(&ctx->hash256_ctx, data, datalen);
@@ -735,17 +779,17 @@ int sm3_xmss_sign_update(SM3_XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t dat
return 1; return 1;
} }
int sm3_xmss_sign_finish(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, uint8_t *sigbuf, size_t *siglen) int xmss_sign_finish(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key, uint8_t *sigbuf, size_t *siglen)
{ {
SM3_XMSS_SIGNATURE *sig = (SM3_XMSS_SIGNATURE *)sigbuf; XMSS_SIGNATURE *sig = (XMSS_SIGNATURE *)sigbuf;
uint8_t adrs[32] = {0}; uint8_t adrs[32] = {0};
uint8_t dgst[32]; uint8_t dgst[32];
uint32_t height; uint32_t height;
hash256_finish(&ctx->hash256_ctx, dgst); hash256_finish(&ctx->hash256_ctx, dgst);
sm3_xmss_key_get_height(key, &height); xmss_key_get_height(key, &height);
sm3_xmss_do_sign(key->secret, key->index, key->seed, adrs, height, key->tree, dgst, xmss_do_sign(key->secret, key->index, key->seed, adrs, height, key->tree, dgst,
sig->wots_sig, sig->auth_path); sig->wots_sig, sig->auth_path);
uint32_to_bytes(key->index, sig->index); uint32_to_bytes(key->index, sig->index);
@@ -755,9 +799,9 @@ int sm3_xmss_sign_finish(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, uint8_
return 1; return 1;
} }
int sm3_xmss_verify_init(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, const 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)
{ {
SM3_XMSS_SIGNATURE *sig = (SM3_XMSS_SIGNATURE *)sigbuf; XMSS_SIGNATURE *sig = (XMSS_SIGNATURE *)sigbuf;
uint8_t hash_id[32] = {0}; uint8_t hash_id[32] = {0};
uint8_t index_buf[32] = {0}; uint8_t index_buf[32] = {0};
@@ -773,7 +817,7 @@ int sm3_xmss_verify_init(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, const
return 1; return 1;
} }
int sm3_xmss_verify_update(SM3_XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) int xmss_verify_update(XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
{ {
if (data && datalen) { if (data && datalen) {
hash256_update(&ctx->hash256_ctx, data, datalen); hash256_update(&ctx->hash256_ctx, data, datalen);
@@ -781,10 +825,10 @@ int sm3_xmss_verify_update(SM3_XMSS_SIGN_CTX *ctx, const uint8_t *data, size_t d
return 1; return 1;
} }
int sm3_xmss_verify_finish(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, const uint8_t *sigbuf, size_t siglen) int xmss_verify_finish(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key, const uint8_t *sigbuf, size_t siglen)
{ {
const SM3_XMSS_SIGNATURE *sig = (const SM3_XMSS_SIGNATURE *)sigbuf; const XMSS_SIGNATURE *sig = (const XMSS_SIGNATURE *)sigbuf;
uint8_t adrs[32] = {0}; uint8_t adrs[32] = {0};
uint8_t dgst[32]; uint8_t dgst[32];
uint32_t index, height; uint32_t index, height;
@@ -792,10 +836,10 @@ int sm3_xmss_verify_finish(SM3_XMSS_SIGN_CTX *ctx, const SM3_XMSS_KEY *key, cons
hash256_finish(&ctx->hash256_ctx, dgst); hash256_finish(&ctx->hash256_ctx, dgst);
sm3_xmss_key_get_height(key, &height); xmss_key_get_height(key, &height);
index = uint32_from_bytes(sig->index); index = uint32_from_bytes(sig->index);
sm3_xmss_sig_to_root(sig->wots_sig, index, sig->auth_path, key->seed, adrs, height, dgst, xmss_root); xmss_sig_to_root(sig->wots_sig, index, sig->auth_path, key->seed, adrs, height, dgst, xmss_root);
if (memcmp(xmss_root, key->root, 32) != 0) { if (memcmp(xmss_root, key->root, 32) != 0) {
error_print(); error_print();

View File

@@ -12,7 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <gmssl/hex.h> #include <gmssl/hex.h>
#include <gmssl/error.h> #include <gmssl/error.h>
#include <gmssl/sm3_xmss.h> #include <gmssl/xmss.h>
// copy this static function from src/sm3_xmss.c // copy this static function from src/sm3_xmss.c
@@ -31,8 +31,8 @@ static int test_sm3_wots_derive_sk(void)
uint8_t wots_secret[32] = {0}; uint8_t wots_secret[32] = {0};
uint8_t seed[32] = {0}; uint8_t seed[32] = {0};
uint8_t adrs[32] = {0}; uint8_t adrs[32] = {0};
hash256_bytes_t wots_sk[67]; hash256_t wots_sk[67];
hash256_bytes_t test_sk[67]; hash256_t test_sk[67];
size_t len; size_t len;
// sha256 test 1 // sha256 test 1
@@ -76,9 +76,9 @@ static int test_sm3_wots_derive_pk(void)
uint8_t wots_secret[32] = {0}; uint8_t wots_secret[32] = {0};
uint8_t seed[32] = {0}; uint8_t seed[32] = {0};
uint8_t adrs[32] = {0}; uint8_t adrs[32] = {0};
hash256_bytes_t wots_sk[67]; hash256_t wots_sk[67];
hash256_bytes_t wots_pk[67]; hash256_t wots_pk[67];
hash256_bytes_t test_pk[67]; hash256_t test_pk[67];
HASH256_CTX prf_seed_ctx; HASH256_CTX prf_seed_ctx;
size_t len; size_t len;
@@ -111,11 +111,11 @@ static int test_sm3_wots_do_sign(void)
uint8_t seed[32] = {0}; uint8_t seed[32] = {0};
uint8_t adrs[32] = {0}; uint8_t adrs[32] = {0};
uint8_t dgst[32] = {0}; uint8_t dgst[32] = {0};
hash256_bytes_t wots_sk[67]; hash256_t wots_sk[67];
hash256_bytes_t wots_pk[67]; hash256_t wots_pk[67];
hash256_bytes_t wots_sig[67]; hash256_t wots_sig[67];
hash256_bytes_t test_sig[67]; hash256_t test_sig[67];
hash256_bytes_t sig_pk[67]; hash256_t sig_pk[67];
HASH256_CTX prf_seed_ctx; HASH256_CTX prf_seed_ctx;
size_t len; size_t len;
int i; int i;
@@ -154,12 +154,12 @@ static int test_sm3_wots_do_sign(void)
return 1; return 1;
} }
static int test_sm3_xmss_derive_root(void) static int test_xmss_derive_root(void)
{ {
uint8_t xmss_secret[32]; uint8_t xmss_secret[32];
uint8_t seed[32]; uint8_t seed[32];
int height = 10; int height = 10;
hash256_bytes_t *tree = malloc(32 * (1<<height) * 2); hash256_t *tree = malloc(32 * (1<<height) * 2);
uint8_t xmss_root[32]; uint8_t xmss_root[32];
uint8_t test_root[32]; uint8_t test_root[32];
size_t len; size_t len;
@@ -168,7 +168,7 @@ static int test_sm3_xmss_derive_root(void)
memset(seed, 0xab, 32); memset(seed, 0xab, 32);
hex_to_bytes("f0415ed807c8f8c2ee8ca3a00178bff37e1ccb2836e02607d06131c9341e52ca", 64, test_root, &len); hex_to_bytes("f0415ed807c8f8c2ee8ca3a00178bff37e1ccb2836e02607d06131c9341e52ca", 64, test_root, &len);
sm3_xmss_derive_root(xmss_secret, height, seed, tree, xmss_root); xmss_derive_root(xmss_secret, height, seed, tree, xmss_root);
if (memcmp(xmss_root, test_root, 32)) { if (memcmp(xmss_root, test_root, 32)) {
error_print(); error_print();
@@ -180,7 +180,7 @@ static int test_sm3_xmss_derive_root(void)
} }
static int test_sm3_xmss_do_sign(void) static int test_xmss_do_sign(void)
{ {
uint8_t xmss_secret[32]; uint8_t xmss_secret[32];
uint8_t xmss_root[32]; uint8_t xmss_root[32];
@@ -188,9 +188,9 @@ static int test_sm3_xmss_do_sign(void)
uint8_t dgst[32]; uint8_t dgst[32];
uint8_t seed[32]; uint8_t seed[32];
uint8_t adrs[32] = {0}; uint8_t adrs[32] = {0};
hash256_bytes_t wots_sig[67]; hash256_t wots_sig[67];
hash256_bytes_t *auth_path = malloc(32 * h); hash256_t *auth_path = malloc(32 * h);
hash256_bytes_t *tree = malloc(32 * (1<<h) * 2); hash256_t *tree = malloc(32 * (1<<h) * 2);
uint32_t index = 0; uint32_t index = 0;
uint8_t i; uint8_t i;
@@ -200,12 +200,12 @@ static int test_sm3_xmss_do_sign(void)
dgst[i] = i; dgst[i] = i;
} }
sm3_xmss_derive_root(xmss_secret, h, seed, tree, xmss_root); xmss_derive_root(xmss_secret, h, seed, tree, xmss_root);
for (index = 0; index < (1<<h); index++) { for (index = 0; index < (1<<h); index++) {
uint8_t root_from_sig[32]; uint8_t root_from_sig[32];
sm3_xmss_do_sign(xmss_secret, index, seed, adrs, h, tree, dgst, wots_sig, auth_path); xmss_do_sign(xmss_secret, index, seed, adrs, h, tree, dgst, wots_sig, auth_path);
sm3_xmss_sig_to_root(wots_sig, index, auth_path, seed, adrs, h, dgst, root_from_sig); 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) { if (memcmp(xmss_root, root_from_sig, 32) != 0) {
printf("xmss_sig_to_root failed\n"); printf("xmss_sig_to_root failed\n");
return -1; return -1;
@@ -216,40 +216,40 @@ static int test_sm3_xmss_do_sign(void)
return 1; return 1;
} }
static int test_sm3_xmss_sign(void) static int test_xmss_sign(void)
{ {
#if defined(ENABLE_SHA2) && defined(ENABLE_SM3_XMSS_CROSSCHECK) #if defined(ENABLE_SHA2) && defined(ENABLE_XMSS_CROSSCHECK)
uint32_t oid = XMSS_SHA256_10; uint32_t oid = XMSS_SHA256_10;
#else #else
uint32_t oid = XMSS_SM3_10; uint32_t oid = XMSS_SM3_10;
#endif #endif
SM3_XMSS_KEY key; XMSS_KEY key;
SM3_XMSS_SIGN_CTX sign_ctx; XMSS_SIGN_CTX sign_ctx;
uint8_t sig[sizeof(SM3_XMSS_SIGNATURE)]; uint8_t sig[sizeof(XMSS_SIGNATURE)];
size_t siglen; size_t siglen;
uint8_t msg[100] = {0}; uint8_t msg[100] = {0};
int i; int i;
sm3_xmss_key_generate(&key, oid); xmss_key_generate(&key, oid);
sm3_xmss_key_print(stderr, 0, 0, "XMSS Key", &key); xmss_key_print(stderr, 0, 0, "XMSS Key", &key);
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
sm3_xmss_sign_init(&sign_ctx, &key); xmss_sign_init(&sign_ctx, &key);
sm3_xmss_sign_update(&sign_ctx, msg, sizeof(msg)); xmss_sign_update(&sign_ctx, msg, sizeof(msg));
sm3_xmss_sign_finish(&sign_ctx, &key, sig, &siglen); xmss_sign_finish(&sign_ctx, &key, sig, &siglen);
(key.index)++; (key.index)++;
sm3_xmss_signature_print(stderr, 0, 0, "XMSS Signature", sig, siglen); xmss_signature_print(stderr, 0, 0, "XMSS Signature", sig, siglen);
sm3_xmss_verify_init(&sign_ctx, &key, sig, siglen); xmss_verify_init(&sign_ctx, &key, sig, siglen);
sm3_xmss_verify_update(&sign_ctx, msg, sizeof(msg)); xmss_verify_update(&sign_ctx, msg, sizeof(msg));
if (sm3_xmss_verify_finish(&sign_ctx, &key, sig, siglen) != 1) { if (xmss_verify_finish(&sign_ctx, &key, sig, siglen) != 1) {
error_print(); error_print();
return -1; return -1;
} }
} }
sm3_xmss_key_cleanup(&key); xmss_key_cleanup(&key);
printf("%s() ok\n", __FUNCTION__); printf("%s() ok\n", __FUNCTION__);
return 1; return 1;
@@ -260,9 +260,9 @@ int main(void)
if (test_sm3_wots_derive_sk() != 1) goto err; if (test_sm3_wots_derive_sk() != 1) goto err;
if (test_sm3_wots_derive_pk() != 1) goto err; if (test_sm3_wots_derive_pk() != 1) goto err;
if (test_sm3_wots_do_sign() != 1) goto err; if (test_sm3_wots_do_sign() != 1) goto err;
if (test_sm3_xmss_derive_root() != 1) goto err; if (test_xmss_derive_root() != 1) goto err;
if (test_sm3_xmss_do_sign() != 1) goto err; if (test_xmss_do_sign() != 1) goto err;
if (test_sm3_xmss_sign() != 1) goto err; if (test_xmss_sign() != 1) goto err;
printf("%s all tests passed\n", __FILE__); printf("%s all tests passed\n", __FILE__);
return 0; return 0;
err: err:

View File

@@ -72,8 +72,10 @@ extern int hsskeygen_main(int argc, char **argv);
extern int hsssign_main(int argc, char **argv); extern int hsssign_main(int argc, char **argv);
extern int hssverify_main(int argc, char **argv); extern int hssverify_main(int argc, char **argv);
#endif #endif
#ifdef ENABLE_SM3_XMSS #ifdef ENABLE_XMSS
extern int sm3xmss_keygen_main(int argc, char **argv); extern int xmsskeygen_main(int argc, char **argv);
extern int xmsssign_main(int argc, char **argv);
extern int xmssverify_main(int argc, char **argv);
#endif #endif
#ifdef ENABLE_SDF #ifdef ENABLE_SDF
extern int sdfinfo_main(int argc, char **argv); extern int sdfinfo_main(int argc, char **argv);
@@ -140,15 +142,17 @@ static const char *options =
" cmssign Generate CMS SignedData\n" " cmssign Generate CMS SignedData\n"
" cmsverify Verify CMS SignedData\n" " cmsverify Verify CMS SignedData\n"
#ifdef ENABLE_LMS_HSS #ifdef ENABLE_LMS_HSS
" lmskeygen Generate SM3-LMS keypair\n" " lmskeygen Generate LMS-SM3 (Leighton-Micali Signature) keypair\n"
" lmssign Generate LMS signature\n" " lmssign Generate LMS-SM3 signature\n"
" lmsverify Verify LMS signature\n" " lmsverify Verify LMS-SM3 signature\n"
" hsskeygen Generate SM3-HSS keypair\n" " hsskeygen Generate HSS-SM3 keypair\n"
" hsssign Generate HSS signature\n" " hsssign Generate HSS-SM3 signature\n"
" hssverify Verify HSS signature\n" " hssverify Verify HSS-SM3 signature\n"
#endif #endif
#ifdef ENABLE_SM3_XMSS #ifdef ENABLE_XMSS
" sm3xmss_keygen Generate SM3-XMSS keypair\n" " xmsskeygen Generate XMSS-SM3 keypair\n"
" xmsssign Generate XMSS-SM3 signature\n"
" xmssverify Verify XMSS-SM3 signature\n"
#endif #endif
#ifdef ENABLE_SDF #ifdef ENABLE_SDF
" sdfinfo Print SDF device info\n" " sdfinfo Print SDF device info\n"
@@ -318,9 +322,13 @@ int main(int argc, char **argv)
} else if (!strcmp(*argv, "hssverify")) { } else if (!strcmp(*argv, "hssverify")) {
return hssverify_main(argc, argv); return hssverify_main(argc, argv);
#endif #endif
#ifdef ENABLE_SM3_XMSS #ifdef ENABLE_XMSS
} else if (!strcmp(*argv, "sm3xmss_keygen")) { } else if (!strcmp(*argv, "xmsskeygen")) {
return sm3xmss_keygen_main(argc, argv); return xmsskeygen_main(argc, argv);
} else if (!strcmp(*argv, "xmsssign")) {
return xmsssign_main(argc, argv);
} else if (!strcmp(*argv, "xmssverify")) {
return xmssverify_main(argc, argv);
#endif #endif
#ifdef ENABLE_SDF #ifdef ENABLE_SDF
} else if (!strcmp(*argv, "sdfinfo")) { } else if (!strcmp(*argv, "sdfinfo")) {

View File

@@ -14,7 +14,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <gmssl/mem.h> #include <gmssl/mem.h>
#include <gmssl/error.h> #include <gmssl/error.h>
#include <gmssl/sm3_xmss.h> #include <gmssl/xmss.h>
static const char *usage = "-oid oid [-out file] [-pubout file]\n"; static const char *usage = "-oid oid [-out file] [-pubout file]\n";
@@ -29,7 +29,7 @@ static const char *help =
" -pubout file Output public key\n" " -pubout file Output public key\n"
"\n"; "\n";
int sm3xmss_keygen_main(int argc, char **argv) int xmsskeygen_main(int argc, char **argv)
{ {
int ret = 1; int ret = 1;
char *prog = argv[0]; char *prog = argv[0];
@@ -39,7 +39,7 @@ int sm3xmss_keygen_main(int argc, char **argv)
char *puboutfile = NULL; char *puboutfile = NULL;
FILE *outfp = stdout; FILE *outfp = stdout;
FILE *puboutfp = stdout; FILE *puboutfp = stdout;
SM3_XMSS_KEY key; XMSS_KEY key;
uint8_t *out = NULL; uint8_t *out = NULL;
uint8_t *pubout = NULL; uint8_t *pubout = NULL;
size_t outlen, puboutlen; size_t outlen, puboutlen;
@@ -103,12 +103,12 @@ bad:
} }
if (sm3_xmss_key_generate(&key, oid_val) != 1) { if (xmss_key_generate(&key, oid_val) != 1) {
error_print(); error_print();
return -1; return -1;
} }
if (sm3_xmss_key_to_bytes(&key, NULL, &outlen) != 1) { if (xmss_key_to_bytes(&key, NULL, &outlen) != 1) {
error_print(); error_print();
goto end; goto end;
} }
@@ -116,11 +116,11 @@ bad:
error_print(); error_print();
goto end; goto end;
} }
if (sm3_xmss_key_to_bytes(&key, out, &outlen) != 1) { if (xmss_key_to_bytes(&key, out, &outlen) != 1) {
error_print(); error_print();
} }
if (sm3_xmss_public_key_to_bytes(&key, NULL, &puboutlen) != 1) { if (xmss_public_key_to_bytes(&key, NULL, &puboutlen) != 1) {
error_print(); error_print();
goto end; goto end;
} }
@@ -128,7 +128,7 @@ bad:
error_print(); error_print();
goto end; goto end;
} }
if (sm3_xmss_public_key_to_bytes(&key, pubout, &puboutlen) != 1) { if (xmss_public_key_to_bytes(&key, pubout, &puboutlen) != 1) {
error_print(); error_print();
goto end; goto end;
} }

View File

@@ -12,8 +12,10 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <gmssl/mem.h>
#include <gmssl/file.h>
#include <gmssl/error.h> #include <gmssl/error.h>
#include <gmssl/sm3_xmss.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]\n";
@@ -24,7 +26,7 @@ static const char *help =
" -out file Output signature file\n" " -out file Output signature file\n"
"\n"; "\n";
int sm3xmss_sign_main(int argc, char **argv) int xmsssign_main(int argc, char **argv)
{ {
int ret = 1; int ret = 1;
char *prog = argv[0]; char *prog = argv[0];
@@ -34,8 +36,10 @@ int sm3xmss_sign_main(int argc, char **argv)
FILE *keyfp = NULL; FILE *keyfp = NULL;
FILE *infp = stdin; FILE *infp = stdin;
FILE *outfp = stdout; FILE *outfp = stdout;
SM3_XMSS_KEY key; uint8_t *keybuf = NULL;
SM3_XMSS_SIGN_CTX sign_ctx; size_t keylen;
XMSS_KEY key;
XMSS_SIGN_CTX sign_ctx;
uint8_t *sigbuf = NULL; uint8_t *sigbuf = NULL;
size_t siglen; size_t siglen;
@@ -56,10 +60,16 @@ int sm3xmss_sign_main(int argc, char **argv)
} else if (!strcmp(*argv, "-key")) { } else if (!strcmp(*argv, "-key")) {
if (--argc < 1) goto bad; if (--argc < 1) goto bad;
keyfile = *(++argv); keyfile = *(++argv);
/*
if (!(keyfp = fopen(keyfile, "rb"))) { if (!(keyfp = fopen(keyfile, "rb"))) {
fprintf(stderr, "%s: open '%s' failure: %s\n", prog, keyfile, strerror(errno)); fprintf(stderr, "%s: open '%s' failure: %s\n", prog, keyfile, strerror(errno));
goto end; goto end;
} }
*/
if (file_read_all(keyfile, &keybuf, &keylen) != 1) {
error_print();
goto end;
}
} else if (!strcmp(*argv, "-in")) { } else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad; if (--argc < 1) goto bad;
infile = *(++argv); infile = *(++argv);
@@ -91,17 +101,13 @@ bad:
goto end; goto end;
} }
if (sm3_xmss_key_from_bytes(&key, NULL, 0) != 1) {
if (xmss_key_from_bytes(&key, keybuf, keylen) != 1) {
error_print(); error_print();
goto end; goto end;
} }
if (fread(&key, 1, sizeof(key), keyfp) != sizeof(key)) { if (xmss_sign_init(&sign_ctx, &key) != 1) {
fprintf(stderr, "%s: read private key failure\n", prog);
goto end;
}
if (sm3_xmss_sign_init(&sign_ctx, &key) != 1) {
error_print(); error_print();
goto end; goto end;
} }
@@ -112,13 +118,13 @@ bad:
if (len == 0) { if (len == 0) {
break; break;
} }
if (sm3_xmss_sign_update(&sign_ctx, buf, len) != 1) { if (xmss_sign_update(&sign_ctx, buf, len) != 1) {
error_print(); error_print();
goto end; goto end;
} }
} }
if (sm3_xmss_sign_finish(&sign_ctx, &key, NULL, &siglen) != 1) { if (xmss_sign_finish(&sign_ctx, &key, NULL, &siglen) != 1) {
error_print(); error_print();
goto end; goto end;
} }
@@ -128,7 +134,7 @@ bad:
goto end; goto end;
} }
if (sm3_xmss_sign_finish(&sign_ctx, &key, sigbuf, &siglen) != 1) { if (xmss_sign_finish(&sign_ctx, &key, sigbuf, &siglen) != 1) {
error_print(); error_print();
goto end; goto end;
} }
@@ -147,7 +153,11 @@ end:
gmssl_secure_clear(sigbuf, siglen); gmssl_secure_clear(sigbuf, siglen);
free(sigbuf); free(sigbuf);
} }
if (keyfp) fclose(keyfp); if (keybuf) {
gmssl_secure_clear(keybuf, keylen);
free(keybuf);
}
//if (keyfp) fclose(keyfp);
if (infp && infp != stdin) fclose(infp); if (infp && infp != stdin) fclose(infp);
if (outfp && outfp != stdout) fclose(outfp); if (outfp && outfp != stdout) fclose(outfp);
return ret; return ret;

158
tools/xmssverify.c Normal file
View File

@@ -0,0 +1,158 @@
/*
* 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/mem.h>
#include <gmssl/error.h>
#include <gmssl/xmss.h>
static const char *usage = "-pubkey file [-in file] -sig file [-verbose]\n";
static const char *options =
"Options\n"
" -pubkey file Input public key file\n"
" -in file Input data file (if not using stdin)\n"
" -sig file Input signature file\n"
" -verbose Print public key and signature\n"
"\n";
int xmssverify_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *pubkeyfile = NULL;
char *infile = NULL;
char *sigfile = NULL;
int verbose = 0;
FILE *pubkeyfp = NULL;
FILE *infp = stdin;
FILE *sigfp = NULL;
uint8_t pubkeybuf[XMSS_PUBLIC_KEY_SIZE];
size_t pubkeylen = XMSS_PUBLIC_KEY_SIZE;
const uint8_t *cp = pubkeybuf;
uint8_t sig[XMSS_SIGNATURE_MAX_SIZE];
size_t siglen;
XMSS_KEY key;
XMSS_SIGN_CTX ctx;
int vr;
argc--;
argv++;
if (argc < 1) {
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", options);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-pubkey")) {
if (--argc < 1) goto bad;
pubkeyfile = *(++argv);
if (!(pubkeyfp = fopen(pubkeyfile, "rb"))) {
fprintf(stderr, "%s: open '%s' failure: %s\n", prog, pubkeyfile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "rb"))) {
fprintf(stderr, "%s: open '%s' failure: %s\n", prog, infile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-sig")) {
if (--argc < 1) goto bad;
sigfile = *(++argv);
if (!(sigfp = fopen(sigfile, "rb"))) {
fprintf(stderr, "%s: open '%s' failure: %s\n", prog, sigfile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-verbose")) {
verbose = 1;
} else {
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
goto end;
bad:
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
goto end;
}
argc--;
argv++;
}
if (!pubkeyfile) {
fprintf(stderr, "%s: `-key` option required\n", prog);
goto end;
}
if (!sigfile) {
fprintf(stderr, "%s: `-sig` option required\n", prog);
goto end;
}
if (fread(pubkeybuf, 1, pubkeylen, pubkeyfp) != pubkeylen) {
fprintf(stderr, "%s: read public key failure\n", prog);
goto end;
}
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);
}
// read signature even if signature not compatible with the public key
if ((siglen = fread(sig, 1, XMSS_SIGNATURE_MAX_SIZE, sigfp)) <= 0) {
fprintf(stderr, "%s: read signature failure\n", prog);
goto end;
}
if (verbose) {
xmss_signature_print(stderr, 0, 0, "xmss_signature", sig, siglen);
}
if (xmss_verify_init(&ctx, &key, sig, siglen) != 1) {
error_print();
goto end;
}
while (1) {
uint8_t buf[1024];
size_t len = fread(buf, 1, sizeof(buf), infp);
if (len == 0) {
break;
}
if (xmss_verify_update(&ctx, buf, len) != 1) {
error_print();
goto end;
}
}
if ((vr = xmss_verify_finish(&ctx, &key, sig, siglen)) < 0) {
error_print();
goto end;
}
fprintf(stdout, "verify : %s\n", vr == 1 ? "success" : "failure");
if (vr == 1) {
ret = 0;
}
end:
if (pubkeyfp) fclose(pubkeyfp);
if (infp && infp != stdin) fclose(infp);
if (sigfp) fclose(sigfp);
return ret;
}