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_ECDSA) && 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 "ECDSA" 28*f0865ec9SKyle Evans #endif 29*f0865ec9SKyle Evans #include <libecc/utils/dbg_sig.h> 30*f0865ec9SKyle Evans 31*f0865ec9SKyle Evans /* NOTE: the following versions of ECDSA 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 37*f0865ec9SKyle Evans #define ECDSA_SIGN_MAGIC ((word_t)(0x80299a2bf630945bULL)) 38*f0865ec9SKyle Evans #define ECDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \ 39*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == ECDSA_SIGN_MAGIC), ret, err) 40*f0865ec9SKyle Evans 41*f0865ec9SKyle Evans int ecdsa_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 const ec_priv_key *priv_key; 44*f0865ec9SKyle Evans prj_pt_src_t G; 45*f0865ec9SKyle Evans /* NOTE: hash here is not really a hash ... */ 46*f0865ec9SKyle Evans u8 hash[LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8))]; 47*f0865ec9SKyle Evans bitcnt_t rshift, q_bit_len; 48*f0865ec9SKyle Evans prj_pt kG; 49*f0865ec9SKyle Evans nn_src_t q, x; 50*f0865ec9SKyle Evans u8 hsize, q_len; 51*f0865ec9SKyle Evans int ret, iszero, cmp; 52*f0865ec9SKyle Evans nn k, r, e, tmp, s, kinv; 53*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 54*f0865ec9SKyle Evans /* b is the blinding mask */ 55*f0865ec9SKyle Evans nn b; 56*f0865ec9SKyle Evans b.magic = WORD(0); 57*f0865ec9SKyle Evans #endif 58*f0865ec9SKyle Evans k.magic = r.magic = e.magic = WORD(0); 59*f0865ec9SKyle Evans tmp.magic = s.magic = kinv.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 ECDSA 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 ECDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecdsa), ret, err); 69*f0865ec9SKyle Evans MUST_HAVE((input != NULL) && (sig != NULL), ret, err); 70*f0865ec9SKyle Evans 71*f0865ec9SKyle Evans /* Zero init out poiny */ 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 q = &(priv_key->params->ec_gen_order); 77*f0865ec9SKyle Evans q_bit_len = priv_key->params->ec_gen_order_bitlen; 78*f0865ec9SKyle Evans G = &(priv_key->params->ec_gen); 79*f0865ec9SKyle Evans q_len = (u8)BYTECEIL(q_bit_len); 80*f0865ec9SKyle Evans x = &(priv_key->x); 81*f0865ec9SKyle Evans hsize = inputlen; 82*f0865ec9SKyle Evans 83*f0865ec9SKyle Evans dbg_nn_print("p", &(priv_key->params->ec_fp.p)); 84*f0865ec9SKyle Evans dbg_nn_print("q", &(priv_key->params->ec_gen_order)); 85*f0865ec9SKyle Evans dbg_priv_key_print("x", priv_key); 86*f0865ec9SKyle Evans dbg_ec_point_print("G", &(priv_key->params->ec_gen)); 87*f0865ec9SKyle Evans dbg_pub_key_print("Y", &(ctx->key_pair->pub_key)); 88*f0865ec9SKyle Evans 89*f0865ec9SKyle Evans /* Check given signature buffer length has the expected size */ 90*f0865ec9SKyle Evans MUST_HAVE((siglen == ECDSA_SIGLEN(q_bit_len)), ret, err); 91*f0865ec9SKyle Evans 92*f0865ec9SKyle Evans /* 1. Compute h = H(m) */ 93*f0865ec9SKyle Evans /* NOTE: here we have raw ECDSA, this is the raw input */ 94*f0865ec9SKyle Evans /* NOTE: the MUST_HAVE is protected by a preprocessing check 95*f0865ec9SKyle Evans * to avoid -Werror=type-limits errors: 96*f0865ec9SKyle Evans * "error: comparison is always true due to limited range of data type" 97*f0865ec9SKyle Evans */ 98*f0865ec9SKyle Evans #if LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8)) < 255 99*f0865ec9SKyle Evans MUST_HAVE(((u32)inputlen <= sizeof(hash)), ret, err); 100*f0865ec9SKyle Evans #endif 101*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 102*f0865ec9SKyle Evans ret = local_memcpy(hash, input, hsize); EG(ret, err); 103*f0865ec9SKyle Evans 104*f0865ec9SKyle Evans dbg_buf_print("h", hash, hsize); 105*f0865ec9SKyle Evans 106*f0865ec9SKyle Evans /* 107*f0865ec9SKyle Evans * 2. If |h| > bitlen(q), set h to bitlen(q) 108*f0865ec9SKyle Evans * leftmost bits of h. 109*f0865ec9SKyle Evans * 110*f0865ec9SKyle Evans * Note that it's easier to check if the truncation has 111*f0865ec9SKyle Evans * to be done here but only implement it using a logical 112*f0865ec9SKyle Evans * shift at the beginning of step 3. below once the hash 113*f0865ec9SKyle Evans * has been converted to an integer. 114*f0865ec9SKyle Evans */ 115*f0865ec9SKyle Evans rshift = 0; 116*f0865ec9SKyle Evans if ((hsize * 8) > q_bit_len) { 117*f0865ec9SKyle Evans rshift = (bitcnt_t)((hsize * 8) - q_bit_len); 118*f0865ec9SKyle Evans } 119*f0865ec9SKyle Evans 120*f0865ec9SKyle Evans /* 121*f0865ec9SKyle Evans * 3. Compute e = OS2I(h) mod q, i.e. by converting h to an 122*f0865ec9SKyle Evans * integer and reducing it mod q 123*f0865ec9SKyle Evans */ 124*f0865ec9SKyle Evans ret = nn_init_from_buf(&e, hash, hsize); EG(ret, err); 125*f0865ec9SKyle Evans ret = local_memset(hash, 0, hsize); EG(ret, err); 126*f0865ec9SKyle Evans dbg_nn_print("h initial import as nn", &e); 127*f0865ec9SKyle Evans if (rshift) { 128*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&e, &e, rshift); EG(ret, err); 129*f0865ec9SKyle Evans } 130*f0865ec9SKyle Evans dbg_nn_print("h final import as nn", &e); 131*f0865ec9SKyle Evans ret = nn_mod(&e, &e, q); EG(ret, err); 132*f0865ec9SKyle Evans dbg_nn_print("e", &e); 133*f0865ec9SKyle Evans 134*f0865ec9SKyle Evans /* 135*f0865ec9SKyle Evans NOTE: the restart label is removed in CRYPTOFUZZ mode as 136*f0865ec9SKyle Evans we trigger MUST_HAVE instead of restarting in this mode. 137*f0865ec9SKyle Evans restart: 138*f0865ec9SKyle Evans */ 139*f0865ec9SKyle Evans /* 4. get a random value k in ]0,q[ */ 140*f0865ec9SKyle Evans /* NOTE: copy our input nonce if not NULL */ 141*f0865ec9SKyle Evans if(nonce != NULL){ 142*f0865ec9SKyle Evans MUST_HAVE((noncelen <= (u8)(BYTECEIL(q_bit_len))), ret, err); 143*f0865ec9SKyle Evans ret = nn_init_from_buf(&k, nonce, noncelen); EG(ret, err); 144*f0865ec9SKyle Evans } 145*f0865ec9SKyle Evans else{ 146*f0865ec9SKyle Evans ret = ctx->rand(&k, q); EG(ret, err); 147*f0865ec9SKyle Evans } 148*f0865ec9SKyle Evans dbg_nn_print("k", &k); 149*f0865ec9SKyle Evans 150*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 151*f0865ec9SKyle Evans /* Note: if we use blinding, r and e are multiplied by 152*f0865ec9SKyle Evans * a random value b in ]0,q[ */ 153*f0865ec9SKyle Evans ret = nn_get_random_mod(&b, q); EG(ret, err); 154*f0865ec9SKyle Evans dbg_nn_print("b", &b); 155*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 156*f0865ec9SKyle Evans 157*f0865ec9SKyle Evans 158*f0865ec9SKyle Evans /* 5. Compute W = (W_x,W_y) = kG */ 159*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 160*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err); 161*f0865ec9SKyle Evans #else 162*f0865ec9SKyle Evans ret = prj_pt_mul(&kG, &k, G); EG(ret, err); 163*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 164*f0865ec9SKyle Evans ret = prj_pt_unique(&kG, &kG); EG(ret, err); 165*f0865ec9SKyle Evans 166*f0865ec9SKyle Evans dbg_nn_print("W_x", &(kG.X.fp_val)); 167*f0865ec9SKyle Evans dbg_nn_print("W_y", &(kG.Y.fp_val)); 168*f0865ec9SKyle Evans 169*f0865ec9SKyle Evans /* 6. Compute r = W_x mod q */ 170*f0865ec9SKyle Evans ret = nn_mod(&r, &(kG.X.fp_val), q); EG(ret, err); 171*f0865ec9SKyle Evans dbg_nn_print("r", &r); 172*f0865ec9SKyle Evans 173*f0865ec9SKyle Evans /* 7. If r is 0, restart the process at step 4. */ 174*f0865ec9SKyle Evans /* NOTE: for the CRYPTOFUZZ mode, we do not restart 175*f0865ec9SKyle Evans * the procedure but throw an assert exception instead. 176*f0865ec9SKyle Evans */ 177*f0865ec9SKyle Evans ret = nn_iszero(&r, &iszero); EG(ret, err); 178*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 179*f0865ec9SKyle Evans 180*f0865ec9SKyle Evans /* Export r */ 181*f0865ec9SKyle Evans ret = nn_export_to_buf(sig, q_len, &r); EG(ret, err); 182*f0865ec9SKyle Evans 183*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 184*f0865ec9SKyle Evans /* Blind r with b */ 185*f0865ec9SKyle Evans ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err); 186*f0865ec9SKyle Evans 187*f0865ec9SKyle Evans /* Blind the message e */ 188*f0865ec9SKyle Evans ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err); 189*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 190*f0865ec9SKyle Evans 191*f0865ec9SKyle Evans /* tmp = xr mod q */ 192*f0865ec9SKyle Evans ret = nn_mod_mul(&tmp, x, &r, q); EG(ret, err); 193*f0865ec9SKyle Evans dbg_nn_print("x*r mod q", &tmp); 194*f0865ec9SKyle Evans 195*f0865ec9SKyle Evans /* 8. If e == rx, restart the process at step 4. */ 196*f0865ec9SKyle Evans /* NOTE: for the CRYPTOFUZZ mode, we do not restart 197*f0865ec9SKyle Evans * the procedure but throw an assert exception instead. 198*f0865ec9SKyle Evans */ 199*f0865ec9SKyle Evans ret = nn_cmp(&e, &tmp, &cmp); EG(ret, err); 200*f0865ec9SKyle Evans MUST_HAVE(cmp, ret, err); 201*f0865ec9SKyle Evans 202*f0865ec9SKyle Evans /* 9. Compute s = k^-1 * (xr + e) mod q */ 203*f0865ec9SKyle Evans 204*f0865ec9SKyle Evans /* tmp2 = (e + xr) mod q */ 205*f0865ec9SKyle Evans ret = nn_mod_add(&tmp, &tmp, &e, q); EG(ret, err); 206*f0865ec9SKyle Evans dbg_nn_print("(xr + e) mod q", &tmp); 207*f0865ec9SKyle Evans 208*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 209*f0865ec9SKyle Evans /* In case of blinding, we compute (b*k)^-1, and 210*f0865ec9SKyle Evans * b^-1 will automatically unblind (r*x) in the following 211*f0865ec9SKyle Evans */ 212*f0865ec9SKyle Evans ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err); 213*f0865ec9SKyle Evans #endif 214*f0865ec9SKyle Evans /* Compute k^-1 mod q */ 215*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 216*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 217*f0865ec9SKyle Evans */ 218*f0865ec9SKyle Evans ret = nn_modinv_fermat(&kinv, &k, q); EG(ret, err); 219*f0865ec9SKyle Evans 220*f0865ec9SKyle Evans dbg_nn_print("k^-1 mod q", &kinv); 221*f0865ec9SKyle Evans 222*f0865ec9SKyle Evans /* s = k^-1 * tmp2 mod q */ 223*f0865ec9SKyle Evans ret = nn_mod_mul(&s, &tmp, &kinv, q); EG(ret, err); 224*f0865ec9SKyle Evans 225*f0865ec9SKyle Evans dbg_nn_print("s", &s); 226*f0865ec9SKyle Evans 227*f0865ec9SKyle Evans /* 10. If s is 0, restart the process at step 4. */ 228*f0865ec9SKyle Evans /* NOTE: for the CRYPTOFUZZ mode, we do not restart 229*f0865ec9SKyle Evans * the procedure but throw an assert exception instead. 230*f0865ec9SKyle Evans */ 231*f0865ec9SKyle Evans ret = nn_iszero(&s, &iszero); EG(ret, err); 232*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 233*f0865ec9SKyle Evans 234*f0865ec9SKyle Evans /* 11. return (r,s) */ 235*f0865ec9SKyle Evans ret = nn_export_to_buf(sig + q_len, q_len, &s); 236*f0865ec9SKyle Evans 237*f0865ec9SKyle Evans err: 238*f0865ec9SKyle Evans 239*f0865ec9SKyle Evans nn_uninit(&r); 240*f0865ec9SKyle Evans nn_uninit(&s); 241*f0865ec9SKyle Evans nn_uninit(&e); 242*f0865ec9SKyle Evans nn_uninit(&tmp); 243*f0865ec9SKyle Evans nn_uninit(&k); 244*f0865ec9SKyle Evans nn_uninit(&kinv); 245*f0865ec9SKyle Evans prj_pt_uninit(&kG); 246*f0865ec9SKyle Evans 247*f0865ec9SKyle Evans /* 248*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 249*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 250*f0865ec9SKyle Evans */ 251*f0865ec9SKyle Evans if(ctx != NULL){ 252*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->sign_data.ecdsa), 0, sizeof(ecdsa_sign_data))); 253*f0865ec9SKyle Evans } 254*f0865ec9SKyle Evans 255*f0865ec9SKyle Evans /* Clean what remains on the stack */ 256*f0865ec9SKyle Evans PTR_NULLIFY(priv_key); 257*f0865ec9SKyle Evans PTR_NULLIFY(G); 258*f0865ec9SKyle Evans PTR_NULLIFY(q); 259*f0865ec9SKyle Evans PTR_NULLIFY(x); 260*f0865ec9SKyle Evans VAR_ZEROIFY(q_len); 261*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 262*f0865ec9SKyle Evans VAR_ZEROIFY(rshift); 263*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 264*f0865ec9SKyle Evans 265*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 266*f0865ec9SKyle Evans nn_uninit(&b); 267*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 268*f0865ec9SKyle Evans 269*f0865ec9SKyle Evans return ret; 270*f0865ec9SKyle Evans } 271*f0865ec9SKyle Evans 272*f0865ec9SKyle Evans /******************************/ 273*f0865ec9SKyle Evans #define ECDSA_VERIFY_MAGIC ((word_t)(0x5155fe73e7fd51beULL)) 274*f0865ec9SKyle Evans #define ECDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \ 275*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == ECDSA_VERIFY_MAGIC), ret, err) 276*f0865ec9SKyle Evans 277*f0865ec9SKyle Evans int ecdsa_verify_raw(struct ec_verify_context *ctx, const u8 *input, u8 inputlen) 278*f0865ec9SKyle Evans { 279*f0865ec9SKyle Evans prj_pt uG, vY; 280*f0865ec9SKyle Evans prj_pt_t W_prime; 281*f0865ec9SKyle Evans nn e, sinv, uv, r_prime; 282*f0865ec9SKyle Evans prj_pt_src_t G, Y; 283*f0865ec9SKyle Evans /* NOTE: hash here is not really a hash ... */ 284*f0865ec9SKyle Evans u8 hash[LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8))]; 285*f0865ec9SKyle Evans bitcnt_t rshift, q_bit_len; 286*f0865ec9SKyle Evans nn_src_t q; 287*f0865ec9SKyle Evans nn *s, *r; 288*f0865ec9SKyle Evans u8 hsize; 289*f0865ec9SKyle Evans int ret, iszero, cmp; 290*f0865ec9SKyle Evans 291*f0865ec9SKyle Evans e.magic = sinv.magic = uv.magic = r_prime.magic = WORD(0); 292*f0865ec9SKyle Evans uG.magic = vY.magic = WORD(0); 293*f0865ec9SKyle Evans 294*f0865ec9SKyle Evans /* NOTE: we reuse uG for W_prime to optimize local variables */ 295*f0865ec9SKyle Evans W_prime = &uG; 296*f0865ec9SKyle Evans 297*f0865ec9SKyle Evans /* 298*f0865ec9SKyle Evans * First, verify context has been initialized and public 299*f0865ec9SKyle Evans * part too. This guarantees the context is an ECDSA 300*f0865ec9SKyle Evans * verification one and we do not finalize() before init(). 301*f0865ec9SKyle Evans */ 302*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 303*f0865ec9SKyle Evans ECDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecdsa), ret, err); 304*f0865ec9SKyle Evans MUST_HAVE((input != NULL), ret, err); 305*f0865ec9SKyle Evans 306*f0865ec9SKyle Evans /* Zero init points */ 307*f0865ec9SKyle Evans ret = local_memset(&uG, 0, sizeof(prj_pt)); EG(ret, err); 308*f0865ec9SKyle Evans ret = local_memset(&vY, 0, sizeof(prj_pt)); EG(ret, err); 309*f0865ec9SKyle Evans 310*f0865ec9SKyle Evans /* Make things more readable */ 311*f0865ec9SKyle Evans G = &(ctx->pub_key->params->ec_gen); 312*f0865ec9SKyle Evans Y = &(ctx->pub_key->y); 313*f0865ec9SKyle Evans q = &(ctx->pub_key->params->ec_gen_order); 314*f0865ec9SKyle Evans q_bit_len = ctx->pub_key->params->ec_gen_order_bitlen; 315*f0865ec9SKyle Evans hsize = inputlen; 316*f0865ec9SKyle Evans r = &(ctx->verify_data.ecdsa.r); 317*f0865ec9SKyle Evans s = &(ctx->verify_data.ecdsa.s); 318*f0865ec9SKyle Evans 319*f0865ec9SKyle Evans /* 2. Compute h = H(m) */ 320*f0865ec9SKyle Evans /* NOTE: here we have raw ECDSA, this is the raw input */ 321*f0865ec9SKyle Evans MUST_HAVE((input != NULL), ret, err); 322*f0865ec9SKyle Evans /* NOTE: the MUST_HAVE is protected by a preprocessing check 323*f0865ec9SKyle Evans * to avoid -Werror=type-limits errors: 324*f0865ec9SKyle Evans * "error: comparison is always true due to limited range of data type" 325*f0865ec9SKyle Evans */ 326*f0865ec9SKyle Evans #if LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8)) < 255 327*f0865ec9SKyle Evans MUST_HAVE(((u32)inputlen <= sizeof(hash)), ret, err); 328*f0865ec9SKyle Evans #endif 329*f0865ec9SKyle Evans 330*f0865ec9SKyle Evans ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err); 331*f0865ec9SKyle Evans ret = local_memcpy(hash, input, hsize); EG(ret, err); 332*f0865ec9SKyle Evans 333*f0865ec9SKyle Evans dbg_buf_print("h = H(m)", hash, hsize); 334*f0865ec9SKyle Evans 335*f0865ec9SKyle Evans /* 336*f0865ec9SKyle Evans * 3. If |h| > bitlen(q), set h to bitlen(q) 337*f0865ec9SKyle Evans * leftmost bits of h. 338*f0865ec9SKyle Evans * 339*f0865ec9SKyle Evans * Note that it's easier to check here if the truncation 340*f0865ec9SKyle Evans * needs to be done but implement it using a logical 341*f0865ec9SKyle Evans * shift at the beginning of step 3. below once the hash 342*f0865ec9SKyle Evans * has been converted to an integer. 343*f0865ec9SKyle Evans */ 344*f0865ec9SKyle Evans rshift = 0; 345*f0865ec9SKyle Evans if ((hsize * 8) > q_bit_len) { 346*f0865ec9SKyle Evans rshift = (bitcnt_t)((hsize * 8) - q_bit_len); 347*f0865ec9SKyle Evans } 348*f0865ec9SKyle Evans 349*f0865ec9SKyle Evans /* 350*f0865ec9SKyle Evans * 4. Compute e = OS2I(h) mod q, by converting h to an integer 351*f0865ec9SKyle Evans * and reducing it mod q 352*f0865ec9SKyle Evans */ 353*f0865ec9SKyle Evans ret = nn_init_from_buf(&e, hash, hsize); EG(ret, err); 354*f0865ec9SKyle Evans ret = local_memset(hash, 0, hsize); EG(ret, err); 355*f0865ec9SKyle Evans dbg_nn_print("h initial import as nn", &e); 356*f0865ec9SKyle Evans if (rshift) { 357*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&e, &e, rshift); EG(ret, err); 358*f0865ec9SKyle Evans } 359*f0865ec9SKyle Evans dbg_nn_print("h final import as nn", &e); 360*f0865ec9SKyle Evans 361*f0865ec9SKyle Evans ret = nn_mod(&e, &e, q); EG(ret, err); 362*f0865ec9SKyle Evans dbg_nn_print("e", &e); 363*f0865ec9SKyle Evans 364*f0865ec9SKyle Evans /* Compute s^-1 mod q */ 365*f0865ec9SKyle Evans ret = nn_modinv(&sinv, s, q); EG(ret, err); 366*f0865ec9SKyle Evans dbg_nn_print("s", s); 367*f0865ec9SKyle Evans dbg_nn_print("sinv", &sinv); 368*f0865ec9SKyle Evans nn_uninit(s); 369*f0865ec9SKyle Evans 370*f0865ec9SKyle Evans /* 5. Compute u = (s^-1)e mod q */ 371*f0865ec9SKyle Evans ret = nn_mod_mul(&uv, &e, &sinv, q); EG(ret, err); 372*f0865ec9SKyle Evans dbg_nn_print("u = (s^-1)e mod q", &uv); 373*f0865ec9SKyle Evans ret = prj_pt_mul(&uG, &uv, G); EG(ret, err); 374*f0865ec9SKyle Evans 375*f0865ec9SKyle Evans /* 6. Compute v = (s^-1)r mod q */ 376*f0865ec9SKyle Evans ret = nn_mod_mul(&uv, r, &sinv, q); EG(ret, err); 377*f0865ec9SKyle Evans dbg_nn_print("v = (s^-1)r mod q", &uv); 378*f0865ec9SKyle Evans ret = prj_pt_mul(&vY, &uv, Y); EG(ret, err); 379*f0865ec9SKyle Evans 380*f0865ec9SKyle Evans /* 7. Compute W' = uG + vY */ 381*f0865ec9SKyle Evans ret = prj_pt_add(W_prime, &uG, &vY); EG(ret, err); 382*f0865ec9SKyle Evans 383*f0865ec9SKyle Evans /* 8. If W' is the point at infinity, reject the signature. */ 384*f0865ec9SKyle Evans ret = prj_pt_iszero(W_prime, &iszero); EG(ret, err); 385*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 386*f0865ec9SKyle Evans 387*f0865ec9SKyle Evans /* 9. Compute r' = W'_x mod q */ 388*f0865ec9SKyle Evans ret = prj_pt_unique(W_prime, W_prime); EG(ret, err); 389*f0865ec9SKyle Evans dbg_nn_print("W'_x", &(W_prime->X.fp_val)); 390*f0865ec9SKyle Evans dbg_nn_print("W'_y", &(W_prime->Y.fp_val)); 391*f0865ec9SKyle Evans ret = nn_mod(&r_prime, &(W_prime->X.fp_val), q); EG(ret, err); 392*f0865ec9SKyle Evans 393*f0865ec9SKyle Evans /* 10. Accept the signature if and only if r equals r' */ 394*f0865ec9SKyle Evans ret = nn_cmp(&r_prime, r, &cmp); EG(ret, err); 395*f0865ec9SKyle Evans ret = (cmp != 0) ? -1 : 0; 396*f0865ec9SKyle Evans 397*f0865ec9SKyle Evans err: 398*f0865ec9SKyle Evans nn_uninit(&r_prime); 399*f0865ec9SKyle Evans nn_uninit(&uv); 400*f0865ec9SKyle Evans nn_uninit(&e); 401*f0865ec9SKyle Evans nn_uninit(&sinv); 402*f0865ec9SKyle Evans prj_pt_uninit(&uG); 403*f0865ec9SKyle Evans prj_pt_uninit(&vY); 404*f0865ec9SKyle Evans 405*f0865ec9SKyle Evans /* 406*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 407*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 408*f0865ec9SKyle Evans */ 409*f0865ec9SKyle Evans if(ctx != NULL){ 410*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->verify_data.ecdsa), 0, sizeof(ecdsa_verify_data))); 411*f0865ec9SKyle Evans } 412*f0865ec9SKyle Evans 413*f0865ec9SKyle Evans /* Clean what remains on the stack */ 414*f0865ec9SKyle Evans PTR_NULLIFY(W_prime); 415*f0865ec9SKyle Evans PTR_NULLIFY(G); 416*f0865ec9SKyle Evans PTR_NULLIFY(Y); 417*f0865ec9SKyle Evans VAR_ZEROIFY(rshift); 418*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 419*f0865ec9SKyle Evans PTR_NULLIFY(q); 420*f0865ec9SKyle Evans PTR_NULLIFY(s); 421*f0865ec9SKyle Evans PTR_NULLIFY(r); 422*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 423*f0865ec9SKyle Evans 424*f0865ec9SKyle Evans return ret; 425*f0865ec9SKyle Evans } 426*f0865ec9SKyle Evans 427*f0865ec9SKyle Evans 428*f0865ec9SKyle Evans #else /* WITH_SIG_ECDSA && USE_CRYPTOFUZZ */ 429*f0865ec9SKyle Evans 430*f0865ec9SKyle Evans /* 431*f0865ec9SKyle Evans * Dummy definition to avoid the empty translation unit ISO C warning 432*f0865ec9SKyle Evans */ 433*f0865ec9SKyle Evans typedef int dummy; 434*f0865ec9SKyle Evans #endif /* WITH_SIG_ECDSA */ 435