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 #ifdef WITH_SIG_ECKCDSA 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/sig_algs_internal.h> 24*f0865ec9SKyle Evans #include <libecc/sig/ec_key.h> 25*f0865ec9SKyle Evans #ifdef VERBOSE_INNER_VALUES 26*f0865ec9SKyle Evans #define EC_SIG_ALG "ECKCDSA" 27*f0865ec9SKyle Evans #endif 28*f0865ec9SKyle Evans #include <libecc/utils/dbg_sig.h> 29*f0865ec9SKyle Evans 30*f0865ec9SKyle Evans /* 31*f0865ec9SKyle Evans * Initialize public key 'out_pub' from input private key 'in_priv'. The 32*f0865ec9SKyle Evans * function returns 0 on success, -1 on error. 33*f0865ec9SKyle Evans */ 34*f0865ec9SKyle Evans int eckcdsa_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv) 35*f0865ec9SKyle Evans { 36*f0865ec9SKyle Evans prj_pt_src_t G; 37*f0865ec9SKyle Evans int ret, cmp; 38*f0865ec9SKyle Evans nn xinv; 39*f0865ec9SKyle Evans nn_src_t q; 40*f0865ec9SKyle Evans xinv.magic = WORD(0); 41*f0865ec9SKyle Evans 42*f0865ec9SKyle Evans MUST_HAVE((out_pub != NULL), ret, err); 43*f0865ec9SKyle Evans 44*f0865ec9SKyle Evans ret = priv_key_check_initialized_and_type(in_priv, ECKCDSA); EG(ret, err); 45*f0865ec9SKyle Evans 46*f0865ec9SKyle Evans /* For readability in the remaining of the function */ 47*f0865ec9SKyle Evans q = &(in_priv->params->ec_gen_order); 48*f0865ec9SKyle Evans 49*f0865ec9SKyle Evans /* Zero init public key to be generated */ 50*f0865ec9SKyle Evans ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err); 51*f0865ec9SKyle Evans 52*f0865ec9SKyle Evans /* Sanity check on key */ 53*f0865ec9SKyle Evans MUST_HAVE((!nn_cmp(&(in_priv->x), q, &cmp)) && (cmp < 0), ret, err); 54*f0865ec9SKyle Evans 55*f0865ec9SKyle Evans /* Y = (x^-1)G */ 56*f0865ec9SKyle Evans G = &(in_priv->params->ec_gen); 57*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 58*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 59*f0865ec9SKyle Evans */ 60*f0865ec9SKyle Evans ret = nn_modinv_fermat(&xinv, &(in_priv->x), q); EG(ret, err); 61*f0865ec9SKyle Evans 62*f0865ec9SKyle Evans /* Use blinding when computing point scalar multiplication */ 63*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&(out_pub->y), &xinv, G); EG(ret, err); 64*f0865ec9SKyle Evans 65*f0865ec9SKyle Evans out_pub->key_type = ECKCDSA; 66*f0865ec9SKyle Evans out_pub->params = in_priv->params; 67*f0865ec9SKyle Evans out_pub->magic = PUB_KEY_MAGIC; 68*f0865ec9SKyle Evans 69*f0865ec9SKyle Evans err: 70*f0865ec9SKyle Evans nn_uninit(&xinv); 71*f0865ec9SKyle Evans 72*f0865ec9SKyle Evans return ret; 73*f0865ec9SKyle Evans } 74*f0865ec9SKyle Evans 75*f0865ec9SKyle Evans /* 76*f0865ec9SKyle Evans * Helper providing ECKCDSA signature length when exported to a buffer based on 77*f0865ec9SKyle Evans * hash algorithm digest and block size, generator point order bit length, and 78*f0865ec9SKyle Evans * underlying prime field order bit length. The function returns 0 on success, 79*f0865ec9SKyle Evans * -1 on error. On success, signature length is provided via 'siglen' out 80*f0865ec9SKyle Evans * parameter. 81*f0865ec9SKyle Evans */ 82*f0865ec9SKyle Evans int eckcdsa_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize, 83*f0865ec9SKyle Evans u8 *siglen) 84*f0865ec9SKyle Evans { 85*f0865ec9SKyle Evans int ret; 86*f0865ec9SKyle Evans 87*f0865ec9SKyle Evans MUST_HAVE((siglen != NULL), ret, err); 88*f0865ec9SKyle Evans MUST_HAVE((p_bit_len <= CURVES_MAX_P_BIT_LEN) && 89*f0865ec9SKyle Evans (q_bit_len <= CURVES_MAX_Q_BIT_LEN) && 90*f0865ec9SKyle Evans (hsize <= MAX_DIGEST_SIZE) && 91*f0865ec9SKyle Evans (blocksize <= MAX_BLOCK_SIZE), ret, err); 92*f0865ec9SKyle Evans 93*f0865ec9SKyle Evans (*siglen) = (u8)ECKCDSA_SIGLEN(hsize, q_bit_len); 94*f0865ec9SKyle Evans ret = 0; 95*f0865ec9SKyle Evans 96*f0865ec9SKyle Evans err: 97*f0865ec9SKyle Evans return ret; 98*f0865ec9SKyle Evans } 99*f0865ec9SKyle Evans 100*f0865ec9SKyle Evans /* 101*f0865ec9SKyle Evans * ISO 14888-3:2016 has some insane specific case when the digest size 102*f0865ec9SKyle Evans * (gamma) is larger than beta, the bit length of q (i.e. hsize > 103*f0865ec9SKyle Evans * bitlen(q), i.e. gamma > beta). In that case, both the values of h 104*f0865ec9SKyle Evans * (= H(z||m)) and r (= H(FE2OS(W_x))) must be post-processed/mangled 105*f0865ec9SKyle Evans * in the following way: 106*f0865ec9SKyle Evans * 107*f0865ec9SKyle Evans * - h = I2BS(beta', (BS2I(gamma, h))) mod 2^beta' 108*f0865ec9SKyle Evans * - r = I2BS(beta', (BS2I(gamma, r))) mod 2^beta' 109*f0865ec9SKyle Evans * 110*f0865ec9SKyle Evans * where beta' = 8 * ceil(beta / 8) 111*f0865ec9SKyle Evans * 112*f0865ec9SKyle Evans * There are two things to consider before implementing those steps 113*f0865ec9SKyle Evans * using various conversions to/from nn, shifting and masking: 114*f0865ec9SKyle Evans * 115*f0865ec9SKyle Evans * - the expected post-processing work is simply clearing the first 116*f0865ec9SKyle Evans * (gamma - beta') bits at the beginning of h and r to keep only 117*f0865ec9SKyle Evans * last beta ones unmodified. 118*f0865ec9SKyle Evans * - In the library, we do not work on bitstring but byte strings in 119*f0865ec9SKyle Evans * all cases 120*f0865ec9SKyle Evans * - In EC-KCDSA sig/verif, the result (h and then r) are then XORed 121*f0865ec9SKyle Evans * together and then converted to an integer (the buffer being 122*f0865ec9SKyle Evans * considered in big endian order) 123*f0865ec9SKyle Evans * 124*f0865ec9SKyle Evans * For that reason, this function simply takes a buffer 'buf' of 125*f0865ec9SKyle Evans * 'buflen' bytes and shifts it 'shift' bytes to the left, clearing 126*f0865ec9SKyle Evans * the trailing 'shift' bytes at the end of the buffer. The function 127*f0865ec9SKyle Evans * is expected to be used with 'shift' parameter set to 128*f0865ec9SKyle Evans * (gamma - beta') / 8. 129*f0865ec9SKyle Evans * 130*f0865ec9SKyle Evans * This is better presented on an example: 131*f0865ec9SKyle Evans * 132*f0865ec9SKyle Evans * shift = (gamma - beta') / 8 = 4 133*f0865ec9SKyle Evans * before: buf = { 0xff, 0xff, 0xff, 0x12, 0x34, 0x56, 0x78} 134*f0865ec9SKyle Evans * after : buf = { 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00} 135*f0865ec9SKyle Evans */ 136*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int buf_lshift(u8 *buf, u8 buflen, u8 shift) 137*f0865ec9SKyle Evans { 138*f0865ec9SKyle Evans u8 i; 139*f0865ec9SKyle Evans int ret; 140*f0865ec9SKyle Evans 141*f0865ec9SKyle Evans MUST_HAVE((buf != NULL), ret, err); 142*f0865ec9SKyle Evans 143*f0865ec9SKyle Evans if (shift > buflen) { 144*f0865ec9SKyle Evans shift = buflen; 145*f0865ec9SKyle Evans } 146*f0865ec9SKyle Evans 147*f0865ec9SKyle Evans /* Start by shifting all trailing bytes to the left ... */ 148*f0865ec9SKyle Evans for (i = shift; i < buflen; i++) { 149*f0865ec9SKyle Evans buf[i - shift] = buf[i]; 150*f0865ec9SKyle Evans } 151*f0865ec9SKyle Evans 152*f0865ec9SKyle Evans /* Let's now zeroize the end of the buffer ... */ 153*f0865ec9SKyle Evans for (i = 1; i <= shift; i++) { 154*f0865ec9SKyle Evans buf[buflen - i] = 0; 155*f0865ec9SKyle Evans } 156*f0865ec9SKyle Evans 157*f0865ec9SKyle Evans ret = 0; 158*f0865ec9SKyle Evans 159*f0865ec9SKyle Evans err: 160*f0865ec9SKyle Evans return ret; 161*f0865ec9SKyle Evans } 162*f0865ec9SKyle Evans 163*f0865ec9SKyle Evans /* 164*f0865ec9SKyle Evans * Generic *internal* EC-KCDSA signature functions (init, update and finalize). 165*f0865ec9SKyle Evans * Their purpose is to allow passing a specific hash function (along with 166*f0865ec9SKyle Evans * its output size) and the random ephemeral key k, so that compliance 167*f0865ec9SKyle Evans * tests against test vectors can be made without ugly hack in the code 168*f0865ec9SKyle Evans * itself. 169*f0865ec9SKyle Evans * 170*f0865ec9SKyle Evans * Global EC-KCDSA signature process is as follows (I,U,F provides 171*f0865ec9SKyle Evans * information in which function(s) (init(), update() or finalize()) 172*f0865ec9SKyle Evans * a specific step is performed): 173*f0865ec9SKyle Evans * 174*f0865ec9SKyle Evans *| IUF - EC-KCDSA signature 175*f0865ec9SKyle Evans *| 176*f0865ec9SKyle Evans *| IUF 1. Compute h = H(z||m) 177*f0865ec9SKyle Evans *| F 2. If |H| > bitlen(q), set h to beta' rightmost bits of 178*f0865ec9SKyle Evans *| bitstring h (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e. 179*f0865ec9SKyle Evans *| set h to I2BS(beta', BS2I(|H|, h) mod 2^beta') 180*f0865ec9SKyle Evans *| F 3. Get a random value k in ]0,q[ 181*f0865ec9SKyle Evans *| F 4. Compute W = (W_x,W_y) = kG 182*f0865ec9SKyle Evans *| F 5. Compute r = H(FE2OS(W_x)). 183*f0865ec9SKyle Evans *| F 6. If |H| > bitlen(q), set r to beta' rightmost bits of 184*f0865ec9SKyle Evans *| bitstring r (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e. 185*f0865ec9SKyle Evans *| set r to I2BS(beta', BS2I(|H|, r) mod 2^beta') 186*f0865ec9SKyle Evans *| F 7. Compute e = OS2I(r XOR h) mod q 187*f0865ec9SKyle Evans *| F 8. Compute s = x(k - e) mod q 188*f0865ec9SKyle Evans *| F 9. if s == 0, restart at step 3. 189*f0865ec9SKyle Evans *| F 10. return (r,s) 190*f0865ec9SKyle Evans * 191*f0865ec9SKyle Evans */ 192*f0865ec9SKyle Evans 193*f0865ec9SKyle Evans #define ECKCDSA_SIGN_MAGIC ((word_t)(0x45503fcf5114bf1eULL)) 194*f0865ec9SKyle Evans #define ECKCDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \ 195*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && \ 196*f0865ec9SKyle Evans ((A)->magic == ECKCDSA_SIGN_MAGIC), ret, err) 197*f0865ec9SKyle Evans 198*f0865ec9SKyle Evans /* 199*f0865ec9SKyle Evans * ECKCDSA signature initialization function. Returns 0 on success, -1 on 200*f0865ec9SKyle Evans * error. 201*f0865ec9SKyle Evans */ 202*f0865ec9SKyle Evans int _eckcdsa_sign_init(struct ec_sign_context *ctx) 203*f0865ec9SKyle Evans { 204*f0865ec9SKyle Evans u8 tmp_buf[LOCAL_MAX(2 * BYTECEIL(CURVES_MAX_P_BIT_LEN), MAX_BLOCK_SIZE)]; 205*f0865ec9SKyle Evans const ec_pub_key *pub_key; 206*f0865ec9SKyle Evans aff_pt y_aff; 207*f0865ec9SKyle Evans u8 p_len; 208*f0865ec9SKyle Evans u16 z_len; 209*f0865ec9SKyle Evans int ret; 210*f0865ec9SKyle Evans y_aff.magic = WORD(0); 211*f0865ec9SKyle Evans 212*f0865ec9SKyle Evans /* First, verify context has been initialized */ 213*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 214*f0865ec9SKyle Evans 215*f0865ec9SKyle Evans /* Additional sanity checks on input params from context */ 216*f0865ec9SKyle Evans ret = key_pair_check_initialized_and_type(ctx->key_pair, ECKCDSA); EG(ret, err); 217*f0865ec9SKyle Evans MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) && 218*f0865ec9SKyle Evans (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err); 219*f0865ec9SKyle Evans 220*f0865ec9SKyle Evans /* Make things more readable */ 221*f0865ec9SKyle Evans pub_key = &(ctx->key_pair->pub_key); 222*f0865ec9SKyle Evans p_len = (u8)BYTECEIL(pub_key->params->ec_fp.p_bitlen); 223*f0865ec9SKyle Evans z_len = ctx->h->block_size; 224*f0865ec9SKyle Evans 225*f0865ec9SKyle Evans /* 226*f0865ec9SKyle Evans * 1. Compute h = H(z||m) 227*f0865ec9SKyle Evans * 228*f0865ec9SKyle Evans * We first need to compute z, the certificate data that will be 229*f0865ec9SKyle Evans * prepended to the message m prior to hashing. In ISO-14888-3:2016, 230*f0865ec9SKyle Evans * z is basically the concatenation of Yx and Yy (the affine coordinates 231*f0865ec9SKyle Evans * of the public key Y) up to the block size of the hash function. 232*f0865ec9SKyle Evans * If the concatenation of those coordinates is smaller than blocksize, 233*f0865ec9SKyle Evans * 0 are appended. 234*f0865ec9SKyle Evans * 235*f0865ec9SKyle Evans * So, we convert the public key point to its affine representation and 236*f0865ec9SKyle Evans * concatenate the two coordinates in a temporary (zeroized) buffer, of 237*f0865ec9SKyle Evans * which the first z_len (i.e. blocksize) bytes are exported to z. 238*f0865ec9SKyle Evans * 239*f0865ec9SKyle Evans * Message m will be handled during following update() calls. 240*f0865ec9SKyle Evans */ 241*f0865ec9SKyle Evans ret = prj_pt_to_aff(&y_aff, &(pub_key->y)); EG(ret, err); 242*f0865ec9SKyle Evans ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err); 243*f0865ec9SKyle Evans ret = fp_export_to_buf(tmp_buf, p_len, &(y_aff.x)); EG(ret, err); 244*f0865ec9SKyle Evans ret = fp_export_to_buf(tmp_buf + p_len, p_len, &(y_aff.y)); EG(ret, err); 245*f0865ec9SKyle Evans 246*f0865ec9SKyle Evans dbg_pub_key_print("Y", pub_key); 247*f0865ec9SKyle Evans 248*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 249*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 250*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(&(ctx->sign_data.eckcdsa.h_ctx)); EG(ret, err); 251*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->sign_data.eckcdsa.h_ctx), tmp_buf, z_len); EG(ret, err); 252*f0865ec9SKyle Evans ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err); 253*f0865ec9SKyle Evans 254*f0865ec9SKyle Evans /* Initialize data part of the context */ 255*f0865ec9SKyle Evans ctx->sign_data.eckcdsa.magic = ECKCDSA_SIGN_MAGIC; 256*f0865ec9SKyle Evans 257*f0865ec9SKyle Evans err: 258*f0865ec9SKyle Evans aff_pt_uninit(&y_aff); 259*f0865ec9SKyle Evans 260*f0865ec9SKyle Evans VAR_ZEROIFY(p_len); 261*f0865ec9SKyle Evans VAR_ZEROIFY(z_len); 262*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 263*f0865ec9SKyle Evans 264*f0865ec9SKyle Evans return ret; 265*f0865ec9SKyle Evans } 266*f0865ec9SKyle Evans 267*f0865ec9SKyle Evans /* ECKCDSA signature update function. Returns 0 on success, -1 on error. */ 268*f0865ec9SKyle Evans int _eckcdsa_sign_update(struct ec_sign_context *ctx, 269*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 270*f0865ec9SKyle Evans { 271*f0865ec9SKyle Evans int ret; 272*f0865ec9SKyle Evans 273*f0865ec9SKyle Evans /* 274*f0865ec9SKyle Evans * First, verify context has been initialized and private 275*f0865ec9SKyle Evans * part too. This guarantees the context is an EC-KCDSA 276*f0865ec9SKyle Evans * signature one and we do not update() or finalize() 277*f0865ec9SKyle Evans * before init(). 278*f0865ec9SKyle Evans */ 279*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 280*f0865ec9SKyle Evans ECKCDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.eckcdsa), ret, err); 281*f0865ec9SKyle Evans 282*f0865ec9SKyle Evans /* 1. Compute h = H(z||m) */ 283*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 284*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 285*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->sign_data.eckcdsa.h_ctx), chunk, chunklen); 286*f0865ec9SKyle Evans 287*f0865ec9SKyle Evans err: 288*f0865ec9SKyle Evans return ret; 289*f0865ec9SKyle Evans } 290*f0865ec9SKyle Evans 291*f0865ec9SKyle Evans /* 292*f0865ec9SKyle Evans * ECKCDSA signature finalization function. Returns 0 on success, -1 on 293*f0865ec9SKyle Evans * error. 294*f0865ec9SKyle Evans */ 295*f0865ec9SKyle Evans int _eckcdsa_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen) 296*f0865ec9SKyle Evans { 297*f0865ec9SKyle Evans prj_pt_src_t G; 298*f0865ec9SKyle Evans nn_src_t q, x; 299*f0865ec9SKyle Evans prj_pt kG; 300*f0865ec9SKyle Evans unsigned int i; 301*f0865ec9SKyle Evans nn e, tmp, s, k; 302*f0865ec9SKyle Evans u8 hzm[MAX_DIGEST_SIZE]; 303*f0865ec9SKyle Evans u8 r[MAX_DIGEST_SIZE]; 304*f0865ec9SKyle Evans u8 tmp_buf[BYTECEIL(CURVES_MAX_P_BIT_LEN)]; 305*f0865ec9SKyle Evans hash_context r_ctx; 306*f0865ec9SKyle Evans const ec_priv_key *priv_key; 307*f0865ec9SKyle Evans u8 p_len, r_len, s_len, hsize, shift; 308*f0865ec9SKyle Evans bitcnt_t q_bit_len; 309*f0865ec9SKyle Evans int ret, iszero, cmp; 310*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 311*f0865ec9SKyle Evans /* b is the blinding mask */ 312*f0865ec9SKyle Evans nn b, binv; 313*f0865ec9SKyle Evans b.magic = binv.magic = WORD(0); 314*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 315*f0865ec9SKyle Evans 316*f0865ec9SKyle Evans kG.magic = WORD(0); 317*f0865ec9SKyle Evans e.magic = tmp.magic = s.magic = k.magic = WORD(0); 318*f0865ec9SKyle Evans 319*f0865ec9SKyle Evans /* 320*f0865ec9SKyle Evans * First, verify context has been initialized and private 321*f0865ec9SKyle Evans * part too. This guarantees the context is an EC-KCDSA 322*f0865ec9SKyle Evans * signature one and we do not finalize() before init(). 323*f0865ec9SKyle Evans */ 324*f0865ec9SKyle Evans ret = sig_sign_check_initialized(ctx); EG(ret, err); 325*f0865ec9SKyle Evans ECKCDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.eckcdsa), ret, err); 326*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 327*f0865ec9SKyle Evans 328*f0865ec9SKyle Evans /* Zero init points */ 329*f0865ec9SKyle Evans ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err); 330*f0865ec9SKyle Evans 331*f0865ec9SKyle Evans /* Make things more readable */ 332*f0865ec9SKyle Evans priv_key = &(ctx->key_pair->priv_key); 333*f0865ec9SKyle Evans G = &(priv_key->params->ec_gen); 334*f0865ec9SKyle Evans q = &(priv_key->params->ec_gen_order); 335*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 336*f0865ec9SKyle Evans p_len = (u8)BYTECEIL(priv_key->params->ec_fp.p_bitlen); 337*f0865ec9SKyle Evans q_bit_len = priv_key->params->ec_gen_order_bitlen; 338*f0865ec9SKyle Evans r_len = (u8)ECKCDSA_R_LEN(hsize, q_bit_len); 339*f0865ec9SKyle Evans s_len = (u8)ECKCDSA_S_LEN(q_bit_len); 340*f0865ec9SKyle Evans x = &(priv_key->x); 341*f0865ec9SKyle Evans 342*f0865ec9SKyle Evans /* Sanity check */ 343*f0865ec9SKyle Evans ret = nn_cmp(x, q, &cmp); EG(ret, err); 344*f0865ec9SKyle Evans /* This should not happen and means that our 345*f0865ec9SKyle Evans * private key is not compliant! 346*f0865ec9SKyle Evans */ 347*f0865ec9SKyle Evans MUST_HAVE((cmp < 0), ret, err); 348*f0865ec9SKyle Evans 349*f0865ec9SKyle Evans MUST_HAVE((siglen == ECKCDSA_SIGLEN(hsize, q_bit_len)), ret, err); 350*f0865ec9SKyle Evans 351*f0865ec9SKyle Evans dbg_nn_print("p", &(priv_key->params->ec_fp.p)); 352*f0865ec9SKyle Evans dbg_nn_print("q", q); 353*f0865ec9SKyle Evans dbg_priv_key_print("x", priv_key); 354*f0865ec9SKyle Evans dbg_ec_point_print("G", G); 355*f0865ec9SKyle Evans 356*f0865ec9SKyle Evans /* 1. Compute h = H(z||m) */ 357*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 358*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 359*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(&(ctx->sign_data.eckcdsa.h_ctx), hzm); EG(ret, err); 360*f0865ec9SKyle Evans dbg_buf_print("h = H(z||m) pre-mask", hzm, hsize); 361*f0865ec9SKyle Evans 362*f0865ec9SKyle Evans /* 363*f0865ec9SKyle Evans * 2. If |H| > bitlen(q), set h to beta' rightmost bits of 364*f0865ec9SKyle Evans * bitstring h (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e. 365*f0865ec9SKyle Evans * set h to I2BS(beta', BS2I(|H|, h) mod 2^beta') 366*f0865ec9SKyle Evans */ 367*f0865ec9SKyle Evans shift = (u8)((hsize > r_len) ? (hsize - r_len) : 0); 368*f0865ec9SKyle Evans MUST_HAVE((hsize <= sizeof(hzm)), ret, err); 369*f0865ec9SKyle Evans 370*f0865ec9SKyle Evans ret = buf_lshift(hzm, hsize, shift); EG(ret, err); 371*f0865ec9SKyle Evans dbg_buf_print("h = H(z||m) post-mask", hzm, r_len); 372*f0865ec9SKyle Evans 373*f0865ec9SKyle Evans restart: 374*f0865ec9SKyle Evans /* 3. Get a random value k in ]0,q[ */ 375*f0865ec9SKyle Evans #ifdef NO_KNOWN_VECTORS 376*f0865ec9SKyle Evans /* NOTE: when we do not need self tests for known vectors, 377*f0865ec9SKyle Evans * we can be strict about random function handler! 378*f0865ec9SKyle Evans * This allows us to avoid the corruption of such a pointer. 379*f0865ec9SKyle Evans */ 380*f0865ec9SKyle Evans /* Sanity check on the handler before calling it */ 381*f0865ec9SKyle Evans MUST_HAVE((ctx->rand == nn_get_random_mod), ret, err); 382*f0865ec9SKyle Evans #endif 383*f0865ec9SKyle Evans MUST_HAVE((ctx->rand != NULL), ret, err); 384*f0865ec9SKyle Evans ret = ctx->rand(&k, q); EG(ret, err); 385*f0865ec9SKyle Evans dbg_nn_print("k", &k); 386*f0865ec9SKyle Evans 387*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 388*f0865ec9SKyle Evans /* Note: if we use blinding, k and e are multiplied by 389*f0865ec9SKyle Evans * a random value b in ]0,q[ */ 390*f0865ec9SKyle Evans ret = nn_get_random_mod(&b, q); EG(ret, err); 391*f0865ec9SKyle Evans dbg_nn_print("b", &b); 392*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 393*f0865ec9SKyle Evans 394*f0865ec9SKyle Evans /* 4. Compute W = (W_x,W_y) = kG */ 395*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 396*f0865ec9SKyle Evans /* We use blinding for the scalar multiplication */ 397*f0865ec9SKyle Evans ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err); 398*f0865ec9SKyle Evans #else 399*f0865ec9SKyle Evans ret = prj_pt_mul(&kG, &k, G); EG(ret, err); 400*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 401*f0865ec9SKyle Evans ret = prj_pt_unique(&kG, &kG); EG(ret, err); 402*f0865ec9SKyle Evans dbg_nn_print("W_x", &(kG.X.fp_val)); 403*f0865ec9SKyle Evans dbg_nn_print("W_y", &(kG.Y.fp_val)); 404*f0865ec9SKyle Evans 405*f0865ec9SKyle Evans /* 5 Compute r = h(FE2OS(W_x)). */ 406*f0865ec9SKyle Evans ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err); 407*f0865ec9SKyle Evans ret = fp_export_to_buf(tmp_buf, p_len, &(kG.X)); EG(ret, err); 408*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 409*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 410*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(&r_ctx); EG(ret, err); 411*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&r_ctx, tmp_buf, p_len); EG(ret, err); 412*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(&r_ctx, r); EG(ret, err); 413*f0865ec9SKyle Evans ret = local_memset(tmp_buf, 0, p_len); EG(ret, err); 414*f0865ec9SKyle Evans ret = local_memset(&r_ctx, 0, sizeof(hash_context)); EG(ret, err); 415*f0865ec9SKyle Evans 416*f0865ec9SKyle Evans /* 417*f0865ec9SKyle Evans * 6. If |H| > bitlen(q), set r to beta' rightmost bits of 418*f0865ec9SKyle Evans * bitstring r (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e. 419*f0865ec9SKyle Evans * set r to I2BS(beta', BS2I(|H|, r) mod 2^beta') 420*f0865ec9SKyle Evans */ 421*f0865ec9SKyle Evans dbg_buf_print("r pre-mask", r, hsize); 422*f0865ec9SKyle Evans MUST_HAVE((hsize <= sizeof(r)), ret, err); 423*f0865ec9SKyle Evans 424*f0865ec9SKyle Evans ret = buf_lshift(r, hsize, shift); EG(ret, err); 425*f0865ec9SKyle Evans dbg_buf_print("r post-mask", r, r_len); 426*f0865ec9SKyle Evans 427*f0865ec9SKyle Evans /* 7. Compute e = OS2I(r XOR h) mod q */ 428*f0865ec9SKyle Evans for (i = 0; i < r_len; i++) { 429*f0865ec9SKyle Evans hzm[i] ^= r[i]; 430*f0865ec9SKyle Evans } 431*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp, hzm, r_len); EG(ret, err); 432*f0865ec9SKyle Evans ret = local_memset(hzm, 0, r_len); EG(ret, err); 433*f0865ec9SKyle Evans ret = nn_mod(&e, &tmp, q); EG(ret, err); 434*f0865ec9SKyle Evans dbg_nn_print("e", &e); 435*f0865ec9SKyle Evans 436*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 437*f0865ec9SKyle Evans /* In case of blinding, we compute (k*b - e*b) * x * b^-1 */ 438*f0865ec9SKyle Evans ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err); 439*f0865ec9SKyle Evans ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err); 440*f0865ec9SKyle Evans /* NOTE: we use Fermat's little theorem inversion for 441*f0865ec9SKyle Evans * constant time here. This is possible since q is prime. 442*f0865ec9SKyle Evans */ 443*f0865ec9SKyle Evans ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err); 444*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 445*f0865ec9SKyle Evans /* 446*f0865ec9SKyle Evans * 8. Compute s = x(k - e) mod q 447*f0865ec9SKyle Evans * 448*f0865ec9SKyle Evans * This is equivalent to computing s = x(k + (q - e)) mod q. 449*f0865ec9SKyle Evans * This second version avoids checking if k < e before the 450*f0865ec9SKyle Evans * subtraction, because e has already been reduced mod q 451*f0865ec9SKyle Evans */ 452*f0865ec9SKyle Evans ret = nn_mod_neg(&tmp, &e, q); EG(ret, err); 453*f0865ec9SKyle Evans ret = nn_mod_add(&tmp, &k, &tmp, q); EG(ret, err); 454*f0865ec9SKyle Evans ret = nn_mod_mul(&s, x, &tmp, q); EG(ret, err); 455*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 456*f0865ec9SKyle Evans /* Unblind s with b^-1 */ 457*f0865ec9SKyle Evans ret = nn_mod_mul(&s, &s, &binv, q); EG(ret, err); 458*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 459*f0865ec9SKyle Evans 460*f0865ec9SKyle Evans /* 9. if s == 0, restart at step 3. */ 461*f0865ec9SKyle Evans ret = nn_iszero(&s, &iszero); EG(ret, err); 462*f0865ec9SKyle Evans if (iszero) { 463*f0865ec9SKyle Evans goto restart; 464*f0865ec9SKyle Evans } 465*f0865ec9SKyle Evans 466*f0865ec9SKyle Evans dbg_nn_print("s", &s); 467*f0865ec9SKyle Evans 468*f0865ec9SKyle Evans /* 10. return (r,s) */ 469*f0865ec9SKyle Evans ret = local_memcpy(sig, r, r_len); EG(ret, err); 470*f0865ec9SKyle Evans ret = local_memset(r, 0, r_len); EG(ret, err); 471*f0865ec9SKyle Evans ret = nn_export_to_buf(sig + r_len, s_len, &s); 472*f0865ec9SKyle Evans 473*f0865ec9SKyle Evans err: 474*f0865ec9SKyle Evans prj_pt_uninit(&kG); 475*f0865ec9SKyle Evans nn_uninit(&e); 476*f0865ec9SKyle Evans nn_uninit(&tmp); 477*f0865ec9SKyle Evans nn_uninit(&s); 478*f0865ec9SKyle Evans nn_uninit(&k); 479*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING 480*f0865ec9SKyle Evans nn_uninit(&b); 481*f0865ec9SKyle Evans nn_uninit(&binv); 482*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */ 483*f0865ec9SKyle Evans 484*f0865ec9SKyle Evans /* 485*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 486*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 487*f0865ec9SKyle Evans */ 488*f0865ec9SKyle Evans if(ctx != NULL){ 489*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->sign_data.eckcdsa), 0, sizeof(eckcdsa_sign_data))); 490*f0865ec9SKyle Evans } 491*f0865ec9SKyle Evans 492*f0865ec9SKyle Evans PTR_NULLIFY(G); 493*f0865ec9SKyle Evans PTR_NULLIFY(q); 494*f0865ec9SKyle Evans PTR_NULLIFY(x); 495*f0865ec9SKyle Evans VAR_ZEROIFY(i); 496*f0865ec9SKyle Evans PTR_NULLIFY(priv_key); 497*f0865ec9SKyle Evans VAR_ZEROIFY(p_len); 498*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 499*f0865ec9SKyle Evans VAR_ZEROIFY(s_len); 500*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 501*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 502*f0865ec9SKyle Evans 503*f0865ec9SKyle Evans return ret; 504*f0865ec9SKyle Evans } 505*f0865ec9SKyle Evans 506*f0865ec9SKyle Evans /* 507*f0865ec9SKyle Evans * Generic *internal* EC-KCDSA verification functions (init, update and 508*f0865ec9SKyle Evans * finalize). Their purpose is to allow passing a specific hash function 509*f0865ec9SKyle Evans * (along with its output size) and the random ephemeral key k, so that 510*f0865ec9SKyle Evans * compliance tests against test vectors can be made without ugly hack 511*f0865ec9SKyle Evans * in the code itself. 512*f0865ec9SKyle Evans * 513*f0865ec9SKyle Evans * Global EC-CKDSA verification process is as follows (I,U,F provides 514*f0865ec9SKyle Evans * information in which function(s) (init(), update() or finalize()) 515*f0865ec9SKyle Evans * a specific step is performed): 516*f0865ec9SKyle Evans * 517*f0865ec9SKyle Evans *| IUF - EC-KCDSA verification 518*f0865ec9SKyle Evans *| 519*f0865ec9SKyle Evans *| I 1. Check the length of r: 520*f0865ec9SKyle Evans *| - if |H| > bitlen(q), r must be of length 521*f0865ec9SKyle Evans *| beta' = 8 * ceil(bitlen(q) / 8) 522*f0865ec9SKyle Evans *| - if |H| <= bitlen(q), r must be of length hsize 523*f0865ec9SKyle Evans *| I 2. Check that s is in ]0,q[ 524*f0865ec9SKyle Evans *| IUF 3. Compute h = H(z||m) 525*f0865ec9SKyle Evans *| F 4. If |H| > bitlen(q), set h to beta' rightmost bits of 526*f0865ec9SKyle Evans *| bitstring h (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e. 527*f0865ec9SKyle Evans *| set h to I2BS(beta', BS2I(|H|, h) mod 2^beta') 528*f0865ec9SKyle Evans *| F 5. Compute e = OS2I(r XOR h) mod q 529*f0865ec9SKyle Evans *| F 6. Compute W' = sY + eG, where Y is the public key 530*f0865ec9SKyle Evans *| F 7. Compute r' = h(W'x) 531*f0865ec9SKyle Evans *| F 8. If |H| > bitlen(q), set r' to beta' rightmost bits of 532*f0865ec9SKyle Evans *| bitstring r' (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e. 533*f0865ec9SKyle Evans *| set r' to I2BS(beta', BS2I(|H|, r') mod 2^beta') 534*f0865ec9SKyle Evans *| F 9. Check if r == r' 535*f0865ec9SKyle Evans * 536*f0865ec9SKyle Evans */ 537*f0865ec9SKyle Evans 538*f0865ec9SKyle Evans #define ECKCDSA_VERIFY_MAGIC ((word_t)(0xa836a75de66643aaULL)) 539*f0865ec9SKyle Evans #define ECKCDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \ 540*f0865ec9SKyle Evans MUST_HAVE((((void *)(A)) != NULL) && \ 541*f0865ec9SKyle Evans ((A)->magic == ECKCDSA_VERIFY_MAGIC), ret, err) 542*f0865ec9SKyle Evans 543*f0865ec9SKyle Evans /* 544*f0865ec9SKyle Evans * ECKCDSA verification finalization function. Returns 0 on success, -1 on error. 545*f0865ec9SKyle Evans */ 546*f0865ec9SKyle Evans int _eckcdsa_verify_init(struct ec_verify_context *ctx, 547*f0865ec9SKyle Evans const u8 *sig, u8 siglen) 548*f0865ec9SKyle Evans { 549*f0865ec9SKyle Evans u8 tmp_buf[LOCAL_MAX(2 * BYTECEIL(CURVES_MAX_P_BIT_LEN), MAX_BLOCK_SIZE)]; 550*f0865ec9SKyle Evans u8 p_len, r_len, s_len, z_len; 551*f0865ec9SKyle Evans bitcnt_t q_bit_len; 552*f0865ec9SKyle Evans const ec_pub_key *pub_key; 553*f0865ec9SKyle Evans aff_pt y_aff; 554*f0865ec9SKyle Evans nn_src_t q; 555*f0865ec9SKyle Evans u8 hsize; 556*f0865ec9SKyle Evans int ret, iszero, cmp; 557*f0865ec9SKyle Evans nn s; 558*f0865ec9SKyle Evans y_aff.magic = s.magic = WORD(0); 559*f0865ec9SKyle Evans 560*f0865ec9SKyle Evans /* First, verify context has been initialized */ 561*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 562*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 563*f0865ec9SKyle Evans 564*f0865ec9SKyle Evans /* Do some sanity checks on input params */ 565*f0865ec9SKyle Evans ret = pub_key_check_initialized_and_type(ctx->pub_key, ECKCDSA); EG(ret, err); 566*f0865ec9SKyle Evans MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) && 567*f0865ec9SKyle Evans (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err); 568*f0865ec9SKyle Evans MUST_HAVE((sig != NULL), ret, err); 569*f0865ec9SKyle Evans 570*f0865ec9SKyle Evans /* Make things more readable */ 571*f0865ec9SKyle Evans pub_key = ctx->pub_key; 572*f0865ec9SKyle Evans p_len = (u8)BYTECEIL(pub_key->params->ec_fp.p_bitlen); 573*f0865ec9SKyle Evans q_bit_len = pub_key->params->ec_gen_order_bitlen; 574*f0865ec9SKyle Evans q = &(pub_key->params->ec_gen_order); 575*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 576*f0865ec9SKyle Evans r_len = (u8)ECKCDSA_R_LEN(hsize, q_bit_len); 577*f0865ec9SKyle Evans s_len = (u8)ECKCDSA_S_LEN(q_bit_len); 578*f0865ec9SKyle Evans z_len = ctx->h->block_size; 579*f0865ec9SKyle Evans 580*f0865ec9SKyle Evans /* 581*f0865ec9SKyle Evans * 1. Check the length of r: 582*f0865ec9SKyle Evans * - if |H| > bitlen(q), r must be of length 583*f0865ec9SKyle Evans * beta' = 8 * ceil(bitlen(q) / 8) 584*f0865ec9SKyle Evans * - if |H| <= bitlen(q), r must be of length hsize 585*f0865ec9SKyle Evans * 586*f0865ec9SKyle Evans * As we expect the signature as the concatenation of r and s, the check 587*f0865ec9SKyle Evans * is done by verifying the length of the signature is the expected one. 588*f0865ec9SKyle Evans */ 589*f0865ec9SKyle Evans MUST_HAVE((siglen == ECKCDSA_SIGLEN(hsize, q_bit_len)), ret, err); 590*f0865ec9SKyle Evans 591*f0865ec9SKyle Evans /* 2. Check that s is in ]0,q[ */ 592*f0865ec9SKyle Evans ret = nn_init_from_buf(&s, sig + r_len, s_len); EG(ret, err); 593*f0865ec9SKyle Evans ret = nn_iszero(&s, &iszero); EG(ret, err); 594*f0865ec9SKyle Evans ret = nn_cmp(&s, q, &cmp); EG(ret, err); 595*f0865ec9SKyle Evans MUST_HAVE((!iszero) && (cmp < 0), ret, err); 596*f0865ec9SKyle Evans dbg_nn_print("s", &s); 597*f0865ec9SKyle Evans 598*f0865ec9SKyle Evans /* 599*f0865ec9SKyle Evans * 3. Compute h = H(z||m) 600*f0865ec9SKyle Evans * 601*f0865ec9SKyle Evans * We first need to compute z, the certificate data that will be 602*f0865ec9SKyle Evans * prepended to the message m prior to hashing. In ISO-14888-3:2016, 603*f0865ec9SKyle Evans * z is basically the concatenation of Yx and Yy (the affine coordinates 604*f0865ec9SKyle Evans * of the public key Y) up to the block size of the hash function. 605*f0865ec9SKyle Evans * If the concatenation of those coordinates is smaller than blocksize, 606*f0865ec9SKyle Evans * 0 are appended. 607*f0865ec9SKyle Evans * 608*f0865ec9SKyle Evans * So, we convert the public key point to its affine representation and 609*f0865ec9SKyle Evans * concatenate the two coordinates in a temporary (zeroized) buffer, of 610*f0865ec9SKyle Evans * which the first z_len (i.e. blocksize) bytes are exported to z. 611*f0865ec9SKyle Evans * 612*f0865ec9SKyle Evans * Message m will be handled during following update() calls. 613*f0865ec9SKyle Evans */ 614*f0865ec9SKyle Evans ret = prj_pt_to_aff(&y_aff, &(pub_key->y)); EG(ret, err); 615*f0865ec9SKyle Evans ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err); 616*f0865ec9SKyle Evans ret = fp_export_to_buf(tmp_buf, p_len, &(y_aff.x)); EG(ret, err); 617*f0865ec9SKyle Evans ret = fp_export_to_buf(tmp_buf + p_len, p_len, &(y_aff.y)); EG(ret, err); 618*f0865ec9SKyle Evans 619*f0865ec9SKyle Evans dbg_pub_key_print("Y", pub_key); 620*f0865ec9SKyle Evans 621*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 622*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 623*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(&(ctx->verify_data.eckcdsa.h_ctx)); EG(ret, err); 624*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->verify_data.eckcdsa.h_ctx), tmp_buf, 625*f0865ec9SKyle Evans z_len); EG(ret, err); 626*f0865ec9SKyle Evans ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err); 627*f0865ec9SKyle Evans 628*f0865ec9SKyle Evans /* 629*f0865ec9SKyle Evans * Initialize the verify context by storing r and s as imported 630*f0865ec9SKyle Evans * from the signature 631*f0865ec9SKyle Evans */ 632*f0865ec9SKyle Evans ret = local_memcpy(ctx->verify_data.eckcdsa.r, sig, r_len); EG(ret, err); 633*f0865ec9SKyle Evans ret = nn_copy(&(ctx->verify_data.eckcdsa.s), &s); EG(ret, err); 634*f0865ec9SKyle Evans 635*f0865ec9SKyle Evans ctx->verify_data.eckcdsa.magic = ECKCDSA_VERIFY_MAGIC; 636*f0865ec9SKyle Evans 637*f0865ec9SKyle Evans err: 638*f0865ec9SKyle Evans aff_pt_uninit(&y_aff); 639*f0865ec9SKyle Evans nn_uninit(&s); 640*f0865ec9SKyle Evans 641*f0865ec9SKyle Evans if (ret && (ctx != NULL)) { 642*f0865ec9SKyle Evans /* 643*f0865ec9SKyle Evans * Signature is invalid. Clear data part of the context. 644*f0865ec9SKyle Evans * This will clear magic and avoid further reuse of the 645*f0865ec9SKyle Evans * whole context. 646*f0865ec9SKyle Evans */ 647*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->verify_data.eckcdsa), 0, 648*f0865ec9SKyle Evans sizeof(eckcdsa_verify_data))); 649*f0865ec9SKyle Evans } 650*f0865ec9SKyle Evans 651*f0865ec9SKyle Evans /* Let's also clear what remains on the stack */ 652*f0865ec9SKyle Evans PTR_NULLIFY(q); 653*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 654*f0865ec9SKyle Evans VAR_ZEROIFY(p_len); 655*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 656*f0865ec9SKyle Evans VAR_ZEROIFY(s_len); 657*f0865ec9SKyle Evans VAR_ZEROIFY(z_len); 658*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 659*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 660*f0865ec9SKyle Evans 661*f0865ec9SKyle Evans return ret; 662*f0865ec9SKyle Evans } 663*f0865ec9SKyle Evans 664*f0865ec9SKyle Evans /* ECKCDSA verification update function. Returns 0 on success, -1 on error. */ 665*f0865ec9SKyle Evans int _eckcdsa_verify_update(struct ec_verify_context *ctx, 666*f0865ec9SKyle Evans const u8 *chunk, u32 chunklen) 667*f0865ec9SKyle Evans { 668*f0865ec9SKyle Evans int ret; 669*f0865ec9SKyle Evans 670*f0865ec9SKyle Evans /* 671*f0865ec9SKyle Evans * First, verify context has been initialized and public 672*f0865ec9SKyle Evans * part too. This guarantees the context is an EC-KCDSA 673*f0865ec9SKyle Evans * verification one and we do not update() or finalize() 674*f0865ec9SKyle Evans * before init(). 675*f0865ec9SKyle Evans */ 676*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 677*f0865ec9SKyle Evans ECKCDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.eckcdsa), ret, err); 678*f0865ec9SKyle Evans 679*f0865ec9SKyle Evans /* 3. Compute h = H(z||m) */ 680*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 681*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 682*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&(ctx->verify_data.eckcdsa.h_ctx), 683*f0865ec9SKyle Evans chunk, chunklen); 684*f0865ec9SKyle Evans 685*f0865ec9SKyle Evans err: 686*f0865ec9SKyle Evans return ret; 687*f0865ec9SKyle Evans } 688*f0865ec9SKyle Evans 689*f0865ec9SKyle Evans /* 690*f0865ec9SKyle Evans * ECKCDSA verification finalization function. Returns 0 on success, -1 on error. 691*f0865ec9SKyle Evans */ 692*f0865ec9SKyle Evans int _eckcdsa_verify_finalize(struct ec_verify_context *ctx) 693*f0865ec9SKyle Evans { 694*f0865ec9SKyle Evans u8 tmp_buf[BYTECEIL(CURVES_MAX_P_BIT_LEN)]; 695*f0865ec9SKyle Evans bitcnt_t q_bit_len, p_bit_len; 696*f0865ec9SKyle Evans u8 p_len, r_len; 697*f0865ec9SKyle Evans prj_pt sY, eG; 698*f0865ec9SKyle Evans prj_pt_t Wprime; 699*f0865ec9SKyle Evans prj_pt_src_t G, Y; 700*f0865ec9SKyle Evans u8 r_prime[MAX_DIGEST_SIZE]; 701*f0865ec9SKyle Evans const ec_pub_key *pub_key; 702*f0865ec9SKyle Evans hash_context r_prime_ctx; 703*f0865ec9SKyle Evans u8 hzm[MAX_DIGEST_SIZE]; 704*f0865ec9SKyle Evans unsigned int i; 705*f0865ec9SKyle Evans nn_src_t q; 706*f0865ec9SKyle Evans nn e, tmp; 707*f0865ec9SKyle Evans u8 hsize, shift; 708*f0865ec9SKyle Evans int ret, check; 709*f0865ec9SKyle Evans u8 *r; 710*f0865ec9SKyle Evans nn *s; 711*f0865ec9SKyle Evans 712*f0865ec9SKyle Evans sY.magic = eG.magic = WORD(0); 713*f0865ec9SKyle Evans e.magic = tmp.magic = WORD(0); 714*f0865ec9SKyle Evans 715*f0865ec9SKyle Evans /* NOTE: we reuse eG for Wprime to optimize local variables */ 716*f0865ec9SKyle Evans Wprime = &eG; 717*f0865ec9SKyle Evans 718*f0865ec9SKyle Evans /* 719*f0865ec9SKyle Evans * First, verify context has been initialized and public 720*f0865ec9SKyle Evans * part too. This guarantees the context is an EC-KCDSA 721*f0865ec9SKyle Evans * verification one and we do not finalize() before init(). 722*f0865ec9SKyle Evans */ 723*f0865ec9SKyle Evans ret = sig_verify_check_initialized(ctx); EG(ret, err); 724*f0865ec9SKyle Evans ECKCDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.eckcdsa), ret, err); 725*f0865ec9SKyle Evans 726*f0865ec9SKyle Evans /* Zero init points */ 727*f0865ec9SKyle Evans ret = local_memset(&sY, 0, sizeof(prj_pt)); EG(ret, err); 728*f0865ec9SKyle Evans ret = local_memset(&eG, 0, sizeof(prj_pt)); EG(ret, err); 729*f0865ec9SKyle Evans 730*f0865ec9SKyle Evans /* Make things more readable */ 731*f0865ec9SKyle Evans pub_key = ctx->pub_key; 732*f0865ec9SKyle Evans G = &(pub_key->params->ec_gen); 733*f0865ec9SKyle Evans Y = &(pub_key->y); 734*f0865ec9SKyle Evans q = &(pub_key->params->ec_gen_order); 735*f0865ec9SKyle Evans p_bit_len = pub_key->params->ec_fp.p_bitlen; 736*f0865ec9SKyle Evans q_bit_len = pub_key->params->ec_gen_order_bitlen; 737*f0865ec9SKyle Evans p_len = (u8)BYTECEIL(p_bit_len); 738*f0865ec9SKyle Evans hsize = ctx->h->digest_size; 739*f0865ec9SKyle Evans r_len = (u8)ECKCDSA_R_LEN(hsize, q_bit_len); 740*f0865ec9SKyle Evans r = ctx->verify_data.eckcdsa.r; 741*f0865ec9SKyle Evans s = &(ctx->verify_data.eckcdsa.s); 742*f0865ec9SKyle Evans 743*f0865ec9SKyle Evans /* 3. Compute h = H(z||m) */ 744*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 745*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 746*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(&(ctx->verify_data.eckcdsa.h_ctx), hzm); EG(ret, err); 747*f0865ec9SKyle Evans dbg_buf_print("h = H(z||m) pre-mask", hzm, hsize); 748*f0865ec9SKyle Evans 749*f0865ec9SKyle Evans /* 750*f0865ec9SKyle Evans * 4. If |H| > bitlen(q), set h to beta' rightmost bits of 751*f0865ec9SKyle Evans * bitstring h (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e. 752*f0865ec9SKyle Evans * set h to I2BS(beta', BS2I(|H|, h) mod 2^beta') 753*f0865ec9SKyle Evans */ 754*f0865ec9SKyle Evans shift = (u8)((hsize > r_len) ? (hsize - r_len) : 0); 755*f0865ec9SKyle Evans MUST_HAVE(hsize <= sizeof(hzm), ret, err); 756*f0865ec9SKyle Evans ret = buf_lshift(hzm, hsize, shift); EG(ret, err); 757*f0865ec9SKyle Evans dbg_buf_print("h = H(z||m) post-mask", hzm, r_len); 758*f0865ec9SKyle Evans 759*f0865ec9SKyle Evans /* 5. Compute e = OS2I(r XOR h) mod q */ 760*f0865ec9SKyle Evans for (i = 0; i < r_len; i++) { 761*f0865ec9SKyle Evans hzm[i] ^= r[i]; 762*f0865ec9SKyle Evans } 763*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp, hzm, r_len); EG(ret, err); 764*f0865ec9SKyle Evans ret = local_memset(hzm, 0, hsize); EG(ret, err); 765*f0865ec9SKyle Evans ret = nn_mod(&e, &tmp, q); EG(ret, err); 766*f0865ec9SKyle Evans 767*f0865ec9SKyle Evans dbg_nn_print("e", &e); 768*f0865ec9SKyle Evans 769*f0865ec9SKyle Evans /* 6. Compute W' = sY + eG, where Y is the public key */ 770*f0865ec9SKyle Evans ret = prj_pt_mul(&sY, s, Y); EG(ret, err); 771*f0865ec9SKyle Evans ret = prj_pt_mul(&eG, &e, G); EG(ret, err); 772*f0865ec9SKyle Evans ret = prj_pt_add(Wprime, &sY, &eG); EG(ret, err); 773*f0865ec9SKyle Evans ret = prj_pt_unique(Wprime, Wprime); EG(ret, err); 774*f0865ec9SKyle Evans dbg_nn_print("W'_x", &(Wprime->X.fp_val)); 775*f0865ec9SKyle Evans dbg_nn_print("W'_y", &(Wprime->Y.fp_val)); 776*f0865ec9SKyle Evans 777*f0865ec9SKyle Evans /* 7. Compute r' = h(W'x) */ 778*f0865ec9SKyle Evans ret = local_memset(tmp_buf, 0, sizeof(tmp_buf)); EG(ret, err); 779*f0865ec9SKyle Evans ret = fp_export_to_buf(tmp_buf, p_len, &(Wprime->X)); EG(ret, err); 780*f0865ec9SKyle Evans /* Since we call a callback, sanity check our mapping */ 781*f0865ec9SKyle Evans ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err); 782*f0865ec9SKyle Evans ret = ctx->h->hfunc_init(&r_prime_ctx); EG(ret, err); 783*f0865ec9SKyle Evans ret = ctx->h->hfunc_update(&r_prime_ctx, tmp_buf, p_len); EG(ret, err); 784*f0865ec9SKyle Evans ret = ctx->h->hfunc_finalize(&r_prime_ctx, r_prime); EG(ret, err); 785*f0865ec9SKyle Evans ret = local_memset(tmp_buf, 0, p_len); EG(ret, err); 786*f0865ec9SKyle Evans ret = local_memset(&r_prime_ctx, 0, sizeof(hash_context)); EG(ret, err); 787*f0865ec9SKyle Evans 788*f0865ec9SKyle Evans /* 789*f0865ec9SKyle Evans * 8. If |H| > bitlen(q), set r' to beta' rightmost bits of 790*f0865ec9SKyle Evans * bitstring r' (w/ beta' = 8 * ceil(bitlen(q) / 8)), i.e. 791*f0865ec9SKyle Evans * set r' to I2BS(beta', BS2I(|H|, r') mod 2^beta') 792*f0865ec9SKyle Evans */ 793*f0865ec9SKyle Evans dbg_buf_print("r' pre-mask", r_prime, hsize); 794*f0865ec9SKyle Evans ret = buf_lshift(r_prime, hsize, shift); EG(ret, err); 795*f0865ec9SKyle Evans dbg_buf_print("r' post-mask", r_prime, r_len); 796*f0865ec9SKyle Evans dbg_buf_print("r", r, r_len); 797*f0865ec9SKyle Evans 798*f0865ec9SKyle Evans /* 9. Check if r == r' */ 799*f0865ec9SKyle Evans ret = are_equal(r, r_prime, r_len, &check); EG(ret, err); 800*f0865ec9SKyle Evans ret = check ? 0 : -1; 801*f0865ec9SKyle Evans 802*f0865ec9SKyle Evans err: 803*f0865ec9SKyle Evans prj_pt_uninit(&sY); 804*f0865ec9SKyle Evans prj_pt_uninit(&eG); 805*f0865ec9SKyle Evans nn_uninit(&e); 806*f0865ec9SKyle Evans nn_uninit(&tmp); 807*f0865ec9SKyle Evans 808*f0865ec9SKyle Evans /* 809*f0865ec9SKyle Evans * We can now clear data part of the context. This will clear 810*f0865ec9SKyle Evans * magic and avoid further reuse of the whole context. 811*f0865ec9SKyle Evans */ 812*f0865ec9SKyle Evans if(ctx != NULL){ 813*f0865ec9SKyle Evans IGNORE_RET_VAL(local_memset(&(ctx->verify_data.eckcdsa), 0, 814*f0865ec9SKyle Evans sizeof(eckcdsa_verify_data))); 815*f0865ec9SKyle Evans } 816*f0865ec9SKyle Evans 817*f0865ec9SKyle Evans /* Let's also clear what remains on the stack */ 818*f0865ec9SKyle Evans VAR_ZEROIFY(i); 819*f0865ec9SKyle Evans PTR_NULLIFY(Wprime); 820*f0865ec9SKyle Evans PTR_NULLIFY(G); 821*f0865ec9SKyle Evans PTR_NULLIFY(Y); 822*f0865ec9SKyle Evans PTR_NULLIFY(q); 823*f0865ec9SKyle Evans VAR_ZEROIFY(p_len); 824*f0865ec9SKyle Evans VAR_ZEROIFY(r_len); 825*f0865ec9SKyle Evans VAR_ZEROIFY(q_bit_len); 826*f0865ec9SKyle Evans VAR_ZEROIFY(p_bit_len); 827*f0865ec9SKyle Evans PTR_NULLIFY(pub_key); 828*f0865ec9SKyle Evans VAR_ZEROIFY(hsize); 829*f0865ec9SKyle Evans PTR_NULLIFY(r); 830*f0865ec9SKyle Evans PTR_NULLIFY(s); 831*f0865ec9SKyle Evans 832*f0865ec9SKyle Evans return ret; 833*f0865ec9SKyle Evans } 834*f0865ec9SKyle Evans 835*f0865ec9SKyle Evans #else /* WITH_SIG_ECKCDSA */ 836*f0865ec9SKyle Evans 837*f0865ec9SKyle Evans /* 838*f0865ec9SKyle Evans * Dummy definition to avoid the empty translation unit ISO C warning 839*f0865ec9SKyle Evans */ 840*f0865ec9SKyle Evans typedef int dummy; 841*f0865ec9SKyle Evans #endif /* WITH_SIG_ECKCDSA */ 842