From 8bd870d35471037ef6c917fc10510f9af203ab8f Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Thu, 25 Jun 2026 10:37:57 +0800 Subject: [PATCH] Update EDSA --- CMakeLists.txt | 16 +- include/gmssl/ec.h | 20 ++ include/gmssl/ecdsa.h | 46 +-- include/gmssl/secp256r1_ecdsa.h | 79 +++++ include/gmssl/secp384r1_ecdsa.h | 79 +++++ include/gmssl/secp384r1_key.h | 63 ++++ include/gmssl/version.h | 2 +- include/gmssl/x509_key.h | 6 +- src/ec_ecdsa.c | 180 ++++++++++ src/ecdh.c | 62 ++++ src/ecdsa.c | 76 ++--- src/secp384r1_ecdsa.c | 461 +++++++++++++++++++++++++ src/secp384r1_key.c | 587 ++++++++++++++++++++++++++++++++ src/x509_key.c | 14 +- tests/ecdsatest.c | 58 +++- tests/secp384r1_ecdsatest.c | 213 ++++++++++++ tests/secp384r1_keytest.c | 329 ++++++++++++++++++ 17 files changed, 2192 insertions(+), 99 deletions(-) create mode 100644 include/gmssl/secp256r1_ecdsa.h create mode 100644 include/gmssl/secp384r1_ecdsa.h create mode 100644 include/gmssl/secp384r1_key.h create mode 100644 src/ec_ecdsa.c create mode 100644 src/secp384r1_ecdsa.c create mode 100644 src/secp384r1_key.c create mode 100644 tests/secp384r1_ecdsatest.c create mode 100644 tests/secp384r1_keytest.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ad1ecabe..d1c42e51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -542,12 +542,20 @@ endif() if (ENABLE_SECP384R1) message(STATUS "ENABLE_SECP384R1 is ON") + if (NOT ENABLE_SHA2) + message(STATUS "ENABLE_SECP384R1 requires ENABLE_SHA2; enabling ENABLE_SHA2") + set(ENABLE_SHA2 ON) + endif() add_definitions(-DENABLE_SECP384R1) if (NOT ENABLE_SECP256R1) - list(APPEND src src/bn.c) + list(APPEND src src/bn.c src/ecdh.c) endif() - list(APPEND src src/secp384r1.c) - list(APPEND tests secp384r1) + list(APPEND src src/secp384r1.c src/secp384r1_key.c src/secp384r1_ecdsa.c) + list(APPEND tests secp384r1 secp384r1_key secp384r1_ecdsa) +endif() + +if (ENABLE_SECP256R1 OR ENABLE_SECP384R1) + list(APPEND src src/ec_ecdsa.c) endif() @@ -1016,7 +1024,7 @@ endif() # set(CPACK_PACKAGE_NAME "GmSSL") set(CPACK_PACKAGE_VENDOR "GmSSL develop team") -set(CPACK_PACKAGE_VERSION "3.3.0-dev.1170") +set(CPACK_PACKAGE_VERSION "3.3.0-dev.1171") set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) set(CPACK_NSIS_MODIFY_PATH ON) include(CPack) diff --git a/include/gmssl/ec.h b/include/gmssl/ec.h index 91adc44e..bc64a708 100644 --- a/include/gmssl/ec.h +++ b/include/gmssl/ec.h @@ -18,6 +18,12 @@ #include #include #include +#ifdef ENABLE_SECP256R1 +#include +#endif +#ifdef ENABLE_SECP384R1 +#include +#endif #include @@ -39,11 +45,25 @@ int ec_named_curve_from_name(const char *name); int ec_named_curve_to_der(int curve, uint8_t **out, size_t *outlen); int ec_named_curve_from_der(int *curve, const uint8_t **in, size_t *inlen); +typedef struct { + int oid; + union { +#ifdef ENABLE_SECP256R1 + SECP256R1_KEY secp256r1_key; +#endif +#ifdef ENABLE_SECP384R1 + SECP384R1_KEY secp384r1_key; +#endif + int unused; + } u; +} EC_KEY; + /* ECPoint ::= OCTET STRING -- uncompressed point */ int ec_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + /* ECPrivateKey ::= SEQUENCE { version INTEGER, -- value MUST be (1) diff --git a/include/gmssl/ecdsa.h b/include/gmssl/ecdsa.h index 80d5af5e..05b8f490 100644 --- a/include/gmssl/ecdsa.h +++ b/include/gmssl/ecdsa.h @@ -7,16 +7,13 @@ * http://www.apache.org/licenses/LICENSE-2.0 */ - #ifndef GMSSL_ECDSA_H #define GMSSL_ECDSA_H -#include #include #include -#include -#include +#include #ifdef __cplusplus @@ -24,43 +21,12 @@ extern "C" { #endif -typedef struct { - secp256r1_t r; - secp256r1_t s; -} ECDSA_SIGNATURE; - -#define ECDSA_SIGNATURE_COMPACT_SIZE 70 -#define ECDSA_SIGNATURE_TYPICAL_SIZE 71 -#define ECDSA_SIGNATURE_MAX_SIZE 72 - -int ecdsa_signature_to_der(const ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen); -int ecdsa_signature_from_der(ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen); -int ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const ECDSA_SIGNATURE *sig); -int ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen); - -int ecdsa_do_sign_ex(const SECP256R1_KEY *key, const secp256r1_t k, const uint8_t dgst[32], ECDSA_SIGNATURE *sig); -int ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], ECDSA_SIGNATURE *sig); -int ecdsa_do_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const ECDSA_SIGNATURE *sig); -int ecdsa_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen); -int ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig); -int ecdsa_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const uint8_t *sig, size_t siglen); - - -typedef struct { - DIGEST_CTX digest_ctx; - SECP256R1_KEY key; - ECDSA_SIGNATURE sig; -} ECDSA_SIGN_CTX; - -int ecdsa_sign_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST *digest); -int ecdsa_sign_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); -int ecdsa_sign_finish(ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen); -int ecdsa_sign_finish_fixlen(ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig); -int ecdsa_verify_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST *digest, +int ecdsa_sign(const EC_KEY *key, const uint8_t *dgst, size_t dgstlen, + uint8_t *sig, size_t *siglen); +int ecdsa_sign_fixed_len(const EC_KEY *key, const uint8_t *dgst, size_t dgstlen, + size_t siglen, uint8_t *sig); +int ecdsa_verify(const EC_KEY *key, const uint8_t *dgst, size_t dgstlen, const uint8_t *sig, size_t siglen); -int ecdsa_verify_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); -int ecdsa_verify_finish(ECDSA_SIGN_CTX *ctx); - #ifdef __cplusplus diff --git a/include/gmssl/secp256r1_ecdsa.h b/include/gmssl/secp256r1_ecdsa.h new file mode 100644 index 00000000..77dc9841 --- /dev/null +++ b/include/gmssl/secp256r1_ecdsa.h @@ -0,0 +1,79 @@ +/* + * 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. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SECP256R1_ECDSA_H +#define GMSSL_SECP256R1_ECDSA_H + + +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +// 不应该在保留一个独立的SECP256R1_ECDSA_SIGNATURE类型,应该直接输出紧凑的二进制,实际上一般来说总是输出DER +typedef struct { + secp256r1_t r; + secp256r1_t s; +} SECP256R1_ECDSA_SIGNATURE; + +#define SECP256R1_ECDSA_SIGNATURE_COMPACT_SIZE 70 +#define SECP256R1_ECDSA_SIGNATURE_TYPICAL_SIZE 71 +#define SECP256R1_ECDSA_SIGNATURE_MAX_SIZE 72 + +// 这几个函数应都去掉,不再开放底层的类型了 +int secp256r1_ecdsa_signature_to_der(const SECP256R1_ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen); +int secp256r1_ecdsa_signature_from_der(SECP256R1_ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen); +int secp256r1_ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_ECDSA_SIGNATURE *sig); + + + +int secp256r1_ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen); + + +int secp256r1_ecdsa_do_sign_ex(const SECP256R1_KEY *key, const secp256r1_t k, const uint8_t dgst[32], SECP256R1_ECDSA_SIGNATURE *sig); +int secp256r1_ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], SECP256R1_ECDSA_SIGNATURE *sig); +int secp256r1_ecdsa_do_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const SECP256R1_ECDSA_SIGNATURE *sig); + + +// 这个函数应该改为将key的类型编程通用支持P256, P384的,摘要可以支持不同长度的 +int secp256r1_ecdsa_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen); +int secp256r1_ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig); +int secp256r1_ecdsa_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const uint8_t *sig, size_t siglen); + + +// 后面的CTX就没有意义了 +typedef struct { + DIGEST_CTX digest_ctx; + SECP256R1_KEY key; + SECP256R1_ECDSA_SIGNATURE sig; +} SECP256R1_ECDSA_SIGN_CTX; + +int secp256r1_ecdsa_sign_init(SECP256R1_ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST *digest); +int secp256r1_ecdsa_sign_update(SECP256R1_ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int secp256r1_ecdsa_sign_finish(SECP256R1_ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen); +int secp256r1_ecdsa_sign_finish_fixlen(SECP256R1_ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig); +int secp256r1_ecdsa_verify_init(SECP256R1_ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST *digest, + const uint8_t *sig, size_t siglen); +int secp256r1_ecdsa_verify_update(SECP256R1_ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int secp256r1_ecdsa_verify_finish(SECP256R1_ECDSA_SIGN_CTX *ctx); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/gmssl/secp384r1_ecdsa.h b/include/gmssl/secp384r1_ecdsa.h new file mode 100644 index 00000000..4118811c --- /dev/null +++ b/include/gmssl/secp384r1_ecdsa.h @@ -0,0 +1,79 @@ +/* + * 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. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#ifndef GMSSL_SECP384R1_ECDSA_H +#define GMSSL_SECP384R1_ECDSA_H + + +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +// 不应该在保留一个独立的SECP384R1_ECDSA_SIGNATURE类型,应该直接输出紧凑的二进制,实际上一般来说总是输出DER +typedef struct { + secp384r1_t r; + secp384r1_t s; +} SECP384R1_ECDSA_SIGNATURE; + +#define SECP384R1_ECDSA_SIGNATURE_COMPACT_SIZE 102 +#define SECP384R1_ECDSA_SIGNATURE_TYPICAL_SIZE 103 +#define SECP384R1_ECDSA_SIGNATURE_MAX_SIZE 104 + +// 这几个函数应都去掉,不再开放底层的类型了 +int secp384r1_ecdsa_signature_to_der(const SECP384R1_ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen); +int secp384r1_ecdsa_signature_from_der(SECP384R1_ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen); +int secp384r1_ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const SECP384R1_ECDSA_SIGNATURE *sig); + + + +int secp384r1_ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen); + + +int secp384r1_ecdsa_do_sign_ex(const SECP384R1_KEY *key, const secp384r1_t k, const uint8_t dgst[48], SECP384R1_ECDSA_SIGNATURE *sig); +int secp384r1_ecdsa_do_sign(const SECP384R1_KEY *key, const uint8_t dgst[48], SECP384R1_ECDSA_SIGNATURE *sig); +int secp384r1_ecdsa_do_verify(const SECP384R1_KEY *key, const uint8_t dgst[48], const SECP384R1_ECDSA_SIGNATURE *sig); + + +// 这个函数应该改为将key的类型编程通用支持P256, P384的,摘要可以支持不同长度的 +int secp384r1_ecdsa_sign(const SECP384R1_KEY *key, const uint8_t dgst[48], uint8_t *sig, size_t *siglen); +int secp384r1_ecdsa_sign_fixlen(const SECP384R1_KEY *key, const uint8_t dgst[48], size_t siglen, uint8_t *sig); +int secp384r1_ecdsa_verify(const SECP384R1_KEY *key, const uint8_t dgst[48], const uint8_t *sig, size_t siglen); + + +// 后面的CTX就没有意义了 +typedef struct { + DIGEST_CTX digest_ctx; + SECP384R1_KEY key; + SECP384R1_ECDSA_SIGNATURE sig; +} SECP384R1_ECDSA_SIGN_CTX; + +int secp384r1_ecdsa_sign_init(SECP384R1_ECDSA_SIGN_CTX *ctx, const SECP384R1_KEY *key, const DIGEST *digest); +int secp384r1_ecdsa_sign_update(SECP384R1_ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int secp384r1_ecdsa_sign_finish(SECP384R1_ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen); +int secp384r1_ecdsa_sign_finish_fixlen(SECP384R1_ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig); +int secp384r1_ecdsa_verify_init(SECP384R1_ECDSA_SIGN_CTX *ctx, const SECP384R1_KEY *key, const DIGEST *digest, + const uint8_t *sig, size_t siglen); +int secp384r1_ecdsa_verify_update(SECP384R1_ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); +int secp384r1_ecdsa_verify_finish(SECP384R1_ECDSA_SIGN_CTX *ctx); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/gmssl/secp384r1_key.h b/include/gmssl/secp384r1_key.h new file mode 100644 index 00000000..1f87e6bd --- /dev/null +++ b/include/gmssl/secp384r1_key.h @@ -0,0 +1,63 @@ +/* + * 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. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_SECP384R1_KEY_H +#define GMSSL_SECP384R1_KEY_H + + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + SECP384R1_POINT public_key; + secp384r1_t private_key; +} SECP384R1_KEY; + +int secp384r1_key_generate(SECP384R1_KEY *key); +int secp384r1_key_set_private_key(SECP384R1_KEY *key, const secp384r1_t private_key); +int secp384r1_public_key_equ(const SECP384R1_KEY *key, const SECP384R1_KEY *pub); + +int secp384r1_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP384R1_KEY *key); +int secp384r1_private_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP384R1_KEY *key); + +int secp384r1_public_key_to_bytes(const SECP384R1_KEY *key, uint8_t **out, size_t *outlen); +int secp384r1_public_key_from_bytes(SECP384R1_KEY *key, const uint8_t **in, size_t *inlen); +int secp384r1_public_key_to_der(const SECP384R1_KEY *key, uint8_t **out, size_t *outlen); +int secp384r1_public_key_from_der(SECP384R1_KEY *key, const uint8_t **in, size_t *inlen); +int secp384r1_private_key_to_der(const SECP384R1_KEY *key, uint8_t **out, size_t *outlen); +int secp384r1_private_key_from_der(SECP384R1_KEY *key, const uint8_t **in, size_t *inlen); +int secp384r1_private_key_info_to_der(const SECP384R1_KEY *key, uint8_t **out, size_t *outlen); +int secp384r1_private_key_info_from_der(SECP384R1_KEY *key, const uint8_t **attrs, size_t *attrslen, + const uint8_t **in, size_t *inlen); +int secp384r1_private_key_info_encrypt_to_der(const SECP384R1_KEY *ec_key, const char *pass, + uint8_t **out, size_t *outlen); +int secp384r1_private_key_info_decrypt_from_der(SECP384R1_KEY *ec_key, + const uint8_t **attrs, size_t *attrs_len, + const char *pass, const uint8_t **in, size_t *inlen); + +int secp384r1_private_key_to_pem(const SECP384R1_KEY *key, FILE *fp); +int secp384r1_private_key_from_pem(SECP384R1_KEY *key, FILE *fp); +int secp384r1_private_key_info_encrypt_to_pem(const SECP384R1_KEY *key, const char *pass, FILE *fp); +int secp384r1_private_key_info_decrypt_from_pem(SECP384R1_KEY *key, const char *pass, FILE *fp); + +int secp384r1_do_ecdh(const SECP384R1_KEY *key, const SECP384R1_KEY *pub, uint8_t out[48]); +int secp384r1_ecdh(const SECP384R1_KEY *key, const uint8_t uncompressed_point[97], uint8_t out[48]); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/gmssl/version.h b/include/gmssl/version.h index c61a20bf..38b94de4 100644 --- a/include/gmssl/version.h +++ b/include/gmssl/version.h @@ -18,7 +18,7 @@ extern "C" { #define GMSSL_VERSION_NUM 30300 -#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1170" +#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1171" int gmssl_version_num(void); const char *gmssl_version_str(void); diff --git a/include/gmssl/x509_key.h b/include/gmssl/x509_key.h index c87141b8..e4b8088d 100644 --- a/include/gmssl/x509_key.h +++ b/include/gmssl/x509_key.h @@ -25,7 +25,7 @@ #endif #ifdef ENABLE_SECP256R1 #include -#include +#include #endif #ifdef ENABLE_LMS #include @@ -187,7 +187,7 @@ int x509_private_keys_from_file(X509_KEY *keys, size_t *keys_cnt, size_t max_cnt // XMSS_SIGNATURE_MAX_SIZE = 2820 // XMSSMT_SIGNATURE_MAX_SIZE = 8356? // SPHINCS_SIGNATURE_SIZE = 7856? -// ECDSA_SIGNATURE_MAX_SIZE = 72 +// SECP256R1_ECDSA_SIGNATURE_MAX_SIZE = 72 typedef union { uint8_t sm2_sig[SM2_MAX_SIGNATURE_SIZE]; @@ -215,7 +215,7 @@ typedef struct { SM2_SIGN_CTX sm2_sign_ctx; SM2_VERIFY_CTX sm2_verify_ctx; #ifdef ENABLE_SECP256R1 - ECDSA_SIGN_CTX ecdsa_sign_ctx; + SECP256R1_ECDSA_SIGN_CTX secp256r1_ecdsa_sign_ctx; #endif #ifdef ENABLE_SM9 SM9_SIGN_CTX sm9_sign_ctx; diff --git a/src/ec_ecdsa.c b/src/ec_ecdsa.c new file mode 100644 index 00000000..901e87df --- /dev/null +++ b/src/ec_ecdsa.c @@ -0,0 +1,180 @@ +/* + * 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. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#ifdef ENABLE_SECP256R1 +#include +#endif +#ifdef ENABLE_SECP384R1 +#include +#endif +#include + + +#ifdef ENABLE_SECP256R1 +static int ecdsa_digest_to_p256(const uint8_t *dgst, size_t dgstlen, uint8_t out[32]) +{ + if (!dgst || !out) { + error_print(); + return -1; + } + if (dgstlen == 32) { + memcpy(out, dgst, 32); + } else if (dgstlen == 48) { + memcpy(out, dgst, 32); + } else { + error_print(); + return -1; + } + return 1; +} +#endif + +#ifdef ENABLE_SECP384R1 +static int ecdsa_digest_to_p384(const uint8_t *dgst, size_t dgstlen, uint8_t out[48]) +{ + if (!dgst || !out) { + error_print(); + return -1; + } + if (dgstlen == 32) { + memset(out, 0, 16); + memcpy(out + 16, dgst, 32); + } else if (dgstlen == 48) { + memcpy(out, dgst, 48); + } else { + error_print(); + return -1; + } + return 1; +} +#endif + +int ecdsa_sign(const EC_KEY *key, const uint8_t *dgst, size_t dgstlen, + uint8_t *sig, size_t *siglen) +{ + if (!key || !dgst || !sig || !siglen) { + error_print(); + return -1; + } + switch (key->oid) { +#ifdef ENABLE_SECP256R1 + case OID_secp256r1: + { + uint8_t e[32]; + if (ecdsa_digest_to_p256(dgst, dgstlen, e) != 1 + || secp256r1_ecdsa_sign(&key->u.secp256r1_key, e, sig, siglen) != 1) { + error_print(); + return -1; + } + } + return 1; +#endif +#ifdef ENABLE_SECP384R1 + case OID_secp384r1: + { + uint8_t e[48]; + if (ecdsa_digest_to_p384(dgst, dgstlen, e) != 1 + || secp384r1_ecdsa_sign(&key->u.secp384r1_key, e, sig, siglen) != 1) { + error_print(); + return -1; + } + } + return 1; +#endif + default: + error_print(); + return -1; + } +} + +int ecdsa_sign_fixed_len(const EC_KEY *key, const uint8_t *dgst, size_t dgstlen, + size_t siglen, uint8_t *sig) +{ + if (!key || !dgst || !sig || !siglen) { + error_print(); + return -1; + } + switch (key->oid) { +#ifdef ENABLE_SECP256R1 + case OID_secp256r1: + { + uint8_t e[32]; + if (ecdsa_digest_to_p256(dgst, dgstlen, e) != 1 + || secp256r1_ecdsa_sign_fixlen(&key->u.secp256r1_key, e, siglen, sig) != 1) { + error_print(); + return -1; + } + } + return 1; +#endif +#ifdef ENABLE_SECP384R1 + case OID_secp384r1: + { + uint8_t e[48]; + if (ecdsa_digest_to_p384(dgst, dgstlen, e) != 1 + || secp384r1_ecdsa_sign_fixlen(&key->u.secp384r1_key, e, siglen, sig) != 1) { + error_print(); + return -1; + } + } + return 1; +#endif + default: + error_print(); + return -1; + } +} + +int ecdsa_verify(const EC_KEY *key, const uint8_t *dgst, size_t dgstlen, + const uint8_t *sig, size_t siglen) +{ + if (!key || !dgst || !sig || !siglen) { + error_print(); + return -1; + } + switch (key->oid) { +#ifdef ENABLE_SECP256R1 + case OID_secp256r1: + { + uint8_t e[32]; + int ret; + if (ecdsa_digest_to_p256(dgst, dgstlen, e) != 1) { + error_print(); + return -1; + } + if ((ret = secp256r1_ecdsa_verify(&key->u.secp256r1_key, e, sig, siglen)) < 0) { + error_print(); + return -1; + } + return ret; + } +#endif +#ifdef ENABLE_SECP384R1 + case OID_secp384r1: + { + uint8_t e[48]; + int ret; + if (ecdsa_digest_to_p384(dgst, dgstlen, e) != 1) { + error_print(); + return -1; + } + if ((ret = secp384r1_ecdsa_verify(&key->u.secp384r1_key, e, sig, siglen)) < 0) { + error_print(); + return -1; + } + return ret; + } +#endif + default: + error_print(); + return -1; + } +} diff --git a/src/ecdh.c b/src/ecdh.c index c23a1b4c..ee9af783 100644 --- a/src/ecdh.c +++ b/src/ecdh.c @@ -13,9 +13,16 @@ #include #include #include + +#ifdef ENABLE_SECP256R1 #include +#endif +#ifdef ENABLE_SECP384R1 +#include +#endif +#ifdef ENABLE_SECP256R1 int secp256r1_do_ecdh(const SECP256R1_KEY *key, const SECP256R1_KEY *peer_key, uint8_t out[32]) { SECP256R1_POINT point; @@ -67,3 +74,58 @@ int secp256r1_ecdh(const SECP256R1_KEY *key, const uint8_t uncompressed_point[65 gmssl_secure_clear(y, sizeof(secp256r1_t)); return 1; } +#endif + +#ifdef ENABLE_SECP384R1 +int secp384r1_do_ecdh(const SECP384R1_KEY *key, const SECP384R1_KEY *peer_key, uint8_t out[48]) +{ + SECP384R1_POINT point; + secp384r1_t x; + secp384r1_t y; + + if (!key || !peer_key || !out) { + error_print(); + return -1; + } + if (secp384r1_point_mul(&point, key->private_key, &peer_key->public_key) != 1 + || secp384r1_point_get_xy(&point, x, y) != 1 + || secp384r1_to_48bytes(x, out) != 1) { + error_print(); + gmssl_secure_clear(&point, sizeof(SECP384R1_POINT)); + return -1; + } + + gmssl_secure_clear(&point, sizeof(SECP384R1_POINT)); + gmssl_secure_clear(x, sizeof(secp384r1_t)); + gmssl_secure_clear(y, sizeof(secp384r1_t)); + return 1; +} + +int secp384r1_ecdh(const SECP384R1_KEY *key, const uint8_t uncompressed_point[97], uint8_t out[48]) +{ + SECP384R1_POINT point; + secp384r1_t x; + secp384r1_t y; + + if (!key || !uncompressed_point || !out) { + error_print(); + return -1; + } + if (secp384r1_point_from_uncompressed_octets(&point, uncompressed_point) != 1) { + error_print(); + return -1; + } + if (secp384r1_point_mul(&point, key->private_key, &point) != 1 + || secp384r1_point_get_xy(&point, x, y) != 1 + || secp384r1_to_48bytes(x, out) != 1) { + error_print(); + gmssl_secure_clear(&point, sizeof(SECP384R1_POINT)); + return -1; + } + + gmssl_secure_clear(&point, sizeof(SECP384R1_POINT)); + gmssl_secure_clear(x, sizeof(secp384r1_t)); + gmssl_secure_clear(y, sizeof(secp384r1_t)); + return 1; +} +#endif diff --git a/src/ecdsa.c b/src/ecdsa.c index 2af79dd8..638c9477 100644 --- a/src/ecdsa.c +++ b/src/ecdsa.c @@ -14,12 +14,12 @@ #include #include #include -#include +#include #include #include -int ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const ECDSA_SIGNATURE *sig) +int secp256r1_ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_ECDSA_SIGNATURE *sig) { format_print(fp, fmt, ind, "%s\n", label); ind += 4; @@ -31,15 +31,15 @@ int ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, cons return 1; } -int ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sigbuf, size_t siglen) +int secp256r1_ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sigbuf, size_t siglen) { - ECDSA_SIGNATURE sig; + SECP256R1_ECDSA_SIGNATURE sig; - if (ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) { + if (secp256r1_ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) { error_print(); return -1; } - ecdsa_signature_print_ex(fp, fmt, ind, label, &sig); + secp256r1_ecdsa_signature_print_ex(fp, fmt, ind, label, &sig); if (siglen) { error_print(); return -1; @@ -47,7 +47,7 @@ int ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const u return 1; } -int ecdsa_do_sign_ex(const SECP256R1_KEY *key, const secp256r1_t k, const uint8_t dgst[32], ECDSA_SIGNATURE *sig) +int secp256r1_ecdsa_do_sign_ex(const SECP256R1_KEY *key, const secp256r1_t k, const uint8_t dgst[32], SECP256R1_ECDSA_SIGNATURE *sig) { secp256r1_t e; secp256r1_t x1; @@ -87,7 +87,7 @@ int ecdsa_do_sign_ex(const SECP256R1_KEY *key, const secp256r1_t k, const uint8_ return 1; } -int ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], ECDSA_SIGNATURE *sig) +int secp256r1_ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], SECP256R1_ECDSA_SIGNATURE *sig) { secp256r1_t k; @@ -99,7 +99,7 @@ int ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], ECDSA_SIGNAT } } while (secp256r1_is_zero(k) || secp256r1_cmp(k, SECP256R1_N) >= 0); - if (ecdsa_do_sign_ex(key, k, dgst, sig) != 1) { + if (secp256r1_ecdsa_do_sign_ex(key, k, dgst, sig) != 1) { error_print(); return -1; } @@ -107,7 +107,7 @@ int ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], ECDSA_SIGNAT } -int ecdsa_do_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const ECDSA_SIGNATURE *sig) +int secp256r1_ecdsa_do_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const SECP256R1_ECDSA_SIGNATURE *sig) { secp256r1_t e; secp256r1_t w; @@ -176,7 +176,7 @@ int ecdsa_do_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const ECDS return 1; } -int ecdsa_signature_to_der(const ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen) +int secp256r1_ecdsa_signature_to_der(const SECP256R1_ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen) { size_t len = 0; uint8_t r[32]; @@ -203,7 +203,7 @@ int ecdsa_signature_to_der(const ECDSA_SIGNATURE *sig, uint8_t **out, size_t *ou return 1; } -int ecdsa_signature_from_der(ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen) +int secp256r1_ecdsa_signature_from_der(SECP256R1_ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen) { int ret; const uint8_t *d; @@ -233,32 +233,32 @@ int ecdsa_signature_from_der(ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *i return 1; } -int ecdsa_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], uint8_t *sigbuf, size_t *siglen) +int secp256r1_ecdsa_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], uint8_t *sigbuf, size_t *siglen) { - ECDSA_SIGNATURE sig; + SECP256R1_ECDSA_SIGNATURE sig; - if (ecdsa_do_sign(key, dgst, &sig) != 1) { + if (secp256r1_ecdsa_do_sign(key, dgst, &sig) != 1) { error_print(); return -1; } *siglen = 0; - if (ecdsa_signature_to_der(&sig, &sigbuf, siglen) != 1) { + if (secp256r1_ecdsa_signature_to_der(&sig, &sigbuf, siglen) != 1) { error_print(); return -1; } return 1; } -int ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig) +int secp256r1_ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig) { unsigned int trys = 200; - uint8_t buf[ECDSA_SIGNATURE_MAX_SIZE]; + uint8_t buf[SECP256R1_ECDSA_SIGNATURE_MAX_SIZE]; size_t len; switch (siglen) { - case ECDSA_SIGNATURE_COMPACT_SIZE: - case ECDSA_SIGNATURE_TYPICAL_SIZE: - case ECDSA_SIGNATURE_MAX_SIZE: + case SECP256R1_ECDSA_SIGNATURE_COMPACT_SIZE: + case SECP256R1_ECDSA_SIGNATURE_TYPICAL_SIZE: + case SECP256R1_ECDSA_SIGNATURE_MAX_SIZE: break; default: error_print(); @@ -266,7 +266,7 @@ int ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t s } while (trys--) { - if (ecdsa_sign(key, dgst, buf, &len) != 1) { + if (secp256r1_ecdsa_sign(key, dgst, buf, &len) != 1) { error_print(); return -1; } @@ -282,12 +282,12 @@ int ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t s } -int ecdsa_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const uint8_t *sigbuf, size_t siglen) +int secp256r1_ecdsa_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const uint8_t *sigbuf, size_t siglen) { int ret; - ECDSA_SIGNATURE sig; + SECP256R1_ECDSA_SIGNATURE sig; - if (ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) { + if (secp256r1_ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) { error_print(); return -1; } @@ -295,14 +295,14 @@ int ecdsa_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const uint8_t error_print(); return -1; } - if ((ret = ecdsa_do_verify(key, dgst, &sig)) < 0) { + if ((ret = secp256r1_ecdsa_do_verify(key, dgst, &sig)) < 0) { error_print(); return -1; } return ret; } -int ecdsa_sign_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST *digest) +int secp256r1_ecdsa_sign_init(SECP256R1_ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST *digest) { if (!ctx || !key) { error_print(); @@ -311,7 +311,7 @@ int ecdsa_sign_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST if (!digest) { digest = DIGEST_sha256(); } - memset(ctx, 0, sizeof(ECDSA_SIGN_CTX)); + memset(ctx, 0, sizeof(SECP256R1_ECDSA_SIGN_CTX)); ctx->key = *key; @@ -323,7 +323,7 @@ int ecdsa_sign_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST return 1; } -int ecdsa_sign_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +int secp256r1_ecdsa_sign_update(SECP256R1_ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) { if (!ctx) { error_print(); @@ -336,7 +336,7 @@ int ecdsa_sign_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) return 1; } -int ecdsa_sign_finish(ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) +int secp256r1_ecdsa_sign_finish(SECP256R1_ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) { uint8_t dgst[DIGEST_MAX_SIZE]; size_t dgstlen; @@ -352,14 +352,14 @@ int ecdsa_sign_finish(ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) return -1; } - if (ecdsa_sign(&ctx->key, dgst, sig, siglen) != 1) { + if (secp256r1_ecdsa_sign(&ctx->key, dgst, sig, siglen) != 1) { error_print(); return -1; } return 1; } -int ecdsa_sign_finish_fixlen(ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig) +int secp256r1_ecdsa_sign_finish_fixlen(SECP256R1_ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig) { uint8_t dgst[DIGEST_MAX_SIZE]; size_t dgstlen; @@ -375,7 +375,7 @@ int ecdsa_sign_finish_fixlen(ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig) return -1; } - if (ecdsa_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1) { + if (secp256r1_ecdsa_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1) { error_print(); return -1; } @@ -387,7 +387,7 @@ int ecdsa_sign_finish_fixlen(ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig) -int ecdsa_verify_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST *digest, +int secp256r1_ecdsa_verify_init(SECP256R1_ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGEST *digest, const uint8_t *sig, size_t siglen) { if (!ctx || !key || !sig || !siglen) { @@ -395,7 +395,7 @@ int ecdsa_verify_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGES return -1; } - if (ecdsa_signature_from_der(&ctx->sig, &sig, &siglen) != 1) { + if (secp256r1_ecdsa_signature_from_der(&ctx->sig, &sig, &siglen) != 1) { error_print(); return -1; } @@ -418,7 +418,7 @@ int ecdsa_verify_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const DIGES } -int ecdsa_verify_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +int secp256r1_ecdsa_verify_update(SECP256R1_ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) { if (!ctx) { error_print(); @@ -432,7 +432,7 @@ int ecdsa_verify_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen } -int ecdsa_verify_finish(ECDSA_SIGN_CTX *ctx) +int secp256r1_ecdsa_verify_finish(SECP256R1_ECDSA_SIGN_CTX *ctx) { uint8_t dgst[DIGEST_MAX_SIZE]; size_t dgstlen; @@ -449,7 +449,7 @@ int ecdsa_verify_finish(ECDSA_SIGN_CTX *ctx) return -1; } - if ((ret = ecdsa_do_verify(&ctx->key, dgst, &ctx->sig)) < 0) { + if ((ret = secp256r1_ecdsa_do_verify(&ctx->key, dgst, &ctx->sig)) < 0) { error_print(); return -1; } diff --git a/src/secp384r1_ecdsa.c b/src/secp384r1_ecdsa.c new file mode 100644 index 00000000..03f64206 --- /dev/null +++ b/src/secp384r1_ecdsa.c @@ -0,0 +1,461 @@ +/* + * 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. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int secp384r1_ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const SECP384R1_ECDSA_SIGNATURE *sig) +{ + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + if (secp384r1_print(fp, fmt, ind, "r", sig->r) != 1 + || secp384r1_print(fp, fmt, ind, "s", sig->s) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sigbuf, size_t siglen) +{ + SECP384R1_ECDSA_SIGNATURE sig; + + if (secp384r1_ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) { + error_print(); + return -1; + } + secp384r1_ecdsa_signature_print_ex(fp, fmt, ind, label, &sig); + if (siglen) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_ecdsa_do_sign_ex(const SECP384R1_KEY *key, const secp384r1_t k, const uint8_t dgst[48], SECP384R1_ECDSA_SIGNATURE *sig) +{ + secp384r1_t e; + secp384r1_t x1; + secp384r1_t y1; + secp384r1_t k_inv; + SECP384R1_POINT P; + + // e = hash(m) + if (secp384r1_from_48bytes(e, dgst) != 1 + || secp384r1_modn(e, e) != 1) { + error_print(); + return -1; + } + + // (x1, y1) = k*G + if (secp384r1_point_mul_generator(&P, k) != 1 + || secp384r1_point_get_xy(&P, x1, y1) != 1) { + error_print(); + return -1; + } + + // r = x1 mod n + if (secp384r1_modn(sig->r, x1) != 1) { + error_print(); + return -1; + } + + // s = k^-1 * (e + d * r) mod n + if (secp384r1_modn_inv(k_inv, k) != 1 + || secp384r1_modn_mul(sig->s, key->private_key, sig->r) != 1 + || secp384r1_modn_add(sig->s, sig->s, e) != 1 + || secp384r1_modn_mul(sig->s, sig->s, k_inv) != 1) { + error_print(); + return -1; + } + + return 1; +} + +int secp384r1_ecdsa_do_sign(const SECP384R1_KEY *key, const uint8_t dgst[48], SECP384R1_ECDSA_SIGNATURE *sig) +{ + secp384r1_t k; + + // rand k in [1, n-1] + do { + if (rand_bytes((uint8_t *)k, sizeof(k)) != 1) { + error_print(); + return -1; + } + } while (secp384r1_is_zero(k) || secp384r1_cmp(k, SECP384R1_N) >= 0); + + if (secp384r1_ecdsa_do_sign_ex(key, k, dgst, sig) != 1) { + error_print(); + return -1; + } + return 1; +} + + +int secp384r1_ecdsa_do_verify(const SECP384R1_KEY *key, const uint8_t dgst[48], const SECP384R1_ECDSA_SIGNATURE *sig) +{ + secp384r1_t e; + secp384r1_t w; + secp384r1_t u1; + secp384r1_t u2; + secp384r1_t x1; + secp384r1_t y1; + SECP384R1_POINT P; + SECP384R1_POINT Q; + SECP384R1_POINT R; + + // check r, s in [1, n-1] + if (secp384r1_is_zero(sig->r) + || secp384r1_cmp(sig->r, SECP384R1_N) >= 0 + || secp384r1_is_zero(sig->s) + || secp384r1_cmp(sig->s, SECP384R1_N) >= 0) { + error_print(); + return -1; + } + + // e = hash(m) + if (secp384r1_from_48bytes(e, dgst) != 1 + || secp384r1_modn(e, e) != 1) { + error_print(); + return -1; + } + + // w = s^-1 (mod n) + if (secp384r1_modn_inv(w, sig->s) != 1) { + error_print(); + return -1; + } + + // u1 = e * w (mod n) + if (secp384r1_modn_mul(u1, e, w) != 1) { + error_print(); + return -1; + } + + // u2 = r * w (mod n) + if (secp384r1_modn_mul(u2, sig->r, w) != 1) { + error_print(); + return -1; + } + + // (x1, y1) = u1*G + u2*Q + if (secp384r1_point_mul_generator(&P, u1) != 1 + || secp384r1_point_mul(&Q, u2, &key->public_key) != 1 + || secp384r1_point_add(&R, &P, &Q) != 1) { + error_print(); + return -1; + } + if (secp384r1_point_get_xy(&R, x1, y1) != 1) { + return 0; + } + + // x1 = x1 mod n + if (secp384r1_modn(x1, x1) != 1) { + error_print(); + return -1; + } + + if (secp384r1_cmp(x1, sig->r) != 0) { + return 0; + } + return 1; +} + +int secp384r1_ecdsa_signature_to_der(const SECP384R1_ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + uint8_t r[48]; + uint8_t s[48]; + + if (!sig) { + return 0; + } + + if (secp384r1_to_48bytes(sig->r, r) != 1 + || secp384r1_to_48bytes(sig->s, s) != 1) { + error_print(); + return -1; + } + + if (asn1_integer_to_der(r, 48, NULL, &len) != 1 + || asn1_integer_to_der(s, 48, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(r, 48, out, outlen) != 1 + || asn1_integer_to_der(s, 48, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_ecdsa_signature_from_der(SECP384R1_ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + const uint8_t *r; + const uint8_t *s; + uint8_t rbuf[48] = {0}; + uint8_t sbuf[48] = {0}; + size_t dlen, rlen, slen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&r, &rlen, &d, &dlen) != 1 + || asn1_integer_from_der(&s, &slen, &d, &dlen) != 1 + || asn1_length_le(rlen, 48) != 1 + || asn1_length_le(slen, 48) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + + memcpy(rbuf + sizeof(rbuf) - rlen, r, rlen); + memcpy(sbuf + sizeof(sbuf) - slen, s, slen); + if (secp384r1_from_48bytes(sig->r, rbuf) != 1 + || secp384r1_from_48bytes(sig->s, sbuf) != 1) { + error_print(); + return -1; + } + + return 1; +} + +int secp384r1_ecdsa_sign(const SECP384R1_KEY *key, const uint8_t dgst[48], uint8_t *sigbuf, size_t *siglen) +{ + SECP384R1_ECDSA_SIGNATURE sig; + + if (secp384r1_ecdsa_do_sign(key, dgst, &sig) != 1) { + error_print(); + return -1; + } + *siglen = 0; + if (secp384r1_ecdsa_signature_to_der(&sig, &sigbuf, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_ecdsa_sign_fixlen(const SECP384R1_KEY *key, const uint8_t dgst[48], size_t siglen, uint8_t *sig) +{ + unsigned int trys = 200; + uint8_t buf[SECP384R1_ECDSA_SIGNATURE_MAX_SIZE]; + size_t len; + + switch (siglen) { + case SECP384R1_ECDSA_SIGNATURE_COMPACT_SIZE: + case SECP384R1_ECDSA_SIGNATURE_TYPICAL_SIZE: + case SECP384R1_ECDSA_SIGNATURE_MAX_SIZE: + break; + default: + error_print(); + return -1; + } + + while (trys--) { + if (secp384r1_ecdsa_sign(key, dgst, buf, &len) != 1) { + error_print(); + return -1; + } + if (len == siglen) { + memcpy(sig, buf, len); + return 1; + } + } + + // might caused by bad randomness + error_print(); + return -1; +} + + +int secp384r1_ecdsa_verify(const SECP384R1_KEY *key, const uint8_t dgst[48], const uint8_t *sigbuf, size_t siglen) +{ + int ret; + SECP384R1_ECDSA_SIGNATURE sig; + + if (secp384r1_ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) { + error_print(); + return -1; + } + if (siglen) { + error_print(); + return -1; + } + if ((ret = secp384r1_ecdsa_do_verify(key, dgst, &sig)) < 0) { + error_print(); + return -1; + } + return ret; +} + +int secp384r1_ecdsa_sign_init(SECP384R1_ECDSA_SIGN_CTX *ctx, const SECP384R1_KEY *key, const DIGEST *digest) +{ + if (!ctx || !key) { + error_print(); + return -1; + } + if (!digest) { + digest = DIGEST_sha384(); + } + memset(ctx, 0, sizeof(SECP384R1_ECDSA_SIGN_CTX)); + + ctx->key = *key; + + if (digest_init(&ctx->digest_ctx, digest) != 1) { + error_print(); + return -1; + } + + return 1; +} + +int secp384r1_ecdsa_sign_update(SECP384R1_ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + if (!ctx) { + error_print(); + return -1; + } + if (digest_update(&ctx->digest_ctx, data, datalen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_ecdsa_sign_finish(SECP384R1_ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) +{ + uint8_t dgst[DIGEST_MAX_SIZE]; + size_t dgstlen; + + if (!ctx || !sig || !siglen) { + error_print(); + return -1; + } + + if (digest_finish(&ctx->digest_ctx, dgst, &dgstlen) != 1 + || dgstlen < 48) { + error_print(); + return -1; + } + + if (secp384r1_ecdsa_sign(&ctx->key, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_ecdsa_sign_finish_fixlen(SECP384R1_ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig) +{ + uint8_t dgst[DIGEST_MAX_SIZE]; + size_t dgstlen; + + if (!ctx || !sig || !siglen) { + error_print(); + return -1; + } + + if (digest_finish(&ctx->digest_ctx, dgst, &dgstlen) != 1 + || dgstlen < 48) { + error_print(); + return -1; + } + + if (secp384r1_ecdsa_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1) { + error_print(); + return -1; + } + return 1; +} + + + + + + +int secp384r1_ecdsa_verify_init(SECP384R1_ECDSA_SIGN_CTX *ctx, const SECP384R1_KEY *key, const DIGEST *digest, + const uint8_t *sig, size_t siglen) +{ + if (!ctx || !key || !sig || !siglen) { + error_print(); + return -1; + } + + if (secp384r1_ecdsa_signature_from_der(&ctx->sig, &sig, &siglen) != 1) { + error_print(); + return -1; + } + if (siglen) { + error_print(); + return -1; + } + + ctx->key = *key; + + if (!digest) { + digest = DIGEST_sha384(); + } + if (digest_init(&ctx->digest_ctx, digest) != 1) { + error_print(); + return -1; + } + + return 1; +} + + +int secp384r1_ecdsa_verify_update(SECP384R1_ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +{ + if (!ctx) { + error_print(); + return -1; + } + if (digest_update(&ctx->digest_ctx, data, datalen) != 1) { + error_print(); + return -1; + } + return 1; +} + + +int secp384r1_ecdsa_verify_finish(SECP384R1_ECDSA_SIGN_CTX *ctx) +{ + uint8_t dgst[DIGEST_MAX_SIZE]; + size_t dgstlen; + int ret; + + if (!ctx) { + error_print(); + return -1; + } + + if (digest_finish(&ctx->digest_ctx, dgst, &dgstlen) != 1 + || dgstlen < 48) { + error_print(); + return -1; + } + + if ((ret = secp384r1_ecdsa_do_verify(&ctx->key, dgst, &ctx->sig)) < 0) { + error_print(); + return -1; + } + return ret; +} diff --git a/src/secp384r1_key.c b/src/secp384r1_key.c new file mode 100644 index 00000000..4da9e247 --- /dev/null +++ b/src/secp384r1_key.c @@ -0,0 +1,587 @@ +/* + * 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. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int secp384r1_key_generate(SECP384R1_KEY *key) +{ + do { + if (rand_bytes((uint8_t *)key->private_key, sizeof(secp384r1_t)) != 1) { + error_print(); + return -1; + } + } while (secp384r1_is_zero(key->private_key) || secp384r1_cmp(key->private_key, SECP384R1_N) >= 0); + + if (secp384r1_point_mul_generator(&key->public_key, key->private_key) != 1) { + error_print(); + return -1; + } + + return 1; +} + +int secp384r1_key_set_private_key(SECP384R1_KEY *key, const secp384r1_t private_key) +{ + if (!key || !private_key) { + error_print(); + return -1; + } + if (secp384r1_is_zero(private_key) || secp384r1_cmp(private_key, SECP384R1_N) >= 0) { + error_print(); + return -1; + } + memset(key, 0, sizeof(SECP384R1_KEY)); + + if (secp384r1_copy(key->private_key, private_key) != 1 + || secp384r1_point_mul_generator(&key->public_key, key->private_key) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_public_key_equ(const SECP384R1_KEY *key, const SECP384R1_KEY *pub) +{ + if (secp384r1_point_equ(&key->public_key, &pub->public_key) == 1) { + return 1; + } else { + return 0; + } +} + + +// SM2将这个命名为_to_octets,应该更准确一些 +int secp384r1_public_key_to_bytes(const SECP384R1_KEY *key, uint8_t **out, size_t *outlen) +{ + if (!key || !outlen) { + error_print(); + return -1; + } + if (out && *out) { + if (secp384r1_point_to_uncompressed_octets(&key->public_key, *out) != 1) { + error_print(); + return -1; + } + *out += 97; + } + *outlen += 97; + return 1; +} + +int secp384r1_public_key_from_bytes(SECP384R1_KEY *key, const uint8_t **in, size_t *inlen) +{ + if (!key || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (*inlen < 97) { + error_print(); + return -1; + } + memset(key, 0, sizeof(SECP384R1_KEY)); + + if (secp384r1_point_from_uncompressed_octets(&key->public_key, *in) != 1) { + error_print(); + return -1; + } + *in += 97; + *inlen -= 97; + + return 1; +} + +int secp384r1_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP384R1_KEY *key) +{ + secp384r1_t x; + secp384r1_t y; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (secp384r1_print(fp, fmt, ind, "X", key->public_key.X) != 1 + || secp384r1_print(fp, fmt, ind, "Y", key->public_key.Y) != 1 + || secp384r1_print(fp, fmt, ind, "Z", key->public_key.Z) != 1) { + error_print(); + return -1; + } + + if (secp384r1_point_get_xy(&key->public_key, x, y) != 1 + || secp384r1_print(fp, fmt, ind, "x", x) != 1 + || secp384r1_print(fp, fmt, ind, "y", y) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_private_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP384R1_KEY *key) +{ + uint8_t buf[48]; + + if (secp384r1_to_48bytes(key->private_key, buf) != 1) { + error_print(); + return -1; + } + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + if (secp384r1_public_key_print(fp, fmt, ind, "public_key", key) != 1) { + error_print(); + return -1; + } + format_bytes(fp, fmt, ind, "private_key", buf, 48); + return 1; +} + +int secp384r1_public_key_to_der(const SECP384R1_KEY *key, uint8_t **out, size_t *outlen) +{ + uint8_t octets[97]; + uint8_t *p = octets; + size_t len = 0; + + if (!key) { + return 0; + } + + // different from SM2 + if (out && *out) { + if (secp384r1_public_key_to_bytes(key, &p, &len) != 1) { + error_print(); + return -1; + } + } + + if (asn1_bit_octets_to_der(octets, sizeof(octets), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_public_key_from_der(SECP384R1_KEY *key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_bit_octets_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (secp384r1_public_key_from_bytes(key, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (dlen) { + error_print(); + return -1; + } + return 1; +} + + +// 这里应该提供public_key_info_to_pem 和SM2完全一样的功能 +// 这样才可以生成证书 + + + + + + + + + + + + + + + + + +int secp384r1_private_key_to_der(const SECP384R1_KEY *key, uint8_t **out, size_t *outlen) +{ + int curve = OID_secp384r1; + uint8_t params[64]; + uint8_t pubkey[128]; + uint8_t *params_ptr = params; + uint8_t *pubkey_ptr = pubkey; + size_t params_len = 0; + size_t pubkey_len = 0; + uint8_t prikey[48]; + size_t len = 0; + + if (!key) { + error_print(); + return -1; + } + if (ec_named_curve_to_der(curve, ¶ms_ptr, ¶ms_len) != 1 + || secp384r1_public_key_to_der(key, &pubkey_ptr, &pubkey_len) != 1) { + error_print(); + return -1; + } + // fprintf(stderr, "%s %d: params_len = %zu\n", params_len); + // fprintf(stderr, "%s %d: pubkey_len = %zu\n", pubkey_len); + if (secp384r1_to_48bytes(key->private_key, prikey) != 1) { + error_print(); + return -1; + } + if (asn1_int_to_der(EC_private_key_version, NULL, &len) != 1 + || asn1_octet_string_to_der(prikey, 48, NULL, &len) != 1 + || asn1_explicit_to_der(0, params, params_len, NULL, &len) != 1 + || asn1_explicit_to_der(1, pubkey, pubkey_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(EC_private_key_version, out, outlen) != 1 + || asn1_octet_string_to_der(prikey, 48, out, outlen) != 1 + || asn1_explicit_to_der(0, params, params_len, out, outlen) != 1 + || asn1_explicit_to_der(1, pubkey, pubkey_len, out, outlen) != 1) { + gmssl_secure_clear(prikey, 48); + error_print(); + return -1; + } + gmssl_secure_clear(prikey, 48); + return 1; +} + +int secp384r1_private_key_from_der(SECP384R1_KEY *key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + int ver; + const uint8_t *prikey; + const uint8_t *params; + const uint8_t *pubkey; + size_t prikey_len, params_len, pubkey_len; + int curve; + SECP384R1_KEY tmp_key; + secp384r1_t private_key; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(&ver, &d, &dlen) != 1 + || asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1 + || asn1_explicit_from_der(0, ¶ms, ¶ms_len, &d, &dlen) != 1 + || asn1_explicit_from_der(1, &pubkey, &pubkey_len, &d, &dlen) != 1 + || asn1_check(ver == EC_private_key_version) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (!params || !pubkey) { + error_print(); + return -1; + } + + // public_key + if (ec_named_curve_from_der(&curve, ¶ms, ¶ms_len) != 1 + || asn1_check(curve == OID_secp384r1) != 1 + || asn1_length_is_zero(params_len) != 1) { + error_print(); + return -1; + } + if (secp384r1_public_key_from_der(&tmp_key, &pubkey, &pubkey_len) != 1 + || asn1_length_is_zero(pubkey_len) != 1) { + error_print(); + return -1; + } + + // private_key + if (!prikey || prikey_len != 48) { + error_print(); + return -1; + } + if (secp384r1_from_48bytes(private_key, prikey) != 1) { + error_print(); + return -1; + } + if (secp384r1_key_set_private_key(key, private_key) != 1) { + gmssl_secure_clear(private_key, 48); + error_print(); + return -1; + } + gmssl_secure_clear(private_key, 48); + + // check + if (secp384r1_public_key_equ(key, &tmp_key) != 1) { + gmssl_secure_clear(key, sizeof(SECP384R1_KEY)); + error_print(); + return -1; + } + + return 1; +} + +int secp384r1_private_key_info_to_der(const SECP384R1_KEY *key, uint8_t **out, size_t *outlen) +{ + int algor = OID_ec_public_key; + int algor_param = OID_secp384r1; + size_t len = 0; + uint8_t prikey[256]; + uint8_t *p = prikey; + size_t prikey_len = 0; + + if (secp384r1_private_key_to_der(key, &p, &prikey_len) != 1) { + error_print(); + return -1; + } + //fprintf(stderr, "%s %d: prikey_len = %zu\n", __FILE__, __LINE__, prikey_len); + + if (asn1_int_to_der(PKCS8_private_key_info_version, NULL, &len) != 1 + || x509_public_key_algor_to_der(algor, algor_param, NULL, &len) != 1 + || asn1_octet_string_to_der(prikey, prikey_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(PKCS8_private_key_info_version, out, outlen) != 1 + || x509_public_key_algor_to_der(algor, algor_param, out, outlen) != 1 + || asn1_octet_string_to_der(prikey, prikey_len, out, outlen) != 1) { + memset(prikey, 0, sizeof(prikey)); + error_print(); + return -1; + } + memset(prikey, 0, sizeof(prikey)); + return 1; +} + +int secp384r1_private_key_info_from_der(SECP384R1_KEY *key, const uint8_t **attrs, size_t *attrslen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + int version; + int algor; + int algor_param; + const uint8_t *prikey; + size_t prikey_len; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(&version, &d, &dlen) != 1 + || x509_public_key_algor_from_der(&algor, &algor_param, &d, &dlen) != 1 + || asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1 + || asn1_implicit_set_from_der(0, attrs, attrslen, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (asn1_check(version == PKCS8_private_key_info_version) != 1 + || asn1_check(algor == OID_ec_public_key) != 1 + || asn1_check(algor_param == OID_secp384r1) != 1 + || secp384r1_private_key_from_der(key, &prikey, &prikey_len) != 1 + || asn1_length_is_zero(prikey_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_private_key_info_encrypt_to_der(const SECP384R1_KEY *ec_key, const char *pass, + uint8_t **out, size_t *outlen) +{ + int ret = -1; + uint8_t pkey_info[512]; + uint8_t *p = pkey_info; + size_t pkey_info_len = 0; + uint8_t salt[16]; + int iter = 65536; + uint8_t iv[16]; + uint8_t key[16]; + SM4_KEY sm4_key; + uint8_t enced_pkey_info[sizeof(pkey_info) + 32]; + size_t enced_pkey_info_len; + + if (!ec_key || !pass || !outlen) { + error_print(); + return -1; + } + if (secp384r1_private_key_info_to_der(ec_key, &p, &pkey_info_len) != 1 + || rand_bytes(salt, sizeof(salt)) != 1 + || rand_bytes(iv, sizeof(iv)) != 1 + || sm3_pbkdf2(pass, strlen(pass), salt, sizeof(salt), iter, sizeof(key), key) != 1) { + error_print(); + goto end; + } + /* + if (pkey_info_len != sizeof(pkey_info)) { + error_print(); + goto end; + } + */ + sm4_set_encrypt_key(&sm4_key, key); + if (sm4_cbc_padding_encrypt( + &sm4_key, iv, pkey_info, pkey_info_len, + enced_pkey_info, &enced_pkey_info_len) != 1 + || pkcs8_enced_private_key_info_to_der( + salt, sizeof(salt), iter, sizeof(key), OID_hmac_sm3, + OID_sm4_cbc, iv, sizeof(iv), + enced_pkey_info, enced_pkey_info_len, out, outlen) != 1) { + error_print(); + goto end; + } + + ret = 1; +end: + gmssl_secure_clear(pkey_info, sizeof(pkey_info)); + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(&sm4_key, sizeof(sm4_key)); + return ret; +} + +int secp384r1_private_key_info_decrypt_from_der(SECP384R1_KEY *ec_key, + const uint8_t **attrs, size_t *attrs_len, + const char *pass, const uint8_t **in, size_t *inlen) +{ + int ret = -1; + const uint8_t *salt; + size_t saltlen; + int iter; + int keylen; + int prf; + int cipher; + const uint8_t *iv; + size_t ivlen; + uint8_t key[16]; + SM4_KEY sm4_key; + const uint8_t *enced_pkey_info; + size_t enced_pkey_info_len; + uint8_t pkey_info[256]; + const uint8_t *cp = pkey_info; + size_t pkey_info_len; + + if (!ec_key || !attrs || !attrs_len || !pass || !in || !(*in) || !inlen) { + error_print(); + return -1; + } + if (pkcs8_enced_private_key_info_from_der(&salt, &saltlen, &iter, &keylen, &prf, + &cipher, &iv, &ivlen, &enced_pkey_info, &enced_pkey_info_len, in, inlen) != 1 + || asn1_check(keylen == -1 || keylen == 16) != 1 + || asn1_check(prf == - 1 || prf == OID_hmac_sm3) != 1 + || asn1_check(cipher == OID_sm4_cbc) != 1 + || asn1_check(ivlen == 16) != 1 + || asn1_length_le(enced_pkey_info_len, sizeof(pkey_info)) != 1) { + error_print(); + return -1; + } + if (sm3_pbkdf2(pass, strlen(pass), salt, saltlen, iter, sizeof(key), key) != 1) { + error_print(); + goto end; + } + sm4_set_decrypt_key(&sm4_key, key); + if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced_pkey_info, enced_pkey_info_len, + pkey_info, &pkey_info_len) != 1 + || secp384r1_private_key_info_from_der(ec_key, attrs, attrs_len, &cp, &pkey_info_len) != 1 + || asn1_length_is_zero(pkey_info_len) != 1) { + error_print(); + goto end; + } + ret = 1; +end: + gmssl_secure_clear(&sm4_key, sizeof(sm4_key)); + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(pkey_info, sizeof(pkey_info)); + return ret; +} + +int secp384r1_private_key_info_encrypt_to_pem(const SECP384R1_KEY *key, const char *pass, FILE *fp) +{ + uint8_t buf[1024]; + uint8_t *p = buf; + size_t len = 0; + + if (!fp) { + error_print(); + return -1; + } + if (secp384r1_private_key_info_encrypt_to_der(key, pass, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, "ENCRYPTED PRIVATE KEY", buf, len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_private_key_info_decrypt_from_pem(SECP384R1_KEY *key, const char *pass, FILE *fp) +{ + uint8_t buf[512]; + const uint8_t *cp = buf; + size_t len; + const uint8_t *attrs; + size_t attrs_len; + + if (!key || !pass || !fp) { + error_print(); + return -1; + } + if (pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len, sizeof(buf)) != 1 + || secp384r1_private_key_info_decrypt_from_der(key, &attrs, &attrs_len, pass, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + +// FIXME: side-channel of Base64 +int secp384r1_private_key_to_pem(const SECP384R1_KEY *a, FILE *fp) +{ + uint8_t buf[512]; + uint8_t *p = buf; + size_t len = 0; + + if (secp384r1_private_key_to_der(a, &p, &len) != 1) { + error_print(); + return -1; + } + if (pem_write(fp, "EC PRIVATE KEY", buf, len) <= 0) { + error_print(); + return -1; + } + return 1; +} + +int secp384r1_private_key_from_pem(SECP384R1_KEY *a, FILE *fp) +{ + uint8_t buf[512]; + const uint8_t *cp = buf; + size_t len; + + if (pem_read(fp, "EC PRIVATE KEY", buf, &len, sizeof(buf)) != 1) { + error_print(); + return -1; + } + if (secp384r1_private_key_from_der(a, &cp, &len) != 1 + || len > 0) { + error_print(); + return -1; + } + return 1; +} diff --git a/src/x509_key.c b/src/x509_key.c index 8387a242..9964f925 100644 --- a/src/x509_key.c +++ b/src/x509_key.c @@ -1837,7 +1837,7 @@ int x509_sign_init(X509_SIGN_CTX *ctx, X509_KEY *key, int sign_algor, const void break; #ifdef ENABLE_SECP256R1 case OID_secp256r1: - if (ecdsa_sign_init(&ctx->u.ecdsa_sign_ctx, &key->u.secp256r1_key, + if (secp256r1_ecdsa_sign_init(&ctx->u.secp256r1_ecdsa_sign_ctx, &key->u.secp256r1_key, x509_ecdsa_sign_algor_digest(sign_algor)) != 1) { error_print(); return -1; @@ -1970,7 +1970,7 @@ int x509_sign_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) case OID_ecdsa_with_sha256: case OID_ecdsa_with_sha384: case OID_ecdsa_with_sha512: - if (ecdsa_sign_update(&ctx->u.ecdsa_sign_ctx, data, datalen) != 1) { + if (secp256r1_ecdsa_sign_update(&ctx->u.secp256r1_ecdsa_sign_ctx, data, datalen) != 1) { error_print(); return -1; } @@ -2050,13 +2050,13 @@ int x509_sign_finish(X509_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) case OID_ecdsa_with_sha384: case OID_ecdsa_with_sha512: if (ctx->fixed_siglen) { - if (ecdsa_sign_finish_fixlen(&ctx->u.ecdsa_sign_ctx, ctx->fixed_siglen, sig) != 1) { + if (secp256r1_ecdsa_sign_finish_fixlen(&ctx->u.secp256r1_ecdsa_sign_ctx, ctx->fixed_siglen, sig) != 1) { error_print(); return -1; } *siglen = ctx->fixed_siglen; } else { - if (ecdsa_sign_finish(&ctx->u.ecdsa_sign_ctx, sig, siglen) != 1) { + if (secp256r1_ecdsa_sign_finish(&ctx->u.secp256r1_ecdsa_sign_ctx, sig, siglen) != 1) { error_print(); return -1; } @@ -2225,7 +2225,7 @@ int x509_verify_init(X509_SIGN_CTX *ctx, const X509_KEY *key, int sign_algor, co break; #ifdef ENABLE_SECP256R1 case OID_secp256r1: - if (ecdsa_verify_init(&ctx->u.ecdsa_sign_ctx, &key->u.secp256r1_key, + if (secp256r1_ecdsa_verify_init(&ctx->u.secp256r1_ecdsa_sign_ctx, &key->u.secp256r1_key, x509_ecdsa_sign_algor_digest(sign_algor), sig, siglen) != 1) { error_print(); return -1; @@ -2317,7 +2317,7 @@ int x509_verify_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) case OID_ecdsa_with_sha256: case OID_ecdsa_with_sha384: case OID_ecdsa_with_sha512: - if (ecdsa_verify_update(&ctx->u.ecdsa_sign_ctx, data, datalen) != 1) { + if (secp256r1_ecdsa_verify_update(&ctx->u.secp256r1_ecdsa_sign_ctx, data, datalen) != 1) { error_print(); return -1; } @@ -2389,7 +2389,7 @@ int x509_verify_finish(X509_SIGN_CTX *ctx) case OID_ecdsa_with_sha256: case OID_ecdsa_with_sha384: case OID_ecdsa_with_sha512: - if ((ret = ecdsa_verify_finish(&ctx->u.ecdsa_sign_ctx)) < 0) { + if ((ret = secp256r1_ecdsa_verify_finish(&ctx->u.secp256r1_ecdsa_sign_ctx)) < 0) { error_print(); return -1; } diff --git a/tests/ecdsatest.c b/tests/ecdsatest.c index be98230a..ee27da42 100644 --- a/tests/ecdsatest.c +++ b/tests/ecdsatest.c @@ -17,6 +17,7 @@ #include #include #include +#include /* d 0x5 @@ -33,7 +34,7 @@ v 0x5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c static int test_ecdsa(void) { SECP256R1_KEY key; - ECDSA_SIGNATURE sig; + SECP256R1_ECDSA_SIGNATURE sig; uint8_t dgst[32]; secp256r1_t d; secp256r1_t k; @@ -54,13 +55,13 @@ static int test_ecdsa(void) dgst[31] = 2; /* - if (ecdsa_do_sign_ex(&key, k, dgst, &sig) != 1) { + if (secp256r1_ecdsa_do_sign_ex(&key, k, dgst, &sig) != 1) { error_print(); return -1; } */ - if (ecdsa_do_sign(&key, dgst, &sig) != 1) { + if (secp256r1_ecdsa_do_sign(&key, dgst, &sig) != 1) { error_print(); return -1; } @@ -71,7 +72,7 @@ static int test_ecdsa(void) secp256r1_print(stderr, 0, 0, "s", sig.s); - if (ecdsa_do_verify(&key, dgst, &sig) != 1) { + if (secp256r1_ecdsa_do_verify(&key, dgst, &sig) != 1) { error_print(); return -1; } @@ -83,7 +84,7 @@ static int test_ecdsa(void) static int test_ecdsa_verify_infinity(void) { SECP256R1_KEY key; - ECDSA_SIGNATURE sig; + SECP256R1_ECDSA_SIGNATURE sig; secp256r1_t d; uint8_t dgst[32]; size_t dgstlen; @@ -103,7 +104,51 @@ static int test_ecdsa_verify_infinity(void) error_print(); return -1; } - if (ecdsa_do_verify(&key, dgst, &sig) != 0) { + if (secp256r1_ecdsa_do_verify(&key, dgst, &sig) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_ecdsa_generic(void) +{ + EC_KEY key; + uint8_t dgst32[32]; + uint8_t dgst48[48]; + uint8_t sig[SECP256R1_ECDSA_SIGNATURE_MAX_SIZE]; + size_t siglen; + + key.oid = OID_secp256r1; + if (secp256r1_key_generate(&key.u.secp256r1_key) != 1) { + error_print(); + return -1; + } + memset(dgst32, 0x11, sizeof(dgst32)); + memset(dgst48, 0x22, sizeof(dgst48)); + + if (ecdsa_sign(&key, dgst32, sizeof(dgst32), sig, &siglen) != 1 + || siglen > sizeof(sig) + || ecdsa_verify(&key, dgst32, sizeof(dgst32), sig, siglen) != 1) { + error_print(); + return -1; + } + dgst32[0] ^= 0x01; + if (ecdsa_verify(&key, dgst32, sizeof(dgst32), sig, siglen) != 0) { + error_print(); + return -1; + } + + if (ecdsa_sign(&key, dgst48, sizeof(dgst48), sig, &siglen) != 1 + || siglen > sizeof(sig) + || ecdsa_verify(&key, dgst48, sizeof(dgst48), sig, siglen) != 1) { + error_print(); + return -1; + } + if (ecdsa_sign_fixed_len(&key, dgst48, sizeof(dgst48), siglen, sig) != 1 + || ecdsa_verify(&key, dgst48, sizeof(dgst48), sig, siglen) != 1) { error_print(); return -1; } @@ -116,6 +161,7 @@ int main(void) { if (test_ecdsa() != 1) goto err; if (test_ecdsa_verify_infinity() != 1) goto err; + if (test_ecdsa_generic() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; diff --git a/tests/secp384r1_ecdsatest.c b/tests/secp384r1_ecdsatest.c new file mode 100644 index 00000000..82bf622c --- /dev/null +++ b/tests/secp384r1_ecdsatest.c @@ -0,0 +1,213 @@ +/* + * 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. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_secp384r1_ecdsa_do_sign(void) +{ + SECP384R1_KEY key; + SECP384R1_ECDSA_SIGNATURE sig; + uint8_t dgst[48]; + secp384r1_t d; + secp384r1_t k; + + // d = 5 + bn_set_word(d, 5, 8); + secp384r1_key_set_private_key(&key, d); + + secp384r1_private_key_print(stderr, 0, 0, "private_key", &key); + + // k = 3 + bn_set_word(k, 3, 8); + + // e = 2 + memset(dgst, 0, sizeof(dgst)); + dgst[47] = 2; + + if (secp384r1_ecdsa_do_sign_ex(&key, k, dgst, &sig) != 1) { + error_print(); + return -1; + } + + secp384r1_print(stderr, 0, 0, "r", sig.r); + secp384r1_print(stderr, 0, 0, "s", sig.s); + + + if (secp384r1_ecdsa_do_verify(&key, dgst, &sig) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_ecdsa_sign(void) +{ + SECP384R1_KEY key; + uint8_t dgst[48]; + uint8_t sig[SECP384R1_ECDSA_SIGNATURE_MAX_SIZE]; + size_t siglen; + + if (secp384r1_key_generate(&key) != 1) { + error_print(); + return -1; + } + memset(dgst, 0x5a, sizeof(dgst)); + + if (secp384r1_ecdsa_sign(&key, dgst, sig, &siglen) != 1 + || siglen > sizeof(sig)) { + error_print(); + return -1; + } + if (secp384r1_ecdsa_verify(&key, dgst, sig, siglen) != 1) { + error_print(); + return -1; + } + dgst[0] ^= 0x01; + if (secp384r1_ecdsa_verify(&key, dgst, sig, siglen) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_ecdsa_ctx(void) +{ + SECP384R1_KEY key; + SECP384R1_ECDSA_SIGN_CTX sign_ctx; + SECP384R1_ECDSA_SIGN_CTX verify_ctx; + uint8_t sig[SECP384R1_ECDSA_SIGNATURE_MAX_SIZE]; + size_t siglen; + uint8_t msg[] = "message"; + + if (secp384r1_key_generate(&key) != 1) { + error_print(); + return -1; + } + if (secp384r1_ecdsa_sign_init(&sign_ctx, &key, NULL) != 1 + || secp384r1_ecdsa_sign_update(&sign_ctx, msg, sizeof(msg) - 1) != 1 + || secp384r1_ecdsa_sign_finish(&sign_ctx, sig, &siglen) != 1 + || siglen > sizeof(sig)) { + error_print(); + return -1; + } + if (secp384r1_ecdsa_verify_init(&verify_ctx, &key, NULL, sig, siglen) != 1 + || secp384r1_ecdsa_verify_update(&verify_ctx, msg, sizeof(msg) - 1) != 1 + || secp384r1_ecdsa_verify_finish(&verify_ctx) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_ecdsa_verify_infinity(void) +{ + SECP384R1_KEY key; + SECP384R1_ECDSA_SIGNATURE sig; + secp384r1_t d; + uint8_t dgst[48]; + size_t dgstlen; + + if (secp384r1_set_one(d) != 1 + || secp384r1_key_set_private_key(&key, d) != 1 + || secp384r1_set_one(sig.r) != 1 + || secp384r1_set_one(sig.s) != 1) { + error_print(); + return -1; + } + + // e = n - 1, so u1 * G + u2 * Q = (n - 1)G + G = O for Q = G + if (hex_to_bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52972", + 96, dgst, &dgstlen) != 1 + || dgstlen != sizeof(dgst)) { + error_print(); + return -1; + } + if (secp384r1_ecdsa_do_verify(&key, dgst, &sig) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_ecdsa_generic(void) +{ + EC_KEY key; + uint8_t dgst32[32]; + uint8_t dgst48[48]; + uint8_t sig[SECP384R1_ECDSA_SIGNATURE_MAX_SIZE]; + size_t siglen; + + key.oid = OID_secp384r1; + if (secp384r1_key_generate(&key.u.secp384r1_key) != 1) { + error_print(); + return -1; + } + memset(dgst32, 0x33, sizeof(dgst32)); + memset(dgst48, 0x44, sizeof(dgst48)); + + if (ecdsa_sign(&key, dgst48, sizeof(dgst48), sig, &siglen) != 1 + || siglen > sizeof(sig) + || ecdsa_verify(&key, dgst48, sizeof(dgst48), sig, siglen) != 1) { + error_print(); + return -1; + } + dgst48[0] ^= 0x01; + if (ecdsa_verify(&key, dgst48, sizeof(dgst48), sig, siglen) != 0) { + error_print(); + return -1; + } + + if (ecdsa_sign(&key, dgst32, sizeof(dgst32), sig, &siglen) != 1 + || siglen > sizeof(sig) + || ecdsa_verify(&key, dgst32, sizeof(dgst32), sig, siglen) != 1) { + error_print(); + return -1; + } + if (ecdsa_sign_fixed_len(&key, dgst32, sizeof(dgst32), siglen, sig) != 1 + || ecdsa_verify(&key, dgst32, sizeof(dgst32), sig, siglen) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +int main(void) +{ + if (test_secp384r1_ecdsa_do_sign() != 1) goto err; + if (test_secp384r1_ecdsa_sign() != 1) goto err; + if (test_secp384r1_ecdsa_ctx() != 1) goto err; + if (test_secp384r1_ecdsa_verify_infinity() != 1) goto err; + if (test_secp384r1_ecdsa_generic() != 1) goto err; + + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return 1; +} diff --git a/tests/secp384r1_keytest.c b/tests/secp384r1_keytest.c new file mode 100644 index 00000000..050ba8dc --- /dev/null +++ b/tests/secp384r1_keytest.c @@ -0,0 +1,329 @@ +/* + * 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. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int test_secp384r1_key_generate(void) +{ + SECP384R1_KEY key; + + if (secp384r1_key_generate(&key) != 1) { + error_print(); + return -1; + } + secp384r1_public_key_print(stderr, 0, 4, "public_key", &key); + secp384r1_private_key_print(stderr, 0, 4, "private_key", &key); + gmssl_secure_clear(&key, sizeof(key)); + secp384r1_private_key_print(stderr, 0, 4, "private_key", &key); + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_key_set_private_key(void) +{ + SECP384R1_KEY key; + secp384r1_t private_key; + uint8_t bytes[48]; + size_t len; + + // key = 1 + memset(bytes, 0, sizeof(bytes)); + bytes[47] = 1; + secp384r1_from_48bytes(private_key, bytes); + if (secp384r1_key_set_private_key(&key, private_key) != 1) { + error_print(); + return -1; + } + secp384r1_private_key_print(stderr, 0, 4, "private_key = 1", &key); + + + // key = n-1 + hex_to_bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52972", 96, bytes, &len); + secp384r1_from_48bytes(private_key, bytes); + if (secp384r1_key_set_private_key(&key, private_key) != 1) { + error_print(); + return -1; + } + + + // key = 0, should fail + memset(bytes, 0, sizeof(bytes)); + secp384r1_from_48bytes(private_key, bytes); + if (secp384r1_key_set_private_key(&key, private_key) >= 0) { + error_print(); + return -1; + } + + // key = n, should fail + hex_to_bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", 96, bytes, &len); + secp384r1_from_48bytes(private_key, bytes); + if (secp384r1_key_set_private_key(&key, private_key) >= 0) { + error_print(); + return -1; + } + + // key = 0xff..f, should fail + memset(bytes, 0xff, sizeof(bytes)); + secp384r1_from_48bytes(private_key, bytes); + if (secp384r1_key_set_private_key(&key, private_key) >= 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_public_key_to_bytes(void) +{ + SECP384R1_KEY key; + SECP384R1_KEY key1; + uint8_t bytes[512]; + uint8_t *p = bytes; + const uint8_t *cp = bytes; + size_t len = 0; + + if (secp384r1_key_generate(&key) != 1) { + error_print(); + return -1; + } + if (secp384r1_public_key_to_bytes(&key, &p, &len) != 1) { + error_print(); + return -1; + } + if (secp384r1_public_key_from_bytes(&key1, &cp, &len) != 1) { + error_print(); + return -1; + } + if (len) { + error_print(); + return -1; + } + if (secp384r1_public_key_equ(&key, &key1) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_public_key_to_der(void) +{ + SECP384R1_KEY key; + SECP384R1_KEY key1; + uint8_t bytes[512]; + uint8_t *p = bytes; + const uint8_t *cp = bytes; + size_t len = 0; + + if (secp384r1_key_generate(&key) != 1) { + error_print(); + return -1; + } + if (secp384r1_public_key_to_der(&key, &p, &len) != 1) { + error_print(); + return -1; + } + if (secp384r1_public_key_from_der(&key1, &cp, &len) != 1) { + error_print(); + return -1; + } + if (len) { + error_print(); + return -1; + } + if (secp384r1_public_key_equ(&key, &key1) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_private_key_to_der(void) +{ + SECP384R1_KEY key; + SECP384R1_KEY key1; + uint8_t bytes[512]; + uint8_t *p = bytes; + const uint8_t *cp = bytes; + size_t len = 0; + + if (secp384r1_key_generate(&key) != 1) { + error_print(); + return -1; + } + if (secp384r1_private_key_to_der(&key, &p, &len) != 1) { + error_print(); + return -1; + } + if (secp384r1_private_key_from_der(&key1, &cp, &len) != 1) { + error_print(); + return -1; + } + if (len) { + error_print(); + return -1; + } + if (secp384r1_public_key_equ(&key, &key1) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_private_key_info_to_der(void) +{ + SECP384R1_KEY key; + SECP384R1_KEY key1; + uint8_t bytes[512]; + uint8_t *p = bytes; + const uint8_t *cp = bytes; + size_t len = 0; + const uint8_t *attrs; + size_t attrslen; + + if (secp384r1_key_generate(&key) != 1) { + error_print(); + return -1; + } + if (secp384r1_private_key_info_to_der(&key, &p, &len) != 1) { + error_print(); + return -1; + } + if (secp384r1_private_key_info_from_der(&key1, &attrs, &attrslen, &cp, &len) != 1) { + error_print(); + return -1; + } + if (len) { + error_print(); + return -1; + } + if (secp384r1_public_key_equ(&key, &key1) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_private_key_info_encrypt_to_der(void) +{ + SECP384R1_KEY key; + SECP384R1_KEY key1; + uint8_t bytes[512]; + uint8_t *p = bytes; + const uint8_t *cp = bytes; + size_t len = 0; + char *pass = "password"; + const uint8_t *attrs; + size_t attrslen; + + if (secp384r1_key_generate(&key) != 1) { + error_print(); + return -1; + } + if (secp384r1_private_key_info_encrypt_to_der(&key, pass, &p, &len) != 1) { + error_print(); + return -1; + } + if (secp384r1_private_key_info_decrypt_from_der(&key1, &attrs, &attrslen, pass, &cp, &len) != 1) { + error_print(); + return -1; + } + if (len) { + error_print(); + return -1; + } + if (secp384r1_public_key_equ(&key, &key1) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_secp384r1_ecdh(void) +{ + SECP384R1_KEY key; + SECP384R1_KEY peer_key; + uint8_t peer_public_key[97]; + uint8_t shared_key[48]; + uint8_t peer_shared_key[48]; + uint8_t *p = peer_public_key; + size_t len = 0; + + if (secp384r1_key_generate(&key) != 1 + || secp384r1_key_generate(&peer_key) != 1 + || secp384r1_do_ecdh(&key, &peer_key, shared_key) != 1 + || secp384r1_do_ecdh(&peer_key, &key, peer_shared_key) != 1) { + error_print(); + return -1; + } + if (memcmp(shared_key, peer_shared_key, sizeof(shared_key)) != 0) { + error_print(); + return -1; + } + if (secp384r1_public_key_to_bytes(&peer_key, &p, &len) != 1 + || len != sizeof(peer_public_key) + || secp384r1_ecdh(&key, peer_public_key, peer_shared_key) != 1) { + error_print(); + return -1; + } + if (memcmp(shared_key, peer_shared_key, sizeof(shared_key)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + + + + + + + + +int main(void) +{ + if (test_secp384r1_key_generate() != 1) goto err; + if (test_secp384r1_key_set_private_key() != 1) goto err; + if (test_secp384r1_public_key_to_bytes() != 1) goto err; + if (test_secp384r1_public_key_to_der() != 1) goto err; + if (test_secp384r1_private_key_to_der() != 1) goto err; + if (test_secp384r1_private_key_info_to_der() != 1) goto err; + if (test_secp384r1_private_key_info_encrypt_to_der() != 1) goto err; + if (test_secp384r1_ecdh() != 1) goto err; + + printf("%s all tests passed\n", __FILE__); + return 0; +err: + error_print(); + return 1; +}