Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/libecc/src/sig/ecsdsa_common.c
2066 views
1
/*
2
* Copyright (C) 2017 - This file is part of libecc project
3
*
4
* Authors:
5
* Ryad BENADJILA <[email protected]>
6
* Arnaud EBALARD <[email protected]>
7
* Jean-Pierre FLORI <[email protected]>
8
*
9
* Contributors:
10
* Nicolas VIVET <[email protected]>
11
* Karim KHALFALLAH <[email protected]>
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
634