1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright 2017 Ribose Inc. All Rights Reserved. 4e1051a39Sopenharmony_ci * Ported from Ribose contributions from Botan. 5e1051a39Sopenharmony_ci * 6e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 7e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 8e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 9e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 10e1051a39Sopenharmony_ci */ 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include "internal/deprecated.h" 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#include "crypto/sm2.h" 15e1051a39Sopenharmony_ci#include "crypto/sm2err.h" 16e1051a39Sopenharmony_ci#include "crypto/ec.h" /* ossl_ec_group_do_inverse_ord() */ 17e1051a39Sopenharmony_ci#include "internal/numbers.h" 18e1051a39Sopenharmony_ci#include <openssl/err.h> 19e1051a39Sopenharmony_ci#include <openssl/evp.h> 20e1051a39Sopenharmony_ci#include <openssl/err.h> 21e1051a39Sopenharmony_ci#include <openssl/bn.h> 22e1051a39Sopenharmony_ci#include <string.h> 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ciint ossl_sm2_compute_z_digest(uint8_t *out, 25e1051a39Sopenharmony_ci const EVP_MD *digest, 26e1051a39Sopenharmony_ci const uint8_t *id, 27e1051a39Sopenharmony_ci const size_t id_len, 28e1051a39Sopenharmony_ci const EC_KEY *key) 29e1051a39Sopenharmony_ci{ 30e1051a39Sopenharmony_ci int rc = 0; 31e1051a39Sopenharmony_ci const EC_GROUP *group = EC_KEY_get0_group(key); 32e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 33e1051a39Sopenharmony_ci EVP_MD_CTX *hash = NULL; 34e1051a39Sopenharmony_ci BIGNUM *p = NULL; 35e1051a39Sopenharmony_ci BIGNUM *a = NULL; 36e1051a39Sopenharmony_ci BIGNUM *b = NULL; 37e1051a39Sopenharmony_ci BIGNUM *xG = NULL; 38e1051a39Sopenharmony_ci BIGNUM *yG = NULL; 39e1051a39Sopenharmony_ci BIGNUM *xA = NULL; 40e1051a39Sopenharmony_ci BIGNUM *yA = NULL; 41e1051a39Sopenharmony_ci int p_bytes = 0; 42e1051a39Sopenharmony_ci uint8_t *buf = NULL; 43e1051a39Sopenharmony_ci uint16_t entl = 0; 44e1051a39Sopenharmony_ci uint8_t e_byte = 0; 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_ci hash = EVP_MD_CTX_new(); 47e1051a39Sopenharmony_ci ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key)); 48e1051a39Sopenharmony_ci if (hash == NULL || ctx == NULL) { 49e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 50e1051a39Sopenharmony_ci goto done; 51e1051a39Sopenharmony_ci } 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci p = BN_CTX_get(ctx); 54e1051a39Sopenharmony_ci a = BN_CTX_get(ctx); 55e1051a39Sopenharmony_ci b = BN_CTX_get(ctx); 56e1051a39Sopenharmony_ci xG = BN_CTX_get(ctx); 57e1051a39Sopenharmony_ci yG = BN_CTX_get(ctx); 58e1051a39Sopenharmony_ci xA = BN_CTX_get(ctx); 59e1051a39Sopenharmony_ci yA = BN_CTX_get(ctx); 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci if (yA == NULL) { 62e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 63e1051a39Sopenharmony_ci goto done; 64e1051a39Sopenharmony_ci } 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ci if (!EVP_DigestInit(hash, digest)) { 67e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 68e1051a39Sopenharmony_ci goto done; 69e1051a39Sopenharmony_ci } 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */ 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci if (id_len >= (UINT16_MAX / 8)) { 74e1051a39Sopenharmony_ci /* too large */ 75e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_ID_TOO_LARGE); 76e1051a39Sopenharmony_ci goto done; 77e1051a39Sopenharmony_ci } 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci entl = (uint16_t)(8 * id_len); 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci e_byte = entl >> 8; 82e1051a39Sopenharmony_ci if (!EVP_DigestUpdate(hash, &e_byte, 1)) { 83e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 84e1051a39Sopenharmony_ci goto done; 85e1051a39Sopenharmony_ci } 86e1051a39Sopenharmony_ci e_byte = entl & 0xFF; 87e1051a39Sopenharmony_ci if (!EVP_DigestUpdate(hash, &e_byte, 1)) { 88e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 89e1051a39Sopenharmony_ci goto done; 90e1051a39Sopenharmony_ci } 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_ci if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) { 93e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 94e1051a39Sopenharmony_ci goto done; 95e1051a39Sopenharmony_ci } 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci if (!EC_GROUP_get_curve(group, p, a, b, ctx)) { 98e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); 99e1051a39Sopenharmony_ci goto done; 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci p_bytes = BN_num_bytes(p); 103e1051a39Sopenharmony_ci buf = OPENSSL_zalloc(p_bytes); 104e1051a39Sopenharmony_ci if (buf == NULL) { 105e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 106e1051a39Sopenharmony_ci goto done; 107e1051a39Sopenharmony_ci } 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ci if (BN_bn2binpad(a, buf, p_bytes) < 0 110e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 111e1051a39Sopenharmony_ci || BN_bn2binpad(b, buf, p_bytes) < 0 112e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 113e1051a39Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, 114e1051a39Sopenharmony_ci EC_GROUP_get0_generator(group), 115e1051a39Sopenharmony_ci xG, yG, ctx) 116e1051a39Sopenharmony_ci || BN_bn2binpad(xG, buf, p_bytes) < 0 117e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 118e1051a39Sopenharmony_ci || BN_bn2binpad(yG, buf, p_bytes) < 0 119e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 120e1051a39Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, 121e1051a39Sopenharmony_ci EC_KEY_get0_public_key(key), 122e1051a39Sopenharmony_ci xA, yA, ctx) 123e1051a39Sopenharmony_ci || BN_bn2binpad(xA, buf, p_bytes) < 0 124e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 125e1051a39Sopenharmony_ci || BN_bn2binpad(yA, buf, p_bytes) < 0 126e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hash, buf, p_bytes) 127e1051a39Sopenharmony_ci || !EVP_DigestFinal(hash, out, NULL)) { 128e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 129e1051a39Sopenharmony_ci goto done; 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_ci rc = 1; 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci done: 135e1051a39Sopenharmony_ci OPENSSL_free(buf); 136e1051a39Sopenharmony_ci BN_CTX_free(ctx); 137e1051a39Sopenharmony_ci EVP_MD_CTX_free(hash); 138e1051a39Sopenharmony_ci return rc; 139e1051a39Sopenharmony_ci} 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_cistatic BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest, 142e1051a39Sopenharmony_ci const EC_KEY *key, 143e1051a39Sopenharmony_ci const uint8_t *id, 144e1051a39Sopenharmony_ci const size_t id_len, 145e1051a39Sopenharmony_ci const uint8_t *msg, size_t msg_len) 146e1051a39Sopenharmony_ci{ 147e1051a39Sopenharmony_ci EVP_MD_CTX *hash = EVP_MD_CTX_new(); 148e1051a39Sopenharmony_ci const int md_size = EVP_MD_get_size(digest); 149e1051a39Sopenharmony_ci uint8_t *z = NULL; 150e1051a39Sopenharmony_ci BIGNUM *e = NULL; 151e1051a39Sopenharmony_ci EVP_MD *fetched_digest = NULL; 152e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); 153e1051a39Sopenharmony_ci const char *propq = ossl_ec_key_get0_propq(key); 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci if (md_size < 0) { 156e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST); 157e1051a39Sopenharmony_ci goto done; 158e1051a39Sopenharmony_ci } 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ci z = OPENSSL_zalloc(md_size); 161e1051a39Sopenharmony_ci if (hash == NULL || z == NULL) { 162e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 163e1051a39Sopenharmony_ci goto done; 164e1051a39Sopenharmony_ci } 165e1051a39Sopenharmony_ci 166e1051a39Sopenharmony_ci fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq); 167e1051a39Sopenharmony_ci if (fetched_digest == NULL) { 168e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 169e1051a39Sopenharmony_ci goto done; 170e1051a39Sopenharmony_ci } 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ci if (!ossl_sm2_compute_z_digest(z, fetched_digest, id, id_len, key)) { 173e1051a39Sopenharmony_ci /* SM2err already called */ 174e1051a39Sopenharmony_ci goto done; 175e1051a39Sopenharmony_ci } 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ci if (!EVP_DigestInit(hash, fetched_digest) 178e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hash, z, md_size) 179e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hash, msg, msg_len) 180e1051a39Sopenharmony_ci /* reuse z buffer to hold H(Z || M) */ 181e1051a39Sopenharmony_ci || !EVP_DigestFinal(hash, z, NULL)) { 182e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 183e1051a39Sopenharmony_ci goto done; 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci e = BN_bin2bn(z, md_size, NULL); 187e1051a39Sopenharmony_ci if (e == NULL) 188e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 189e1051a39Sopenharmony_ci 190e1051a39Sopenharmony_ci done: 191e1051a39Sopenharmony_ci EVP_MD_free(fetched_digest); 192e1051a39Sopenharmony_ci OPENSSL_free(z); 193e1051a39Sopenharmony_ci EVP_MD_CTX_free(hash); 194e1051a39Sopenharmony_ci return e; 195e1051a39Sopenharmony_ci} 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_cistatic ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) 198e1051a39Sopenharmony_ci{ 199e1051a39Sopenharmony_ci const BIGNUM *dA = EC_KEY_get0_private_key(key); 200e1051a39Sopenharmony_ci const EC_GROUP *group = EC_KEY_get0_group(key); 201e1051a39Sopenharmony_ci const BIGNUM *order = EC_GROUP_get0_order(group); 202e1051a39Sopenharmony_ci ECDSA_SIG *sig = NULL; 203e1051a39Sopenharmony_ci EC_POINT *kG = NULL; 204e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 205e1051a39Sopenharmony_ci BIGNUM *k = NULL; 206e1051a39Sopenharmony_ci BIGNUM *rk = NULL; 207e1051a39Sopenharmony_ci BIGNUM *r = NULL; 208e1051a39Sopenharmony_ci BIGNUM *s = NULL; 209e1051a39Sopenharmony_ci BIGNUM *x1 = NULL; 210e1051a39Sopenharmony_ci BIGNUM *tmp = NULL; 211e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); 212e1051a39Sopenharmony_ci 213e1051a39Sopenharmony_ci kG = EC_POINT_new(group); 214e1051a39Sopenharmony_ci ctx = BN_CTX_new_ex(libctx); 215e1051a39Sopenharmony_ci if (kG == NULL || ctx == NULL) { 216e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 217e1051a39Sopenharmony_ci goto done; 218e1051a39Sopenharmony_ci } 219e1051a39Sopenharmony_ci 220e1051a39Sopenharmony_ci BN_CTX_start(ctx); 221e1051a39Sopenharmony_ci k = BN_CTX_get(ctx); 222e1051a39Sopenharmony_ci rk = BN_CTX_get(ctx); 223e1051a39Sopenharmony_ci x1 = BN_CTX_get(ctx); 224e1051a39Sopenharmony_ci tmp = BN_CTX_get(ctx); 225e1051a39Sopenharmony_ci if (tmp == NULL) { 226e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 227e1051a39Sopenharmony_ci goto done; 228e1051a39Sopenharmony_ci } 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci /* 231e1051a39Sopenharmony_ci * These values are returned and so should not be allocated out of the 232e1051a39Sopenharmony_ci * context 233e1051a39Sopenharmony_ci */ 234e1051a39Sopenharmony_ci r = BN_new(); 235e1051a39Sopenharmony_ci s = BN_new(); 236e1051a39Sopenharmony_ci 237e1051a39Sopenharmony_ci if (r == NULL || s == NULL) { 238e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 239e1051a39Sopenharmony_ci goto done; 240e1051a39Sopenharmony_ci } 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci /* 243e1051a39Sopenharmony_ci * A3: Generate a random number k in [1,n-1] using random number generators; 244e1051a39Sopenharmony_ci * A4: Compute (x1,y1)=[k]G, and convert the type of data x1 to be integer 245e1051a39Sopenharmony_ci * as specified in clause 4.2.8 of GM/T 0003.1-2012; 246e1051a39Sopenharmony_ci * A5: Compute r=(e+x1) mod n. If r=0 or r+k=n, then go to A3; 247e1051a39Sopenharmony_ci * A6: Compute s=(1/(1+dA)*(k-r*dA)) mod n. If s=0, then go to A3; 248e1051a39Sopenharmony_ci * A7: Convert the type of data (r,s) to be bit strings according to the details 249e1051a39Sopenharmony_ci * in clause 4.2.2 of GM/T 0003.1-2012. Then the signature of message M is (r,s). 250e1051a39Sopenharmony_ci */ 251e1051a39Sopenharmony_ci for (;;) { 252e1051a39Sopenharmony_ci if (!BN_priv_rand_range_ex(k, order, 0, ctx)) { 253e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 254e1051a39Sopenharmony_ci goto done; 255e1051a39Sopenharmony_ci } 256e1051a39Sopenharmony_ci 257e1051a39Sopenharmony_ci if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx) 258e1051a39Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, kG, x1, NULL, 259e1051a39Sopenharmony_ci ctx) 260e1051a39Sopenharmony_ci || !BN_mod_add(r, e, x1, order, ctx)) { 261e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 262e1051a39Sopenharmony_ci goto done; 263e1051a39Sopenharmony_ci } 264e1051a39Sopenharmony_ci 265e1051a39Sopenharmony_ci /* try again if r == 0 or r+k == n */ 266e1051a39Sopenharmony_ci if (BN_is_zero(r)) 267e1051a39Sopenharmony_ci continue; 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci if (!BN_add(rk, r, k)) { 270e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 271e1051a39Sopenharmony_ci goto done; 272e1051a39Sopenharmony_ci } 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci if (BN_cmp(rk, order) == 0) 275e1051a39Sopenharmony_ci continue; 276e1051a39Sopenharmony_ci 277e1051a39Sopenharmony_ci if (!BN_add(s, dA, BN_value_one()) 278e1051a39Sopenharmony_ci || !ossl_ec_group_do_inverse_ord(group, s, s, ctx) 279e1051a39Sopenharmony_ci || !BN_mod_mul(tmp, dA, r, order, ctx) 280e1051a39Sopenharmony_ci || !BN_sub(tmp, k, tmp) 281e1051a39Sopenharmony_ci || !BN_mod_mul(s, s, tmp, order, ctx)) { 282e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 283e1051a39Sopenharmony_ci goto done; 284e1051a39Sopenharmony_ci } 285e1051a39Sopenharmony_ci 286e1051a39Sopenharmony_ci /* try again if s == 0 */ 287e1051a39Sopenharmony_ci if (BN_is_zero(s)) 288e1051a39Sopenharmony_ci continue; 289e1051a39Sopenharmony_ci 290e1051a39Sopenharmony_ci sig = ECDSA_SIG_new(); 291e1051a39Sopenharmony_ci if (sig == NULL) { 292e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 293e1051a39Sopenharmony_ci goto done; 294e1051a39Sopenharmony_ci } 295e1051a39Sopenharmony_ci 296e1051a39Sopenharmony_ci /* takes ownership of r and s */ 297e1051a39Sopenharmony_ci ECDSA_SIG_set0(sig, r, s); 298e1051a39Sopenharmony_ci break; 299e1051a39Sopenharmony_ci } 300e1051a39Sopenharmony_ci 301e1051a39Sopenharmony_ci done: 302e1051a39Sopenharmony_ci if (sig == NULL) { 303e1051a39Sopenharmony_ci BN_free(r); 304e1051a39Sopenharmony_ci BN_free(s); 305e1051a39Sopenharmony_ci } 306e1051a39Sopenharmony_ci 307e1051a39Sopenharmony_ci BN_CTX_free(ctx); 308e1051a39Sopenharmony_ci EC_POINT_free(kG); 309e1051a39Sopenharmony_ci return sig; 310e1051a39Sopenharmony_ci} 311e1051a39Sopenharmony_ci 312e1051a39Sopenharmony_cistatic int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, 313e1051a39Sopenharmony_ci const BIGNUM *e) 314e1051a39Sopenharmony_ci{ 315e1051a39Sopenharmony_ci int ret = 0; 316e1051a39Sopenharmony_ci const EC_GROUP *group = EC_KEY_get0_group(key); 317e1051a39Sopenharmony_ci const BIGNUM *order = EC_GROUP_get0_order(group); 318e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 319e1051a39Sopenharmony_ci EC_POINT *pt = NULL; 320e1051a39Sopenharmony_ci BIGNUM *t = NULL; 321e1051a39Sopenharmony_ci BIGNUM *x1 = NULL; 322e1051a39Sopenharmony_ci const BIGNUM *r = NULL; 323e1051a39Sopenharmony_ci const BIGNUM *s = NULL; 324e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); 325e1051a39Sopenharmony_ci 326e1051a39Sopenharmony_ci ctx = BN_CTX_new_ex(libctx); 327e1051a39Sopenharmony_ci pt = EC_POINT_new(group); 328e1051a39Sopenharmony_ci if (ctx == NULL || pt == NULL) { 329e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 330e1051a39Sopenharmony_ci goto done; 331e1051a39Sopenharmony_ci } 332e1051a39Sopenharmony_ci 333e1051a39Sopenharmony_ci BN_CTX_start(ctx); 334e1051a39Sopenharmony_ci t = BN_CTX_get(ctx); 335e1051a39Sopenharmony_ci x1 = BN_CTX_get(ctx); 336e1051a39Sopenharmony_ci if (x1 == NULL) { 337e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 338e1051a39Sopenharmony_ci goto done; 339e1051a39Sopenharmony_ci } 340e1051a39Sopenharmony_ci 341e1051a39Sopenharmony_ci /* 342e1051a39Sopenharmony_ci * B1: verify whether r' in [1,n-1], verification failed if not 343e1051a39Sopenharmony_ci * B2: verify whether s' in [1,n-1], verification failed if not 344e1051a39Sopenharmony_ci * B3: set M'~=ZA || M' 345e1051a39Sopenharmony_ci * B4: calculate e'=Hv(M'~) 346e1051a39Sopenharmony_ci * B5: calculate t = (r' + s') modn, verification failed if t=0 347e1051a39Sopenharmony_ci * B6: calculate the point (x1', y1')=[s']G + [t]PA 348e1051a39Sopenharmony_ci * B7: calculate R=(e'+x1') modn, verification pass if yes, otherwise failed 349e1051a39Sopenharmony_ci */ 350e1051a39Sopenharmony_ci 351e1051a39Sopenharmony_ci ECDSA_SIG_get0(sig, &r, &s); 352e1051a39Sopenharmony_ci 353e1051a39Sopenharmony_ci if (BN_cmp(r, BN_value_one()) < 0 354e1051a39Sopenharmony_ci || BN_cmp(s, BN_value_one()) < 0 355e1051a39Sopenharmony_ci || BN_cmp(order, r) <= 0 356e1051a39Sopenharmony_ci || BN_cmp(order, s) <= 0) { 357e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE); 358e1051a39Sopenharmony_ci goto done; 359e1051a39Sopenharmony_ci } 360e1051a39Sopenharmony_ci 361e1051a39Sopenharmony_ci if (!BN_mod_add(t, r, s, order, ctx)) { 362e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 363e1051a39Sopenharmony_ci goto done; 364e1051a39Sopenharmony_ci } 365e1051a39Sopenharmony_ci 366e1051a39Sopenharmony_ci if (BN_is_zero(t)) { 367e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE); 368e1051a39Sopenharmony_ci goto done; 369e1051a39Sopenharmony_ci } 370e1051a39Sopenharmony_ci 371e1051a39Sopenharmony_ci if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx) 372e1051a39Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) { 373e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); 374e1051a39Sopenharmony_ci goto done; 375e1051a39Sopenharmony_ci } 376e1051a39Sopenharmony_ci 377e1051a39Sopenharmony_ci if (!BN_mod_add(t, e, x1, order, ctx)) { 378e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 379e1051a39Sopenharmony_ci goto done; 380e1051a39Sopenharmony_ci } 381e1051a39Sopenharmony_ci 382e1051a39Sopenharmony_ci if (BN_cmp(r, t) == 0) 383e1051a39Sopenharmony_ci ret = 1; 384e1051a39Sopenharmony_ci 385e1051a39Sopenharmony_ci done: 386e1051a39Sopenharmony_ci EC_POINT_free(pt); 387e1051a39Sopenharmony_ci BN_CTX_free(ctx); 388e1051a39Sopenharmony_ci return ret; 389e1051a39Sopenharmony_ci} 390e1051a39Sopenharmony_ci 391e1051a39Sopenharmony_ciECDSA_SIG *ossl_sm2_do_sign(const EC_KEY *key, 392e1051a39Sopenharmony_ci const EVP_MD *digest, 393e1051a39Sopenharmony_ci const uint8_t *id, 394e1051a39Sopenharmony_ci const size_t id_len, 395e1051a39Sopenharmony_ci const uint8_t *msg, size_t msg_len) 396e1051a39Sopenharmony_ci{ 397e1051a39Sopenharmony_ci BIGNUM *e = NULL; 398e1051a39Sopenharmony_ci ECDSA_SIG *sig = NULL; 399e1051a39Sopenharmony_ci 400e1051a39Sopenharmony_ci e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len); 401e1051a39Sopenharmony_ci if (e == NULL) { 402e1051a39Sopenharmony_ci /* SM2err already called */ 403e1051a39Sopenharmony_ci goto done; 404e1051a39Sopenharmony_ci } 405e1051a39Sopenharmony_ci 406e1051a39Sopenharmony_ci sig = sm2_sig_gen(key, e); 407e1051a39Sopenharmony_ci 408e1051a39Sopenharmony_ci done: 409e1051a39Sopenharmony_ci BN_free(e); 410e1051a39Sopenharmony_ci return sig; 411e1051a39Sopenharmony_ci} 412e1051a39Sopenharmony_ci 413e1051a39Sopenharmony_ciint ossl_sm2_do_verify(const EC_KEY *key, 414e1051a39Sopenharmony_ci const EVP_MD *digest, 415e1051a39Sopenharmony_ci const ECDSA_SIG *sig, 416e1051a39Sopenharmony_ci const uint8_t *id, 417e1051a39Sopenharmony_ci const size_t id_len, 418e1051a39Sopenharmony_ci const uint8_t *msg, size_t msg_len) 419e1051a39Sopenharmony_ci{ 420e1051a39Sopenharmony_ci BIGNUM *e = NULL; 421e1051a39Sopenharmony_ci int ret = 0; 422e1051a39Sopenharmony_ci 423e1051a39Sopenharmony_ci e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len); 424e1051a39Sopenharmony_ci if (e == NULL) { 425e1051a39Sopenharmony_ci /* SM2err already called */ 426e1051a39Sopenharmony_ci goto done; 427e1051a39Sopenharmony_ci } 428e1051a39Sopenharmony_ci 429e1051a39Sopenharmony_ci ret = sm2_sig_verify(key, sig, e); 430e1051a39Sopenharmony_ci 431e1051a39Sopenharmony_ci done: 432e1051a39Sopenharmony_ci BN_free(e); 433e1051a39Sopenharmony_ci return ret; 434e1051a39Sopenharmony_ci} 435e1051a39Sopenharmony_ci 436e1051a39Sopenharmony_ciint ossl_sm2_internal_sign(const unsigned char *dgst, int dgstlen, 437e1051a39Sopenharmony_ci unsigned char *sig, unsigned int *siglen, 438e1051a39Sopenharmony_ci EC_KEY *eckey) 439e1051a39Sopenharmony_ci{ 440e1051a39Sopenharmony_ci BIGNUM *e = NULL; 441e1051a39Sopenharmony_ci ECDSA_SIG *s = NULL; 442e1051a39Sopenharmony_ci int sigleni; 443e1051a39Sopenharmony_ci int ret = -1; 444e1051a39Sopenharmony_ci 445e1051a39Sopenharmony_ci if (sig == NULL) { 446e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER); 447e1051a39Sopenharmony_ci goto done; 448e1051a39Sopenharmony_ci } 449e1051a39Sopenharmony_ci 450e1051a39Sopenharmony_ci e = BN_bin2bn(dgst, dgstlen, NULL); 451e1051a39Sopenharmony_ci if (e == NULL) { 452e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 453e1051a39Sopenharmony_ci goto done; 454e1051a39Sopenharmony_ci } 455e1051a39Sopenharmony_ci 456e1051a39Sopenharmony_ci s = sm2_sig_gen(eckey, e); 457e1051a39Sopenharmony_ci if (s == NULL) { 458e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 459e1051a39Sopenharmony_ci goto done; 460e1051a39Sopenharmony_ci } 461e1051a39Sopenharmony_ci 462e1051a39Sopenharmony_ci sigleni = i2d_ECDSA_SIG(s, &sig); 463e1051a39Sopenharmony_ci if (sigleni < 0) { 464e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 465e1051a39Sopenharmony_ci goto done; 466e1051a39Sopenharmony_ci } 467e1051a39Sopenharmony_ci *siglen = (unsigned int)sigleni; 468e1051a39Sopenharmony_ci 469e1051a39Sopenharmony_ci ret = 1; 470e1051a39Sopenharmony_ci 471e1051a39Sopenharmony_ci done: 472e1051a39Sopenharmony_ci ECDSA_SIG_free(s); 473e1051a39Sopenharmony_ci BN_free(e); 474e1051a39Sopenharmony_ci return ret; 475e1051a39Sopenharmony_ci} 476e1051a39Sopenharmony_ci 477e1051a39Sopenharmony_ciint ossl_sm2_internal_verify(const unsigned char *dgst, int dgstlen, 478e1051a39Sopenharmony_ci const unsigned char *sig, int sig_len, 479e1051a39Sopenharmony_ci EC_KEY *eckey) 480e1051a39Sopenharmony_ci{ 481e1051a39Sopenharmony_ci ECDSA_SIG *s = NULL; 482e1051a39Sopenharmony_ci BIGNUM *e = NULL; 483e1051a39Sopenharmony_ci const unsigned char *p = sig; 484e1051a39Sopenharmony_ci unsigned char *der = NULL; 485e1051a39Sopenharmony_ci int derlen = -1; 486e1051a39Sopenharmony_ci int ret = -1; 487e1051a39Sopenharmony_ci 488e1051a39Sopenharmony_ci s = ECDSA_SIG_new(); 489e1051a39Sopenharmony_ci if (s == NULL) { 490e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 491e1051a39Sopenharmony_ci goto done; 492e1051a39Sopenharmony_ci } 493e1051a39Sopenharmony_ci if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) { 494e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING); 495e1051a39Sopenharmony_ci goto done; 496e1051a39Sopenharmony_ci } 497e1051a39Sopenharmony_ci /* Ensure signature uses DER and doesn't have trailing garbage */ 498e1051a39Sopenharmony_ci derlen = i2d_ECDSA_SIG(s, &der); 499e1051a39Sopenharmony_ci if (derlen != sig_len || memcmp(sig, der, derlen) != 0) { 500e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING); 501e1051a39Sopenharmony_ci goto done; 502e1051a39Sopenharmony_ci } 503e1051a39Sopenharmony_ci 504e1051a39Sopenharmony_ci e = BN_bin2bn(dgst, dgstlen, NULL); 505e1051a39Sopenharmony_ci if (e == NULL) { 506e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 507e1051a39Sopenharmony_ci goto done; 508e1051a39Sopenharmony_ci } 509e1051a39Sopenharmony_ci 510e1051a39Sopenharmony_ci ret = sm2_sig_verify(eckey, s, e); 511e1051a39Sopenharmony_ci 512e1051a39Sopenharmony_ci done: 513e1051a39Sopenharmony_ci OPENSSL_free(der); 514e1051a39Sopenharmony_ci BN_free(e); 515e1051a39Sopenharmony_ci ECDSA_SIG_free(s); 516e1051a39Sopenharmony_ci return ret; 517e1051a39Sopenharmony_ci} 518