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 */
__ecsdsa_init_pub_key(ec_pub_key * out_pub,const ec_priv_key * in_priv,ec_alg_type key_type)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 */
__ecsdsa_siglen(u16 p_bit_len,u16 q_bit_len,u8 hsize,u8 blocksize,u8 * siglen)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 */
__ecsdsa_sign_init(struct ec_sign_context * ctx,ec_alg_type key_type,int optimized)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 */
__ecsdsa_sign_update(struct ec_sign_context * ctx,const u8 * chunk,u32 chunklen)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 */
__ecsdsa_sign_finalize(struct ec_sign_context * ctx,u8 * sig,u8 siglen)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 */
__ecsdsa_verify_init(struct ec_verify_context * ctx,const u8 * sig,u8 siglen,ec_alg_type key_type,int optimized)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 */
__ecsdsa_verify_update(struct ec_verify_context * ctx,const u8 * chunk,u32 chunklen)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 */
__ecsdsa_verify_finalize(struct ec_verify_context * ctx)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