Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/libecc/src/sig/ecgdsa.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
#ifdef WITH_SIG_ECGDSA
18
19
#include <libecc/nn/nn.h>
20
#include <libecc/nn/nn_rand.h>
21
#include <libecc/nn/nn_mul_public.h>
22
#include <libecc/nn/nn_logical.h>
23
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 "ECGDSA"
28
#endif
29
#include <libecc/utils/dbg_sig.h>
30
31
int ecgdsa_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv)
32
{
33
prj_pt_src_t G;
34
nn_src_t q;
35
nn xinv;
36
int ret, cmp;
37
xinv.magic = WORD(0);
38
39
MUST_HAVE((out_pub != NULL), ret, err);
40
41
/* Zero init public key to be generated */
42
ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err);
43
44
ret = priv_key_check_initialized_and_type(in_priv, ECGDSA); EG(ret, err);
45
q = &(in_priv->params->ec_gen_order);
46
47
/* Sanity check on key */
48
MUST_HAVE((!nn_cmp(&(in_priv->x), q, &cmp)) && (cmp < 0), ret, err);
49
50
/* Y = (x^-1)G */
51
G = &(in_priv->params->ec_gen);
52
/* NOTE: we use Fermat's little theorem inversion for
53
* constant time here. This is possible since q is prime.
54
*/
55
ret = nn_modinv_fermat(&xinv, &(in_priv->x), &(in_priv->params->ec_gen_order)); EG(ret, err);
56
/* Use blinding with scalar_b when computing point scalar multiplication */
57
ret = prj_pt_mul_blind(&(out_pub->y), &xinv, G); EG(ret, err);
58
59
out_pub->key_type = ECGDSA;
60
out_pub->params = in_priv->params;
61
out_pub->magic = PUB_KEY_MAGIC;
62
63
err:
64
nn_uninit(&xinv);
65
66
return ret;
67
}
68
69
int ecgdsa_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize, u8 *siglen)
70
{
71
int ret;
72
73
MUST_HAVE((siglen != NULL), ret, err);
74
MUST_HAVE((p_bit_len <= CURVES_MAX_P_BIT_LEN) &&
75
(q_bit_len <= CURVES_MAX_Q_BIT_LEN) &&
76
(hsize <= MAX_DIGEST_SIZE) && (blocksize <= MAX_BLOCK_SIZE), ret, err);
77
78
(*siglen) = (u8)ECGDSA_SIGLEN(q_bit_len);
79
80
ret = 0;
81
82
err:
83
return ret;
84
}
85
86
/*
87
* Generic *internal* EC-GDSA signature functions (init, update and finalize).
88
* Their purpose is to allow passing a specific hash function (along with
89
* its output size) and the random ephemeral key k, so that compliance
90
* tests against test vectors can be made without ugly hack in the code
91
* itself.
92
*
93
* Global EC-GDSA signature process is as follows (I,U,F provides
94
* information in which function(s) (init(), update() or finalize())
95
* a specific step is performed):
96
*
97
*| IUF - EC-GDSA signature
98
*|
99
*| UF 1. Compute h = H(m). If |h| > bitlen(q), set h to bitlen(q)
100
*| leftmost (most significant) bits of h
101
*| F 2. Compute e = - OS2I(h) mod q
102
*| F 3. Get a random value k in ]0,q[
103
*| F 4. Compute W = (W_x,W_y) = kG
104
*| F 5. Compute r = W_x mod q
105
*| F 6. If r is 0, restart the process at step 4.
106
*| F 7. Compute s = x(kr + e) mod q
107
*| F 8. If s is 0, restart the process at step 4.
108
*| F 9. Return (r,s)
109
*
110
* Implementation notes:
111
*
112
* a) Usually (this is for instance the case in ISO 14888-3 and X9.62), the
113
* process starts with steps 4 to 7 and is followed by steps 1 to 3.
114
* The order is modified here w/o impact on the result and the security
115
* in order to allow the algorithm to be compatible with an
116
* init/update/finish API. More explicitly, the generation of k, which
117
* may later result in a (unlikely) restart of the whole process is
118
* postponed until the hash of the message has been computed.
119
* b) sig is built as the concatenation of r and s. Both r and s are
120
* encoded on ceil(bitlen(q)/8) bytes.
121
* c) in EC-GDSA, the public part of the key is not needed per se during the
122
* signature but - as it is needed in other signature algs implemented
123
* in the library - the whole key pair is passed instead of just the
124
* private key.
125
*/
126
127
#define ECGDSA_SIGN_MAGIC ((word_t)(0xe2f60ea3353ecc9eULL))
128
#define ECGDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \
129
MUST_HAVE((((void *)(A)) != NULL) && \
130
((A)->magic == ECGDSA_SIGN_MAGIC), ret, err)
131
132
int _ecgdsa_sign_init(struct ec_sign_context *ctx)
133
{
134
int ret;
135
136
/* First, verify context has been initialized */
137
ret = sig_sign_check_initialized(ctx); EG(ret, err);
138
139
/* Additional sanity checks on input params from context */
140
ret = key_pair_check_initialized_and_type(ctx->key_pair, ECGDSA); EG(ret, err);
141
MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) &&
142
(ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);
143
144
/*
145
* Initialize hash context stored in our private part of context
146
* and record data init has been done
147
*/
148
/* Since we call a callback, sanity check our mapping */
149
ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
150
ret = ctx->h->hfunc_init(&(ctx->sign_data.ecgdsa.h_ctx)); EG(ret, err);
151
152
ctx->sign_data.ecgdsa.magic = ECGDSA_SIGN_MAGIC;
153
154
err:
155
return ret;
156
}
157
158
int _ecgdsa_sign_update(struct ec_sign_context *ctx,
159
const u8 *chunk, u32 chunklen)
160
{
161
int ret;
162
163
/*
164
* First, verify context has been initialized and private
165
* part too. This guarantees the context is an EC-GDSA
166
* signature one and we do not update() or finalize()
167
* before init().
168
*/
169
ret = sig_sign_check_initialized(ctx); EG(ret, err);
170
ECGDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecgdsa), ret, err);
171
172
/* 1. Compute h = H(m) */
173
/* Since we call a callback, sanity check our mapping */
174
ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
175
ret = ctx->h->hfunc_update(&(ctx->sign_data.ecgdsa.h_ctx), chunk, chunklen);
176
177
err:
178
return ret;
179
}
180
181
int _ecgdsa_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen)
182
{
183
nn_src_t q, x;
184
u8 e_buf[MAX_DIGEST_SIZE];
185
const ec_priv_key *priv_key;
186
prj_pt_src_t G;
187
u8 hsize, r_len, s_len;
188
bitcnt_t q_bit_len, p_bit_len, rshift;
189
prj_pt kG;
190
int ret, cmp, iszero;
191
nn tmp, s, e, kr, k, r;
192
#ifdef USE_SIG_BLINDING
193
/* b is the blinding mask */
194
nn b, binv;
195
b.magic = binv.magic = WORD(0);
196
#endif
197
198
tmp.magic = s.magic = e.magic = WORD(0);
199
kr.magic = k.magic = r.magic = WORD(0);
200
kG.magic = WORD(0);
201
202
/*
203
* First, verify context has been initialized and private
204
* part too. This guarantees the context is an EC-GDSA
205
* signature one and we do not finalize() before init().
206
*/
207
ret = sig_sign_check_initialized(ctx); EG(ret, err);
208
ECGDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.ecgdsa), ret, err);
209
MUST_HAVE((sig != NULL), ret, err);
210
211
/* Zero init points */
212
ret = local_memset(&kG, 0, sizeof(prj_pt)); EG(ret, err);
213
214
/* Make things more readable */
215
priv_key = &(ctx->key_pair->priv_key);
216
G = &(priv_key->params->ec_gen);
217
q = &(priv_key->params->ec_gen_order);
218
x = &(priv_key->x);
219
q_bit_len = priv_key->params->ec_gen_order_bitlen;
220
p_bit_len = priv_key->params->ec_fp.p_bitlen;
221
MUST_HAVE(((u32)BYTECEIL(p_bit_len) <= NN_MAX_BYTE_LEN), ret, err);
222
r_len = (u8)ECGDSA_R_LEN(q_bit_len);
223
s_len = (u8)ECGDSA_S_LEN(q_bit_len);
224
hsize = ctx->h->digest_size;
225
226
/* Sanity check */
227
ret = nn_cmp(x, q, &cmp); EG(ret, err);
228
/* This should not happen and means that our
229
* private key is not compliant!
230
*/
231
MUST_HAVE((cmp < 0), ret, err);
232
233
MUST_HAVE((siglen == ECGDSA_SIGLEN(q_bit_len)), ret, err);
234
235
dbg_nn_print("p", &(priv_key->params->ec_fp.p));
236
dbg_nn_print("q", q);
237
dbg_priv_key_print("x", priv_key);
238
dbg_ec_point_print("G", G);
239
dbg_pub_key_print("Y", &(ctx->key_pair->pub_key));
240
241
/* 1. Compute h = H(m) */
242
ret = local_memset(e_buf, 0, hsize); EG(ret, err);
243
/* Since we call a callback, sanity check our mapping */
244
ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
245
ret = ctx->h->hfunc_finalize(&(ctx->sign_data.ecgdsa.h_ctx), e_buf); EG(ret, err);
246
dbg_buf_print("H(m)", e_buf, hsize);
247
248
/*
249
* If |h| > bitlen(q), set h to bitlen(q)
250
* leftmost bits of h.
251
*
252
*/
253
rshift = 0;
254
if ((hsize * 8) > q_bit_len) {
255
rshift = (bitcnt_t)((hsize * 8) - q_bit_len);
256
}
257
ret = nn_init_from_buf(&tmp, e_buf, hsize); EG(ret, err);
258
ret = local_memset(e_buf, 0, hsize); EG(ret, err);
259
if (rshift) {
260
ret = nn_rshift_fixedlen(&tmp, &tmp, rshift); EG(ret, err);
261
}
262
dbg_nn_print("H(m) truncated as nn", &tmp);
263
264
/*
265
* 2. Convert h to an integer and then compute e = -h mod q,
266
* i.e. compute e = - OS2I(h) mod q
267
*
268
* Because we only support positive integers, we compute
269
* e = q - (h mod q) (except when h is 0).
270
*/
271
ret = nn_mod(&tmp, &tmp, q); EG(ret, err);
272
ret = nn_mod_neg(&e, &tmp, q); EG(ret, err);
273
274
restart:
275
/* 3. Get a random value k in ]0,q[ */
276
#ifdef NO_KNOWN_VECTORS
277
/* NOTE: when we do not need self tests for known vectors,
278
* we can be strict about random function handler!
279
* This allows us to avoid the corruption of such a pointer.
280
*/
281
/* Sanity check on the handler before calling it */
282
MUST_HAVE(ctx->rand == nn_get_random_mod, ret, err);
283
#endif
284
MUST_HAVE(ctx->rand != NULL, ret, err);
285
286
ret = ctx->rand(&k, q); EG(ret, err);
287
288
#ifdef USE_SIG_BLINDING
289
/* Note: if we use blinding, e and e are multiplied by
290
* a random value b in ]0,q[ */
291
ret = nn_get_random_mod(&b, q); EG(ret, err);
292
dbg_nn_print("b", &b);
293
#endif /* USE_SIG_BLINDING */
294
295
/* 4. Compute W = kG = (Wx, Wy) */
296
#ifdef USE_SIG_BLINDING
297
/* We use blinding for the scalar multiplication */
298
ret = prj_pt_mul_blind(&kG, &k, G); EG(ret, err);
299
#else
300
ret = prj_pt_mul(&kG, &k, G); EG(ret, err);
301
#endif /* USE_SIG_BLINDING */
302
ret = prj_pt_unique(&kG, &kG); EG(ret, err);
303
304
dbg_nn_print("W_x", &(kG.X.fp_val));
305
dbg_nn_print("W_y", &(kG.Y.fp_val));
306
307
/* 5. Compute r = Wx mod q */
308
ret = nn_mod(&r, &(kG.X.fp_val), q); EG(ret, err);
309
dbg_nn_print("r", &r);
310
311
/* 6. If r is 0, restart the process at step 4. */
312
ret = nn_iszero(&r, &iszero); EG(ret, err);
313
if (iszero) {
314
goto restart;
315
}
316
317
/* Export r */
318
ret = nn_export_to_buf(sig, r_len, &r); EG(ret, err);
319
320
#ifdef USE_SIG_BLINDING
321
/* Blind e and r with b */
322
ret = nn_mod_mul(&e, &e, &b, q); EG(ret, err);
323
ret = nn_mod_mul(&r, &r, &b, q); EG(ret, err);
324
#endif /* USE_SIG_BLINDING */
325
/* 7. Compute s = x(kr + e) mod q */
326
ret = nn_mod_mul(&kr, &k, &r, q); EG(ret, err);
327
ret = nn_mod_add(&tmp, &kr, &e, q); EG(ret, err);
328
ret = nn_mod_mul(&s, x, &tmp, q); EG(ret, err);
329
#ifdef USE_SIG_BLINDING
330
/* Unblind s */
331
/* NOTE: we use Fermat's little theorem inversion for
332
* constant time here. This is possible since q is prime.
333
*/
334
ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err);
335
ret = nn_mod_mul(&s, &s, &binv, q); EG(ret, err);
336
#endif
337
dbg_nn_print("s", &s);
338
339
/* 8. If s is 0, restart the process at step 4. */
340
ret = nn_iszero(&s, &iszero); EG(ret, err);
341
if (iszero) {
342
goto restart;
343
}
344
345
/* 9. Return (r,s) */
346
ret = nn_export_to_buf(sig + r_len, s_len, &s);
347
348
err:
349
nn_uninit(&tmp);
350
nn_uninit(&s);
351
nn_uninit(&e);
352
nn_uninit(&kr);
353
nn_uninit(&k);
354
nn_uninit(&r);
355
prj_pt_uninit(&kG);
356
#ifdef USE_SIG_BLINDING
357
nn_uninit(&b);
358
nn_uninit(&binv);
359
#endif
360
361
/*
362
* We can now clear data part of the context. This will clear
363
* magic and avoid further reuse of the whole context.
364
*/
365
if(ctx != NULL){
366
IGNORE_RET_VAL(local_memset(&(ctx->sign_data.ecgdsa), 0, sizeof(ecgdsa_sign_data)));
367
}
368
369
/* Clean what remains on the stack */
370
VAR_ZEROIFY(q_bit_len);
371
VAR_ZEROIFY(p_bit_len);
372
VAR_ZEROIFY(r_len);
373
VAR_ZEROIFY(s_len);
374
VAR_ZEROIFY(hsize);
375
PTR_NULLIFY(q);
376
PTR_NULLIFY(x);
377
PTR_NULLIFY(priv_key);
378
PTR_NULLIFY(G);
379
380
return ret;
381
}
382
383
/*
384
* Generic *internal* EC-GDSA verification functions (init, update and finalize).
385
* Their purpose is to allow passing a specific hash function (along with
386
* their output size) and the random ephemeral key k, so that compliance
387
* tests against test vectors can be made without ugly hack in the code
388
* itself.
389
*
390
* Global EC-GDSA verification process is as follows (I,U,F provides
391
* information in which function(s) (init(), update() or finalize())
392
* a specific step is performed):
393
*
394
*| IUF - EC-GDSA verification
395
*|
396
*| I 1. Reject the signature if r or s is 0.
397
*| UF 2. Compute h = H(m). If |h| > bitlen(q), set h to bitlen(q)
398
*| leftmost (most significant) bits of h
399
*| F 3. Compute e = OS2I(h) mod q
400
*| F 4. Compute u = ((r^-1)e mod q)
401
*| F 5. Compute v = ((r^-1)s mod q)
402
*| F 6. Compute W' = uG + vY
403
*| F 7. Compute r' = W'_x mod q
404
*| F 8. Accept the signature if and only if r equals r'
405
*
406
*/
407
408
#define ECGDSA_VERIFY_MAGIC ((word_t)(0xd4da37527288d1b6ULL))
409
#define ECGDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \
410
MUST_HAVE((((void *)(A)) != NULL) && \
411
((A)->magic == ECGDSA_VERIFY_MAGIC), ret, err)
412
413
int _ecgdsa_verify_init(struct ec_verify_context *ctx,
414
const u8 *sig, u8 siglen)
415
{
416
u8 r_len, s_len;
417
bitcnt_t q_bit_len;
418
nn_src_t q;
419
nn *s, *r;
420
int ret, iszero1, iszero2, cmp1, cmp2;
421
422
/* First, verify context has been initialized */
423
ret = sig_verify_check_initialized(ctx); EG(ret, err);
424
425
/* Do some sanity checks on input params */
426
ret = pub_key_check_initialized_and_type(ctx->pub_key, ECGDSA); EG(ret, err);
427
MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) &&
428
(ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);
429
MUST_HAVE((sig != NULL), ret, err);
430
431
/* Make things more readable */
432
q = &(ctx->pub_key->params->ec_gen_order);
433
q_bit_len = ctx->pub_key->params->ec_gen_order_bitlen;
434
r = &(ctx->verify_data.ecgdsa.r);
435
s = &(ctx->verify_data.ecgdsa.s);
436
r_len = (u8)ECGDSA_R_LEN(q_bit_len);
437
s_len = (u8)ECGDSA_S_LEN(q_bit_len);
438
439
/* Check given signature length is the expected one */
440
MUST_HAVE((siglen == ECGDSA_SIGLEN(q_bit_len)), ret, err);
441
442
/* 1. Reject the signature if r or s is 0. */
443
444
/* Let's first import r, the x coordinates of the point reduced mod q */
445
ret = nn_init_from_buf(r, sig, r_len); EG(ret, err);
446
447
/* Import s as a nn */
448
ret = nn_init_from_buf(s, sig + r_len, s_len); EG(ret, err);
449
450
/* Check that r and s are both in ]0,q[ */
451
ret = nn_iszero(s, &iszero1); EG(ret, err);
452
ret = nn_iszero(r, &iszero2); EG(ret, err);
453
ret = nn_cmp(s, q, &cmp1); EG(ret, err);
454
ret = nn_cmp(r, q, &cmp2); EG(ret, err);
455
456
MUST_HAVE((!iszero1) && (cmp1 < 0) && (!iszero2) && (cmp2 < 0), ret, err);
457
458
/* Initialize the remaining of verify context */
459
/* Since we call a callback, sanity check our mapping */
460
ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
461
ret = ctx->h->hfunc_init(&(ctx->verify_data.ecgdsa.h_ctx)); EG(ret, err);
462
463
ctx->verify_data.ecgdsa.magic = ECGDSA_VERIFY_MAGIC;
464
465
err:
466
VAR_ZEROIFY(q_bit_len);
467
VAR_ZEROIFY(r_len);
468
VAR_ZEROIFY(s_len);
469
PTR_NULLIFY(q);
470
PTR_NULLIFY(s);
471
PTR_NULLIFY(r);
472
473
return ret;
474
}
475
476
int _ecgdsa_verify_update(struct ec_verify_context *ctx,
477
const u8 *chunk, u32 chunklen)
478
{
479
int ret;
480
481
/*
482
* First, verify context has been initialized and public
483
* part too. This guarantees the context is an EC-GDSA
484
* verification one and we do not update() or finalize()
485
* before init().
486
*/
487
ret = sig_verify_check_initialized(ctx); EG(ret, err);
488
ECGDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecgdsa), ret, err);
489
490
/* 2. Compute h = H(m) */
491
/* Since we call a callback, sanity check our mapping */
492
ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
493
ret = ctx->h->hfunc_update(&(ctx->verify_data.ecgdsa.h_ctx), chunk,
494
chunklen);
495
496
err:
497
return ret;
498
}
499
500
int _ecgdsa_verify_finalize(struct ec_verify_context *ctx)
501
{
502
nn e, r_prime, rinv, uv, *r, *s;
503
prj_pt uG, vY;
504
prj_pt_t Wprime;
505
prj_pt_src_t G, Y;
506
u8 e_buf[MAX_DIGEST_SIZE];
507
nn_src_t q;
508
u8 hsize;
509
bitcnt_t q_bit_len, rshift;
510
int ret, cmp;
511
512
e.magic = r_prime.magic = WORD(0);
513
rinv.magic = uv.magic = WORD(0);
514
uG.magic = vY.magic = WORD(0);
515
516
/* NOTE: we reuse uG for Wprime to optimize local variables */
517
Wprime = &uG;
518
519
/*
520
* First, verify context has been initialized and public
521
* part too. This guarantees the context is an EC-GDSA
522
* verification one and we do not finalize() before init().
523
*/
524
ret = sig_verify_check_initialized(ctx); EG(ret, err);
525
ECGDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.ecgdsa), ret, err);
526
527
/* Zero init points */
528
ret = local_memset(&uG, 0, sizeof(prj_pt)); EG(ret, err);
529
ret = local_memset(&vY, 0, sizeof(prj_pt)); EG(ret, err);
530
531
/* Make things more readable */
532
G = &(ctx->pub_key->params->ec_gen);
533
Y = &(ctx->pub_key->y);
534
q = &(ctx->pub_key->params->ec_gen_order);
535
r = &(ctx->verify_data.ecgdsa.r);
536
s = &(ctx->verify_data.ecgdsa.s);
537
q_bit_len = ctx->pub_key->params->ec_gen_order_bitlen;
538
hsize = ctx->h->digest_size;
539
540
/* 2. Compute h = H(m) */
541
/* Since we call a callback, sanity check our mapping */
542
ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
543
ret = ctx->h->hfunc_finalize(&(ctx->verify_data.ecgdsa.h_ctx), e_buf); EG(ret, err);
544
dbg_buf_print("H(m)", e_buf, hsize);
545
546
/*
547
* If |h| > bitlen(q), set h to bitlen(q)
548
* leftmost bits of h.
549
*
550
*/
551
rshift = 0;
552
if ((hsize * 8) > q_bit_len) {
553
rshift = (bitcnt_t)((hsize * 8) - q_bit_len);
554
}
555
ret = nn_init_from_buf(&e, e_buf, hsize); EG(ret, err);
556
ret = local_memset(e_buf, 0, hsize); EG(ret, err);
557
if (rshift) {
558
ret = nn_rshift_fixedlen(&e, &e, rshift); EG(ret, err);
559
}
560
dbg_nn_print("H(m) truncated as nn", &e);
561
562
/* 3. Compute e by converting h to an integer and reducing it mod q */
563
ret = nn_mod(&e, &e, q); EG(ret, err);
564
565
/* 4. Compute u = (r^-1)e mod q */
566
ret = nn_modinv(&rinv, r, q); EG(ret, err); /* r^-1 */
567
ret = nn_mod_mul(&uv, &rinv, &e, q); EG(ret, err);
568
ret = prj_pt_mul(&uG, &uv, G); EG(ret, err);
569
570
/* 5. Compute v = (r^-1)s mod q */
571
ret = nn_mod_mul(&uv, &rinv, s, q); EG(ret, err);
572
ret = prj_pt_mul(&vY, &uv, Y); EG(ret, err);
573
574
/* 6. Compute W' = uG + vY */
575
ret = prj_pt_add(Wprime, &uG, &vY); EG(ret, err);
576
577
/* 7. Compute r' = W'_x mod q */
578
ret = prj_pt_unique(Wprime, Wprime); EG(ret, err);
579
dbg_nn_print("W'_x", &(Wprime->X.fp_val));
580
dbg_nn_print("W'_y", &(Wprime->Y.fp_val));
581
ret = nn_mod(&r_prime, &(Wprime->X.fp_val), q); EG(ret, err);
582
583
/* 8. Accept the signature if and only if r equals r' */
584
ret = nn_cmp(r, &r_prime, &cmp); EG(ret, err);
585
ret = (cmp != 0) ? -1 : 0;
586
587
err:
588
nn_uninit(&e);
589
nn_uninit(&r_prime);
590
nn_uninit(&rinv);
591
nn_uninit(&uv);
592
prj_pt_uninit(&uG);
593
prj_pt_uninit(&vY);
594
595
/*
596
* We can now clear data part of the context. This will clear
597
* magic and avoid further reuse of the whole context.
598
*/
599
if(ctx != NULL){
600
IGNORE_RET_VAL(local_memset(&(ctx->verify_data.ecgdsa), 0,
601
sizeof(ecgdsa_verify_data)));
602
}
603
604
PTR_NULLIFY(Wprime);
605
PTR_NULLIFY(r);
606
PTR_NULLIFY(s);
607
PTR_NULLIFY(G);
608
PTR_NULLIFY(Y);
609
PTR_NULLIFY(q);
610
VAR_ZEROIFY(hsize);
611
612
return ret;
613
}
614
615
#else /* WITH_SIG_ECGDSA */
616
617
/*
618
* Dummy definition to avoid the empty translation unit ISO C warning
619
*/
620
typedef int dummy;
621
#endif /* WITH_SIG_ECGDSA */
622
623