11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * Copyright 2017 Ribose Inc. All Rights Reserved. 41cb0ef41Sopenharmony_ci * Ported from Ribose contributions from Botan. 51cb0ef41Sopenharmony_ci * 61cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 71cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 81cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 91cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 101cb0ef41Sopenharmony_ci */ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include "internal/deprecated.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci#include "crypto/sm2.h" 151cb0ef41Sopenharmony_ci#include "crypto/sm2err.h" 161cb0ef41Sopenharmony_ci#include "crypto/ec.h" /* ossl_ec_group_do_inverse_ord() */ 171cb0ef41Sopenharmony_ci#include "internal/numbers.h" 181cb0ef41Sopenharmony_ci#include <openssl/err.h> 191cb0ef41Sopenharmony_ci#include <openssl/evp.h> 201cb0ef41Sopenharmony_ci#include <openssl/err.h> 211cb0ef41Sopenharmony_ci#include <openssl/bn.h> 221cb0ef41Sopenharmony_ci#include <string.h> 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciint ossl_sm2_compute_z_digest(uint8_t *out, 251cb0ef41Sopenharmony_ci const EVP_MD *digest, 261cb0ef41Sopenharmony_ci const uint8_t *id, 271cb0ef41Sopenharmony_ci const size_t id_len, 281cb0ef41Sopenharmony_ci const EC_KEY *key) 291cb0ef41Sopenharmony_ci{ 301cb0ef41Sopenharmony_ci int rc = 0; 311cb0ef41Sopenharmony_ci const EC_GROUP *group = EC_KEY_get0_group(key); 321cb0ef41Sopenharmony_ci BN_CTX *ctx = NULL; 331cb0ef41Sopenharmony_ci EVP_MD_CTX *hash = NULL; 341cb0ef41Sopenharmony_ci BIGNUM *p = NULL; 351cb0ef41Sopenharmony_ci BIGNUM *a = NULL; 361cb0ef41Sopenharmony_ci BIGNUM *b = NULL; 371cb0ef41Sopenharmony_ci BIGNUM *xG = NULL; 381cb0ef41Sopenharmony_ci BIGNUM *yG = NULL; 391cb0ef41Sopenharmony_ci BIGNUM *xA = NULL; 401cb0ef41Sopenharmony_ci BIGNUM *yA = NULL; 411cb0ef41Sopenharmony_ci int p_bytes = 0; 421cb0ef41Sopenharmony_ci uint8_t *buf = NULL; 431cb0ef41Sopenharmony_ci uint16_t entl = 0; 441cb0ef41Sopenharmony_ci uint8_t e_byte = 0; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci hash = EVP_MD_CTX_new(); 471cb0ef41Sopenharmony_ci ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key)); 481cb0ef41Sopenharmony_ci if (hash == NULL || ctx == NULL) { 491cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 501cb0ef41Sopenharmony_ci goto done; 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci p = BN_CTX_get(ctx); 541cb0ef41Sopenharmony_ci a = BN_CTX_get(ctx); 551cb0ef41Sopenharmony_ci b = BN_CTX_get(ctx); 561cb0ef41Sopenharmony_ci xG = BN_CTX_get(ctx); 571cb0ef41Sopenharmony_ci yG = BN_CTX_get(ctx); 581cb0ef41Sopenharmony_ci xA = BN_CTX_get(ctx); 591cb0ef41Sopenharmony_ci yA = BN_CTX_get(ctx); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci if (yA == NULL) { 621cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 631cb0ef41Sopenharmony_ci goto done; 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci if (!EVP_DigestInit(hash, digest)) { 671cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 681cb0ef41Sopenharmony_ci goto done; 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */ 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci if (id_len >= (UINT16_MAX / 8)) { 741cb0ef41Sopenharmony_ci /* too large */ 751cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_ID_TOO_LARGE); 761cb0ef41Sopenharmony_ci goto done; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci entl = (uint16_t)(8 * id_len); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci e_byte = entl >> 8; 821cb0ef41Sopenharmony_ci if (!EVP_DigestUpdate(hash, &e_byte, 1)) { 831cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 841cb0ef41Sopenharmony_ci goto done; 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci e_byte = entl & 0xFF; 871cb0ef41Sopenharmony_ci if (!EVP_DigestUpdate(hash, &e_byte, 1)) { 881cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 891cb0ef41Sopenharmony_ci goto done; 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) { 931cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 941cb0ef41Sopenharmony_ci goto done; 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci if (!EC_GROUP_get_curve(group, p, a, b, ctx)) { 981cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); 991cb0ef41Sopenharmony_ci goto done; 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci p_bytes = BN_num_bytes(p); 1031cb0ef41Sopenharmony_ci buf = OPENSSL_zalloc(p_bytes); 1041cb0ef41Sopenharmony_ci if (buf == NULL) { 1051cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 1061cb0ef41Sopenharmony_ci goto done; 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci if (BN_bn2binpad(a, buf, p_bytes) < 0 1101cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 1111cb0ef41Sopenharmony_ci || BN_bn2binpad(b, buf, p_bytes) < 0 1121cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 1131cb0ef41Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, 1141cb0ef41Sopenharmony_ci EC_GROUP_get0_generator(group), 1151cb0ef41Sopenharmony_ci xG, yG, ctx) 1161cb0ef41Sopenharmony_ci || BN_bn2binpad(xG, buf, p_bytes) < 0 1171cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 1181cb0ef41Sopenharmony_ci || BN_bn2binpad(yG, buf, p_bytes) < 0 1191cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 1201cb0ef41Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, 1211cb0ef41Sopenharmony_ci EC_KEY_get0_public_key(key), 1221cb0ef41Sopenharmony_ci xA, yA, ctx) 1231cb0ef41Sopenharmony_ci || BN_bn2binpad(xA, buf, p_bytes) < 0 1241cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 1251cb0ef41Sopenharmony_ci || BN_bn2binpad(yA, buf, p_bytes) < 0 1261cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 1271cb0ef41Sopenharmony_ci || !EVP_DigestFinal(hash, out, NULL)) { 1281cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 1291cb0ef41Sopenharmony_ci goto done; 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci rc = 1; 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci done: 1351cb0ef41Sopenharmony_ci OPENSSL_free(buf); 1361cb0ef41Sopenharmony_ci BN_CTX_free(ctx); 1371cb0ef41Sopenharmony_ci EVP_MD_CTX_free(hash); 1381cb0ef41Sopenharmony_ci return rc; 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_cistatic BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest, 1421cb0ef41Sopenharmony_ci const EC_KEY *key, 1431cb0ef41Sopenharmony_ci const uint8_t *id, 1441cb0ef41Sopenharmony_ci const size_t id_len, 1451cb0ef41Sopenharmony_ci const uint8_t *msg, size_t msg_len) 1461cb0ef41Sopenharmony_ci{ 1471cb0ef41Sopenharmony_ci EVP_MD_CTX *hash = EVP_MD_CTX_new(); 1481cb0ef41Sopenharmony_ci const int md_size = EVP_MD_get_size(digest); 1491cb0ef41Sopenharmony_ci uint8_t *z = NULL; 1501cb0ef41Sopenharmony_ci BIGNUM *e = NULL; 1511cb0ef41Sopenharmony_ci EVP_MD *fetched_digest = NULL; 1521cb0ef41Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); 1531cb0ef41Sopenharmony_ci const char *propq = ossl_ec_key_get0_propq(key); 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci if (md_size < 0) { 1561cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST); 1571cb0ef41Sopenharmony_ci goto done; 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci z = OPENSSL_zalloc(md_size); 1611cb0ef41Sopenharmony_ci if (hash == NULL || z == NULL) { 1621cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 1631cb0ef41Sopenharmony_ci goto done; 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq); 1671cb0ef41Sopenharmony_ci if (fetched_digest == NULL) { 1681cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 1691cb0ef41Sopenharmony_ci goto done; 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci if (!ossl_sm2_compute_z_digest(z, fetched_digest, id, id_len, key)) { 1731cb0ef41Sopenharmony_ci /* SM2err already called */ 1741cb0ef41Sopenharmony_ci goto done; 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci if (!EVP_DigestInit(hash, fetched_digest) 1781cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, z, md_size) 1791cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, msg, msg_len) 1801cb0ef41Sopenharmony_ci /* reuse z buffer to hold H(Z || M) */ 1811cb0ef41Sopenharmony_ci || !EVP_DigestFinal(hash, z, NULL)) { 1821cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 1831cb0ef41Sopenharmony_ci goto done; 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci e = BN_bin2bn(z, md_size, NULL); 1871cb0ef41Sopenharmony_ci if (e == NULL) 1881cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci done: 1911cb0ef41Sopenharmony_ci EVP_MD_free(fetched_digest); 1921cb0ef41Sopenharmony_ci OPENSSL_free(z); 1931cb0ef41Sopenharmony_ci EVP_MD_CTX_free(hash); 1941cb0ef41Sopenharmony_ci return e; 1951cb0ef41Sopenharmony_ci} 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_cistatic ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) 1981cb0ef41Sopenharmony_ci{ 1991cb0ef41Sopenharmony_ci const BIGNUM *dA = EC_KEY_get0_private_key(key); 2001cb0ef41Sopenharmony_ci const EC_GROUP *group = EC_KEY_get0_group(key); 2011cb0ef41Sopenharmony_ci const BIGNUM *order = EC_GROUP_get0_order(group); 2021cb0ef41Sopenharmony_ci ECDSA_SIG *sig = NULL; 2031cb0ef41Sopenharmony_ci EC_POINT *kG = NULL; 2041cb0ef41Sopenharmony_ci BN_CTX *ctx = NULL; 2051cb0ef41Sopenharmony_ci BIGNUM *k = NULL; 2061cb0ef41Sopenharmony_ci BIGNUM *rk = NULL; 2071cb0ef41Sopenharmony_ci BIGNUM *r = NULL; 2081cb0ef41Sopenharmony_ci BIGNUM *s = NULL; 2091cb0ef41Sopenharmony_ci BIGNUM *x1 = NULL; 2101cb0ef41Sopenharmony_ci BIGNUM *tmp = NULL; 2111cb0ef41Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci kG = EC_POINT_new(group); 2141cb0ef41Sopenharmony_ci ctx = BN_CTX_new_ex(libctx); 2151cb0ef41Sopenharmony_ci if (kG == NULL || ctx == NULL) { 2161cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 2171cb0ef41Sopenharmony_ci goto done; 2181cb0ef41Sopenharmony_ci } 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci BN_CTX_start(ctx); 2211cb0ef41Sopenharmony_ci k = BN_CTX_get(ctx); 2221cb0ef41Sopenharmony_ci rk = BN_CTX_get(ctx); 2231cb0ef41Sopenharmony_ci x1 = BN_CTX_get(ctx); 2241cb0ef41Sopenharmony_ci tmp = BN_CTX_get(ctx); 2251cb0ef41Sopenharmony_ci if (tmp == NULL) { 2261cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 2271cb0ef41Sopenharmony_ci goto done; 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ci /* 2311cb0ef41Sopenharmony_ci * These values are returned and so should not be allocated out of the 2321cb0ef41Sopenharmony_ci * context 2331cb0ef41Sopenharmony_ci */ 2341cb0ef41Sopenharmony_ci r = BN_new(); 2351cb0ef41Sopenharmony_ci s = BN_new(); 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci if (r == NULL || s == NULL) { 2381cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 2391cb0ef41Sopenharmony_ci goto done; 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci /* 2431cb0ef41Sopenharmony_ci * A3: Generate a random number k in [1,n-1] using random number generators; 2441cb0ef41Sopenharmony_ci * A4: Compute (x1,y1)=[k]G, and convert the type of data x1 to be integer 2451cb0ef41Sopenharmony_ci * as specified in clause 4.2.8 of GM/T 0003.1-2012; 2461cb0ef41Sopenharmony_ci * A5: Compute r=(e+x1) mod n. If r=0 or r+k=n, then go to A3; 2471cb0ef41Sopenharmony_ci * A6: Compute s=(1/(1+dA)*(k-r*dA)) mod n. If s=0, then go to A3; 2481cb0ef41Sopenharmony_ci * A7: Convert the type of data (r,s) to be bit strings according to the details 2491cb0ef41Sopenharmony_ci * in clause 4.2.2 of GM/T 0003.1-2012. Then the signature of message M is (r,s). 2501cb0ef41Sopenharmony_ci */ 2511cb0ef41Sopenharmony_ci for (;;) { 2521cb0ef41Sopenharmony_ci if (!BN_priv_rand_range_ex(k, order, 0, ctx)) { 2531cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 2541cb0ef41Sopenharmony_ci goto done; 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx) 2581cb0ef41Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, kG, x1, NULL, 2591cb0ef41Sopenharmony_ci ctx) 2601cb0ef41Sopenharmony_ci || !BN_mod_add(r, e, x1, order, ctx)) { 2611cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 2621cb0ef41Sopenharmony_ci goto done; 2631cb0ef41Sopenharmony_ci } 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ci /* try again if r == 0 or r+k == n */ 2661cb0ef41Sopenharmony_ci if (BN_is_zero(r)) 2671cb0ef41Sopenharmony_ci continue; 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ci if (!BN_add(rk, r, k)) { 2701cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 2711cb0ef41Sopenharmony_ci goto done; 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci if (BN_cmp(rk, order) == 0) 2751cb0ef41Sopenharmony_ci continue; 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci if (!BN_add(s, dA, BN_value_one()) 2781cb0ef41Sopenharmony_ci || !ossl_ec_group_do_inverse_ord(group, s, s, ctx) 2791cb0ef41Sopenharmony_ci || !BN_mod_mul(tmp, dA, r, order, ctx) 2801cb0ef41Sopenharmony_ci || !BN_sub(tmp, k, tmp) 2811cb0ef41Sopenharmony_ci || !BN_mod_mul(s, s, tmp, order, ctx)) { 2821cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 2831cb0ef41Sopenharmony_ci goto done; 2841cb0ef41Sopenharmony_ci } 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci /* try again if s == 0 */ 2871cb0ef41Sopenharmony_ci if (BN_is_zero(s)) 2881cb0ef41Sopenharmony_ci continue; 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci sig = ECDSA_SIG_new(); 2911cb0ef41Sopenharmony_ci if (sig == NULL) { 2921cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 2931cb0ef41Sopenharmony_ci goto done; 2941cb0ef41Sopenharmony_ci } 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ci /* takes ownership of r and s */ 2971cb0ef41Sopenharmony_ci ECDSA_SIG_set0(sig, r, s); 2981cb0ef41Sopenharmony_ci break; 2991cb0ef41Sopenharmony_ci } 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci done: 3021cb0ef41Sopenharmony_ci if (sig == NULL) { 3031cb0ef41Sopenharmony_ci BN_free(r); 3041cb0ef41Sopenharmony_ci BN_free(s); 3051cb0ef41Sopenharmony_ci } 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci BN_CTX_free(ctx); 3081cb0ef41Sopenharmony_ci EC_POINT_free(kG); 3091cb0ef41Sopenharmony_ci return sig; 3101cb0ef41Sopenharmony_ci} 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_cistatic int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, 3131cb0ef41Sopenharmony_ci const BIGNUM *e) 3141cb0ef41Sopenharmony_ci{ 3151cb0ef41Sopenharmony_ci int ret = 0; 3161cb0ef41Sopenharmony_ci const EC_GROUP *group = EC_KEY_get0_group(key); 3171cb0ef41Sopenharmony_ci const BIGNUM *order = EC_GROUP_get0_order(group); 3181cb0ef41Sopenharmony_ci BN_CTX *ctx = NULL; 3191cb0ef41Sopenharmony_ci EC_POINT *pt = NULL; 3201cb0ef41Sopenharmony_ci BIGNUM *t = NULL; 3211cb0ef41Sopenharmony_ci BIGNUM *x1 = NULL; 3221cb0ef41Sopenharmony_ci const BIGNUM *r = NULL; 3231cb0ef41Sopenharmony_ci const BIGNUM *s = NULL; 3241cb0ef41Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci ctx = BN_CTX_new_ex(libctx); 3271cb0ef41Sopenharmony_ci pt = EC_POINT_new(group); 3281cb0ef41Sopenharmony_ci if (ctx == NULL || pt == NULL) { 3291cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 3301cb0ef41Sopenharmony_ci goto done; 3311cb0ef41Sopenharmony_ci } 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci BN_CTX_start(ctx); 3341cb0ef41Sopenharmony_ci t = BN_CTX_get(ctx); 3351cb0ef41Sopenharmony_ci x1 = BN_CTX_get(ctx); 3361cb0ef41Sopenharmony_ci if (x1 == NULL) { 3371cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 3381cb0ef41Sopenharmony_ci goto done; 3391cb0ef41Sopenharmony_ci } 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci /* 3421cb0ef41Sopenharmony_ci * B1: verify whether r' in [1,n-1], verification failed if not 3431cb0ef41Sopenharmony_ci * B2: verify whether s' in [1,n-1], verification failed if not 3441cb0ef41Sopenharmony_ci * B3: set M'~=ZA || M' 3451cb0ef41Sopenharmony_ci * B4: calculate e'=Hv(M'~) 3461cb0ef41Sopenharmony_ci * B5: calculate t = (r' + s') modn, verification failed if t=0 3471cb0ef41Sopenharmony_ci * B6: calculate the point (x1', y1')=[s']G + [t]PA 3481cb0ef41Sopenharmony_ci * B7: calculate R=(e'+x1') modn, verification pass if yes, otherwise failed 3491cb0ef41Sopenharmony_ci */ 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci ECDSA_SIG_get0(sig, &r, &s); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci if (BN_cmp(r, BN_value_one()) < 0 3541cb0ef41Sopenharmony_ci || BN_cmp(s, BN_value_one()) < 0 3551cb0ef41Sopenharmony_ci || BN_cmp(order, r) <= 0 3561cb0ef41Sopenharmony_ci || BN_cmp(order, s) <= 0) { 3571cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE); 3581cb0ef41Sopenharmony_ci goto done; 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci if (!BN_mod_add(t, r, s, order, ctx)) { 3621cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 3631cb0ef41Sopenharmony_ci goto done; 3641cb0ef41Sopenharmony_ci } 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci if (BN_is_zero(t)) { 3671cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE); 3681cb0ef41Sopenharmony_ci goto done; 3691cb0ef41Sopenharmony_ci } 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx) 3721cb0ef41Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) { 3731cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); 3741cb0ef41Sopenharmony_ci goto done; 3751cb0ef41Sopenharmony_ci } 3761cb0ef41Sopenharmony_ci 3771cb0ef41Sopenharmony_ci if (!BN_mod_add(t, e, x1, order, ctx)) { 3781cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 3791cb0ef41Sopenharmony_ci goto done; 3801cb0ef41Sopenharmony_ci } 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci if (BN_cmp(r, t) == 0) 3831cb0ef41Sopenharmony_ci ret = 1; 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci done: 3861cb0ef41Sopenharmony_ci EC_POINT_free(pt); 3871cb0ef41Sopenharmony_ci BN_CTX_free(ctx); 3881cb0ef41Sopenharmony_ci return ret; 3891cb0ef41Sopenharmony_ci} 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ciECDSA_SIG *ossl_sm2_do_sign(const EC_KEY *key, 3921cb0ef41Sopenharmony_ci const EVP_MD *digest, 3931cb0ef41Sopenharmony_ci const uint8_t *id, 3941cb0ef41Sopenharmony_ci const size_t id_len, 3951cb0ef41Sopenharmony_ci const uint8_t *msg, size_t msg_len) 3961cb0ef41Sopenharmony_ci{ 3971cb0ef41Sopenharmony_ci BIGNUM *e = NULL; 3981cb0ef41Sopenharmony_ci ECDSA_SIG *sig = NULL; 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len); 4011cb0ef41Sopenharmony_ci if (e == NULL) { 4021cb0ef41Sopenharmony_ci /* SM2err already called */ 4031cb0ef41Sopenharmony_ci goto done; 4041cb0ef41Sopenharmony_ci } 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_ci sig = sm2_sig_gen(key, e); 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci done: 4091cb0ef41Sopenharmony_ci BN_free(e); 4101cb0ef41Sopenharmony_ci return sig; 4111cb0ef41Sopenharmony_ci} 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ciint ossl_sm2_do_verify(const EC_KEY *key, 4141cb0ef41Sopenharmony_ci const EVP_MD *digest, 4151cb0ef41Sopenharmony_ci const ECDSA_SIG *sig, 4161cb0ef41Sopenharmony_ci const uint8_t *id, 4171cb0ef41Sopenharmony_ci const size_t id_len, 4181cb0ef41Sopenharmony_ci const uint8_t *msg, size_t msg_len) 4191cb0ef41Sopenharmony_ci{ 4201cb0ef41Sopenharmony_ci BIGNUM *e = NULL; 4211cb0ef41Sopenharmony_ci int ret = 0; 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len); 4241cb0ef41Sopenharmony_ci if (e == NULL) { 4251cb0ef41Sopenharmony_ci /* SM2err already called */ 4261cb0ef41Sopenharmony_ci goto done; 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci ret = sm2_sig_verify(key, sig, e); 4301cb0ef41Sopenharmony_ci 4311cb0ef41Sopenharmony_ci done: 4321cb0ef41Sopenharmony_ci BN_free(e); 4331cb0ef41Sopenharmony_ci return ret; 4341cb0ef41Sopenharmony_ci} 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ciint ossl_sm2_internal_sign(const unsigned char *dgst, int dgstlen, 4371cb0ef41Sopenharmony_ci unsigned char *sig, unsigned int *siglen, 4381cb0ef41Sopenharmony_ci EC_KEY *eckey) 4391cb0ef41Sopenharmony_ci{ 4401cb0ef41Sopenharmony_ci BIGNUM *e = NULL; 4411cb0ef41Sopenharmony_ci ECDSA_SIG *s = NULL; 4421cb0ef41Sopenharmony_ci int sigleni; 4431cb0ef41Sopenharmony_ci int ret = -1; 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci e = BN_bin2bn(dgst, dgstlen, NULL); 4461cb0ef41Sopenharmony_ci if (e == NULL) { 4471cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 4481cb0ef41Sopenharmony_ci goto done; 4491cb0ef41Sopenharmony_ci } 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci s = sm2_sig_gen(eckey, e); 4521cb0ef41Sopenharmony_ci if (s == NULL) { 4531cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 4541cb0ef41Sopenharmony_ci goto done; 4551cb0ef41Sopenharmony_ci } 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci sigleni = i2d_ECDSA_SIG(s, sig != NULL ? &sig : NULL); 4581cb0ef41Sopenharmony_ci if (sigleni < 0) { 4591cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 4601cb0ef41Sopenharmony_ci goto done; 4611cb0ef41Sopenharmony_ci } 4621cb0ef41Sopenharmony_ci *siglen = (unsigned int)sigleni; 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci ret = 1; 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci done: 4671cb0ef41Sopenharmony_ci ECDSA_SIG_free(s); 4681cb0ef41Sopenharmony_ci BN_free(e); 4691cb0ef41Sopenharmony_ci return ret; 4701cb0ef41Sopenharmony_ci} 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ciint ossl_sm2_internal_verify(const unsigned char *dgst, int dgstlen, 4731cb0ef41Sopenharmony_ci const unsigned char *sig, int sig_len, 4741cb0ef41Sopenharmony_ci EC_KEY *eckey) 4751cb0ef41Sopenharmony_ci{ 4761cb0ef41Sopenharmony_ci ECDSA_SIG *s = NULL; 4771cb0ef41Sopenharmony_ci BIGNUM *e = NULL; 4781cb0ef41Sopenharmony_ci const unsigned char *p = sig; 4791cb0ef41Sopenharmony_ci unsigned char *der = NULL; 4801cb0ef41Sopenharmony_ci int derlen = -1; 4811cb0ef41Sopenharmony_ci int ret = -1; 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ci s = ECDSA_SIG_new(); 4841cb0ef41Sopenharmony_ci if (s == NULL) { 4851cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 4861cb0ef41Sopenharmony_ci goto done; 4871cb0ef41Sopenharmony_ci } 4881cb0ef41Sopenharmony_ci if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) { 4891cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING); 4901cb0ef41Sopenharmony_ci goto done; 4911cb0ef41Sopenharmony_ci } 4921cb0ef41Sopenharmony_ci /* Ensure signature uses DER and doesn't have trailing garbage */ 4931cb0ef41Sopenharmony_ci derlen = i2d_ECDSA_SIG(s, &der); 4941cb0ef41Sopenharmony_ci if (derlen != sig_len || memcmp(sig, der, derlen) != 0) { 4951cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING); 4961cb0ef41Sopenharmony_ci goto done; 4971cb0ef41Sopenharmony_ci } 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci e = BN_bin2bn(dgst, dgstlen, NULL); 5001cb0ef41Sopenharmony_ci if (e == NULL) { 5011cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 5021cb0ef41Sopenharmony_ci goto done; 5031cb0ef41Sopenharmony_ci } 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci ret = sm2_sig_verify(eckey, s, e); 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci done: 5081cb0ef41Sopenharmony_ci OPENSSL_free(der); 5091cb0ef41Sopenharmony_ci BN_free(e); 5101cb0ef41Sopenharmony_ci ECDSA_SIG_free(s); 5111cb0ef41Sopenharmony_ci return ret; 5121cb0ef41Sopenharmony_ci} 513