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/utils/utils.h>
17 #include <libecc/external_deps/rand.h>
18 #include <libecc/external_deps/time.h>
19 #include <libecc/external_deps/print.h>
20 #include "ec_self_tests_core.h"
21
22 /* Parallelize self tests? */
23 #ifdef WITH_OPENMP_SELF_TESTS
24 /* No openmp without stdlib ... */
25 #ifndef WITH_STDLIB
26 #error "Sorry: no possible self tests parallelization (OpenMP) without stdlib! Please use WITH_STDLIB"
27 #endif
28 #include <omp.h>
29 #include <stdlib.h>
30 static omp_lock_t global_lock;
31 static volatile u8 global_lock_initialized = 0;
32 #define OPENMP_LOCK() do { \
33 if(!global_lock_initialized){ \
34 omp_init_lock(&global_lock); \
35 global_lock_initialized = 1; \
36 } \
37 omp_set_lock(&global_lock); \
38 } while(0)
39 #define OPENMP_UNLOCK() do { \
40 omp_unset_lock(&global_lock); \
41 } while(0)
42 #define OPENMP_EG(ret, err) do { \
43 if(ret){ \
44 ext_printf("OpenMP abort following error ... %s:%d\n", __FILE__, __LINE__); \
45 exit(-1); \
46 } \
47 } while(0)
48 #else
49 #define OPENMP_LOCK()
50 #define OPENMP_UNLOCK()
51 #define OPENMP_EG(ret, err) do { \
52 EG(ret, err); \
53 } while(0)
54 #endif
55
ec_gen_import_export_kp(ec_key_pair * kp,const ec_params * params,const ec_test_case * c)56 ATTRIBUTE_WARN_UNUSED_RET static int ec_gen_import_export_kp(ec_key_pair *kp, const ec_params *params,
57 const ec_test_case *c)
58 {
59 u8 pub_key_buf[EC_STRUCTURED_PUB_KEY_MAX_EXPORT_SIZE];
60 u8 priv_key_buf[EC_STRUCTURED_PRIV_KEY_MAX_EXPORT_SIZE];
61 u8 pub_key_buf_len, priv_key_buf_len;
62 ec_key_pair imported_kp;
63 int ret;
64
65 MUST_HAVE(c != NULL, ret, err);
66
67 ret = local_memset(pub_key_buf, 0, sizeof(pub_key_buf)); EG(ret, err);
68 ret = local_memset(priv_key_buf, 0, sizeof(priv_key_buf)); EG(ret, err);
69 ret = local_memset(&imported_kp, 0, sizeof(imported_kp)); EG(ret, err);
70
71 /* Generate key pair */
72 ret = ec_key_pair_gen(kp, params, c->sig_type);
73 if (ret) {
74 ext_printf("Error generating key pair\n");
75 goto err;
76 }
77 pub_key_buf_len = EC_STRUCTURED_PUB_KEY_EXPORT_SIZE(&(kp->pub_key));
78 priv_key_buf_len = EC_STRUCTURED_PRIV_KEY_EXPORT_SIZE(&(kp->priv_key));
79
80 /* Export public and private keys in buffers */
81 ret = ec_structured_pub_key_export_to_buf(&(kp->pub_key), pub_key_buf,
82 pub_key_buf_len);
83 if (ret) {
84 ext_printf("Error exporting public key\n");
85 goto err;
86 }
87 ret = ec_structured_priv_key_export_to_buf(&(kp->priv_key),
88 priv_key_buf,
89 priv_key_buf_len);
90 if (ret) {
91 ext_printf("Error exporting private key\n");
92 goto err;
93 }
94
95 /* Import public and private key */
96 ret = ec_structured_pub_key_import_from_buf(&(imported_kp.pub_key),
97 params,
98 pub_key_buf,
99 pub_key_buf_len,
100 c->sig_type);
101 if (ret) {
102 ext_printf("Error importing public key\n");
103 goto err;
104 }
105 ret = ec_structured_priv_key_import_from_buf(&(imported_kp.priv_key),
106 params, priv_key_buf,
107 priv_key_buf_len,
108 c->sig_type);
109 if (ret) {
110 ext_printf("Error importing private key\n");
111 goto err;
112 }
113 ret = 0;
114
115 err:
116 return ret;
117 }
118
119 /* This function randomly splits the message input in small chunks to
120 * test the signature init / multiple updates / finalize mechanism for
121 * algorithms that support them.
122 */
random_split_ec_sign(u8 * sig,u8 siglen,const ec_key_pair * key_pair,const u8 * m,u32 mlen,int (* rand)(nn_t out,nn_src_t q),ec_alg_type sig_type,hash_alg_type hash_type,const u8 * adata,u16 adata_len)123 ATTRIBUTE_WARN_UNUSED_RET static int random_split_ec_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair,
124 const u8 *m, u32 mlen,
125 int (*rand) (nn_t out, nn_src_t q),
126 ec_alg_type sig_type, hash_alg_type hash_type, const u8 *adata, u16 adata_len)
127 {
128 struct ec_sign_context ctx;
129 int ret;
130 u32 consumed;
131
132 ret = local_memset(&ctx, 0, sizeof(ctx)); EG(ret, err);
133
134 MUST_HAVE(sig != NULL, ret, err);
135 MUST_HAVE(key_pair != NULL, ret, err);
136 MUST_HAVE(m != NULL, ret, err);
137 /* note: adata == NULL is allowed */
138
139 ret = _ec_sign_init(&ctx, key_pair, rand, sig_type, hash_type, adata, adata_len);
140 if (ret) {
141 goto err;
142 }
143 /* We randomly split the input message in chunks and proceed with updates */
144 consumed = 0;
145 while(consumed < mlen){
146 u32 toconsume = 0;
147 ret = get_random((u8 *)&toconsume, sizeof(toconsume));
148 if (ret) {
149 ext_printf("Error when getting random\n");
150 goto err;
151 }
152 toconsume = (toconsume % (mlen - consumed));
153 if(((mlen - consumed) == 1) && (toconsume == 0)){
154 toconsume = 1;
155 }
156 ret = ec_sign_update(&ctx, &m[consumed], toconsume);
157 if (ret) {
158 goto err;
159 }
160 consumed += toconsume;
161 }
162
163 ret = ec_sign_finalize(&ctx, sig, siglen);
164
165 err:
166 return ret;
167 }
168
169 /* This function randomly splits the message input in small chunks to
170 * test the verification init / multiple updates / finalize mechanism for
171 * algorithms that support them.
172 */
random_split_ec_verify(const u8 * sig,u8 siglen,const ec_pub_key * pub_key,const u8 * m,u32 mlen,ec_alg_type sig_type,hash_alg_type hash_type,const u8 * adata,u16 adata_len)173 ATTRIBUTE_WARN_UNUSED_RET static int random_split_ec_verify(const u8 *sig, u8 siglen, const ec_pub_key *pub_key,
174 const u8 *m, u32 mlen,
175 ec_alg_type sig_type, hash_alg_type hash_type, const u8 *adata, u16 adata_len)
176 {
177 int ret;
178 struct ec_verify_context ctx;
179 u32 consumed;
180
181 ret = local_memset(&ctx, 0, sizeof(ctx)); EG(ret, err);
182
183 ret = ec_verify_init(&ctx, pub_key, sig, siglen, sig_type, hash_type, adata, adata_len);
184 if (ret) {
185 goto err;
186 }
187
188 /* We randomly split the input message in chunks and proceed with updates */
189 consumed = 0;
190 while(consumed < mlen){
191 u32 toconsume = 0;
192 ret = get_random((u8 *)&toconsume, sizeof(toconsume));
193 if (ret) {
194 ext_printf("Error when getting random\n");
195 goto err;
196 }
197 toconsume = (toconsume % (mlen - consumed));
198 if(((mlen - consumed) == 1) && (toconsume == 0)){
199 toconsume = 1;
200 }
201 ret = ec_verify_update(&ctx, &m[consumed], toconsume);
202 if (ret) {
203 goto err;
204 }
205 consumed += toconsume;
206 }
207
208 ret = ec_verify_finalize(&ctx);
209
210 err:
211 return ret;
212 }
213
214
215 /* Reduce pressure on the stack for small targets
216 * by letting the user override this value.
217 */
218 #ifndef MAX_MSG_LEN
219 #if WORDSIZE == 16
220 /* For wordsize 16 bits, avoid overflows */
221 #define MAX_MSG_LEN 1024
222 #else
223 #define MAX_MSG_LEN 8192
224 #endif
225 #endif
226 #ifndef MAX_BATCH_SIG_SIZE
227 #define MAX_BATCH_SIG_SIZE 20
228 #endif
229
230 /*
231 * ECC generic self tests (sign/verify on random values
232 * with import/export)
233 */
ec_import_export_test(const ec_test_case * c)234 ATTRIBUTE_WARN_UNUSED_RET static int ec_import_export_test(const ec_test_case *c)
235 {
236 ec_key_pair kp;
237 ec_params params;
238 int ret, check;
239
240 MUST_HAVE(c != NULL, ret, err);
241
242 ret = local_memset(&kp, 0, sizeof(kp)); EG(ret, err);
243 ret = local_memset(¶ms, 0, sizeof(params)); EG(ret, err);
244
245 /* Import EC params from test case */
246 ret = import_params(¶ms, c->ec_str_p);
247 if (ret) {
248 ext_printf("Error importing params\n");
249 goto err;
250 }
251
252 /* Generate, import/export a key pair */
253 ret = ec_gen_import_export_kp(&kp, ¶ms, c);
254 if (ret) {
255 ext_printf("Error at key pair generation/import/export\n");
256 goto err;
257 }
258
259 /* Perform test */
260 {
261 u16 msglen;
262 u8 siglen;
263 u8 msg[MAX_MSG_LEN];
264 u8 sig[EC_MAX_SIGLEN];
265 u8 check_type = 0;
266 u8 sig_tmp1[EC_MAX_SIGLEN];
267 u8 sig_tmp2[EC_MAX_SIGLEN];
268 FORCE_USED_VAR(check_type);
269
270 ret = ec_get_sig_len(¶ms, c->sig_type, c->hash_type,
271 (u8 *)&siglen);
272 if (ret) {
273 ext_printf("Error computing effective sig size\n");
274 goto err;
275 }
276
277 /* Generate a random message to sign */
278 ret = get_random((u8 *)&msglen, sizeof(msglen));
279 if (ret) {
280 ext_printf("Error when getting random\n");
281 goto err;
282 }
283 msglen = msglen % MAX_MSG_LEN;
284 ret = get_random(msg, msglen);
285 if (ret) {
286 ext_printf("Error when getting random\n");
287 goto err;
288 }
289
290 ret = _ec_sign(sig, siglen, &kp, msg, msglen,
291 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len);
292 if (ret) {
293 ext_printf("Error when signing\n");
294 goto err;
295 }
296 ret = local_memset(sig_tmp1, 0, sizeof(sig_tmp1)); EG(ret, err);
297 ret = local_memset(sig_tmp2, 0, sizeof(sig_tmp2)); EG(ret, err);
298 /* If the algorithm supports streaming mode, test it against direct mode */
299 ret = is_sign_streaming_mode_supported(c->sig_type, &check); EG(ret, err);
300 if(check){
301 MUST_HAVE(siglen <= LOCAL_MAX(sizeof(sig_tmp1), sizeof(sig_tmp2)), ret, err);
302 ret = generic_ec_sign(sig_tmp1, siglen, &kp, msg, msglen,
303 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len);
304 if(ret){
305 ext_printf("Error when signing\n");
306 ret = -1;
307 goto err;
308 }
309 ret = random_split_ec_sign(sig_tmp2, siglen, &kp, msg, msglen,
310 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len);
311 if(ret){
312 ext_printf("Error when signing\n");
313 ret = -1;
314 goto err;
315 }
316 /* Verify signature equality only in case of deterministic signatures */
317 ret = is_sign_deterministic(c->sig_type, &check); EG(ret, err);
318 if(check){
319 ret = are_equal(sig, sig_tmp1, siglen, &check); EG(ret, err);
320 if(!check){
321 ext_printf("Error when signing: streaming and non streaming modes results differ "\
322 "for deterministic signature scheme!\n");
323 ret = -1;
324 goto err;
325 }
326 ret = are_equal(sig, sig_tmp2, siglen, &check); EG(ret, err);
327 if(!check){
328 ext_printf("Error when signing: streaming and non streaming modes results differ "\
329 "for deterministic signature scheme!\n");
330 ret = -1;
331 goto err;
332 }
333 }
334 }
335
336 ret = ec_verify(sig, siglen, &(kp.pub_key), msg, msglen,
337 c->sig_type, c->hash_type, c->adata, c->adata_len);
338 if (ret) {
339 ext_printf("Error when verifying signature\n");
340 goto err;
341 }
342 /* If the algorithm supports streaming mode, test it against direct mode */
343 ret = is_verify_streaming_mode_supported(c->sig_type, &check); EG(ret, err);
344 if(check){
345 ret = is_sign_streaming_mode_supported(c->sig_type, &check); EG(ret, err);
346 if(check){
347 ret = ec_verify(sig_tmp2, siglen, &(kp.pub_key), msg, msglen,
348 c->sig_type, c->hash_type, c->adata, c->adata_len);
349 }
350 else{
351 ret = ec_verify(sig, siglen, &(kp.pub_key), msg, msglen,
352 c->sig_type, c->hash_type, c->adata, c->adata_len);
353 }
354 if (ret) {
355 ext_printf("Error when verifying signature ec_verify\n");
356 goto err;
357 }
358 ret = is_sign_streaming_mode_supported(c->sig_type, &check); EG(ret, err);
359 if(check){
360 ret = random_split_ec_verify(sig_tmp1, siglen, &(kp.pub_key), msg, msglen,
361 c->sig_type, c->hash_type, c->adata, c->adata_len);
362 }
363 else{
364 ret = random_split_ec_verify(sig, siglen, &(kp.pub_key), msg, msglen,
365 c->sig_type, c->hash_type, c->adata, c->adata_len);
366 }
367 if (ret) {
368 ext_printf("Error when verifying signature random_split_ec_verify\n");
369 goto err;
370 }
371 }
372 /* Also test the "single" signature batch verification */
373 ret = is_verify_batch_mode_supported(c->sig_type, &check); EG(ret, err);
374 if(check){
375 const u8 *signatures[] = { sig };
376 const u8 signatures_len[] = { siglen };
377 const u8 *messages[] = { msg };
378 const u32 messages_len[] = { msglen };
379 const ec_pub_key *pub_keys[] = { &(kp.pub_key) };
380 const u8 *adatas[] = { c->adata };
381 const u16 adatas_len[] = { c->adata_len };
382 ret = ec_verify_batch(signatures, signatures_len, pub_keys, messages, messages_len,
383 1, c->sig_type, c->hash_type, adatas, adatas_len, NULL, NULL);
384 if(ret){
385 ext_printf("Error when verifying signature ec_verify_batch with batch 1\n");
386 goto err;
387 }
388 }
389 check_type = 0;
390 #if defined(WITH_SIG_ECDSA)
391 if(c->sig_type == ECDSA){
392 check_type = 1;
393 }
394 #endif
395 #if defined(WITH_SIG_DECDSA)
396 if(c->sig_type == DECDSA){
397 check_type = 1;
398 }
399 #endif
400 /* Try a public key recovery from the signature and the message.
401 * This is only possible for ECDSA.
402 */
403 if(check_type){
404 struct ec_sign_context sig_ctx;
405 u8 digest[MAX_DIGEST_SIZE] = { 0 };
406 u8 digestlen;
407 ec_pub_key pub_key1;
408 ec_pub_key pub_key2;
409 nn_src_t cofactor = &(params.ec_gen_cofactor);
410 int cofactorisone;
411 const u8 *input[2] = { (const u8*)msg , NULL};
412 u32 ilens[2] = { msglen , 0 };
413 /* Initialize our signature context only for the hash */
414 ret = ec_sign_init(&sig_ctx, &kp, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err);
415 /* Perform the hash of the data ourselves */
416 ret = hash_mapping_callbacks_sanity_check(sig_ctx.h); EG(ret, err);
417 ret = sig_ctx.h->hfunc_scattered(input, ilens, digest); EG(ret, err);
418 digestlen = sig_ctx.h->digest_size;
419 MUST_HAVE(digestlen <= sizeof(digest), ret, err);
420 /* Check the cofactor */
421 ret = nn_isone(cofactor, &cofactorisone); EG(ret, err);
422 /* Compute the two possible public keys */
423 ret = __ecdsa_public_key_from_sig(&pub_key1, &pub_key2, ¶ms, sig, siglen, digest, digestlen, c->sig_type);
424 if(ret){
425 ret = 0;
426 check = -1;
427 goto pubkey_recovery_warning;
428 }
429 /* Check equality with one of the two keys */
430 ret = prj_pt_cmp(&(pub_key1.y), &(kp.pub_key.y), &check); EG(ret, err);
431 if(check){
432 ret = prj_pt_cmp(&(pub_key2.y), &(kp.pub_key.y), &check); EG(ret, err);
433 }
434 pubkey_recovery_warning:
435 if(check && cofactorisone){
436 OPENMP_LOCK();
437 ext_printf("[~] Warning: ECDSA recovered public key differs from real one ...");
438 ext_printf("This can happen with very low probability. Please check the trace:\n");
439 pub_key_print("pub_key1", &pub_key1);
440 pub_key_print("pub_key2", &pub_key2);
441 pub_key_print("pub_key", &(kp.pub_key));
442 buf_print("digest", digest, digestlen);
443 buf_print("sig", sig, siglen);
444 OPENMP_UNLOCK();
445 }
446 }
447 #ifdef USE_CRYPTOFUZZ
448 check_type = 0;
449 /* Specific case where we have access to raw signature API */
450 #if defined(WITH_SIG_ECDSA)
451 if(c->sig_type == ECDSA){
452 check_type = 1;
453 }
454 #endif
455 #if defined(WITH_SIG_ECGDSA)
456 if(c->sig_type == ECGDSA){
457 check_type = 1;
458 }
459 #endif
460 #if defined(WITH_SIG_ECRDSA)
461 if(c->sig_type == ECRDSA){
462 check_type = 1;
463 }
464 #endif
465 if(check_type){
466 struct ec_sign_context sig_ctx;
467 struct ec_verify_context verif_ctx;
468 u8 digest[MAX_DIGEST_SIZE] = { 0 };
469 u8 digestlen;
470 const u8 *input[2] = { (const u8*)msg , NULL};
471 u32 ilens[2] = { msglen , 0 };
472 /* Initialize our signature context */
473 ret = ec_sign_init(&sig_ctx, &kp, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err);
474 /* Perform the hash of the data ourselves */
475 ret = hash_mapping_callbacks_sanity_check(sig_ctx.h); EG(ret, err);
476 ret = sig_ctx.h->hfunc_scattered(input, ilens, digest); EG(ret, err);
477 digestlen = sig_ctx.h->digest_size;
478 MUST_HAVE(digestlen <= sizeof(digest), ret, err);
479 /* Raw signing of data */
480 #if defined(WITH_SIG_ECDSA)
481 if(c->sig_type == ECDSA){
482 ret = ecdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, NULL, 0); EG(ret, err);
483 }
484 #endif
485 #if defined(WITH_SIG_ECGDSA)
486 if(c->sig_type == ECGDSA){
487 ret = ecgdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, NULL, 0); EG(ret, err);
488 }
489 #endif
490 #if defined(WITH_SIG_ECRDSA)
491 if(c->sig_type == ECRDSA){
492 ret = ecrdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, NULL, 0); EG(ret, err);
493 }
494 #endif
495 /* Now verify signature */
496 ret = ec_verify_init(&verif_ctx, &(kp.pub_key), sig, siglen, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err);
497 #if defined(WITH_SIG_ECDSA)
498 if(c->sig_type == ECDSA){
499 ret = ecdsa_verify_raw(&verif_ctx, digest, digestlen); EG(ret, err);
500 }
501 #endif
502 #if defined(WITH_SIG_ECGDSA)
503 if(c->sig_type == ECGDSA){
504 ret = ecgdsa_verify_raw(&verif_ctx, digest, digestlen); EG(ret, err);
505 }
506 #endif
507 #if defined(WITH_SIG_ECRDSA)
508 if(c->sig_type == ECRDSA){
509 ret = ecrdsa_verify_raw(&verif_ctx, digest, digestlen); EG(ret, err);
510 }
511 #endif
512 }
513 #endif
514 }
515
516 /* Perform test specific to batch verification */
517 ret = is_verify_batch_mode_supported(c->sig_type, &check); EG(ret, err);
518 if(check){
519 u16 msglen;
520 u8 siglen;
521 ec_key_pair keypairs[MAX_BATCH_SIG_SIZE];
522 const ec_pub_key *pubkeys[MAX_BATCH_SIG_SIZE];
523 u8 msg[MAX_BATCH_SIG_SIZE * MAX_MSG_LEN];
524 const u8 *messages[MAX_BATCH_SIG_SIZE];
525 u32 messages_len[MAX_BATCH_SIG_SIZE];
526 u8 sig[MAX_BATCH_SIG_SIZE * EC_MAX_SIGLEN];
527 const u8 *signatures[MAX_BATCH_SIG_SIZE];
528 u8 signatures_len[MAX_BATCH_SIG_SIZE];
529 const u8 *adata[MAX_BATCH_SIG_SIZE];
530 u16 adata_len[MAX_BATCH_SIG_SIZE];
531 u8 check_type = 0;
532 u32 num_batch, i, current;
533
534 FORCE_USED_VAR(check_type);
535
536 gen_num_batch:
537 ret = get_random((u8 *)&num_batch, sizeof(num_batch));
538 if(ret){
539 ext_printf("Error when getting random\n");
540 goto err;
541 }
542 num_batch = (num_batch % MAX_BATCH_SIG_SIZE);
543 if(num_batch == 0){
544 goto gen_num_batch;
545 }
546
547 ret = ec_get_sig_len(¶ms, c->sig_type, c->hash_type,
548 (u8 *)&siglen);
549 if (ret) {
550 ext_printf("Error computing effective sig size\n");
551 goto err;
552 }
553
554 /* Generate random messages to sign */
555 current = 0;
556 for(i = 0; i < num_batch; i++){
557 /* Generate, import/export a key pair */
558 ret = ec_gen_import_export_kp(&keypairs[i], ¶ms, c);
559 pubkeys[i] = &(keypairs[i].pub_key);
560 if (ret) {
561 ext_printf("Error at key pair generation/import/export\n");
562 goto err;
563 }
564 ret = get_random((u8 *)&msglen, sizeof(msglen));
565 if (ret) {
566 ext_printf("Error when getting random\n");
567 goto err;
568 }
569 msglen = msglen % MAX_MSG_LEN;
570 messages_len[i] = msglen;
571 messages[i] = &msg[current];
572 ret = get_random(&msg[current], msglen);
573 if (ret) {
574 ext_printf("Error when getting random\n");
575 goto err;
576 }
577 current += msglen;
578
579 signatures[i] = &sig[i * siglen];
580 signatures_len[i] = siglen;
581 adata_len[i] = c->adata_len;
582 adata[i] = c->adata;
583 ret = _ec_sign(&sig[i * siglen], siglen, &keypairs[i], messages[i], messages_len[i],
584 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len);
585 if (ret) {
586 ext_printf("Error when signing\n");
587 goto err;
588 }
589 }
590 /* Test */
591 ret = ec_verify_batch(signatures, signatures_len, pubkeys, messages, messages_len,
592 num_batch, c->sig_type, c->hash_type, adata, adata_len, NULL, NULL);
593 if(ret){
594 ext_printf("Error when verifying signature ec_verify_batch no memory for batch size %" PRIu32 "\n", num_batch);
595 goto err;
596 }
597 {
598 u32 scratch_pad_area_len = 0;
599 /* We need 2 * n + 1 scratch pad storage, compute this with max */
600 verify_batch_scratch_pad scratch_pad_area[(2 * MAX_BATCH_SIG_SIZE) + 1];
601
602 ret = ec_verify_batch(signatures, signatures_len, pubkeys, messages, messages_len,
603 num_batch, c->sig_type, c->hash_type, adata, adata_len, NULL, &scratch_pad_area_len);
604 if(ret){
605 ext_printf("Error when getting scratch_pad_area length for ec_verify_batch optimized for batch size %" PRIu32 "\n", num_batch);
606 goto err;
607 }
608 MUST_HAVE((scratch_pad_area_len <= sizeof(scratch_pad_area)), ret, err);
609
610 scratch_pad_area_len = sizeof(scratch_pad_area);
611 ret = ec_verify_batch(signatures, signatures_len, pubkeys, messages, messages_len,
612 num_batch, c->sig_type, c->hash_type, adata, adata_len, scratch_pad_area, &scratch_pad_area_len);
613 if(ret){
614 ext_printf("Error when verifying signature ec_verify_batch optimized for batch size %" PRIu32 "\n", num_batch);
615 goto err;
616 }
617 }
618 }
619
620 ret = 0;
621
622 err:
623 return ret;
624 }
625
626 /*
627 * Those functions respectively perform signature and verification tests
628 * based the content of a given test case.
629 */
ec_test_sign(u8 * sig,u8 siglen,ec_key_pair * kp,const ec_test_case * c)630 ATTRIBUTE_WARN_UNUSED_RET static int ec_test_sign(u8 *sig, u8 siglen, ec_key_pair *kp,
631 const ec_test_case *c)
632 {
633 /* If the algorithm supports streaming, we check that both the streaming and
634 * non streaming modes produce the same result.
635 */
636 int ret, check;
637
638 MUST_HAVE(sig != NULL, ret, err);
639 MUST_HAVE(c != NULL, ret, err);
640
641 ret = _ec_sign(sig, siglen, kp, (const u8 *)(c->msg), c->msglen,
642 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err);
643 ret = is_sign_streaming_mode_supported(c->sig_type, &check); EG(ret, err);
644 if(check){
645 u8 sig_tmp[EC_MAX_SIGLEN];
646 MUST_HAVE(siglen <= sizeof(sig_tmp), ret, err);
647 ret = generic_ec_sign(sig_tmp, siglen, kp, (const u8 *)(c->msg), c->msglen,
648 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err);
649 ret = are_equal(sig, sig_tmp, siglen, &check); EG(ret, err);
650 if(!check){
651 ret = -1;
652 goto err;
653 }
654 /* Now test the random split version */
655 ret = random_split_ec_sign(sig_tmp, siglen, kp, (const u8 *)(c->msg), c->msglen,
656 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err);
657 ret = are_equal(sig, sig_tmp, siglen, &check); EG(ret, err);
658 if(!check){
659 ret = -1;
660 goto err;
661 }
662 }
663
664 ret = 0;
665 err:
666 return ret;
667 }
668
ec_test_verify(u8 * sig,u8 siglen,const ec_pub_key * pub_key,const ec_test_case * c)669 ATTRIBUTE_WARN_UNUSED_RET static int ec_test_verify(u8 *sig, u8 siglen, const ec_pub_key *pub_key,
670 const ec_test_case *c)
671 {
672 /* If the algorithm supports streaming, we check that both the streaming and
673 * non streaming modes produce the same result.
674 */
675 int ret, check;
676
677 MUST_HAVE(sig != NULL, ret, err);
678 MUST_HAVE(c != NULL, ret, err);
679
680 ret = ec_verify(sig, siglen, pub_key, (const u8 *)(c->msg), c->msglen,
681 c->sig_type, c->hash_type, c->adata, c->adata_len);
682 if(ret){
683 ret = -1;
684 goto err;
685 }
686 ret = is_verify_streaming_mode_supported(c->sig_type, &check); EG(ret, err);
687 if(check){
688 ret = ec_verify(sig, siglen, pub_key, (const u8 *)(c->msg), c->msglen,
689 c->sig_type, c->hash_type, c->adata, c->adata_len);
690 if(ret){
691 ret = -1;
692 goto err;
693 }
694 /* Now test the random split version */
695 ret = random_split_ec_verify(sig, siglen, pub_key, (const u8 *)(c->msg), c->msglen,
696 c->sig_type, c->hash_type, c->adata, c->adata_len);
697 if(ret){
698 ret = -1;
699 goto err;
700 }
701 }
702 /* Also test the "single" signature batch verification */
703 ret = is_verify_batch_mode_supported(c->sig_type, &check); EG(ret, err);
704 if(check){
705 const u8 *signatures[] = { sig };
706 const u8 signatures_len[] = { siglen };
707 const u8 *messages[] = { (const u8*)c->msg };
708 const u32 messages_len[] = { c->msglen };
709 const ec_pub_key *pub_keys[] = { pub_key };
710 const u8 *adatas[] = { c->adata };
711 const u16 adatas_len[] = { c->adata_len };
712 ret = ec_verify_batch(signatures, signatures_len, pub_keys, messages, messages_len,
713 1, c->sig_type, c->hash_type, adatas, adatas_len, NULL, NULL);
714 if(ret){
715 ret = -1;
716 goto err;
717 }
718 }
719
720 ret = 0;
721 err:
722 return ret;
723 }
724
725 /*
726 * ECC generic self tests (sign/verify on known test vectors). Returns
727 * 0 if given test succeeded, or a non-zero value otherwise. In that
728 * case, the value encodes the information on what went wrong as
729 * described above.
730 */
ec_sig_known_vector_tests_one(const ec_test_case * c)731 ATTRIBUTE_WARN_UNUSED_RET static int ec_sig_known_vector_tests_one(const ec_test_case *c)
732 {
733 test_err_kind failed_test = TEST_KEY_IMPORT_ERROR;
734 u8 sig[EC_MAX_SIGLEN];
735 ec_params params;
736 ec_key_pair kp;
737 u8 siglen;
738 int ret;
739 int check = 0;
740
741 MUST_HAVE((c != NULL), ret, err);
742
743 ret = local_memset(&kp, 0, sizeof(kp)); EG(ret, err);
744 ret = local_memset(¶ms, 0, sizeof(params)); EG(ret, err);
745 ret = local_memset(sig, 0, sizeof(sig)); EG(ret, err);
746
747 ret = import_params(¶ms, c->ec_str_p);
748 if (ret) {
749 ext_printf("Error importing params\n");
750 goto err;
751 }
752
753 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448)
754 /* In the specific case of EdDSA, we perform a specific key derivation */
755 #if defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_EDDSA448)
756 if((c->sig_type == EDDSA25519) || (c->sig_type == EDDSA25519CTX) || (c->sig_type == EDDSA25519PH) || \
757 (c->sig_type == EDDSA448) || (c->sig_type == EDDSA448PH)){
758 #endif
759 #if defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_EDDSA448)
760 if((c->sig_type == EDDSA25519) || (c->sig_type == EDDSA25519CTX) || (c->sig_type == EDDSA25519PH)){
761 #endif
762 #if !defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_EDDSA448)
763 if((c->sig_type == EDDSA448) || (c->sig_type == EDDSA448PH)){
764 #endif
765 /* Import the key pair using the EdDSA dedicated function */
766 if(eddsa_import_key_pair_from_priv_key_buf(&kp, c->priv_key, c->priv_key_len, ¶ms, c->sig_type)){
767 ret = -1;
768 failed_test = TEST_KEY_IMPORT_ERROR;
769 goto err;
770 }
771 }
772 else
773 #endif /* !(defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448)) */
774 {
775 /* Regular import if not EdDSA */
776 ret = ec_key_pair_import_from_priv_key_buf(&kp, ¶ms, c->priv_key,
777 c->priv_key_len,
778 c->sig_type);
779 if (ret) {
780 failed_test = TEST_KEY_IMPORT_ERROR;
781 goto err;
782 }
783 }
784
785 siglen = c->exp_siglen;
786 ret = ec_test_sign(sig, siglen, &kp, c);
787 if (ret) {
788 failed_test = TEST_SIG_ERROR;
789 goto err;
790 }
791
792 ret = are_equal(sig, c->exp_sig, siglen, &check); EG(ret, err);
793 if (!check) {
794 ret = -1;
795 failed_test = TEST_SIG_COMP_ERROR;
796 goto err;
797 }
798
799 ret = ec_test_verify(sig, siglen, &(kp.pub_key), c);
800 if (ret) {
801 failed_test = TEST_VERIF_ERROR;
802 goto err;
803 }
804
805 check = 0;
806 #if defined(WITH_SIG_ECDSA)
807 if(c->sig_type == ECDSA){
808 check = 1;
809 }
810 #endif
811 #if defined(WITH_SIG_DECDSA)
812 if(c->sig_type == DECDSA){
813 check = 1;
814 }
815 #endif
816 /* Try a public key recovery from the signature and the message.
817 * This is only possible for ECDSA.
818 */
819 if(check){
820 struct ec_sign_context sig_ctx;
821 u8 digest[MAX_DIGEST_SIZE] = { 0 };
822 u8 digestlen;
823 ec_pub_key pub_key1;
824 ec_pub_key pub_key2;
825 nn_src_t cofactor = &(params.ec_gen_cofactor);
826 int cofactorisone;
827 const u8 *input[2] = { (const u8*)(c->msg) , NULL};
828 u32 ilens[2] = { c->msglen , 0 };
829 /* Initialize our signature context only for the hash */
830 ret = ec_sign_init(&sig_ctx, &kp, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err);
831 /* Perform the hash of the data ourselves */
832 ret = hash_mapping_callbacks_sanity_check(sig_ctx.h); EG(ret, err);
833 ret = sig_ctx.h->hfunc_scattered(input, ilens, digest); EG(ret, err);
834 digestlen = sig_ctx.h->digest_size;
835 MUST_HAVE(digestlen <= sizeof(digest), ret, err);
836 /* Check the cofactor */
837 ret = nn_isone(cofactor, &cofactorisone); EG(ret, err);
838 /* Compute the two possible public keys */
839 ret = __ecdsa_public_key_from_sig(&pub_key1, &pub_key2, ¶ms, sig, siglen, digest, digestlen, c->sig_type);
840 if(ret){
841 ret = 0;
842 check = -1;
843 goto pubkey_recovery_warning;
844 }
845 /* Check equality with one of the two keys */
846 ret = prj_pt_cmp(&(pub_key1.y), &(kp.pub_key.y), &check); EG(ret, err);
847 if(check){
848 ret = prj_pt_cmp(&(pub_key2.y), &(kp.pub_key.y), &check); EG(ret, err);
849 }
850 pubkey_recovery_warning:
851 if(check && cofactorisone){
852 OPENMP_LOCK();
853 ext_printf("[~] Warning: ECDSA recovered public key differs from real one ...");
854 ext_printf("This can happen with very low probability. Please check the trace:\n");
855 pub_key_print("pub_key1", &pub_key1);
856 pub_key_print("pub_key2", &pub_key2);
857 pub_key_print("pub_key", &(kp.pub_key));
858 buf_print("digest", digest, digestlen);
859 buf_print("sig", sig, siglen);
860 OPENMP_UNLOCK();
861 }
862 }
863 #ifdef USE_CRYPTOFUZZ
864 check = 0;
865 /* Specific case where we have access to raw signature API */
866 #if defined(WITH_SIG_ECDSA)
867 if(c->sig_type == ECDSA){
868 check = 1;
869 }
870 #endif
871 #if defined(WITH_SIG_ECGDSA)
872 if(c->sig_type == ECGDSA){
873 check = 1;
874 }
875 #endif
876 #if defined(WITH_SIG_ECRDSA)
877 if(c->sig_type == ECRDSA){
878 check = 1;
879 }
880 #endif
881 /* Specific case where we have access to raw signature API */
882 if(check){
883 struct ec_sign_context sig_ctx;
884 struct ec_verify_context verif_ctx;
885 u8 digest[MAX_DIGEST_SIZE] = { 0 };
886 u8 digestlen;
887 const u8 *input[2] = { (const u8*)(c->msg) , NULL};
888 u32 ilens[2] = { c->msglen , 0 };
889 u8 nonce[LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8))] = { 0 };
890 nn n_nonce;
891 bitcnt_t q_bit_len;
892 u8 noncelen;
893 /* Initialize our signature context */
894 if(ec_sign_init(&sig_ctx, &kp, c->sig_type, c->hash_type, c->adata, c->adata_len)){
895 ret = -1;
896 failed_test = TEST_SIG_ERROR;
897 goto err;
898 }
899 /* Perform the hash of the data ourselves */
900 if(hash_mapping_callbacks_sanity_check(sig_ctx.h)){
901 ret = -1;
902 failed_test = TEST_SIG_ERROR;
903 goto err;
904 }
905 ret = sig_ctx.h->hfunc_scattered(input, ilens, digest); EG(ret, err);
906 digestlen = sig_ctx.h->digest_size;
907 MUST_HAVE(digestlen <= sizeof(digest), ret, err);
908 /* Import the fixed nonce */
909 q_bit_len = kp.priv_key.params->ec_gen_order_bitlen;
910 if(c->nn_random(&n_nonce, &(kp.priv_key.params->ec_gen_order))){
911 ret = -1;
912 failed_test = TEST_SIG_ERROR;
913 goto err;
914 }
915 ret = nn_export_to_buf(nonce, (u16)BYTECEIL(q_bit_len), &n_nonce); EG(ret, err);
916 if((unsigned int)BYTECEIL(q_bit_len) > sizeof(nonce)){
917 ret = -1;
918 failed_test = TEST_SIG_ERROR;
919 goto err;
920 }
921 noncelen = (u8)(BYTECEIL(q_bit_len));
922 /* Force used variable to avoid warnings */
923 FORCE_USED_VAR(noncelen);
924 /* NOTE: the MUST_HAVE is protected by a preprocessing check
925 * to avoid -Werror=type-limits errors:
926 * "error: comparison is always true due to limited range of data type"
927 */
928 #if LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8)) < 255
929 MUST_HAVE((u32)noncelen <= sizeof(nonce), ret, err);
930 #endif
931 /* Raw signing of data */
932 #if defined(WITH_SIG_ECDSA)
933 if(c->sig_type == ECDSA){
934 if(ecdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, nonce, noncelen)){
935 ret = -1;
936 failed_test = TEST_SIG_ERROR;
937 goto err;
938 }
939 }
940 #endif
941 #if defined(WITH_SIG_ECGDSA)
942 if(c->sig_type == ECGDSA){
943 if(ecgdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, nonce, noncelen)){
944 ret = -1;
945 failed_test = TEST_SIG_ERROR;
946 goto err;
947 }
948 }
949 #endif
950 #if defined(WITH_SIG_ECRDSA)
951 if(c->sig_type == ECRDSA){
952 if(ecrdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, nonce, noncelen)){
953 ret = -1;
954 failed_test = TEST_SIG_ERROR;
955 goto err;
956 }
957 }
958 #endif
959 /* Check computed signature against expected one */
960 ret = are_equal(sig, c->exp_sig, siglen, &check); EG(ret, err);
961 if (!check) {
962 failed_test = TEST_SIG_COMP_ERROR;
963 ret = -1;
964 goto err;
965 }
966 /* Now verify signature */
967 if(ec_verify_init(&verif_ctx, &(kp.pub_key), sig, siglen, c->sig_type, c->hash_type, c->adata, c->adata_len)){
968 ret = -1;
969 failed_test = TEST_VERIF_ERROR;
970 goto err;
971 }
972 /* Raw verification of data */
973 #if defined(WITH_SIG_ECDSA)
974 if(c->sig_type == ECDSA){
975 if(ecdsa_verify_raw(&verif_ctx, digest, digestlen)){
976 ret = -1;
977 failed_test = TEST_VERIF_ERROR;
978 goto err;
979 }
980 }
981 #endif
982 #if defined(WITH_SIG_ECGDSA)
983 if(c->sig_type == ECGDSA){
984 if(ecgdsa_verify_raw(&verif_ctx, digest, digestlen)){
985 ret = -1;
986 failed_test = TEST_VERIF_ERROR;
987 goto err;
988 }
989 }
990 #endif
991 #if defined(WITH_SIG_ECRDSA)
992 if(c->sig_type == ECRDSA){
993 if(ecrdsa_verify_raw(&verif_ctx, digest, digestlen)){
994 ret = -1;
995 failed_test = TEST_VERIF_ERROR;
996 goto err;
997 }
998 }
999 #endif
1000 }
1001 #endif
1002 ret = 0;
1003
1004 err:
1005 if (ret) {
1006 u32 ret_;
1007 ret = encode_error_value(c, failed_test, &ret_); EG(ret, err);
1008 ret = (int)ret_;
1009 }
1010
1011 return ret;
1012 }
1013
1014 #if defined(WITH_ECCCDH) || defined(WITH_X25519) || defined(WITH_X448)
1015 /*
1016 * ECC generic self tests (ecdh on known test vectors). Returns
1017 * 0 if given test succeeded, or a non-zero value otherwise. In that
1018 * case, the value encodes the information on what went wrong as
1019 * described above.
1020 */
1021 ATTRIBUTE_WARN_UNUSED_RET static int ecdh_known_vector_tests_one(const ecdh_test_case *c)
1022 {
1023 test_err_kind failed_test = TEST_KEY_IMPORT_ERROR;
1024 ec_params params;
1025 ec_key_pair kp;
1026 int ret, check;
1027
1028 MUST_HAVE((c != NULL), ret, err);
1029
1030 ret = local_memset(&kp, 0, sizeof(kp)); EG(ret, err);
1031 ret = local_memset(¶ms, 0, sizeof(params)); EG(ret, err);
1032
1033 ret = import_params(¶ms, c->ec_str_p);
1034 if (ret) {
1035 ext_printf("Error importing params\n");
1036 goto err;
1037 }
1038
1039 /* Check what ECDH test we have to perform */
1040 switch(c->ecdh_type){
1041 #if defined(WITH_ECCCDH)
1042 case ECCCDH:{
1043 u8 serialized_pub_key[EC_PUB_KEY_MAX_SIZE];
1044 u8 serialized_pub_key_len;
1045 /* This maximum size is way bigger than expected, but we ensure
1046 * that there is enough room for our shared secret.
1047 */
1048 u8 shared_secret[EC_PUB_KEY_MAX_SIZE];
1049 u8 shared_secret_len;
1050
1051 ret = local_memset(serialized_pub_key, 0, sizeof(serialized_pub_key)); EG(ret, err);
1052 ret = local_memset(shared_secret, 0, sizeof(shared_secret)); EG(ret, err);
1053
1054 /* Import our ECDH key pair */
1055 ret = ecccdh_import_key_pair_from_priv_key_buf(&kp, ¶ms, c->our_priv_key,
1056 c->our_priv_key_len);
1057 if (ret) {
1058 failed_test = TEST_KEY_IMPORT_ERROR;
1059 ret = -1;
1060 goto err;
1061 }
1062 /* Serialize our public key */
1063 ret = ecccdh_serialized_pub_key_size(¶ms, &serialized_pub_key_len); EG(ret, err);
1064 MUST_HAVE((sizeof(serialized_pub_key) >= serialized_pub_key_len), ret, err);
1065 ret = ecccdh_serialize_pub_key(&(kp.pub_key), serialized_pub_key, serialized_pub_key_len);
1066 if (ret) {
1067 failed_test = TEST_ECDH_ERROR;
1068 ret = -1;
1069 goto err;
1070 }
1071 /* Check it against the expected one */
1072 MUST_HAVE((serialized_pub_key_len == c->exp_our_pub_key_len), ret, err);
1073 ret = are_equal(serialized_pub_key, c->exp_our_pub_key, serialized_pub_key_len, &check); EG(ret, err);
1074 if (!check) {
1075 failed_test = TEST_ECDH_COMP_ERROR;
1076 ret = -1;
1077 goto err;
1078 }
1079 /* Now derive the shared secret */
1080 ret = ecccdh_shared_secret_size(¶ms, &shared_secret_len); EG(ret, err);
1081 MUST_HAVE((sizeof(shared_secret) >= shared_secret_len), ret, err);
1082 ret = ecccdh_derive_secret(&(kp.priv_key), c->peer_pub_key, c->peer_pub_key_len, shared_secret, shared_secret_len);
1083 if (ret) {
1084 failed_test = TEST_ECDH_ERROR;
1085 ret = -1;
1086 goto err;
1087 }
1088 /* Check it against the expected one */
1089 MUST_HAVE((shared_secret_len == c->exp_shared_secret_len), ret, err);
1090 ret = are_equal(shared_secret, c->exp_shared_secret, shared_secret_len, &check); EG(ret, err);
1091 if (!check) {
1092 failed_test = TEST_ECDH_COMP_ERROR;
1093 ret = -1;
1094 goto err;
1095 }
1096
1097 break;
1098 }
1099 #endif
1100 #if defined(WITH_X25519)
1101 case X25519:{
1102 u8 pub_key[X25519_SIZE];
1103 u8 shared_secret[X25519_SIZE];
1104
1105 ret = local_memset(pub_key, 0, sizeof(pub_key)); EG(ret, err);
1106 ret = local_memset(shared_secret, 0, sizeof(shared_secret)); EG(ret, err);
1107
1108 /* Compute our public key */
1109 MUST_HAVE((c->our_priv_key_len == X25519_SIZE), ret, err);
1110 ret = x25519_init_pub_key(c->our_priv_key, pub_key);
1111 if (ret) {
1112 failed_test = TEST_KEY_IMPORT_ERROR;
1113 ret = -1;
1114 goto err;
1115 }
1116 /* Check it against the expected one */
1117 MUST_HAVE((c->exp_our_pub_key_len == X25519_SIZE), ret, err);
1118 ret = are_equal(pub_key, c->exp_our_pub_key, X25519_SIZE, &check); EG(ret, err);
1119 if (!check) {
1120 failed_test = TEST_ECDH_COMP_ERROR;
1121 ret = -1;
1122 goto err;
1123 }
1124 /* Now derive the shared secret */
1125 MUST_HAVE((c->peer_pub_key_len == X25519_SIZE), ret, err);
1126 ret = x25519_derive_secret(c->our_priv_key, c->peer_pub_key, shared_secret);
1127 if (ret) {
1128 failed_test = TEST_ECDH_ERROR;
1129 ret = -1;
1130 goto err;
1131 }
1132 /* Check it against the expected one */
1133 MUST_HAVE((c->exp_shared_secret_len == X25519_SIZE), ret, err);
1134 ret = are_equal(shared_secret, c->exp_shared_secret, X25519_SIZE, &check); EG(ret, err);
1135 if (!check) {
1136 failed_test = TEST_ECDH_COMP_ERROR;
1137 ret = -1;
1138 goto err;
1139 }
1140
1141 break;
1142 }
1143 #endif
1144 #if defined(WITH_X448)
1145 case X448:{
1146 u8 pub_key[X448_SIZE];
1147 u8 shared_secret[X448_SIZE];
1148
1149 ret = local_memset(pub_key, 0, sizeof(pub_key)); EG(ret, err);
1150 ret = local_memset(shared_secret, 0, sizeof(shared_secret)); EG(ret, err);
1151
1152 /* Compute our public key */
1153 MUST_HAVE((c->our_priv_key_len == X448_SIZE), ret, err);
1154 ret = x448_init_pub_key(c->our_priv_key, pub_key);
1155 if (ret) {
1156 failed_test = TEST_KEY_IMPORT_ERROR;
1157 ret = -1;
1158 goto err;
1159 }
1160 /* Check it against the expected one */
1161 MUST_HAVE((c->exp_our_pub_key_len == X448_SIZE), ret, err);
1162 ret = are_equal(pub_key, c->exp_our_pub_key, X448_SIZE, &check); EG(ret, err);
1163 if (!check) {
1164 failed_test = TEST_ECDH_COMP_ERROR;
1165 ret = -1;
1166 goto err;
1167 }
1168 /* Now derive the shared secret */
1169 MUST_HAVE((c->peer_pub_key_len == X448_SIZE), ret, err);
1170 ret = x448_derive_secret(c->our_priv_key, c->peer_pub_key, shared_secret);
1171 if (ret) {
1172 failed_test = TEST_ECDH_ERROR;
1173 ret = -1;
1174 goto err;
1175 }
1176 /* Check it against the expected one */
1177 MUST_HAVE((c->exp_shared_secret_len == X448_SIZE), ret, err);
1178 ret = are_equal(shared_secret, c->exp_shared_secret, X448_SIZE, &check); EG(ret, err);
1179 if (!check) {
1180 failed_test = TEST_ECDH_COMP_ERROR;
1181 ret = -1;
1182 goto err;
1183 }
1184
1185 break;
1186 }
1187 #endif
1188 default:{
1189 ext_printf("Error: not an ECDH test\n");
1190 ret = -1;
1191 goto err;
1192 }
1193 }
1194
1195 err:
1196 if (ret) {
1197 u32 ret_;
1198 ret = ecdh_encode_error_value(c, failed_test, &ret_); EG(ret, err);
1199 ret = (int)ret_;
1200 }
1201
1202 return ret;
1203 }
1204 #endif
1205
1206 ATTRIBUTE_WARN_UNUSED_RET int perform_known_test_vectors_test(const char *sig, const char *hash, const char *curve)
1207 {
1208 unsigned int i;
1209 int ret = 0;
1210
1211 ext_printf("======= Known test vectors test =================\n");
1212 #ifdef WITH_OPENMP_SELF_TESTS
1213 #pragma omp parallel
1214 #pragma omp for schedule(static, 1) nowait
1215 #endif
1216 for (i = 0; i < EC_FIXED_VECTOR_NUM_TESTS; i++) {
1217 int check;
1218 const ec_test_case *cur_test;
1219 cur_test = ec_fixed_vector_tests[i];
1220 if(cur_test == NULL){
1221 continue;
1222 }
1223 /* If this is a dummy test case, skip it! */
1224 if(cur_test->sig_type == UNKNOWN_ALG){
1225 continue;
1226 }
1227 /* Filter out */
1228 if(sig != NULL){
1229 const ec_sig_mapping *sig_map;
1230 ret = get_sig_by_type(cur_test->sig_type, &sig_map); OPENMP_EG(ret, err);
1231 if(sig_map == NULL){
1232 continue;
1233 }
1234 ret = are_str_equal(sig_map->name, sig, &check); OPENMP_EG(ret, err);
1235 if(!check){
1236 continue;
1237 }
1238 }
1239 if(hash != NULL){
1240 const hash_mapping *hash_map;
1241 ret = get_hash_by_type(cur_test->hash_type, &hash_map); OPENMP_EG(ret, err);
1242 if(hash_map == NULL){
1243 continue;
1244 }
1245 ret = are_str_equal(hash_map->name, hash, &check); OPENMP_EG(ret, err);
1246 if(!check){
1247 continue;
1248 }
1249 }
1250 if(curve != NULL){
1251 if(cur_test->ec_str_p == NULL){
1252 continue;
1253 }
1254 ret = are_str_equal((const char*)cur_test->ec_str_p->name->buf, curve, &check); OPENMP_EG(ret, err);
1255 if(!check){
1256 continue;
1257 }
1258 }
1259 ret = ec_sig_known_vector_tests_one(cur_test);
1260 OPENMP_LOCK();
1261 ext_printf("[%s] %30s selftests: known test vectors "
1262 "sig/verif %s\n", ret ? "-" : "+",
1263 cur_test->name, ret ? "failed" : "ok");
1264 check = 0;
1265 #if defined(WITH_SIG_ECDSA)
1266 if(cur_test->sig_type == ECDSA){
1267 check = 1;
1268 }
1269 #endif
1270 #if defined(WITH_SIG_DECDSA)
1271 if(cur_test->sig_type == DECDSA){
1272 check = 1;
1273 }
1274 #endif
1275 if(check){
1276 ext_printf("\t(ECDSA public key recovery also checked!)\n");
1277 }
1278 #ifdef USE_CRYPTOFUZZ
1279 #if defined(WITH_SIG_ECDSA)
1280 if(cur_test->sig_type == ECDSA){
1281 ext_printf("\t(RAW ECDSA for CRYPTOFUZZ also checked!)\n");
1282 }
1283 #endif
1284 #if defined(WITH_SIG_ECGDSA)
1285 if(cur_test->sig_type == ECGDSA){
1286 ext_printf("\t(RAW ECGDSA for CRYPTOFUZZ also checked!)\n");
1287 }
1288 #endif
1289 #if defined(WITH_SIG_ECRDSA)
1290 if(cur_test->sig_type == ECRDSA){
1291 ext_printf("\t(RAW ECRDSA for CRYPTOFUZZ also checked!)\n");
1292 }
1293 #endif
1294 #endif
1295 OPENMP_UNLOCK();
1296 OPENMP_EG(ret, err);
1297 }
1298 #if defined(WITH_ECCCDH) || defined(WITH_X25519) || defined(WITH_X448)
1299 /* Now take care of ECDH */
1300 if((sig == NULL) && (hash == NULL)){
1301 #ifdef WITH_OPENMP_SELF_TESTS
1302 #pragma omp parallel
1303 #pragma omp for schedule(static, 1) nowait
1304 #endif
1305 for (i = 0; i < ECDH_FIXED_VECTOR_NUM_TESTS; i++) {
1306 int check;
1307 const ecdh_test_case *ecdh_cur_test;
1308 ecdh_cur_test = ecdh_fixed_vector_tests[i];
1309 if(ecdh_cur_test == NULL){
1310 continue;
1311 }
1312 /* If this is not an ECDH test case, skip it! */
1313 if(ecdh_cur_test->ecdh_type == UNKNOWN_ALG){
1314 continue;
1315 }
1316 if(curve != NULL){
1317 if(ecdh_cur_test->ec_str_p == NULL){
1318 continue;
1319 }
1320 ret = are_str_equal((const char*)ecdh_cur_test->ec_str_p->name->buf, curve, &check); OPENMP_EG(ret, err);
1321 if(!check){
1322 continue;
1323 }
1324 }
1325 ret = ecdh_known_vector_tests_one(ecdh_cur_test);
1326 OPENMP_LOCK();
1327 ext_printf("[%s] %30s selftests: known test vectors "
1328 "ecdh %s\n", ret ? "-" : "+",
1329 ecdh_cur_test->name, ret ? "failed" : "ok");
1330 OPENMP_EG(ret, err);
1331 OPENMP_UNLOCK();
1332 }
1333 }
1334 #endif
1335
1336 #ifndef WITH_OPENMP_SELF_TESTS
1337 err:
1338 #endif
1339 return ret;
1340 }
1341
1342 ATTRIBUTE_WARN_UNUSED_RET static int rand_sig_verif_test_one(const ec_sig_mapping *sig,
1343 const hash_mapping *hash,
1344 const ec_mapping *ec)
1345 {
1346 char test_name[MAX_CURVE_NAME_LEN + MAX_HASH_ALG_NAME_LEN +
1347 MAX_SIG_ALG_NAME_LEN + 2];
1348 const unsigned int tn_size = sizeof(test_name) - 1; /* w/o trailing 0 */
1349 const char *crv_name;
1350 ec_test_case t;
1351 int ret, check;
1352 u32 len;
1353
1354 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_SM2) || defined(WITH_SIG_BIGN) || defined(WITH_SIG_DBIGN)
1355 u8 rand_adata[255];
1356 ret = local_memset(rand_adata, 0, sizeof(rand_adata)); EG(ret, err);
1357 /* The case of EDDSA25519CTX and SM2 needs a non NULL context (ancillary data).
1358 * Create a random string of size <= 255 for this.
1359 */
1360 /*
1361 * In the case of BIGN and DBIGN, the ancillary data have a structure containing the OID as well
1362 * as an optional generation token.
1363 */
1364 #endif
1365 ret = local_memset(test_name, 0, sizeof(test_name)); EG(ret, err);
1366
1367 MUST_HAVE((sig != NULL), ret, err);
1368 MUST_HAVE((hash != NULL), ret, err);
1369 MUST_HAVE((ec != NULL), ret, err);
1370
1371 crv_name = (const char *)PARAM_BUF_PTR((ec->params)->name);
1372
1373 /* Generate the test name */
1374 ret = local_memset(test_name, 0, tn_size + 1); EG(ret, err);
1375 ret = local_strncpy(test_name, sig->name, tn_size); EG(ret, err);
1376 ret = local_strlen(test_name, &len); EG(ret, err);
1377 ret = local_strncat(test_name, "-", tn_size - len); EG(ret, err);
1378 ret = local_strlen(test_name, &len); EG(ret, err);
1379 ret = local_strncat(test_name, hash->name, tn_size - len); EG(ret, err);
1380 ret = local_strlen(test_name, &len); EG(ret, err);
1381 ret = local_strncat(test_name, "/", tn_size - len); EG(ret, err);
1382 ret = local_strlen(test_name, &len); EG(ret, err);
1383 ret = local_strncat(test_name, crv_name, tn_size - len); EG(ret, err);
1384
1385 /* Create a test */
1386 t.name = test_name;
1387 t.ec_str_p = ec->params;
1388 t.priv_key = NULL;
1389 t.priv_key_len = 0;
1390 t.nn_random = NULL;
1391 t.hash_type = hash->type;
1392 t.msg = NULL;
1393 t.msglen = 0;
1394 t.sig_type = sig->type;
1395 t.exp_sig = NULL;
1396 t.exp_siglen = 0;
1397 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_SM2)
1398 #if defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_SM2)
1399 if(sig->type == EDDSA25519CTX)
1400 #endif
1401 #if !defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_SM2)
1402 if(sig->type == SM2)
1403 #endif
1404 #if defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_SM2)
1405 if((sig->type == EDDSA25519CTX) || (sig->type == SM2))
1406 #endif
1407 {
1408 u8 rand_len = 0;
1409 ret = get_random((u8 *)&rand_len, sizeof(rand_len)); EG(ret, err);
1410 ret = get_random((u8 *)rand_adata, (u16)(rand_len % sizeof(rand_adata))); EG(ret, err);
1411 t.adata = rand_adata;
1412 t.adata_len = rand_len;
1413 }
1414 else
1415 #endif
1416 {
1417 #if defined(WITH_SIG_BIGN) || defined(WITH_SIG_DBIGN)
1418 #if defined(WITH_SIG_BIGN) && !defined(WITH_SIG_DBIGN)
1419 if(sig->type == BIGN)
1420 #endif
1421 #if !defined(WITH_SIG_BIGN) && defined(WITH_SIG_DBIGN)
1422 if(sig->type == DBIGN)
1423 #endif
1424 #if defined(WITH_SIG_BIGN) && defined(WITH_SIG_DBIGN)
1425 if((sig->type == BIGN) || (sig->type == DBIGN))
1426 #endif
1427 {
1428 u16 oid_len = 0;
1429 u16 t_len = 0;
1430 ret = get_random((u8 *)rand_adata, sizeof(rand_adata)); EG(ret, err);
1431
1432 ret = get_random((u8 *)&oid_len, sizeof(oid_len)); EG(ret, err);
1433 ret = get_random((u8 *)&t_len, sizeof(oid_len)); EG(ret, err);
1434
1435 oid_len = (u8)(oid_len % (sizeof(rand_adata) - 4));
1436 t_len = (u8)(t_len % (sizeof(rand_adata) - 4 - oid_len));
1437 rand_adata[0] = (u8)(oid_len >> 8);
1438 rand_adata[1] = (u8)(oid_len & 0xff);
1439 rand_adata[2] = (u8)(t_len >> 8);
1440 rand_adata[3] = (u8)(t_len & 0xff);
1441 t.adata = rand_adata;
1442 t.adata_len = (u8)(oid_len + t_len + 4);
1443 }
1444 else
1445 #endif
1446 {
1447 t.adata = NULL;
1448 t.adata_len = 0;
1449 }
1450 }
1451
1452 /* Execute the test */
1453 ret = ec_import_export_test(&t);
1454 OPENMP_LOCK();
1455 ext_printf("[%s] %34s randtests: random import/export "
1456 "with sig/verif %s\n", ret ? "-" : "+", t.name,
1457 ret ? "failed" : "ok");
1458 check = 0;
1459 #if defined(WITH_SIG_ECDSA)
1460 if(t.sig_type == ECDSA){
1461 check = 1;
1462 }
1463 #endif
1464 #if defined(WITH_SIG_DECDSA)
1465 if(t.sig_type == DECDSA){
1466 check = 1;
1467 }
1468 #endif
1469 if(check){
1470 ext_printf("\t(ECDSA public key recovery also checked!)\n");
1471 }
1472
1473 #ifdef USE_CRYPTOFUZZ
1474 #if defined(WITH_SIG_ECDSA)
1475 if(t.sig_type == ECDSA){
1476 ext_printf("\t(RAW ECDSA for CRYPTOFUZZ also checked!)\n");
1477 }
1478 #endif
1479 #if defined(WITH_SIG_ECGDSA)
1480 if(t.sig_type == ECGDSA){
1481 ext_printf("\t(RAW ECGDSA for CRYPTOFUZZ also checked!)\n");
1482 }
1483 #endif
1484 #if defined(WITH_SIG_ECRDSA)
1485 if(t.sig_type == ECRDSA){
1486 ext_printf("\t(RAW ECRDSA for CRYPTOFUZZ also checked!)\n");
1487 }
1488 #endif
1489 #endif
1490 OPENMP_UNLOCK();
1491
1492 err:
1493 return ret;
1494 }
1495
1496 ATTRIBUTE_WARN_UNUSED_RET int perform_random_sig_verif_test(const char *sig, const char *hash, const char *curve)
1497 {
1498 unsigned int num_sig_maps, num_hash_maps;
1499 int ret = 0;
1500
1501 /* Compute number of sig and hash maps */
1502 for (num_sig_maps = 0; ec_sig_maps[num_sig_maps].type != UNKNOWN_ALG; num_sig_maps++) {}
1503 for (num_hash_maps = 0; hash_maps[num_hash_maps].type != UNKNOWN_HASH_ALG; num_hash_maps++) {}
1504
1505 /*
1506 * Perform basic sign/verify tests on all the cipher suites
1507 * (combination of sign algo/hash function/curve)
1508 */
1509 ext_printf("======= Random sig/verif test ===================\n");
1510 for (unsigned int i = 0; i < num_sig_maps; i++) {
1511 #ifdef WITH_OPENMP_SELF_TESTS
1512 #pragma omp parallel for collapse(2)
1513 #endif
1514 for (unsigned int j = 0; j < num_hash_maps; j++) {
1515 for (unsigned int k = 0; k < EC_CURVES_NUM; k++) {
1516 int check;
1517 if(sig != NULL){
1518 ret = are_str_equal(ec_sig_maps[i].name, sig, &check); OPENMP_EG(ret, err);
1519 if(!check){
1520 continue;
1521 }
1522 }
1523 if(hash != NULL){
1524 ret = are_str_equal(hash_maps[j].name, hash, &check); OPENMP_EG(ret, err);
1525 if(!check){
1526 continue;
1527 }
1528 }
1529 if(curve != NULL){
1530 ret = are_str_equal((const char*)ec_maps[k].params->name->buf, curve, &check); OPENMP_EG(ret, err);
1531 if(!check){
1532 continue;
1533 }
1534 }
1535 /* If we have EDDSA25519 or EDDSA448, we only accept specific hash functions.
1536 * Skip the other tests.
1537 */
1538 #ifdef WITH_SIG_EDDSA25519
1539 if((ec_sig_maps[i].type == EDDSA25519) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){
1540 continue;
1541 }
1542 if((ec_sig_maps[i].type == EDDSA25519CTX) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){
1543 continue;
1544 }
1545 if((ec_sig_maps[i].type == EDDSA25519PH) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){
1546 continue;
1547 }
1548 #endif
1549 #ifdef WITH_SIG_EDDSA448
1550 if((ec_sig_maps[i].type == EDDSA448) && ((hash_maps[j].type != SHAKE256) || (ec_maps[k].type != WEI448))){
1551 continue;
1552 }
1553 if((ec_sig_maps[i].type == EDDSA448PH) && ((hash_maps[j].type != SHAKE256) || (ec_maps[k].type != WEI448))){
1554 continue;
1555 }
1556 #endif
1557 ret = rand_sig_verif_test_one(&ec_sig_maps[i],
1558 &hash_maps[j],
1559 &ec_maps[k]);
1560 OPENMP_EG(ret, err);
1561 }
1562 }
1563 }
1564
1565 #ifndef WITH_OPENMP_SELF_TESTS
1566 err:
1567 #endif
1568 return ret;
1569 }
1570
1571 #define PERF_NUM_OP 300
1572 #define PERF_BATCH_VERIFICATION 16
1573
1574 /*
1575 * ECC generic performance test: Returns the number of signatures
1576 * and verifications per second
1577 */
1578 ATTRIBUTE_WARN_UNUSED_RET static int ec_performance_test(const ec_test_case *c,
1579 unsigned int *n_perf_sign,
1580 unsigned int *n_perf_verif,
1581 unsigned int *n_perf_batch_verif,
1582 unsigned char *batch_verify_ok)
1583 {
1584 ec_key_pair kp;
1585 ec_params params;
1586 int ret, check;
1587
1588 MUST_HAVE(c != NULL, ret, err);
1589 MUST_HAVE(n_perf_sign != NULL, ret, err);
1590 MUST_HAVE(n_perf_verif != NULL, ret, err);
1591 MUST_HAVE((n_perf_batch_verif != NULL) && (batch_verify_ok != NULL), ret, err);
1592
1593 ret = local_memset(&kp, 0, sizeof(kp)); EG(ret, err);
1594
1595 /* Import EC params from test case */
1596 ret = import_params(¶ms, c->ec_str_p);
1597 if (ret) {
1598 ext_printf("Error when importing parameters\n");
1599 goto err;
1600 }
1601
1602 /* Generate, import/export a key pair */
1603 ret = ec_gen_import_export_kp(&kp, ¶ms, c);
1604 if (ret) {
1605 ext_printf("Error at key pair generation/import/export\n");
1606 goto err;
1607 }
1608
1609 /* Perform test */
1610 {
1611 u8 sig[EC_MAX_SIGLEN];
1612 u8 siglen;
1613 u8 msg[MAX_BLOCK_SIZE];
1614 u16 msglen;
1615 u8 hash_digest_size, hash_block_size;
1616 /* Time related variables */
1617 u64 time1, time2, cumulated_time_sign, cumulated_time_verify, cumulated_time_batch_verify;
1618 unsigned int i;
1619
1620 ret = local_memset(sig, 0, sizeof(sig)); EG(ret, err);
1621 ret = local_memset(msg, 0, sizeof(msg)); EG(ret, err);
1622
1623 ret = ec_get_sig_len(¶ms, c->sig_type, c->hash_type,
1624 (u8 *)&siglen);
1625 if (ret) {
1626 ext_printf("Error computing effective sig size\n");
1627 goto err;
1628 }
1629
1630 /*
1631 * Random tests to measure performance: We do it on small
1632 * messages to "absorb" the hash function cost
1633 */
1634 ret = get_hash_sizes(c->hash_type, &hash_digest_size,
1635 &hash_block_size);
1636 if (ret) {
1637 ext_printf("Error when getting hash size\n");
1638 goto err;
1639 }
1640 cumulated_time_sign = cumulated_time_verify = cumulated_time_batch_verify = 0;
1641 for (i = 0; i < PERF_NUM_OP; i++) {
1642 /* Generate a random message to sign */
1643 ret = get_random((u8 *)&msglen, sizeof(msglen));
1644 if (ret) {
1645 ext_printf("Error when getting random\n");
1646 goto err;
1647 }
1648 msglen = (u16)(msglen % hash_block_size);
1649 ret = get_random(msg, msglen);
1650 if (ret) {
1651 ext_printf("Error when getting random\n");
1652 goto err;
1653 }
1654
1655 /***** Signature **********/
1656 ret = get_ms_time(&time1);
1657 if (ret) {
1658 ext_printf("Error when getting time\n");
1659 goto err;
1660 }
1661 ret = _ec_sign(sig, siglen, &kp, msg, msglen,
1662 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len);
1663 if (ret) {
1664 ext_printf("Error when signing\n");
1665 goto err;
1666 }
1667 ret = get_ms_time(&time2);
1668 if (ret) {
1669 ext_printf("Error when getting time\n");
1670 goto err;
1671 }
1672 if (time2 < time1) {
1673 ext_printf("Error: time error (t2 < t1)\n");
1674 goto err;
1675 }
1676 cumulated_time_sign += (time2 - time1);
1677
1678 /***** Verification **********/
1679 ret = get_ms_time(&time1);
1680 if (ret) {
1681 ext_printf("Error when getting time\n");
1682 goto err;
1683 }
1684 ret = ec_verify(sig, siglen, &(kp.pub_key), msg, msglen,
1685 c->sig_type, c->hash_type, c->adata, c->adata_len);
1686 if (ret) {
1687 ext_printf("Error when verifying signature\n");
1688 goto err;
1689 }
1690 ret = get_ms_time(&time2);
1691 if (ret) {
1692 ext_printf("Error when getting time\n");
1693 goto err;
1694 }
1695 if (time2 < time1) {
1696 ext_printf("Error: time error (time2 < time1)\n");
1697 goto err;
1698 }
1699 cumulated_time_verify += (time2 - time1);
1700
1701 /***** Batch verification **********/
1702 ret = is_verify_batch_mode_supported(c->sig_type, &check); EG(ret, err);
1703 if(check){
1704 unsigned int j;
1705 const u8 *signatures[PERF_BATCH_VERIFICATION];
1706 u8 signatures_len[PERF_BATCH_VERIFICATION];
1707 const u8 *messages[PERF_BATCH_VERIFICATION];
1708 u32 messages_len[PERF_BATCH_VERIFICATION];
1709 const ec_pub_key *pub_keys[PERF_BATCH_VERIFICATION];
1710 const u8 *adatas[PERF_BATCH_VERIFICATION];
1711 u16 adatas_len[PERF_BATCH_VERIFICATION];
1712 /* We need 2 * n + 1 scratch pad storage, compute this with max */
1713 verify_batch_scratch_pad scratch_pad_area[(2 * PERF_BATCH_VERIFICATION) + 1];
1714 u32 scratch_pad_area_len = sizeof(scratch_pad_area);
1715
1716 for(j = 0; j < PERF_BATCH_VERIFICATION; j++){
1717 signatures[j] = sig;
1718 signatures_len[j] = siglen;
1719 messages[j] = msg;
1720 messages_len[j] = msglen;
1721 pub_keys[j] = &(kp.pub_key);
1722 adatas[j] = c->adata;
1723 adatas_len[j] = c->adata_len;
1724 }
1725 ret = get_ms_time(&time1);
1726 if (ret) {
1727 ext_printf("Error when getting time\n");
1728 goto err;
1729 }
1730 ret = ec_verify_batch(signatures, signatures_len, pub_keys, messages, messages_len,
1731 PERF_BATCH_VERIFICATION, c->sig_type, c->hash_type, adatas, adatas_len, scratch_pad_area, &scratch_pad_area_len);
1732 if(ret){
1733 ext_printf("Error when verifying signature ec_verify_batch with batch %d\n", PERF_BATCH_VERIFICATION);
1734 goto err;
1735 }
1736 ret = get_ms_time(&time2);
1737 if (ret) {
1738 ext_printf("Error when getting time\n");
1739 goto err;
1740 }
1741 if (time2 < time1) {
1742 ext_printf("Error: time error (time2 < time1)\n");
1743 goto err;
1744 }
1745 cumulated_time_batch_verify += (time2 - time1);
1746 (*batch_verify_ok) = 1;
1747 }
1748 else{
1749 (*batch_verify_ok) = 0;
1750 }
1751 }
1752
1753 if (n_perf_sign != NULL) {
1754 (*n_perf_sign) = (unsigned int)((PERF_NUM_OP * 1000ULL) / cumulated_time_sign);
1755 }
1756 if (n_perf_verif != NULL) {
1757 (*n_perf_verif) = (unsigned int)((PERF_NUM_OP * 1000ULL) / cumulated_time_verify);
1758 }
1759 if (n_perf_batch_verif != NULL) {
1760 if((*batch_verify_ok) == 1){
1761 (*n_perf_batch_verif) = (unsigned int)((PERF_NUM_OP * PERF_BATCH_VERIFICATION * 1000ULL) / cumulated_time_batch_verify);
1762 }
1763 else{
1764 (*n_perf_batch_verif) = 0;
1765 }
1766 }
1767 }
1768 ret = 0;
1769 err:
1770 return ret;
1771 }
1772
1773
1774 ATTRIBUTE_WARN_UNUSED_RET static int perf_test_one(const ec_sig_mapping *sig, const hash_mapping *hash,
1775 const ec_mapping *ec)
1776 {
1777 char test_name[MAX_CURVE_NAME_LEN + MAX_HASH_ALG_NAME_LEN +
1778 MAX_SIG_ALG_NAME_LEN + 2];
1779 const unsigned int tn_size = sizeof(test_name) - 1; /* w/o trailing 0 */
1780 unsigned int n_perf_sign = 0, n_perf_verif = 0, n_perf_batch_verif = 0;
1781 unsigned char batch_verify_ok = 0;
1782 const char *crv_name;
1783 ec_test_case t;
1784 int ret;
1785 u32 len;
1786 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_SM2) || defined(WITH_SIG_BIGN) || defined(WITH_SIG_DBIGN)
1787 u8 rand_adata[255];
1788 ret = local_memset(rand_adata, 0, sizeof(rand_adata)); EG(ret, err);
1789 /* The case of EDDSA25519CTX and SM2 needs a non NULL context (ancillary data).
1790 * Create a random string of size <= 255 for this.
1791 */
1792 /*
1793 * In the case of BIGN and DBIGN, the ancillary data have a structure containing the OID as well
1794 * as an optional generation token.
1795 */
1796 #endif
1797 MUST_HAVE((sig != NULL), ret, err);
1798 MUST_HAVE((hash != NULL), ret, err);
1799 MUST_HAVE((ec != NULL), ret, err);
1800
1801 ret = local_memset(test_name, 0, sizeof(test_name)); EG(ret, err);
1802
1803 crv_name = (const char *)PARAM_BUF_PTR((ec->params)->name);
1804
1805 /* Generate the test name */
1806 ret = local_memset(test_name, 0, tn_size + 1); EG(ret, err);
1807 ret = local_strncpy(test_name, sig->name, tn_size); EG(ret, err);
1808 ret = local_strlen(test_name, &len); EG(ret, err);
1809 ret = local_strncat(test_name, "-", tn_size - len); EG(ret, err);
1810 ret = local_strlen(test_name, &len); EG(ret, err);
1811 ret = local_strncat(test_name, hash->name, tn_size - len); EG(ret, err);
1812 ret = local_strlen(test_name, &len); EG(ret, err);
1813 ret = local_strncat(test_name, "/", tn_size - len); EG(ret, err);
1814 ret = local_strlen(test_name, &len); EG(ret, err);
1815 ret = local_strncat(test_name, crv_name, tn_size - len); EG(ret, err);
1816
1817 /* Create a test */
1818 t.name = test_name;
1819 t.ec_str_p = ec->params;
1820 t.priv_key = NULL;
1821 t.priv_key_len = 0;
1822 t.nn_random = NULL;
1823 t.hash_type = hash->type;
1824 t.msg = NULL;
1825 t.msglen = 0;
1826 t.sig_type = sig->type;
1827 t.exp_sig = NULL;
1828 t.exp_siglen = 0;
1829 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_SM2)
1830 #if defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_SM2)
1831 if(sig->type == EDDSA25519CTX)
1832 #endif
1833 #if !defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_SM2)
1834 if(sig->type == SM2)
1835 #endif
1836 #if defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_SM2)
1837 if((sig->type == EDDSA25519CTX) || (sig->type == SM2))
1838 #endif
1839 {
1840 u8 rand_len = 0;
1841 ret = get_random((u8 *)&rand_len, sizeof(rand_len)); EG(ret, err);
1842 ret = get_random((u8 *)rand_adata, (u16)(rand_len % sizeof(rand_adata))); EG(ret, err);
1843 t.adata = rand_adata;
1844 t.adata_len = rand_len;
1845 }
1846 else
1847 #endif
1848 {
1849 #if defined(WITH_SIG_BIGN) || defined(WITH_SIG_DBIGN)
1850 #if defined(WITH_SIG_BIGN) && !defined(WITH_SIG_DBIGN)
1851 if(sig->type == BIGN)
1852 #endif
1853 #if !defined(WITH_SIG_BIGN) && defined(WITH_SIG_DBIGN)
1854 if(sig->type == DBIGN)
1855 #endif
1856 #if defined(WITH_SIG_BIGN) && defined(WITH_SIG_DBIGN)
1857 if((sig->type == BIGN) || (sig->type == DBIGN))
1858 #endif
1859 {
1860 u16 oid_len = 0;
1861 u16 t_len = 0;
1862 ret = get_random((u8 *)rand_adata, sizeof(rand_adata)); EG(ret, err);
1863
1864 ret = get_random((u8 *)&oid_len, sizeof(oid_len)); EG(ret, err);
1865 ret = get_random((u8 *)&t_len, sizeof(oid_len)); EG(ret, err);
1866
1867 oid_len = (u8)(oid_len % (sizeof(rand_adata) - 4));
1868 t_len = (u8)(t_len % (sizeof(rand_adata) - 4 - oid_len));
1869 rand_adata[0] = (u8)(oid_len >> 8);
1870 rand_adata[1] = (u8)(oid_len & 0xff);
1871 rand_adata[2] = (u8)(t_len >> 8);
1872 rand_adata[3] = (u8)(t_len & 0xff);
1873 t.adata = rand_adata;
1874 t.adata_len = (u8)(oid_len + t_len + 4);
1875 }
1876 else
1877 #endif
1878 {
1879 t.adata = NULL;
1880 t.adata_len = 0;
1881 }
1882 }
1883
1884 /* Sign and verify some random data during some time */
1885 ret = ec_performance_test(&t, &n_perf_sign, &n_perf_verif, &n_perf_batch_verif, &batch_verify_ok);
1886 OPENMP_LOCK();
1887 if(batch_verify_ok == 1){
1888 ext_printf("[%s] %30s perf: %u sign/s and %u verif/s, %u batch verif/s (for %u batch)\n",
1889 ret ? "-" : "+", t.name, n_perf_sign, n_perf_verif, n_perf_batch_verif, (unsigned int)PERF_BATCH_VERIFICATION);
1890 if ((n_perf_sign == 0) || (n_perf_verif == 0) || (n_perf_batch_verif == 0)) {
1891 ext_printf("\t(0 is less than one sig/verif per sec)\n");
1892 }
1893 }
1894 else{
1895 ext_printf("[%s] %30s perf: %u sign/s and %u verif/s\n",
1896 ret ? "-" : "+", t.name, n_perf_sign, n_perf_verif);
1897 if ((n_perf_sign == 0) || (n_perf_verif == 0)) {
1898 ext_printf("\t(0 is less than one sig/verif per sec)\n");
1899 }
1900 }
1901 OPENMP_UNLOCK();
1902
1903 err:
1904 return ret;
1905 }
1906
1907 ATTRIBUTE_WARN_UNUSED_RET int perform_performance_test(const char *sig, const char *hash, const char *curve)
1908 {
1909 unsigned int i, j, k;
1910 int ret, check;
1911
1912 /* Perform performance tests like "openssl speed" command */
1913 ext_printf("======= Performance test ========================\n");
1914 #ifdef WITH_OPENMP_SELF_TESTS
1915 ext_printf("== NOTE: OpenMP parallelization is not applied to performance tests ...\n");
1916 ext_printf("== (because of CPU/cores shared ressources such as caches, BPU, etc.)\n");
1917 #endif
1918 for (i = 0; ec_sig_maps[i].type != UNKNOWN_ALG; i++) {
1919 for (j = 0; hash_maps[j].type != UNKNOWN_HASH_ALG; j++) {
1920 for (k = 0; k < EC_CURVES_NUM; k++) {
1921 if(sig != NULL){
1922 ret = are_str_equal(ec_sig_maps[i].name, sig, &check); OPENMP_EG(ret, err);
1923 if(!check){
1924 continue;
1925 }
1926 }
1927 if(hash != NULL){
1928 ret = are_str_equal(hash_maps[j].name, hash, &check); OPENMP_EG(ret, err);
1929 if(!check){
1930 continue;
1931 }
1932 }
1933 if(curve != NULL){
1934 ret = are_str_equal((const char*)ec_maps[k].params->name->buf, curve, &check); OPENMP_EG(ret, err);
1935 if(!check){
1936 continue;
1937 }
1938 }
1939 /* If we have EDDSA25519 or EDDSA448, we only accept specific hash functions.
1940 * Skip the other tests.
1941 */
1942 #ifdef WITH_SIG_EDDSA25519
1943 if((ec_sig_maps[i].type == EDDSA25519) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){
1944 continue;
1945 }
1946 if((ec_sig_maps[i].type == EDDSA25519CTX) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){
1947 continue;
1948 }
1949 if((ec_sig_maps[i].type == EDDSA25519PH) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){
1950 continue;
1951 }
1952 #endif
1953 #ifdef WITH_SIG_EDDSA448
1954 if((ec_sig_maps[i].type == EDDSA448) && ((hash_maps[j].type != SHAKE256) || (ec_maps[k].type != WEI448))){
1955 continue;
1956 }
1957 if((ec_sig_maps[i].type == EDDSA448PH) && ((hash_maps[j].type != SHAKE256) || (ec_maps[k].type != WEI448))){
1958 continue;
1959 }
1960 #endif
1961 ret = perf_test_one(&ec_sig_maps[i],
1962 &hash_maps[j],
1963 &ec_maps[k]);
1964 if (ret) {
1965 goto err;
1966 }
1967 }
1968 }
1969 }
1970
1971 return 0;
1972
1973 err:
1974 return -1;
1975 }
1976