]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/crypto/crypto_tester.c
Merge branch 'tun-device-ipv6'
[thirdparty/strongswan.git] / src / libstrongswan / crypto / crypto_tester.c
1 /*
2 * Copyright (C) 2009-2010 Martin Willi
3 * Copyright (C) 2016-2019 Andreas Steffen
4 *
5 * Copyright (C) secunet Security Networks AG
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #ifdef HAVE_DLADDR
19 # define _GNU_SOURCE
20 # include <dlfcn.h>
21 #endif
22 #include <time.h>
23
24 #include "crypto_tester.h"
25
26 #include <utils/debug.h>
27 #include <collections/linked_list.h>
28 #include <crypto/rngs/rng_tester.h>
29
30 typedef struct private_crypto_tester_t private_crypto_tester_t;
31
32 /**
33 * Private data of an crypto_tester_t object.
34 */
35 struct private_crypto_tester_t {
36
37 /**
38 * Public crypto_tester_t interface.
39 */
40 crypto_tester_t public;
41
42 /**
43 * List of crypter test vectors
44 */
45 linked_list_t *crypter;
46
47 /**
48 * List of aead test vectors
49 */
50 linked_list_t *aead;
51
52 /**
53 * List of signer test vectors
54 */
55 linked_list_t *signer;
56
57 /**
58 * List of hasher test vectors
59 */
60 linked_list_t *hasher;
61
62 /**
63 * List of PRF test vectors
64 */
65 linked_list_t *prf;
66
67 /**
68 * List of XOF test vectors
69 */
70 linked_list_t *xof;
71
72 /**
73 * List of KDF test vectors
74 */
75 linked_list_t *kdf;
76
77 /**
78 * List of DRBG test vectors
79 */
80 linked_list_t *drbg;
81
82 /**
83 * List of RNG test vectors
84 */
85 linked_list_t *rng;
86
87 /**
88 * List of key exchange method test vectors
89 */
90 linked_list_t *ke;
91
92 /**
93 * Is a test vector required to pass a test?
94 */
95 bool required;
96
97 /**
98 * should we run RNG_TRUE tests? Enough entropy?
99 */
100 bool rng_true;
101
102 /**
103 * time we test each algorithm
104 */
105 int bench_time;
106
107 /**
108 * size of buffer we use for benchmarking
109 */
110 int bench_size;
111 };
112
113 #if DEBUG_LEVEL >= 1
114 /**
115 * Get the name of a test vector, if available
116 */
117 static const char* get_name(void *sym)
118 {
119 #ifdef HAVE_DLADDR
120 Dl_info dli;
121
122 if (dladdr(sym, &dli))
123 {
124 return dli.dli_sname;
125 }
126 #endif
127 return "unknown";
128 }
129 #endif
130
131 #if defined(CLOCK_THREAD_CPUTIME_ID) && defined(HAVE_CLOCK_GETTIME)
132
133 /**
134 * Start a benchmark timer
135 */
136 static void start_timing(struct timespec *start)
137 {
138 clock_gettime(CLOCK_THREAD_CPUTIME_ID, start);
139 }
140
141 /**
142 * End a benchmark timer, return ms
143 */
144 static u_int end_timing(struct timespec *start)
145 {
146 struct timespec end;
147
148 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
149 return (end.tv_nsec - start->tv_nsec) / 1000000 +
150 (end.tv_sec - start->tv_sec) * 1000;
151 }
152
153 #else /* CLOCK_THREAD_CPUTIME_ID */
154
155 /* Make benchmarking a no-op if CLOCK_THREAD_CPUTIME_ID is not available */
156 #define start_timing(start) ((start)->tv_sec = 0, (start)->tv_nsec = 0)
157 #define end_timing(...) (this->bench_time)
158
159 #endif /* CLOCK_THREAD_CPUTIME_ID */
160
161 /**
162 * Benchmark a crypter
163 */
164 static u_int bench_crypter(private_crypto_tester_t *this,
165 encryption_algorithm_t alg, crypter_constructor_t create, size_t key_size)
166 {
167 crypter_t *crypter;
168
169 crypter = create(alg, key_size);
170 if (crypter)
171 {
172 char iv[crypter->get_iv_size(crypter)];
173 char key[crypter->get_key_size(crypter)];
174 chunk_t buf;
175 struct timespec start;
176 u_int runs;
177
178 memset(iv, 0x56, sizeof(iv));
179 memset(key, 0x12, sizeof(key));
180 if (!crypter->set_key(crypter, chunk_from_thing(key)))
181 {
182 return 0;
183 }
184
185 buf = chunk_alloc(this->bench_size);
186 memset(buf.ptr, 0x34, buf.len);
187
188 runs = 0;
189 start_timing(&start);
190 while (end_timing(&start) < this->bench_time)
191 {
192 if (crypter->encrypt(crypter, buf, chunk_from_thing(iv), NULL))
193 {
194 runs++;
195 }
196 if (crypter->decrypt(crypter, buf, chunk_from_thing(iv), NULL))
197 {
198 runs++;
199 }
200 }
201 free(buf.ptr);
202 crypter->destroy(crypter);
203
204 return runs;
205 }
206 return 0;
207 }
208
209 METHOD(crypto_tester_t, test_crypter, bool,
210 private_crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size,
211 crypter_constructor_t create, u_int *speed, const char *plugin_name)
212 {
213 enumerator_t *enumerator;
214 crypter_test_vector_t *vector;
215 bool failed = FALSE;
216 u_int tested = 0;
217
218 enumerator = this->crypter->create_enumerator(this->crypter);
219 while (enumerator->enumerate(enumerator, &vector))
220 {
221 crypter_t *crypter;
222 chunk_t key, iv, plain = chunk_empty, cipher = chunk_empty;
223
224 if (vector->alg != alg)
225 {
226 continue;
227 }
228 if (key_size && key_size != vector->key_size)
229 { /* test only vectors with a specific key size, if key size given */
230 continue;
231 }
232
233 crypter = create(alg, vector->key_size);
234 if (!crypter)
235 { /* key size not supported */
236 continue;
237 }
238 tested++;
239 failed = TRUE;
240
241 key = chunk_create(vector->key, crypter->get_key_size(crypter));
242 if (!crypter->set_key(crypter, key))
243 {
244 goto failure;
245 }
246 iv = chunk_create(vector->iv, crypter->get_iv_size(crypter));
247
248 /* allocated encryption */
249 plain = chunk_create(vector->plain, vector->len);
250 if (!crypter->encrypt(crypter, plain, iv, &cipher))
251 {
252 goto failure;
253 }
254 if (!memeq(vector->cipher, cipher.ptr, cipher.len))
255 {
256 goto failure;
257 }
258 /* inline decryption */
259 if (!crypter->decrypt(crypter, cipher, iv, NULL))
260 {
261 goto failure;
262 }
263 if (!memeq(vector->plain, cipher.ptr, cipher.len))
264 {
265 goto failure;
266 }
267 /* allocated decryption */
268 if (!crypter->decrypt(crypter,
269 chunk_create(vector->cipher, vector->len), iv, &plain))
270 {
271 goto failure;
272 }
273 if (!memeq(vector->plain, plain.ptr, plain.len))
274 {
275 goto failure;
276 }
277 /* inline encryption */
278 if (!crypter->encrypt(crypter, plain, iv, NULL))
279 {
280 goto failure;
281 }
282 if (!memeq(vector->cipher, plain.ptr, plain.len))
283 {
284 goto failure;
285 }
286
287 failed = FALSE;
288 failure:
289 crypter->destroy(crypter);
290 chunk_free(&cipher);
291 if (plain.ptr != vector->plain)
292 {
293 chunk_free(&plain);
294 }
295 if (failed)
296 {
297 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
298 encryption_algorithm_names, alg, plugin_name, get_name(vector));
299 break;
300 }
301 }
302 enumerator->destroy(enumerator);
303 if (!tested)
304 {
305 if (failed)
306 {
307 DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported",
308 encryption_algorithm_names, alg, plugin_name, key_size);
309 return FALSE;
310 }
311 else
312 {
313 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
314 this->required ? "disabled" : "enabled ",
315 encryption_algorithm_names, alg, plugin_name);
316 return !this->required;
317 }
318 }
319 if (!failed)
320 {
321 if (speed)
322 {
323 *speed = bench_crypter(this, alg, create, key_size);
324 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points "
325 "(%zd bit key)", encryption_algorithm_names, alg,
326 plugin_name, tested, *speed, key_size * 8);
327 }
328 else
329 {
330 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
331 encryption_algorithm_names, alg, plugin_name, tested);
332 }
333 }
334 return !failed;
335 }
336
337 /**
338 * Benchmark an aead transform
339 */
340 static u_int bench_aead(private_crypto_tester_t *this,
341 encryption_algorithm_t alg, aead_constructor_t create, size_t key_size)
342 {
343 aead_t *aead;
344
345 aead = create(alg, key_size, 0);
346 if (aead)
347 {
348 char iv[aead->get_iv_size(aead)];
349 char key[aead->get_key_size(aead)];
350 char assoc[4];
351 chunk_t buf;
352 struct timespec start;
353 u_int runs;
354 size_t icv;
355
356 memset(iv, 0x56, sizeof(iv));
357 memset(key, 0x12, sizeof(key));
358 memset(assoc, 0x78, sizeof(assoc));
359 if (!aead->set_key(aead, chunk_from_thing(key)))
360 {
361 return 0;
362 }
363 icv = aead->get_icv_size(aead);
364
365 buf = chunk_alloc(this->bench_size + icv);
366 memset(buf.ptr, 0x34, buf.len);
367 buf.len -= icv;
368
369 runs = 0;
370 start_timing(&start);
371 while (end_timing(&start) < this->bench_time)
372 {
373 if (aead->encrypt(aead, buf, chunk_from_thing(assoc),
374 chunk_from_thing(iv), NULL))
375 {
376 runs += 2;
377 }
378 if (aead->decrypt(aead, chunk_create(buf.ptr, buf.len + icv),
379 chunk_from_thing(assoc), chunk_from_thing(iv), NULL))
380 {
381 runs += 2;
382 }
383 }
384 free(buf.ptr);
385 aead->destroy(aead);
386
387 return runs;
388 }
389 return 0;
390 }
391
392 METHOD(crypto_tester_t, test_aead, bool,
393 private_crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size,
394 size_t salt_size, aead_constructor_t create,
395 u_int *speed, const char *plugin_name)
396 {
397 enumerator_t *enumerator;
398 aead_test_vector_t *vector;
399 bool failed = FALSE;
400 u_int tested = 0;
401
402 enumerator = this->aead->create_enumerator(this->aead);
403 while (enumerator->enumerate(enumerator, &vector))
404 {
405 aead_t *aead;
406 chunk_t key, iv, assoc, plain = chunk_empty, cipher = chunk_empty;
407 size_t icv;
408
409 if (vector->alg != alg)
410 {
411 continue;
412 }
413 if (key_size && key_size != vector->key_size)
414 { /* test only vectors with a specific key size, if key size given */
415 continue;
416 }
417 if (salt_size && salt_size != vector->salt_size)
418 {
419 continue;
420 }
421
422 tested++;
423 failed = TRUE;
424 aead = create(alg, vector->key_size, vector->salt_size);
425 if (!aead)
426 {
427 DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported",
428 encryption_algorithm_names, alg, plugin_name,
429 BITS_PER_BYTE * vector->key_size);
430 continue;
431 }
432
433 key = chunk_create(vector->key, aead->get_key_size(aead));
434 if (!aead->set_key(aead, key))
435 {
436 goto failure;
437 }
438 iv = chunk_create(vector->iv, aead->get_iv_size(aead));
439 assoc = chunk_create(vector->adata, vector->alen);
440 icv = aead->get_icv_size(aead);
441
442 /* allocated encryption */
443 plain = chunk_create(vector->plain, vector->len);
444 if (!aead->encrypt(aead, plain, assoc, iv, &cipher))
445 {
446 goto failure;
447 }
448 if (!memeq(vector->cipher, cipher.ptr, cipher.len))
449 {
450 goto failure;
451 }
452 /* inline decryption */
453 if (!aead->decrypt(aead, cipher, assoc, iv, NULL))
454 {
455 goto failure;
456 }
457 if (!memeq(vector->plain, cipher.ptr, cipher.len - icv))
458 {
459 goto failure;
460 }
461 /* allocated decryption */
462 if (!aead->decrypt(aead, chunk_create(vector->cipher, vector->len + icv),
463 assoc, iv, &plain))
464 {
465 goto failure;
466 }
467 if (!memeq(vector->plain, plain.ptr, plain.len))
468 {
469 goto failure;
470 }
471 plain.ptr = realloc(plain.ptr, plain.len + icv);
472 /* inline encryption */
473 if (!aead->encrypt(aead, plain, assoc, iv, NULL))
474 {
475 goto failure;
476 }
477 if (!memeq(vector->cipher, plain.ptr, plain.len + icv))
478 {
479 goto failure;
480 }
481
482 failed = FALSE;
483 failure:
484 aead->destroy(aead);
485 chunk_free(&cipher);
486 if (plain.ptr != vector->plain)
487 {
488 chunk_free(&plain);
489 }
490 if (failed)
491 {
492 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
493 encryption_algorithm_names, alg, plugin_name, get_name(vector));
494 break;
495 }
496 }
497 enumerator->destroy(enumerator);
498 if (!tested)
499 {
500 if (failed)
501 {
502 DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported",
503 encryption_algorithm_names, alg, plugin_name, key_size);
504 return FALSE;
505 }
506 else
507 {
508 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
509 this->required ? "disabled" : "enabled ",
510 encryption_algorithm_names, alg, plugin_name);
511 return !this->required;
512 }
513 }
514 if (!failed)
515 {
516 if (speed)
517 {
518 *speed = bench_aead(this, alg, create, key_size);
519 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points "
520 "(%zd bit key)", encryption_algorithm_names, alg,
521 plugin_name, tested, *speed, key_size * 8);
522 }
523 else
524 {
525 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
526 encryption_algorithm_names, alg, plugin_name, tested);
527 }
528 }
529 return !failed;
530 }
531
532 /**
533 * Benchmark a signer
534 */
535 static u_int bench_signer(private_crypto_tester_t *this,
536 integrity_algorithm_t alg, signer_constructor_t create)
537 {
538 signer_t *signer;
539
540 signer = create(alg);
541 if (signer)
542 {
543 char key[signer->get_key_size(signer)];
544 char mac[signer->get_block_size(signer)];
545 chunk_t buf;
546 struct timespec start;
547 u_int runs;
548
549 memset(key, 0x12, sizeof(key));
550 if (!signer->set_key(signer, chunk_from_thing(key)))
551 {
552 return 0;
553 }
554
555 buf = chunk_alloc(this->bench_size);
556 memset(buf.ptr, 0x34, buf.len);
557
558 runs = 0;
559 start_timing(&start);
560 while (end_timing(&start) < this->bench_time)
561 {
562 if (signer->get_signature(signer, buf, mac))
563 {
564 runs++;
565 }
566 if (signer->verify_signature(signer, buf, chunk_from_thing(mac)))
567 {
568 runs++;
569 }
570 }
571 free(buf.ptr);
572 signer->destroy(signer);
573
574 return runs;
575 }
576 return 0;
577 }
578
579 METHOD(crypto_tester_t, test_signer, bool,
580 private_crypto_tester_t *this, integrity_algorithm_t alg,
581 signer_constructor_t create, u_int *speed, const char *plugin_name)
582 {
583 enumerator_t *enumerator;
584 signer_test_vector_t *vector;
585 bool failed = FALSE;
586 u_int tested = 0;
587
588 enumerator = this->signer->create_enumerator(this->signer);
589 while (enumerator->enumerate(enumerator, &vector))
590 {
591 signer_t *signer;
592 chunk_t key, data, mac = chunk_empty;
593
594 if (vector->alg != alg)
595 {
596 continue;
597 }
598
599 tested++;
600 failed = TRUE;
601 signer = create(alg);
602 if (!signer)
603 {
604 DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
605 integrity_algorithm_names, alg, plugin_name);
606 break;
607 }
608
609 data = chunk_create(vector->data, vector->len);
610 key = chunk_create(vector->key, signer->get_key_size(signer));
611 if (!signer->set_key(signer, key))
612 {
613 goto failure;
614 }
615 /* do partial append mode and check if key gets set correctly */
616 if (!signer->get_signature(signer, data, NULL))
617 {
618 goto failure;
619 }
620 if (!signer->set_key(signer, key))
621 {
622 goto failure;
623 }
624 /* allocated signature */
625 if (!signer->allocate_signature(signer, data, &mac))
626 {
627 goto failure;
628 }
629 if (mac.len != signer->get_block_size(signer))
630 {
631 goto failure;
632 }
633 if (!memeq(vector->mac, mac.ptr, mac.len))
634 {
635 goto failure;
636 }
637 /* signature to existing buffer */
638 memset(mac.ptr, 0, mac.len);
639 if (!signer->get_signature(signer, data, mac.ptr))
640 {
641 goto failure;
642 }
643 if (!memeq(vector->mac, mac.ptr, mac.len))
644 {
645 goto failure;
646 }
647 /* signature verification, good case */
648 if (!signer->verify_signature(signer, data, mac))
649 {
650 goto failure;
651 }
652 /* signature verification, bad case */
653 *(mac.ptr + mac.len - 1) += 1;
654 if (signer->verify_signature(signer, data, mac))
655 {
656 goto failure;
657 }
658 /* signature to existing buffer, using append mode */
659 if (data.len > 2)
660 {
661 if (!signer->allocate_signature(signer,
662 chunk_create(data.ptr, 1), NULL))
663 {
664 goto failure;
665 }
666 if (!signer->get_signature(signer,
667 chunk_create(data.ptr + 1, 1), NULL))
668 {
669 goto failure;
670 }
671 if (!signer->verify_signature(signer, chunk_skip(data, 2),
672 chunk_create(vector->mac, mac.len)))
673 {
674 goto failure;
675 }
676 }
677
678 failed = FALSE;
679 failure:
680 signer->destroy(signer);
681 chunk_free(&mac);
682 if (failed)
683 {
684 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
685 integrity_algorithm_names, alg, plugin_name, get_name(vector));
686 break;
687 }
688 }
689 enumerator->destroy(enumerator);
690 if (!tested)
691 {
692 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
693 this->required ? "disabled" : "enabled ",
694 integrity_algorithm_names, alg, plugin_name);
695 return !this->required;
696 }
697 if (!failed)
698 {
699 if (speed)
700 {
701 *speed = bench_signer(this, alg, create);
702 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points",
703 integrity_algorithm_names, alg, plugin_name, tested, *speed);
704 }
705 else
706 {
707 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
708 integrity_algorithm_names, alg, plugin_name, tested);
709 }
710 }
711 return !failed;
712 }
713
714 /**
715 * Benchmark a hasher
716 */
717 static u_int bench_hasher(private_crypto_tester_t *this,
718 hash_algorithm_t alg, hasher_constructor_t create)
719 {
720 hasher_t *hasher;
721
722 hasher = create(alg);
723 if (hasher)
724 {
725 char hash[hasher->get_hash_size(hasher)];
726 chunk_t buf;
727 struct timespec start;
728 u_int runs;
729
730 buf = chunk_alloc(this->bench_size);
731 memset(buf.ptr, 0x34, buf.len);
732
733 runs = 0;
734 start_timing(&start);
735 while (end_timing(&start) < this->bench_time)
736 {
737 if (hasher->get_hash(hasher, buf, hash))
738 {
739 runs++;
740 }
741 }
742 free(buf.ptr);
743 hasher->destroy(hasher);
744
745 return runs;
746 }
747 return 0;
748 }
749
750 METHOD(crypto_tester_t, test_hasher, bool,
751 private_crypto_tester_t *this, hash_algorithm_t alg,
752 hasher_constructor_t create, u_int *speed, const char *plugin_name)
753 {
754 enumerator_t *enumerator;
755 hasher_test_vector_t *vector;
756 bool failed = FALSE;
757 u_int tested = 0;
758
759 enumerator = this->hasher->create_enumerator(this->hasher);
760 while (enumerator->enumerate(enumerator, &vector))
761 {
762 hasher_t *hasher;
763 chunk_t data, hash;
764
765 if (vector->alg != alg)
766 {
767 continue;
768 }
769
770 tested++;
771 failed = TRUE;
772 hasher = create(alg);
773 if (!hasher)
774 {
775 DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
776 hash_algorithm_names, alg, plugin_name);
777 break;
778 }
779
780 /* allocated hash */
781 data = chunk_create(vector->data, vector->len);
782 if (!hasher->allocate_hash(hasher, data, &hash))
783 {
784 goto failure;
785 }
786 if (hash.len != hasher->get_hash_size(hasher))
787 {
788 goto failure;
789 }
790 if (!memeq(vector->hash, hash.ptr, hash.len))
791 {
792 goto failure;
793 }
794 /* hash to existing buffer, with a reset */
795 memset(hash.ptr, 0, hash.len);
796 if (!hasher->get_hash(hasher, data, NULL))
797 {
798 goto failure;
799 }
800 if (!hasher->reset(hasher))
801 {
802 goto failure;
803 }
804 if (!hasher->get_hash(hasher, data, hash.ptr))
805 {
806 goto failure;
807 }
808 if (!memeq(vector->hash, hash.ptr, hash.len))
809 {
810 goto failure;
811 }
812 /* hasher to existing buffer, using append mode */
813 if (data.len > 2)
814 {
815 memset(hash.ptr, 0, hash.len);
816 if (!hasher->allocate_hash(hasher, chunk_create(data.ptr, 1), NULL))
817 {
818 goto failure;
819 }
820 if (!hasher->get_hash(hasher, chunk_create(data.ptr + 1, 1), NULL))
821 {
822 goto failure;
823 }
824 if (!hasher->get_hash(hasher, chunk_skip(data, 2), hash.ptr))
825 {
826 goto failure;
827 }
828 if (!memeq(vector->hash, hash.ptr, hash.len))
829 {
830 goto failure;
831 }
832 }
833
834 failed = FALSE;
835 failure:
836 hasher->destroy(hasher);
837 chunk_free(&hash);
838 if (failed)
839 {
840 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
841 hash_algorithm_names, alg, plugin_name, get_name(vector));
842 break;
843 }
844 }
845 enumerator->destroy(enumerator);
846 if (!tested)
847 {
848 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
849 this->required ? "disabled" : "enabled ",
850 hash_algorithm_names, alg, plugin_name);
851 return !this->required;
852 }
853 if (!failed)
854 {
855 if (speed)
856 {
857 *speed = bench_hasher(this, alg, create);
858 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points",
859 hash_algorithm_names, alg, plugin_name, tested, *speed);
860 }
861 else
862 {
863 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
864 hash_algorithm_names, alg, plugin_name, tested);
865 }
866 }
867 return !failed;
868 }
869
870 /**
871 * Benchmark a PRF
872 */
873 static u_int bench_prf(private_crypto_tester_t *this,
874 pseudo_random_function_t alg, prf_constructor_t create)
875 {
876 prf_t *prf;
877
878 prf = create(alg);
879 if (prf)
880 {
881 char bytes[prf->get_block_size(prf)], key[prf->get_block_size(prf)];
882 chunk_t buf;
883 struct timespec start;
884 u_int runs;
885
886 memset(key, 0x56, prf->get_block_size(prf));
887 if (!prf->set_key(prf, chunk_create(key, prf->get_block_size(prf))))
888 {
889 prf->destroy(prf);
890 return 0;
891 }
892
893 buf = chunk_alloc(this->bench_size);
894 memset(buf.ptr, 0x34, buf.len);
895
896 runs = 0;
897 start_timing(&start);
898 while (end_timing(&start) < this->bench_time)
899 {
900 if (prf->get_bytes(prf, buf, bytes))
901 {
902 runs++;
903 }
904 }
905 free(buf.ptr);
906 prf->destroy(prf);
907
908 return runs;
909 }
910 return 0;
911 }
912
913 METHOD(crypto_tester_t, test_prf, bool,
914 private_crypto_tester_t *this, pseudo_random_function_t alg,
915 prf_constructor_t create, u_int *speed, const char *plugin_name)
916 {
917 enumerator_t *enumerator;
918 prf_test_vector_t *vector;
919 bool failed = FALSE;
920 u_int tested = 0;
921
922 enumerator = this->prf->create_enumerator(this->prf);
923 while (enumerator->enumerate(enumerator, &vector))
924 {
925 prf_t *prf;
926 chunk_t key, seed, out = chunk_empty;
927
928 if (vector->alg != alg)
929 {
930 continue;
931 }
932
933 tested++;
934 failed = TRUE;
935 prf = create(alg);
936 if (!prf)
937 {
938 DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
939 pseudo_random_function_names, alg, plugin_name);
940 break;
941 }
942
943 seed = chunk_create(vector->seed, vector->len);
944 key = chunk_create(vector->key, vector->key_size);
945 if (!prf->set_key(prf, key))
946 {
947 goto failure;
948 }
949 if (alg != PRF_FIPS_SHA1_160)
950 {
951 /* do partial append mode and check if key gets set correctly */
952 if (!prf->get_bytes(prf, seed, NULL))
953 {
954 goto failure;
955 }
956 if (!prf->set_key(prf, key))
957 {
958 goto failure;
959 }
960 }
961 /* allocated bytes */
962 if (!prf->allocate_bytes(prf, seed, &out))
963 {
964 goto failure;
965 }
966 if (out.len != prf->get_block_size(prf))
967 {
968 goto failure;
969 }
970 if (!memeq(vector->out, out.ptr, out.len))
971 {
972 goto failure;
973 }
974 /* bytes to existing buffer */
975 memset(out.ptr, 0, out.len);
976 if (vector->stateful)
977 {
978 if (!prf->set_key(prf, key))
979 {
980 goto failure;
981 }
982 }
983 if (!prf->get_bytes(prf, seed, out.ptr))
984 {
985 goto failure;
986 }
987 if (!memeq(vector->out, out.ptr, out.len))
988 {
989 goto failure;
990 }
991 /* bytes to existing buffer, using append mode */
992 if (alg != PRF_FIPS_SHA1_160 && seed.len > 2)
993 {
994 memset(out.ptr, 0, out.len);
995 if (vector->stateful)
996 {
997 if (!prf->set_key(prf, key))
998 {
999 goto failure;
1000 }
1001 }
1002 if (!prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL))
1003 {
1004 goto failure;
1005 }
1006 if (!prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL))
1007 {
1008 goto failure;
1009 }
1010 if (!prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr))
1011 {
1012 goto failure;
1013 }
1014 if (!memeq(vector->out, out.ptr, out.len))
1015 {
1016 goto failure;
1017 }
1018 }
1019
1020 failed = FALSE;
1021 failure:
1022 prf->destroy(prf);
1023 chunk_free(&out);
1024 if (failed)
1025 {
1026 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1027 pseudo_random_function_names, alg, plugin_name, get_name(vector));
1028 break;
1029 }
1030 }
1031 enumerator->destroy(enumerator);
1032 if (!tested)
1033 {
1034 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1035 this->required ? "disabled" : "enabled ",
1036 pseudo_random_function_names, alg, plugin_name);
1037 return !this->required;
1038 }
1039 if (!failed)
1040 {
1041 if (speed)
1042 {
1043 *speed = bench_prf(this, alg, create);
1044 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points",
1045 pseudo_random_function_names, alg, plugin_name, tested, *speed);
1046 }
1047 else
1048 {
1049 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
1050 pseudo_random_function_names, alg, plugin_name, tested);
1051 }
1052 }
1053 return !failed;
1054 }
1055
1056 /**
1057 * Benchmark an XOF
1058 */
1059 static u_int bench_xof(private_crypto_tester_t *this,
1060 ext_out_function_t alg, xof_constructor_t create)
1061 {
1062 xof_t *xof;
1063
1064 xof = create(alg);
1065 if (xof)
1066 {
1067 char seed[xof->get_seed_size(xof)];
1068 char bytes[xof->get_block_size(xof)];
1069 struct timespec start;
1070 u_int runs;
1071
1072 memset(seed, 0x56, xof->get_seed_size(xof));
1073 if (!xof->set_seed(xof, chunk_create(seed, xof->get_seed_size(xof))))
1074 {
1075 xof->destroy(xof);
1076 return 0;
1077 }
1078
1079 runs = 0;
1080 start_timing(&start);
1081 while (end_timing(&start) < this->bench_time)
1082 {
1083 if (xof->get_bytes(xof, xof->get_block_size(xof), bytes))
1084 {
1085 runs++;
1086 }
1087 }
1088 xof->destroy(xof);
1089
1090 return runs;
1091 }
1092 return 0;
1093 }
1094
1095 METHOD(crypto_tester_t, test_xof, bool,
1096 private_crypto_tester_t *this, ext_out_function_t alg,
1097 xof_constructor_t create, u_int *speed, const char *plugin_name)
1098 {
1099 enumerator_t *enumerator;
1100 xof_test_vector_t *vector;
1101 bool failed = FALSE;
1102 u_int tested = 0;
1103
1104 enumerator = this->xof->create_enumerator(this->xof);
1105 while (enumerator->enumerate(enumerator, &vector))
1106 {
1107 xof_t *xof;
1108 chunk_t seed, out = chunk_empty;
1109
1110 if (vector->alg != alg)
1111 {
1112 continue;
1113 }
1114
1115 tested++;
1116 failed = TRUE;
1117 xof = create(alg);
1118 if (!xof)
1119 {
1120 DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1121 ext_out_function_names, alg, plugin_name);
1122 break;
1123 }
1124
1125 seed = chunk_create(vector->seed, vector->len);
1126 if (!xof->set_seed(xof, seed))
1127 {
1128 goto failure;
1129 }
1130 /* allocated bytes */
1131 if (!xof->allocate_bytes(xof, vector->out_len, &out))
1132 {
1133 goto failure;
1134 }
1135 if (out.len != vector->out_len)
1136 {
1137 goto failure;
1138 }
1139 if (!memeq(vector->out, out.ptr, out.len))
1140 {
1141 goto failure;
1142 }
1143 /* bytes to existing buffer */
1144 memset(out.ptr, 0, out.len);
1145 if (!xof->set_seed(xof, seed))
1146 {
1147 goto failure;
1148 }
1149 if (!xof->get_bytes(xof, vector->out_len, out.ptr))
1150 {
1151 goto failure;
1152 }
1153 if (!memeq(vector->out, out.ptr, vector->out_len))
1154 {
1155 goto failure;
1156 }
1157 /* bytes to existing buffer, using append mode */
1158 /* TODO */
1159
1160 failed = FALSE;
1161 failure:
1162 xof->destroy(xof);
1163 chunk_free(&out);
1164 if (failed)
1165 {
1166 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1167 ext_out_function_names, alg, plugin_name, get_name(vector));
1168 break;
1169 }
1170 }
1171 enumerator->destroy(enumerator);
1172 if (!tested)
1173 {
1174 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1175 this->required ? "disabled" : "enabled ",
1176 ext_out_function_names, alg, plugin_name);
1177 return !this->required;
1178 }
1179 if (!failed)
1180 {
1181 if (speed)
1182 {
1183 *speed = bench_xof(this, alg, create);
1184 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points",
1185 ext_out_function_names, alg, plugin_name, tested, *speed);
1186 }
1187 else
1188 {
1189 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
1190 ext_out_function_names, alg, plugin_name, tested);
1191 }
1192 }
1193 return !failed;
1194 }
1195
1196
1197
1198 /**
1199 * Create a KDF using the given arguments
1200 */
1201 static kdf_t *create_kdf_args(kdf_constructor_t create,
1202 key_derivation_function_t alg, ...)
1203 {
1204 va_list args;
1205 kdf_t *kdf;
1206
1207 va_start(args, alg);
1208 kdf = create(alg, args);
1209 va_end(args);
1210 return kdf;
1211 }
1212
1213 /**
1214 * Create a KDF using arguments from the given test vector
1215 */
1216 static kdf_t *create_kdf_vector(kdf_constructor_t create,
1217 key_derivation_function_t alg,
1218 kdf_test_vector_t *vector)
1219 {
1220 switch (alg)
1221 {
1222 case KDF_PRF:
1223 case KDF_PRF_PLUS:
1224 return create_kdf_args(create, alg, vector->arg.prf);
1225 case KDF_UNDEFINED:
1226 break;
1227 }
1228 return NULL;
1229 }
1230
1231 /**
1232 * Check if the given test vector applies to the passed arguments
1233 */
1234 static bool kdf_vector_applies(key_derivation_function_t alg,
1235 kdf_test_args_t *args, kdf_test_vector_t *vector)
1236 {
1237 bool applies = FALSE;
1238
1239 switch (alg)
1240 {
1241 case KDF_PRF:
1242 case KDF_PRF_PLUS:
1243 {
1244 pseudo_random_function_t prf;
1245 VA_ARGS_VGET(args->args, prf);
1246 applies = (prf == vector->arg.prf);
1247 break;
1248 }
1249 case KDF_UNDEFINED:
1250 break;
1251 }
1252 return applies;
1253 }
1254
1255 METHOD(crypto_tester_t, test_kdf, bool,
1256 private_crypto_tester_t *this, key_derivation_function_t alg,
1257 kdf_constructor_t create, kdf_test_args_t *args, u_int *speed,
1258 const char *plugin_name)
1259 {
1260 enumerator_t *enumerator;
1261 kdf_test_vector_t *vector;
1262 va_list copy;
1263 bool failed = FALSE;
1264 u_int tested = 0, construction_failed = 0;
1265
1266 enumerator = this->kdf->create_enumerator(this->kdf);
1267 while (enumerator->enumerate(enumerator, &vector))
1268 {
1269 kdf_t *kdf;
1270 chunk_t out = chunk_empty;
1271
1272 if (vector->alg != alg ||
1273 (args && !kdf_vector_applies(alg, args, vector)))
1274 {
1275 continue;
1276 }
1277
1278 tested++;
1279 failed = TRUE;
1280 if (args)
1281 {
1282 va_copy(copy, args->args);
1283 kdf = create(alg, copy);
1284 va_end(copy);
1285 }
1286 else
1287 {
1288 kdf = create_kdf_vector(create, alg, vector);
1289 }
1290 if (!kdf)
1291 {
1292 if (args)
1293 {
1294 DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1295 key_derivation_function_names, alg, plugin_name);
1296 break;
1297 }
1298 /* while there could be a problem, the constructor might just not
1299 * be able to create an instance for this test vector, we check
1300 * for that at the end */
1301 construction_failed++;
1302 failed = FALSE;
1303 continue;
1304 }
1305
1306 if (vector->key.len &&
1307 !kdf->set_param(kdf, KDF_PARAM_KEY, vector->key))
1308 {
1309 goto failure;
1310 }
1311 if (vector->salt.len &&
1312 !kdf->set_param(kdf, KDF_PARAM_SALT, vector->salt))
1313 {
1314 goto failure;
1315 }
1316 if (kdf_has_fixed_output_length(alg))
1317 {
1318 if (kdf->get_length(kdf) != vector->out.len)
1319 {
1320 goto failure;
1321 }
1322 }
1323 else if (kdf->get_length(kdf) != SIZE_MAX)
1324 {
1325 goto failure;
1326 }
1327 /* allocated bytes */
1328 if (!kdf->allocate_bytes(kdf, vector->out.len, &out))
1329 {
1330 goto failure;
1331 }
1332 if (!chunk_equals(out, vector->out))
1333 {
1334 goto failure;
1335 }
1336 /* allocate without knowing the length */
1337 if (kdf_has_fixed_output_length(alg))
1338 {
1339 chunk_free(&out);
1340 if (!kdf->allocate_bytes(kdf, 0, &out))
1341 {
1342 goto failure;
1343 }
1344 if (!chunk_equals(out, vector->out))
1345 {
1346 goto failure;
1347 }
1348 }
1349 /* bytes to existing buffer */
1350 memset(out.ptr, 0, out.len);
1351 if (!kdf->get_bytes(kdf, out.len, out.ptr))
1352 {
1353 goto failure;
1354 }
1355 if (!chunk_equals(out, vector->out))
1356 {
1357 goto failure;
1358 }
1359
1360 failed = FALSE;
1361 failure:
1362 kdf->destroy(kdf);
1363 chunk_free(&out);
1364 if (failed)
1365 {
1366 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1367 key_derivation_function_names, alg, plugin_name,
1368 get_name(vector));
1369 break;
1370 }
1371 }
1372 enumerator->destroy(enumerator);
1373 if (!tested)
1374 {
1375 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1376 this->required ? "disabled" : "enabled ",
1377 key_derivation_function_names, alg, plugin_name);
1378 return !this->required;
1379 }
1380 tested -= construction_failed;
1381 if (!tested)
1382 {
1383 DBG1(DBG_LIB, "%s %N[%s]: unable to apply any available test vectors",
1384 this->required ? "disabled" : "enabled ",
1385 key_derivation_function_names, alg, plugin_name);
1386 return !this->required;
1387 }
1388 if (!failed)
1389 {
1390 if (speed)
1391 {
1392 DBG2(DBG_LIB, "benchmarking for %N is currently not supported",
1393 key_derivation_function_names, alg);
1394 }
1395 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
1396 key_derivation_function_names, alg, plugin_name, tested);
1397 }
1398 return !failed;
1399 }
1400
1401 /**
1402 * Benchmark a DRBG
1403 */
1404 static u_int bench_drbg(private_crypto_tester_t *this,
1405 drbg_type_t type, drbg_constructor_t create)
1406 {
1407 drbg_t *drbg;
1408 rng_t *entropy;
1409 uint32_t strength = 128;
1410 chunk_t seed = chunk_alloca(48);
1411
1412 memset(seed.ptr, 0x81, seed.len);
1413 entropy = rng_tester_create(seed);
1414
1415 drbg = create(type, strength, entropy, chunk_empty);
1416 if (drbg)
1417 {
1418 struct timespec start;
1419 u_int runs = 0;
1420 size_t out_len = 128;
1421 char out_buf[out_len];
1422
1423 start_timing(&start);
1424 while (end_timing(&start) < this->bench_time)
1425 {
1426 if (drbg->generate(drbg, out_len, out_buf))
1427 {
1428 runs++;
1429 }
1430 }
1431 drbg->destroy(drbg);
1432
1433 return runs;
1434 }
1435 return 0;
1436 }
1437
1438 METHOD(crypto_tester_t, test_drbg, bool,
1439 private_crypto_tester_t *this, drbg_type_t type,
1440 drbg_constructor_t create, u_int *speed, const char *plugin_name)
1441 {
1442 enumerator_t *enumerator;
1443 drbg_test_vector_t *vector;
1444 bool failed = FALSE;
1445 u_int tested = 0;
1446
1447 enumerator = this->drbg->create_enumerator(this->drbg);
1448 while (enumerator->enumerate(enumerator, &vector))
1449 {
1450 drbg_t *drbg;
1451 rng_t *entropy;
1452 chunk_t out = chunk_empty;
1453
1454 if (vector->type != type)
1455 {
1456 continue;
1457 }
1458 tested++;
1459 failed = TRUE;
1460
1461 entropy = rng_tester_create(vector->entropy);
1462 out = chunk_alloc(vector->out.len);
1463
1464 drbg = create(type, vector->strength, entropy,
1465 vector->personalization_str);
1466 if (!drbg)
1467 {
1468 DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1469 drbg_type_names, type, plugin_name);
1470 entropy->destroy(entropy);
1471 chunk_free(&out);
1472 break;
1473 }
1474 if (!drbg->reseed(drbg))
1475 {
1476 goto failure;
1477 }
1478 if (!drbg->generate(drbg, out.len, out.ptr))
1479 {
1480 goto failure;
1481 }
1482 if (!drbg->generate(drbg, out.len, out.ptr))
1483 {
1484 goto failure;
1485 }
1486 if (!chunk_equals(out, vector->out))
1487 {
1488 goto failure;
1489 }
1490 failed = FALSE;
1491
1492 failure:
1493 drbg->destroy(drbg);
1494 chunk_free(&out);
1495 if (failed)
1496 {
1497 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1498 drbg_type_names, type, plugin_name, get_name(vector));
1499 break;
1500 }
1501 }
1502 enumerator->destroy(enumerator);
1503 if (!tested)
1504 {
1505 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1506 this->required ? "disabled" : "enabled ",
1507 drbg_type_names, type, plugin_name);
1508 return !this->required;
1509 }
1510 if (!failed)
1511 {
1512 if (speed)
1513 {
1514 *speed = bench_drbg(this, type, create);
1515 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points",
1516 drbg_type_names, type, plugin_name, tested, *speed);
1517 }
1518 else
1519 {
1520 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
1521 drbg_type_names, type, plugin_name, tested);
1522 }
1523 }
1524 return !failed;
1525 }
1526
1527 /**
1528 * Benchmark a RNG
1529 */
1530 static u_int bench_rng(private_crypto_tester_t *this,
1531 rng_quality_t quality, rng_constructor_t create)
1532 {
1533 rng_t *rng;
1534
1535 rng = create(quality);
1536 if (rng)
1537 {
1538 struct timespec start;
1539 chunk_t buf;
1540 u_int runs;
1541
1542 runs = 0;
1543 buf = chunk_alloc(this->bench_size);
1544 start_timing(&start);
1545 while (end_timing(&start) < this->bench_time)
1546 {
1547 if (!rng->get_bytes(rng, buf.len, buf.ptr))
1548 {
1549 runs = 0;
1550 break;
1551 }
1552 runs++;
1553 }
1554 free(buf.ptr);
1555 rng->destroy(rng);
1556
1557 return runs;
1558 }
1559 return 0;
1560 }
1561
1562 METHOD(crypto_tester_t, test_rng, bool,
1563 private_crypto_tester_t *this, rng_quality_t quality,
1564 rng_constructor_t create, u_int *speed, const char *plugin_name)
1565 {
1566 enumerator_t *enumerator;
1567 rng_test_vector_t *vector;
1568 bool failed = FALSE;
1569 u_int tested = 0;
1570
1571 if (!this->rng_true && quality == RNG_TRUE)
1572 {
1573 DBG1(DBG_LIB, "enabled %N[%s]: skipping test (disabled by config)",
1574 rng_quality_names, quality, plugin_name);
1575 return TRUE;
1576 }
1577
1578 enumerator = this->rng->create_enumerator(this->rng);
1579 while (enumerator->enumerate(enumerator, &vector))
1580 {
1581 chunk_t data = chunk_empty;
1582 rng_t *rng;
1583
1584 if (vector->quality != quality)
1585 {
1586 continue;
1587 }
1588
1589 tested++;
1590 failed = TRUE;
1591 rng = create(quality);
1592 if (!rng)
1593 {
1594 DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1595 rng_quality_names, quality, plugin_name);
1596 break;
1597 }
1598
1599 /* allocated bytes */
1600 if (!rng->allocate_bytes(rng, vector->len, &data) ||
1601 data.len != vector->len ||
1602 !vector->test(vector->user, data))
1603 {
1604 goto failure;
1605 }
1606 /* write bytes into existing buffer */
1607 memset(data.ptr, 0, data.len);
1608 if (!rng->get_bytes(rng, vector->len, data.ptr))
1609 {
1610 goto failure;
1611 }
1612 if (!vector->test(vector->user, data))
1613 {
1614 goto failure;
1615 }
1616
1617 failed = FALSE;
1618 failure:
1619 rng->destroy(rng);
1620 chunk_free(&data);
1621 if (failed)
1622 {
1623 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1624 rng_quality_names, quality, plugin_name, get_name(vector));
1625 break;
1626 }
1627 }
1628 enumerator->destroy(enumerator);
1629 if (!tested)
1630 {
1631 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1632 this->required ? ", disabled" : "enabled ",
1633 rng_quality_names, quality, plugin_name);
1634 return !this->required;
1635 }
1636 if (!failed)
1637 {
1638 if (speed)
1639 {
1640 *speed = bench_rng(this, quality, create);
1641 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points",
1642 rng_quality_names, quality, plugin_name, tested, *speed);
1643 }
1644 else
1645 {
1646 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
1647 rng_quality_names, quality, plugin_name, tested);
1648 }
1649 }
1650 return !failed;
1651 }
1652
1653 /**
1654 * Benchmark a key exchange backend
1655 */
1656 static u_int bench_ke(private_crypto_tester_t *this,
1657 key_exchange_method_t method, ke_constructor_t create)
1658 {
1659 chunk_t pub = chunk_empty, shared = chunk_empty;
1660 key_exchange_t *ke;
1661 struct timespec start;
1662 u_int runs;
1663
1664 runs = 0;
1665 start_timing(&start);
1666 while (end_timing(&start) < this->bench_time)
1667 {
1668 ke = create(method);
1669 if (!ke)
1670 {
1671 return 0;
1672 }
1673 if (ke->get_public_key(ke, &pub) &&
1674 ke->set_public_key(ke, pub) &&
1675 ke->get_shared_secret(ke, &shared))
1676 {
1677 runs++;
1678 }
1679 chunk_free(&pub);
1680 chunk_free(&shared);
1681 ke->destroy(ke);
1682 }
1683 return runs;
1684 }
1685
1686 METHOD(crypto_tester_t, test_ke, bool,
1687 private_crypto_tester_t *this, key_exchange_method_t method,
1688 ke_constructor_t create, u_int *speed, const char *plugin_name)
1689 {
1690 enumerator_t *enumerator;
1691 ke_test_vector_t *v;
1692 bool failed = FALSE;
1693 u_int tested = 0;
1694
1695 enumerator = this->ke->create_enumerator(this->ke);
1696 while (enumerator->enumerate(enumerator, &v))
1697 {
1698 key_exchange_t *a, *b;
1699 chunk_t apub, bpub, asec, bsec;
1700
1701 if (v->method != method)
1702 {
1703 continue;
1704 }
1705
1706 a = create(method);
1707 b = create(method);
1708 if (!a || !b)
1709 {
1710 DESTROY_IF(a);
1711 DESTROY_IF(b);
1712 failed = TRUE;
1713 tested++;
1714 DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1715 key_exchange_method_names, method, plugin_name);
1716 break;
1717 }
1718
1719 if (!a->set_private_key || !b->set_private_key)
1720 { /* does not support testing */
1721 a->destroy(a);
1722 b->destroy(b);
1723 continue;
1724 }
1725 failed = TRUE;
1726 tested++;
1727
1728 apub = bpub = asec = bsec = chunk_empty;
1729
1730 if (!a->set_private_key(a, chunk_create(v->priv_a, v->priv_len)) ||
1731 !b->set_private_key(b, chunk_create(v->priv_b, v->priv_len)))
1732 {
1733 goto failure;
1734 }
1735 if (!a->get_public_key(a, &apub) ||
1736 !chunk_equals(apub, chunk_create(v->pub_a, v->pub_len)))
1737 {
1738 goto failure;
1739 }
1740 if (!b->get_public_key(b, &bpub) ||
1741 !chunk_equals(bpub, chunk_create(v->pub_b, v->pub_len)))
1742 {
1743 goto failure;
1744 }
1745 if (!a->set_public_key(a, bpub) ||
1746 !b->set_public_key(b, apub))
1747 {
1748 goto failure;
1749 }
1750 if (!a->get_shared_secret(a, &asec) ||
1751 !chunk_equals(asec, chunk_create(v->shared, v->shared_len)))
1752 {
1753 goto failure;
1754 }
1755 if (!b->get_shared_secret(b, &bsec) ||
1756 !chunk_equals(bsec, chunk_create(v->shared, v->shared_len)))
1757 {
1758 goto failure;
1759 }
1760
1761 failed = FALSE;
1762 failure:
1763 a->destroy(a);
1764 b->destroy(b);
1765 chunk_free(&apub);
1766 chunk_free(&bpub);
1767 chunk_free(&asec);
1768 chunk_free(&bsec);
1769 if (failed)
1770 {
1771 DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1772 key_exchange_method_names, method, plugin_name, get_name(v));
1773 break;
1774 }
1775 }
1776 enumerator->destroy(enumerator);
1777 if (!tested)
1778 {
1779 DBG1(DBG_LIB, "%s %N[%s]: no test vectors found / untestable",
1780 this->required ? "disabled" : "enabled ",
1781 key_exchange_method_names, method, plugin_name);
1782 return !this->required;
1783 }
1784 if (!failed)
1785 {
1786 if (speed)
1787 {
1788 *speed = bench_ke(this, method, create);
1789 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points",
1790 key_exchange_method_names, method, plugin_name, tested, *speed);
1791 }
1792 else
1793 {
1794 DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
1795 key_exchange_method_names, method, plugin_name, tested);
1796 }
1797 }
1798 return !failed;
1799 }
1800
1801 METHOD(crypto_tester_t, add_crypter_vector, void,
1802 private_crypto_tester_t *this, crypter_test_vector_t *vector)
1803 {
1804 this->crypter->insert_last(this->crypter, vector);
1805 }
1806
1807 METHOD(crypto_tester_t, add_aead_vector, void,
1808 private_crypto_tester_t *this, aead_test_vector_t *vector)
1809 {
1810 this->aead->insert_last(this->aead, vector);
1811 }
1812
1813 METHOD(crypto_tester_t, add_signer_vector, void,
1814 private_crypto_tester_t *this, signer_test_vector_t *vector)
1815 {
1816 this->signer->insert_last(this->signer, vector);
1817 }
1818
1819 METHOD(crypto_tester_t, add_hasher_vector, void,
1820 private_crypto_tester_t *this, hasher_test_vector_t *vector)
1821 {
1822 this->hasher->insert_last(this->hasher, vector);
1823 }
1824
1825 METHOD(crypto_tester_t, add_prf_vector, void,
1826 private_crypto_tester_t *this, prf_test_vector_t *vector)
1827 {
1828 this->prf->insert_last(this->prf, vector);
1829 }
1830
1831 METHOD(crypto_tester_t, add_xof_vector, void,
1832 private_crypto_tester_t *this, xof_test_vector_t *vector)
1833 {
1834 this->xof->insert_last(this->xof, vector);
1835 }
1836
1837 METHOD(crypto_tester_t, add_kdf_vector, void,
1838 private_crypto_tester_t *this, kdf_test_vector_t *vector)
1839 {
1840 this->kdf->insert_last(this->kdf, vector);
1841 }
1842
1843 METHOD(crypto_tester_t, add_drbg_vector, void,
1844 private_crypto_tester_t *this, drbg_test_vector_t *vector)
1845 {
1846 this->drbg->insert_last(this->drbg, vector);
1847 }
1848
1849 METHOD(crypto_tester_t, add_rng_vector, void,
1850 private_crypto_tester_t *this, rng_test_vector_t *vector)
1851 {
1852 this->rng->insert_last(this->rng, vector);
1853 }
1854
1855 METHOD(crypto_tester_t, add_ke_vector, void,
1856 private_crypto_tester_t *this, ke_test_vector_t *vector)
1857 {
1858 this->ke->insert_last(this->ke, vector);
1859 }
1860
1861 METHOD(crypto_tester_t, destroy, void,
1862 private_crypto_tester_t *this)
1863 {
1864 this->crypter->destroy(this->crypter);
1865 this->aead->destroy(this->aead);
1866 this->signer->destroy(this->signer);
1867 this->hasher->destroy(this->hasher);
1868 this->prf->destroy(this->prf);
1869 this->xof->destroy(this->xof);
1870 this->kdf->destroy(this->kdf);
1871 this->drbg->destroy(this->drbg);
1872 this->rng->destroy(this->rng);
1873 this->ke->destroy(this->ke);
1874 free(this);
1875 }
1876
1877 /**
1878 * See header
1879 */
1880 crypto_tester_t *crypto_tester_create()
1881 {
1882 private_crypto_tester_t *this;
1883
1884 INIT(this,
1885 .public = {
1886 .test_crypter = _test_crypter,
1887 .test_aead = _test_aead,
1888 .test_signer = _test_signer,
1889 .test_hasher = _test_hasher,
1890 .test_prf = _test_prf,
1891 .test_xof = _test_xof,
1892 .test_kdf = _test_kdf,
1893 .test_drbg = _test_drbg,
1894 .test_rng = _test_rng,
1895 .test_ke = _test_ke,
1896 .add_crypter_vector = _add_crypter_vector,
1897 .add_aead_vector = _add_aead_vector,
1898 .add_signer_vector = _add_signer_vector,
1899 .add_hasher_vector = _add_hasher_vector,
1900 .add_prf_vector = _add_prf_vector,
1901 .add_xof_vector = _add_xof_vector,
1902 .add_kdf_vector = _add_kdf_vector,
1903 .add_drbg_vector = _add_drbg_vector,
1904 .add_rng_vector = _add_rng_vector,
1905 .add_ke_vector = _add_ke_vector,
1906 .destroy = _destroy,
1907 },
1908 .crypter = linked_list_create(),
1909 .aead = linked_list_create(),
1910 .signer = linked_list_create(),
1911 .hasher = linked_list_create(),
1912 .prf = linked_list_create(),
1913 .xof = linked_list_create(),
1914 .kdf = linked_list_create(),
1915 .drbg = linked_list_create(),
1916 .rng = linked_list_create(),
1917 .ke = linked_list_create(),
1918
1919 .required = lib->settings->get_bool(lib->settings,
1920 "%s.crypto_test.required", FALSE, lib->ns),
1921 .rng_true = lib->settings->get_bool(lib->settings,
1922 "%s.crypto_test.rng_true", FALSE, lib->ns),
1923 .bench_time = lib->settings->get_int(lib->settings,
1924 "%s.crypto_test.bench_time", 50, lib->ns),
1925 .bench_size = lib->settings->get_int(lib->settings,
1926 "%s.crypto_test.bench_size", 1024, lib->ns),
1927 );
1928
1929 /* enforce a block size of 16, should be fine for all algorithms */
1930 this->bench_size = this->bench_size / 16 * 16;
1931
1932 return &this->public;
1933 }