mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Add SM3 LMS/HSS hash-based post-quantum signatures
This commit is contained in:
@@ -53,7 +53,8 @@ option(ENABLE_SM4_XTS "Enable SM4 XTS mode" ON)
|
|||||||
option(ENABLE_SM4_CBC_MAC "Enable SM4-CBC-MAC" ON)
|
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_SM3_XMSS "Enable SM3-XMSS signature" ON)
|
option(ENABLE_SM3_LMS "Enable SM3-LMS signature" ON)
|
||||||
|
option(ENABLE_SM3_XMSS "Enable SM3-XMSS signature" OFF)
|
||||||
|
|
||||||
|
|
||||||
option(ENABLE_SHA1 "Enable SHA1" ON)
|
option(ENABLE_SHA1 "Enable SHA1" ON)
|
||||||
@@ -141,7 +142,6 @@ set(tools
|
|||||||
tools/sm3.c
|
tools/sm3.c
|
||||||
tools/sm3hmac.c
|
tools/sm3hmac.c
|
||||||
tools/sm3_pbkdf2.c
|
tools/sm3_pbkdf2.c
|
||||||
tools/sm3xmss_keygen.c
|
|
||||||
tools/sm2keygen.c
|
tools/sm2keygen.c
|
||||||
tools/sm2sign.c
|
tools/sm2sign.c
|
||||||
tools/sm2verify.c
|
tools/sm2verify.c
|
||||||
@@ -416,8 +416,25 @@ if (ENABLE_SM2_EXTS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if (ENABLE_SM3_LMS)
|
||||||
|
message(STATUS "ENABLE_SM3_LMS is ON")
|
||||||
|
add_definitions(-DENABLE_SM3_LMS)
|
||||||
|
list(APPEND src src/sm3_lms.c)
|
||||||
|
list(APPEND tools tools/sm3lmskeygen.c tools/sm3lmssign.c tools/sm3lmsverify.c)
|
||||||
|
list(APPEND tools tools/sm3hsskeygen.c tools/sm3hsssign.c tools/sm3hssverify.c)
|
||||||
|
list(APPEND tests sm3_lms)
|
||||||
|
|
||||||
|
option(ENABLE_SM3_LMS_CROSSCHECK "Enable LMS SHA-256 cross-check" OFF)
|
||||||
|
if (ENABLE_SM3_LMS_CROSSCHECK)
|
||||||
|
message(STATUS "ENABLE_SM3_LMS_CROSSCHECK is ON")
|
||||||
|
add_definitions(-DENABLE_SM3_LMS_CROSSCHECK)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if (ENABLE_SM3_XMSS)
|
if (ENABLE_SM3_XMSS)
|
||||||
message(STATUS "ENABLE_SM3_XMSS is ON")
|
message(STATUS "ENABLE_SM3_XMSS is ON")
|
||||||
|
add_definitions(-DENABLE_SM3_XMSS)
|
||||||
list(APPEND src src/sm3_xmss.c)
|
list(APPEND src src/sm3_xmss.c)
|
||||||
|
|
||||||
option(ENABLE_SM3_XMSS_CROSSCHECK "Enable XMSS SHA-256 cross-check" OFF)
|
option(ENABLE_SM3_XMSS_CROSSCHECK "Enable XMSS SHA-256 cross-check" OFF)
|
||||||
@@ -644,7 +661,7 @@ endif()
|
|||||||
#
|
#
|
||||||
set(CPACK_PACKAGE_NAME "GmSSL")
|
set(CPACK_PACKAGE_NAME "GmSSL")
|
||||||
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
||||||
set(CPACK_PACKAGE_VERSION "3.1.2-Dev")
|
set(CPACK_PACKAGE_VERSION "3.1.3-Dev")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
||||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|||||||
299
include/gmssl/sm3_lms.h
Normal file
299
include/gmssl/sm3_lms.h
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
* 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_SM3_LMS_H
|
||||||
|
#define GMSSL_SM3_LMS_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.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
|
||||||
|
|
||||||
|
|
||||||
|
typedef uint8_t hash256_t[32];
|
||||||
|
|
||||||
|
|
||||||
|
#define SM3_HSS_MAX_LEVELS 5
|
||||||
|
#define SM3_LMS_MAX_HEIGHT 25
|
||||||
|
|
||||||
|
|
||||||
|
// Crosscheck with data from LMS-reference (SHA-256), except the LMS signature.
|
||||||
|
#if defined(ENABLE_SM3_LMS_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 LMOTS_HASH256_N32_W8 LMOTS_SHA256_N32_W8
|
||||||
|
# define LMOTS_HASH256_N32_W8_NAME "LMOTS_SHA256_N32_W8"
|
||||||
|
# define LMS_HASH256_M32_H5 LMS_SHA256_M32_H5
|
||||||
|
# define LMS_HASH256_M32_H10 LMS_SHA256_M32_H10
|
||||||
|
# define LMS_HASH256_M32_H15 LMS_SHA256_M32_H15
|
||||||
|
# define LMS_HASH256_M32_H20 LMS_SHA256_M32_H20
|
||||||
|
# define LMS_HASH256_M32_H25 LMS_SHA256_M32_H25
|
||||||
|
# define LMS_HASH256_M32_H5_NAME "LMS_SHA256_M32_H5"
|
||||||
|
# define LMS_HASH256_M32_H10_NAME "LMS_SHA256_M32_H10"
|
||||||
|
# define LMS_HASH256_M32_H15_NAME "LMS_SHA256_M32_H15"
|
||||||
|
# define LMS_HASH256_M32_H20_NAME "LMS_SHA256_M32_H20"
|
||||||
|
# define LMS_HASH256_M32_H25_NAME "LMS_SHA256_M32_H25"
|
||||||
|
#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 LMOTS_HASH256_N32_W8 LMOTS_SM3_N32_W8
|
||||||
|
# define LMOTS_HASH256_N32_W8_NAME "LMOTS_SM3_N32_W8"
|
||||||
|
# define LMS_HASH256_M32_H5 LMS_SM3_M32_H5
|
||||||
|
# define LMS_HASH256_M32_H10 LMS_SM3_M32_H10
|
||||||
|
# define LMS_HASH256_M32_H15 LMS_SM3_M32_H15
|
||||||
|
# define LMS_HASH256_M32_H20 LMS_SM3_M32_H20
|
||||||
|
# define LMS_HASH256_M32_H25 LMS_SM3_M32_H25
|
||||||
|
# define LMS_HASH256_M32_H5_NAME "LMS_SM3_M32_H5"
|
||||||
|
# define LMS_HASH256_M32_H10_NAME "LMS_SM3_M32_H10"
|
||||||
|
# define LMS_HASH256_M32_H15_NAME "LMS_SM3_M32_H15"
|
||||||
|
# define LMS_HASH256_M32_H20_NAME "LMS_SM3_M32_H20"
|
||||||
|
# define LMS_HASH256_M32_H25_NAME "LMS_SM3_M32_H25"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LMOTS_RESERVED = 0,
|
||||||
|
LMOTS_SHA256_N32_W1 = 1,
|
||||||
|
LMOTS_SHA256_N32_W2 = 2,
|
||||||
|
LMOTS_SHA256_N32_W4 = 3,
|
||||||
|
LMOTS_SHA256_N32_W8 = 4,
|
||||||
|
LMOTS_SM3_N32_W1 = 11,
|
||||||
|
LMOTS_SM3_N32_W2 = 12,
|
||||||
|
LMOTS_SM3_N32_W4 = 13,
|
||||||
|
LMOTS_SM3_N32_W8 = 14,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
#if defined(ENABLE_SM3_LMS_CROSSCHECK) && defined(ENABLE_SHA2)
|
||||||
|
LMS_SHA256_M32_H5 = 5,
|
||||||
|
LMS_SHA256_M32_H10 = 6,
|
||||||
|
LMS_SHA256_M32_H15 = 7,
|
||||||
|
LMS_SHA256_M32_H20 = 8,
|
||||||
|
LMS_SHA256_M32_H25 = 9,
|
||||||
|
#else
|
||||||
|
// TODO: submit to IETF
|
||||||
|
LMS_SM3_M32_H5 = 5,
|
||||||
|
LMS_SM3_M32_H10 = 6,
|
||||||
|
LMS_SM3_M32_H15 = 7,
|
||||||
|
LMS_SM3_M32_H20 = 8,
|
||||||
|
LMS_SM3_M32_H25 = 9,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
char *sm3_lmots_type_name(int lmots_type);
|
||||||
|
void sm3_lmots_derive_secrets(const hash256_t seed, const uint8_t I[16], int q, hash256_t x[34]);
|
||||||
|
void sm3_lmots_secrets_to_public_hash(const uint8_t I[16], int q, const hash256_t x[34], hash256_t pub);
|
||||||
|
void sm3_lmots_compute_signature(const uint8_t I[16], int q, const hash256_t dgst, const hash256_t x[34], hash256_t y[34]);
|
||||||
|
void sm3_lmots_signature_to_public_hash(const uint8_t I[16], int q, const hash256_t y[34], const hash256_t dgst, hash256_t pub);
|
||||||
|
|
||||||
|
|
||||||
|
char *sm3_lms_type_name(int lms_type);
|
||||||
|
int sm3_lms_type_from_name(const char *name);
|
||||||
|
int sm3_lms_type_to_height(int type, size_t *height);
|
||||||
|
void sm3_lms_derive_merkle_tree(const hash256_t seed, const uint8_t I[16], int height, hash256_t *tree);
|
||||||
|
void sm3_lms_derive_merkle_root(const hash256_t seed, const uint8_t I[16], int height, hash256_t root);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int lms_type;
|
||||||
|
int lmots_type;
|
||||||
|
uint8_t I[16]; // lms key identifier
|
||||||
|
hash256_t root; // merkle tree root
|
||||||
|
} SM3_LMS_PUBLIC_KEY;
|
||||||
|
|
||||||
|
#define SM3_LMS_PUBLIC_KEY_SIZE (4 + 4 + 16 + 32) // = 56 bytes
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SM3_LMS_PUBLIC_KEY public_key;
|
||||||
|
hash256_t *tree;
|
||||||
|
hash256_t seed;
|
||||||
|
uint32_t q; // in [0, 2^h - 1], q++ after every sign
|
||||||
|
} SM3_LMS_KEY;
|
||||||
|
|
||||||
|
#define SM3_LMS_PRIVATE_KEY_SIZE (SM3_LMS_PUBLIC_KEY_SIZE + 32 + 4) // = 92 bytes
|
||||||
|
|
||||||
|
// FIXME: do we need a function to update lms_key->q ?
|
||||||
|
|
||||||
|
int sm3_lms_key_generate_ex(SM3_LMS_KEY *key, int lms_type, const hash256_t seed, const uint8_t I[16], int cache_tree);
|
||||||
|
int sm3_lms_key_generate(SM3_LMS_KEY *key, int lms_type);
|
||||||
|
int sm3_lms_key_check(const SM3_LMS_KEY *key, const SM3_LMS_PUBLIC_KEY *pub);
|
||||||
|
int sm3_lms_key_remaining_signs(const SM3_LMS_KEY *key, size_t *count);
|
||||||
|
int sm3_lms_public_key_to_bytes(const SM3_LMS_KEY *key, uint8_t **out, size_t *outlen);
|
||||||
|
int sm3_lms_public_key_from_bytes_ex(const SM3_LMS_PUBLIC_KEY **key, const uint8_t **in, size_t *inlen);
|
||||||
|
int sm3_lms_public_key_from_bytes(SM3_LMS_KEY *key, const uint8_t **in, size_t *inlen);
|
||||||
|
int sm3_lms_private_key_to_bytes(const SM3_LMS_KEY *key, uint8_t **out, size_t *outlen);
|
||||||
|
int sm3_lms_private_key_from_bytes(SM3_LMS_KEY *key, const uint8_t **in, size_t *inlen);
|
||||||
|
int sm3_lms_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM3_LMS_PUBLIC_KEY *pub);
|
||||||
|
int sm3_lms_key_print(FILE *fp, int fmt, int ind, const char *label, const SM3_LMS_KEY *key);
|
||||||
|
void sm3_lms_key_cleanup(SM3_LMS_KEY *key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int q; // index of LMS tree leaf, in [0, 2^h - 1]
|
||||||
|
struct {
|
||||||
|
int lmots_type; // LMOTS_SM3_N32_W8 or LMOTS_SHA256_N32_W8 in compile time
|
||||||
|
hash256_t C; // randomness of every LMOTS signature
|
||||||
|
hash256_t y[34]; // for w = 8 and hash256, 34 winternitz chains
|
||||||
|
} lmots_sig;
|
||||||
|
int lms_type;
|
||||||
|
hash256_t path[25]; // max tree height = 25 when LMS_SM3_M32_H25
|
||||||
|
} SM3_LMS_SIGNATURE;
|
||||||
|
|
||||||
|
// encoded size, SHOULD be changed when supporting text/der encoding
|
||||||
|
#define SM3_LMS_SIGNATURE_MIN_SIZE (4 + 4 + 32 + 32*34 + 4 + 32*5) // = 1292 bytes
|
||||||
|
#define SM3_LMS_SIGNATURE_MAX_SIZE (4 + 4 + 32 + 32*34 + 4 + 32*25) // = 1932 bytes
|
||||||
|
|
||||||
|
|
||||||
|
int sm3_lms_signature_to_merkle_root(const uint8_t I[16], size_t h, int q,
|
||||||
|
const hash256_t y[34], const hash256_t *path,
|
||||||
|
const hash256_t dgst, hash256_t root);
|
||||||
|
|
||||||
|
int sm3_lms_key_get_signature_size(const SM3_LMS_KEY *key, size_t *siglen);
|
||||||
|
int sm3_lms_signature_size(int lms_type, size_t *siglen);
|
||||||
|
|
||||||
|
int sm3_lms_signature_to_bytes(const SM3_LMS_SIGNATURE *sig, uint8_t **out, size_t *outlen);
|
||||||
|
int sm3_lms_signature_from_bytes_ex(const SM3_LMS_SIGNATURE **sig, size_t *siglen, const uint8_t **in, size_t *inlen);
|
||||||
|
int sm3_lms_signature_from_bytes(SM3_LMS_SIGNATURE *sig, const uint8_t **in, size_t *inlen);
|
||||||
|
int sm3_lms_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const SM3_LMS_SIGNATURE *sig);
|
||||||
|
int sm3_lms_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HASH256_CTX hash256_ctx;
|
||||||
|
SM3_LMS_PUBLIC_KEY lms_public_key; // FIXME: or use LMS_PUBLIC_KEY to re-use tree?
|
||||||
|
SM3_LMS_SIGNATURE lms_sig;
|
||||||
|
} SM3_LMS_SIGN_CTX;
|
||||||
|
|
||||||
|
int sm3_lms_sign_init(SM3_LMS_SIGN_CTX *ctx, SM3_LMS_KEY *key);
|
||||||
|
int sm3_lms_sign_update(SM3_LMS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||||
|
int sm3_lms_sign_finish(SM3_LMS_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen);
|
||||||
|
int sm3_lms_sign_finish_ex(SM3_LMS_SIGN_CTX *ctx, SM3_LMS_SIGNATURE *sig);
|
||||||
|
int sm3_lms_verify_init_ex(SM3_LMS_SIGN_CTX *ctx, const SM3_LMS_KEY *key, const SM3_LMS_SIGNATURE *sig);
|
||||||
|
int sm3_lms_verify_init(SM3_LMS_SIGN_CTX *ctx, const SM3_LMS_KEY *key, const uint8_t *sigbuf, size_t siglen);
|
||||||
|
int sm3_lms_verify_update(SM3_LMS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||||
|
int sm3_lms_verify_finish(SM3_LMS_SIGN_CTX *ctx);
|
||||||
|
|
||||||
|
// `sm3_lms_sign_init` copy lmots private to ctx->lms_sig.y
|
||||||
|
// call `sm3_lms_sign_ctx_cleanup` incase `sm3_lms_sign_finish` not called nor finished
|
||||||
|
void sm3_lms_sign_ctx_cleanup(SM3_LMS_SIGN_CTX *ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// just for reference, HSS_PUBLIC_KEY memory layout might not compatible with HSS_KEY
|
||||||
|
typedef struct {
|
||||||
|
uint32_t levels;
|
||||||
|
SM3_LMS_PUBLIC_KEY lms_public_key;
|
||||||
|
} SM3_HSS_PUBLIC_KEY;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// SM3_HSS_PUBLIC_KEY: { level, lms_key[0].public_key }
|
||||||
|
#define SM3_HSS_PUBLIC_KEY_SIZE (4 + SM3_LMS_PUBLIC_KEY_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: LMS_KEY should be a tree other than a vector
|
||||||
|
// when updated, low level lms keys will lost, maybe a good feature
|
||||||
|
typedef struct {
|
||||||
|
uint32_t levels; // should be checked to prevent memory error
|
||||||
|
SM3_LMS_KEY lms_key[5];
|
||||||
|
SM3_LMS_SIGNATURE lms_sig[4];
|
||||||
|
} SM3_HSS_KEY;
|
||||||
|
|
||||||
|
|
||||||
|
#define SM3_HSS_PRIVATE_KEY_MAX_SIZE sizeof(SM3_HSS_KEY)
|
||||||
|
int sm3_hss_private_key_size(const int *lms_types, size_t levels, size_t *len);
|
||||||
|
|
||||||
|
int sm3_hss_key_generate(SM3_HSS_KEY *key, const int *lms_types, size_t levels);
|
||||||
|
int sm3_hss_key_update(SM3_HSS_KEY *key);
|
||||||
|
|
||||||
|
int sm3_hss_public_key_to_bytes(const SM3_HSS_KEY *key, uint8_t **out, size_t *outlen);
|
||||||
|
int sm3_hss_private_key_to_bytes(const SM3_HSS_KEY *key, uint8_t **out, size_t *outlen);
|
||||||
|
int sm3_hss_public_key_from_bytes(SM3_HSS_KEY *key, const uint8_t **in, size_t *inlen);
|
||||||
|
int sm3_hss_private_key_from_bytes(SM3_HSS_KEY *key, const uint8_t **in, size_t *inlen);
|
||||||
|
int sm3_hss_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM3_HSS_KEY *key);
|
||||||
|
int sm3_hss_key_print(FILE *fp, int fmt, int ind, const char *label, const SM3_HSS_KEY *key);
|
||||||
|
void sm3_hss_key_cleanup(SM3_HSS_KEY *key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t num_signed_public_keys; // = hss_key->levels - 1
|
||||||
|
struct {
|
||||||
|
SM3_LMS_SIGNATURE lms_sig; // lms_sig[i] = sign(hss_key->lms_key[i], lms_public_key[i])
|
||||||
|
SM3_LMS_PUBLIC_KEY lms_public_key; // signed_public_keys[i] = hss_key->lms_key[i+1].public_key
|
||||||
|
} signed_public_keys[SM3_HSS_MAX_LEVELS - 1];
|
||||||
|
SM3_LMS_SIGNATURE msg_lms_sig; // = sign(hss->lms_key[levels-1], msg)
|
||||||
|
} SM3_HSS_SIGNATURE;
|
||||||
|
|
||||||
|
|
||||||
|
#define SM3_HSS_SIGNATURE_MAX_SIZE sizeof(SM3_HSS_SIGNATURE)
|
||||||
|
int sm3_hss_signature_size(const int *lms_types, size_t levels, size_t *len);
|
||||||
|
int sm3_hss_key_get_signature_size(const SM3_HSS_KEY *key, size_t *siglen);
|
||||||
|
|
||||||
|
int sm3_hss_signature_to_bytes(const SM3_HSS_SIGNATURE *sig, uint8_t **out, size_t *outlen);
|
||||||
|
int sm3_hss_signature_from_bytes(SM3_HSS_SIGNATURE *sig, const uint8_t **in, size_t *inlen);
|
||||||
|
int sm3_hss_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const SM3_HSS_SIGNATURE *sig);
|
||||||
|
int sm3_hss_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SM3_LMS_SIGN_CTX lms_ctx;
|
||||||
|
uint32_t levels;
|
||||||
|
SM3_LMS_SIGNATURE lms_sigs[SM3_HSS_MAX_LEVELS - 1];
|
||||||
|
SM3_LMS_PUBLIC_KEY lms_public_keys[SM3_HSS_MAX_LEVELS - 1];
|
||||||
|
} SM3_HSS_SIGN_CTX;
|
||||||
|
|
||||||
|
|
||||||
|
int sm3_hss_sign_init(SM3_HSS_SIGN_CTX *ctx, SM3_HSS_KEY *key);
|
||||||
|
int sm3_hss_sign_update(SM3_HSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||||
|
int sm3_hss_sign_finish(SM3_HSS_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen);
|
||||||
|
int sm3_hss_sign_finish_ex(SM3_HSS_SIGN_CTX *ctx, SM3_HSS_SIGNATURE *sig);
|
||||||
|
int sm3_hss_verify_init_ex(SM3_HSS_SIGN_CTX *ctx, const SM3_HSS_KEY *key, const SM3_HSS_SIGNATURE *sig);
|
||||||
|
int sm3_hss_verify_init(SM3_HSS_SIGN_CTX *ctx, const SM3_HSS_KEY *key, const uint8_t *sigbuf, size_t siglen);
|
||||||
|
int sm3_hss_verify_update(SM3_HSS_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||||
|
int sm3_hss_verify_finish(SM3_HSS_SIGN_CTX *ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
from RFC 9708
|
||||||
|
|
||||||
|
id-alg-hss-lms-hashsig OBJECT IDENTIFIER ::= {
|
||||||
|
iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
|
||||||
|
pkcs-9(9) smime(16) alg(3) 17
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#include <gmssl/oid.h>
|
||||||
|
|
||||||
|
#define oid_hss_lms_hashsig oid_pkcs,9,16,3,17
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -18,8 +18,8 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
// Also update CPACK_PACKAGE_VERSION in CMakeLists.txt
|
// Also update CPACK_PACKAGE_VERSION in CMakeLists.txt
|
||||||
#define GMSSL_VERSION_NUM 30102
|
#define GMSSL_VERSION_NUM 30103
|
||||||
#define GMSSL_VERSION_STR "GmSSL 3.1.2 Dev"
|
#define GMSSL_VERSION_STR "GmSSL 3.1.3 Dev"
|
||||||
|
|
||||||
int gmssl_version_num(void);
|
int gmssl_version_num(void);
|
||||||
const char *gmssl_version_str(void);
|
const char *gmssl_version_str(void);
|
||||||
|
|||||||
1892
src/sm3_lms.c
1892
src/sm3_lms.c
File diff suppressed because it is too large
Load Diff
903
tests/sm3_lmstest.c
Normal file
903
tests/sm3_lmstest.c
Normal file
@@ -0,0 +1,903 @@
|
|||||||
|
/*
|
||||||
|
* 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 <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gmssl/hex.h>
|
||||||
|
#include <gmssl/rand.h>
|
||||||
|
#include <gmssl/error.h>
|
||||||
|
#include <gmssl/sm3_lms.h>
|
||||||
|
|
||||||
|
|
||||||
|
static int lms_types[] = {
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(ENABLE_SM3_LMS_CROSSCHECK) && defined(ENABLE_SHA2)
|
||||||
|
static int test_rfc8554_test1(void)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
// HSS Public key
|
||||||
|
int levels = 2;
|
||||||
|
int lms_type = LMS_SHA256_M32_H5;
|
||||||
|
int lmots_type = LMOTS_SHA256_N32_W8;
|
||||||
|
char *I = "61a5d57d37f5e46bfb7520806b07a1b8";
|
||||||
|
char *K = "50650e3b31fe4a773ea29a07f09cf2ea30e579f0df58ef8e298da0434cb2b878";
|
||||||
|
|
||||||
|
// Message
|
||||||
|
char *msg =
|
||||||
|
"54686520706f77657273206e6f742064656c65676174656420746f2074686520"
|
||||||
|
"556e69746564205374617465732062792074686520436f6e737469747574696f"
|
||||||
|
"6e2c206e6f722070726f6869626974656420627920697420746f207468652053"
|
||||||
|
"74617465732c2061726520726573657276656420746f20746865205374617465"
|
||||||
|
"7320726573706563746976656c792c206f7220746f207468652070656f706c65"
|
||||||
|
"2e0a"; // MUST NOT use strlen(msg), which will not count the last 0x0a
|
||||||
|
|
||||||
|
// Signature
|
||||||
|
int Nspk = 1;
|
||||||
|
|
||||||
|
int sig0_q = 5;
|
||||||
|
int sig0_lmots_type = LMOTS_SHA256_N32_W8;
|
||||||
|
char *sig0_C =
|
||||||
|
"d32b56671d7eb98833c49b433c272586"
|
||||||
|
"bc4a1c8a8970528ffa04b966f9426eb9";
|
||||||
|
char *sig0_y[34] = {
|
||||||
|
"965a25bfd37f196b9073f3d4a232feb69128ec45146f86292f9dff9610a7bf95",
|
||||||
|
"a64c7f60f6261a62043f86c70324b7707f5b4a8a6e19c114c7be866d488778a0",
|
||||||
|
"e05fd5c6509a6e61d559cf1a77a970de927d60c70d3de31a7fa0100994e162a2",
|
||||||
|
"582e8ff1b10cd99d4e8e413ef469559f7d7ed12c838342f9b9c96b83a4943d16",
|
||||||
|
"81d84b15357ff48ca579f19f5e71f18466f2bbef4bf660c2518eb20de2f66e3b",
|
||||||
|
"14784269d7d876f5d35d3fbfc7039a462c716bb9f6891a7f41ad133e9e1f6d95",
|
||||||
|
"60b960e7777c52f060492f2d7c660e1471e07e72655562035abc9a701b473ecb",
|
||||||
|
"c3943c6b9c4f2405a3cb8bf8a691ca51d3f6ad2f428bab6f3a30f55dd9625563",
|
||||||
|
"f0a75ee390e385e3ae0b906961ecf41ae073a0590c2eb6204f44831c26dd768c",
|
||||||
|
"35b167b28ce8dc988a3748255230cef99ebf14e730632f27414489808afab1d1",
|
||||||
|
"e783ed04516de012498682212b07810579b250365941bcc98142da13609e9768",
|
||||||
|
"aaf65de7620dabec29eb82a17fde35af15ad238c73f81bdb8dec2fc0e7f93270",
|
||||||
|
"1099762b37f43c4a3c20010a3d72e2f606be108d310e639f09ce7286800d9ef8",
|
||||||
|
"a1a40281cc5a7ea98d2adc7c7400c2fe5a101552df4e3cccfd0cbf2ddf5dc677",
|
||||||
|
"9cbbc68fee0c3efe4ec22b83a2caa3e48e0809a0a750b73ccdcf3c79e6580c15",
|
||||||
|
"4f8a58f7f24335eec5c5eb5e0cf01dcf4439424095fceb077f66ded5bec73b27",
|
||||||
|
"c5b9f64a2a9af2f07c05e99e5cf80f00252e39db32f6c19674f190c9fbc506d8",
|
||||||
|
"26857713afd2ca6bb85cd8c107347552f30575a5417816ab4db3f603f2df56fb",
|
||||||
|
"c413e7d0acd8bdd81352b2471fc1bc4f1ef296fea1220403466b1afe78b94f7e",
|
||||||
|
"cf7cc62fb92be14f18c2192384ebceaf8801afdf947f698ce9c6ceb696ed70e9",
|
||||||
|
"e87b0144417e8d7baf25eb5f70f09f016fc925b4db048ab8d8cb2a661ce3b57a",
|
||||||
|
"da67571f5dd546fc22cb1f97e0ebd1a65926b1234fd04f171cf469c76b884cf3",
|
||||||
|
"115cce6f792cc84e36da58960c5f1d760f32c12faef477e94c92eb75625b6a37",
|
||||||
|
"1efc72d60ca5e908b3a7dd69fef0249150e3eebdfed39cbdc3ce9704882a2072",
|
||||||
|
"c75e13527b7a581a556168783dc1e97545e31865ddc46b3c957835da252bb732",
|
||||||
|
"8d3ee2062445dfb85ef8c35f8e1f3371af34023cef626e0af1e0bc017351aae2",
|
||||||
|
"ab8f5c612ead0b729a1d059d02bfe18efa971b7300e882360a93b025ff97e9e0",
|
||||||
|
"eec0f3f3f13039a17f88b0cf808f488431606cb13f9241f40f44e537d302c64a",
|
||||||
|
"4f1f4ab949b9feefadcb71ab50ef27d6d6ca8510f150c85fb525bf25703df720",
|
||||||
|
"9b6066f09c37280d59128d2f0f637c7d7d7fad4ed1c1ea04e628d221e3d8db77",
|
||||||
|
"b7c878c9411cafc5071a34a00f4cf07738912753dfce48f07576f0d4f94f42c6",
|
||||||
|
"d76f7ce973e9367095ba7e9a3649b7f461d9f9ac1332a4d1044c96aefee67676",
|
||||||
|
"401b64457c54d65fef6500c59cdfb69af7b6dddfcb0f086278dd8ad0686078df",
|
||||||
|
"b0f3f79cd893d314168648499898fbc0ced5f95b74e8ff14d735cdea968bee74",
|
||||||
|
};
|
||||||
|
int sig0_lms_type = LMS_SHA256_M32_H5;
|
||||||
|
char *sig0_path[5] = {
|
||||||
|
"d8b8112f9200a5e50c4a262165bd342cd800b8496810bc716277435ac376728d",
|
||||||
|
"129ac6eda839a6f357b5a04387c5ce97382a78f2a4372917eefcbf93f63bb591",
|
||||||
|
"12f5dbe400bd49e4501e859f885bf0736e90a509b30a26bfac8c17b5991c157e",
|
||||||
|
"b5971115aa39efd8d564a6b90282c3168af2d30ef89d51bf14654510a12b8a14",
|
||||||
|
"4cca1848cf7da59cc2b3d9d0692dd2a20ba3863480e25b1b85ee860c62bf5136",
|
||||||
|
};
|
||||||
|
|
||||||
|
int pub0_lms_type = LMS_SHA256_M32_H5;
|
||||||
|
int pub0_lmots_type = LMOTS_SHA256_N32_W8;
|
||||||
|
char *pub0_I = "d2f14ff6346af964569f7d6cb880a1b6";
|
||||||
|
char *pub0_K = "6c5004917da6eafe4d9ef6c6407b3db0e5485b122d9ebe15cda93cfec582d7ab";
|
||||||
|
|
||||||
|
int sig1_q = 0x0a;
|
||||||
|
int sig1_lmots_type = LMOTS_SHA256_N32_W8;
|
||||||
|
char *sig1_C = "0703c491e7558b35011ece3592eaa5da4d918786771233e8353bc4f62323185c";
|
||||||
|
char *sig1_y[34] = {
|
||||||
|
"95cae05b899e35dffd717054706209988ebfdf6e37960bb5c38d7657e8bffeef",
|
||||||
|
"9bc042da4b4525650485c66d0ce19b317587c6ba4bffcc428e25d08931e72dfb",
|
||||||
|
"6a120c5612344258b85efdb7db1db9e1865a73caf96557eb39ed3e3f426933ac",
|
||||||
|
"9eeddb03a1d2374af7bf77185577456237f9de2d60113c23f846df26fa942008",
|
||||||
|
"a698994c0827d90e86d43e0df7f4bfcdb09b86a373b98288b7094ad81a0185ac",
|
||||||
|
"100e4f2c5fc38c003c1ab6fea479eb2f5ebe48f584d7159b8ada03586e65ad9c",
|
||||||
|
"969f6aecbfe44cf356888a7b15a3ff074f771760b26f9c04884ee1faa329fbf4",
|
||||||
|
"e61af23aee7fa5d4d9a5dfcf43c4c26ce8aea2ce8a2990d7ba7b57108b47dabf",
|
||||||
|
"beadb2b25b3cacc1ac0cef346cbb90fb044beee4fac2603a442bdf7e507243b7",
|
||||||
|
"319c9944b1586e899d431c7f91bcccc8690dbf59b28386b2315f3d36ef2eaa3c",
|
||||||
|
"f30b2b51f48b71b003dfb08249484201043f65f5a3ef6bbd61ddfee81aca9ce6",
|
||||||
|
"0081262a00000480dcbc9a3da6fbef5c1c0a55e48a0e729f9184fcb1407c3152",
|
||||||
|
"9db268f6fe50032a363c9801306837fafabdf957fd97eafc80dbd165e435d0e2",
|
||||||
|
"dfd836a28b354023924b6fb7e48bc0b3ed95eea64c2d402f4d734c8dc26f3ac5",
|
||||||
|
"91825daef01eae3c38e3328d00a77dc657034f287ccb0f0e1c9a7cbdc828f627",
|
||||||
|
"205e4737b84b58376551d44c12c3c215c812a0970789c83de51d6ad787271963",
|
||||||
|
"327f0a5fbb6b5907dec02c9a90934af5a1c63b72c82653605d1dcce51596b3c2",
|
||||||
|
"b45696689f2eb382007497557692caac4d57b5de9f5569bc2ad0137fd47fb47e",
|
||||||
|
"664fcb6db4971f5b3e07aceda9ac130e9f38182de994cff192ec0e82fd6d4cb7",
|
||||||
|
"f3fe00812589b7a7ce515440456433016b84a59bec6619a1c6c0b37dd1450ed4",
|
||||||
|
"f2d8b584410ceda8025f5d2d8dd0d2176fc1cf2cc06fa8c82bed4d944e71339e",
|
||||||
|
"ce780fd025bd41ec34ebff9d4270a3224e019fcb444474d482fd2dbe75efb203",
|
||||||
|
"89cc10cd600abb54c47ede93e08c114edb04117d714dc1d525e11bed8756192f",
|
||||||
|
"929d15462b939ff3f52f2252da2ed64d8fae88818b1efa2c7b08c8794fb1b214",
|
||||||
|
"aa233db3162833141ea4383f1a6f120be1db82ce3630b3429114463157a64e91",
|
||||||
|
"234d475e2f79cbf05e4db6a9407d72c6bff7d1198b5c4d6aad2831db61274993",
|
||||||
|
"715a0182c7dc8089e32c8531deed4f7431c07c02195eba2ef91efb5613c37af7",
|
||||||
|
"ae0c066babc69369700e1dd26eddc0d216c781d56e4ce47e3303fa73007ff7b9",
|
||||||
|
"49ef23be2aa4dbf25206fe45c20dd888395b2526391a724996a44156beac8082",
|
||||||
|
"12858792bf8e74cba49dee5e8812e019da87454bff9e847ed83db07af3137430",
|
||||||
|
"82f880a278f682c2bd0ad6887cb59f652e155987d61bbf6a88d36ee93b6072e6",
|
||||||
|
"656d9ccbaae3d655852e38deb3a2dcf8058dc9fb6f2ab3d3b3539eb77b248a66",
|
||||||
|
"1091d05eb6e2f297774fe6053598457cc61908318de4b826f0fc86d4bb117d33",
|
||||||
|
"e865aa805009cc2918d9c2f840c4da43a703ad9f5b5806163d7161696b5a0adc",
|
||||||
|
};
|
||||||
|
int sig1_lms_type = LMS_SHA256_M32_H5;
|
||||||
|
char *sig1_path[5] = {
|
||||||
|
"d5c0d1bebb06048ed6fe2ef2c6cef305b3ed633941ebc8b3bec9738754cddd60",
|
||||||
|
"e1920ada52f43d055b5031cee6192520d6a5115514851ce7fd448d4a39fae2ab",
|
||||||
|
"2335b525f484e9b40d6a4a969394843bdcf6d14c48e8015e08ab92662c05c6e9",
|
||||||
|
"f90b65a7a6201689999f32bfd368e5e3ec9cb70ac7b8399003f175c40885081a",
|
||||||
|
"09ab3034911fe125631051df0408b3946b0bde790911e8978ba07dd56c73e7ee",
|
||||||
|
};
|
||||||
|
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
SM3_HSS_SIGNATURE sig;
|
||||||
|
SM3_LMS_SIGNATURE *lms_sig;
|
||||||
|
SM3_LMS_PUBLIC_KEY *lms_pub;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
// hss public key
|
||||||
|
memset(&key, 0, sizeof(key));
|
||||||
|
key.levels = levels;
|
||||||
|
lms_pub = &key.lms_key[0].public_key;
|
||||||
|
lms_pub->lms_type = lms_type;
|
||||||
|
lms_pub->lmots_type = lmots_type;
|
||||||
|
hex_to_bytes(I, strlen(I), lms_pub->I, &len);
|
||||||
|
hex_to_bytes(K, strlen(K), lms_pub->root, &len);
|
||||||
|
|
||||||
|
// hss signature
|
||||||
|
memset(&sig, 0, sizeof(sig));
|
||||||
|
sig.num_signed_public_keys = Nspk;
|
||||||
|
|
||||||
|
// sig[0]
|
||||||
|
lms_sig = &sig.signed_public_keys[0].lms_sig;
|
||||||
|
lms_sig->q = sig0_q;
|
||||||
|
lms_sig->lmots_sig.lmots_type = sig0_lmots_type;
|
||||||
|
hex_to_bytes(sig0_C, 64, lms_sig->lmots_sig.C, &len);
|
||||||
|
for (i = 0; i < 34; i++) {
|
||||||
|
hex_to_bytes(sig0_y[i], 64, lms_sig->lmots_sig.y[i], &len);
|
||||||
|
}
|
||||||
|
lms_sig->lms_type = sig0_lms_type;
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
hex_to_bytes(sig0_path[i], 64, lms_sig->path[i], &len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub[0]
|
||||||
|
lms_pub = &sig.signed_public_keys[0].lms_public_key;
|
||||||
|
lms_pub->lms_type = pub0_lms_type;
|
||||||
|
lms_pub->lmots_type = pub0_lmots_type;
|
||||||
|
hex_to_bytes(pub0_I, 32, lms_pub->I, &len);
|
||||||
|
hex_to_bytes(pub0_K, 64, lms_pub->root, &len);
|
||||||
|
|
||||||
|
// sig[1]
|
||||||
|
lms_sig = &sig.msg_lms_sig;
|
||||||
|
lms_sig->q = sig1_q;
|
||||||
|
lms_sig->lmots_sig.lmots_type = sig1_lmots_type;
|
||||||
|
hex_to_bytes(sig1_C, 64, lms_sig->lmots_sig.C, &len);
|
||||||
|
for (i = 0; i < 34; i++) {
|
||||||
|
hex_to_bytes(sig1_y[i], 64, lms_sig->lmots_sig.y[i], &len);
|
||||||
|
}
|
||||||
|
lms_sig->lms_type = sig1_lms_type;
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
hex_to_bytes(sig1_path[i], 64, lms_sig->path[i], &len);
|
||||||
|
}
|
||||||
|
|
||||||
|
sm3_hss_public_key_print(stderr, 0, 0, "hss_public_key", &key);
|
||||||
|
|
||||||
|
sm3_hss_signature_print_ex(stderr, 0, 0, "hss_signature", &sig);
|
||||||
|
|
||||||
|
|
||||||
|
SM3_HSS_SIGN_CTX ctx;
|
||||||
|
uint8_t data[162];
|
||||||
|
|
||||||
|
hex_to_bytes(msg, strlen(msg), data, &len);
|
||||||
|
|
||||||
|
if (sm3_hss_verify_init_ex(&ctx, &key, &sig) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_verify_update(&ctx, data, len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_verify_finish(&ctx) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static int test_sm3_lmots(void)
|
||||||
|
{
|
||||||
|
hash256_t seed = {0}; // TODO: change to test vector
|
||||||
|
uint8_t I[16] = {0};
|
||||||
|
int q = 0;
|
||||||
|
hash256_t dgst = {0};
|
||||||
|
hash256_t x[34];
|
||||||
|
hash256_t y[34];
|
||||||
|
hash256_t pub;
|
||||||
|
hash256_t pub2;
|
||||||
|
|
||||||
|
sm3_lmots_derive_secrets(seed, I, q, x); // TODO: compare results with test vector
|
||||||
|
sm3_lmots_secrets_to_public_hash(I, q, x, pub); // TODO: compare results with test vector
|
||||||
|
|
||||||
|
sm3_lmots_compute_signature(I, q, dgst, x, y); // TODO: compare results with test vector
|
||||||
|
sm3_lmots_signature_to_public_hash(I, q, y, dgst, pub2);
|
||||||
|
|
||||||
|
if (memcmp(pub, pub2, 32) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_lms_derive_merkle_root(void)
|
||||||
|
{
|
||||||
|
hash256_t seed = {0}; // TODO: change to test vector
|
||||||
|
uint8_t I[16] = {0};
|
||||||
|
int h = 5;
|
||||||
|
int n = 1<<h;
|
||||||
|
hash256_t *tree = NULL;
|
||||||
|
hash256_t root;
|
||||||
|
|
||||||
|
if (!(tree = (hash256_t *)malloc(sizeof(hash256_t)*(2*n - 1)))) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm3_lms_derive_merkle_tree(seed, I, h, tree);
|
||||||
|
sm3_lms_derive_merkle_root(seed, I, h, root);
|
||||||
|
|
||||||
|
if (memcmp(tree[0], root, 32) != 0) {
|
||||||
|
free(tree);
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(tree);
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_lms_key_generate(void)
|
||||||
|
{
|
||||||
|
SM3_LMS_KEY lms_key;
|
||||||
|
int lms_type = lms_types[0];
|
||||||
|
|
||||||
|
if (sm3_lms_key_generate(&lms_key, lms_type) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//sm3_lms_key_print(stdout, 0, 0, "lms_key", &lms_key);
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_lms_key_to_bytes(void)
|
||||||
|
{
|
||||||
|
SM3_LMS_KEY key;
|
||||||
|
int lms_type = lms_types[0];
|
||||||
|
|
||||||
|
uint8_t buf[sizeof(SM3_LMS_KEY) * 2];
|
||||||
|
uint8_t *p = buf;
|
||||||
|
const uint8_t *cp = buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
|
||||||
|
if (sm3_lms_key_generate(&key, lms_type) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
len = 0;
|
||||||
|
if (sm3_lms_public_key_to_bytes(&key, &p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len != SM3_LMS_PUBLIC_KEY_SIZE) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_lms_private_key_to_bytes(&key, &p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len != SM3_LMS_PUBLIC_KEY_SIZE + SM3_LMS_PRIVATE_KEY_SIZE) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = buf;
|
||||||
|
if (sm3_lms_public_key_from_bytes(&key, &cp, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_lms_key_print(stdout, 0, 4, "lms_public_key", &key);
|
||||||
|
|
||||||
|
if (sm3_lms_private_key_from_bytes(&key, &cp, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_lms_key_print(stdout, 0, 4, "lms_private_key", &key);
|
||||||
|
if (len != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_lms_sign(void)
|
||||||
|
{
|
||||||
|
int lms_type = lms_types[0];
|
||||||
|
SM3_LMS_KEY key;
|
||||||
|
SM3_LMS_SIGN_CTX ctx;
|
||||||
|
uint8_t msg[200];
|
||||||
|
uint8_t sig[SM3_LMS_SIGNATURE_MAX_SIZE];
|
||||||
|
size_t siglen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (sm3_lms_key_generate(&key, lms_type) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ctx, 0, sizeof(ctx));
|
||||||
|
memset(sig, 0, sizeof(sig));
|
||||||
|
|
||||||
|
if (sm3_lms_sign_init(&ctx, &key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_lms_sign_update(&ctx, msg, 100) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_lms_sign_update(&ctx, msg + 100, 100) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_lms_sign_finish(&ctx, sig, &siglen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1) {
|
||||||
|
SM3_LMS_SIGNATURE signature;
|
||||||
|
const uint8_t *cp = sig;
|
||||||
|
size_t len = siglen;
|
||||||
|
|
||||||
|
if (sm3_lms_signature_from_bytes(&signature, &cp, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_lms_signature_print_ex(stderr, 0, 4, "lms_signature", &signature);
|
||||||
|
if (len) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ctx, 0, sizeof(ctx));
|
||||||
|
|
||||||
|
if (sm3_lms_verify_init(&ctx, &key, sig, siglen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_lms_verify_update(&ctx, msg, 100) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_lms_verify_update(&ctx, msg + 100, 100) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((ret = sm3_lms_verify_finish(&ctx)) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_lms_max_sigs(void)
|
||||||
|
{
|
||||||
|
int lms_type = LMS_HASH256_M32_H5;
|
||||||
|
int height = 5;
|
||||||
|
SM3_LMS_KEY key;
|
||||||
|
SM3_LMS_SIGN_CTX ctx;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sm3_lms_key_generate(&key, lms_type) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
key.q = 1 << height;
|
||||||
|
|
||||||
|
if (sm3_lms_sign_init(&ctx, &key) == 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_hss_key_generate(void)
|
||||||
|
{
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key, lms_types, sizeof(lms_types)/sizeof(lms_types[0])) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm3_hss_public_key_print(stdout, 0, 4, "sm3_hss_public_key", &key);
|
||||||
|
sm3_hss_key_print(stdout, 0, 4, "sm3_hss_key", &key);
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_hss_key_update_level1(void)
|
||||||
|
{
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
|
||||||
|
memset(&key, 0, sizeof(SM3_HSS_KEY));
|
||||||
|
|
||||||
|
key.levels = 1;
|
||||||
|
key.lms_key[0].public_key.lms_type = LMS_HASH256_M32_H25;
|
||||||
|
key.lms_key[0].public_key.lmots_type = LMOTS_HASH256_N32_W8;
|
||||||
|
key.lms_key[0].q = (1 << 25);
|
||||||
|
|
||||||
|
// out of keys
|
||||||
|
if (sm3_hss_key_update(&key) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_hss_key_update_level2(void)
|
||||||
|
{
|
||||||
|
int lms_types[] = {
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
};
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key, lms_types, 2) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
key.lms_key[1].q = 32;
|
||||||
|
|
||||||
|
// update 1
|
||||||
|
if (sm3_hss_key_update(&key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (key.lms_key[0].q != 2
|
||||||
|
|| key.lms_sig[0].q != 1
|
||||||
|
|| key.lms_key[1].q != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update 2
|
||||||
|
key.lms_key[1].q = 32;
|
||||||
|
if (sm3_hss_key_update(&key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (key.lms_key[0].q != 3
|
||||||
|
|| key.lms_sig[0].q != 2
|
||||||
|
|| key.lms_key[1].q != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update 31
|
||||||
|
key.lms_key[0].q = 31;
|
||||||
|
key.lms_key[1].q = 32;
|
||||||
|
if (sm3_hss_key_update(&key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (key.lms_key[0].q != 32
|
||||||
|
|| key.lms_sig[0].q != 31
|
||||||
|
|| key.lms_key[1].q != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update 32, key space exhausted, return 0
|
||||||
|
key.lms_key[1].q = 32;
|
||||||
|
if (sm3_hss_key_update(&key) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int test_sm3_hss_key_update_level5(void)
|
||||||
|
{
|
||||||
|
int lms_types[] = {
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
LMS_HASH256_M32_H5,
|
||||||
|
};
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key, lms_types, 5) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (key.lms_key[0].q != 1
|
||||||
|
|| key.lms_sig[0].q != 0
|
||||||
|
|| key.lms_key[1].q != 1
|
||||||
|
|| key.lms_sig[1].q != 0
|
||||||
|
|| key.lms_key[2].q != 1
|
||||||
|
|| key.lms_sig[2].q != 0
|
||||||
|
|| key.lms_key[3].q != 1
|
||||||
|
|| key.lms_sig[3].q != 0
|
||||||
|
|| key.lms_key[4].q != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// level-4 update
|
||||||
|
key.lms_key[4].q = 32;
|
||||||
|
if (sm3_hss_key_update(&key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (key.lms_key[0].q != 1
|
||||||
|
|| key.lms_sig[0].q != 0
|
||||||
|
|| key.lms_key[1].q != 1
|
||||||
|
|| key.lms_sig[1].q != 0
|
||||||
|
|| key.lms_key[2].q != 1
|
||||||
|
|| key.lms_sig[2].q != 0
|
||||||
|
|| key.lms_key[3].q != 2
|
||||||
|
|| key.lms_sig[3].q != 1
|
||||||
|
|| key.lms_key[4].q != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// level-4 to level-2 update
|
||||||
|
key.lms_key[0].q = 1;
|
||||||
|
key.lms_sig[0].q = 0;
|
||||||
|
key.lms_key[1].q = 3;
|
||||||
|
key.lms_sig[1].q = 2;
|
||||||
|
key.lms_key[2].q = 32;
|
||||||
|
key.lms_sig[2].q = 31;
|
||||||
|
key.lms_key[3].q = 32;
|
||||||
|
key.lms_sig[3].q = 31;
|
||||||
|
key.lms_key[4].q = 32;
|
||||||
|
if (sm3_hss_key_update(&key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (key.lms_key[0].q != 1
|
||||||
|
|| key.lms_sig[0].q != 0
|
||||||
|
|| key.lms_key[1].q != 4
|
||||||
|
|| key.lms_sig[1].q != 3
|
||||||
|
|| key.lms_key[2].q != 1
|
||||||
|
|| key.lms_sig[2].q != 0
|
||||||
|
|| key.lms_key[3].q != 1
|
||||||
|
|| key.lms_sig[3].q != 0
|
||||||
|
|| key.lms_key[4].q != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// level-4 to level-1 update
|
||||||
|
key.lms_key[0].q = 1;
|
||||||
|
key.lms_sig[0].q = 0;
|
||||||
|
key.lms_key[1].q = 32;
|
||||||
|
key.lms_sig[1].q = 31;
|
||||||
|
key.lms_key[2].q = 32;
|
||||||
|
key.lms_sig[2].q = 31;
|
||||||
|
key.lms_key[3].q = 32;
|
||||||
|
key.lms_sig[3].q = 31;
|
||||||
|
key.lms_key[4].q = 32;
|
||||||
|
if (sm3_hss_key_update(&key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (key.lms_key[0].q != 2
|
||||||
|
|| key.lms_sig[0].q != 1
|
||||||
|
|| key.lms_key[1].q != 1
|
||||||
|
|| key.lms_sig[1].q != 0
|
||||||
|
|| key.lms_key[2].q != 1
|
||||||
|
|| key.lms_sig[2].q != 0
|
||||||
|
|| key.lms_key[3].q != 1
|
||||||
|
|| key.lms_sig[3].q != 0
|
||||||
|
|| key.lms_key[4].q != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// out of keys
|
||||||
|
key.lms_key[0].q = 32;
|
||||||
|
key.lms_sig[0].q = 31;
|
||||||
|
key.lms_key[1].q = 32;
|
||||||
|
key.lms_sig[1].q = 31;
|
||||||
|
key.lms_key[2].q = 32;
|
||||||
|
key.lms_sig[2].q = 31;
|
||||||
|
key.lms_key[3].q = 32;
|
||||||
|
key.lms_sig[3].q = 31;
|
||||||
|
key.lms_key[4].q = 32;
|
||||||
|
if (sm3_hss_key_update(&key) != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_hss_key_to_bytes(void)
|
||||||
|
{
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
|
||||||
|
uint8_t buf[SM3_HSS_PUBLIC_KEY_SIZE + sizeof(SM3_HSS_KEY)];
|
||||||
|
uint8_t *p = buf;
|
||||||
|
const uint8_t *cp = buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key,
|
||||||
|
lms_types, sizeof(lms_types)/sizeof(lms_types[0])) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
len = 0;
|
||||||
|
if (sm3_hss_public_key_to_bytes(&key, &p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len != SM3_HSS_PUBLIC_KEY_SIZE) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_private_key_to_bytes(&key, &p, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = buf;
|
||||||
|
if (sm3_hss_public_key_from_bytes(&key, &cp, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_hss_public_key_print(stdout, 0, 4, "lms_public_key", &key);
|
||||||
|
|
||||||
|
if (sm3_hss_private_key_from_bytes(&key, &cp, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_hss_key_print(stdout, 0, 4, "lms_private_key", &key);
|
||||||
|
if (len != 0) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_hss_sign_level1(void)
|
||||||
|
{
|
||||||
|
int levels = 1;
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
SM3_HSS_SIGN_CTX ctx;
|
||||||
|
SM3_HSS_SIGNATURE sig;
|
||||||
|
uint8_t msg[200];
|
||||||
|
uint8_t buf[sizeof(SM3_HSS_SIGNATURE)];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key, lms_types, levels) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_sign_init(&ctx, &key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_sign_update(&ctx, msg, sizeof(msg)) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_sign_finish(&ctx, buf, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_verify_init(&ctx, &key, buf, len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_verify_update(&ctx, msg, sizeof(msg)) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_verify_finish(&ctx) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_hss_sign_level2(void)
|
||||||
|
{
|
||||||
|
int levels = 2;
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
SM3_HSS_SIGN_CTX ctx;
|
||||||
|
SM3_HSS_SIGNATURE sig;
|
||||||
|
uint8_t msg[200];
|
||||||
|
uint8_t buf[sizeof(SM3_HSS_SIGNATURE)];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key, lms_types, levels) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_hss_key_print(stderr, 0, 4, "sm3_hss_key", &key);
|
||||||
|
|
||||||
|
|
||||||
|
if (sm3_hss_sign_init(&ctx, &key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_sign_update(&ctx, msg, sizeof(msg)) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_sign_finish(&ctx, buf, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_hss_signature_print(stderr, 0, 4, "sm3_hss_signature", buf, len);
|
||||||
|
|
||||||
|
|
||||||
|
if (sm3_hss_verify_init(&ctx, &key, buf, len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_verify_update(&ctx, msg, sizeof(msg)) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_verify_finish(&ctx) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_sm3_hss_sign(void)
|
||||||
|
{
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
SM3_HSS_SIGN_CTX ctx;
|
||||||
|
SM3_HSS_SIGNATURE sig;
|
||||||
|
uint8_t msg[200];
|
||||||
|
uint8_t buf[sizeof(SM3_HSS_SIGNATURE)];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key, lms_types, sizeof(lms_types)/sizeof(lms_types[0])) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_hss_key_print(stderr, 0, 4, "sm3_hss_key", &key);
|
||||||
|
|
||||||
|
|
||||||
|
if (sm3_hss_sign_init(&ctx, &key) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_sign_update(&ctx, msg, sizeof(msg)) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_sign_finish(&ctx, buf, &len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sm3_hss_signature_print(stderr, 0, 4, "sm3_hss_signature", buf, len);
|
||||||
|
|
||||||
|
|
||||||
|
if (sm3_hss_verify_init(&ctx, &key, buf, len) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_verify_update(&ctx, msg, sizeof(msg)) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sm3_hss_verify_finish(&ctx) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s() ok\n", __FUNCTION__);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_SM3_LMS_CROSSCHECK) && defined(ENABLE_SHA2)
|
||||||
|
if (test_rfc8554_test1() != 1) goto err;
|
||||||
|
#endif
|
||||||
|
if (test_sm3_lmots() != 1) goto err;
|
||||||
|
if (test_sm3_lms_derive_merkle_root() != 1) goto err;
|
||||||
|
if (test_sm3_lms_key_generate() != 1) goto err;
|
||||||
|
if (test_sm3_lms_key_to_bytes() != 1) goto err;
|
||||||
|
if (test_sm3_lms_sign() != 1) goto err;
|
||||||
|
if (test_sm3_lms_max_sigs() != 1) goto err;
|
||||||
|
if (test_sm3_hss_key_generate() != 1) goto err;
|
||||||
|
if (test_sm3_hss_key_to_bytes() != 1) goto err;
|
||||||
|
if (test_sm3_hss_key_update_level1() != 1) goto err;
|
||||||
|
if (test_sm3_hss_key_update_level2() != 1) goto err;
|
||||||
|
if (test_sm3_hss_key_update_level5() != 1) goto err;
|
||||||
|
if (test_sm3_hss_sign_level1() != 1) goto err;
|
||||||
|
if (test_sm3_hss_sign_level2() != 1) goto err;
|
||||||
|
if (test_sm3_hss_sign() != 1) goto err;
|
||||||
|
|
||||||
|
printf("%s all tests passed\n", __FILE__);
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
error_print();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014-2024 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
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
* not use this file except in compliance with the License.
|
* not use this file except in compliance with the License.
|
||||||
@@ -34,7 +34,6 @@ extern int sm2decrypt_main(int argc, char **argv);
|
|||||||
extern int sm3_main(int argc, char **argv);
|
extern int sm3_main(int argc, char **argv);
|
||||||
extern int sm3hmac_main(int argc, char **argv);
|
extern int sm3hmac_main(int argc, char **argv);
|
||||||
extern int sm3_pbkdf2_main(int argc, char **argv);
|
extern int sm3_pbkdf2_main(int argc, char **argv);
|
||||||
extern int sm3xmss_keygen_main(int argc, char **argv);
|
|
||||||
extern int sm4_ecb_main(int argc, char **argv);
|
extern int sm4_ecb_main(int argc, char **argv);
|
||||||
extern int sm4_cbc_main(int argc, char **argv);
|
extern int sm4_cbc_main(int argc, char **argv);
|
||||||
extern int sm4_ctr_main(int argc, char **argv);
|
extern int sm4_ctr_main(int argc, char **argv);
|
||||||
@@ -65,6 +64,17 @@ extern int tls12_client_main(int argc, char **argv);
|
|||||||
extern int tls12_server_main(int argc, char **argv);
|
extern int tls12_server_main(int argc, char **argv);
|
||||||
extern int tls13_client_main(int argc, char **argv);
|
extern int tls13_client_main(int argc, char **argv);
|
||||||
extern int tls13_server_main(int argc, char **argv);
|
extern int tls13_server_main(int argc, char **argv);
|
||||||
|
#ifdef ENABLE_SM3_LMS
|
||||||
|
extern int sm3lmskeygen_main(int argc, char **argv);
|
||||||
|
extern int sm3lmssign_main(int argc, char **argv);
|
||||||
|
extern int sm3lmsverify_main(int argc, char **argv);
|
||||||
|
extern int sm3hsskeygen_main(int argc, char **argv);
|
||||||
|
extern int sm3hsssign_main(int argc, char **argv);
|
||||||
|
extern int sm3hssverify_main(int argc, char **argv);
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_SM3_XMSS
|
||||||
|
extern int sm3xmss_keygen_main(int argc, char **argv);
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_SDF
|
#ifdef ENABLE_SDF
|
||||||
extern int sdfinfo_main(int argc, char **argv);
|
extern int sdfinfo_main(int argc, char **argv);
|
||||||
extern int sdfdigest_main(int argc, char **argv);
|
extern int sdfdigest_main(int argc, char **argv);
|
||||||
@@ -94,7 +104,6 @@ static const char *options =
|
|||||||
" sm3 Generate SM3 hash\n"
|
" sm3 Generate SM3 hash\n"
|
||||||
" sm3hmac Generate SM3 HMAC tag\n"
|
" sm3hmac Generate SM3 HMAC tag\n"
|
||||||
" sm3_pbkdf2 Hash password into key using PBKDF2 algoritm\n"
|
" sm3_pbkdf2 Hash password into key using PBKDF2 algoritm\n"
|
||||||
" sm3xmss_keygen Generate SM3-XMSS keypair\n"
|
|
||||||
" sm4_ecb Encrypt or decrypt with SM4 ECB\n"
|
" sm4_ecb Encrypt or decrypt with SM4 ECB\n"
|
||||||
" sm4_cbc Encrypt or decrypt with SM4 CBC\n"
|
" sm4_cbc Encrypt or decrypt with SM4 CBC\n"
|
||||||
" sm4_ctr Encrypt or decrypt with SM4 CTR\n"
|
" sm4_ctr Encrypt or decrypt with SM4 CTR\n"
|
||||||
@@ -130,6 +139,17 @@ static const char *options =
|
|||||||
" cmsdecrypt Decrypt CMS EnvelopedData\n"
|
" cmsdecrypt Decrypt CMS EnvelopedData\n"
|
||||||
" cmssign Generate CMS SignedData\n"
|
" cmssign Generate CMS SignedData\n"
|
||||||
" cmsverify Verify CMS SignedData\n"
|
" cmsverify Verify CMS SignedData\n"
|
||||||
|
#ifdef ENABLE_SM3_LMS
|
||||||
|
" sm3lmskeygen Generate SM3-LMS keypair\n"
|
||||||
|
" sm3lmssign Generate LMS signature\n"
|
||||||
|
" sm3lmsverify Verify LMS signature\n"
|
||||||
|
" sm3hsskeygen Generate SM3-HSS keypair\n"
|
||||||
|
" sm3hsssign Generate HSS signature\n"
|
||||||
|
" sm3hssverify Verify HSS signature\n"
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_SM3_XMSS
|
||||||
|
" sm3xmss_keygen Generate SM3-XMSS keypair\n"
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_SDF
|
#ifdef ENABLE_SDF
|
||||||
" sdfinfo Print SDF device info\n"
|
" sdfinfo Print SDF device info\n"
|
||||||
" sdfdigest Generate SM3 hash with SDF device\n"
|
" sdfdigest Generate SM3 hash with SDF device\n"
|
||||||
@@ -212,8 +232,6 @@ int main(int argc, char **argv)
|
|||||||
return sm3hmac_main(argc, argv);
|
return sm3hmac_main(argc, argv);
|
||||||
} else if (!strcmp(*argv, "sm3_pbkdf2")) {
|
} else if (!strcmp(*argv, "sm3_pbkdf2")) {
|
||||||
return sm3_pbkdf2_main(argc, argv);
|
return sm3_pbkdf2_main(argc, argv);
|
||||||
} else if (!strcmp(*argv, "sm3xmss_keygen")) {
|
|
||||||
return sm3xmss_keygen_main(argc, argv);
|
|
||||||
#if ENABLE_SM4_ECB
|
#if ENABLE_SM4_ECB
|
||||||
} else if (!strcmp(*argv, "sm4_ecb")) {
|
} else if (!strcmp(*argv, "sm4_ecb")) {
|
||||||
return sm4_ecb_main(argc, argv);
|
return sm4_ecb_main(argc, argv);
|
||||||
@@ -286,6 +304,24 @@ int main(int argc, char **argv)
|
|||||||
return tls13_client_main(argc, argv);
|
return tls13_client_main(argc, argv);
|
||||||
} else if (!strcmp(*argv, "tls13_server")) {
|
} else if (!strcmp(*argv, "tls13_server")) {
|
||||||
return tls13_server_main(argc, argv);
|
return tls13_server_main(argc, argv);
|
||||||
|
#ifdef ENABLE_SM3_LMS
|
||||||
|
} else if (!strcmp(*argv, "sm3lmskeygen")) {
|
||||||
|
return sm3lmskeygen_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "sm3lmssign")) {
|
||||||
|
return sm3lmssign_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "sm3lmsverify")) {
|
||||||
|
return sm3lmsverify_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "sm3hsskeygen")) {
|
||||||
|
return sm3hsskeygen_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "sm3hsssign")) {
|
||||||
|
return sm3hsssign_main(argc, argv);
|
||||||
|
} else if (!strcmp(*argv, "sm3hssverify")) {
|
||||||
|
return sm3hssverify_main(argc, argv);
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_SM3_XMSS
|
||||||
|
} else if (!strcmp(*argv, "sm3xmss_keygen")) {
|
||||||
|
return sm3xmss_keygen_main(argc, argv);
|
||||||
|
#endif
|
||||||
#ifdef ENABLE_SDF
|
#ifdef ENABLE_SDF
|
||||||
} else if (!strcmp(*argv, "sdfinfo")) {
|
} else if (!strcmp(*argv, "sdfinfo")) {
|
||||||
return sdfinfo_main(argc, argv);
|
return sdfinfo_main(argc, argv);
|
||||||
|
|||||||
158
tools/sm3hsskeygen.c
Normal file
158
tools/sm3hsskeygen.c
Normal 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/sm3_lms.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char *usage = "-lms_types types -out file [-pubout file] [-verbose]\n";
|
||||||
|
|
||||||
|
static const char *options =
|
||||||
|
"Options\n"
|
||||||
|
" -lms_types types LMS Algorithm Types, start from level 0, seperate by ':'\n"
|
||||||
|
" such as "LMS_HASH256_M32_H5_NAME":"LMS_HASH256_M32_H10_NAME"\n"
|
||||||
|
" Supported types:\n"
|
||||||
|
" "LMS_HASH256_M32_H5_NAME"\n"
|
||||||
|
" "LMS_HASH256_M32_H10_NAME"\n"
|
||||||
|
" "LMS_HASH256_M32_H15_NAME"\n"
|
||||||
|
" "LMS_HASH256_M32_H20_NAME"\n"
|
||||||
|
" "LMS_HASH256_M32_H25_NAME"\n"
|
||||||
|
" -out file Output private key\n"
|
||||||
|
" -pubout file Output public key\n"
|
||||||
|
" -verbose Print public key\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
#define LMS_TYPES_STR_MAX_SIZE (sizeof("LMS_SM3_M32_H20_NAME") * 5)
|
||||||
|
|
||||||
|
int sm3hsskeygen_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *prog = argv[0];
|
||||||
|
char *lms_types = NULL;
|
||||||
|
char *outfile = NULL;
|
||||||
|
char *puboutfile = NULL;
|
||||||
|
int verbose = 0;
|
||||||
|
char lms_types_str[LMS_TYPES_STR_MAX_SIZE];
|
||||||
|
int lms_types_val[5];
|
||||||
|
int levels = 0;
|
||||||
|
FILE *outfp = NULL;
|
||||||
|
FILE *puboutfp = stdout;
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
uint8_t out[SM3_HSS_PRIVATE_KEY_MAX_SIZE];
|
||||||
|
uint8_t pubout[SM3_HSS_PUBLIC_KEY_SIZE];
|
||||||
|
uint8_t *pout = out;
|
||||||
|
uint8_t *ppubout = pubout;
|
||||||
|
size_t outlen = 0, puboutlen = 0;
|
||||||
|
|
||||||
|
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: gmssl %s %s\n", prog, usage);
|
||||||
|
printf("%s\n", options);
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
} else if (!strcmp(*argv, "-lms_types")) {
|
||||||
|
char *tok;
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
lms_types = *(++argv);
|
||||||
|
strncpy(lms_types_str, lms_types, sizeof(lms_types_str));
|
||||||
|
|
||||||
|
tok = strtok(lms_types_str, ":");
|
||||||
|
while (tok) {
|
||||||
|
if (!(lms_types_val[levels] = sm3_lms_type_from_name(tok))) {
|
||||||
|
fprintf(stderr, "%s: invalid lms_type `%s`\n", prog, tok);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
tok = strtok(NULL, ":");
|
||||||
|
levels++;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-out")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
outfile = *(++argv);
|
||||||
|
if (!(outfp = fopen(outfile, "wb"))) {
|
||||||
|
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-pubout")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
puboutfile = *(++argv);
|
||||||
|
if (!(puboutfp = fopen(puboutfile, "wb"))) {
|
||||||
|
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;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lms_types) {
|
||||||
|
fprintf(stderr, "%s: `-lms_types` option required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!outfp) {
|
||||||
|
fprintf(stderr, "%s: `-out` option required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_key_generate(&key, lms_types_val, levels) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
sm3_hss_public_key_print(stderr, 0, 0, "hss_public_key", &key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_private_key_to_bytes(&key, &pout, &outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (fwrite(out, 1, outlen, outfp) != outlen) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_public_key_to_bytes(&key, &ppubout, &puboutlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (fwrite(pubout, 1, puboutlen, puboutfp) != puboutlen) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(out, outlen);
|
||||||
|
if (outfile && outfp) fclose(outfp);
|
||||||
|
if (puboutfile && puboutfp) fclose(puboutfp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
170
tools/sm3hsssign.c
Normal file
170
tools/sm3hsssign.c
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* 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/sm3_lms.h>
|
||||||
|
|
||||||
|
static const char *usage = "-key file [-in file] [-out file] [-verbose]\n";
|
||||||
|
|
||||||
|
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 sm3hsssign_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *prog = argv[0];
|
||||||
|
char *keyfile = NULL;
|
||||||
|
char *infile = NULL;
|
||||||
|
char *outfile = NULL;
|
||||||
|
int verbose = 0;
|
||||||
|
FILE *keyfp = NULL;
|
||||||
|
FILE *infp = stdin;
|
||||||
|
FILE *outfp = stdout;
|
||||||
|
uint8_t keybuf[SM3_HSS_PRIVATE_KEY_MAX_SIZE];
|
||||||
|
size_t keylen = SM3_HSS_PRIVATE_KEY_MAX_SIZE;
|
||||||
|
const uint8_t *cp = keybuf;
|
||||||
|
uint8_t *p = keybuf;
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
SM3_HSS_SIGN_CTX ctx;
|
||||||
|
uint8_t sig[SM3_HSS_SIGNATURE_MAX_SIZE];
|
||||||
|
size_t siglen;
|
||||||
|
|
||||||
|
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, "-key")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keyfile = *(++argv);
|
||||||
|
if (!(keyfp = fopen(keyfile, "rb+"))) {
|
||||||
|
fprintf(stderr, "%s: open '%s' failure: %s\n", prog, keyfile, 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, "-out")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
outfile = *(++argv);
|
||||||
|
if (!(outfp = fopen(outfile, "wb"))) {
|
||||||
|
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;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
fprintf(stderr, "%s: `-key` option required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((keylen = fread(keybuf, 1, keylen, keyfp)) <= 0) {
|
||||||
|
fprintf(stderr, "%s: read private key failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm3_hss_private_key_from_bytes(&key, &cp, &keylen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (keylen) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
sm3_hss_public_key_print(stderr, 0, 0, "hss_public_key", &key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_hss_sign_init(&ctx, &key) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write updated key back to file
|
||||||
|
// TODO: write back `q` only
|
||||||
|
if (sm3_hss_private_key_to_bytes(&key, &p, &keylen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rewind(keyfp);
|
||||||
|
if (fwrite(keybuf, 1, keylen, keyfp) != keylen) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint8_t buf[1024];
|
||||||
|
size_t len = fread(buf, 1, sizeof(buf), infp);
|
||||||
|
if (len == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sm3_hss_sign_update(&ctx, buf, len) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sm3_hss_sign_finish(&ctx, sig, &siglen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (fwrite(sig, 1, siglen, outfp) != siglen) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
sm3_hss_signature_print(stderr, 0, 0, "hss_signature", sig, siglen);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(keybuf, sizeof(keybuf));
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(&ctx, sizeof(ctx));
|
||||||
|
if (keyfp) fclose(keyfp);
|
||||||
|
if (infp && infp != stdin) fclose(infp);
|
||||||
|
if (outfp && outfp != stdout) fclose(outfp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
157
tools/sm3hssverify.c
Normal file
157
tools/sm3hssverify.c
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* 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/sm3_lms.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 sm3hssverify_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[SM3_HSS_PUBLIC_KEY_SIZE];
|
||||||
|
size_t pubkeylen = SM3_HSS_PUBLIC_KEY_SIZE;
|
||||||
|
const uint8_t *cp = pubkeybuf;
|
||||||
|
uint8_t sig[SM3_HSS_SIGNATURE_MAX_SIZE];
|
||||||
|
size_t siglen;
|
||||||
|
SM3_HSS_KEY key;
|
||||||
|
SM3_HSS_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 (sm3_hss_public_key_from_bytes(&key, &cp, &pubkeylen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
sm3_hss_public_key_print(stderr, 0, 0, "lms_public_key", &key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read signature even if signature not compatible with the public key
|
||||||
|
if ((siglen = fread(sig, 1, SM3_HSS_SIGNATURE_MAX_SIZE, sigfp)) <= 0) {
|
||||||
|
fprintf(stderr, "%s: read signature failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
sm3_hss_signature_print(stderr, 0, 0, "lms_signature", sig, siglen);
|
||||||
|
}
|
||||||
|
if (sm3_hss_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 (sm3_hss_verify_update(&ctx, buf, len) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((vr = sm3_hss_verify_finish(&ctx)) < 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;
|
||||||
|
}
|
||||||
144
tools/sm3lmskeygen.c
Normal file
144
tools/sm3lmskeygen.c
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* 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/sm3_lms.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const char *usage = "-lms_type type -out file [-pubout file] [-verbose]\n";
|
||||||
|
|
||||||
|
static const char *options =
|
||||||
|
"Options\n"
|
||||||
|
" -lms_type type LMS Algorithm Type\n"
|
||||||
|
" "LMS_HASH256_M32_H5_NAME"\n"
|
||||||
|
" "LMS_HASH256_M32_H10_NAME"\n"
|
||||||
|
" "LMS_HASH256_M32_H15_NAME"\n"
|
||||||
|
" "LMS_HASH256_M32_H20_NAME"\n"
|
||||||
|
" "LMS_HASH256_M32_H25_NAME"\n"
|
||||||
|
" -out file Output private key\n"
|
||||||
|
" -pubout file Output public key\n"
|
||||||
|
" -verbose Print public key\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
int sm3lmskeygen_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *prog = argv[0];
|
||||||
|
char *lms_type = NULL;
|
||||||
|
int lms_type_val = 0;
|
||||||
|
char *outfile = NULL;
|
||||||
|
char *puboutfile = NULL;
|
||||||
|
int verbose = 0;
|
||||||
|
FILE *outfp = NULL;
|
||||||
|
FILE *puboutfp = stdout;
|
||||||
|
SM3_LMS_KEY key;
|
||||||
|
uint8_t out[SM3_LMS_PRIVATE_KEY_SIZE];
|
||||||
|
uint8_t pubout[SM3_LMS_PUBLIC_KEY_SIZE];
|
||||||
|
uint8_t *pout = out;
|
||||||
|
uint8_t *ppubout = pubout;
|
||||||
|
size_t outlen = 0, puboutlen = 0;
|
||||||
|
|
||||||
|
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: gmssl %s %s\n", prog, usage);
|
||||||
|
printf("%s\n", options);
|
||||||
|
ret = 0;
|
||||||
|
goto end;
|
||||||
|
} else if (!strcmp(*argv, "-lms_type")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
lms_type = *(++argv);
|
||||||
|
if (!(lms_type_val = sm3_lms_type_from_name(lms_type))) {
|
||||||
|
fprintf(stderr, "%s: invalid lms_type `%s`\n", prog, lms_type);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-out")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
outfile = *(++argv);
|
||||||
|
if (!(outfp = fopen(outfile, "wb"))) {
|
||||||
|
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(*argv, "-pubout")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
puboutfile = *(++argv);
|
||||||
|
if (!(puboutfp = fopen(puboutfile, "wb"))) {
|
||||||
|
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;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lms_type) {
|
||||||
|
fprintf(stderr, "%s: `-lms_type` option required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!outfp) {
|
||||||
|
fprintf(stderr, "%s: `-out` option required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_lms_key_generate(&key, lms_type_val) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
sm3_lms_public_key_print(stderr, 0, 0, "lms_public_key", &key.public_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_lms_private_key_to_bytes(&key, &pout, &outlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (fwrite(out, 1, outlen, outfp) != outlen) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_lms_public_key_to_bytes(&key, &ppubout, &puboutlen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (fwrite(pubout, 1, puboutlen, puboutfp) != puboutlen) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(out, outlen);
|
||||||
|
if (outfile && outfp) fclose(outfp);
|
||||||
|
if (puboutfile && puboutfp) fclose(puboutfp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
170
tools/sm3lmssign.c
Normal file
170
tools/sm3lmssign.c
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* 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/sm3_lms.h>
|
||||||
|
|
||||||
|
static const char *usage = "-key file [-in file] [-out file] [-verbose]\n";
|
||||||
|
|
||||||
|
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 sm3lmssign_main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *prog = argv[0];
|
||||||
|
char *keyfile = NULL;
|
||||||
|
char *infile = NULL;
|
||||||
|
char *outfile = NULL;
|
||||||
|
int verbose = 0;
|
||||||
|
FILE *keyfp = NULL;
|
||||||
|
FILE *infp = stdin;
|
||||||
|
FILE *outfp = stdout;
|
||||||
|
uint8_t keybuf[SM3_LMS_PRIVATE_KEY_SIZE];
|
||||||
|
size_t keylen = SM3_LMS_PRIVATE_KEY_SIZE;
|
||||||
|
const uint8_t *cp = keybuf;
|
||||||
|
uint8_t *p = keybuf;
|
||||||
|
SM3_LMS_KEY key;
|
||||||
|
SM3_LMS_SIGN_CTX ctx;
|
||||||
|
uint8_t sig[SM3_LMS_SIGNATURE_MAX_SIZE];
|
||||||
|
size_t siglen;
|
||||||
|
|
||||||
|
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, "-key")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
keyfile = *(++argv);
|
||||||
|
if (!(keyfp = fopen(keyfile, "rb+"))) {
|
||||||
|
fprintf(stderr, "%s: open '%s' failure: %s\n", prog, keyfile, 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, "-out")) {
|
||||||
|
if (--argc < 1) goto bad;
|
||||||
|
outfile = *(++argv);
|
||||||
|
if (!(outfp = fopen(outfile, "wb"))) {
|
||||||
|
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;
|
||||||
|
bad:
|
||||||
|
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyfile) {
|
||||||
|
fprintf(stderr, "%s: `-key` option required\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(keybuf, 1, keylen, keyfp) != keylen) {
|
||||||
|
fprintf(stderr, "%s: read private key failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (sm3_lms_private_key_from_bytes(&key, &cp, &keylen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (keylen) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
sm3_lms_public_key_print(stderr, 0, 0, "lms_public_key", &key.public_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sm3_lms_sign_init(&ctx, &key) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write updated key back to file
|
||||||
|
// TODO: write back `q` only
|
||||||
|
if (sm3_lms_private_key_to_bytes(&key, &p, &keylen) != 1) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rewind(keyfp);
|
||||||
|
if (fwrite(keybuf, 1, keylen, keyfp) != keylen) {
|
||||||
|
error_print();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint8_t buf[1024];
|
||||||
|
size_t len = fread(buf, 1, sizeof(buf), infp);
|
||||||
|
if (len == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sm3_lms_sign_update(&ctx, buf, len) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sm3_lms_sign_finish(&ctx, sig, &siglen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (fwrite(sig, 1, siglen, outfp) != siglen) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
sm3_lms_signature_print(stderr, 0, 0, "lms_signature", sig, siglen);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
gmssl_secure_clear(keybuf, sizeof(keybuf));
|
||||||
|
gmssl_secure_clear(&key, sizeof(key));
|
||||||
|
gmssl_secure_clear(&ctx, sizeof(ctx));
|
||||||
|
if (keyfp) fclose(keyfp);
|
||||||
|
if (infp && infp != stdin) fclose(infp);
|
||||||
|
if (outfp && outfp != stdout) fclose(outfp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
157
tools/sm3lmsverify.c
Normal file
157
tools/sm3lmsverify.c
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* 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/sm3_lms.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 sm3lmsverify_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[SM3_LMS_PUBLIC_KEY_SIZE];
|
||||||
|
size_t pubkeylen = SM3_LMS_PUBLIC_KEY_SIZE;
|
||||||
|
const uint8_t *cp = pubkeybuf;
|
||||||
|
uint8_t sig[SM3_LMS_SIGNATURE_MAX_SIZE];
|
||||||
|
size_t siglen;
|
||||||
|
SM3_LMS_KEY key;
|
||||||
|
SM3_LMS_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 (sm3_lms_public_key_from_bytes(&key, &cp, &pubkeylen) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
sm3_lms_public_key_print(stderr, 0, 0, "lms_public_key", &key.public_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read signature even if signature not compatible with the public key
|
||||||
|
if ((siglen = fread(sig, 1, SM3_LMS_SIGNATURE_MAX_SIZE, sigfp)) <= 0) {
|
||||||
|
fprintf(stderr, "%s: read signature failure\n", prog);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
sm3_lms_signature_print(stderr, 0, 0, "lms_signature", sig, siglen);
|
||||||
|
}
|
||||||
|
if (sm3_lms_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 (sm3_lms_verify_update(&ctx, buf, len) != 1) {
|
||||||
|
error_print();
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((vr = sm3_lms_verify_finish(&ctx)) < 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user