1*f0865ec9SKyle Evans /* 2*f0865ec9SKyle Evans * Copyright (C) 2021 - This file is part of libecc project 3*f0865ec9SKyle Evans * 4*f0865ec9SKyle Evans * Authors: 5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com> 6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7*f0865ec9SKyle Evans * 8*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license. 9*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project. 10*f0865ec9SKyle Evans */ 11*f0865ec9SKyle Evans 12*f0865ec9SKyle Evans #include <libecc/lib_ecc_config.h> 13*f0865ec9SKyle Evans #ifdef WITH_SIG_SM2 14*f0865ec9SKyle Evans 15*f0865ec9SKyle Evans #include <libecc/nn/nn_rand.h> 16*f0865ec9SKyle Evans #include <libecc/nn/nn_mul_public.h> 17*f0865ec9SKyle Evans #include <libecc/nn/nn_logical.h> 18*f0865ec9SKyle Evans 19*f0865ec9SKyle Evans #include <libecc/sig/sig_algs_internal.h> 20*f0865ec9SKyle Evans #include <libecc/sig/ec_key.h> 21*f0865ec9SKyle Evans #include <libecc/utils/utils.h> 22*f0865ec9SKyle Evans #ifdef VERBOSE_INNER_VALUES 23*f0865ec9SKyle Evans #define EC_SIG_ALG "SM2" 24*f0865ec9SKyle Evans #endif 25*f0865ec9SKyle Evans #include <libecc/utils/dbg_sig.h> 26*f0865ec9SKyle Evans 27*f0865ec9SKyle Evans /* 28*f0865ec9SKyle Evans * NOTE: SM2 has an oddity in private key generation when compared to 29*f0865ec9SKyle Evans * other EC*DSA style signature algorithms described in ISO14888-3: 30*f0865ec9SKyle Evans * the private key x MUST be in ]0, q-1[ instead of ]0, q[ (this is actually 31*f0865ec9SKyle Evans * explained by the fact that (1 + x) must be inversible modulo q during the 32*f0865ec9SKyle Evans * signature process). 33*f0865ec9SKyle Evans * 34*f0865ec9SKyle Evans * Hence the following specific key generation function. 35*f0865ec9SKyle Evans * 36*f0865ec9SKyle Evans */ 37*f0865ec9SKyle Evans int sm2_gen_priv_key(ec_priv_key *priv_key) 38*f0865ec9SKyle Evans { 39*f0865ec9SKyle Evans int ret; 40*f0865ec9SKyle Evans nn tmp; 41*f0865ec9SKyle Evans tmp.magic = WORD(0); 42*f0865ec9SKyle Evans 43*f0865ec9SKyle Evans ret = priv_key_check_initialized_and_type(priv_key, SM2); EG(ret, err); 44*f0865ec9SKyle Evans 45*f0865ec9SKyle Evans /* Get a random value in ]0,q-1[ where q is the group generator order */ 46*f0865ec9SKyle Evans ret = nn_init(&tmp, 0); EG(ret, err); 47*f0865ec9SKyle Evans ret = nn_dec(&tmp, &(priv_key->params->ec_gen_order)); EG(ret, err); 48*f0865ec9SKyle Evans ret = nn_get_random_mod(&(priv_key->x), &tmp); 49*f0865ec9SKyle Evans 50*f0865ec9SKyle Evans err: 51*f0865ec9SKyle Evans nn_uninit(&tmp); 52*f0865ec9SKyle Evans 53*f0865ec9SKyle Evans return ret; 54*f0865ec9SKyle Evans } 55*f0865ec9SKyle Evans 56*f0865ec9SKyle Evans int sm2_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv) 57*f0865ec9SKyle Evans { 58*f0865ec9SKyle Evans prj_pt_src_t G; 59*f0865ec9SKyle Evans int ret, cmp; 60*f0865ec9SKyle Evans nn tmp; 61*f0865ec9SKyle Evans tmp.magic = WORD(0); 62*f0865ec9SKyle Evans 63*f0865ec9SKyle Evans MUST_HAVE((out_pub != NULL), ret, err); 64*f0865ec9SKyle Evans 65*f0865ec9SKyle Evans ret = priv_key_check_initialized_and_type(in_priv, SM2); EG(ret, err); 66*f0865ec9SKyle Evans 67*f0865ec9SKyle Evans /* 68*f0865ec9SKyle Evans * We verify that the private key is valid, i.e. in 69*f0865ec9SKyle Evans * ]0, q-1[. This excluded q-1 is an oddity but is what the 70*f0865ec9SKyle Evans * ISO14888-3:2018 has. 71*f0865ec9SKyle Evans */ 72*f0865ec9SKyle Evans ret = nn_init(&tmp, 0); EG(ret, err); 73*f0865ec9SKyle Evans ret = nn_dec(&tmp, &in_priv->params->ec_gen_order); EG(ret, err); 74*f0865ec9SKyle Evans /* If x >= (q - 1), this is an error */ 75*f0865ec9SKyle Evans MUST_HAVE((!nn_cmp(&(in_priv->x), &tmp, &cmp)) && (cmp < 0), ret, err); 76*f0865ec9SKyle Evans 77*f0865ec9SKyle Evans /* Y = xG */ 78*f0865ec9SKyle Evans G = &(in_priv->params->ec_gen); 79*f0865ec9SKyle Evans 80*f0865ec9SKyle Evans /* Zero init public key to be generated */ 81*f0865ec9SKyle Evans ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err); 82*f0865ec9SKyle Evans 83*f0865ec9SKyle Evans /* Use blinding with scalar_b when computing point scalar multiplication */ 84*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&(out_pub->y), &(in_priv->x), G); EG(ret, err); 85*f0865ec9SKyle Evans 86*f0865ec9SKyle Evans out_pub->key_type = SM2; 87*f0865ec9SKyle Evans out_pub->params = in_priv->params; 88*f0865ec9SKyle Evans out_pub->magic = PUB_KEY_MAGIC; 89*f0865ec9SKyle Evans 90*f0865ec9SKyle Evans err: 91*f0865ec9SKyle Evans nn_uninit(&tmp); 92*f0865ec9SKyle Evans 93*f0865ec9SKyle Evans return ret; 94*f0865ec9SKyle Evans } 95*f0865ec9SKyle Evans 96*f0865ec9SKyle Evans int sm2_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize, u8 *siglen) 97*f0865ec9SKyle Evans { 98*f0865ec9SKyle Evans int ret; 99*f0865ec9SKyle Evans 100*f0865ec9SKyle Evans MUST_HAVE((siglen != NULL), ret, err); 101*f0865ec9SKyle Evans MUST_HAVE((p_bit_len <= CURVES_MAX_P_BIT_LEN) && 102*f0865ec9SKyle Evans (q_bit_len <= CURVES_MAX_Q_BIT_LEN) && 103*f0865ec9SKyle Evans (hsize <= MAX_DIGEST_SIZE) && (blocksize <= MAX_BLOCK_SIZE), ret, err); 104*f0865ec9SKyle Evans 105*f0865ec9SKyle Evans (*siglen) = (u8)SM2_SIGLEN(q_bit_len); 106*f0865ec9SKyle Evans ret = 0; 107*f0865ec9SKyle Evans 108*f0865ec9SKyle Evans err: 109*f0865ec9SKyle Evans return ret; 110*f0865ec9SKyle Evans } 111*f0865ec9SKyle Evans 112*f0865ec9SKyle Evans /* 113*f0865ec9SKyle Evans * Helper to compute Z from user ID, curve parameters, public key and hash 114*f0865ec9SKyle Evans * function as defined in section 6.12.4.3 of ISO14888-3:2018. The function 115*f0865ec9SKyle Evans * returns 0 on success, -1 on error. On success, the number of bytes 116*f0865ec9SKyle Evans * written to Z is provided using Zlen. On input, Zlen provides the size of 117*f0865ec9SKyle Evans * Z buffer, which must be large enough for selected hash function (Z has 118*f0865ec9SKyle Evans * the digest size of the hash function). 'id' buffer of size 'id_len' must 119*f0865ec9SKyle Evans * be smaller than SM2_MAX_ID_LEN (see sm2.h). 120*f0865ec9SKyle Evans * 121*f0865ec9SKyle Evans * Z = h(ENTL || ID || FE2BS(p, a) || FE2BS(p, b) || FE2BS(p, Gx) || 122*f0865ec9SKyle Evans * FE2BS(p, Gy) || FE2BS(p, Yx) || FE2BS(p, Yy)). 123*f0865ec9SKyle Evans * 124*f0865ec9SKyle Evans * with: 125*f0865ec9SKyle Evans * 126*f0865ec9SKyle Evans * - GF(p), Finite field of cardinality p. 127*f0865ec9SKyle Evans * - Curve Weierstrass Equation y^2 = x^3 + a * x + b. 128*f0865ec9SKyle Evans * - ID string containing an identifier of the signer 129*f0865ec9SKyle Evans * - G = (Gx, Gy) an element of order q in E. 130*f0865ec9SKyle Evans * - entlen is the bit-length of ID and ENTL the two bytes string transformed 131*f0865ec9SKyle Evans * from the integer entlen, i.e. ENTL = I2BS(12, entlen). 132*f0865ec9SKyle Evans * 133*f0865ec9SKyle Evans */ 134*f0865ec9SKyle Evans #define Z_INPUT_MAX_LEN (2 + SM2_MAX_ID_LEN + (6 * BYTECEIL(CURVES_MAX_P_BIT_LEN))) 135*f0865ec9SKyle Evans 136*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int sm2_compute_Z(u8 *Z, u16 *Zlen, const u8 *id, u16 id_len, 137*f0865ec9SKyle Evans const ec_pub_key *pub_key, hash_alg_type hash_type) 138*f0865ec9SKyle Evans { 139*f0865ec9SKyle Evans u16 hsize, entlen, p_len; 140*f0865ec9SKyle Evans u8 buf[2 * BYTECEIL(CURVES_MAX_P_BIT_LEN)]; 141*f0865ec9SKyle Evans const hash_mapping *hm; 142*f0865ec9SKyle Evans prj_pt_src_t G, Y; 143*f0865ec9SKyle Evans hash_context hctx; 144*f0865ec9SKyle Evans bitcnt_t p_bit_len; 145*f0865ec9SKyle Evans fp_src_t a, b; 146*f0865ec9SKyle Evans int ret; 147*f0865ec9SKyle Evans 148*f0865ec9SKyle Evans MUST_HAVE((Z != NULL) && (Zlen != NULL), ret, err); 149*f0865ec9SKyle Evans MUST_HAVE((id != NULL) && (pub_key != NULL), ret, err); 150*f0865ec9SKyle Evans /* Maximum size is Entlen on 16 bits in *bits*, i.e. 8192 bytes */ 151*f0865ec9SKyle Evans MUST_HAVE((id_len <= SM2_MAX_ID_LEN), ret, err); 152*f0865ec9SKyle Evans ret = pub_key_check_initialized_and_type(pub_key, SM2); EG(ret, err); 153*f0865ec9SKyle Evans 154*f0865ec9SKyle Evans ret = get_hash_by_type(hash_type, &hm); EG(ret, err); 155*f0865ec9SKyle Evans MUST_HAVE((hm != NULL), ret, err); 156*f0865ec9SKyle Evans 157*f0865ec9SKyle Evans /* Zlen must be large enough to receive digest */ 158*f0865ec9SKyle Evans hsize = hm->digest_size; 159*f0865ec9SKyle Evans MUST_HAVE((*Zlen) >= hsize, ret, err); 160*f0865ec9SKyle Evans 161*f0865ec9SKyle Evans /* Make things more readable */ 162*f0865ec9SKyle Evans G = &(pub_key->params->ec_gen); 163*f0865ec9SKyle Evans Y = &(pub_key->y); 164*f0865ec9SKyle Evans p_bit_len = pub_key->params->ec_fp.p_bitlen; 165*f0865ec9SKyle Evans p_len = (u8)BYTECEIL(p_bit_len); 166*f0865ec9SKyle Evans entlen = (u16)(id_len * 8); 167*f0865ec9SKyle Evans a = &(pub_key->params->ec_curve.a); 168*f0865ec9SKyle Evans b = &(pub_key->params->ec_curve.b); 169*f0865ec9SKyle Evans 170*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 171*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(hm); EG(ret, err); 172*f0865ec9SKyle Evans ret = hm->hfunc_init(&hctx); EG(ret, err); 173*f0865ec9SKyle Evans 174*f0865ec9SKyle Evans /* ENTL */ 175*f0865ec9SKyle Evans buf[0] = (u8)((entlen >> 8) & 0xff); 176*f0865ec9SKyle Evans buf[1] = (u8)(entlen & 0xff); 177*f0865ec9SKyle Evans ret = hm->hfunc_update(&hctx, buf, 2); EG(ret, err); 178*f0865ec9SKyle Evans 179*f0865ec9SKyle Evans /* ID */ 180*f0865ec9SKyle Evans ret = hm->hfunc_update(&hctx, id, id_len); EG(ret, err); 181*f0865ec9SKyle Evans 182*f0865ec9SKyle Evans /* FE2BS(p, a) */ 183*f0865ec9SKyle Evans ret = fp_export_to_buf(buf, p_len, a); EG(ret, err); 184*f0865ec9SKyle Evans ret = hm->hfunc_update(&hctx, buf, p_len); EG(ret, err); 185*f0865ec9SKyle Evans 186*f0865ec9SKyle Evans /* FE2BS(p, b) */ 187*f0865ec9SKyle Evans ret = fp_export_to_buf(buf, p_len, b); EG(ret, err); 188*f0865ec9SKyle Evans ret = hm->hfunc_update(&hctx, buf, p_len); EG(ret, err); 189*f0865ec9SKyle Evans 190*f0865ec9SKyle Evans /* FE2BS(p, Gx) || FE2BS(p, Gy) */ 191*f0865ec9SKyle Evans ret = prj_pt_export_to_aff_buf(G, buf, (u32)(2 * p_len)); EG(ret, err); 192*f0865ec9SKyle Evans ret = hm->hfunc_update(&hctx, buf, (u32)(2 * p_len)); EG(ret, err); 193*f0865ec9SKyle Evans 194*f0865ec9SKyle Evans /* FE2BS(p, Yx) || FE2BS(p, Yy) */ 195*f0865ec9SKyle Evans ret = prj_pt_export_to_aff_buf(Y, buf, (u32)(2 * p_len)); EG(ret, err); 196*f0865ec9SKyle Evans ret = hm->hfunc_update(&hctx, buf, (u32)(2 * p_len)); EG(ret, err); 197*f0865ec9SKyle Evans 198*f0865ec9SKyle Evans /* Let's now finalize hash computation */ 199*f0865ec9SKyle Evans ret = hm->hfunc_finalize(&hctx, Z); EG(ret, err); 200*f0865ec9SKyle Evans dbg_buf_print("Z", Z, hsize); 201*f0865ec9SKyle Evans 202*f0865ec9SKyle Evans ret = local_memset(buf, 0, sizeof(buf)); EG(ret, err); 203*f0865ec9SKyle Evans ret = local_memset(&hctx, 0, sizeof(hctx)); EG(ret, err); 204*f0865ec9SKyle Evans 205*f0865ec9SKyle Evans (*Zlen) = hsize; 206*f0865ec9SKyle Evans 207*f0865ec9SKyle Evans err: 208*f0865ec9SKyle Evans if (ret && (Zlen != NULL)){ 209*f0865ec9SKyle Evans (*Zlen) = 0; 210*f0865ec9SKyle Evans } 211*f0865ec9SKyle Evans return ret; 212*f0865ec9SKyle Evans } 213*f0865ec9SKyle Evans 214*f0865ec9SKyle Evans 215*f0865ec9SKyle Evans /* 216*f0865ec9SKyle Evans * Generic *internal* SM2 signature functions (init, update and finalize). 217*f0865ec9SKyle Evans * Their purpose is to allow passing a specific hash function (along with 218*f0865ec9SKyle Evans * its output size) and the random ephemeral key k, so that compliance 219*f0865ec9SKyle Evans * tests against test vectors can be made without ugly hack in the code 220*f0865ec9SKyle Evans * itself. 221*f0865ec9SKyle Evans * 222*f0865ec9SKyle Evans * Global SM2 signature process is as follows (I,U,F provides information 223*f0865ec9SKyle Evans * in which function(s) (init(), update() or finalize()) a specific step 224*f0865ec9SKyle Evans * is performed): 225*f0865ec9SKyle Evans * 226*f0865ec9SKyle Evans *| IUF - SM2 signature 227*f0865ec9SKyle Evans *| 228*f0865ec9SKyle Evans *| UF 1. set M1 = Z || M (See (*) below) 229*f0865ec9SKyle Evans *| F 2. Compute H = h(M1) 230*f0865ec9SKyle Evans *| F 3. Get a random value k in ]0,q[ 231*f0865ec9SKyle Evans *| F 4. Compute W = (W_x,W_y) = kG 232*f0865ec9SKyle Evans *| F 5. Compute r = (OS2I(H) + Wx) mod q 233*f0865ec9SKyle Evans *| F 6. If r is 0, restart the process at step 3. 234*f0865ec9SKyle Evans *| F 7. If r + k is q, restart the process at step 3. 235*f0865ec9SKyle Evans *| F 8. Compute s = ((1 + x)^(-1) * (k - rx)) mod q 236*f0865ec9SKyle Evans *| F 9. If s is 0, restart the process at step 3. 237*f0865ec9SKyle Evans *| F 10. Export r and s 238*f0865ec9SKyle Evans * 239*f0865ec9SKyle Evans * (*) It is user responsibility to pass the ID string in the optional ancillary 240*f0865ec9SKyle Evans * data of the API. 241*f0865ec9SKyle Evans */ 242*f0865ec9SKyle Evans 243*f0865ec9SKyle Evans #define SM2_SIGN_MAGIC ((word_t)(0x324300884035dae8ULL)) 244*f0865ec9SKyle Evans #define SM2_SIGN_CHECK_INITIALIZED(A, ret, err) \ 245*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == SM2_SIGN_MAGIC), ret, err) 246*f0865ec9SKyle Evans 247*f0865ec9SKyle Evans int _sm2_sign_init(struct ec_sign_context *ctx) 248*f0865ec9SKyle Evans { 249*f0865ec9SKyle Evans int ret; 250*f0865ec9SKyle Evans u8 Z[Z_INPUT_MAX_LEN]; 251*f0865ec9SKyle Evans u16 Zlen; 252*f0865ec9SKyle Evans 253*f0865ec9SKyle Evans /* First, verify context has been initialized */ 254*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 255*f0865ec9SKyle Evans 256*f0865ec9SKyle Evans /* Additional sanity checks on input params from context */ 257*f0865ec9SKyle Evans ret = key_pair_check_initialized_and_type(ctx->key_pair, SM2); EG(ret, err); 258*f0865ec9SKyle Evans MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) && 259*f0865ec9SKyle Evans (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err); 260*f0865ec9SKyle Evans 261*f0865ec9SKyle Evans /* 262*f0865ec9SKyle Evans * Initialize hash context stored in our private part of context 263*f0865ec9SKyle Evans * and record data init has been done 264*f0865ec9SKyle Evans */ 265*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 266*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 267*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(&(ctx->sign_data.sm2.h_ctx)); EG(ret, err); 268*f0865ec9SKyle Evans 269*f0865ec9SKyle Evans /* Compute Z from the ID */ 270*f0865ec9SKyle Evans ret = local_memset(Z, 0, sizeof(Z)); EG(ret, err); 271*f0865ec9SKyle Evans Zlen = sizeof(Z); 272*f0865ec9SKyle Evans ret = sm2_compute_Z(Z, &Zlen, ctx->adata, ctx->adata_len, 273*f0865ec9SKyle Evans &(ctx->key_pair->pub_key), ctx->h->type); EG(ret, err); 274*f0865ec9SKyle Evans 275*f0865ec9SKyle Evans /* Update the hash function with Z */ 276*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 277*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 278*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->sign_data.sm2.h_ctx), Z, Zlen); EG(ret, err); 279*f0865ec9SKyle Evans 280*f0865ec9SKyle Evans ctx->sign_data.sm2.magic = SM2_SIGN_MAGIC; 281*f0865ec9SKyle Evans 282*f0865ec9SKyle Evans err: 283*f0865ec9SKyle Evans VAR_ZEROIFY(Zlen); 284*f0865ec9SKyle Evans 285*f0865ec9SKyle Evans return ret; 286*f0865ec9SKyle Evans } 287*f0865ec9SKyle Evans 288*f0865ec9SKyle Evans int _sm2_sign_update(struct ec_sign_context *ctx, 289*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 290*f0865ec9SKyle Evans { 291*f0865ec9SKyle Evans int ret; 292*f0865ec9SKyle Evans 293*f0865ec9SKyle Evans /* 294*f0865ec9SKyle Evans * First, verify context has been initialized and private part too. 295*f0865ec9SKyle Evans * This guarantees the context is an SM2 signature one and we do not 296*f0865ec9SKyle Evans * update() or finalize() before init(). 297*f0865ec9SKyle Evans */ 298*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 299*f0865ec9SKyle Evans SM2_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.sm2), ret, err); 300*f0865ec9SKyle Evans 301*f0865ec9SKyle Evans /* 1. Compute h = H(m) */ 302*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 303*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 304*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->sign_data.sm2.h_ctx), chunk, chunklen); 305*f0865ec9SKyle Evans 306*f0865ec9SKyle Evans err: 307*f0865ec9SKyle Evans return ret; 308*f0865ec9SKyle Evans } 309*f0865ec9SKyle Evans 310*f0865ec9SKyle Evans int _sm2_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen) 311*f0865ec9SKyle Evans { 312*f0865ec9SKyle Evans const ec_priv_key *priv_key; 313*f0865ec9SKyle Evans u8 hash[MAX_DIGEST_SIZE]; 314*f0865ec9SKyle Evans bitcnt_t q_bit_len; 315*f0865ec9SKyle Evans u8 hsize, q_len; 316*f0865ec9SKyle Evans prj_pt_src_t G; 317*f0865ec9SKyle Evans nn_src_t q, x; 318*f0865ec9SKyle Evans prj_pt kG; 319*f0865ec9SKyle Evans int ret, iszero, cmp; 320*f0865ec9SKyle Evans nn k, r, s, tmp, tmp2, tmp3; 321*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 322*f0865ec9SKyle Evans nn b; /* blinding mask */ 323*f0865ec9SKyle Evans b.magic = WORD(0); 324*f0865ec9SKyle Evans #endif 325*f0865ec9SKyle Evans 326*f0865ec9SKyle Evans kG.magic = WORD(0); 327*f0865ec9SKyle Evans k.magic = r.magic = s.magic = tmp.magic = tmp2.magic = tmp3.magic = WORD(0); 328*f0865ec9SKyle Evans 329*f0865ec9SKyle Evans /* 330*f0865ec9SKyle Evans * First, verify context has been initialized and private part too. 331*f0865ec9SKyle Evans * This guarantees the context is an SM2 signature one and we do not 332*f0865ec9SKyle Evans * update() or finalize() before init(). 333*f0865ec9SKyle Evans */ 334*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 335*f0865ec9SKyle Evans SM2_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.sm2), ret, err); 336*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 337*f0865ec9SKyle Evans 338*f0865ec9SKyle Evans /* Zero init out point */ 339*f0865ec9SKyle Evans ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err); 340*f0865ec9SKyle Evans 341*f0865ec9SKyle Evans /* Make things more readable */ 342*f0865ec9SKyle Evans priv_key = &(ctx->key_pair->priv_key); 343*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order); 344*f0865ec9SKyle Evans q_bit_len = priv_key->params->ec_gen_order_bitlen; 345*f0865ec9SKyle Evans G = &(priv_key->params->ec_gen); 346*f0865ec9SKyle Evans q_len = (u8)BYTECEIL(q_bit_len); 347*f0865ec9SKyle Evans x = &(priv_key->x); 348*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 349*f0865ec9SKyle Evans 350*f0865ec9SKyle Evans dbg_nn_print("p", &(priv_key->params->ec_fp.p)); 351*f0865ec9SKyle Evans dbg_nn_print("q", &(priv_key->params->ec_gen_order)); 352*f0865ec9SKyle Evans dbg_priv_key_print("x", priv_key); 353*f0865ec9SKyle Evans dbg_ec_point_print("G", &(priv_key->params->ec_gen)); 354*f0865ec9SKyle Evans dbg_pub_key_print("Y", &(ctx->key_pair->pub_key)); 355*f0865ec9SKyle Evans 356*f0865ec9SKyle Evans /* Check given signature buffer length has the expected size */ 357*f0865ec9SKyle Evans MUST_HAVE((siglen == SM2_SIGLEN(q_bit_len)), ret, err); 358*f0865ec9SKyle Evans 359*f0865ec9SKyle Evans ret = local_memset(hash, 0, hsize); EG(ret, err); 360*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 361*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 362*f0865ec9SKyle Evans 363*f0865ec9SKyle Evans /* 2. Compute H = h(M1) */ 364*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(&(ctx->sign_data.sm2.h_ctx), hash); EG(ret, err); 365*f0865ec9SKyle Evans dbg_buf_print("h", hash, hsize); 366*f0865ec9SKyle Evans 367*f0865ec9SKyle Evans restart: 368*f0865ec9SKyle Evans 369*f0865ec9SKyle Evans /* 3. Get a random value k in ]0,q[ */ 370*f0865ec9SKyle Evans #ifdef NO_KNOWN_VECTORS 371*f0865ec9SKyle Evans /* NOTE: when we do not need self tests for known vectors, 372*f0865ec9SKyle Evans * we can be strict about random function handler! 373*f0865ec9SKyle Evans * This allows us to avoid the corruption of such a pointer. 374*f0865ec9SKyle Evans */ 375*f0865ec9SKyle Evans /* Sanity check on the handler before calling it */ 376*f0865ec9SKyle Evans MUST_HAVE(ctx->rand == nn_get_random_mod, ret, err); 377*f0865ec9SKyle Evans #endif 378*f0865ec9SKyle Evans ret = ctx->rand(&k, q); EG(ret, err); 379*f0865ec9SKyle Evans dbg_nn_print("k", &k); 380*f0865ec9SKyle Evans 381*f0865ec9SKyle Evans /* 4. Compute W = (W_x,W_y) = kG */ 382*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 383*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err); 384*f0865ec9SKyle Evans #else 385*f0865ec9SKyle Evans ret = prj_pt_mul(&kG, &k, G); EG(ret, err); 386*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 387*f0865ec9SKyle Evans ret = prj_pt_unique(&kG, &kG); EG(ret, err); 388*f0865ec9SKyle Evans 389*f0865ec9SKyle Evans dbg_nn_print("W_x", &(kG.X.fp_val)); 390*f0865ec9SKyle Evans dbg_nn_print("W_y", &(kG.Y.fp_val)); 391*f0865ec9SKyle Evans 392*f0865ec9SKyle Evans /* 5. Compute r = (OS2I(H) + Wx) mod q */ 393*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp, hash, hsize); EG(ret, err); 394*f0865ec9SKyle Evans ret = local_memset(hash, 0, hsize); EG(ret, err); 395*f0865ec9SKyle Evans dbg_nn_print("OS2I(H)", &tmp); 396*f0865ec9SKyle Evans ret = nn_add(&tmp2, &tmp, &(kG.X.fp_val)); EG(ret, err); 397*f0865ec9SKyle Evans ret = nn_mod(&r, &tmp2, q); EG(ret, err); 398*f0865ec9SKyle Evans dbg_nn_print("r", &r); 399*f0865ec9SKyle Evans 400*f0865ec9SKyle Evans /* 6. If r is 0, restart the process at step 3. */ 401*f0865ec9SKyle Evans ret = nn_iszero(&r, &iszero); EG(ret, err); 402*f0865ec9SKyle Evans if (iszero) { 403*f0865ec9SKyle Evans goto restart; 404*f0865ec9SKyle Evans } 405*f0865ec9SKyle Evans 406*f0865ec9SKyle Evans /* 7. If r + k is q, restart the process at step 3. */ 407*f0865ec9SKyle Evans ret = nn_add(&tmp, &r, q); EG(ret, err); 408*f0865ec9SKyle Evans ret = nn_cmp(&tmp, q, &cmp); EG(ret, err); 409*f0865ec9SKyle Evans if (cmp == 0) { 410*f0865ec9SKyle Evans goto restart; 411*f0865ec9SKyle Evans } 412*f0865ec9SKyle Evans 413*f0865ec9SKyle Evans /* 8. Compute s = ((1 + x)^(-1) * (k - rx)) mod q */ 414*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 415*f0865ec9SKyle Evans /* 416*f0865ec9SKyle Evans * With blinding enabled, the computation above is performed in the 417*f0865ec9SKyle Evans * following way s = ((b*(1 + x))^(-1) * (kb - (br)x)) mod q 418*f0865ec9SKyle Evans */ 419*f0865ec9SKyle Evans ret = nn_get_random_mod(&b, q); EG(ret, err); 420*f0865ec9SKyle Evans dbg_nn_print("b", &b); 421*f0865ec9SKyle Evans ret = nn_inc(&tmp2, x); EG(ret, err); 422*f0865ec9SKyle Evans ret = nn_mod_mul(&tmp2, &tmp2, &b, q); EG(ret, err); 423*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 424*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 425*f0865ec9SKyle Evans */ 426*f0865ec9SKyle Evans ret = nn_modinv_fermat(&tmp, &tmp2, q); EG(ret, err); /* tmp = (b*(1 + x))^(-1) */ 427*f0865ec9SKyle Evans dbg_nn_print("(b*(1 + x))^(-1)", &tmp); 428*f0865ec9SKyle Evans ret = nn_mod_mul(&tmp3, &r, &b, q); EG(ret, err); /* rb */ 429*f0865ec9SKyle Evans ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err); /* kb */ 430*f0865ec9SKyle Evans ret = nn_mod_mul(&tmp3, &tmp3, x, q); EG(ret, err); /* (rb)x mod q */ 431*f0865ec9SKyle Evans ret = nn_mod_sub(&tmp2, &k, &tmp3, q); EG(ret, err); /* tmp2 = (kb - (rb)x) mod q */ 432*f0865ec9SKyle Evans ret = nn_mod_mul(&s, &tmp, &tmp2, q); EG(ret, err); 433*f0865ec9SKyle Evans dbg_nn_print("s", &s); 434*f0865ec9SKyle Evans #else 435*f0865ec9SKyle Evans ret = nn_inc(&tmp2, x); EG(ret, err); 436*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 437*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 438*f0865ec9SKyle Evans */ 439*f0865ec9SKyle Evans ret = nn_modinv_fermat(&tmp, &tmp2, q); EG(ret, err); /* tmp = (1 + x)^(-1) */ 440*f0865ec9SKyle Evans dbg_nn_print("(1 + x)^(-1)", &tmp); 441*f0865ec9SKyle Evans ret = nn_mod_mul(&tmp3, &r, x, q); EG(ret, err); /* rx mod q */ 442*f0865ec9SKyle Evans ret = nn_mod_sub(&tmp2, &k, &tmp3, q); EG(ret, err); /* tmp2 = (k - rx) mod q */ 443*f0865ec9SKyle Evans ret = nn_mod_mul(&s, &tmp, &tmp2, q); EG(ret, err); 444*f0865ec9SKyle Evans dbg_nn_print("s", &s); 445*f0865ec9SKyle Evans #endif 446*f0865ec9SKyle Evans 447*f0865ec9SKyle Evans /* 9. If s is 0, restart the process at step 3. */ 448*f0865ec9SKyle Evans ret = nn_iszero(&s, &iszero); EG(ret, err); 449*f0865ec9SKyle Evans if (iszero) { 450*f0865ec9SKyle Evans goto restart; 451*f0865ec9SKyle Evans } 452*f0865ec9SKyle Evans 453*f0865ec9SKyle Evans /* 10. Export r and s */ 454*f0865ec9SKyle Evans ret = nn_export_to_buf(sig, q_len, &r); EG(ret, err); 455*f0865ec9SKyle Evans ret = nn_export_to_buf(sig + q_len, q_len, &s); 456*f0865ec9SKyle Evans 457*f0865ec9SKyle Evans err: 458*f0865ec9SKyle Evans prj_pt_uninit(&kG); 459*f0865ec9SKyle Evans nn_uninit(&k); 460*f0865ec9SKyle Evans nn_uninit(&r); 461*f0865ec9SKyle Evans nn_uninit(&s); 462*f0865ec9SKyle Evans nn_uninit(&tmp); 463*f0865ec9SKyle Evans nn_uninit(&tmp2); 464*f0865ec9SKyle Evans nn_uninit(&tmp3); 465*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 466*f0865ec9SKyle Evans nn_uninit(&b); 467*f0865ec9SKyle Evans #endif 468*f0865ec9SKyle Evans /* 469*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 470*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 471*f0865ec9SKyle Evans */ 472*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->sign_data.sm2), 0, sizeof(sm2_sign_data))); 473*f0865ec9SKyle Evans 474*f0865ec9SKyle Evans /* Clean what remains on the stack */ 475*f0865ec9SKyle Evans PTR_NULLIFY(priv_key); 476*f0865ec9SKyle Evans PTR_NULLIFY(G); 477*f0865ec9SKyle Evans PTR_NULLIFY(q); 478*f0865ec9SKyle Evans PTR_NULLIFY(x); 479*f0865ec9SKyle Evans VAR_ZEROIFY(q_len); 480*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 481*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 482*f0865ec9SKyle Evans 483*f0865ec9SKyle Evans return ret; 484*f0865ec9SKyle Evans } 485*f0865ec9SKyle Evans 486*f0865ec9SKyle Evans 487*f0865ec9SKyle Evans /* 488*f0865ec9SKyle Evans * Generic *internal* SM2 verification functions (init, update and finalize). 489*f0865ec9SKyle Evans * Their purpose is to allow passing a specific hash function (along with 490*f0865ec9SKyle Evans * its output size) and the random ephemeral key k, so that compliance 491*f0865ec9SKyle Evans * tests against test vectors can be made without ugly hack in the code 492*f0865ec9SKyle Evans * itself. 493*f0865ec9SKyle Evans * 494*f0865ec9SKyle Evans * Global SM2 verification process is as follows (I,U,F provides information 495*f0865ec9SKyle Evans * in which function(s) (init(), update() or finalize()) a specific step is 496*f0865ec9SKyle Evans * performed): 497*f0865ec9SKyle Evans * 498*f0865ec9SKyle Evans *| IUF - SM2 verification 499*f0865ec9SKyle Evans *| 500*f0865ec9SKyle Evans *| I 1. Reject the signature if r or s is 0 or >= q. 501*f0865ec9SKyle Evans *| UF 2. Compute h = H(M1) w/ M1 = Z || M (See (*) below) 502*f0865ec9SKyle Evans *| F 3. Compute t = r + s mod q 503*f0865ec9SKyle Evans *| F 4. Reject signature if t is 0 504*f0865ec9SKyle Evans *| F 5. Compute e = OS2I(h) mod q 505*f0865ec9SKyle Evans *| F 6. Compute W' = sG + tY 506*f0865ec9SKyle Evans *| F 7. If W' is the point at infinity, reject the signature. 507*f0865ec9SKyle Evans *| F 8. Compute r' = (e + W'_x) mod q 508*f0865ec9SKyle Evans *| F 9. Accept the signature if and only if r equals r' 509*f0865ec9SKyle Evans * 510*f0865ec9SKyle Evans * (*) It is user responsibility to pass the ID string in the optional ancillary 511*f0865ec9SKyle Evans * data of the API. 512*f0865ec9SKyle Evans */ 513*f0865ec9SKyle Evans 514*f0865ec9SKyle Evans #define SM2_VERIFY_MAGIC ((word_t)(0x9177c61e777f9f22ULL)) 515*f0865ec9SKyle Evans #define SM2_VERIFY_CHECK_INITIALIZED(A, ret, err) \ 516*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == SM2_VERIFY_MAGIC), ret, err) 517*f0865ec9SKyle Evans 518*f0865ec9SKyle Evans int _sm2_verify_init(struct ec_verify_context *ctx, 519*f0865ec9SKyle Evans const u8 *sig, u8 siglen) 520*f0865ec9SKyle Evans { 521*f0865ec9SKyle Evans bitcnt_t q_bit_len; 522*f0865ec9SKyle Evans u8 q_len; 523*f0865ec9SKyle Evans nn_src_t q; 524*f0865ec9SKyle Evans nn *r = NULL, *s = NULL; 525*f0865ec9SKyle Evans int ret, iszero1, iszero2, cmp1, cmp2; 526*f0865ec9SKyle Evans u8 Z[Z_INPUT_MAX_LEN]; 527*f0865ec9SKyle Evans u16 Zlen; 528*f0865ec9SKyle Evans 529*f0865ec9SKyle Evans /* First, verify context has been initialized */ 530*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 531*f0865ec9SKyle Evans 532*f0865ec9SKyle Evans /* Do some sanity checks on input params */ 533*f0865ec9SKyle Evans ret = pub_key_check_initialized_and_type(ctx->pub_key, SM2); EG(ret, err); 534*f0865ec9SKyle Evans MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) && 535*f0865ec9SKyle Evans (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err); 536*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 537*f0865ec9SKyle Evans 538*f0865ec9SKyle Evans /* Make things more readable */ 539*f0865ec9SKyle Evans q = &(ctx->pub_key->params->ec_gen_order); 540*f0865ec9SKyle Evans q_bit_len = ctx->pub_key->params->ec_gen_order_bitlen; 541*f0865ec9SKyle Evans q_len = (u8)BYTECEIL(q_bit_len); 542*f0865ec9SKyle Evans r = &(ctx->verify_data.sm2.r); 543*f0865ec9SKyle Evans s = &(ctx->verify_data.sm2.s); 544*f0865ec9SKyle Evans 545*f0865ec9SKyle Evans /* Check given signature length is the expected one */ 546*f0865ec9SKyle Evans MUST_HAVE((siglen == SM2_SIGLEN(q_bit_len)), ret, err); 547*f0865ec9SKyle Evans 548*f0865ec9SKyle Evans /* Import r and s values from signature buffer */ 549*f0865ec9SKyle Evans ret = nn_init_from_buf(r, sig, q_len); EG(ret, err); 550*f0865ec9SKyle Evans ret = nn_init_from_buf(s, sig + q_len, q_len); EG(ret, err); 551*f0865ec9SKyle Evans dbg_nn_print("r", r); 552*f0865ec9SKyle Evans dbg_nn_print("s", s); 553*f0865ec9SKyle Evans 554*f0865ec9SKyle Evans /* 1. Reject the signature if r or s is 0 or >= q. */ 555*f0865ec9SKyle Evans ret = nn_iszero(r, &iszero1); EG(ret, err); 556*f0865ec9SKyle Evans ret = nn_iszero(s, &iszero2); EG(ret, err); 557*f0865ec9SKyle Evans ret = nn_cmp(r, q, &cmp1); EG(ret, err); 558*f0865ec9SKyle Evans ret = nn_cmp(s, q, &cmp2); EG(ret, err); 559*f0865ec9SKyle Evans MUST_HAVE((!iszero1) && (cmp1 < 0) && (!iszero2) && (cmp2 < 0), ret, err); 560*f0865ec9SKyle Evans 561*f0865ec9SKyle Evans /* Initialize the remaining of verify context. */ 562*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 563*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 564*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(&(ctx->verify_data.sm2.h_ctx)); EG(ret, err); 565*f0865ec9SKyle Evans 566*f0865ec9SKyle Evans /* Compute Z from the ID */ 567*f0865ec9SKyle Evans ret = local_memset(Z, 0, sizeof(Z)); EG(ret, err); 568*f0865ec9SKyle Evans Zlen = sizeof(Z); 569*f0865ec9SKyle Evans ret = sm2_compute_Z(Z, &Zlen, ctx->adata, ctx->adata_len, ctx->pub_key, ctx->h->type); EG(ret, err); 570*f0865ec9SKyle Evans 571*f0865ec9SKyle Evans /* Update the hash function with Z */ 572*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->verify_data.sm2.h_ctx), Z, Zlen); EG(ret, err); 573*f0865ec9SKyle Evans 574*f0865ec9SKyle Evans ctx->verify_data.sm2.magic = SM2_VERIFY_MAGIC; 575*f0865ec9SKyle Evans 576*f0865ec9SKyle Evans err: 577*f0865ec9SKyle Evans VAR_ZEROIFY(q_len); 578*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 579*f0865ec9SKyle Evans VAR_ZEROIFY(Zlen); 580*f0865ec9SKyle Evans PTR_NULLIFY(q); 581*f0865ec9SKyle Evans PTR_NULLIFY(r); 582*f0865ec9SKyle Evans PTR_NULLIFY(s); 583*f0865ec9SKyle Evans 584*f0865ec9SKyle Evans return ret; 585*f0865ec9SKyle Evans } 586*f0865ec9SKyle Evans 587*f0865ec9SKyle Evans 588*f0865ec9SKyle Evans int _sm2_verify_update(struct ec_verify_context *ctx, 589*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 590*f0865ec9SKyle Evans { 591*f0865ec9SKyle Evans int ret; 592*f0865ec9SKyle Evans 593*f0865ec9SKyle Evans /* 594*f0865ec9SKyle Evans * First, verify context has been initialized and public part too. This 595*f0865ec9SKyle Evans * guarantees the context is a SM2 verification one and we do not 596*f0865ec9SKyle Evans * update() or finalize() before init(). 597*f0865ec9SKyle Evans */ 598*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 599*f0865ec9SKyle Evans SM2_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.sm2), ret, err); 600*f0865ec9SKyle Evans 601*f0865ec9SKyle Evans /* 2. Compute h = H(M1) w/ M1 = Z || M */ 602*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 603*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 604*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->verify_data.sm2.h_ctx), chunk, chunklen); 605*f0865ec9SKyle Evans 606*f0865ec9SKyle Evans err: 607*f0865ec9SKyle Evans return ret; 608*f0865ec9SKyle Evans } 609*f0865ec9SKyle Evans 610*f0865ec9SKyle Evans int _sm2_verify_finalize(struct ec_verify_context *ctx) 611*f0865ec9SKyle Evans { 612*f0865ec9SKyle Evans prj_pt sG, tY; 613*f0865ec9SKyle Evans prj_pt_t W_prime; 614*f0865ec9SKyle Evans nn e, tmp, r_prime; 615*f0865ec9SKyle Evans prj_pt_src_t G, Y; 616*f0865ec9SKyle Evans u8 hash[MAX_DIGEST_SIZE]; 617*f0865ec9SKyle Evans nn_src_t q; 618*f0865ec9SKyle Evans nn *s, *r; 619*f0865ec9SKyle Evans nn t; 620*f0865ec9SKyle Evans u8 hsize; 621*f0865ec9SKyle Evans int ret, iszero, cmp; 622*f0865ec9SKyle Evans 623*f0865ec9SKyle Evans e.magic = tmp.magic = r_prime.magic = t.magic = WORD(0); 624*f0865ec9SKyle Evans sG.magic = tY.magic = WORD(0); 625*f0865ec9SKyle Evans 626*f0865ec9SKyle Evans /* NOTE: we reuse sG for W_prime to optimize local variables */ 627*f0865ec9SKyle Evans W_prime = &sG; 628*f0865ec9SKyle Evans 629*f0865ec9SKyle Evans /* 630*f0865ec9SKyle Evans * First, verify context has been initialized and public 631*f0865ec9SKyle Evans * part too. This guarantees the context is an SM2 632*f0865ec9SKyle Evans * verification one and we do not finalize() before init(). 633*f0865ec9SKyle Evans */ 634*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 635*f0865ec9SKyle Evans SM2_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.sm2), ret, err); 636*f0865ec9SKyle Evans 637*f0865ec9SKyle Evans /* Zero init points */ 638*f0865ec9SKyle Evans ret = local_memset(&sG, 0, sizeof(prj_pt)); EG(ret, err); 639*f0865ec9SKyle Evans ret = local_memset(&tY, 0, sizeof(prj_pt)); EG(ret, err); 640*f0865ec9SKyle Evans 641*f0865ec9SKyle Evans /* Make things more readable */ 642*f0865ec9SKyle Evans G = &(ctx->pub_key->params->ec_gen); 643*f0865ec9SKyle Evans Y = &(ctx->pub_key->y); 644*f0865ec9SKyle Evans q = &(ctx->pub_key->params->ec_gen_order); 645*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 646*f0865ec9SKyle Evans r = &(ctx->verify_data.sm2.r); 647*f0865ec9SKyle Evans s = &(ctx->verify_data.sm2.s); 648*f0865ec9SKyle Evans 649*f0865ec9SKyle Evans /* 2. Compute h = H(M1) w/ M1 = Z || M */ 650*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 651*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 652*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(&(ctx->verify_data.sm2.h_ctx), hash); EG(ret, err); 653*f0865ec9SKyle Evans dbg_buf_print("h = H(m)", hash, hsize); 654*f0865ec9SKyle Evans 655*f0865ec9SKyle Evans /* 3. Compute t = r + s mod q */ 656*f0865ec9SKyle Evans ret = nn_mod_add(&t, r, s, q); EG(ret, err); 657*f0865ec9SKyle Evans 658*f0865ec9SKyle Evans /* 4. Reject signature if t is 0 */ 659*f0865ec9SKyle Evans ret = nn_iszero(&t, &iszero); EG(ret, err); 660*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 661*f0865ec9SKyle Evans 662*f0865ec9SKyle Evans /* 5. Compute e = OS2I(h) mod q */ 663*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp, hash, hsize); EG(ret, err); 664*f0865ec9SKyle Evans ret = local_memset(hash, 0, hsize); EG(ret, err); 665*f0865ec9SKyle Evans dbg_nn_print("h imported as nn", &tmp); 666*f0865ec9SKyle Evans ret = nn_mod(&e, &tmp, q); EG(ret, err); 667*f0865ec9SKyle Evans dbg_nn_print("e", &e); 668*f0865ec9SKyle Evans 669*f0865ec9SKyle Evans /* 6. Compute W' = sG + tY */ 670*f0865ec9SKyle Evans ret = prj_pt_mul(&sG, s, G); EG(ret, err); 671*f0865ec9SKyle Evans ret = prj_pt_mul(&tY, &t, Y); EG(ret, err); 672*f0865ec9SKyle Evans ret = prj_pt_add(W_prime, &sG, &tY); EG(ret, err); 673*f0865ec9SKyle Evans 674*f0865ec9SKyle Evans /* 7. If W' is the point at infinity, reject the signature. */ 675*f0865ec9SKyle Evans ret = prj_pt_iszero(W_prime, &iszero); EG(ret, err); 676*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 677*f0865ec9SKyle Evans 678*f0865ec9SKyle Evans /* 8. Compute r' = (e + W'_x) mod q */ 679*f0865ec9SKyle Evans ret = prj_pt_unique(W_prime, W_prime); EG(ret, err); 680*f0865ec9SKyle Evans dbg_nn_print("W'_x", &(W_prime->X.fp_val)); 681*f0865ec9SKyle Evans dbg_nn_print("W'_y", &(W_prime->Y.fp_val)); 682*f0865ec9SKyle Evans 683*f0865ec9SKyle Evans /* First, reduce W'_x mod q */ 684*f0865ec9SKyle Evans ret = nn_mod(&r_prime, &(W_prime->X.fp_val), q); EG(ret, err); 685*f0865ec9SKyle Evans /* Then compute r' = (e + W'_x) mod q */ 686*f0865ec9SKyle Evans ret = nn_mod_add(&r_prime, &e, &r_prime, q); EG(ret, err); 687*f0865ec9SKyle Evans 688*f0865ec9SKyle Evans /* 9. Accept the signature if and only if r equals r' */ 689*f0865ec9SKyle Evans ret = nn_cmp(&r_prime, r, &cmp); EG(ret, err); 690*f0865ec9SKyle Evans ret = (cmp != 0) ? -1 : 0; 691*f0865ec9SKyle Evans 692*f0865ec9SKyle Evans err: 693*f0865ec9SKyle Evans nn_uninit(&e); 694*f0865ec9SKyle Evans nn_uninit(&tmp); 695*f0865ec9SKyle Evans nn_uninit(&r_prime); 696*f0865ec9SKyle Evans nn_uninit(&t); 697*f0865ec9SKyle Evans prj_pt_uninit(&sG); 698*f0865ec9SKyle Evans prj_pt_uninit(&tY); 699*f0865ec9SKyle Evans 700*f0865ec9SKyle Evans /* 701*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 702*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 703*f0865ec9SKyle Evans */ 704*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->verify_data.sm2), 0, sizeof(sm2_verify_data))); 705*f0865ec9SKyle Evans 706*f0865ec9SKyle Evans /* Clean what remains on the stack */ 707*f0865ec9SKyle Evans PTR_NULLIFY(W_prime); 708*f0865ec9SKyle Evans PTR_NULLIFY(G); 709*f0865ec9SKyle Evans PTR_NULLIFY(Y); 710*f0865ec9SKyle Evans PTR_NULLIFY(q); 711*f0865ec9SKyle Evans PTR_NULLIFY(s); 712*f0865ec9SKyle Evans PTR_NULLIFY(r); 713*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 714*f0865ec9SKyle Evans 715*f0865ec9SKyle Evans return ret; 716*f0865ec9SKyle Evans } 717*f0865ec9SKyle Evans 718*f0865ec9SKyle Evans #else /* WITH_SIG_SM2 */ 719*f0865ec9SKyle Evans 720*f0865ec9SKyle Evans /* 721*f0865ec9SKyle Evans * Dummy definition to avoid the empty translation unit ISO C warning 722*f0865ec9SKyle Evans */ 723*f0865ec9SKyle Evans typedef int dummy; 724*f0865ec9SKyle Evans #endif /* WITH_SIG_SM2 */ 725