1 /* $OpenBSD: sm2_sign.c,v 1.4 2023/07/05 17:36:19 tb Exp $ */ 2 /* 3 * Copyright (c) 2017, 2019 Ribose Inc 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #ifndef OPENSSL_NO_SM2 19 20 #include <string.h> 21 22 #include <openssl/sm2.h> 23 #include <openssl/evp.h> 24 #include <openssl/err.h> 25 #include <openssl/bn.h> 26 27 #include "bn_local.h" 28 #include "sm2_local.h" 29 30 static BIGNUM * 31 sm2_compute_msg_hash(const EVP_MD *digest, const EC_KEY *key, 32 const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len) 33 { 34 EVP_MD_CTX *hash; 35 BIGNUM *e = NULL; 36 int md_size; 37 uint8_t *za = NULL; 38 39 if ((hash = EVP_MD_CTX_new()) == NULL) { 40 SM2error(ERR_R_MALLOC_FAILURE); 41 goto err; 42 } 43 44 if ((md_size = EVP_MD_size(digest)) < 0) { 45 SM2error(SM2_R_INVALID_DIGEST); 46 goto err; 47 } 48 49 if ((za = calloc(1, md_size)) == NULL) { 50 SM2error(ERR_R_MALLOC_FAILURE); 51 goto err; 52 } 53 54 if (!sm2_compute_userid_digest(za, digest, uid, uid_len, key)) { 55 SM2error(SM2_R_DIGEST_FAILURE); 56 goto err; 57 } 58 59 if (!EVP_DigestInit(hash, digest)) { 60 SM2error(ERR_R_EVP_LIB); 61 goto err; 62 } 63 64 if (!EVP_DigestUpdate(hash, za, md_size)) { 65 SM2error(ERR_R_EVP_LIB); 66 goto err; 67 } 68 69 if (!EVP_DigestUpdate(hash, msg, msg_len)) { 70 SM2error(ERR_R_EVP_LIB); 71 goto err; 72 } 73 74 /* reuse za buffer to hold H(ZA || M) */ 75 if (!EVP_DigestFinal(hash, za, NULL)) { 76 SM2error(ERR_R_EVP_LIB); 77 goto err; 78 } 79 80 e = BN_bin2bn(za, md_size, NULL); 81 82 err: 83 free(za); 84 EVP_MD_CTX_free(hash); 85 return e; 86 } 87 88 static ECDSA_SIG * 89 sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) 90 { 91 ECDSA_SIG *sig = NULL; 92 const EC_GROUP *group; 93 EC_POINT *kG = NULL; 94 BN_CTX *ctx = NULL; 95 const BIGNUM *dA; 96 BIGNUM *order = NULL, *r = NULL, *s = NULL; 97 BIGNUM *k, *rk, *tmp, *x1; 98 99 if ((dA = EC_KEY_get0_private_key(key)) == NULL) { 100 SM2error(SM2_R_INVALID_FIELD); 101 goto err; 102 } 103 104 if ((group = EC_KEY_get0_group(key)) == NULL) { 105 SM2error(SM2_R_INVALID_FIELD); 106 goto err; 107 } 108 109 if ((order = BN_new()) == NULL) { 110 SM2error(ERR_R_MALLOC_FAILURE); 111 goto err; 112 } 113 114 if (!EC_GROUP_get_order(group, order, NULL)) { 115 SM2error(ERR_R_EC_LIB); 116 goto err; 117 } 118 119 if ((kG = EC_POINT_new(group)) == NULL) { 120 SM2error(ERR_R_MALLOC_FAILURE); 121 goto err; 122 } 123 124 if ((ctx = BN_CTX_new()) == NULL) { 125 SM2error(ERR_R_MALLOC_FAILURE); 126 goto err; 127 } 128 129 BN_CTX_start(ctx); 130 131 if ((k = BN_CTX_get(ctx)) == NULL) { 132 SM2error(ERR_R_BN_LIB); 133 goto err; 134 } 135 if ((rk = BN_CTX_get(ctx)) == NULL) { 136 SM2error(ERR_R_BN_LIB); 137 goto err; 138 } 139 if ((x1 = BN_CTX_get(ctx)) == NULL) { 140 SM2error(ERR_R_BN_LIB); 141 goto err; 142 } 143 if ((tmp = BN_CTX_get(ctx)) == NULL) { 144 SM2error(ERR_R_BN_LIB); 145 goto err; 146 } 147 148 /* r and s are returned as part of sig, so they can't be part of ctx. */ 149 if ((r = BN_new()) == NULL) { 150 SM2error(ERR_R_MALLOC_FAILURE); 151 goto err; 152 } 153 if ((s = BN_new()) == NULL) { 154 SM2error(ERR_R_MALLOC_FAILURE); 155 goto err; 156 } 157 158 for (;;) { 159 if (!BN_rand_range(k, order)) { 160 SM2error(SM2_R_RANDOM_NUMBER_GENERATION_FAILED); 161 goto err; 162 } 163 164 if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)) { 165 SM2error(ERR_R_EC_LIB); 166 goto err; 167 } 168 169 if (!EC_POINT_get_affine_coordinates(group, kG, x1, NULL, 170 ctx)) { 171 SM2error(ERR_R_EC_LIB); 172 goto err; 173 } 174 175 if (!BN_mod_add(r, e, x1, order, ctx)) { 176 SM2error(ERR_R_BN_LIB); 177 goto err; 178 } 179 180 /* try again if r == 0 or r + k == n */ 181 if (BN_is_zero(r)) 182 continue; 183 184 if (!BN_add(rk, r, k)) { 185 SM2error(ERR_R_BN_LIB); 186 goto err; 187 } 188 189 if (BN_cmp(rk, order) == 0) 190 continue; 191 192 if (!BN_add(s, dA, BN_value_one())) { 193 SM2error(ERR_R_BN_LIB); 194 goto err; 195 } 196 197 if (BN_mod_inverse_ct(s, s, order, ctx) == NULL) { 198 SM2error(ERR_R_BN_LIB); 199 goto err; 200 } 201 202 if (!BN_mod_mul(tmp, dA, r, order, ctx)) { 203 SM2error(ERR_R_BN_LIB); 204 goto err; 205 } 206 207 if (!BN_sub(tmp, k, tmp)) { 208 SM2error(ERR_R_BN_LIB); 209 goto err; 210 } 211 212 if (!BN_mod_mul(s, s, tmp, order, ctx)) { 213 SM2error(ERR_R_BN_LIB); 214 goto err; 215 } 216 217 if ((sig = ECDSA_SIG_new()) == NULL) { 218 SM2error(ERR_R_MALLOC_FAILURE); 219 goto err; 220 } 221 222 /* sig takes ownership of r and s */ 223 if (!ECDSA_SIG_set0(sig, r, s)) { 224 SM2error(ERR_R_INTERNAL_ERROR); 225 goto err; 226 } 227 break; 228 } 229 230 err: 231 if (sig == NULL) { 232 BN_free(r); 233 BN_free(s); 234 } 235 236 BN_free(order); 237 BN_CTX_end(ctx); 238 BN_CTX_free(ctx); 239 EC_POINT_free(kG); 240 return sig; 241 } 242 243 static int 244 sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, const BIGNUM *e) 245 { 246 const EC_GROUP *group; 247 EC_POINT *pt = NULL; 248 const BIGNUM *r = NULL, *s = NULL; 249 BN_CTX *ctx = NULL; 250 BIGNUM *order, *t, *x1; 251 int ret = 0; 252 253 if ((group = EC_KEY_get0_group(key)) == NULL) { 254 SM2error(SM2_R_INVALID_FIELD); 255 goto err; 256 } 257 258 if ((ctx = BN_CTX_new()) == NULL) { 259 SM2error(ERR_R_MALLOC_FAILURE); 260 goto err; 261 } 262 263 BN_CTX_start(ctx); 264 265 if ((order = BN_CTX_get(ctx)) == NULL) { 266 SM2error(ERR_R_MALLOC_FAILURE); 267 goto err; 268 } 269 270 if (!EC_GROUP_get_order(group, order, NULL)) { 271 SM2error(ERR_R_EC_LIB); 272 goto err; 273 } 274 275 if ((pt = EC_POINT_new(group)) == NULL) { 276 SM2error(ERR_R_MALLOC_FAILURE); 277 goto err; 278 } 279 280 if ((t = BN_CTX_get(ctx)) == NULL) { 281 SM2error(ERR_R_MALLOC_FAILURE); 282 goto err; 283 } 284 if ((x1 = BN_CTX_get(ctx)) == NULL) { 285 SM2error(ERR_R_MALLOC_FAILURE); 286 goto err; 287 } 288 289 /* 290 * Section 5.3.1 in https://tools.ietf.org/html/draft-shen-sm2-ecdsa-00 291 * 292 * B1: verify that r' is in [1, n-1] 293 * B2: verify that s' is in [1, n-1] 294 * B3: set M' ~= ZA || M' 295 * B4: calculate e' = Hv(M'~) 296 * B5: verify that t = r' + s' (mod n) is not zero 297 * B6: calculate the point (x1', y1') = [s']G + [t]PA 298 * B7: verify that r' == e' + x1' (mod n) 299 */ 300 301 ECDSA_SIG_get0(sig, &r, &s); 302 303 /* B1: verify that r' is in [1, n-1] */ 304 if (BN_cmp(r, BN_value_one()) < 0 || BN_cmp(order, r) <= 0) { 305 SM2error(SM2_R_BAD_SIGNATURE); 306 goto err; 307 } 308 309 /* B2: verify that s' is in [1, n-1] */ 310 if (BN_cmp(s, BN_value_one()) < 0 || BN_cmp(order, s) <= 0) { 311 SM2error(SM2_R_BAD_SIGNATURE); 312 goto err; 313 } 314 315 /* B5: verify that t = r + s is not zero */ 316 if (!BN_mod_add(t, r, s, order, ctx)) { 317 SM2error(ERR_R_BN_LIB); 318 goto err; 319 } 320 if (BN_is_zero(t)) { 321 SM2error(SM2_R_BAD_SIGNATURE); 322 goto err; 323 } 324 325 /* B6: calculate pt = (x1', y1') = [s']G + [t]PA */ 326 if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx)) { 327 SM2error(ERR_R_EC_LIB); 328 goto err; 329 } 330 331 if (!EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) { 332 SM2error(ERR_R_EC_LIB); 333 goto err; 334 } 335 336 /* B7: verify that r' == e' + x1' (mod n) */ 337 if (!BN_mod_add(t, e, x1, order, ctx)) { 338 SM2error(ERR_R_BN_LIB); 339 goto err; 340 } 341 if (BN_cmp(r, t) == 0) 342 ret = 1; 343 344 err: 345 EC_POINT_free(pt); 346 BN_CTX_end(ctx); 347 BN_CTX_free(ctx); 348 return ret; 349 } 350 351 ECDSA_SIG * 352 sm2_do_sign(const EC_KEY *key, const EVP_MD *digest, const uint8_t *uid, 353 size_t uid_len, const uint8_t *msg, size_t msg_len) 354 { 355 ECDSA_SIG *sig = NULL; 356 BIGNUM *e; 357 358 e = sm2_compute_msg_hash(digest, key, uid, uid_len, msg, msg_len); 359 if (e == NULL) { 360 SM2error(SM2_R_DIGEST_FAILURE); 361 goto err; 362 } 363 364 sig = sm2_sig_gen(key, e); 365 366 err: 367 BN_free(e); 368 return sig; 369 } 370 371 int 372 sm2_do_verify(const EC_KEY *key, const EVP_MD *digest, const ECDSA_SIG *sig, 373 const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len) 374 { 375 BIGNUM *e; 376 int ret = -1; 377 378 e = sm2_compute_msg_hash(digest, key, uid, uid_len, msg, msg_len); 379 if (e == NULL) { 380 SM2error(SM2_R_DIGEST_FAILURE); 381 goto err; 382 } 383 384 ret = sm2_sig_verify(key, sig, e); 385 386 err: 387 BN_free(e); 388 return ret; 389 } 390 391 int 392 SM2_sign(const unsigned char *dgst, int dgstlen, unsigned char *sig, 393 unsigned int *siglen, EC_KEY *eckey) 394 { 395 BIGNUM *e; 396 ECDSA_SIG *s = NULL; 397 int outlen = 0; 398 int ret = -1; 399 400 if ((e = BN_bin2bn(dgst, dgstlen, NULL)) == NULL) { 401 SM2error(ERR_R_MALLOC_FAILURE); 402 goto err; 403 } 404 405 if ((s = sm2_sig_gen(eckey, e)) == NULL) { 406 goto err; 407 } 408 409 if ((outlen = i2d_ECDSA_SIG(s, &sig)) < 0) { 410 SM2error(SM2_R_ASN1_ERROR); 411 goto err; 412 } 413 414 *siglen = outlen; 415 ret = 1; 416 417 err: 418 ECDSA_SIG_free(s); 419 BN_free(e); 420 return ret; 421 } 422 423 int 424 SM2_verify(const unsigned char *dgst, int dgstlen, const unsigned char *sig, 425 int sig_len, EC_KEY *eckey) 426 { 427 ECDSA_SIG *s; 428 BIGNUM *e = NULL; 429 const unsigned char *p = sig; 430 unsigned char *der = NULL; 431 int derlen = -1; 432 int ret = -1; 433 434 if ((s = ECDSA_SIG_new()) == NULL) { 435 SM2error(ERR_R_MALLOC_FAILURE); 436 goto err; 437 } 438 439 if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) { 440 SM2error(SM2_R_INVALID_ENCODING); 441 goto err; 442 } 443 444 /* Ensure signature uses DER and doesn't have trailing garbage */ 445 derlen = i2d_ECDSA_SIG(s, &der); 446 if (derlen != sig_len || memcmp(sig, der, derlen) != 0) { 447 SM2error(SM2_R_INVALID_ENCODING); 448 goto err; 449 } 450 451 if ((e = BN_bin2bn(dgst, dgstlen, NULL)) == NULL) { 452 SM2error(ERR_R_BN_LIB); 453 goto err; 454 } 455 456 ret = sm2_sig_verify(eckey, s, e); 457 458 err: 459 free(der); 460 BN_free(e); 461 ECDSA_SIG_free(s); 462 return ret; 463 } 464 465 #endif /* OPENSSL_NO_SM2 */ 466