From cac8f394a06a4f723feecf8d6bf6ea12ae3c0d3d Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Tue, 24 Feb 2026 10:45:33 +0800 Subject: [PATCH] Update X509_KEY API to support SM9 --- include/gmssl/lms.h | 7 +- include/gmssl/pkcs8.h | 3 + include/gmssl/sm9.h | 16 ++- include/gmssl/sphincs.h | 7 +- include/gmssl/x509_key.h | 51 +++++---- src/sm9_key.c | 68 +++++++++++ src/x509_alg.c | 38 ++++--- src/x509_key.c | 235 +++++++++++++++++++++++++++++++++++++-- tests/lmstest.c | 17 +++ tests/x509_keytest.c | 61 ++++++++++ tools/sm9keygen.c | 10 +- 11 files changed, 455 insertions(+), 58 deletions(-) diff --git a/include/gmssl/lms.h b/include/gmssl/lms.h index 37a19b1b..570fbb0d 100644 --- a/include/gmssl/lms.h +++ b/include/gmssl/lms.h @@ -266,7 +266,12 @@ typedef struct { LMS_SIGNATURE msg_lms_sig; // = sign(hss->lms_key[levels-1], msg) } HSS_SIGNATURE; -#define HSS_SIGNATURE_MAX_SIZE sizeof(HSS_SIGNATURE) +// not correct +#define HSS_SIGNATURE_MAX_SIZE ( \ + sizeof(uint32_t) + \ + (LMS_SIGNATURE_MAX_SIZE + LMS_PUBLIC_KEY_SIZE) * (HSS_MAX_LEVELS - 1) + \ + LMS_SIGNATURE_MAX_SIZE) + int hss_signature_size(const int *lms_types, size_t levels, size_t *len); int hss_signature_to_bytes(const HSS_SIGNATURE *sig, uint8_t **out, size_t *outlen); int hss_signature_from_bytes(HSS_SIGNATURE *sig, const uint8_t **in, size_t *inlen); diff --git a/include/gmssl/pkcs8.h b/include/gmssl/pkcs8.h index e4a27f10..75c8ce08 100644 --- a/include/gmssl/pkcs8.h +++ b/include/gmssl/pkcs8.h @@ -142,6 +142,9 @@ PrivateKeyInfo ::= SEQUENCE { attributes [0] Attributes OPTIONAL } */ +#define PKCS8_ENCED_PRIVATE_KEY_INFO_ITER 65536 +//#define PKCS8_ENCED_PRIVATE_KEY_INFO_ITER 8000 // if too slow + int pkcs8_enced_private_key_info_to_der( const uint8_t *salt, size_t saltlen, int iter, diff --git a/include/gmssl/sm9.h b/include/gmssl/sm9.h index 4e9646b8..a70d39db 100644 --- a/include/gmssl/sm9.h +++ b/include/gmssl/sm9.h @@ -42,12 +42,14 @@ int sm9_algor_to_der(int alg, int params, uint8_t **out, size_t *outlen); int sm9_algor_from_der(int *alg, int *params, const uint8_t **in, size_t *inlen); -#define PEM_SM9_SIGN_MASTER_KEY "ENCRYPTED SM9 SIGN MASTER KEY" +// ENCRYPTED PRIVATE KEY => PKCS #8 PrivateKeyInfo => public key algro +// FIXME: master public key should support public_key_info API +#define PEM_SM9_SIGN_MASTER_KEY "ENCRYPTED PRIVATE KEY" //"ENCRYPTED SM9 SIGN MASTER KEY" #define PEM_SM9_SIGN_MASTER_PUBLIC_KEY "SM9 SIGN MASTER PUBLIC KEY" -#define PEM_SM9_SIGN_PRIVATE_KEY "ENCRYPTED SM9 SIGN PRIVATE KEY" -#define PEM_SM9_ENC_MASTER_KEY "ENCRYPTED SM9 ENC MASTER KEY" +#define PEM_SM9_SIGN_PRIVATE_KEY "ENCRYPTED PRIVATE KEY" //"ENCRYPTED SM9 SIGN PRIVATE KEY" +#define PEM_SM9_ENC_MASTER_KEY "ENCRYPTED PRIVATE KEY" //"ENCRYPTED SM9 ENC MASTER KEY" #define PEM_SM9_ENC_MASTER_PUBLIC_KEY "SM9 ENC MASTER PUBLIC KEY" -#define PEM_SM9_ENC_PRIVATE_KEY "ENCRYPTED SM9 ENC PRIVATE KEY" +#define PEM_SM9_ENC_PRIVATE_KEY "ENCRYPTED PRIVATE KEY" //"ENCRYPTED SM9 ENC PRIVATE KEY" #define SM9_MAX_ID_SIZE (SM2_MAX_ID_SIZE) @@ -87,7 +89,10 @@ int sm9_sign_master_key_info_encrypt_to_pem(const SM9_SIGN_MASTER_KEY *msk, cons int sm9_sign_master_key_info_decrypt_from_pem(SM9_SIGN_MASTER_KEY *msk, const char *pass, FILE *fp); int sm9_sign_master_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_SIGN_MASTER_KEY *msk); +#define SM9_SIGN_MASTER_PUBLIC_KEY_BYTES (1 + 32*4) // = 129 #define SM9_SIGN_MASTER_PUBLIC_KEY_SIZE 136 +int sm9_sign_master_public_key_to_bytes(const SM9_SIGN_MASTER_KEY *msk, uint8_t **out, size_t *outlen); +int sm9_sign_master_public_key_from_bytes(SM9_SIGN_MASTER_KEY *msk, const uint8_t **in, size_t *inlen); int sm9_sign_master_public_key_to_der(const SM9_SIGN_MASTER_KEY *mpk, uint8_t **out, size_t *outlen); int sm9_sign_master_public_key_from_der(SM9_SIGN_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen); int sm9_sign_master_public_key_to_pem(const SM9_SIGN_MASTER_KEY *mpk, FILE *fp); @@ -173,7 +178,10 @@ int sm9_enc_master_key_info_encrypt_to_pem(const SM9_ENC_MASTER_KEY *msk, const int sm9_enc_master_key_info_decrypt_from_pem(SM9_ENC_MASTER_KEY *msk, const char *pass, FILE *fp); int sm9_enc_master_key_print(FILE *fp, int fmt, int ind, const char *label, const SM9_ENC_MASTER_KEY *msk); +#define SM9_ENC_MASTER_PUBLIC_KEY_BYTES (1 + 32*2) // = 65 #define SM9_ENC_MASTER_PUBLIC_KEY_SIZE 70 +int sm9_enc_master_public_key_to_bytes(const SM9_ENC_MASTER_KEY *mpk, uint8_t **out, size_t *outlen); +int sm9_enc_master_public_key_from_bytes(SM9_ENC_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen); int sm9_enc_master_public_key_to_der(const SM9_ENC_MASTER_KEY *mpk, uint8_t **out, size_t *outlen); int sm9_enc_master_public_key_from_der(SM9_ENC_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen); int sm9_enc_master_public_key_to_pem(const SM9_ENC_MASTER_KEY *mpk, FILE *fp); diff --git a/include/gmssl/sphincs.h b/include/gmssl/sphincs.h index 85c0b64b..a46770a1 100644 --- a/include/gmssl/sphincs.h +++ b/include/gmssl/sphincs.h @@ -246,6 +246,9 @@ typedef struct { sphincs_hash128_t auth_path[SPHINCS_XMSS_HEIGHT]; } SPHINCS_XMSS_SIGNATURE; +#define SPHINCS_XMSS_SIGNATURE_SIZE sizeof(SPHINCS_XMSS_SIGNATURE) + + int sphincs_xmss_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const SPHINCS_XMSS_SIGNATURE *sig); int sphincs_xmss_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen); int sphincs_xmss_signature_to_bytes(const SPHINCS_XMSS_SIGNATURE *sig, uint8_t **out, size_t *outlen); @@ -291,7 +294,7 @@ typedef struct { sphincs_hash128_t auth_path[SPHINCS_FORS_NUM_TREES][SPHINCS_FORS_TREE_HEIGHT]; } SPHINCS_FORS_SIGNATURE; -#define SPHINCS_FORS_SIGNATURE_SIZE sizeof(SPHINCS_FORS_SIGNATURE) +#define SPHINCS_FORS_SIGNATURE_SIZE sizeof(SPHINCS_FORS_SIGNATURE) // = 2912 int sphincs_fors_signature_to_bytes(const SPHINCS_FORS_SIGNATURE *sig, uint8_t **out, size_t *outlen); int sphincs_fors_signature_from_bytes(SPHINCS_FORS_SIGNATURE *sig, const uint8_t **in, size_t *inlen); @@ -339,7 +342,7 @@ typedef struct { SPHINCS_XMSS_SIGNATURE xmss_sigs[SPHINCS_HYPERTREE_LAYERS]; } SPHINCS_SIGNATURE; -#define SPHINCS_SIGNATURE_SIZE sizeof(SPHINCS_SIGNATURE) +#define SPHINCS_SIGNATURE_SIZE sizeof(SPHINCS_SIGNATURE) // =7856? int sphincs_signature_to_bytes(const SPHINCS_SIGNATURE *sig, uint8_t **out, size_t *outlen); int sphincs_signature_from_bytes(SPHINCS_SIGNATURE *sig, const uint8_t **in, size_t *inlen); diff --git a/include/gmssl/x509_key.h b/include/gmssl/x509_key.h index 488da04e..03f00eb9 100644 --- a/include/gmssl/x509_key.h +++ b/include/gmssl/x509_key.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,8 @@ typedef struct { XMSSMT_KEY xmssmt_key; SPHINCS_KEY sphincs_key; KYBER_KEY kyber_key; + SM9_SIGN_MASTER_KEY sm9_sign_master_key; // OID_sm9,OID_sm9sign + SM9_SIGN_KEY sm9_sign_key; // OID_sm9sign,OID_undef } u; } X509_KEY; @@ -55,16 +58,18 @@ int x509_key_set_xmss_key(X509_KEY *x509_key, const XMSS_KEY *xmss_key); int x509_key_set_xmssmt_key(X509_KEY *x509_key, const XMSSMT_KEY *xmssmt_key); int x509_key_set_sphincs_key(X509_KEY *x509_key, const SPHINCS_KEY *sphincs_key); int x509_key_set_kyber_key(X509_KEY *x509_key, const KYBER_KEY *kyber_key); +int x509_key_set_sm9_sign_key(X509_KEY *x509_key, const SM9_SIGN_KEY *sm9_sign_key); +int x509_key_set_sm9_sign_master_key(X509_KEY *x509_key, const SM9_SIGN_MASTER_KEY *sm9_sign_master_key); /* - algor: algor_param: + algor: param paramlen ------------------------------------------------------------------------- - OID_ec_public_key OID_sm2 or OID_secp256r1 - OID_lms_hashsig lms_type - OID_hss_lms_hashsig x509_algor_param_from_lms_types(lms_types[]) - OID_xmsss_hashsig xmss_type - OID_xmsssmt_hashsig xmssmt_type - OID_sphincs_hashsig OID_undef + OID_ec_public_key OID_sm2 or OID_secp256r1 sizeof(oid) + OID_lms_hashsig lms_type sizeof(lms_type) + OID_hss_lms_hashsig lms_types[] sizeof(lms_types[]) + OID_xmsss_hashsig xmss_type sizeof(xmss_type) + OID_xmsssmt_hashsig xmssmt_type sizeof(xmssmt_type) + OID_sphincs_hashsig NULL 0 */ int x509_key_generate(X509_KEY *key, int algor, const void *param, size_t paramlen); void x509_key_cleanup(X509_KEY *key); @@ -123,21 +128,24 @@ int x509_private_key_info_from_der(X509_KEY *key, const uint8_t **attrs, size_t // TODO: no x509_private_key_info_print // PKCS #8 EncryptedPrivateKeyInfo -#define PKCS8_ENCED_PRIVATE_KEY_INFO_ITER 65536 int x509_private_key_info_encrypt_to_der(const X509_KEY *x509_key, const char *pass, uint8_t **out, size_t *outlen); int x509_private_key_info_decrypt_from_der(X509_KEY *x509_key, const uint8_t **attrs, size_t *attrs_len, const char *pass, const uint8_t **in, size_t *inlen); +// require stdio +int x509_private_key_info_encrypt_to_pem(const X509_KEY *key, const char *pass, FILE *fp); +int x509_private_key_info_decrypt_from_pem(X509_KEY *key, const uint8_t **attrs, size_t *attrslen, const char *pass, FILE *fp); +int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE *fp); // SM2_SIGNATURE_MAX_SIZE = 72 // LMS_SIGNATURE_MAX_SIZE = 1932 -// HSS_SIGNATURE_MAX_SIZE = ? +// HSS_SIGNATURE_MAX_SIZE = 9888? // XMSS_SIGNATURE_MAX_SIZE = 2820 -// XMSSMT_SIGNATURE_MAX_SIZE >= 27688 ? -// SPHINCS_SIGNATURE_SIZE = ? +// XMSSMT_SIGNATURE_MAX_SIZE = 8356? +// SPHINCS_SIGNATURE_SIZE = 7856? // ECDSA_SIGNATURE_MAX_SIZE = 72 typedef union { @@ -158,14 +166,18 @@ typedef struct { SM2_SIGN_CTX sm2_sign_ctx; SM2_VERIFY_CTX sm2_verify_ctx; ECDSA_SIGN_CTX ecdsa_sign_ctx; + SM9_SIGN_CTX sm9_sign_ctx; LMS_SIGN_CTX lms_sign_ctx; HSS_SIGN_CTX hss_sign_ctx; XMSS_SIGN_CTX xmss_sign_ctx; XMSSMT_SIGN_CTX xmssmt_sign_ctx; SPHINCS_SIGN_CTX sphincs_sign_ctx; } u; + X509_KEY key; + const void *args; + size_t argslen; int sign_algor; - uint8_t sig[X509_SIGNATURE_MAX_SIZE]; + const uint8_t *sig; size_t siglen; size_t fixed_siglen; } X509_SIGN_CTX; @@ -184,18 +196,14 @@ typedef struct { int x509_key_get_sign_algor(const X509_KEY *key, int *algor); int x509_key_get_signature_size(const X509_KEY *key, size_t *siglen); -// args, argslen: -// sm2 SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH -// TLS13_SM2_ID, TLS13_SM2_ID_LENGTH -// sphincs optiona_random, 16 - - /* - x509_sign_init argumetns + x509_sign_init x509_key->algor:algor_param ctx->sign_algor args argslen ------------------------------------------------------------------------------------------------ OID_ec_public_key:OID_sm2 OID_sm2sign_with_sm3 char *id idlen + SM2_DEFAULT_ID[_LENGTH] + TLS13_SM2_ID[_LENGTH] for TLS1.3 NULL 0 use SM2_DEFAULT_ID OID_ec_public_key:OID_secp256r1 OID_ecdsa_with_sha256 NULL 0 OID_lms_hashsig:OID_undef OID_lms_hashsig NULL 0 @@ -227,11 +235,6 @@ int x509_key_encapsulate(const X509_KEY *key, uint8_t *ciphertext, size_t *ciphe int x509_key_decapsulate(const X509_KEY *key, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t secret[32]); -// require stdio -int x509_private_key_info_encrypt_to_pem(const X509_KEY *key, const char *pass, FILE *fp); -int x509_private_key_info_decrypt_from_pem(X509_KEY *key, const uint8_t **attrs, size_t *attrslen, const char *pass, FILE *fp); -int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE *fp); - #ifdef __cplusplus } diff --git a/src/sm9_key.c b/src/sm9_key.c index bf92ce30..4563fa73 100644 --- a/src/sm9_key.c +++ b/src/sm9_key.c @@ -106,6 +106,40 @@ int sm9_sign_master_key_from_der(SM9_SIGN_MASTER_KEY *msk, const uint8_t **in, s return 1; } +int sm9_sign_master_public_key_to_bytes(const SM9_SIGN_MASTER_KEY *mpk, uint8_t **out, size_t *outlen) +{ + if (!mpk || !outlen) { + error_print(); + return -1; + } + if (out && *out) { + sm9_z256_twist_point_to_uncompressed_octets(&mpk->Ppubs, *out); + *out += 1 + 32 * 4; + } + *outlen += 1 + 32 * 4; + return 1; +} + +int sm9_sign_master_public_key_from_bytes(SM9_SIGN_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen) +{ + if (!mpk || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (*inlen < 1 + 32 * 4) { + error_print(); + return -1; + } + memset(mpk, 0, sizeof(SM9_SIGN_MASTER_KEY)); + if (sm9_z256_twist_point_from_uncompressed_octets(&mpk->Ppubs, *in) != 1) { + error_print(); + return -1; + } + *in += 1 + 32 * 4; + *inlen -= 1 + 32 * 4; + return 1; +} + int sm9_sign_master_public_key_to_der(const SM9_SIGN_MASTER_KEY *mpk, uint8_t **out, size_t *outlen) { uint8_t Ppubs[1 + 32 * 4]; @@ -258,6 +292,40 @@ int sm9_enc_master_key_from_der(SM9_ENC_MASTER_KEY *msk, const uint8_t **in, siz return 1; } +int sm9_enc_master_public_key_to_bytes(const SM9_ENC_MASTER_KEY *mpk, uint8_t **out, size_t *outlen) +{ + if (!mpk || !outlen) { + error_print(); + return -1; + } + if (out && *out) { + sm9_z256_point_to_uncompressed_octets(&mpk->Ppube, *out); + *out += 1 + 32 * 2; + } + *outlen += 1 + 32 * 2; + return 1; +} + +int sm9_enc_master_public_key_from_bytes(SM9_ENC_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen) +{ + if (!mpk || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (*inlen < 1 + 32 * 2) { + error_print(); + return -1; + } + memset(mpk, 0, sizeof(SM9_ENC_MASTER_KEY)); + if (sm9_z256_point_from_uncompressed_octets(&mpk->Ppube, *in) != 1) { + error_print(); + return -1; + } + *in += 1 + 32 * 2; + *inlen -= 1 + 32 * 2; + return 1; +} + int sm9_enc_master_public_key_to_der(const SM9_ENC_MASTER_KEY *mpk, uint8_t **out, size_t *outlen) { uint8_t Ppube[1 + 32 * 2]; diff --git a/src/x509_alg.c b/src/x509_alg.c index 864e0bf1..06fbae67 100644 --- a/src/x509_alg.c +++ b/src/x509_alg.c @@ -245,6 +245,13 @@ err: } +#define oid_sm9_algor oid_sm_algors,302 +static uint32_t oid_sm9[] = { oid_sm9_algor }; +static uint32_t oid_sm9sign[] = { oid_sm9_algor,1 }; +static uint32_t oid_sm9keyagreement[] = { oid_sm9_algor,2 }; +static uint32_t oid_sm9encrypt[] = { oid_sm9_algor,3 }; + + static uint32_t oid_sm2sign_with_sm3[] = { 1,2,156,10197,1,501 }; static uint32_t oid_rsasign_with_sm3[] = { 1,2,156,10197,1,504 }; static uint32_t oid_ecdsa_with_sha1[] = { 1,2,840,10045,4,1 }; @@ -355,6 +362,7 @@ from RFC 5758 Internet X.509 Public Key Infrastructure: static const ASN1_OID_INFO x509_sign_algors[] = { { OID_sm2sign_with_sm3, "sm2sign-with-sm3", oid_sm2sign_with_sm3, sizeof(oid_sm2sign_with_sm3)/sizeof(int), SM2_SIGN_ALGOR_FLAGS }, + { OID_sm9sign, "sm9sign", oid_sm9sign, sizeof(oid_sm9sign)/sizeof(int), 1 }, { OID_rsasign_with_sm3, "rsasign-with-sm3", oid_rsasign_with_sm3, sizeof(oid_rsasign_with_sm3)/sizeof(int), 1 }, { OID_ecdsa_with_sha1, "ecdsa-with-sha1", oid_ecdsa_with_sha1, sizeof(oid_ecdsa_with_sha1)/sizeof(int), 0 }, { OID_ecdsa_with_sha224, "ecdsa-with-sha224", oid_ecdsa_with_sha224, sizeof(oid_ecdsa_with_sha224)/sizeof(int), 0 } , @@ -488,6 +496,7 @@ static uint32_t oid_rsaes_oaep[] = { 1,2,840,113549,1,1,7 }; static const ASN1_OID_INFO x509_pke_algors[] = { { OID_sm2encrypt, "sm2encrypt", oid_sm2encrypt, sizeof(oid_sm2encrypt)/sizeof(int) }, + { OID_sm9encrypt, "sm9encrypt", oid_sm9encrypt, sizeof(oid_sm9encrypt)/sizeof(int) }, { OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int) }, { OID_rsaes_oaep, "rsaesOAEP", oid_rsaes_oaep, sizeof(oid_rsaes_oaep)/sizeof(int) }, }; @@ -592,18 +601,13 @@ static uint32_t oid_ec_public_key[] = { oid_x9_62,2,1 }; static const ASN1_OID_INFO x509_public_key_algors[] = { { OID_ec_public_key, "ecPublicKey", oid_ec_public_key, sizeof(oid_ec_public_key)/sizeof(int), 0, "X9.62 ecPublicKey" }, + { OID_sm9, "sm9", oid_sm9, sizeof(oid_sm9)/sizeof(int), 0, "SM9" }, { OID_rsa_encryption, "rsaEncryption", oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), 0, "RSAEncryption" }, -#ifdef ENABLE_LMS { OID_lms_hashsig, "lms-hashsig", oid_lms_hashsig, sizeof(oid_lms_hashsig)/sizeof(int), 0, "HSS/LMS HashSig" }, { OID_hss_lms_hashsig, "hss-lms-hashsig", oid_hss_lms_hashsig, sizeof(oid_hss_lms_hashsig)/sizeof(int), 0, "HSS/LMS HashSig" }, -#endif -#ifdef ENABLE_XMSS { OID_xmss_hashsig, "xmss-hashsig", oid_xmss_hashsig, sizeof(oid_xmss_hashsig)/sizeof(int), 1 }, { OID_xmssmt_hashsig, "xmssmt-hashsig", oid_xmssmt_hashsig, sizeof(oid_xmssmt_hashsig)/sizeof(int), 1 }, -#endif -#ifdef ENABLE_SPHINCS { OID_sphincs_hashsig, "sphincs-hashsig", oid_sphincs_hashsig, sizeof(oid_sphincs_hashsig)/sizeof(int), 1 }, -#endif { OID_kyber_kem, "kyber-kem", oid_kyber_kem, sizeof(oid_kyber_kem)/sizeof(int), 1 }, }; @@ -630,7 +634,6 @@ int x509_public_key_algor_from_name(const char *name) return info->oid; } -// FIXME: add kyber, and use same code for LMS/XMSS/SPHINCS... int x509_public_key_algor_to_der(int oid, int curve_or_null, uint8_t **out, size_t *outlen) { size_t len = 0; @@ -646,6 +649,17 @@ int x509_public_key_algor_to_der(int oid, int curve_or_null, uint8_t **out, size return -1; } break; + case OID_sm9: + if (asn1_object_identifier_to_der(oid_sm9, sizeof(oid_sm9)/sizeof(int), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_object_identifier_to_der(oid_sm9, sizeof(oid_sm9)/sizeof(int), out, outlen) != 1) { + error_print(); + return -1; + } + break; + + + case OID_rsa_encryption: if (asn1_object_identifier_to_der(oid_rsa_encryption, sizeof(oid_rsa_encryption)/sizeof(int), NULL, &len) != 1 || asn1_null_to_der(NULL, &len) != 1 @@ -773,14 +787,11 @@ int x509_public_key_algor_from_der(int *oid , int *curve_or_null, const uint8_t *curve_or_null = OID_undef; break; -#ifdef ENABLE_LMS + case OID_sm9: case OID_lms_hashsig: case OID_hss_lms_hashsig: -#endif -#ifdef ENABLE_XMSS case OID_xmss_hashsig: case OID_xmssmt_hashsig: -#endif case OID_sphincs_hashsig: case OID_kyber_kem: // for hashsigs, parmaeters is set to empty @@ -817,15 +828,12 @@ int x509_public_key_algor_print(FILE *fp, int fmt, int ind, const char *label, c if (ec_named_curve_from_der(&val, &d, &dlen) != 1) goto err; format_print(fp, fmt, ind, "namedCurve: %s\n", ec_named_curve_name(val)); break; + case OID_sm9: case OID_rsa_encryption: -#ifdef ENABLE_LMS case OID_lms_hashsig: case OID_hss_lms_hashsig: -#endif -#ifdef ENABLE_XMSS case OID_xmss_hashsig: case OID_xmssmt_hashsig: -#endif case OID_sphincs_hashsig: if ((val = asn1_null_from_der(&d, &dlen)) < 0) goto err; else if (val) format_print(fp, fmt, ind, "parameters: %s\n", asn1_null_name()); diff --git a/src/x509_key.c b/src/x509_key.c index 1cf8eb0b..d9ab3437 100644 --- a/src/x509_key.c +++ b/src/x509_key.c @@ -130,6 +130,32 @@ int x509_key_set_kyber_key(X509_KEY *x509_key, const KYBER_KEY *kyber_key) return 1; } +int x509_key_set_sm9_sign_master_key(X509_KEY *x509_key, const SM9_SIGN_MASTER_KEY *sm9_sign_master_key) +{ + if (!x509_key || !sm9_sign_master_key) { + error_print(); + return -1; + } + memset(x509_key, 0, sizeof(X509_KEY)); + x509_key->algor = OID_sm9; + x509_key->algor_param = OID_sm9sign; + x509_key->u.sm9_sign_master_key = *sm9_sign_master_key; + return 1; +} + +int x509_key_set_sm9_sign_key(X509_KEY *x509_key, const SM9_SIGN_KEY *sm9_sign_key) +{ + if (!x509_key || !sm9_sign_key) { + error_print(); + return -1; + } + memset(x509_key, 0, sizeof(X509_KEY)); + x509_key->algor = OID_sm9sign; + x509_key->algor_param = OID_undef; + x509_key->u.sm9_sign_key = *sm9_sign_key; + return 1; +} + int x509_key_generate(X509_KEY *key, int algor, const void *param, size_t paramlen) { int param_val; @@ -184,6 +210,9 @@ int x509_key_generate(X509_KEY *key, int algor, const void *param, size_t paraml return -1; } break; + case OID_sm9: + error_print(); + return -1; default: error_print(); return -1; @@ -246,6 +275,7 @@ int x509_key_generate(X509_KEY *key, int algor, const void *param, size_t paraml return -1; } break; + case OID_sm9: default: error_print(); return -1; @@ -289,6 +319,19 @@ void x509_key_cleanup(X509_KEY *key) case OID_kyber_kem: kyber_key_cleanup(&key->u.kyber_key); break; + case OID_sm9: + switch (key->algor_param) { + case OID_sm9sign: + gmssl_secure_clear(&key->u.sm9_sign_master_key, sizeof(SM9_SIGN_MASTER_KEY)); + break; + default: + error_print(); + return; + } + break; + case OID_sm9sign: + gmssl_secure_clear(&key->u.sm9_sign_key, sizeof(SM9_SIGN_KEY)); + break; default: error_print(); } @@ -360,6 +403,22 @@ int x509_public_key_to_bytes(const X509_KEY *key, uint8_t **out, size_t *outlen) return -1; } break; + case OID_sm9: + switch (key->algor_param) { + case OID_sm9sign: + if (sm9_sign_master_public_key_to_bytes(&key->u.sm9_sign_master_key, out, outlen) != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + break; + case OID_sm9sign: + error_print(); + return -1; default: error_print(); return -1; @@ -446,6 +505,22 @@ int x509_public_key_from_bytes(X509_KEY *key, int algor, int algor_param, const return -1; } break; + case OID_sm9: + switch (key->algor_param) { + case OID_sm9sign: + if (sm9_sign_master_public_key_from_bytes(&key->u.sm9_sign_master_key, in, inlen) != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + break; + case OID_sm9sign: + error_print(); + return -1; default: error_print(); return -1; @@ -544,6 +619,25 @@ int x509_public_key_equ(const X509_KEY *key, const X509_KEY *pub) return 0; } break; + case OID_sm9: + switch (key->algor_param) { + case OID_sm9sign: + if (memcmp(&key->u.sm9_sign_master_key, &pub->u.sm9_sign_master_key, sizeof(SM9_SIGN_MASTER_KEY)) != 0) { + error_print(); + return 0; + } + break; + default: + error_print(); + return -1; + } + break; + case OID_sm9sign: + if (memcmp(&key->u.sm9_sign_key, &pub->u.sm9_sign_key, sizeof(SM9_SIGN_KEY)) != 0) { + error_print(); + return 0; + } + break; default: error_print(); return -1; @@ -606,6 +700,23 @@ int x509_public_key_print(FILE *fp, int fmt, int ind, const char *label, const X return -1; } break; + case OID_sm9: + switch (key->algor_param) { + case OID_sm9sign: + if (sm9_sign_master_public_key_print(fp, fmt, ind, label, &key->u.sm9_sign_master_key) != 1) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + break; + case OID_sm9sign: + // TODO: no public key, do we need print ID? + error_print(); + return -1; default: error_print(); return -1; @@ -699,6 +810,9 @@ int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, co case OID_rsa_encryption: rsa_public_key_print(fp, fmt, ind, "RSAPublicKey", p, len); break; + case OID_sm9: + error_print(); + break; case OID_lms_hashsig: case OID_hss_lms_hashsig: case OID_xmss_hashsig: @@ -948,6 +1062,7 @@ int x509_private_key_info_to_der(const X509_KEY *key, uint8_t **out, size_t *out case OID_xmssmt_hashsig: case OID_sphincs_hashsig: case OID_kyber_kem: + case OID_sm9: // TODO: support these algors, (MUST change private_key[] size)! default: error_print(); @@ -1007,12 +1122,27 @@ int x509_private_key_info_from_der(X509_KEY *key, const uint8_t **attrs, size_t return -1; } break; + case OID_sm9sign: + if (algor_param != OID_undef) { + error_print(); + return -1; + } + memset(key, 0, sizeof(X509_KEY)); + key->algor = algor; + key->algor_param = algor_param; + if (sm9_sign_key_from_der(&key->u.sm9_sign_key, &private_key, &private_key_len) != 1 + || asn1_length_is_zero(private_key_len) != 1) { + error_print(); + return -1; + } + break; case OID_lms_hashsig: case OID_hss_lms_hashsig: case OID_xmss_hashsig: case OID_xmssmt_hashsig: case OID_sphincs_hashsig: case OID_kyber_kem: + case OID_sm9: default: error_print(); return -1; @@ -1311,6 +1441,16 @@ int x509_key_get_sign_algor(const X509_KEY *key, int *algor) return -1; } break; + case OID_sm9: + switch (key->algor_param) { + case OID_sm9sign: + *algor = OID_sm9sign; + break; + default: + error_print(); + return -1; + } + break; case OID_lms_hashsig: case OID_hss_lms_hashsig: case OID_xmss_hashsig: @@ -1332,6 +1472,9 @@ int x509_key_get_signature_size(const X509_KEY *key, size_t *siglen) case OID_ec_public_key: *siglen = SM2_signature_max_size; break; + case OID_sm9: + *siglen = SM9_SIGNATURE_SIZE; + break; case OID_lms_hashsig: if (lms_key_get_signature_size(&key->u.lms_key, siglen) != 1) { error_print(); @@ -1360,6 +1503,8 @@ int x509_key_get_signature_size(const X509_KEY *key, size_t *siglen) *siglen = SPHINCS_SIGNATURE_SIZE; break; case OID_kyber_kem: + error_print(); + return -1; default: error_print(); return -1; @@ -1374,6 +1519,7 @@ int x509_sign_init(X509_SIGN_CTX *ctx, X509_KEY *key, const void *args, size_t a return -1; } switch (key->algor) { + case OID_sm9: case OID_lms_hashsig: case OID_hss_lms_hashsig: case OID_xmss_hashsig: @@ -1460,6 +1606,18 @@ int x509_sign_init(X509_SIGN_CTX *ctx, X509_KEY *key, const void *args, size_t a } ctx->sign_algor = key->algor; break; + case OID_sm9sign: + if (key->algor_param != OID_undef) { + error_print(); + return -1; + } + if (sm9_sign_init(&ctx->u.sm9_sign_ctx) != 1) { + error_print(); + return -1; + } + ctx->key = *key; + ctx->sign_algor = OID_sm9sign; + break; default: error_print(); return -1; @@ -1487,6 +1645,7 @@ int x509_sign_set_signature_size(X509_SIGN_CTX *ctx, size_t siglen) error_print(); return -1; } + break; default: error_print(); return -1; @@ -1514,6 +1673,12 @@ int x509_sign_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) return -1; } break; + case OID_sm9sign: + if (sm9_sign_update(&ctx->u.sm9_sign_ctx, data, datalen) != 1) { + error_print(); + return -1; + } + break; case OID_lms_hashsig: if (lms_sign_update(&ctx->u.lms_sign_ctx, data, datalen) != 1) { error_print(); @@ -1583,6 +1748,12 @@ int x509_sign_finish(X509_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) } } break; + case OID_sm9sign: + if (sm9_sign_finish(&ctx->u.sm9_sign_ctx, &ctx->key.u.sm9_sign_key, sig, siglen) != 1) { + error_print(); + return -1; + } + break; case OID_lms_hashsig: if (lms_sign_finish(&ctx->u.lms_sign_ctx, sig, siglen) != 1) { error_print(); @@ -1631,6 +1802,7 @@ int x509_sign(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen, uint8_t * switch (ctx->sign_algor) { case OID_sm2sign_with_sm3: case OID_ecdsa_with_sha256: + case OID_sm9sign: case OID_lms_hashsig: case OID_hss_lms_hashsig: case OID_xmss_hashsig: @@ -1672,9 +1844,20 @@ int x509_verify_init(X509_SIGN_CTX *ctx, const X509_KEY *key, const void *args, error_print(); return -1; } - if (args && key->algor != OID_ec_public_key) { - error_print(); - return -1; + switch (key->algor) { + case OID_sm9: + if (!args || !argslen) { + error_print(); + return -1; + } + break; + case OID_ec_public_key: + break; + default: + if (args) { + error_print(); + return -1; + } } switch (key->algor) { @@ -1694,11 +1877,7 @@ int x509_verify_init(X509_SIGN_CTX *ctx, const X509_KEY *key, const void *args, return -1; } ctx->sign_algor = OID_sm2sign_with_sm3; - if (siglen > sizeof(ctx->sig)) { - error_print(); - return -1; - } - memcpy(ctx->sig, sig, siglen); + ctx->sig = sig; ctx->siglen = siglen; break; case OID_secp256r1: @@ -1713,6 +1892,22 @@ int x509_verify_init(X509_SIGN_CTX *ctx, const X509_KEY *key, const void *args, return -1; } break; + case OID_sm9: + if (key->algor_param != OID_sm9sign) { + error_print(); + return -1; + } + if (sm9_verify_init(&ctx->u.sm9_sign_ctx) != 1) { + error_print(); + return -1; + } + ctx->key = *key; + ctx->sign_algor = OID_sm9sign; + ctx->args = args; + ctx->argslen = argslen; + ctx->sig = sig; + ctx->siglen = siglen; + break; case OID_lms_hashsig: if (lms_verify_init(&ctx->u.lms_sign_ctx, &key->u.lms_key, sig, siglen) != 1) { error_print(); @@ -1770,6 +1965,12 @@ int x509_verify_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) return -1; } break; + case OID_sm9sign: + if (sm9_verify_update(&ctx->u.sm9_sign_ctx, data, datalen) != 1) { + error_print(); + return -1; + } + break; case OID_lms_hashsig: if (lms_verify_update(&ctx->u.lms_sign_ctx, data, datalen) != 1) { error_print(); @@ -1808,6 +2009,8 @@ int x509_verify_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) int x509_verify_finish(X509_SIGN_CTX *ctx) { int ret; + const char *id; + size_t idlen; switch (ctx->sign_algor) { case OID_sm2sign_with_sm3: @@ -1822,6 +2025,19 @@ int x509_verify_finish(X509_SIGN_CTX *ctx) return -1; } break; + case OID_sm9sign: + id = ctx->args; + idlen = ctx->argslen; + + fprintf(stderr, "id = %s, idlen = %zu\n", id, idlen); + sm9_sign_master_key_print(stderr, 0, 4, "master_key", &ctx->key.u.sm9_sign_master_key); + + if ((ret = sm9_verify_finish(&ctx->u.sm9_sign_ctx, ctx->sig, ctx->siglen, + &ctx->key.u.sm9_sign_master_key, id, idlen)) < 0) { + error_print(); + return -1; + } + break; case OID_lms_hashsig: if ((ret = lms_verify_finish(&ctx->u.lms_sign_ctx)) < 0) { error_print(); @@ -1871,6 +2087,7 @@ int x509_verify(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) case OID_hss_lms_hashsig: case OID_xmss_hashsig: case OID_xmssmt_hashsig: + case OID_sm9sign: if (x509_verify_update(ctx, data, datalen) != 1) { error_print(); return -1; @@ -1922,6 +2139,8 @@ void x509_sign_ctx_cleanup(X509_SIGN_CTX *ctx) case OID_sphincs_hashsig: sphincs_sign_ctx_cleanup(&ctx->u.sphincs_sign_ctx); break; + case OID_sm9sign: + gmssl_secure_clear(&ctx->u.sm9_sign_ctx, sizeof(SM9_SIGN_CTX)); } memset(ctx, 0, sizeof(X509_SIGN_CTX)); } diff --git a/tests/lmstest.c b/tests/lmstest.c index d6fe59d5..d1253bbe 100644 --- a/tests/lmstest.c +++ b/tests/lmstest.c @@ -22,6 +22,22 @@ static int lms_types[] = { LMS_HASH256_M32_H5, }; +static int test_print_consts(void) +{ + format_print(stderr, 0, 4, "sizeof(LMS_PUBLIC_KEY): %zu\n", sizeof(LMS_PUBLIC_KEY)); + format_print(stderr, 0, 4, "LMS_PUBLIC_KEY_SIZE: %zu\n", LMS_PUBLIC_KEY_SIZE); + format_print(stderr, 0, 4, "LMS_PRIVATE_KEY_SIZE: %zu\n", LMS_PRIVATE_KEY_SIZE); + format_print(stderr, 0, 4, "sizeof(LMS_SIGNATURE): %zu\n", sizeof(LMS_SIGNATURE)); + format_print(stderr, 0, 4, "LMS_SIGNATURE_MAX_SIZE: %zu\n", LMS_SIGNATURE_MAX_SIZE); + format_print(stderr, 0, 4, "sizeof(HSS_PUBLIC_KEY): %zu\n", sizeof(HSS_PUBLIC_KEY)); + format_print(stderr, 0, 4, "HSS_PUBLIC_KEY_SIZE: %zu\n", HSS_PUBLIC_KEY_SIZE); + format_print(stderr, 0, 4, "HSS_PRIVATE_KEY_MAX_SIZE: %zu\n", HSS_PRIVATE_KEY_MAX_SIZE); + format_print(stderr, 0, 4, "sizeof(HSS_SIGNATURE): %zu\n", sizeof(HSS_SIGNATURE)); + format_print(stderr, 0, 4, "HSS_SIGNATURE_MAX_SIZE: %zu\n", HSS_SIGNATURE_MAX_SIZE); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} #if defined(ENABLE_LMS_CROSSCHECK) && defined(ENABLE_SHA2) static int test_rfc8554_test1(void) @@ -1030,6 +1046,7 @@ static int test_hss_public_key_algor(void) int main(void) { + if (test_print_consts() != 1) goto err; #if defined(ENABLE_LMS_CROSSCHECK) && defined(ENABLE_SHA2) if (test_rfc8554_test1() != 1) goto err; #endif diff --git a/tests/x509_keytest.c b/tests/x509_keytest.c index d0992622..e762606e 100644 --- a/tests/x509_keytest.c +++ b/tests/x509_keytest.c @@ -375,6 +375,7 @@ static int test_x509_sign(void) error_print(); return -1; } + format_print(stderr, 0, 4, "%s: %zu\n", x509_public_key_algor_name(tests[i].algor), siglen); if (x509_verify_init(&sign_ctx, &x509_keys[i], args, argslen, sig, siglen) != 1) { error_print(); return -1; @@ -389,6 +390,65 @@ static int test_x509_sign(void) return 1; } +static int test_x509_sign_sm9(void) +{ + SM9_SIGN_MASTER_KEY sm9_sign_master_key; + SM9_SIGN_KEY sm9_sign_key; + char *id = "guan@pku.edu.cn"; + size_t idlen = strlen(id); + X509_KEY x509_key; + X509_SIGN_CTX sign_ctx; + uint8_t msg[66]; + uint8_t sig[128]; // sm9 signature size = 104 + size_t siglen; + + if (sm9_sign_master_key_generate(&sm9_sign_master_key) != 1) { + error_print(); + return -1; + } + if (sm9_sign_master_key_extract_key(&sm9_sign_master_key, id, idlen, &sm9_sign_key) != 1) { + error_print(); + return -1; + } + + if (x509_key_set_sm9_sign_key(&x509_key, &sm9_sign_key) != 1) { + error_print(); + return -1; + } + if (x509_sign_init(&sign_ctx, &x509_key, NULL, 0) != 1) { + error_print(); + return -1; + } + if (x509_sign_update(&sign_ctx, msg, sizeof(msg)) != 1) { + error_print(); + return -1; + } + if (x509_sign_finish(&sign_ctx, sig, &siglen) != 1) { + error_print(); + return -1; + } + + if (x509_key_set_sm9_sign_master_key(&x509_key, &sm9_sign_master_key) != 1) { + error_print(); + return -1; + } + if (x509_verify_init(&sign_ctx, &x509_key, id, idlen, sig, siglen) != 1) { + error_print(); + return -1; + } + if (x509_verify_update(&sign_ctx, msg, sizeof(msg)) != 1) { + error_print(); + return -1; + } + if (x509_verify_finish(&sign_ctx) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + static int test_x509_key_exchange(void) { X509_KEY key; @@ -510,6 +570,7 @@ int main(void) if (test_x509_private_key_info_encrypt_to_der() != 1) goto err; if (test_x509_private_key_info_encrypt_to_pem() != 1) goto err; if (test_x509_sign() != 1) goto err; + if (test_x509_sign_sm9() != 1) goto err; if (test_x509_key_exchange() != 1) goto err; if (test_x509_kem() != 1) goto err; diff --git a/tools/sm9keygen.c b/tools/sm9keygen.c index b84a4f59..3fc701c1 100644 --- a/tools/sm9keygen.c +++ b/tools/sm9keygen.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2024 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2026 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -23,9 +23,11 @@ static const char *options = "Options\n" "\n" " -alg sm9sign|sm9encrypt Generate maeter key for sm9sign or sm9encrypt\n" -" -pass pass Password to encrypt the master private key\n" -" -out pem Output password-encrypted master private key in PEM format\n" -" -pubout pem Output master public key in PEM format\n" +" -in pem SM9 master private key in PEM format\n" +" -inpass pass Password to decrypt the master private key\n" +" -id str User's identity\n" +" -out pem Output password-encrypted user's private key in PEM format\n" +" -outpass pass Password to encrypt user's private key\n" "\n" "Examples\n" "\n"