1*f0865ec9SKyle Evans /* 2*f0865ec9SKyle Evans * Copyright (C) 2017 - 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 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8*f0865ec9SKyle Evans * 9*f0865ec9SKyle Evans * Contributors: 10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12*f0865ec9SKyle Evans * 13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license. 14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project. 15*f0865ec9SKyle Evans */ 16*f0865ec9SKyle Evans #include <libecc/lib_ecc_config.h> 17*f0865ec9SKyle Evans #if defined(WITH_SIG_ECGDSA) && defined(USE_CRYPTOFUZZ) 18*f0865ec9SKyle Evans 19*f0865ec9SKyle Evans #include <libecc/nn/nn_rand.h> 20*f0865ec9SKyle Evans #include <libecc/nn/nn_mul.h> 21*f0865ec9SKyle Evans #include <libecc/nn/nn_logical.h> 22*f0865ec9SKyle Evans 23*f0865ec9SKyle Evans #include <libecc/sig/sig_algs_internal.h> 24*f0865ec9SKyle Evans #include <libecc/sig/ec_key.h> 25*f0865ec9SKyle Evans #include <libecc/utils/utils.h> 26*f0865ec9SKyle Evans #ifdef VERBOSE_INNER_VALUES 27*f0865ec9SKyle Evans #define EC_SIG_ALG "ECGDSA" 28*f0865ec9SKyle Evans #endif 29*f0865ec9SKyle Evans #include <libecc/utils/dbg_sig.h> 30*f0865ec9SKyle Evans 31*f0865ec9SKyle Evans /* NOTE: the following versions of ECGDSA are "raw" with 32*f0865ec9SKyle Evans * no hash functions and nonce override. They are DANGEROUS and 33*f0865ec9SKyle Evans * should NOT be used in production mode! They are however useful 34*f0865ec9SKyle Evans * for corner cases tests and fuzzing. 35*f0865ec9SKyle Evans */ 36*f0865ec9SKyle Evans #define ECGDSA_SIGN_MAGIC ((word_t)(0xe2f60ea3353ecc9eULL)) 37*f0865ec9SKyle Evans #define ECGDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \ 38*f0865ec9SKyle Evans MUST_HAVE((((const void *)(A)) != NULL) && \ 39*f0865ec9SKyle Evans ((A)->magic == ECGDSA_SIGN_MAGIC), ret, err) 40*f0865ec9SKyle Evans 41*f0865ec9SKyle Evans int ecgdsa_sign_raw(struct ec_sign_context *ctx, const u8 *input, u8 inputlen, u8 *sig, u8 siglen, const u8 *nonce, u8 noncelen) 42*f0865ec9SKyle Evans { 43*f0865ec9SKyle Evans nn_src_t q, x; 44*f0865ec9SKyle Evans /* NOTE: hash here is not really a hash ... */ 45*f0865ec9SKyle Evans u8 e_buf[LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8))]; 46*f0865ec9SKyle Evans const ec_priv_key *priv_key; 47*f0865ec9SKyle Evans prj_pt_src_t G; 48*f0865ec9SKyle Evans u8 hsize, r_len, s_len; 49*f0865ec9SKyle Evans bitcnt_t q_bit_len, p_bit_len, rshift; 50*f0865ec9SKyle Evans prj_pt kG; 51*f0865ec9SKyle Evans int ret, iszero; 52*f0865ec9SKyle Evans nn tmp, tmp2, s, e, kr, k, r; 53*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 54*f0865ec9SKyle Evans /* b is the blinding mask */ 55*f0865ec9SKyle Evans nn b, binv; 56*f0865ec9SKyle Evans b.magic = binv.magic = WORD(0); 57*f0865ec9SKyle Evans #endif 58*f0865ec9SKyle Evans tmp.magic = tmp2.magic = s.magic = e.magic = WORD(0); 59*f0865ec9SKyle Evans kr.magic = k.magic = r.magic = WORD(0); 60*f0865ec9SKyle Evans kG.magic = WORD(0); 61*f0865ec9SKyle Evans 62*f0865ec9SKyle Evans /* 63*f0865ec9SKyle Evans * First, verify context has been initialized and private 64*f0865ec9SKyle Evans * part too. This guarantees the context is an EC-GDSA 65*f0865ec9SKyle Evans * signature one and we do not finalize() before init(). 66*f0865ec9SKyle Evans */ 67*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 68*f0865ec9SKyle Evans ECGDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecgdsa), ret, err); 69*f0865ec9SKyle Evans MUST_HAVE((sig != NULL) && (input != NULL), ret, err); 70*f0865ec9SKyle Evans 71*f0865ec9SKyle Evans /* Zero init points */ 72*f0865ec9SKyle Evans ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err); 73*f0865ec9SKyle Evans 74*f0865ec9SKyle Evans /* Make things more readable */ 75*f0865ec9SKyle Evans priv_key = &(ctx->key_pair->priv_key); 76*f0865ec9SKyle Evans G = &(priv_key->params->ec_gen); 77*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order); 78*f0865ec9SKyle Evans x = &(priv_key->x); 79*f0865ec9SKyle Evans q_bit_len = priv_key->params->ec_gen_order_bitlen; 80*f0865ec9SKyle Evans p_bit_len = priv_key->params->ec_fp.p_bitlen; 81*f0865ec9SKyle Evans MUST_HAVE(((u32)BYTECEIL(p_bit_len) <= NN_MAX_BYTE_LEN), ret, err); 82*f0865ec9SKyle Evans r_len = (u8)ECGDSA_R_LEN(q_bit_len); 83*f0865ec9SKyle Evans s_len = (u8)ECGDSA_S_LEN(q_bit_len); 84*f0865ec9SKyle Evans hsize = inputlen; 85*f0865ec9SKyle Evans 86*f0865ec9SKyle Evans MUST_HAVE((siglen == ECGDSA_SIGLEN(q_bit_len)), ret, err); 87*f0865ec9SKyle Evans 88*f0865ec9SKyle Evans dbg_nn_print("p", &(priv_key->params->ec_fp.p)); 89*f0865ec9SKyle Evans dbg_nn_print("q", q); 90*f0865ec9SKyle Evans dbg_priv_key_print("x", priv_key); 91*f0865ec9SKyle Evans dbg_ec_point_print("G", G); 92*f0865ec9SKyle Evans dbg_pub_key_print("Y", &(ctx->key_pair->pub_key)); 93*f0865ec9SKyle Evans 94*f0865ec9SKyle Evans /* 1. Compute h = H(m) */ 95*f0865ec9SKyle Evans /* NOTE: here we have raw ECGDSA, this is the raw input */ 96*f0865ec9SKyle Evans /* NOTE: the MUST_HAVE is protected by a preprocessing check 97*f0865ec9SKyle Evans * to avoid -Werror=type-limits errors: 98*f0865ec9SKyle Evans * "error: comparison is always true due to limited range of data type" 99*f0865ec9SKyle Evans */ 100*f0865ec9SKyle Evans #if LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8)) < 255 101*f0865ec9SKyle Evans MUST_HAVE(((u32)inputlen <= sizeof(e_buf)), ret, err); 102*f0865ec9SKyle Evans #endif 103*f0865ec9SKyle Evans ret = local_memset(e_buf, 0, sizeof(e_buf)); EG(ret, err); 104*f0865ec9SKyle Evans ret = local_memcpy(e_buf, input, hsize); EG(ret, err); 105*f0865ec9SKyle Evans dbg_buf_print("H(m)", e_buf, hsize); 106*f0865ec9SKyle Evans 107*f0865ec9SKyle Evans /* 108*f0865ec9SKyle Evans * If |h| > bitlen(q), set h to bitlen(q) 109*f0865ec9SKyle Evans * leftmost bits of h. 110*f0865ec9SKyle Evans * 111*f0865ec9SKyle Evans */ 112*f0865ec9SKyle Evans rshift = 0; 113*f0865ec9SKyle Evans if ((hsize * 8) > q_bit_len) { 114*f0865ec9SKyle Evans rshift = (bitcnt_t)((hsize * 8) - q_bit_len); 115*f0865ec9SKyle Evans } 116*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp, e_buf, hsize); EG(ret, err); 117*f0865ec9SKyle Evans ret = local_memset(e_buf, 0, hsize); EG(ret, err); 118*f0865ec9SKyle Evans if (rshift) { 119*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&tmp, &tmp, rshift); EG(ret, err); 120*f0865ec9SKyle Evans } 121*f0865ec9SKyle Evans dbg_nn_print("H(m) truncated as nn", &tmp); 122*f0865ec9SKyle Evans 123*f0865ec9SKyle Evans /* 124*f0865ec9SKyle Evans * 2. Convert h to an integer and then compute e = -h mod q, 125*f0865ec9SKyle Evans * i.e. compute e = - OS2I(h) mod q 126*f0865ec9SKyle Evans * 127*f0865ec9SKyle Evans * Because we only support positive integers, we compute 128*f0865ec9SKyle Evans * e = q - (h mod q) (except when h is 0). 129*f0865ec9SKyle Evans */ 130*f0865ec9SKyle Evans ret = nn_mod(&tmp2, &tmp, q); EG(ret, err); 131*f0865ec9SKyle Evans ret = nn_mod_neg(&e, &tmp2, q); EG(ret, err); 132*f0865ec9SKyle Evans 133*f0865ec9SKyle Evans /* 134*f0865ec9SKyle Evans NOTE: the restart label is removed in CRYPTOFUZZ mode as 135*f0865ec9SKyle Evans we trigger MUST_HAVE instead of restarting in this mode. 136*f0865ec9SKyle Evans restart: 137*f0865ec9SKyle Evans */ 138*f0865ec9SKyle Evans /* 3. Get a random value k in ]0,q[ */ 139*f0865ec9SKyle Evans /* NOTE: copy our input nonce if not NULL */ 140*f0865ec9SKyle Evans if(nonce != NULL){ 141*f0865ec9SKyle Evans MUST_HAVE((noncelen <= (u8)(BYTECEIL(q_bit_len))), ret, err); 142*f0865ec9SKyle Evans ret = nn_init_from_buf(&k, nonce, noncelen); EG(ret, err); 143*f0865ec9SKyle Evans } 144*f0865ec9SKyle Evans else{ 145*f0865ec9SKyle Evans ret = ctx->rand(&k, q); EG(ret, err); 146*f0865ec9SKyle Evans } 147*f0865ec9SKyle Evans 148*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 149*f0865ec9SKyle Evans /* Note: if we use blinding, e and e are multiplied by 150*f0865ec9SKyle Evans * a random value b in ]0,q[ */ 151*f0865ec9SKyle Evans ret = nn_get_random_mod(&b, q); EG(ret, err); 152*f0865ec9SKyle Evans dbg_nn_print("b", &b); 153*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 154*f0865ec9SKyle Evans 155*f0865ec9SKyle Evans 156*f0865ec9SKyle Evans /* 4. Compute W = kG = (Wx, Wy) */ 157*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 158*f0865ec9SKyle Evans /* We use blinding for the scalar multiplication */ 159*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err); 160*f0865ec9SKyle Evans #else 161*f0865ec9SKyle Evans ret = prj_pt_mul(&kG, &k, G); EG(ret, err); 162*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 163*f0865ec9SKyle Evans ret = prj_pt_unique(&kG, &kG); EG(ret, err); 164*f0865ec9SKyle Evans 165*f0865ec9SKyle Evans dbg_nn_print("W_x", &(kG.X.fp_val)); 166*f0865ec9SKyle Evans dbg_nn_print("W_y", &(kG.Y.fp_val)); 167*f0865ec9SKyle Evans 168*f0865ec9SKyle Evans /* 5. Compute r = Wx mod q */ 169*f0865ec9SKyle Evans ret = nn_mod(&r, &(kG.X.fp_val), q); EG(ret, err); 170*f0865ec9SKyle Evans dbg_nn_print("r", &r); 171*f0865ec9SKyle Evans 172*f0865ec9SKyle Evans /* 6. If r is 0, restart the process at step 4. */ 173*f0865ec9SKyle Evans /* NOTE: for the CRYPTOFUZZ mode, we do not restart 174*f0865ec9SKyle Evans * the procedure but throw an assert exception instead. 175*f0865ec9SKyle Evans */ 176*f0865ec9SKyle Evans ret = nn_iszero(&r, &iszero); EG(ret, err); 177*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 178*f0865ec9SKyle Evans 179*f0865ec9SKyle Evans /* Export r */ 180*f0865ec9SKyle Evans ret = nn_export_to_buf(sig, r_len, &r); EG(ret, err); 181*f0865ec9SKyle Evans 182*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 183*f0865ec9SKyle Evans /* Blind e and r with b */ 184*f0865ec9SKyle Evans ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err); 185*f0865ec9SKyle Evans ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err); 186*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 187*f0865ec9SKyle Evans /* 7. Compute s = x(kr + e) mod q */ 188*f0865ec9SKyle Evans ret = nn_mod_mul(&kr, &k, &r, q); EG(ret, err); 189*f0865ec9SKyle Evans ret = nn_mod_add(&tmp2, &kr, &e, q); EG(ret, err); 190*f0865ec9SKyle Evans ret = nn_mod_mul(&s, x, &tmp2, q); EG(ret, err); 191*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 192*f0865ec9SKyle Evans /* Unblind s */ 193*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 194*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 195*f0865ec9SKyle Evans */ 196*f0865ec9SKyle Evans ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err); 197*f0865ec9SKyle Evans ret = nn_mod_mul(&s, &s, &binv, q); EG(ret, err); 198*f0865ec9SKyle Evans #endif 199*f0865ec9SKyle Evans dbg_nn_print("s", &s); 200*f0865ec9SKyle Evans 201*f0865ec9SKyle Evans /* 8. If s is 0, restart the process at step 4. */ 202*f0865ec9SKyle Evans /* NOTE: for the CRYPTOFUZZ mode, we do not restart 203*f0865ec9SKyle Evans * the procedure but throw an assert exception instead. 204*f0865ec9SKyle Evans */ 205*f0865ec9SKyle Evans ret = nn_iszero(&s, &iszero); EG(ret, err); 206*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 207*f0865ec9SKyle Evans 208*f0865ec9SKyle Evans /* 9. Return (r,s) */ 209*f0865ec9SKyle Evans ret = nn_export_to_buf(sig + r_len, s_len, &s); 210*f0865ec9SKyle Evans 211*f0865ec9SKyle Evans err: 212*f0865ec9SKyle Evans nn_uninit(&r); 213*f0865ec9SKyle Evans nn_uninit(&s); 214*f0865ec9SKyle Evans nn_uninit(&tmp2); 215*f0865ec9SKyle Evans nn_uninit(&tmp); 216*f0865ec9SKyle Evans nn_uninit(&e); 217*f0865ec9SKyle Evans nn_uninit(&kr); 218*f0865ec9SKyle Evans nn_uninit(&k); 219*f0865ec9SKyle Evans 220*f0865ec9SKyle Evans prj_pt_uninit(&kG); 221*f0865ec9SKyle Evans 222*f0865ec9SKyle Evans /* 223*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 224*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 225*f0865ec9SKyle Evans */ 226*f0865ec9SKyle Evans if(ctx != NULL){ 227*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->sign_data.ecgdsa), 0, sizeof(ecgdsa_sign_data))); 228*f0865ec9SKyle Evans } 229*f0865ec9SKyle Evans 230*f0865ec9SKyle Evans /* Clean what remains on the stack */ 231*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 232*f0865ec9SKyle Evans VAR_ZEROIFY(p_bit_len); 233*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 234*f0865ec9SKyle Evans VAR_ZEROIFY(s_len); 235*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 236*f0865ec9SKyle Evans PTR_NULLIFY(q); 237*f0865ec9SKyle Evans PTR_NULLIFY(x); 238*f0865ec9SKyle Evans PTR_NULLIFY(priv_key); 239*f0865ec9SKyle Evans PTR_NULLIFY(G); 240*f0865ec9SKyle Evans 241*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 242*f0865ec9SKyle Evans nn_uninit(&b); 243*f0865ec9SKyle Evans nn_uninit(&binv); 244*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 245*f0865ec9SKyle Evans 246*f0865ec9SKyle Evans return ret; 247*f0865ec9SKyle Evans } 248*f0865ec9SKyle Evans 249*f0865ec9SKyle Evans /******************************/ 250*f0865ec9SKyle Evans #define ECGDSA_VERIFY_MAGIC ((word_t)(0xd4da37527288d1b6ULL)) 251*f0865ec9SKyle Evans #define ECGDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \ 252*f0865ec9SKyle Evans MUST_HAVE((((const void *)(A)) != NULL) && \ 253*f0865ec9SKyle Evans ((A)->magic == ECGDSA_VERIFY_MAGIC), ret, err) 254*f0865ec9SKyle Evans 255*f0865ec9SKyle Evans int ecgdsa_verify_raw(struct ec_verify_context *ctx, const u8 *input, u8 inputlen) 256*f0865ec9SKyle Evans { 257*f0865ec9SKyle Evans nn tmp, e, r_prime, rinv, uv, *r, *s; 258*f0865ec9SKyle Evans prj_pt uG, vY; 259*f0865ec9SKyle Evans prj_pt_t Wprime; 260*f0865ec9SKyle Evans prj_pt_src_t G, Y; 261*f0865ec9SKyle Evans /* NOTE: hash here is not really a hash ... */ 262*f0865ec9SKyle Evans u8 e_buf[LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8))]; 263*f0865ec9SKyle Evans nn_src_t q; 264*f0865ec9SKyle Evans u8 hsize; 265*f0865ec9SKyle Evans bitcnt_t q_bit_len, rshift; 266*f0865ec9SKyle Evans int ret, cmp; 267*f0865ec9SKyle Evans 268*f0865ec9SKyle Evans tmp.magic = e.magic = r_prime.magic = rinv.magic = uv.magic = WORD(0); 269*f0865ec9SKyle Evans uG.magic = vY.magic = WORD(0); 270*f0865ec9SKyle Evans 271*f0865ec9SKyle Evans /* NOTE: we reuse uG for Wprime to optimize local variables */ 272*f0865ec9SKyle Evans Wprime = &uG; 273*f0865ec9SKyle Evans 274*f0865ec9SKyle Evans /* 275*f0865ec9SKyle Evans * First, verify context has been initialized and public 276*f0865ec9SKyle Evans * part too. This guarantees the context is an EC-GDSA 277*f0865ec9SKyle Evans * verification one and we do not finalize() before init(). 278*f0865ec9SKyle Evans */ 279*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 280*f0865ec9SKyle Evans ECGDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecgdsa), ret, err); 281*f0865ec9SKyle Evans MUST_HAVE((input != NULL), ret, err); 282*f0865ec9SKyle Evans 283*f0865ec9SKyle Evans /* Zero init points */ 284*f0865ec9SKyle Evans ret = local_memset(&uG, 0, sizeof(prj_pt)); EG(ret, err); 285*f0865ec9SKyle Evans ret = local_memset(&vY, 0, sizeof(prj_pt)); EG(ret, err); 286*f0865ec9SKyle Evans 287*f0865ec9SKyle Evans /* Make things more readable */ 288*f0865ec9SKyle Evans G = &(ctx->pub_key->params->ec_gen); 289*f0865ec9SKyle Evans Y = &(ctx->pub_key->y); 290*f0865ec9SKyle Evans q = &(ctx->pub_key->params->ec_gen_order); 291*f0865ec9SKyle Evans r = &(ctx->verify_data.ecgdsa.r); 292*f0865ec9SKyle Evans s = &(ctx->verify_data.ecgdsa.s); 293*f0865ec9SKyle Evans q_bit_len = ctx->pub_key->params->ec_gen_order_bitlen; 294*f0865ec9SKyle Evans hsize = inputlen; 295*f0865ec9SKyle Evans 296*f0865ec9SKyle Evans /* 2. Compute h = H(m) */ 297*f0865ec9SKyle Evans /* NOTE: here we have raw ECGDSA, this is the raw input */ 298*f0865ec9SKyle Evans MUST_HAVE((input != NULL), ret, err); 299*f0865ec9SKyle Evans /* NOTE: the MUST_HAVE is protected by a preprocessing check 300*f0865ec9SKyle Evans * to avoid -Werror=type-limits errors: 301*f0865ec9SKyle Evans * "error: comparison is always true due to limited range of data type" 302*f0865ec9SKyle Evans */ 303*f0865ec9SKyle Evans #if LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8)) < 255 304*f0865ec9SKyle Evans MUST_HAVE(((u32)inputlen <= sizeof(e_buf)), ret, err); 305*f0865ec9SKyle Evans #endif 306*f0865ec9SKyle Evans 307*f0865ec9SKyle Evans ret = local_memset(e_buf, 0, sizeof(e_buf)); EG(ret, err); 308*f0865ec9SKyle Evans ret = local_memcpy(e_buf, input, hsize); EG(ret, err); 309*f0865ec9SKyle Evans dbg_buf_print("H(m)", e_buf, hsize); 310*f0865ec9SKyle Evans 311*f0865ec9SKyle Evans /* 312*f0865ec9SKyle Evans * If |h| > bitlen(q), set h to bitlen(q) 313*f0865ec9SKyle Evans * leftmost bits of h. 314*f0865ec9SKyle Evans * 315*f0865ec9SKyle Evans */ 316*f0865ec9SKyle Evans rshift = 0; 317*f0865ec9SKyle Evans if ((hsize * 8) > q_bit_len) { 318*f0865ec9SKyle Evans rshift = (bitcnt_t)((hsize * 8) - q_bit_len); 319*f0865ec9SKyle Evans } 320*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp, e_buf, hsize); EG(ret, err); 321*f0865ec9SKyle Evans ret = local_memset(e_buf, 0, hsize); EG(ret, err); 322*f0865ec9SKyle Evans if (rshift) { 323*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&tmp, &tmp, rshift); EG(ret, err); 324*f0865ec9SKyle Evans } 325*f0865ec9SKyle Evans dbg_nn_print("H(m) truncated as nn", &tmp); 326*f0865ec9SKyle Evans 327*f0865ec9SKyle Evans /* 3. Compute e by converting h to an integer and reducing it mod q */ 328*f0865ec9SKyle Evans ret = nn_mod(&e, &tmp, q); EG(ret, err); 329*f0865ec9SKyle Evans 330*f0865ec9SKyle Evans /* 4. Compute u = (r^-1)e mod q */ 331*f0865ec9SKyle Evans ret = nn_modinv(&rinv, r, q); EG(ret, err); /* r^-1 */ 332*f0865ec9SKyle Evans ret = nn_mul(&tmp, &rinv, &e); EG(ret, err); /* r^-1 * e */ 333*f0865ec9SKyle Evans ret = nn_mod(&uv, &tmp, q); EG(ret, err); /* (r^-1 * e) mod q */ 334*f0865ec9SKyle Evans ret = prj_pt_mul(&uG, &uv, G); EG(ret, err); 335*f0865ec9SKyle Evans 336*f0865ec9SKyle Evans /* 5. Compute v = (r^-1)s mod q */ 337*f0865ec9SKyle Evans ret = nn_mul(&tmp, &rinv, s); EG(ret, err); /* r^-1 * s */ 338*f0865ec9SKyle Evans ret = nn_mod(&uv, &tmp, q); EG(ret, err); /* (r^-1 * s) mod q */ 339*f0865ec9SKyle Evans ret = prj_pt_mul(&vY, &uv, Y); EG(ret, err); 340*f0865ec9SKyle Evans 341*f0865ec9SKyle Evans /* 6. Compute W' = uG + vY */ 342*f0865ec9SKyle Evans ret = prj_pt_add(Wprime, &uG, &vY); EG(ret, err); 343*f0865ec9SKyle Evans 344*f0865ec9SKyle Evans /* 7. Compute r' = W'_x mod q */ 345*f0865ec9SKyle Evans ret = prj_pt_unique(Wprime, Wprime); EG(ret, err); 346*f0865ec9SKyle Evans dbg_nn_print("W'_x", &(Wprime->X.fp_val)); 347*f0865ec9SKyle Evans dbg_nn_print("W'_y", &(Wprime->Y.fp_val)); 348*f0865ec9SKyle Evans ret = nn_mod(&r_prime, &(Wprime->X.fp_val), q); EG(ret, err); 349*f0865ec9SKyle Evans 350*f0865ec9SKyle Evans /* 8. Accept the signature if and only if r equals r' */ 351*f0865ec9SKyle Evans ret = nn_cmp(r, &r_prime, &cmp); EG(ret, err); 352*f0865ec9SKyle Evans ret = (cmp != 0) ? -1 : 0; 353*f0865ec9SKyle Evans 354*f0865ec9SKyle Evans err: 355*f0865ec9SKyle Evans nn_uninit(&r_prime); 356*f0865ec9SKyle Evans nn_uninit(&e); 357*f0865ec9SKyle Evans nn_uninit(&uv); 358*f0865ec9SKyle Evans nn_uninit(&tmp); 359*f0865ec9SKyle Evans nn_uninit(&rinv); 360*f0865ec9SKyle Evans 361*f0865ec9SKyle Evans prj_pt_uninit(&uG); 362*f0865ec9SKyle Evans prj_pt_uninit(&vY); 363*f0865ec9SKyle Evans 364*f0865ec9SKyle Evans /* 365*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 366*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 367*f0865ec9SKyle Evans */ 368*f0865ec9SKyle Evans if(ctx != NULL){ 369*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->verify_data.ecgdsa), 0, 370*f0865ec9SKyle Evans sizeof(ecgdsa_verify_data))); 371*f0865ec9SKyle Evans } 372*f0865ec9SKyle Evans 373*f0865ec9SKyle Evans PTR_NULLIFY(Wprime); 374*f0865ec9SKyle Evans PTR_NULLIFY(r); 375*f0865ec9SKyle Evans PTR_NULLIFY(s); 376*f0865ec9SKyle Evans PTR_NULLIFY(G); 377*f0865ec9SKyle Evans PTR_NULLIFY(Y); 378*f0865ec9SKyle Evans PTR_NULLIFY(q); 379*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 380*f0865ec9SKyle Evans 381*f0865ec9SKyle Evans return ret; 382*f0865ec9SKyle Evans } 383*f0865ec9SKyle Evans 384*f0865ec9SKyle Evans 385*f0865ec9SKyle Evans #else /* WITH_SIG_ECGDSA && USE_CRYPTOFUZZ */ 386*f0865ec9SKyle Evans 387*f0865ec9SKyle Evans /* 388*f0865ec9SKyle Evans * Dummy definition to avoid the empty translation unit ISO C warning 389*f0865ec9SKyle Evans */ 390*f0865ec9SKyle Evans typedef int dummy; 391*f0865ec9SKyle Evans #endif /* WITH_SIG_ECGDSA */ 392