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