xref: /freebsd/crypto/libecc/src/wycheproof_tests/libecc_wycheproof.c (revision dd21556857e8d40f66bf5ad54754d9d52669ebf7)
1 /*
2  *  Copyright (C) 2021 - 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  *
8  *  This software is licensed under a dual BSD and GPL v2 license.
9  *  See LICENSE file at the root folder of the project.
10  */
11 
12 /*
13  * Source code for handling tests imported from the wycheproof project:
14  *     https://github.com/google/wycheproof
15  *
16  * As this project primarily targets java cryptographic libraries, the
17  * json test files have been parsed to generate libecc friendly test cases.
18  *
19  * NOTE: we skip here all the tests related to ASN.1 format errors as libecc
20  * does not handle ASN.1 parsing at all. This explains the "skipped" tests from
21  * the wycheproof project.
22  *
23  */
24 #include "libecc_wycheproof.h"
25 
26 /* Parallelize self tests? */
27 #ifdef WITH_OPENMP_SELF_TESTS
28 /* No openmp without stdlib ... */
29 #ifndef WITH_STDLIB
30 #error "Sorry: no possible self tests parallelization (OpenMP) without stdlib! Please use WITH_STDLIB"
31 #endif
32 #include <omp.h>
33 #include <stdlib.h>
34 static omp_lock_t global_lock;
35 static volatile u8 global_lock_initialized = 0;
36 #define OPENMP_LOCK() do {                                       	\
37         if(!global_lock_initialized){                             	\
38                 omp_init_lock(&global_lock);                      	\
39                 global_lock_initialized = 1;                      	\
40         }                                                         	\
41         omp_set_lock(&global_lock);                               	\
42 } while(0)
43 #define OPENMP_EG(ret, err) do {				  				\
44 	if(ret){						  				\
45 		ext_printf("OpenMP abort following error ... %s:%d\n", __FILE__, __LINE__); 	\
46 		exit(-1);					 				\
47 	}							 				\
48 } while(0)
49 #define OPENMP_MUST_HAVE(cnd, ret, err) do {			 	\
50 	ret = !!(cnd);							\
51 	ret = -((~ret) & 1);						\
52 	OPENMP_EG(ret, err);					     	\
53 } while(0)
54 #define OPENMP_UNLOCK() do {                                     	\
55         omp_unset_lock(&global_lock);                             	\
56 } while(0)
57 #else
58 #define OPENMP_LOCK()
59 #define OPENMP_UNLOCK()
60 #define OPENMP_EG(ret, err) do {				 	\
61 	EG(ret, err);					     		\
62 } while(0)
63 #define OPENMP_MUST_HAVE(cnd, ret, err) do {			 	\
64 	MUST_HAVE(cnd, ret, err);					\
65 } while(0)
66 #endif
67 
68 #include "libecc_wycheproof_tests.h"
69 
70 /* Check all ECDSA test vectors */
71 static unsigned int ecdsa_acceptable_invalid = 0;
72 static unsigned int ecdsa_acceptable_valid = 0;
73 static unsigned int ecdsa_all_performed = 0;
74 static int check_wycheproof_ecdsa(void)
75 {
76 #if defined(WITH_SIG_ECDSA)
77 	int ret;
78 	unsigned int i;
79 
80 #ifdef WITH_OPENMP_SELF_TESTS
81         #pragma omp parallel
82         #pragma omp for schedule(static, 1) nowait
83 #endif
84 	for(i = 0; i < NUM_WYCHEPROOF_ECDSA_TESTS; i++){
85 		const wycheproof_ecdsa_test *t = wycheproof_ecdsa_all_tests[i];
86 		ec_pub_key pub_key;
87 		ec_params params;
88 
89 		if (t == NULL){
90 			continue;
91 		}
92 
93 		ecdsa_all_performed++;
94 		ret = local_memset(&pub_key, 0, sizeof(pub_key)); OPENMP_EG(ret, err);
95 		ret = local_memset(&params, 0, sizeof(params)); OPENMP_EG(ret, err);
96 
97 		/* Import EC params from test case */
98 		ret = import_params(&params, t->curve);
99 		if (ret) {
100 			ext_printf("Error: ECDSA tests error importing params\n");
101 			ret = -1;
102 			OPENMP_EG(ret, err);
103 		}
104 
105 		/* Import the public key */
106 		ret = ec_pub_key_import_from_aff_buf(&pub_key, &params, t->pubkey, (u8)(t->pubkeylen), t->sig_alg);
107 		if (ret) {
108 			ext_printf("Error: ECDSA tests error importing public key\n");
109 			ret = -1;
110 			OPENMP_EG(ret, err);
111 		}
112 
113 
114 		ret = ec_verify(t->sig, (u8)(t->siglen), &pub_key, t->msg, t->msglen, t->sig_alg, t->hash, NULL, 0);
115 		/* Valid result */
116 		if ((t->result == 1) && ret) {
117 			ext_printf("[-] Error when verifying ECDSA test %d / %s (verification NOK while must be valid)\n", i, t->name);
118 			ext_printf("    (comment = %s)\n", t->comment);
119 			ret = -1;
120 			OPENMP_EG(ret, err);
121 		}
122 		/* Invalid result */
123 		if ((t->result == -1) && !ret) {
124 			ext_printf("[-] Error when verifying ECDSA test %d / %s (verification OK while must be invalid)\n", i, t->name);
125 			ext_printf("    (comment = %s)\n", t->comment);
126 			ret = -1;
127 			OPENMP_EG(ret, err);
128 		}
129 		/* Acceptable result: only trigger an informational warning */
130 		if (t->result == 0) {
131 			if(ret){
132 				ecdsa_acceptable_valid++;
133 			}
134 			else{
135 				ecdsa_acceptable_invalid++;
136 			}
137 #ifdef VERBOSE_ACCEPTABLE
138 			ext_printf("\t[~] ECDSA test %d / %s (verification %d while acceptable)\n", i, t->name, ret);
139 			ext_printf("\t    (comment = %s)\n", t->comment);
140 #endif
141 		}
142 	}
143 
144 	ret = 0;
145 #ifndef WITH_OPENMP_SELF_TESTS
146 err:
147 #endif
148 	return ret;
149 #else
150 	return 0;
151 #endif
152 }
153 
154 /* Check all EDDSA test vectors */
155 static unsigned int eddsa_acceptable_invalid = 0;
156 static unsigned int eddsa_acceptable_valid = 0;
157 static unsigned int eddsa_all_performed = 0;
158 static int check_wycheproof_eddsa(void)
159 {
160 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448)
161 	int ret;
162 	unsigned int i;
163 
164 #ifdef WITH_OPENMP_SELF_TESTS
165         #pragma omp parallel
166         #pragma omp for schedule(static, 1) nowait
167 #endif
168 	for(i = 0; i < NUM_WYCHEPROOF_EDDSA_TESTS; i++){
169 		const wycheproof_eddsa_test *t = wycheproof_eddsa_all_tests[i];
170 		ec_pub_key pub_key;
171 		ec_pub_key pub_key_check;
172 		ec_priv_key priv_key;
173 		ec_params params;
174 		int check;
175 		u8 exported_pub_key[EDDSA_MAX_PUB_KEY_ENCODED_LEN];
176 
177 		if (t == NULL){
178 			continue;
179 		}
180 
181 		OPENMP_LOCK();
182 		eddsa_all_performed++;
183 		OPENMP_UNLOCK();
184 		ret = local_memset(&pub_key, 0, sizeof(pub_key)); OPENMP_EG(ret, err);
185 		ret = local_memset(&priv_key, 0, sizeof(priv_key)); OPENMP_EG(ret, err);
186 		ret = local_memset(&params, 0, sizeof(params)); OPENMP_EG(ret, err);
187 
188 		/* Import EC params from test case */
189 		ret = import_params(&params, t->curve);
190 		if (ret) {
191 			ext_printf("Error: EDDSA tests error importing params\n");
192 			ret = -1;
193 			OPENMP_EG(ret, err);
194 		}
195 
196 		/* Import the public key */
197 		ret = eddsa_import_pub_key(&pub_key, t->pubkey, (u8)(t->pubkeylen), &params, t->sig_alg);
198 		if (ret) {
199 			ext_printf("Error: EDDSA tests error importing public key\n");
200 			ret = -1;
201 			OPENMP_EG(ret, err);
202 		}
203 		/* Import the private key */
204 		ret = eddsa_import_priv_key(&priv_key, t->privkey, (u8)(t->privkeylen), &params, t->sig_alg);
205  		if (ret) {
206 			ext_printf("Error: EDDSA tests error importing private key\n");
207 			ret = -1;
208 			OPENMP_EG(ret, err);
209 		}
210 		/* Derive private to public */
211 		ret = eddsa_init_pub_key(&pub_key_check, &priv_key);
212 		if (ret) {
213 			ext_printf("Error: EDDSA tests error deriving private to public key\n");
214 			ret = -1;
215 			OPENMP_EG(ret, err);
216 		}
217 		/* Check */
218 		ret = eddsa_export_pub_key(&pub_key, exported_pub_key, (u8)(t->pubkeylen));
219 		if(ret){
220 			ext_printf("Error: EDDSA tests error when exporting public key\n");
221 			ret = -1;
222 			OPENMP_EG(ret, err);
223 		}
224 		/* */
225 		ret = are_equal(t->pubkey, &exported_pub_key, (u8)(t->pubkeylen), &check); OPENMP_EG(ret, err);
226 		if(!check){
227 			ext_printf("Error: EDDSA tests error when checking public key from private\n");
228 			ret = -1;
229 			OPENMP_EG(ret, err);
230 		}
231 
232 		ret = ec_verify(t->sig, (u8)(t->siglen), &pub_key, t->msg, t->msglen, t->sig_alg, t->hash, NULL, 0);
233 		/* Valid result */
234 		if ((t->result == 1) && ret) {
235 			ext_printf("[-] Error when verifying EDDSA test %d / %s (verification NOK while must be valid)\n", i, t->name);
236 			ext_printf("    (comment = %s)\n", t->comment);
237 			ret = -1;
238 			OPENMP_EG(ret, err);
239 		}
240 		/* Invalid result */
241 		if ((t->result == -1) && !ret) {
242 			ext_printf("[-] Error when verifying EDDSA test %d / %s (verification OK while must be invalid)\n", i, t->name);
243 			ext_printf("    (comment = %s)\n", t->comment);
244 			ret = -1;
245 			OPENMP_EG(ret, err);
246 		}
247 		/* Acceptable result: only trigger an informational warning */
248 		if (t->result == 0) {
249 			OPENMP_LOCK();
250 			if(ret){
251 				eddsa_acceptable_valid++;
252 			}
253 			else{
254 				eddsa_acceptable_invalid++;
255 			}
256 #ifdef VERBOSE_ACCEPTABLE
257 			ext_printf("\t[~] EDDSA test %d / %s (verification %d while acceptable)\n", i, t->name, ret);
258 			ext_printf("\t    (comment = %s)\n", t->comment);
259 #endif
260 			OPENMP_UNLOCK();
261 		}
262 	}
263 
264 	ret = 0;
265 #ifndef WITH_OPENMP_SELF_TESTS
266 err:
267 #endif
268 	return ret;
269 #else
270 	return 0;
271 #endif
272 }
273 
274 /* Check all XDH test vectors */
275 static unsigned int xdh_acceptable_invalid = 0;
276 static unsigned int xdh_acceptable_valid = 0;
277 static unsigned int xdh_all_performed = 0;
278 static int check_wycheproof_xdh(void)
279 {
280 #if defined(WITH_X25519) || defined(WITH_X448)
281 	int ret;
282 	unsigned int i;
283 
284 #ifdef WITH_OPENMP_SELF_TESTS
285         #pragma omp parallel
286         #pragma omp for schedule(static, 1) nowait
287 #endif
288 	for(i = 0; i < NUM_WYCHEPROOF_XDH_TESTS; i++){
289 		int check;
290 		const wycheproof_xdh_test *t = wycheproof_xdh_all_tests[i];
291 		unsigned int alglen = 0;
292 		/* Max size buffer */
293 		u8 pubkey_check[X448_SIZE];
294 		u8 sharedsecret_check[X448_SIZE];
295 
296 		if (t == NULL){
297 			continue;
298 		}
299 
300 		OPENMP_LOCK();
301 		xdh_all_performed++;
302 		OPENMP_UNLOCK();
303 
304 #if defined(WITH_X25519)
305 		if(t->xdh_alg == X25519){
306 			OPENMP_MUST_HAVE(((t->curve) == &wei25519_str_params), ret, err);
307 			alglen = X25519_SIZE;
308 		}
309 #endif
310 #if defined(WITH_X448)
311 		if(t->xdh_alg == X448){
312 			OPENMP_MUST_HAVE(((t->curve) == &wei448_str_params), ret, err);
313 			alglen = X448_SIZE;
314 		}
315 #endif
316 		if(alglen == 0){
317 			ext_printf("Error: XDH tests error, unkown algorithm\n");
318 			ret = -1;
319 			OPENMP_EG(ret, err);
320 		}
321 		/* Reject bad lengths */
322 		if(t->privkeylen != alglen){
323 			if(t->result != -1){
324 				ext_printf("[-] Error: XDH tests error, unkown private key length %d with valid result\n", t->privkeylen);
325 				ext_printf("    (comment = %s)\n", t->comment);
326 				ret = -1;
327 				OPENMP_EG(ret, err);
328 			}
329 			else{
330 				continue;
331 			}
332 		}
333 		if(t->peerpubkeylen != alglen){
334 			if(t->result != -1){
335 				ext_printf("[-] Error: XDH tests error, unkown peer public key length %d with valid result\n", t->peerpubkeylen);
336 				ext_printf("    (comment = %s)\n", t->comment);
337 				ret = -1;
338 				OPENMP_EG(ret, err);
339 			}
340 			else{
341 				continue;
342 			}
343 		}
344 		if(t->sharedsecretlen != alglen){
345 			if(t->result != -1){
346 				ext_printf("[-] Error: XDH tests error, unkown shared secret length %d with valid result\n", t->sharedsecretlen);
347 				ext_printf("    (comment = %s)\n", t->comment);
348 				ret = -1;
349 				OPENMP_EG(ret, err);
350 			}
351 			else{
352 				continue;
353 			}
354 		}
355 		if((t->ourpubkeylen != 0) && (t->ourpubkeylen != alglen)){
356 			if(t->result != -1){
357 				ext_printf("[-] Error: XDH tests error, unkown our public key length %d with valid result\n", t->ourpubkeylen);
358 				ext_printf("    (comment = %s)\n", t->comment);
359 				ret = -1;
360 				OPENMP_EG(ret, err);
361 			}
362 			else{
363 				continue;
364 			}
365 		}
366 #if defined(WITH_X25519)
367 		if(t->xdh_alg == X25519){
368 			/* Derive our public key */
369 			ret = x25519_init_pub_key(t->privkey, pubkey_check);
370 			if(ret){
371 				ext_printf("[-] Error: XDH tests error when deriving private key to public\n");
372 				ext_printf("    (comment = %s)\n", t->comment);
373 				ret = -1;
374 				OPENMP_EG(ret, err);
375 			}
376 			if(t->ourpubkeylen != 0){
377 				/* Check public key against the test one */
378 				ret = are_equal(t->ourpubkey, pubkey_check, alglen, &check); OPENMP_EG(ret, err);
379 				if(!check){
380 					ext_printf("[-] Error: XDH tests error when checking our public key\n");
381 					ext_printf("    (comment = %s)\n", t->comment);
382 					ret = -1;
383 					OPENMP_EG(ret, err);
384 				}
385 			}
386 			/* Derive the shared secret */
387 			ret = x25519_derive_secret(t->privkey, t->peerpubkey, sharedsecret_check);
388 			if(ret){
389 				/* Handle "acceptable" results here (e.g. public key on twist) */
390 				if(t->result == 0){
391 					OPENMP_LOCK();
392 					xdh_acceptable_invalid++;
393 #ifdef VERBOSE_ACCEPTABLE
394 					ext_printf("\t[~] XDH test %d / %s (shared secret derivation NOK while acceptable)\n", i, t->name);
395 					ext_printf("\t    (comment = %s)\n", t->comment);
396 #endif
397 					OPENMP_UNLOCK();
398 					continue;
399 				}
400 				ext_printf("[-] Error: XDH tests error when deriving shared secret\n");
401 				ext_printf("    (comment = %s)\n", t->comment);
402 				ret = -1;
403 				OPENMP_EG(ret, err);
404 			}
405 			if(t->result == -1){
406 				ext_printf("[-] Error: XDH tests is OK while invalid\n");
407 				ext_printf("    (comment = %s)\n", t->comment);
408 				ret = -1;
409 				OPENMP_EG(ret, err);
410 			}
411 			/* Check the shared secret */
412 			ret = are_equal(t->sharedsecret, sharedsecret_check, alglen, &check); OPENMP_EG(ret, err);
413 			if(!check){
414 				ext_printf("[-] Error: XDH tests error when checking shared secret\n");
415 				ext_printf("    (comment = %s)\n", t->comment);
416 				ret = -1;
417 				OPENMP_EG(ret, err);
418 			}
419 		}
420 #endif
421 #if defined(WITH_X448)
422 		if(t->xdh_alg == X448){
423 			/* Derive our public key */
424 			ret = x448_init_pub_key(t->privkey, pubkey_check);
425 			if(ret){
426 				ext_printf("[-] Error: XDH tests error when deriving private key to public\n");
427 				ext_printf("    (comment = %s)\n", t->comment);
428 				ret = -1;
429 				OPENMP_EG(ret, err);
430 			}
431 			if(t->ourpubkeylen != 0){
432 				/* Check public key against the test one */
433 				ret = are_equal(t->ourpubkey, pubkey_check, alglen, &check); OPENMP_EG(ret, err);
434 				if(!check){
435 					ext_printf("[-] Error: XDH tests error when checking our public key\n");
436 					ext_printf("    (comment = %s)\n", t->comment);
437 					ret = -1;
438 					OPENMP_EG(ret, err);
439 				}
440 			}
441 			/* Derive the shared secret */
442 			ret = x448_derive_secret(t->privkey, t->peerpubkey, sharedsecret_check);
443 			if(ret){
444 				/* Handle "acceptable" results here (e.g. public key on twist) */
445 				if(t->result == 0){
446 					OPENMP_LOCK();
447 					xdh_acceptable_invalid++;
448 #ifdef VERBOSE_ACCEPTABLE
449 					ext_printf("\t[~] XDH test %d / %s (shared secret derivation NOK while acceptable)\n", i, t->name);
450 					ext_printf("\t    (comment = %s)\n", t->comment);
451 #endif
452 					OPENMP_UNLOCK();
453 					continue;
454 				}
455 				ext_printf("[-] Error: XDH tests error when deriving shared secret\n");
456 				ext_printf("    (comment = %s)\n", t->comment);
457 				OPENMP_EG(ret, err);
458 			}
459 			if(t->result == -1){
460 				ext_printf("[-] Error: XDH tests is OK while invalid\n");
461 				ext_printf("    (comment = %s)\n", t->comment);
462 				ret = -1;
463 				OPENMP_EG(ret, err);
464 			}
465 			/* Check the shared secret */
466 			ret = are_equal(t->sharedsecret, sharedsecret_check, alglen, &check); OPENMP_EG(ret, err);
467 			if(!check){
468 				ext_printf("[-] Error: XDH tests error when checking shared secret\n");
469 				ext_printf("    (comment = %s)\n", t->comment);
470 				ret = -1;
471 				OPENMP_EG(ret, err);
472 			}
473 
474 		}
475 #endif
476 		/* Log the acceptable results */
477 		if (t->result == 0) {
478 			OPENMP_LOCK();
479 			xdh_acceptable_valid++;
480 #ifdef VERBOSE_ACCEPTABLE
481 			ext_printf("\t[~] XDH test %d / %s (shared secret OK while acceptable)\n", i, t->name);
482 			ext_printf("\t    (comment = %s)\n", t->comment);
483 #endif
484 			OPENMP_UNLOCK();
485 		}
486 	}
487 	ret = 0;
488 #ifndef WITH_OPENMP_SELF_TESTS
489 err:
490 #endif
491 	return ret;
492 #else
493 	return 0;
494 #endif
495 }
496 
497 /* Point decompression routine */
498 static int uncompress_ecc_point(const ec_params *params, const u8 *peerpubkey, u8 peerpubkeylen, u8 *serialized_pub_key, u8 serialized_pub_key_size, int compression)
499 {
500 	int ret, sign, check;
501 	fp x, tmp;
502 	fp_t y;
503 	x.magic = tmp.magic = 0;
504 
505 	MUST_HAVE((params != NULL) && (peerpubkey != NULL) && (serialized_pub_key != NULL), ret, err);
506 
507 	/* Uncompressed point size should be twice the x coordinate */
508 	MUST_HAVE((serialized_pub_key_size == (2 * peerpubkeylen)), ret, err);
509 
510 	/* Compression is either 02 or 03 */
511 	MUST_HAVE(((compression == 0x02) || (compression == 0x03)), ret, err);
512 
513 	/* Import our x coordinate */
514 	ret = fp_init_from_buf(&x, &(params->ec_fp), peerpubkey, peerpubkeylen); EG(ret, err);
515 	ret = fp_init(&tmp, &(params->ec_fp)); EG(ret, err);
516 	/* Compute the Weierstrass equation y^2 = x^3 + ax + b solutions */
517 	ret = aff_pt_y_from_x(&tmp, &x, &x, &(params->ec_curve)); EG(ret, err);
518 
519 	/* Choose the square root depending on the compression information */
520 	sign = (compression - 2);
521 
522 	ret = fp_cmp(&x, &tmp, &check); EG(ret, err);
523 
524 	y = ((check > 0) == sign) ? &x : &tmp;
525 
526 	/* Export the point to our buffer */
527 	ret = local_memcpy(&serialized_pub_key[0], &peerpubkey[0], (serialized_pub_key_size / 2)); EG(ret, err);
528 	ret = fp_export_to_buf(&serialized_pub_key[(serialized_pub_key_size / 2)], (serialized_pub_key_size / 2), y);
529 
530 err:
531 	fp_uninit(&x);
532 	fp_uninit(&tmp);
533 	PTR_NULLIFY(y);
534 
535 	return ret;
536 }
537 
538 /* Check all ECDH test vectors */
539 static unsigned int ecdh_acceptable_invalid = 0;
540 static unsigned int ecdh_acceptable_valid = 0;
541 static unsigned int ecdh_all_performed = 0;
542 static int check_wycheproof_ecdh(void)
543 {
544 #if defined(WITH_ECCCDH)
545 	int ret;
546 	unsigned int i;
547 
548 #ifdef WITH_OPENMP_SELF_TESTS
549         #pragma omp parallel
550         #pragma omp for schedule(static, 1) nowait
551 #endif
552 	for(i = 0; i < NUM_WYCHEPROOF_ECDH_TESTS; i++){
553 		int check;
554 		const wycheproof_ecdh_test *t = wycheproof_ecdh_all_tests[i];
555 		ec_pub_key peerpub_key;
556 		ec_pub_key ourpub_key;
557 		ec_pub_key ourpub_key_check;
558 		ec_priv_key priv_key;
559 		ec_params params;
560 		u8 sharedsecret_check[EC_PRIV_KEY_MAX_SIZE];
561 		u8 sharedsecretsize;
562 		u8 serialized_pub_key[EC_PUB_KEY_MAX_SIZE];
563 		u8 serialized_pub_key_check[EC_PUB_KEY_MAX_SIZE];
564 		u8 serialized_pub_key_size;
565 
566 		if (t == NULL){
567 			continue;
568 		}
569 
570 		OPENMP_LOCK();
571 		ecdh_all_performed++;
572 		OPENMP_UNLOCK();
573 
574 		ret = local_memset(&peerpub_key, 0, sizeof(peerpub_key)); OPENMP_EG(ret, err);
575 		ret = local_memset(&ourpub_key, 0, sizeof(ourpub_key)); OPENMP_EG(ret, err);
576 		ret = local_memset(&ourpub_key_check, 0, sizeof(ourpub_key_check)); OPENMP_EG(ret, err);
577 		ret = local_memset(&priv_key, 0, sizeof(priv_key)); OPENMP_EG(ret, err);
578 		ret = local_memset(&params, 0, sizeof(params)); OPENMP_EG(ret, err);
579 		ret = local_memset(sharedsecret_check, 0, sizeof(sharedsecret_check)); OPENMP_EG(ret, err);
580 		ret = local_memset(serialized_pub_key, 0, sizeof(serialized_pub_key)); OPENMP_EG(ret, err);
581 
582 		/* Import EC params from test case */
583 		ret = import_params(&params, t->curve);
584 		if (ret) {
585 			ext_printf("Error: ECDH tests error importing params\n");
586 			ret = -1;
587 			OPENMP_EG(ret, err);
588 		}
589 
590 		/* Get the sizes */
591 		ret = ecccdh_shared_secret_size(&params, &sharedsecretsize);
592 		if (ret) {
593 			ext_printf("Error: ECDH tests error getting shared secret size\n");
594 			ret = -1;
595 			OPENMP_EG(ret, err);
596 		}
597 		OPENMP_MUST_HAVE((sharedsecretsize <= sizeof(sharedsecret_check)), ret, err);
598 		ret = ecccdh_serialized_pub_key_size(&params, &serialized_pub_key_size);
599 		if (ret) {
600 			ext_printf("Error: ECDH tests error getting serialized public key size\n");
601 			ret = -1;
602 			OPENMP_EG(ret, err);
603 		}
604 		OPENMP_MUST_HAVE((serialized_pub_key_size <= sizeof(serialized_pub_key)), ret, err);
605 		OPENMP_MUST_HAVE((serialized_pub_key_size <= sizeof(serialized_pub_key_check)), ret, err);
606 
607 		/* Import the private key */
608 		ret = ec_priv_key_import_from_buf(&priv_key, &params, t->privkey, (u8)(t->privkeylen), t->ecdh_alg);
609 		if (ret) {
610 			ext_printf("Error: ECDH tests error importing private key\n");
611 			ret = -1;
612 			OPENMP_EG(ret, err);
613 		}
614 
615 		if(t->ourpubkeylen != 0){
616 			/* Import our public key if it exists */
617 			ret = ec_pub_key_import_from_aff_buf(&ourpub_key, &params, t->ourpubkey, (u8)(t->ourpubkeylen), t->ecdh_alg);
618 			if (ret && (t->result >= 0)) {
619 				ext_printf("[-] Error: ECDH tests error when importing our public key\n");
620 				ext_printf("    (comment = %s)\n", t->comment);
621 				ret = -1;
622 				OPENMP_EG(ret, err);
623 			}
624 			/* Derive our private key to public */
625 			ret = ecccdh_init_pub_key(&ourpub_key_check, &priv_key);
626 			if (ret) {
627 				ext_printf("Error: ECDH tests error deriving our private key to public\n");
628 				ret = -1;
629 				OPENMP_EG(ret, err);
630 			}
631 			/* Check if we get the same public key by serializing them */
632 			ret = ecccdh_serialize_pub_key(&ourpub_key, serialized_pub_key, serialized_pub_key_size);
633 			if (ret){
634 				ext_printf("Error: ECDH tests error serializing public key\n");
635 				ret = -1;
636 				OPENMP_EG(ret, err);
637 			}
638 			ret = ecccdh_serialize_pub_key(&ourpub_key_check, serialized_pub_key_check, serialized_pub_key_size);
639 			if (ret){
640 				ext_printf("Error: ECDH tests error serializing public key\n");
641 				ret = -1;
642 				OPENMP_EG(ret, err);
643 			}
644 			ret = are_equal(serialized_pub_key, serialized_pub_key_check, serialized_pub_key_size, &check); OPENMP_EG(ret, err);
645 			if(!check){
646 				ext_printf("[-] Error: ECDH tests error when checking our public key\n");
647 				ext_printf("    (comment = %s)\n", t->comment);
648 				ret = -1;
649 				OPENMP_EG(ret, err);
650 			}
651 		}
652 
653 		/* Do we have to uncompress our point? */
654 		if(t->compressed > 0){
655 			/* Uncompress the point */
656 			ret = uncompress_ecc_point(&params, t->peerpubkey, (u8)(t->peerpubkeylen), serialized_pub_key, serialized_pub_key_size, t->compressed);
657 			if ((ret) && (t->result >= 0)) {
658 				ext_printf("[-] Error: ECDH tests error when uncompressing public key\n");
659 				ext_printf("    (comment = %s)\n", t->comment);
660 				ret = -1;
661 				OPENMP_EG(ret, err);
662 			}
663 		}
664 		else{
665 			/* No point compression is used, copy our raw buffer as public key */
666 			if((t->peerpubkeylen != serialized_pub_key_size) && (t->result >= 0)){
667 				ext_printf("[-] Error: ECDH tests error when checking our public key size, got %d instead of %d\n", t->peerpubkeylen, serialized_pub_key_size);
668 				ext_printf("    (comment = %s)\n", t->comment);
669 				ret = -1;
670 				OPENMP_EG(ret, err);
671 			}
672 			ret = local_memcpy(serialized_pub_key, t->peerpubkey, serialized_pub_key_size); OPENMP_EG(ret, err);
673 		}
674 		/* Now derive the shared secret */
675 		ret = ecccdh_derive_secret(&priv_key, serialized_pub_key, serialized_pub_key_size, sharedsecret_check, sharedsecretsize);
676 		if ((ret) && (t->result >= 0)) {
677 			ext_printf("[-] Error: ECDH tests error when deriving secret while acceptable or valid\n");
678 			ext_printf("    (comment = %s)\n", t->comment);
679 			ret = -1;
680 			OPENMP_EG(ret, err);
681 		}
682 		if((!ret) && (t->result == -1)){
683 			ext_printf("Error: ECDH tests error, secret derived OK while invalid\n");
684 			ext_printf("    (comment = %s)\n", t->comment);
685 			ret = -1;
686 			OPENMP_EG(ret, err);
687 		}
688 		if(t->result == -1){
689 			continue;
690 		}
691 		if(sharedsecretsize != t->sharedsecretlen){
692 			ext_printf("Error: ECDH tests error, bad shared secret size %d instead of %d\n", sharedsecretsize, t->sharedsecretlen);
693 			ext_printf("    (comment = %s)\n", t->comment);
694 			ret = -1;
695 			OPENMP_EG(ret, err);
696 		}
697 		/* Compare */
698 		ret = are_equal(sharedsecret_check, t->sharedsecret, sharedsecretsize, &check); OPENMP_EG(ret, err);
699 		if(!check){
700 			ext_printf("[-] Error: ECDH tests error when checking the computed shared secret, they differ\n");
701 			ext_printf("    (comment = %s)\n", t->comment);
702 			ret = -1;
703 			OPENMP_EG(ret, err);
704 		}
705 		/* Log the acceptable results */
706 		if (t->result == 0) {
707 			OPENMP_LOCK();
708 			ecdh_acceptable_valid++;
709 #ifdef VERBOSE_ACCEPTABLE
710 			ext_printf("\t[~] ECDH test %d / %s (shared secret OK while acceptable)\n", i, t->name);
711 			ext_printf("\t    (comment = %s)\n", t->comment);
712 #endif
713 			OPENMP_UNLOCK();
714 		}
715 
716 	}
717 	ret = 0;
718 #ifndef WITH_OPENMP_SELF_TESTS
719 err:
720 #endif
721 	return ret;
722 #else
723 	return 0;
724 #endif
725 }
726 
727 /* Check all HMAC test vectors */
728 static unsigned int hmac_acceptable_invalid = 0;
729 static unsigned int hmac_acceptable_valid = 0;
730 static unsigned int hmac_all_performed = 0;
731 static int check_wycheproof_hmac(void)
732 {
733 #if defined(WITH_HMAC)
734 	int ret;
735 	unsigned int i;
736 
737 #ifdef WITH_OPENMP_SELF_TESTS
738         #pragma omp parallel
739         #pragma omp for schedule(static, 1) nowait
740 #endif
741 	for(i = 0; i < NUM_WYCHEPROOF_HMAC_TESTS; i++){
742 		int check;
743 		const wycheproof_hmac_test *t = wycheproof_hmac_all_tests[i];
744 		u8 hmac_res[MAX_DIGEST_SIZE];
745 		u8 hlen;
746 
747 		if (t == NULL){
748 			continue;
749 		}
750 
751 		OPENMP_LOCK();
752 		hmac_all_performed++;
753 		OPENMP_UNLOCK();
754 
755 		ret = local_memset(&hmac_res, 0, sizeof(hmac_res)); OPENMP_EG(ret, err);
756 
757 		hlen = sizeof(hmac_res);
758 		ret = hmac(t->key, t->keylen, t->hash, t->msg, t->msglen, hmac_res, &hlen);
759 		if (ret) {
760 			ext_printf("[-] Error: HMAC tests error when performin HMAC\n");
761 			ext_printf("    (comment = %s)\n", t->comment);
762 			ret = -1;
763 			OPENMP_EG(ret, err);
764 		}
765 		if((hlen < t->taglen) && (t->result >= 0)){
766 			ext_printf("[-] Error: HMAC tests error: size error %d < %d\n", hlen, t->taglen);
767 			ext_printf("    (comment = %s)\n", t->comment);
768 			ret = -1;
769 			OPENMP_EG(ret, err);
770 		}
771 		/* Compare */
772 		ret = are_equal(hmac_res, t->tag, t->taglen, &check); OPENMP_EG(ret, err);
773 		if((!check) && (t->result >= 0)){
774 			ext_printf("[-] Error: HMAC tests error when checking the computed tag, they differ\n");
775 			ext_printf("    (comment = %s)\n", t->comment);
776 			ret = -1;
777 			OPENMP_EG(ret, err);
778 		}
779 		/* Log the acceptable results */
780 		if (t->result == 0) {
781 			OPENMP_LOCK();
782 			hmac_acceptable_valid++;
783 #ifdef VERBOSE_ACCEPTABLE
784 			ext_printf("\t[~] HMAC test %d / %s (shared secret OK while acceptable)\n", i, t->name);
785 			ext_printf("\t    (comment = %s)\n", t->comment);
786 #endif
787 			OPENMP_UNLOCK();
788 		}
789 	}
790 	ret = 0;
791 #ifndef WITH_OPENMP_SELF_TESTS
792 err:
793 #endif
794 	return ret;
795 #else
796 	return 0;
797 #endif
798 }
799 
800 int main(int argc, char *argv[])
801 {
802 	FORCE_USED_VAR(argc);
803 	FORCE_USED_VAR(argv);
804 
805 	/**********************/
806 	ext_printf("==== Checking ECDH =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_ECDH_TESTS_IMPORTED, NUM_WYCHEPROOF_ECDH_TESTS_SKIPPED, NUM_WYCHEPROOF_ECDH_TESTS_VALID, NUM_WYCHEPROOF_ECDH_TESTS_INVALID, NUM_WYCHEPROOF_ECDH_TESTS_ACCEPTABLE);
807 	if(check_wycheproof_ecdh()){
808 		goto err;
809 	}
810 	ext_printf("[+][%d] All ECDH tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", ecdh_all_performed, ecdh_acceptable_valid, ecdh_acceptable_invalid);
811 	/**********************/
812 	ext_printf("==== Checking XDH =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_XDH_TESTS_IMPORTED, NUM_WYCHEPROOF_XDH_TESTS_SKIPPED, NUM_WYCHEPROOF_XDH_TESTS_VALID, NUM_WYCHEPROOF_XDH_TESTS_INVALID, NUM_WYCHEPROOF_XDH_TESTS_ACCEPTABLE);
813 	if(check_wycheproof_xdh()){
814 		goto err;
815 	}
816 	ext_printf("[+][%d] All XDH tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", xdh_all_performed, xdh_acceptable_valid, xdh_acceptable_invalid);
817 	/**********************/
818 	ext_printf("==== Checking ECDSA =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_ECDSA_TESTS_IMPORTED, NUM_WYCHEPROOF_ECDSA_TESTS_SKIPPED, NUM_WYCHEPROOF_ECDSA_TESTS_VALID, NUM_WYCHEPROOF_ECDSA_TESTS_INVALID, NUM_WYCHEPROOF_ECDSA_TESTS_ACCEPTABLE);
819 	if(check_wycheproof_ecdsa()){
820 		goto err;
821 	}
822 	ext_printf("[+][%d] All ECDSA tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", ecdsa_all_performed, ecdsa_acceptable_valid, ecdsa_acceptable_invalid);
823 	/**********************/
824 	ext_printf("==== Checking EDDSA =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_EDDSA_TESTS_IMPORTED, NUM_WYCHEPROOF_EDDSA_TESTS_SKIPPED, NUM_WYCHEPROOF_EDDSA_TESTS_VALID, NUM_WYCHEPROOF_EDDSA_TESTS_INVALID, NUM_WYCHEPROOF_EDDSA_TESTS_ACCEPTABLE);
825 	if(check_wycheproof_eddsa()){
826 		goto err;
827 	}
828 	ext_printf("[+][%d] All EDDSA tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", eddsa_all_performed, eddsa_acceptable_valid, eddsa_acceptable_invalid);
829 	/**********************/
830 	ext_printf("==== Checking HMAC =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_HMAC_TESTS_IMPORTED, NUM_WYCHEPROOF_HMAC_TESTS_SKIPPED, NUM_WYCHEPROOF_HMAC_TESTS_VALID, NUM_WYCHEPROOF_HMAC_TESTS_INVALID, NUM_WYCHEPROOF_HMAC_TESTS_ACCEPTABLE);
831 	if(check_wycheproof_hmac()){
832 		goto err;
833 	}
834 	ext_printf("[+][%d] All HMAC tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", hmac_all_performed, hmac_acceptable_valid, hmac_acceptable_invalid);
835 
836 err:
837 	return 0;
838 }
839