Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/libecc/src/sig/sig_algs.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/sig/sig_algs.h>
17
18
/*
19
* Generic private key generation (generate a scalar in ]0,q[
20
* Common accross many schemes, but might diverge for some.
21
*/
22
int generic_gen_priv_key(ec_priv_key *priv_key)
23
{
24
nn_src_t q;
25
int ret;
26
27
ret = priv_key_check_initialized(priv_key); EG(ret, err);
28
29
q = &(priv_key->params->ec_gen_order);
30
31
/* Get a random value in ]0,q[ where q is the group generator order */
32
ret = nn_get_random_mod(&(priv_key->x), q);
33
34
err:
35
return ret;
36
}
37
38
/* Private key generation function per signature scheme */
39
int gen_priv_key(ec_priv_key *priv_key)
40
{
41
const ec_sig_mapping *sm;
42
int ret;
43
u8 i;
44
45
ret = priv_key_check_initialized(priv_key); EG(ret, err);
46
47
ret = -1;
48
for (i = 0, sm = &ec_sig_maps[i];
49
sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) {
50
if (sm->type == priv_key->key_type) {
51
/* NOTE: since sm is initalized with a structure
52
* coming from a const source, we can safely call
53
* the callback here, but better safe than sorry.
54
*/
55
MUST_HAVE((sm->gen_priv_key != NULL), ret, err);
56
ret = sm->gen_priv_key(priv_key);
57
break;
58
}
59
}
60
61
err:
62
return ret;
63
}
64
65
/*
66
* Generic function to init a uninitialized public key from an initialized
67
* private key. The function uses the expected logic to derive the key
68
* (e.g. Y=xG, Y=(x^-1)G, etc). It returns -1 on error (i.e. if the signature
69
* alg is unknown) in which case the public key has not been initialized.
70
* It returns 0 on success.
71
*/
72
int init_pubkey_from_privkey(ec_pub_key *pub_key, ec_priv_key *priv_key)
73
{
74
const ec_sig_mapping *sm;
75
int ret;
76
u8 i;
77
78
ret = priv_key_check_initialized(priv_key); EG(ret, err);
79
80
ret = -1;
81
for (i = 0, sm = &ec_sig_maps[i];
82
sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) {
83
if (sm->type == priv_key->key_type) {
84
/* NOTE: since sm is initalized with a structure
85
* coming from a const source, we can safely call
86
* the callback here, but better safe than sorry.
87
*/
88
MUST_HAVE((sm->init_pub_key != NULL), ret, err);
89
ret = sm->init_pub_key(pub_key, priv_key);
90
break;
91
}
92
}
93
94
err:
95
return ret;
96
}
97
98
/*
99
* On success, 0 is returned and out parameter 'sig_mapping' provides a
100
* pointer to the ec_sig_mapping matching given input parameter
101
* 'sig_name' (a null-terminated string, e.g. "ECDSA"). -1 is returned on error
102
* in which case 'sig_mapping' is not meaningful.
103
*/
104
int get_sig_by_name(const char *ec_sig_name, const ec_sig_mapping **sig_mapping)
105
{
106
const ec_sig_mapping *sm;
107
int ret, check;
108
u8 i;
109
110
MUST_HAVE((ec_sig_name != NULL), ret, err);
111
MUST_HAVE((sig_mapping != NULL), ret, err);
112
113
ret = -1;
114
for (i = 0, sm = &ec_sig_maps[i];
115
sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) {
116
if((!are_str_equal(ec_sig_name, sm->name, &check)) && check){
117
(*sig_mapping) = sm;
118
ret = 0;
119
break;
120
}
121
}
122
123
err:
124
return ret;
125
}
126
127
/*
128
* On success, 0 is returned and out parameter 'sig_mapping' provides a
129
* pointer to the ec_sig_mapping matching given input parameter
130
* 'sig_type' (e.g. ECDSA, ECSDA). -1 is returned on error in which
131
* case 'sig_mapping' is not meaningful.
132
*/
133
int get_sig_by_type(ec_alg_type sig_type, const ec_sig_mapping **sig_mapping)
134
{
135
const ec_sig_mapping *sm;
136
int ret;
137
u8 i;
138
139
MUST_HAVE((sig_mapping != NULL), ret, err);
140
141
ret = -1;
142
for (i = 0, sm = &ec_sig_maps[i];
143
sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) {
144
if (sm->type == sig_type) {
145
(*sig_mapping) = sm;
146
ret = 0;
147
break;
148
}
149
}
150
151
err:
152
return ret;
153
}
154
155
/*
156
* Here, we provide a helper that sanity checks the provided signature
157
* mapping against the constant ones. 0 is returned on success, -1 on
158
* error.
159
*/
160
int ec_sig_mapping_callbacks_sanity_check(const ec_sig_mapping *sig)
161
{
162
const ec_sig_mapping *sm;
163
int ret = -1, check;
164
u8 i;
165
166
MUST_HAVE((sig != NULL), ret, err);
167
168
/* We just check is our mapping is indeed
169
* one of the registered mappings.
170
*/
171
for (i = 0, sm = &ec_sig_maps[i];
172
sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) {
173
if (sm->type == sig->type){
174
if ((!are_str_equal_nlen(sm->name, sig->name, MAX_SIG_ALG_NAME_LEN, &check)) && (!check)){
175
goto err;
176
} else if (sm->siglen != sig->siglen){
177
goto err;
178
} else if (sm->gen_priv_key != sig->gen_priv_key){
179
goto err;
180
} else if (sm->init_pub_key != sig->init_pub_key){
181
goto err;
182
} else if (sm->sign_init != sig->sign_init){
183
goto err;
184
} else if (sm->sign_update != sig->sign_update){
185
goto err;
186
} else if (sm->sign_finalize != sig->sign_finalize){
187
goto err;
188
} else if (sm->sign != sig->sign){
189
goto err;
190
} else if (sm->verify_init != sig->verify_init){
191
goto err;
192
} else if (sm->verify_update != sig->verify_update){
193
goto err;
194
} else if (sm->verify_finalize != sig->verify_finalize){
195
goto err;
196
} else if (sm->verify != sig->verify){
197
goto err;
198
} else{
199
ret = 0;
200
}
201
}
202
}
203
204
err:
205
return ret;
206
}
207
208
/*
209
* Sanity checks of a signature context to see if everything seems OK. 0 is
210
* returned on cucces, -1 on error.
211
*/
212
int ec_sig_ctx_callbacks_sanity_check(const struct ec_sign_context *sig_ctx)
213
{
214
int ret;
215
216
MUST_HAVE((sig_ctx != NULL) && (sig_ctx->ctx_magic == SIG_SIGN_MAGIC), ret, err);
217
218
ret = hash_mapping_callbacks_sanity_check(sig_ctx->h); EG(ret, err);
219
ret = ec_sig_mapping_callbacks_sanity_check(sig_ctx->sig);
220
221
err:
222
return ret;
223
}
224
225
/*
226
* Sanity check of a verification context to see if everything seems
227
* OK. 0 is returned on success, -1 on error.
228
*/
229
int ec_verify_ctx_callbacks_sanity_check(const struct ec_verify_context *verify_ctx)
230
{
231
int ret;
232
233
MUST_HAVE((verify_ctx != NULL) && (verify_ctx->ctx_magic == SIG_VERIFY_MAGIC), ret, err);
234
235
ret = hash_mapping_callbacks_sanity_check(verify_ctx->h); EG(ret, err);
236
ret = ec_sig_mapping_callbacks_sanity_check(verify_ctx->sig);
237
238
err:
239
return ret;
240
}
241
242
243
/*
244
* Compute generic effective signature length (in bytes) depending on the curve
245
* parameters, the signature algorithm and the hash function. On success, 0 is
246
* returned and The signature length is returned using 'siglen' parameter. -1 is
247
* returned on error.
248
*/
249
int ec_get_sig_len(const ec_params *params, ec_alg_type sig_type,
250
hash_alg_type hash_type, u8 *siglen)
251
{
252
const ec_sig_mapping *sm;
253
u8 digest_size = 0;
254
u8 block_size = 0;
255
int ret;
256
u8 i;
257
258
MUST_HAVE(((params != NULL) && (siglen != NULL)), ret, err);
259
260
ret = get_hash_sizes(hash_type, &digest_size, &block_size); EG(ret, err);
261
262
ret = -1;
263
for (i = 0, sm = &ec_sig_maps[i];
264
sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) {
265
if (sm->type == sig_type) {
266
/* NOTE: since sm is initalized with a structure
267
* coming from a const source, we can safely call
268
* the callback here, but better safe than sorry.
269
*/
270
MUST_HAVE((sm->siglen != NULL), ret, err);
271
ret = sm->siglen(params->ec_fp.p_bitlen,
272
params->ec_gen_order_bitlen,
273
digest_size, block_size, siglen);
274
break;
275
}
276
}
277
278
err:
279
return ret;
280
}
281
282
/* Generic signature */
283
284
/*
285
* Core version of generic signature initialization function. Its purpose
286
* is to initialize given sign context structure 'ctx' based on given key pair,
287
* nn random function, signature and hash types. This version allows passing
288
* a specific nn random function. It returns 0 on success, -1 on error.
289
*
290
* The random function is expected to initialize a nn 'out' with a value taken
291
* uniformly at random in [1, q-1]. It returns 0 on success and -1 on error. See
292
* nn_get_random_mod() in nn_rand.c for a function that fits the dscription.
293
*/
294
int _ec_sign_init(struct ec_sign_context *ctx,
295
const ec_key_pair *key_pair,
296
int (*rand) (nn_t out, nn_src_t q),
297
ec_alg_type sig_type, hash_alg_type hash_type,
298
const u8 *adata, u16 adata_len)
299
{
300
const ec_sig_mapping *sm;
301
const hash_mapping *hm;
302
int ret;
303
u8 i;
304
305
MUST_HAVE((ctx != NULL), ret, err);
306
307
ret = key_pair_check_initialized_and_type(key_pair, sig_type); EG(ret, err);
308
309
/* We first need to get the specific hash structure */
310
ret = -1;
311
for (i = 0, hm = &hash_maps[i];
312
hm->type != UNKNOWN_HASH_ALG; hm = &hash_maps[++i]) {
313
if (hm->type == hash_type) {
314
ret = 0;
315
break;
316
}
317
}
318
if (ret) {
319
goto err;
320
}
321
322
/* Now, let's try and get the specific key alg which was requested */
323
ret = -1;
324
for (i = 0, sm = &ec_sig_maps[i];
325
sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) {
326
if ((sm->type == sig_type) && (sm->sign_init != NULL)) {
327
ret = 0;
328
break;
329
}
330
}
331
if (ret) {
332
goto err;
333
}
334
335
#ifdef NO_KNOWN_VECTORS
336
/*
337
* NOTE: when we do not need self tests for known vectors,
338
* we can be strict about random function handler!
339
* We only use our internal method to provide random integers
340
* (which avoids honest mistakes ...).
341
*
342
* This also allows us to avoid the corruption of such a pointer
343
* in our signature contexts.
344
*/
345
if (rand) {
346
MUST_HAVE((rand == nn_get_random_mod), ret, err);
347
}
348
rand = nn_get_random_mod;
349
#else
350
/* Use given random function if provided or fallback to ours */
351
if (!rand) {
352
rand = nn_get_random_mod;
353
}
354
#endif
355
/* Sanity checks on our mappings */
356
ret = hash_mapping_sanity_check(hm); EG(ret, err);
357
ret = sig_mapping_sanity_check(sm); EG(ret, err);
358
359
/* Initialize context for specific signature function */
360
ret = local_memset(ctx, 0, sizeof(struct ec_sign_context)); EG(ret, err);
361
ctx->key_pair = key_pair;
362
ctx->rand = rand;
363
ctx->h = hm;
364
ctx->sig = sm;
365
ctx->adata = adata;
366
ctx->adata_len = adata_len;
367
ctx->ctx_magic = SIG_SIGN_MAGIC;
368
369
/*
370
* NOTE: since sm has been previously initalized with a structure
371
* coming from a const source, we can safely call the callback here.
372
*/
373
ret = sm->sign_init(ctx);
374
375
err:
376
if (ret && (ctx != NULL)) {
377
/* Clear the whole context to prevent future reuse */
378
IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_sign_context)));
379
}
380
381
return ret;
382
}
383
384
/*
385
* Same as previous but for public use; it forces our internal nn random
386
* function (nn_get_random_mod()). Returns 0 on success, -1 on error.
387
*/
388
int ec_sign_init(struct ec_sign_context *ctx, const ec_key_pair *key_pair,
389
ec_alg_type sig_type, hash_alg_type hash_type,
390
const u8 *adata, u16 adata_len)
391
{
392
return _ec_sign_init(ctx, key_pair, NULL, sig_type, hash_type,
393
adata, adata_len);
394
}
395
396
/*
397
* Signature update function. Returns 0 on success, -1 on error. On error,
398
* signature context is zeroized and is no more usable.
399
*/
400
int ec_sign_update(struct ec_sign_context *ctx, const u8 *chunk, u32 chunklen)
401
{
402
int ret;
403
404
/* Sanity checks */
405
ret = sig_sign_check_initialized(ctx); EG(ret, err);
406
ret = sig_mapping_sanity_check(ctx->sig); EG(ret, err);
407
ret = hash_mapping_sanity_check(ctx->h); EG(ret, err);
408
ret = ec_sig_ctx_callbacks_sanity_check(ctx); EG(ret, err);
409
ret = ctx->sig->sign_update(ctx, chunk, chunklen);
410
411
err:
412
if (ret && (ctx != NULL)) {
413
/* Clear the whole context to prevent future reuse */
414
IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_sign_context)));
415
}
416
417
return ret;
418
}
419
420
/*
421
* Signature finalization function. Returns 0 on success, -1 on error.
422
* Upon call, the signature context is cleared to prevent future use.
423
*/
424
int ec_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen)
425
{
426
int ret;
427
428
/* Sanity checks */
429
ret = sig_sign_check_initialized(ctx); EG(ret, err);
430
ret = sig_mapping_sanity_check(ctx->sig); EG(ret, err);
431
ret = hash_mapping_sanity_check(ctx->h); EG(ret, err);
432
ret = ec_sig_ctx_callbacks_sanity_check(ctx); EG(ret, err);
433
ret = ctx->sig->sign_finalize(ctx, sig, siglen);
434
435
err:
436
if (ctx != NULL) {
437
/* Clear the whole context to prevent future reuse */
438
IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_sign_context)));
439
}
440
441
return ret;
442
}
443
444
/*
445
* Single call version of signature function (init, update and finalize). It
446
* returns 0 on success, -1 on error. This version allows passing a custom
447
* random function. This is useful for test vectors but should be done with
448
* care.
449
*
450
* The random function is expected to initialize a nn 'out' with a value taken
451
* uniformly at random in [1, q-1]. It returns 0 on success and -1 on error. See
452
* nn_get_random_mod() in nn_rand.c for a function that fits the dscription.
453
*/
454
int generic_ec_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair,
455
const u8 *m, u32 mlen,
456
int (*rand) (nn_t out, nn_src_t q),
457
ec_alg_type sig_type, hash_alg_type hash_type,
458
const u8 *adata, u16 adata_len)
459
{
460
struct ec_sign_context ctx;
461
int ret;
462
463
ret = _ec_sign_init(&ctx, key_pair, rand, sig_type,
464
hash_type, adata, adata_len); EG(ret, err);
465
ret = ec_sign_update(&ctx, m, mlen); EG(ret, err);
466
ret = ec_sign_finalize(&ctx, sig, siglen);
467
468
err:
469
return ret;
470
}
471
472
473
int _ec_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair,
474
const u8 *m, u32 mlen,
475
int (*rand) (nn_t out, nn_src_t q),
476
ec_alg_type sig_type, hash_alg_type hash_type,
477
const u8 *adata, u16 adata_len)
478
{
479
const ec_sig_mapping *sm;
480
int ret;
481
482
ret = get_sig_by_type(sig_type, &sm); EG(ret, err);
483
MUST_HAVE(((sm != NULL) && (sm->sign != NULL)), ret, err);
484
485
ret = sm->sign(sig, siglen, key_pair, m, mlen, rand,
486
sig_type, hash_type, adata, adata_len);
487
488
err:
489
return ret;
490
}
491
492
/*
493
* Same as previous but for public use; it forces our internal nn random
494
* function (nn_get_random_mod()) by pasing NULL for 'rand' argument
495
* _ec_sign(). Returns 0 on success, -1 on error.
496
*/
497
int ec_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair,
498
const u8 *m, u32 mlen,
499
ec_alg_type sig_type, hash_alg_type hash_type,
500
const u8 *adata, u16 adata_len)
501
{
502
return _ec_sign(sig, siglen, key_pair, m, mlen,
503
NULL, sig_type, hash_type, adata, adata_len);
504
}
505
506
/*
507
* Generic signature verification initialization function. Returns 0 on success,
508
* -1 on error. On error, verification context is cleared to prevent further
509
* reuse.
510
*/
511
int ec_verify_init(struct ec_verify_context *ctx, const ec_pub_key *pub_key,
512
const u8 *sig, u8 siglen,
513
ec_alg_type sig_type, hash_alg_type hash_type,
514
const u8 *adata, u16 adata_len)
515
{
516
const ec_sig_mapping *sm;
517
const hash_mapping *hm;
518
u8 i;
519
int ret;
520
521
MUST_HAVE((ctx != NULL), ret, err);
522
523
ret = pub_key_check_initialized_and_type(pub_key, sig_type); EG(ret, err);
524
525
/* We first need to get the specific hash structure */
526
ret = -1;
527
for (i = 0, hm = &hash_maps[i];
528
hm->type != UNKNOWN_HASH_ALG; hm = &hash_maps[++i]) {
529
if (hm->type == hash_type) {
530
ret = 0;
531
break;
532
}
533
}
534
if (ret) {
535
goto err;
536
}
537
538
/*
539
* Now, let's try and get the specific key algorithm which was
540
* requested
541
*/
542
ret = -1;
543
for (i = 0, sm = &ec_sig_maps[i];
544
sm->type != UNKNOWN_ALG; sm = &ec_sig_maps[++i]) {
545
if ((sm->type == sig_type) && (sm->verify_init != NULL)) {
546
ret = 0;
547
break;
548
}
549
}
550
if (ret) {
551
goto err;
552
}
553
554
/* Sanity checks on our mappings */
555
ret = hash_mapping_sanity_check(hm); EG(ret, err);
556
ret = sig_mapping_sanity_check(sm); EG(ret, err);
557
558
/* Initialize context for specific signature function */
559
ret = local_memset(ctx, 0, sizeof(struct ec_verify_context)); EG(ret, err);
560
ctx->pub_key = pub_key;
561
ctx->h = hm;
562
ctx->sig = sm;
563
ctx->adata = adata;
564
ctx->adata_len = adata_len;
565
ctx->ctx_magic = SIG_VERIFY_MAGIC;
566
567
/*
568
* NOTE: since sm has been previously initalized with a structure
569
* coming from a const source, we can safely call the callback
570
* here.
571
*/
572
ret = sm->verify_init(ctx, sig, siglen);
573
574
err:
575
576
if (ret && (ctx != NULL)) {
577
/* Clear the whole context to prevent future reuse */
578
IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_verify_context)));
579
}
580
581
return ret;
582
}
583
584
/*
585
* Signature verification update function. Returns 0 on success, -1 on error.
586
* On error, verification context is cleared to prevent further reuse.
587
*/
588
int ec_verify_update(struct ec_verify_context *ctx,
589
const u8 *chunk, u32 chunklen)
590
{
591
int ret;
592
593
ret = sig_verify_check_initialized(ctx); EG(ret, err);
594
ret = sig_mapping_sanity_check(ctx->sig); EG(ret, err);
595
ret = hash_mapping_sanity_check(ctx->h); EG(ret, err);
596
597
/* Since we call a callback, sanity check our contexts */
598
ret = ec_verify_ctx_callbacks_sanity_check(ctx); EG(ret, err);
599
ret = ctx->sig->verify_update(ctx, chunk, chunklen);
600
601
err:
602
if (ret && (ctx != NULL)) {
603
/* Clear the whole context to prevent future reuse */
604
IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_verify_context)));
605
}
606
607
return ret;
608
}
609
610
/*
611
* Signature verification finalize function. Returns 0 on success, -1 on error.
612
* On error, verification context is cleared to prevent further reuse.
613
*/
614
int ec_verify_finalize(struct ec_verify_context *ctx)
615
{
616
int ret;
617
618
ret = sig_verify_check_initialized(ctx); EG(ret, err);
619
ret = sig_mapping_sanity_check(ctx->sig); EG(ret, err);
620
ret = hash_mapping_sanity_check(ctx->h); EG(ret, err);
621
622
/* Since we call a callback, sanity check our contexts */
623
ret = ec_verify_ctx_callbacks_sanity_check(ctx); EG(ret, err);
624
ret = ctx->sig->verify_finalize(ctx);
625
626
err:
627
if (ret && (ctx != NULL)) {
628
/* Clear the whole context to prevent future reuse */
629
IGNORE_RET_VAL(local_memset(ctx, 0, sizeof(struct ec_verify_context)));
630
}
631
return ret;
632
}
633
634
/*
635
* Single call version of signature verification function (init, update and
636
* finalize). It returns 0 on success, -1 on error.
637
*/
638
int generic_ec_verify(const u8 *sig, u8 siglen, const ec_pub_key *pub_key,
639
const u8 *m, u32 mlen,
640
ec_alg_type sig_type, hash_alg_type hash_type,
641
const u8 *adata, u16 adata_len)
642
{
643
struct ec_verify_context ctx;
644
int ret;
645
646
ret = ec_verify_init(&ctx, pub_key, sig, siglen, sig_type,
647
hash_type, adata, adata_len); EG(ret, err);
648
ret = ec_verify_update(&ctx, m, mlen); EG(ret, err);
649
ret = ec_verify_finalize(&ctx);
650
651
err:
652
return ret;
653
}
654
655
int ec_verify(const u8 *sig, u8 siglen, const ec_pub_key *pub_key,
656
const u8 *m, u32 mlen,
657
ec_alg_type sig_type, hash_alg_type hash_type,
658
const u8 *adata, u16 adata_len)
659
{
660
661
const ec_sig_mapping *sm;
662
int ret;
663
664
ret = get_sig_by_type(sig_type, &sm); EG(ret, err);
665
666
MUST_HAVE((sm != NULL) && (sm->verify != NULL), ret, err);
667
668
ret = sm->verify(sig, siglen, pub_key, m, mlen, sig_type,
669
hash_type, adata, adata_len);
670
671
err:
672
return ret;
673
}
674
675
int ec_verify_batch(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys,
676
const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type,
677
hash_alg_type hash_type, const u8 **adata, const u16 *adata_len,
678
verify_batch_scratch_pad *scratch_pad_area, u32 *scratch_pad_area_len)
679
{
680
681
const ec_sig_mapping *sm;
682
int ret;
683
684
ret = get_sig_by_type(sig_type, &sm); EG(ret, err);
685
686
MUST_HAVE((sm != NULL) && (sm->verify_batch != NULL), ret, err);
687
688
ret = sm->verify_batch(s, s_len, pub_keys, m, m_len, num, sig_type,
689
hash_type, adata, adata_len,
690
scratch_pad_area, scratch_pad_area_len);
691
692
err:
693
return ret;
694
}
695
696
/*
697
* Import a signature with structured data containing information about the EC
698
* algorithm type as well as the hash function used to produce the signature.
699
* The function returns 0 on success, -1 on error. out parameters (sig_type,
700
* hash_type, curve_name should only be considered on success.
701
*/
702
int ec_structured_sig_import_from_buf(u8 *sig, u32 siglen,
703
const u8 *out_buf, u32 outlen,
704
ec_alg_type * sig_type,
705
hash_alg_type * hash_type,
706
u8 curve_name[MAX_CURVE_NAME_LEN])
707
{
708
u32 metadata_len = (3 * sizeof(u8));
709
int ret;
710
711
MUST_HAVE((out_buf != NULL) && (sig_type != NULL) &&
712
(hash_type != NULL) && (curve_name != NULL), ret, err);
713
/* We only deal with signatures of length < 256 */
714
MUST_HAVE((siglen <= EC_MAX_SIGLEN) && (sig != NULL), ret, err);
715
716
/* We first import the metadata consisting of:
717
* - One byte = the EC algorithm type
718
* - One byte = the hash algorithm type
719
* - One byte = the curve type (FRP256V1, ...)
720
*/
721
MUST_HAVE((outlen <= (siglen + metadata_len)), ret, err);
722
723
*sig_type = (ec_alg_type)out_buf[0];
724
*hash_type = (hash_alg_type)out_buf[1];
725
ret = ec_get_curve_name_by_type((ec_curve_type) out_buf[2],
726
curve_name, MAX_CURVE_NAME_LEN); EG(ret, err);
727
728
/* Copy the raw signature */
729
ret = local_memcpy(sig, out_buf + metadata_len, siglen);
730
731
err:
732
return ret;
733
}
734
735
/*
736
* Export a signature with structured data containing information about the
737
* EC algorithm type as well as the hash function used to produce it. The
738
* function returns 0 on success, -1 on error.
739
*/
740
int ec_structured_sig_export_to_buf(const u8 *sig, u32 siglen,
741
u8 *out_buf, u32 outlen,
742
ec_alg_type sig_type,
743
hash_alg_type hash_type,
744
const u8
745
curve_name[MAX_CURVE_NAME_LEN])
746
{
747
u32 metadata_len = (3 * sizeof(u8));
748
u32 len;
749
u8 curve_name_len;
750
ec_curve_type curve_type;
751
int ret;
752
753
MUST_HAVE((out_buf != NULL) && (curve_name != NULL), ret, err);
754
/* We only deal with signatures of length < 256 */
755
MUST_HAVE((siglen <= EC_MAX_SIGLEN) && (sig != NULL), ret, err);
756
757
/* We first export the metadata consisting of:
758
* - One byte = the EC algorithm type
759
* - One byte = the hash algorithm type
760
* - One byte = the curve type (FRP256V1, ...)
761
*
762
*/
763
MUST_HAVE(outlen >= (siglen + metadata_len), ret, err);
764
765
out_buf[0] = (u8)sig_type;
766
out_buf[1] = (u8)hash_type;
767
ret = local_strlen((const char *)curve_name, &len); EG(ret, err);
768
len += 1;
769
MUST_HAVE((len < 256), ret, err);
770
curve_name_len = (u8)len;
771
ret = ec_get_curve_type_by_name(curve_name, curve_name_len, &curve_type); EG(ret, err);
772
out_buf[2] = (u8)curve_type;
773
MUST_HAVE((out_buf[2] != UNKNOWN_CURVE), ret, err);
774
775
/* Copy the raw signature */
776
ret = local_memcpy(out_buf + metadata_len, sig, siglen);
777
778
err:
779
return ret;
780
}
781
782
783
/* Signature finalization function */
784
int unsupported_sign_init(struct ec_sign_context * ctx)
785
{
786
/* Quirk to avoid unused variables */
787
FORCE_USED_VAR(ctx);
788
789
/* Return an error in any case here */
790
return -1;
791
}
792
793
int unsupported_sign_update(struct ec_sign_context * ctx,
794
const u8 *chunk, u32 chunklen)
795
{
796
/* Quirk to avoid unused variables */
797
FORCE_USED_VAR(ctx);
798
FORCE_USED_VAR(chunk);
799
FORCE_USED_VAR(chunklen);
800
801
/* Return an error in any case here */
802
return -1;
803
}
804
805
int unsupported_sign_finalize(struct ec_sign_context *ctx, u8 *sig, u8 siglen)
806
{
807
/* Quirk to avoid unused variables */
808
FORCE_USED_VAR(ctx);
809
FORCE_USED_VAR(sig);
810
FORCE_USED_VAR(siglen);
811
812
/* Return an error in any case here */
813
return -1;
814
}
815
816
int unsupported_verify_init(struct ec_verify_context * ctx,
817
const u8 *sig, u8 siglen)
818
{
819
/* Quirk to avoid unused variables */
820
FORCE_USED_VAR(ctx);
821
FORCE_USED_VAR(sig);
822
FORCE_USED_VAR(siglen);
823
824
/* Return an error in any case here */
825
return -1;
826
}
827
828
int unsupported_verify_update(struct ec_verify_context * ctx,
829
const u8 *chunk, u32 chunklen)
830
{
831
/* Quirk to avoid unused variables */
832
FORCE_USED_VAR(ctx);
833
FORCE_USED_VAR(chunk);
834
FORCE_USED_VAR(chunklen);
835
836
/* Return an error in any case here */
837
return -1;
838
}
839
840
int unsupported_verify_finalize(struct ec_verify_context * ctx)
841
{
842
/* Quirk to avoid unused variables */
843
FORCE_USED_VAR(ctx);
844
845
/* Return an error in any case here */
846
return -1;
847
}
848
849
/* Unsupported batch verification */
850
int unsupported_verify_batch(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys,
851
const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type,
852
hash_alg_type hash_type, const u8 **adata, const u16 *adata_len,
853
verify_batch_scratch_pad *scratch_pad_area, u32 *scratch_pad_area_len)
854
{
855
/* Quirk to avoid unused variables */
856
FORCE_USED_VAR(s);
857
FORCE_USED_VAR(pub_keys);
858
FORCE_USED_VAR(m);
859
FORCE_USED_VAR(num);
860
FORCE_USED_VAR(sig_type);
861
FORCE_USED_VAR(hash_type);
862
FORCE_USED_VAR(adata);
863
FORCE_USED_VAR(s_len);
864
FORCE_USED_VAR(m_len);
865
FORCE_USED_VAR(adata_len);
866
FORCE_USED_VAR(scratch_pad_area);
867
FORCE_USED_VAR(scratch_pad_area_len);
868
869
/* Return an error in any case here */
870
return -1;
871
}
872
873
/* This function returns 1 in 'check' if the init/update/finalize mode
874
* is supported by the signature algorithm, 0 otherwise.
875
*
876
* Return value is 0 on success, -1 on error. 'check' is only meaningful on
877
* success.
878
*/
879
int is_sign_streaming_mode_supported(ec_alg_type sig_type, int *check)
880
{
881
int ret;
882
const ec_sig_mapping *sig;
883
884
MUST_HAVE((check != NULL), ret, err);
885
886
ret = get_sig_by_type(sig_type, &sig); EG(ret, err);
887
MUST_HAVE((sig != NULL), ret, err);
888
889
if ((sig->sign_init == unsupported_sign_init) ||
890
(sig->sign_update == unsupported_sign_update) ||
891
(sig->sign_finalize == unsupported_sign_finalize)) {
892
(*check) = 0;
893
}
894
else{
895
(*check) = 1;
896
}
897
898
err:
899
return ret;
900
}
901
902
/* This function returns 1 in 'check' if the init/update/finalize mode
903
* is supported by the verification algorithm, 0 otherwise.
904
*
905
* Return value is 0 on success, -1 on error. 'check' is only meaningful on
906
* success.
907
*/
908
int is_verify_streaming_mode_supported(ec_alg_type sig_type, int *check)
909
{
910
int ret;
911
const ec_sig_mapping *sig;
912
913
MUST_HAVE((check != NULL), ret, err);
914
915
ret = get_sig_by_type(sig_type, &sig); EG(ret, err);
916
MUST_HAVE((sig != NULL), ret, err);
917
918
if ((sig->verify_init == unsupported_verify_init) ||
919
(sig->verify_update == unsupported_verify_update) ||
920
(sig->verify_finalize == unsupported_verify_finalize)) {
921
(*check) = 0;
922
}
923
else{
924
(*check) = 1;
925
}
926
927
err:
928
return ret;
929
}
930
931
/* This function returns 1 in 'check' if the batch verification mode
932
* is supported by the verification algorithm, 0 otherwise.
933
*
934
* Return value is 0 on success, -1 on error. 'check' is only meaningful on
935
* success.
936
*/
937
int is_verify_batch_mode_supported(ec_alg_type sig_type, int *check)
938
{
939
int ret;
940
const ec_sig_mapping *sig;
941
942
MUST_HAVE((check != NULL), ret, err);
943
944
ret = get_sig_by_type(sig_type, &sig); EG(ret, err);
945
MUST_HAVE((sig != NULL), ret, err);
946
947
if (sig->verify_batch == unsupported_verify_batch) {
948
(*check) = 0;
949
}
950
else{
951
(*check) = 1;
952
}
953
954
err:
955
return ret;
956
}
957
958
/* Tells if the signature scheme is deterministic or not,
959
* e.g. if random nonces are used to produce signatures.
960
*
961
* 'check' is set to 1 if deterministic, 0 otherwise.
962
*
963
* Return value is 0 on success, -1 on error. 'check' is only meaningful on
964
* success.
965
966
*/
967
int is_sign_deterministic(ec_alg_type sig_type, int *check)
968
{
969
int ret;
970
const ec_sig_mapping *sig;
971
972
MUST_HAVE((check != NULL), ret, err);
973
974
ret = get_sig_by_type(sig_type, &sig); EG(ret, err);
975
MUST_HAVE((sig != NULL), ret, err);
976
977
switch(sig_type) {
978
#if defined(WITH_SIG_EDDSA25519)
979
case EDDSA25519:
980
case EDDSA25519CTX:
981
case EDDSA25519PH:
982
(*check) = 1;
983
break;
984
#endif
985
#if defined(WITH_SIG_EDDSA448)
986
case EDDSA448:
987
case EDDSA448PH:
988
(*check) = 1;
989
break;
990
#endif
991
#if defined(WITH_SIG_DECDSA)
992
case DECDSA:
993
(*check) = 1;
994
break;
995
#endif
996
default:
997
(*check) = 0;
998
break;
999
}
1000
1001
err:
1002
return ret;
1003
}
1004
1005
1006
/*
1007
* Bubble sort the table of numbers and the table of projective points
1008
* accordingly in ascending order. We only work on index numbers in the table
1009
* to avoid useless copies.
1010
*/
1011
ATTRIBUTE_WARN_UNUSED_RET static int _bubble_sort(verify_batch_scratch_pad *elements, u32 num)
1012
{
1013
u32 i, j;
1014
int ret, swapped;
1015
1016
MUST_HAVE((elements != NULL), ret, err);
1017
MUST_HAVE((num >= 1), ret, err);
1018
for(i = 0; i < (num - 1); i++){
1019
swapped = 0;
1020
for(j = 0; j < (num - i - 1); j++){
1021
int check;
1022
u32 indexj, indexj_next;
1023
indexj = elements[j].index;
1024
indexj_next = elements[j + 1].index;
1025
ret = nn_cmp(&elements[indexj].number, &elements[indexj_next].number, &check); EG(ret, err);
1026
if(check < 0){
1027
/* Swap the two elements */
1028
elements[j].index = indexj_next;
1029
elements[j + 1].index = indexj;
1030
swapped = 1;
1031
}
1032
}
1033
/* If no swap occurred in the inner loop, get out */
1034
if(!swapped){
1035
break;
1036
}
1037
}
1038
1039
ret = 0;
1040
err:
1041
return ret;
1042
}
1043
1044
/*
1045
* Bos-Coster algorithm, presented e.g. in https://ed25519.cr.yp.to/ed25519-20110705.pdf
1046
*
1047
* The Bos-Coster algorithm allows to optimize a sum of multi-scalar multiplications using
1048
* addition chains. This is used for example in batch signature verification of schemes
1049
* that support it.
1050
*
1051
*/
1052
int ec_verify_bos_coster(verify_batch_scratch_pad *elements, u32 num, bitcnt_t bits)
1053
{
1054
int ret, check;
1055
u32 i, index0, index1, max_bos_coster_iterations;
1056
1057
MUST_HAVE((elements != NULL), ret, err);
1058
MUST_HAVE((num > 1), ret, err);
1059
1060
/* We fix our maximum attempts here.
1061
*
1062
* NOTE: this avoids "denial of service" when
1063
* providing scalars with too big discrepancies, as
1064
* the Bos-Coster algorithm supposes uniformly randomized
1065
* numbers ...
1066
* If we are provided with scalars with too big differences,
1067
* we end up looping for a very long time. In this case, we
1068
* rather quit with a specific error.
1069
*
1070
* The limit hereafter is fixed using the mean asymptotic complexity
1071
* of the algorithm in the nominal case (multiplied by the bit size
1072
* of num to be lax).
1073
*/
1074
MUST_HAVE((num * bits) >= num, ret, err);
1075
MUST_HAVE((num * bits) >= bits, ret, err);
1076
max_bos_coster_iterations = (num * bits);
1077
1078
/********************************************/
1079
/****** Bos-Coster algorithm ****************/
1080
for(i = 0; i < num; i++){
1081
elements[i].index = i;
1082
}
1083
i = 0;
1084
do {
1085
/* Sort the elements in descending order */
1086
ret = _bubble_sort(elements, num); EG(ret, err);
1087
/* Perform the addition */
1088
index0 = elements[0].index;
1089
index1 = elements[1].index;
1090
ret = prj_pt_add(&elements[index1].point, &elements[index0].point,
1091
&elements[index1].point); EG(ret, err);
1092
/* Check the two first integers */
1093
ret = nn_cmp(&elements[index0].number, &elements[index1].number, &check);
1094
/* Subtract the two first numbers */
1095
ret = nn_sub(&elements[index0].number, &elements[index0].number,
1096
&elements[index1].number); EG(ret, err);
1097
i++;
1098
if(i > max_bos_coster_iterations){
1099
/* Give up with specific error code */
1100
ret = -2;
1101
goto err;
1102
}
1103
} while(check > 0);
1104
1105
index0 = elements[0].index;
1106
/* Proceed with the last scalar multiplication */
1107
ret = _prj_pt_unprotected_mult(&elements[index0].point, &elements[index0].number, &elements[index0].point);
1108
1109
/* The result is in point [0] of elements */
1110
err:
1111
return ret;
1112
}
1113
1114