From f8fbeddd4f2537680511868002b5b8719fa25ef2 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Thu, 25 Apr 2024 08:40:39 +0800 Subject: [PATCH] Add SM2_VERIFY_CTX --- include/gmssl/sm2.h | 21 ++++++-- include/gmssl/sm2_z256.h | 3 ++ src/sm2_sign.c | 103 +++++++++++++++++++++++++++++++++++---- src/sm2_z256.c | 91 +++++++++++++++++++++++++++++++--- src/tlcp.c | 4 +- src/tls.c | 10 ++-- src/tls13.c | 2 +- src/x509_cer.c | 2 +- tests/sm2_signtest.c | 19 ++++---- tools/sm2verify.c | 2 +- 10 files changed, 216 insertions(+), 41 deletions(-) diff --git a/include/gmssl/sm2.h b/include/gmssl/sm2.h index f14b583e..72f13681 100644 --- a/include/gmssl/sm2.h +++ b/include/gmssl/sm2.h @@ -139,6 +139,8 @@ typedef struct { int sm2_fast_sign_pre_compute(SM2_SIGN_PRE_COMP pre_comp[32]); int sm2_fast_sign(const sm2_z256_t fast_private, SM2_SIGN_PRE_COMP *pre_comp, const uint8_t dgst[32], SM2_SIGNATURE *sig); +int sm2_fast_verify(const SM2_Z256_POINT point_table[16], + const uint8_t dgst[32], const SM2_SIGNATURE *sig); #define SM2_MIN_SIGNATURE_SIZE 8 @@ -175,18 +177,29 @@ typedef struct { sm2_z256_t fast_sign_private; SM2_SIGN_PRE_COMP pre_comp[SM2_SIGN_PRE_COMP_COUNT]; unsigned int num_pre_comp; + + // verify public point table, P, 2P, ..., 16P + SM2_Z256_POINT public_point_table[16]; } SM2_SIGN_CTX; _gmssl_export int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen); _gmssl_export int sm2_sign_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); _gmssl_export int sm2_sign_finish(SM2_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen); +_gmssl_export int sm2_sign_reset(SM2_SIGN_CTX *ctx); int sm2_sign_finish_fixlen(SM2_SIGN_CTX *ctx, size_t siglen, uint8_t *sig); -_gmssl_export int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen); -_gmssl_export int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); -_gmssl_export int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen); +typedef struct { + SM3_CTX sm3_ctx; + SM3_CTX saved_sm3_ctx; + SM2_KEY key; + SM2_Z256_POINT public_point_table[16]; +} SM2_VERIFY_CTX; + +_gmssl_export int sm2_verify_init(SM2_VERIFY_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen); +_gmssl_export int sm2_verify_update(SM2_VERIFY_CTX *ctx, const uint8_t *data, size_t datalen); +_gmssl_export int sm2_verify_finish(SM2_VERIFY_CTX *ctx, const uint8_t *sig, size_t siglen); +_gmssl_export int sm2_verify_reset(SM2_VERIFY_CTX *ctx); -_gmssl_export int sm2_sign_ctx_reset(SM2_SIGN_CTX *ctx); /* SM2Cipher ::= SEQUENCE { diff --git a/include/gmssl/sm2_z256.h b/include/gmssl/sm2_z256.h index 47fed5a5..15162c3a 100644 --- a/include/gmssl/sm2_z256.h +++ b/include/gmssl/sm2_z256.h @@ -110,9 +110,12 @@ void sm2_z256_point_sub_affine(SM2_Z256_POINT *R, const SM2_Z256_POINT *A, const int sm2_z256_point_affine_print(FILE *fp, int fmt, int ind, const char *label, const SM2_Z256_AFFINE_POINT *P); void sm2_z256_point_mul_generator(SM2_Z256_POINT *R, const uint64_t k[4]); +void sm2_z256_point_mul_pre_compute(const SM2_Z256_POINT *P, SM2_Z256_POINT T[16]); +void sm2_z256_point_mul_ex(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_POINT P_table[16]); void sm2_z256_point_mul(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_POINT *P); void sm2_z256_point_mul_sum(SM2_Z256_POINT *R, const uint64_t t[4], const SM2_Z256_POINT *P, const uint64_t s[4]); + const uint64_t *sm2_z256_prime(void); const uint64_t *sm2_z256_order(void); const uint64_t *sm2_z256_order_minus_one(void); diff --git a/src/sm2_sign.c b/src/sm2_sign.c index fbcbf721..312b7bed 100644 --- a/src/sm2_sign.c +++ b/src/sm2_sign.c @@ -203,9 +203,10 @@ int sm2_fast_sign(const sm2_z256_t fast_private, SM2_SIGN_PRE_COMP *pre_comp, return 1; } -int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig) +int sm2_fast_verify(const SM2_Z256_POINT point_table[16], const uint8_t dgst[32], const SM2_SIGNATURE *sig) { SM2_Z256_POINT R; + SM2_Z256_POINT T; sm2_z256_t r; sm2_z256_t s; sm2_z256_t e; @@ -240,7 +241,72 @@ int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATUR } // Q(x,y) = s * G + t * P - sm2_z256_point_mul_sum(&R, t, &key->public_key, s); + sm2_z256_point_mul_generator(&R, s); + sm2_z256_point_mul_ex(&T, t, point_table); + sm2_z256_point_add(&R, &R, &T); + sm2_z256_point_get_xy(&R, x, NULL); + + // e = H(M) + sm2_z256_from_bytes(e, dgst); + if (sm2_z256_cmp(e, sm2_z256_order()) >= 0) { + sm2_z256_sub(e, e, sm2_z256_order()); + } + + // r' = e + x (mod n) + if (sm2_z256_cmp(x, sm2_z256_order()) >= 0) { + sm2_z256_sub(x, x, sm2_z256_order()); + } + sm2_z256_modn_add(e, e, x); + + // check if r == r' + if (sm2_z256_cmp(e, r) != 0) { + error_print(); + return -1; + } + return 1; +} + +int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig) +{ + SM2_Z256_POINT R; + SM2_Z256_POINT T; + sm2_z256_t r; + sm2_z256_t s; + sm2_z256_t e; + sm2_z256_t x; + sm2_z256_t t; + + // check r, s in [1, n-1] + sm2_z256_from_bytes(r, sig->r); + if (sm2_z256_is_zero(r) == 1) { + error_print(); + return -1; + } + if (sm2_z256_cmp(r, sm2_z256_order()) >= 0) { + error_print(); + return -1; + } + sm2_z256_from_bytes(s, sig->s); + if (sm2_z256_is_zero(s) == 1) { + error_print(); + return -1; + } + if (sm2_z256_cmp(s, sm2_z256_order()) >= 0) { + error_print(); + return -1; + } + + // t = r + s (mod n), check t != 0 + sm2_z256_modn_add(t, r, s); + if (sm2_z256_is_zero(t)) { + error_print(); + return -1; + } + + // Q(x,y) = s * G + t * P + sm2_z256_point_mul_generator(&R, s); + sm2_z256_point_mul(&T, t, &key->public_key); + sm2_z256_point_add(&R, &R, &T); sm2_z256_point_get_xy(&R, x, NULL); // e = H(M) @@ -471,7 +537,7 @@ int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t return 1; } -int sm2_sign_ctx_reset(SM2_SIGN_CTX *ctx) +int sm2_sign_reset(SM2_SIGN_CTX *ctx) { ctx->sm3_ctx = ctx->saved_sm3_ctx; return 1; @@ -541,7 +607,7 @@ int sm2_sign_finish_fixlen(SM2_SIGN_CTX *ctx, size_t siglen, uint8_t *sig) return 1; } -int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen) +int sm2_verify_init(SM2_VERIFY_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen) { if (!ctx || !key) { error_print(); @@ -565,14 +631,13 @@ int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_ error_print(); return -1; } - sm2_z256_set_zero(ctx->fast_sign_private); - memset(ctx->pre_comp, 0, sizeof(SM2_SIGN_PRE_COMP) * SM2_SIGN_PRE_COMP_COUNT); + sm2_z256_point_mul_pre_compute(&key->public_key, ctx->public_point_table); return 1; } -int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) +int sm2_verify_update(SM2_VERIFY_CTX *ctx, const uint8_t *data, size_t datalen) { if (!ctx) { error_print(); @@ -584,18 +649,36 @@ int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) return 1; } -int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen) +int sm2_verify_finish(SM2_VERIFY_CTX *ctx, const uint8_t *sigbuf, size_t siglen) { uint8_t dgst[SM3_DIGEST_SIZE]; + SM2_SIGNATURE sig; - if (!ctx || !sig) { + if (!ctx || !sigbuf) { error_print(); return -1; } + + if (sm2_signature_from_der(&sig, &sigbuf, &siglen) != 1 + || asn1_length_is_zero(siglen) != 1) { + error_print(); + return -1; + } + sm3_finish(&ctx->sm3_ctx, dgst); - if (sm2_verify(&ctx->key, dgst, sig, siglen) != 1) { + + if (sm2_fast_verify(ctx->public_point_table, dgst, &sig) != 1) { error_print(); return -1; } + return 1; } + +int sm2_verify_reset(SM2_VERIFY_CTX *ctx) +{ + ctx->sm3_ctx = ctx->saved_sm3_ctx; + return 1; +} + + diff --git a/src/sm2_z256.c b/src/sm2_z256.c index 1e6d5b35..4407c120 100644 --- a/src/sm2_z256.c +++ b/src/sm2_z256.c @@ -1371,15 +1371,8 @@ void sm2_z256_point_sub(SM2_Z256_POINT *R, const SM2_Z256_POINT *A, const SM2_Z2 sm2_z256_point_add(R, A, &neg_B); } -void sm2_z256_point_mul(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_POINT *P) +void sm2_z256_point_mul_pre_compute(const SM2_Z256_POINT *P, SM2_Z256_POINT T[16]) { - int window_size = 5; - SM2_Z256_POINT T[16]; - int R_infinity = 1; - int n = (256 + window_size - 1)/window_size; - int i; - - // T[i] = (i + 1) * P memcpy(&T[0], P, sizeof(SM2_Z256_POINT)); /* @@ -1416,6 +1409,88 @@ void sm2_z256_point_mul(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_P sm2_z256_point_add(&T[13-1], &T[7-1], &T[6-1]); sm2_z256_point_add(&T[15-1], &T[8-1], &T[7-1]); +} + +void sm2_z256_point_mul_ex(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_POINT *T) +{ + int window_size = 5; + int R_infinity = 1; + int n = (256 + window_size - 1)/window_size; + int i; + + for (i = n - 1; i >= 0; i--) { + int booth = sm2_z256_get_booth(k, window_size, i); + + if (R_infinity) { + if (booth != 0) { + *R = T[booth - 1]; + R_infinity = 0; + } + } else { + sm2_z256_point_dbl_x5(R, R); + + if (booth > 0) { + sm2_z256_point_add(R, R, &T[booth - 1]); + } else if (booth < 0) { + sm2_z256_point_sub(R, R, &T[-booth - 1]); + } + } + } + + if (R_infinity) { + memset(R, 0, sizeof(*R)); + } + +} + +void sm2_z256_point_mul(SM2_Z256_POINT *R, const uint64_t k[4], const SM2_Z256_POINT *P) +{ + int window_size = 5; + SM2_Z256_POINT T[16]; + int R_infinity = 1; + int n = (256 + window_size - 1)/window_size; + int i; + +#if 0 + sm2_z256_point_mul_pre_compute(P, T); +#else + // T[i] = (i + 1) * P + memcpy(&T[0], P, sizeof(SM2_Z256_POINT)); + + /* + sm2_z256_point_dbl(&T[ 1], &T[ 0]); + sm2_z256_point_add(&T[ 2], &T[ 1], P); + sm2_z256_point_dbl(&T[ 3], &T[ 1]); + sm2_z256_point_add(&T[ 4], &T[ 3], P); + sm2_z256_point_dbl(&T[ 5], &T[ 2]); + sm2_z256_point_add(&T[ 6], &T[ 5], P); + sm2_z256_point_dbl(&T[ 7], &T[ 3]); + sm2_z256_point_add(&T[ 8], &T[ 7], P); + sm2_z256_point_dbl(&T[ 9], &T[ 4]); + sm2_z256_point_add(&T[10], &T[ 9], P); + sm2_z256_point_dbl(&T[11], &T[ 5]); + sm2_z256_point_add(&T[12], &T[11], P); + sm2_z256_point_dbl(&T[13], &T[ 6]); + sm2_z256_point_add(&T[14], &T[13], P); + sm2_z256_point_dbl(&T[15], &T[ 7]); + */ + + sm2_z256_point_dbl(&T[2-1], &T[1-1]); + sm2_z256_point_dbl(&T[4-1], &T[2-1]); + sm2_z256_point_dbl(&T[8-1], &T[4-1]); + sm2_z256_point_dbl(&T[16-1], &T[8-1]); + sm2_z256_point_add(&T[3-1], &T[2-1], P); + sm2_z256_point_dbl(&T[6-1], &T[3-1]); + sm2_z256_point_dbl(&T[12-1], &T[6-1]); + sm2_z256_point_add(&T[5-1], &T[3-1], &T[2-1]); + sm2_z256_point_dbl(&T[10-1], &T[5-1]); + sm2_z256_point_add(&T[7-1], &T[4-1], &T[3-1]); + sm2_z256_point_dbl(&T[14-1], &T[7-1]); + sm2_z256_point_add(&T[9-1], &T[4-1], &T[5-1]); + sm2_z256_point_add(&T[11-1], &T[6-1], &T[5-1]); + sm2_z256_point_add(&T[13-1], &T[7-1], &T[6-1]); + sm2_z256_point_add(&T[15-1], &T[8-1], &T[7-1]); +#endif for (i = n - 1; i >= 0; i--) { int booth = sm2_z256_get_booth(k, window_size, i); diff --git a/src/tlcp.c b/src/tlcp.c index 5e8654b8..9ca0eddc 100644 --- a/src/tlcp.c +++ b/src/tlcp.c @@ -147,7 +147,7 @@ int tlcp_do_connect(TLS_CONNECT *conn) SM2_KEY server_sign_key; SM2_KEY server_enc_key; - SM2_SIGN_CTX verify_ctx; + SM2_VERIFY_CTX verify_ctx; SM2_SIGN_CTX sign_ctx; const uint8_t *sig; size_t siglen; @@ -605,7 +605,7 @@ int tlcp_do_accept(TLS_CONNECT *conn) // ClientCertificate, CertificateVerify SM2_KEY client_sign_key; - SM2_SIGN_CTX verify_ctx; + SM2_VERIFY_CTX verify_ctx; const uint8_t *sig; const int verify_depth = 5; int verify_result; diff --git a/src/tls.c b/src/tls.c index 4ae04ab3..b2d43af1 100644 --- a/src/tls.c +++ b/src/tls.c @@ -568,7 +568,7 @@ int tls_verify_server_ecdh_params(const SM2_KEY *server_sign_key, { int ret; uint8_t server_ecdh_params[69]; - SM2_SIGN_CTX verify_ctx; + SM2_VERIFY_CTX verify_ctx; if (!server_sign_key || !client_random || !server_random || curve != TLS_curve_sm2p256v1 || !point || !sig || !siglen @@ -1973,7 +1973,7 @@ int tls_client_verify_update(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *handshak int tls_client_verify_finish(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *sig, size_t siglen, const SM2_KEY *public_key) { int ret; - SM2_SIGN_CTX sm2_ctx; + SM2_VERIFY_CTX verify_ctx; int i; if (!ctx || !sig || !siglen || !public_key) { @@ -1985,17 +1985,17 @@ int tls_client_verify_finish(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *sig, siz error_print(); return -1; } - if (sm2_verify_init(&sm2_ctx, public_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + if (sm2_verify_init(&verify_ctx, public_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { error_print(); return -1; } for (i = 0; i < 8; i++) { - if (sm2_verify_update(&sm2_ctx, ctx->handshake[i], ctx->handshake_len[i]) != 1) { + if (sm2_verify_update(&verify_ctx, ctx->handshake[i], ctx->handshake_len[i]) != 1) { error_print(); return -1; } } - if ((ret = sm2_verify_finish(&sm2_ctx, sig, siglen)) < 0) { + if ((ret = sm2_verify_finish(&verify_ctx, sig, siglen)) < 0) { error_print(); return -1; } diff --git a/src/tls13.c b/src/tls13.c index 2124afd2..e875b94c 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -526,7 +526,7 @@ int tls13_verify_certificate_verify(int tls_mode, const DIGEST_CTX *tbs_dgst_ctx, const uint8_t *sig, size_t siglen) { int ret; - SM2_SIGN_CTX verify_ctx; + SM2_VERIFY_CTX verify_ctx; uint8_t prefix[64]; const uint8_t *context_str_and_zero; size_t context_str_and_zero_len; diff --git a/src/x509_cer.c b/src/x509_cer.c index 218ace8e..a690a4e3 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -1204,7 +1204,7 @@ int x509_signed_verify(const uint8_t *a, size_t alen, int sig_alg; const uint8_t *sig; size_t siglen; - SM2_SIGN_CTX verify_ctx; + SM2_VERIFY_CTX verify_ctx; if (x509_signed_from_der(&tbs, &tbslen, &sig_alg, &sig, &siglen, &a, &alen) != 1 || asn1_length_is_zero(alen) != 1) { diff --git a/tests/sm2_signtest.c b/tests/sm2_signtest.c index 93a6e7c4..3c1757cf 100644 --- a/tests/sm2_signtest.c +++ b/tests/sm2_signtest.c @@ -202,7 +202,7 @@ static int test_sm2_sign_ctx_speed(void) return -1; } - sm2_sign_ctx_reset(&sign_ctx); + sm2_sign_reset(&sign_ctx); } end = clock(); @@ -219,6 +219,7 @@ static int test_sm2_sign_ctx(void) int ret; SM2_KEY sm2_key; SM2_SIGN_CTX sign_ctx; + SM2_VERIFY_CTX verify_ctx; uint8_t msg[] = "Hello World!"; uint8_t sig[SM2_MAX_SIGNATURE_SIZE] = {0}; size_t siglen; @@ -238,9 +239,9 @@ static int test_sm2_sign_ctx(void) format_bytes(stderr, 0, 4, "signature", sig, siglen); sm2_signature_print(stderr, 0, 4, "signature", sig, siglen); - if (sm2_verify_init(&sign_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 - || sm2_verify_update(&sign_ctx, msg, sizeof(msg)) != 1 - || (ret = sm2_verify_finish(&sign_ctx, sig, siglen)) != 1) { + if (sm2_verify_init(&verify_ctx, &sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 + || sm2_verify_update(&verify_ctx, msg, sizeof(msg)) != 1 + || (ret = sm2_verify_finish(&verify_ctx, sig, siglen)) != 1) { error_print(); return -1; } @@ -252,11 +253,11 @@ static int test_sm2_sign_ctx(void) return 1; } -static int test_sm2_sign_ctx_reset(void) +static int test_sm2_sign_reset(void) { SM2_KEY sm2_key; SM2_SIGN_CTX sign_ctx; - SM2_SIGN_CTX vrfy_ctx; + SM2_VERIFY_CTX vrfy_ctx; uint8_t msg[64]; uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; size_t siglen; @@ -285,7 +286,7 @@ static int test_sm2_sign_ctx_reset(void) // reset sign_ctx and sign another message rand_bytes(msg, sizeof(msg)); - if (sm2_sign_ctx_reset(&sign_ctx) != 1) { + if (sm2_sign_reset(&sign_ctx) != 1) { error_print(); return -1; } @@ -314,7 +315,7 @@ static int test_sm2_sign_ctx_reset(void) } // reset ctx and verify again - if (sm2_sign_ctx_reset(&vrfy_ctx) != 1) { + if (sm2_verify_reset(&vrfy_ctx) != 1) { error_print(); return -1; } @@ -339,7 +340,7 @@ int main(void) if (test_sm2_fast_sign() != 1) goto err; if (test_sm2_sign() != 1) goto err; if (test_sm2_sign_ctx() != 1) goto err; - if (test_sm2_sign_ctx_reset() != 1) goto err; + if (test_sm2_sign_reset() != 1) goto err; if (test_sm2_sign_ctx_speed() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; diff --git a/tools/sm2verify.c b/tools/sm2verify.c index 0e4e91b6..6d66070c 100644 --- a/tools/sm2verify.c +++ b/tools/sm2verify.c @@ -32,7 +32,7 @@ int sm2verify_main(int argc, char **argv) FILE *infp = stdin; FILE *sigfp = NULL; SM2_KEY key; - SM2_SIGN_CTX verify_ctx; + SM2_VERIFY_CTX verify_ctx; uint8_t cert[1024]; size_t certlen; uint8_t buf[4096];