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_ECSDSA) || defined(WITH_SIG_ECOSDSA)) 18*f0865ec9SKyle Evans 19*f0865ec9SKyle Evans #include <libecc/nn/nn_rand.h> 20*f0865ec9SKyle Evans #include <libecc/nn/nn_mul_public.h> 21*f0865ec9SKyle Evans #include <libecc/nn/nn_logical.h> 22*f0865ec9SKyle Evans 23*f0865ec9SKyle Evans #include <libecc/sig/ecsdsa_common.h> 24*f0865ec9SKyle Evans #include <libecc/sig/sig_algs_internal.h> 25*f0865ec9SKyle Evans #include <libecc/sig/ec_key.h> 26*f0865ec9SKyle Evans #ifdef VERBOSE_INNER_VALUES 27*f0865ec9SKyle Evans #define EC_SIG_ALG "EC[O]SDSA" 28*f0865ec9SKyle Evans #endif 29*f0865ec9SKyle Evans #include <libecc/utils/dbg_sig.h> 30*f0865ec9SKyle Evans 31*f0865ec9SKyle Evans /* 32*f0865ec9SKyle Evans * Generic *internal* helper for EC-{,O}SDSA public key initialization 33*f0865ec9SKyle Evans * functions. The function returns 0 on success, -1 on error. 34*f0865ec9SKyle Evans */ 35*f0865ec9SKyle Evans int __ecsdsa_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv, 36*f0865ec9SKyle Evans ec_alg_type key_type) 37*f0865ec9SKyle Evans { 38*f0865ec9SKyle Evans prj_pt_src_t G; 39*f0865ec9SKyle Evans int ret; 40*f0865ec9SKyle Evans 41*f0865ec9SKyle Evans MUST_HAVE((out_pub != NULL), ret, err); 42*f0865ec9SKyle Evans 43*f0865ec9SKyle Evans /* Zero init public key to be generated */ 44*f0865ec9SKyle Evans ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err); 45*f0865ec9SKyle Evans 46*f0865ec9SKyle Evans ret = priv_key_check_initialized_and_type(in_priv, key_type); EG(ret, err); 47*f0865ec9SKyle Evans 48*f0865ec9SKyle Evans /* Y = xG */ 49*f0865ec9SKyle Evans G = &(in_priv->params->ec_gen); 50*f0865ec9SKyle Evans /* Use blinding when computing point scalar multiplication */ 51*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&(out_pub->y), &(in_priv->x), G); EG(ret, err); 52*f0865ec9SKyle Evans 53*f0865ec9SKyle Evans out_pub->key_type = key_type; 54*f0865ec9SKyle Evans out_pub->params = in_priv->params; 55*f0865ec9SKyle Evans out_pub->magic = PUB_KEY_MAGIC; 56*f0865ec9SKyle Evans 57*f0865ec9SKyle Evans err: 58*f0865ec9SKyle Evans return ret; 59*f0865ec9SKyle Evans } 60*f0865ec9SKyle Evans 61*f0865ec9SKyle Evans /* 62*f0865ec9SKyle Evans * Generic *internal* helper for EC{,O}SDSA signature length functions. 63*f0865ec9SKyle Evans * It provides signature length when exported to a buffer based on hash 64*f0865ec9SKyle Evans * algorithm digest and block size, generator point order bit length, and 65*f0865ec9SKyle Evans * uderlying prime field order bit length. The function returns 0 on success, 66*f0865ec9SKyle Evans * -1 on error. On success, signature length is provided via 'siglen' out 67*f0865ec9SKyle Evans * parameter. The function returns 0 on success, -1 on error. On success, 68*f0865ec9SKyle Evans * 'siglen' out parameter provides the length of signature fonction. It is 69*f0865ec9SKyle Evans * not meaningful on error. 70*f0865ec9SKyle Evans */ 71*f0865ec9SKyle Evans int __ecsdsa_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize, 72*f0865ec9SKyle Evans u8 *siglen) 73*f0865ec9SKyle Evans { 74*f0865ec9SKyle Evans int ret; 75*f0865ec9SKyle Evans 76*f0865ec9SKyle Evans MUST_HAVE((siglen != NULL), ret, err); 77*f0865ec9SKyle Evans MUST_HAVE(((p_bit_len <= CURVES_MAX_P_BIT_LEN) && 78*f0865ec9SKyle Evans (q_bit_len <= CURVES_MAX_Q_BIT_LEN) && 79*f0865ec9SKyle Evans (hsize <= MAX_DIGEST_SIZE) && (blocksize <= MAX_BLOCK_SIZE)), 80*f0865ec9SKyle Evans ret, err); 81*f0865ec9SKyle Evans 82*f0865ec9SKyle Evans (*siglen) = (u8)ECSDSA_SIGLEN(hsize, q_bit_len); 83*f0865ec9SKyle Evans ret = 0; 84*f0865ec9SKyle Evans 85*f0865ec9SKyle Evans err: 86*f0865ec9SKyle Evans return ret; 87*f0865ec9SKyle Evans } 88*f0865ec9SKyle Evans 89*f0865ec9SKyle Evans /* 90*f0865ec9SKyle Evans * Generic *internal* EC-{,O}SDSA signature functions. There purpose is to 91*f0865ec9SKyle Evans * allow passing specific hash functions and the random ephemeral 92*f0865ec9SKyle Evans * key k, so that compliance tests against test vector be made 93*f0865ec9SKyle Evans * without ugly hack in the code itself. 94*f0865ec9SKyle Evans * 95*f0865ec9SKyle Evans * The 'optimized' parameter tells the function if the r value of 96*f0865ec9SKyle Evans * the signature is computed using only the x ccordinate of the 97*f0865ec9SKyle Evans * the user's public key (normal version uses both coordinates). 98*f0865ec9SKyle Evans * 99*f0865ec9SKyle Evans * Normal: r = h(Wx || Wy || m) 100*f0865ec9SKyle Evans * Optimized : r = h(Wx || m) 101*f0865ec9SKyle Evans * 102*f0865ec9SKyle Evans *| IUF - ECSDSA/ECOSDSA signature 103*f0865ec9SKyle Evans *| 104*f0865ec9SKyle Evans *| I 1. Get a random value k in ]0, q[ 105*f0865ec9SKyle Evans *| I 2. Compute W = kG = (Wx, Wy) 106*f0865ec9SKyle Evans *| IUF 3. Compute r = H(Wx [|| Wy] || m) 107*f0865ec9SKyle Evans *| - In the normal version (ECSDSA), r = H(Wx || Wy || m). 108*f0865ec9SKyle Evans *| - In the optimized version (ECOSDSA), r = H(Wx || m). 109*f0865ec9SKyle Evans *| F 4. Compute e = OS2I(r) mod q 110*f0865ec9SKyle Evans *| F 5. if e == 0, restart at step 1. 111*f0865ec9SKyle Evans *| F 6. Compute s = (k + ex) mod q. 112*f0865ec9SKyle Evans *| F 7. if s == 0, restart at step 1. 113*f0865ec9SKyle Evans *| F 8. Return (r, s) 114*f0865ec9SKyle Evans * 115*f0865ec9SKyle Evans * In the project, the normal mode is named ECSDSA, the optimized 116*f0865ec9SKyle Evans * one is ECOSDSA. 117*f0865ec9SKyle Evans * 118*f0865ec9SKyle Evans * Implementation note: 119*f0865ec9SKyle Evans * 120*f0865ec9SKyle Evans * In ISO-14888-3, the option is provided to the developer to check 121*f0865ec9SKyle Evans * whether r = 0 and restart the process in that case. Even if 122*f0865ec9SKyle Evans * unlikely to trigger, that check makes a lot of sense because the 123*f0865ec9SKyle Evans * verifier expects a non-zero value for r. In the specification, r 124*f0865ec9SKyle Evans * is a string (r = H(Wx [|| Wy] || m)). But r is used in practice 125*f0865ec9SKyle Evans * - both on the signer and the verifier - after conversion to an 126*f0865ec9SKyle Evans * integer and reduction mod q. The value resulting from that step 127*f0865ec9SKyle Evans * is named e (e = OS2I(r) mod q). The check for the case when r = 0 128*f0865ec9SKyle Evans * should be replaced by a check for e = 0. This is more conservative 129*f0865ec9SKyle Evans * and what is described above and done below in the implementation. 130*f0865ec9SKyle Evans */ 131*f0865ec9SKyle Evans 132*f0865ec9SKyle Evans #define ECSDSA_SIGN_MAGIC ((word_t)(0x743c03ae409d15c4ULL)) 133*f0865ec9SKyle Evans #define ECSDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \ 134*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && \ 135*f0865ec9SKyle Evans ((A)->magic == ECSDSA_SIGN_MAGIC), ret, err) 136*f0865ec9SKyle Evans 137*f0865ec9SKyle Evans /* 138*f0865ec9SKyle Evans * Generic *internal* helper for EC-{,O}SDSA signature initialization functions. 139*f0865ec9SKyle Evans * The function returns 0 on success, -1 on error. 140*f0865ec9SKyle Evans */ 141*f0865ec9SKyle Evans int __ecsdsa_sign_init(struct ec_sign_context *ctx, 142*f0865ec9SKyle Evans ec_alg_type key_type, int optimized) 143*f0865ec9SKyle Evans { 144*f0865ec9SKyle Evans u8 Wx[BYTECEIL(CURVES_MAX_P_BIT_LEN)]; 145*f0865ec9SKyle Evans u8 Wy[BYTECEIL(CURVES_MAX_P_BIT_LEN)]; 146*f0865ec9SKyle Evans const ec_priv_key *priv_key; 147*f0865ec9SKyle Evans prj_pt_src_t G; 148*f0865ec9SKyle Evans bitcnt_t p_bit_len; 149*f0865ec9SKyle Evans u8 p_len; 150*f0865ec9SKyle Evans prj_pt kG; 151*f0865ec9SKyle Evans nn_src_t q; 152*f0865ec9SKyle Evans int ret; 153*f0865ec9SKyle Evans nn k; 154*f0865ec9SKyle Evans kG.magic = k.magic = WORD(0); 155*f0865ec9SKyle Evans 156*f0865ec9SKyle Evans /* First, verify context has been initialized */ 157*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 158*f0865ec9SKyle Evans 159*f0865ec9SKyle Evans /* Zero init points */ 160*f0865ec9SKyle Evans ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err); 161*f0865ec9SKyle Evans 162*f0865ec9SKyle Evans /* Additional sanity checks on input params from context */ 163*f0865ec9SKyle Evans ret = key_pair_check_initialized_and_type(ctx->key_pair, key_type); EG(ret, err); 164*f0865ec9SKyle Evans MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) && 165*f0865ec9SKyle Evans (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err); 166*f0865ec9SKyle Evans 167*f0865ec9SKyle Evans /* Make things more readable */ 168*f0865ec9SKyle Evans priv_key = &(ctx->key_pair->priv_key); 169*f0865ec9SKyle Evans G = &(priv_key->params->ec_gen); 170*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order); 171*f0865ec9SKyle Evans p_bit_len = priv_key->params->ec_fp.p_bitlen; 172*f0865ec9SKyle Evans p_len = (u8)BYTECEIL(p_bit_len); 173*f0865ec9SKyle Evans 174*f0865ec9SKyle Evans dbg_nn_print("p", &(priv_key->params->ec_fp.p)); 175*f0865ec9SKyle Evans dbg_nn_print("q", q); 176*f0865ec9SKyle Evans dbg_priv_key_print("x", priv_key); 177*f0865ec9SKyle Evans dbg_ec_point_print("G", G); 178*f0865ec9SKyle Evans dbg_pub_key_print("Y", &(ctx->key_pair->pub_key)); 179*f0865ec9SKyle Evans 180*f0865ec9SKyle Evans /* 1. Get a random value k in ]0, q[ */ 181*f0865ec9SKyle Evans #ifdef NO_KNOWN_VECTORS 182*f0865ec9SKyle Evans /* NOTE: when we do not need self tests for known vectors, 183*f0865ec9SKyle Evans * we can be strict about random function handler! 184*f0865ec9SKyle Evans * This allows us to avoid the corruption of such a pointer. 185*f0865ec9SKyle Evans */ 186*f0865ec9SKyle Evans /* Sanity check on the handler before calling it */ 187*f0865ec9SKyle Evans MUST_HAVE((ctx->rand == nn_get_random_mod), ret, err); 188*f0865ec9SKyle Evans #endif 189*f0865ec9SKyle Evans MUST_HAVE((ctx->rand != NULL), ret, err); 190*f0865ec9SKyle Evans ret = ctx->rand(&k, q); EG(ret, err); 191*f0865ec9SKyle Evans dbg_nn_print("k", &k); 192*f0865ec9SKyle Evans 193*f0865ec9SKyle Evans /* 2. Compute W = kG = (Wx, Wy). */ 194*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 195*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err); 196*f0865ec9SKyle Evans #else 197*f0865ec9SKyle Evans ret = prj_pt_mul(&kG, &k, G); EG(ret, err); 198*f0865ec9SKyle Evans #endif 199*f0865ec9SKyle Evans ret = prj_pt_unique(&kG, &kG); EG(ret, err); 200*f0865ec9SKyle Evans dbg_nn_print("W_x", &(kG.X.fp_val)); 201*f0865ec9SKyle Evans dbg_nn_print("W_y", &(kG.Y.fp_val)); 202*f0865ec9SKyle Evans 203*f0865ec9SKyle Evans /* 204*f0865ec9SKyle Evans * 3. Compute r = H(Wx [|| Wy] || m) 205*f0865ec9SKyle Evans * 206*f0865ec9SKyle Evans * - In the normal version (ECSDSA), r = h(Wx || Wy || m). 207*f0865ec9SKyle Evans * - In the optimized version (ECOSDSA), r = h(Wx || m). 208*f0865ec9SKyle Evans */ 209*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 210*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 211*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(&(ctx->sign_data.ecsdsa.h_ctx)); EG(ret, err); 212*f0865ec9SKyle Evans ret = fp_export_to_buf(Wx, p_len, &(kG.X)); EG(ret, err); 213*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->sign_data.ecsdsa.h_ctx), Wx, p_len); EG(ret, err); 214*f0865ec9SKyle Evans if (!optimized) { 215*f0865ec9SKyle Evans ret = fp_export_to_buf(Wy, p_len, &(kG.Y)); EG(ret, err); 216*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->sign_data.ecsdsa.h_ctx), Wy, 217*f0865ec9SKyle Evans p_len); EG(ret, err); 218*f0865ec9SKyle Evans } 219*f0865ec9SKyle Evans ret = local_memset(Wx, 0, p_len); EG(ret, err); 220*f0865ec9SKyle Evans ret = local_memset(Wy, 0, p_len); EG(ret, err); 221*f0865ec9SKyle Evans 222*f0865ec9SKyle Evans /* Initialize the remaining of sign context. */ 223*f0865ec9SKyle Evans ret = nn_copy(&(ctx->sign_data.ecsdsa.k), &k); EG(ret, err); 224*f0865ec9SKyle Evans ctx->sign_data.ecsdsa.magic = ECSDSA_SIGN_MAGIC; 225*f0865ec9SKyle Evans 226*f0865ec9SKyle Evans err: 227*f0865ec9SKyle Evans prj_pt_uninit(&kG); 228*f0865ec9SKyle Evans nn_uninit(&k); 229*f0865ec9SKyle Evans 230*f0865ec9SKyle Evans PTR_NULLIFY(priv_key); 231*f0865ec9SKyle Evans PTR_NULLIFY(G); 232*f0865ec9SKyle Evans PTR_NULLIFY(q); 233*f0865ec9SKyle Evans VAR_ZEROIFY(p_len); 234*f0865ec9SKyle Evans VAR_ZEROIFY(p_bit_len); 235*f0865ec9SKyle Evans 236*f0865ec9SKyle Evans return ret; 237*f0865ec9SKyle Evans } 238*f0865ec9SKyle Evans 239*f0865ec9SKyle Evans /* 240*f0865ec9SKyle Evans * Generic *internal* helper for EC-{,O}SDSA signature update functions. 241*f0865ec9SKyle Evans * The function returns 0 on success, -1 on error. 242*f0865ec9SKyle Evans */ 243*f0865ec9SKyle Evans int __ecsdsa_sign_update(struct ec_sign_context *ctx, 244*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 245*f0865ec9SKyle Evans { 246*f0865ec9SKyle Evans int ret; 247*f0865ec9SKyle Evans 248*f0865ec9SKyle Evans /* 249*f0865ec9SKyle Evans * First, verify context has been initialized and private 250*f0865ec9SKyle Evans * part too. This guarantees the context is an ECSDSA 251*f0865ec9SKyle Evans * signature one and we do not update() or finalize() 252*f0865ec9SKyle Evans * before init(). 253*f0865ec9SKyle Evans */ 254*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 255*f0865ec9SKyle Evans ECSDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecsdsa), ret, err); 256*f0865ec9SKyle Evans 257*f0865ec9SKyle Evans /* 3. Compute r = H(Wx [|| Wy] || m) */ 258*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 259*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 260*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->sign_data.ecsdsa.h_ctx), chunk, chunklen); EG(ret, err); 261*f0865ec9SKyle Evans 262*f0865ec9SKyle Evans err: 263*f0865ec9SKyle Evans return ret; 264*f0865ec9SKyle Evans } 265*f0865ec9SKyle Evans 266*f0865ec9SKyle Evans /* 267*f0865ec9SKyle Evans * Generic *internal* helper for EC-{,O}SDSA signature finalization functions. 268*f0865ec9SKyle Evans * The function returns 0 on success, -1 on error. 269*f0865ec9SKyle Evans */ 270*f0865ec9SKyle Evans int __ecsdsa_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen) 271*f0865ec9SKyle Evans { 272*f0865ec9SKyle Evans nn_src_t q, x; 273*f0865ec9SKyle Evans nn s, e, ex; 274*f0865ec9SKyle Evans u8 r[MAX_DIGEST_SIZE]; 275*f0865ec9SKyle Evans const ec_priv_key *priv_key; 276*f0865ec9SKyle Evans bitcnt_t q_bit_len; 277*f0865ec9SKyle Evans u8 r_len, s_len; 278*f0865ec9SKyle Evans u8 hsize; 279*f0865ec9SKyle Evans int ret; 280*f0865ec9SKyle Evans int iszero; 281*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 282*f0865ec9SKyle Evans /* b is the blinding mask */ 283*f0865ec9SKyle Evans nn b, binv; 284*f0865ec9SKyle Evans b.magic = binv.magic = WORD(0); 285*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 286*f0865ec9SKyle Evans 287*f0865ec9SKyle Evans s.magic = e.magic = ex.magic = WORD(0); 288*f0865ec9SKyle Evans 289*f0865ec9SKyle Evans /* 290*f0865ec9SKyle Evans * First, verify context has been initialized and private 291*f0865ec9SKyle Evans * part too. This guarantees the context is an ECSDSA 292*f0865ec9SKyle Evans * signature one and we do not finalize() before init(). 293*f0865ec9SKyle Evans */ 294*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 295*f0865ec9SKyle Evans ECSDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecsdsa), ret, err); 296*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 297*f0865ec9SKyle Evans 298*f0865ec9SKyle Evans /* Make things more readable */ 299*f0865ec9SKyle Evans priv_key = &(ctx->key_pair->priv_key); 300*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order); 301*f0865ec9SKyle Evans x = &(priv_key->x); 302*f0865ec9SKyle Evans q_bit_len = priv_key->params->ec_gen_order_bitlen; 303*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 304*f0865ec9SKyle Evans r_len = (u8)ECSDSA_R_LEN(hsize); 305*f0865ec9SKyle Evans s_len = (u8)ECSDSA_S_LEN(q_bit_len); 306*f0865ec9SKyle Evans 307*f0865ec9SKyle Evans MUST_HAVE((siglen == ECSDSA_SIGLEN(hsize, q_bit_len)), ret, err); 308*f0865ec9SKyle Evans 309*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 310*f0865ec9SKyle Evans ret = nn_get_random_mod(&b, q); EG(ret, err); 311*f0865ec9SKyle Evans dbg_nn_print("b", &b); 312*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 313*f0865ec9SKyle Evans 314*f0865ec9SKyle Evans /* 3. Compute r = H(Wx [|| Wy] || m) */ 315*f0865ec9SKyle Evans ret = local_memset(r, 0, hsize); EG(ret, err); 316*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 317*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 318*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(&(ctx->sign_data.ecsdsa.h_ctx), r); EG(ret, err); 319*f0865ec9SKyle Evans 320*f0865ec9SKyle Evans dbg_buf_print("r", r, r_len); 321*f0865ec9SKyle Evans 322*f0865ec9SKyle Evans /* 4. Compute e = OS2I(r) mod q */ 323*f0865ec9SKyle Evans ret = nn_init_from_buf(&e, r, r_len); EG(ret, err); 324*f0865ec9SKyle Evans ret = nn_mod(&e, &e, q); EG(ret, err); 325*f0865ec9SKyle Evans dbg_nn_print("e", &e); 326*f0865ec9SKyle Evans 327*f0865ec9SKyle Evans /* 328*f0865ec9SKyle Evans * 5. if e == 0, restart at step 1. 329*f0865ec9SKyle Evans * 330*f0865ec9SKyle Evans * As we cannot restart at that point (step 1. is in init()), 331*f0865ec9SKyle Evans * we just stop and return an error. 332*f0865ec9SKyle Evans */ 333*f0865ec9SKyle Evans MUST_HAVE(!nn_iszero(&e, &iszero) && !iszero, ret, err); 334*f0865ec9SKyle Evans 335*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 336*f0865ec9SKyle Evans /* Blind e with b */ 337*f0865ec9SKyle Evans ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err); 338*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 339*f0865ec9SKyle Evans 340*f0865ec9SKyle Evans /* 6. Compute s = (k + ex) mod q. */ 341*f0865ec9SKyle Evans ret = nn_mod_mul(&ex, x, &e, q); EG(ret, err); 342*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 343*f0865ec9SKyle Evans /* Blind k with b */ 344*f0865ec9SKyle Evans ret = nn_mod_mul(&s, &(ctx->sign_data.ecsdsa.k), &b, q); EG(ret, err); 345*f0865ec9SKyle Evans ret = nn_mod_add(&s, &s, &ex, q); EG(ret, err); 346*f0865ec9SKyle Evans #else 347*f0865ec9SKyle Evans ret = nn_mod_add(&s, &(ctx->sign_data.ecsdsa.k), &ex, q); EG(ret, err); 348*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 349*f0865ec9SKyle Evans 350*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 351*f0865ec9SKyle Evans /* Unblind s */ 352*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 353*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 354*f0865ec9SKyle Evans */ 355*f0865ec9SKyle Evans ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err); 356*f0865ec9SKyle Evans ret = nn_mod_mul(&s, &s, &binv, q); EG(ret, err); 357*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 358*f0865ec9SKyle Evans dbg_nn_print("s", &s); 359*f0865ec9SKyle Evans 360*f0865ec9SKyle Evans /* 361*f0865ec9SKyle Evans * 7. if s == 0, restart at step 1. 362*f0865ec9SKyle Evans * 363*f0865ec9SKyle Evans * As we cannot restart at that point (step 1. is in init()), 364*f0865ec9SKyle Evans * we just stop and return an error. 365*f0865ec9SKyle Evans */ 366*f0865ec9SKyle Evans MUST_HAVE((!nn_iszero(&s, &iszero)) && (!iszero), ret, err); 367*f0865ec9SKyle Evans 368*f0865ec9SKyle Evans /* 8. Return (r, s) */ 369*f0865ec9SKyle Evans ret = local_memcpy(sig, r, r_len); EG(ret, err); 370*f0865ec9SKyle Evans ret = local_memset(r, 0, r_len); EG(ret, err); 371*f0865ec9SKyle Evans ret = nn_export_to_buf(sig + r_len, s_len, &s); 372*f0865ec9SKyle Evans 373*f0865ec9SKyle Evans err: 374*f0865ec9SKyle Evans nn_uninit(&s); 375*f0865ec9SKyle Evans nn_uninit(&e); 376*f0865ec9SKyle Evans nn_uninit(&ex); 377*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 378*f0865ec9SKyle Evans nn_uninit(&b); 379*f0865ec9SKyle Evans nn_uninit(&binv); 380*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 381*f0865ec9SKyle Evans 382*f0865ec9SKyle Evans /* 383*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 384*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 385*f0865ec9SKyle Evans */ 386*f0865ec9SKyle Evans if(ctx != NULL){ 387*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->sign_data.ecsdsa), 0, sizeof(ecsdsa_sign_data))); 388*f0865ec9SKyle Evans } 389*f0865ec9SKyle Evans 390*f0865ec9SKyle Evans /* Clean what remains on the stack */ 391*f0865ec9SKyle Evans PTR_NULLIFY(q); 392*f0865ec9SKyle Evans PTR_NULLIFY(x); 393*f0865ec9SKyle Evans PTR_NULLIFY(priv_key); 394*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 395*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 396*f0865ec9SKyle Evans VAR_ZEROIFY(s_len); 397*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 398*f0865ec9SKyle Evans 399*f0865ec9SKyle Evans return ret; 400*f0865ec9SKyle Evans } 401*f0865ec9SKyle Evans 402*f0865ec9SKyle Evans /* local helper for context sanity checks. Returns 0 on success, -1 on error. */ 403*f0865ec9SKyle Evans #define ECSDSA_VERIFY_MAGIC ((word_t)(0x8eac1ff89995bb0aULL)) 404*f0865ec9SKyle Evans #define ECSDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \ 405*f0865ec9SKyle Evans MUST_HAVE((((const void *)(A)) != NULL) && \ 406*f0865ec9SKyle Evans ((A)->magic == ECSDSA_VERIFY_MAGIC), ret, err) 407*f0865ec9SKyle Evans 408*f0865ec9SKyle Evans /* 409*f0865ec9SKyle Evans *| IUF - ECSDSA/ECOSDSA verification 410*f0865ec9SKyle Evans *| 411*f0865ec9SKyle Evans *| I 1. if s is not in ]0,q[, reject the signature. 412*f0865ec9SKyle Evans *| I 2. Compute e = -r mod q 413*f0865ec9SKyle Evans *| I 3. If e == 0, reject the signature. 414*f0865ec9SKyle Evans *| I 4. Compute W' = sG + eY 415*f0865ec9SKyle Evans *| IUF 5. Compute r' = H(W'x [|| W'y] || m) 416*f0865ec9SKyle Evans *| - In the normal version (ECSDSA), r' = H(W'x || W'y || m). 417*f0865ec9SKyle Evans *| - In the optimized version (ECOSDSA), r' = H(W'x || m). 418*f0865ec9SKyle Evans *| F 6. Accept the signature if and only if r and r' are the same 419*f0865ec9SKyle Evans */ 420*f0865ec9SKyle Evans 421*f0865ec9SKyle Evans /* 422*f0865ec9SKyle Evans * Generic *internal* helper for EC-{,O}SDSA verification initialization functions. 423*f0865ec9SKyle Evans * The function returns 0 on success, -1 on error. 424*f0865ec9SKyle Evans */ 425*f0865ec9SKyle Evans int __ecsdsa_verify_init(struct ec_verify_context *ctx, 426*f0865ec9SKyle Evans const u8 *sig, u8 siglen, 427*f0865ec9SKyle Evans ec_alg_type key_type, int optimized) 428*f0865ec9SKyle Evans { 429*f0865ec9SKyle Evans prj_pt_src_t G, Y; 430*f0865ec9SKyle Evans const ec_pub_key *pub_key; 431*f0865ec9SKyle Evans nn_src_t q; 432*f0865ec9SKyle Evans nn rmodq, e, r, s; 433*f0865ec9SKyle Evans prj_pt sG, eY; 434*f0865ec9SKyle Evans prj_pt_t Wprime; 435*f0865ec9SKyle Evans u8 Wprimex[BYTECEIL(CURVES_MAX_P_BIT_LEN)]; 436*f0865ec9SKyle Evans u8 Wprimey[BYTECEIL(CURVES_MAX_P_BIT_LEN)]; 437*f0865ec9SKyle Evans u8 p_len, r_len, s_len; 438*f0865ec9SKyle Evans bitcnt_t q_bit_len; 439*f0865ec9SKyle Evans u8 hsize; 440*f0865ec9SKyle Evans int ret, iszero, cmp; 441*f0865ec9SKyle Evans 442*f0865ec9SKyle Evans rmodq.magic = e.magic = r.magic = s.magic = WORD(0); 443*f0865ec9SKyle Evans sG.magic = eY.magic = WORD(0); 444*f0865ec9SKyle Evans 445*f0865ec9SKyle Evans /* NOTE: we reuse sG for Wprime to optimize local variables */ 446*f0865ec9SKyle Evans Wprime = &sG; 447*f0865ec9SKyle Evans 448*f0865ec9SKyle Evans /* First, verify context has been initialized */ 449*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 450*f0865ec9SKyle Evans 451*f0865ec9SKyle Evans /* Zero init points */ 452*f0865ec9SKyle Evans ret = local_memset(&sG, 0, sizeof(prj_pt)); EG(ret, err); 453*f0865ec9SKyle Evans ret = local_memset(&eY, 0, sizeof(prj_pt)); EG(ret, err); 454*f0865ec9SKyle Evans 455*f0865ec9SKyle Evans /* Do some sanity checks on input params */ 456*f0865ec9SKyle Evans ret = pub_key_check_initialized_and_type(ctx->pub_key, key_type); EG(ret, err); 457*f0865ec9SKyle Evans MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) && 458*f0865ec9SKyle Evans (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err); 459*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 460*f0865ec9SKyle Evans 461*f0865ec9SKyle Evans /* Make things more readable */ 462*f0865ec9SKyle Evans pub_key = ctx->pub_key; 463*f0865ec9SKyle Evans G = &(pub_key->params->ec_gen); 464*f0865ec9SKyle Evans Y = &(pub_key->y); 465*f0865ec9SKyle Evans q = &(pub_key->params->ec_gen_order); 466*f0865ec9SKyle Evans p_len = (u8)BYTECEIL(pub_key->params->ec_fp.p_bitlen); 467*f0865ec9SKyle Evans q_bit_len = pub_key->params->ec_gen_order_bitlen; 468*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 469*f0865ec9SKyle Evans r_len = (u8)ECSDSA_R_LEN(hsize); 470*f0865ec9SKyle Evans s_len = (u8)ECSDSA_S_LEN(q_bit_len); 471*f0865ec9SKyle Evans 472*f0865ec9SKyle Evans MUST_HAVE((siglen == ECSDSA_SIGLEN(hsize, q_bit_len)), ret, err); 473*f0865ec9SKyle Evans 474*f0865ec9SKyle Evans /* 1. if s is not in ]0,q[, reject the signature. */ 475*f0865ec9SKyle Evans ret = nn_init_from_buf(&s, sig + r_len, s_len); EG(ret, err); 476*f0865ec9SKyle Evans ret = nn_iszero(&s, &iszero); EG(ret, err); 477*f0865ec9SKyle Evans ret = nn_cmp(&s, q, &cmp); EG(ret, err); 478*f0865ec9SKyle Evans MUST_HAVE((!iszero) && (cmp < 0), ret, err); 479*f0865ec9SKyle Evans 480*f0865ec9SKyle Evans /* 481*f0865ec9SKyle Evans * 2. Compute e = -r mod q 482*f0865ec9SKyle Evans * 483*f0865ec9SKyle Evans * To avoid dealing w/ negative numbers, we simply compute 484*f0865ec9SKyle Evans * e = -r mod q = q - (r mod q) (except when r is 0). 485*f0865ec9SKyle Evans */ 486*f0865ec9SKyle Evans ret = nn_init_from_buf(&r, sig, r_len); EG(ret, err); 487*f0865ec9SKyle Evans ret = nn_mod(&rmodq, &r, q); EG(ret, err); 488*f0865ec9SKyle Evans ret = nn_mod_neg(&e, &rmodq, q); EG(ret, err); 489*f0865ec9SKyle Evans 490*f0865ec9SKyle Evans /* 3. If e == 0, reject the signature. */ 491*f0865ec9SKyle Evans ret = nn_iszero(&e, &iszero); EG(ret, err); 492*f0865ec9SKyle Evans MUST_HAVE((!iszero), ret, err); 493*f0865ec9SKyle Evans 494*f0865ec9SKyle Evans /* 4. Compute W' = sG + eY */ 495*f0865ec9SKyle Evans ret = prj_pt_mul(&sG, &s, G); EG(ret, err); 496*f0865ec9SKyle Evans ret = prj_pt_mul(&eY, &e, Y); EG(ret, err); 497*f0865ec9SKyle Evans ret = prj_pt_add(Wprime, &sG, &eY); EG(ret, err); 498*f0865ec9SKyle Evans ret = prj_pt_unique(Wprime, Wprime); EG(ret, err); 499*f0865ec9SKyle Evans 500*f0865ec9SKyle Evans /* 501*f0865ec9SKyle Evans * 5. Compute r' = H(W'x [|| W'y] || m) 502*f0865ec9SKyle Evans * 503*f0865ec9SKyle Evans * - In the normal version (ECSDSA), r = h(W'x || W'y || m). 504*f0865ec9SKyle Evans * - In the optimized version (ECOSDSA), r = h(W'x || m). 505*f0865ec9SKyle Evans */ 506*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 507*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 508*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(&(ctx->verify_data.ecsdsa.h_ctx)); EG(ret, err); 509*f0865ec9SKyle Evans ret = fp_export_to_buf(Wprimex, p_len, &(Wprime->X)); EG(ret, err); 510*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 511*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 512*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->verify_data.ecsdsa.h_ctx), Wprimex, p_len); EG(ret, err); 513*f0865ec9SKyle Evans if (!optimized) { 514*f0865ec9SKyle Evans ret = fp_export_to_buf(Wprimey, p_len, &(Wprime->Y)); EG(ret, err); 515*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 516*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 517*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->verify_data.ecsdsa.h_ctx), 518*f0865ec9SKyle Evans Wprimey, p_len); EG(ret, err); 519*f0865ec9SKyle Evans } 520*f0865ec9SKyle Evans ret = local_memset(Wprimex, 0, p_len); EG(ret, err); 521*f0865ec9SKyle Evans ret = local_memset(Wprimey, 0, p_len); EG(ret, err); 522*f0865ec9SKyle Evans 523*f0865ec9SKyle Evans /* Initialize the remaining of verify context. */ 524*f0865ec9SKyle Evans ret = local_memcpy(ctx->verify_data.ecsdsa.r, sig, r_len); EG(ret, err); 525*f0865ec9SKyle Evans ret = nn_copy(&(ctx->verify_data.ecsdsa.s), &s); EG(ret, err); 526*f0865ec9SKyle Evans 527*f0865ec9SKyle Evans ctx->verify_data.ecsdsa.magic = ECSDSA_VERIFY_MAGIC; 528*f0865ec9SKyle Evans 529*f0865ec9SKyle Evans err: 530*f0865ec9SKyle Evans nn_uninit(&rmodq); 531*f0865ec9SKyle Evans nn_uninit(&e); 532*f0865ec9SKyle Evans nn_uninit(&r); 533*f0865ec9SKyle Evans nn_uninit(&s); 534*f0865ec9SKyle Evans prj_pt_uninit(&sG); 535*f0865ec9SKyle Evans prj_pt_uninit(&eY); 536*f0865ec9SKyle Evans 537*f0865ec9SKyle Evans /* Clean what remains on the stack */ 538*f0865ec9SKyle Evans PTR_NULLIFY(Wprime); 539*f0865ec9SKyle Evans PTR_NULLIFY(G); 540*f0865ec9SKyle Evans PTR_NULLIFY(Y); 541*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 542*f0865ec9SKyle Evans PTR_NULLIFY(q); 543*f0865ec9SKyle Evans VAR_ZEROIFY(p_len); 544*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 545*f0865ec9SKyle Evans VAR_ZEROIFY(s_len); 546*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 547*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 548*f0865ec9SKyle Evans 549*f0865ec9SKyle Evans return ret; 550*f0865ec9SKyle Evans } 551*f0865ec9SKyle Evans 552*f0865ec9SKyle Evans /* 553*f0865ec9SKyle Evans * Generic *internal* helper for EC-{,O}SDSA verification update functions. 554*f0865ec9SKyle Evans * The function returns 0 on success, -1 on error. 555*f0865ec9SKyle Evans */ 556*f0865ec9SKyle Evans int __ecsdsa_verify_update(struct ec_verify_context *ctx, 557*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 558*f0865ec9SKyle Evans { 559*f0865ec9SKyle Evans int ret; 560*f0865ec9SKyle Evans 561*f0865ec9SKyle Evans /* 562*f0865ec9SKyle Evans * First, verify context has been initialized and public 563*f0865ec9SKyle Evans * part too. This guarantees the context is an ECSDSA 564*f0865ec9SKyle Evans * verification one and we do not update() or finalize() 565*f0865ec9SKyle Evans * before init(). 566*f0865ec9SKyle Evans */ 567*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 568*f0865ec9SKyle Evans ECSDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecsdsa), ret, err); 569*f0865ec9SKyle Evans 570*f0865ec9SKyle Evans /* 5. Compute r' = H(W'x [|| W'y] || m) */ 571*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 572*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 573*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->verify_data.ecsdsa.h_ctx), chunk, 574*f0865ec9SKyle Evans chunklen); 575*f0865ec9SKyle Evans 576*f0865ec9SKyle Evans err: 577*f0865ec9SKyle Evans return ret; 578*f0865ec9SKyle Evans } 579*f0865ec9SKyle Evans 580*f0865ec9SKyle Evans /* 581*f0865ec9SKyle Evans * Generic *internal* helper for EC-{,O}SDSA verification finalization 582*f0865ec9SKyle Evans * functions. The function returns 0 on success, -1 on error. 583*f0865ec9SKyle Evans */ 584*f0865ec9SKyle Evans int __ecsdsa_verify_finalize(struct ec_verify_context *ctx) 585*f0865ec9SKyle Evans { 586*f0865ec9SKyle Evans u8 r_prime[MAX_DIGEST_SIZE]; 587*f0865ec9SKyle Evans u32 r_len; 588*f0865ec9SKyle Evans int ret, check; 589*f0865ec9SKyle Evans 590*f0865ec9SKyle Evans /* 591*f0865ec9SKyle Evans * First, verify context has been initialized and public 592*f0865ec9SKyle Evans * part too. This guarantees the context is an ECSDSA 593*f0865ec9SKyle Evans * verification one and we do not finalize() before init(). 594*f0865ec9SKyle Evans */ 595*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 596*f0865ec9SKyle Evans ECSDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecsdsa), ret, err); 597*f0865ec9SKyle Evans 598*f0865ec9SKyle Evans r_len = ECSDSA_R_LEN(ctx->h->digest_size); 599*f0865ec9SKyle Evans 600*f0865ec9SKyle Evans /* 5. Compute r' = H(W'x [|| W'y] || m) */ 601*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 602*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 603*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(&(ctx->verify_data.ecsdsa.h_ctx), r_prime); EG(ret, err); 604*f0865ec9SKyle Evans 605*f0865ec9SKyle Evans /* 6. Accept the signature if and only if r and r' are the same */ 606*f0865ec9SKyle Evans ret = are_equal(ctx->verify_data.ecsdsa.r, r_prime, r_len, &check); EG(ret, err); 607*f0865ec9SKyle Evans ret = check ? 0 : -1; 608*f0865ec9SKyle Evans 609*f0865ec9SKyle Evans err: 610*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(r_prime, 0, sizeof(r_prime))); 611*f0865ec9SKyle Evans /* 612*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 613*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 614*f0865ec9SKyle Evans */ 615*f0865ec9SKyle Evans if(ctx != NULL){ 616*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->verify_data.ecsdsa), 0, 617*f0865ec9SKyle Evans sizeof(ecsdsa_verify_data))); 618*f0865ec9SKyle Evans } 619*f0865ec9SKyle Evans 620*f0865ec9SKyle Evans /* Clean what remains on the stack */ 621*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 622*f0865ec9SKyle Evans 623*f0865ec9SKyle Evans return ret; 624*f0865ec9SKyle Evans } 625*f0865ec9SKyle Evans 626*f0865ec9SKyle Evans #else /* (defined(WITH_SIG_ECSDSA) || defined(WITH_SIG_ECOSDSA)) */ 627*f0865ec9SKyle Evans 628*f0865ec9SKyle Evans /* 629*f0865ec9SKyle Evans * Dummy definition to avoid the empty translation unit ISO C warning 630*f0865ec9SKyle Evans */ 631*f0865ec9SKyle Evans typedef int dummy; 632*f0865ec9SKyle Evans #endif /* (defined(WITH_SIG_ECSDSA) || defined(WITH_SIG_ECOSDSA)) */ 633