ikev2: Recreate a CHILD_SA that got a hard lifetime expire without rekeying
[strongswan.git] / src / libstrongswan / crypto / crypto_factory.c
1 /*
2 * Copyright (C) 2013-2014 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "crypto_factory.h"
18
19 #include <utils/debug.h>
20 #include <threading/rwlock.h>
21 #include <collections/linked_list.h>
22 #include <crypto/crypto_tester.h>
23 #include <utils/test.h>
24
25 const char *default_plugin_name = "default";
26
27 typedef struct entry_t entry_t;
28
29 struct entry_t {
30 /**
31 * algorithm
32 */
33 u_int algo;
34
35 /**
36 * plugin that registered this algorithm
37 */
38 const char *plugin_name;
39
40 /**
41 * benchmarked speed
42 */
43 u_int speed;
44
45 /**
46 * constructor
47 */
48 union {
49 crypter_constructor_t create_crypter;
50 aead_constructor_t create_aead;
51 signer_constructor_t create_signer;
52 hasher_constructor_t create_hasher;
53 prf_constructor_t create_prf;
54 rng_constructor_t create_rng;
55 nonce_gen_constructor_t create_nonce_gen;
56 dh_constructor_t create_dh;
57 void *create;
58 };
59 };
60
61 typedef struct private_crypto_factory_t private_crypto_factory_t;
62
63 /**
64 * private data of crypto_factory
65 */
66 struct private_crypto_factory_t {
67
68 /**
69 * public functions
70 */
71 crypto_factory_t public;
72
73 /**
74 * registered crypters, as entry_t
75 */
76 linked_list_t *crypters;
77
78 /**
79 * registered aead transforms, as entry_t
80 */
81 linked_list_t *aeads;
82
83 /**
84 * registered signers, as entry_t
85 */
86 linked_list_t *signers;
87
88 /**
89 * registered hashers, as entry_t
90 */
91 linked_list_t *hashers;
92
93 /**
94 * registered prfs, as entry_t
95 */
96 linked_list_t *prfs;
97
98 /**
99 * registered rngs, as entry_t
100 */
101 linked_list_t *rngs;
102
103 /**
104 * registered nonce generators, as entry_t
105 */
106 linked_list_t *nonce_gens;
107
108 /**
109 * registered diffie hellman, as entry_t
110 */
111 linked_list_t *dhs;
112
113 /**
114 * test manager to test crypto algorithms
115 */
116 crypto_tester_t *tester;
117
118 /**
119 * whether to test algorithms during registration
120 */
121 bool test_on_add;
122
123 /**
124 * whether to test algorithms on each crypto primitive construction
125 */
126 bool test_on_create;
127
128 /**
129 * run algorithm benchmark during registration
130 */
131 bool bench;
132
133 /**
134 * Number of failed test vectors during "add".
135 */
136 u_int test_failures;
137
138 /**
139 * rwlock to lock access to modules
140 */
141 rwlock_t *lock;
142 };
143
144 METHOD(crypto_factory_t, create_crypter, crypter_t*,
145 private_crypto_factory_t *this, encryption_algorithm_t algo,
146 size_t key_size)
147 {
148 enumerator_t *enumerator;
149 entry_t *entry;
150 crypter_t *crypter = NULL;
151
152 this->lock->read_lock(this->lock);
153 enumerator = this->crypters->create_enumerator(this->crypters);
154 while (enumerator->enumerate(enumerator, &entry))
155 {
156 if (entry->algo == algo)
157 {
158 if (this->test_on_create &&
159 !this->tester->test_crypter(this->tester, algo, key_size,
160 entry->create_crypter, NULL,
161 default_plugin_name))
162 {
163 continue;
164 }
165 crypter = entry->create_crypter(algo, key_size);
166 if (crypter)
167 {
168 break;
169 }
170 }
171 }
172 enumerator->destroy(enumerator);
173 this->lock->unlock(this->lock);
174 return crypter;
175 }
176
177 METHOD(crypto_factory_t, create_aead, aead_t*,
178 private_crypto_factory_t *this, encryption_algorithm_t algo,
179 size_t key_size)
180 {
181 enumerator_t *enumerator;
182 entry_t *entry;
183 aead_t *aead = NULL;
184
185 this->lock->read_lock(this->lock);
186 enumerator = this->aeads->create_enumerator(this->aeads);
187 while (enumerator->enumerate(enumerator, &entry))
188 {
189 if (entry->algo == algo)
190 {
191 if (this->test_on_create &&
192 !this->tester->test_aead(this->tester, algo, key_size,
193 entry->create_aead, NULL,
194 default_plugin_name))
195 {
196 continue;
197 }
198 aead = entry->create_aead(algo, key_size);
199 if (aead)
200 {
201 break;
202 }
203 }
204 }
205 enumerator->destroy(enumerator);
206 this->lock->unlock(this->lock);
207 return aead;
208 }
209
210 METHOD(crypto_factory_t, create_signer, signer_t*,
211 private_crypto_factory_t *this, integrity_algorithm_t algo)
212 {
213 enumerator_t *enumerator;
214 entry_t *entry;
215 signer_t *signer = NULL;
216
217 this->lock->read_lock(this->lock);
218 enumerator = this->signers->create_enumerator(this->signers);
219 while (enumerator->enumerate(enumerator, &entry))
220 {
221 if (entry->algo == algo)
222 {
223 if (this->test_on_create &&
224 !this->tester->test_signer(this->tester, algo,
225 entry->create_signer, NULL,
226 default_plugin_name))
227 {
228 continue;
229 }
230 signer = entry->create_signer(algo);
231 if (signer)
232 {
233 break;
234 }
235 }
236 }
237 enumerator->destroy(enumerator);
238 this->lock->unlock(this->lock);
239 return signer;
240 }
241
242 METHOD(crypto_factory_t, create_hasher, hasher_t*,
243 private_crypto_factory_t *this, hash_algorithm_t algo)
244 {
245 enumerator_t *enumerator;
246 entry_t *entry;
247 hasher_t *hasher = NULL;
248
249 this->lock->read_lock(this->lock);
250 enumerator = this->hashers->create_enumerator(this->hashers);
251 while (enumerator->enumerate(enumerator, &entry))
252 {
253 if (entry->algo == algo)
254 {
255 if (this->test_on_create &&
256 !this->tester->test_hasher(this->tester, algo,
257 entry->create_hasher, NULL,
258 default_plugin_name))
259 {
260 continue;
261 }
262 hasher = entry->create_hasher(entry->algo);
263 if (hasher)
264 {
265 break;
266 }
267 }
268 }
269 enumerator->destroy(enumerator);
270 this->lock->unlock(this->lock);
271 return hasher;
272 }
273
274 METHOD(crypto_factory_t, create_prf, prf_t*,
275 private_crypto_factory_t *this, pseudo_random_function_t algo)
276 {
277 enumerator_t *enumerator;
278 entry_t *entry;
279 prf_t *prf = NULL;
280
281 this->lock->read_lock(this->lock);
282 enumerator = this->prfs->create_enumerator(this->prfs);
283 while (enumerator->enumerate(enumerator, &entry))
284 {
285 if (entry->algo == algo)
286 {
287 if (this->test_on_create &&
288 !this->tester->test_prf(this->tester, algo,
289 entry->create_prf, NULL,
290 default_plugin_name))
291 {
292 continue;
293 }
294 prf = entry->create_prf(algo);
295 if (prf)
296 {
297 break;
298 }
299 }
300 }
301 enumerator->destroy(enumerator);
302 this->lock->unlock(this->lock);
303 return prf;
304 }
305
306 METHOD(crypto_factory_t, create_rng, rng_t*,
307 private_crypto_factory_t *this, rng_quality_t quality)
308 {
309 enumerator_t *enumerator;
310 entry_t *entry;
311 rng_t *rng = NULL;
312
313 this->lock->read_lock(this->lock);
314 enumerator = this->rngs->create_enumerator(this->rngs);
315 while (enumerator->enumerate(enumerator, &entry))
316 { /* find the best matching quality, but at least as good as requested */
317 if (entry->algo >= quality)
318 {
319 if (this->test_on_create &&
320 !this->tester->test_rng(this->tester, quality,
321 entry->create_rng, NULL,
322 default_plugin_name))
323 {
324 continue;
325 }
326 rng = entry->create_rng(quality);
327 if (rng)
328 {
329 break;
330 }
331 }
332 }
333 enumerator->destroy(enumerator);
334 this->lock->unlock(this->lock);
335 return rng;
336 }
337
338 METHOD(crypto_factory_t, create_nonce_gen, nonce_gen_t*,
339 private_crypto_factory_t *this)
340 {
341 enumerator_t *enumerator;
342 entry_t *entry;
343 nonce_gen_t *nonce_gen = NULL;
344
345 this->lock->read_lock(this->lock);
346 enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
347 while (enumerator->enumerate(enumerator, &entry))
348 {
349 nonce_gen = entry->create_nonce_gen();
350 }
351 enumerator->destroy(enumerator);
352 this->lock->unlock(this->lock);
353
354 return nonce_gen;
355 }
356
357 METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
358 private_crypto_factory_t *this, diffie_hellman_group_t group, ...)
359 {
360 enumerator_t *enumerator;
361 entry_t *entry;
362 va_list args;
363 chunk_t g = chunk_empty, p = chunk_empty;
364 diffie_hellman_t *diffie_hellman = NULL;
365
366 if (group == MODP_CUSTOM)
367 {
368 va_start(args, group);
369 g = va_arg(args, chunk_t);
370 p = va_arg(args, chunk_t);
371 va_end(args);
372 }
373
374 this->lock->read_lock(this->lock);
375 enumerator = this->dhs->create_enumerator(this->dhs);
376 while (enumerator->enumerate(enumerator, &entry))
377 {
378 if (entry->algo == group)
379 {
380 diffie_hellman = entry->create_dh(group, g, p);
381 if (diffie_hellman)
382 {
383 break;
384 }
385 }
386 }
387 enumerator->destroy(enumerator);
388 this->lock->unlock(this->lock);
389 return diffie_hellman;
390 }
391
392 /**
393 * Insert an algorithm entry to a list
394 *
395 * Entries are sorted by algorithm identifier (which is important for RNGs)
396 * while maintaining the order in which algorithms were added, unless they were
397 * benchmarked and speed is provided, which then is used to order entries of
398 * the same algorithm.
399 */
400 static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
401 int algo, const char *plugin_name,
402 u_int speed, void *create)
403 {
404 enumerator_t *enumerator;
405 entry_t *entry, *current;
406
407 INIT(entry,
408 .algo = algo,
409 .plugin_name = plugin_name,
410 .speed = speed,
411 );
412 entry->create = create;
413
414 this->lock->write_lock(this->lock);
415 enumerator = list->create_enumerator(list);
416 while (enumerator->enumerate(enumerator, &current))
417 {
418 if (current->algo > algo)
419 {
420 break;
421 }
422 else if (current->algo == algo && speed &&
423 current->speed < speed)
424 {
425 break;
426 }
427 }
428 list->insert_before(list, enumerator, entry);
429 enumerator->destroy(enumerator);
430 this->lock->unlock(this->lock);
431 }
432
433 METHOD(crypto_factory_t, add_crypter, bool,
434 private_crypto_factory_t *this, encryption_algorithm_t algo,
435 const char *plugin_name, crypter_constructor_t create)
436 {
437 u_int speed = 0;
438
439 if (!this->test_on_add ||
440 this->tester->test_crypter(this->tester, algo, 0, create,
441 this->bench ? &speed : NULL, plugin_name))
442 {
443 add_entry(this, this->crypters, algo, plugin_name, speed, create);
444 return TRUE;
445 }
446 this->test_failures++;
447 return FALSE;
448 }
449
450 METHOD(crypto_factory_t, remove_crypter, void,
451 private_crypto_factory_t *this, crypter_constructor_t create)
452 {
453 entry_t *entry;
454 enumerator_t *enumerator;
455
456 this->lock->write_lock(this->lock);
457 enumerator = this->crypters->create_enumerator(this->crypters);
458 while (enumerator->enumerate(enumerator, &entry))
459 {
460 if (entry->create_crypter == create)
461 {
462 this->crypters->remove_at(this->crypters, enumerator);
463 free(entry);
464 }
465 }
466 enumerator->destroy(enumerator);
467 this->lock->unlock(this->lock);
468 }
469
470 METHOD(crypto_factory_t, add_aead, bool,
471 private_crypto_factory_t *this, encryption_algorithm_t algo,
472 const char *plugin_name, aead_constructor_t create)
473 {
474 u_int speed = 0;
475
476 if (!this->test_on_add ||
477 this->tester->test_aead(this->tester, algo, 0, create,
478 this->bench ? &speed : NULL, plugin_name))
479 {
480 add_entry(this, this->aeads, algo, plugin_name, speed, create);
481 return TRUE;
482 }
483 this->test_failures++;
484 return FALSE;
485 }
486
487 METHOD(crypto_factory_t, remove_aead, void,
488 private_crypto_factory_t *this, aead_constructor_t create)
489 {
490 entry_t *entry;
491 enumerator_t *enumerator;
492
493 this->lock->write_lock(this->lock);
494 enumerator = this->aeads->create_enumerator(this->aeads);
495 while (enumerator->enumerate(enumerator, &entry))
496 {
497 if (entry->create_aead == create)
498 {
499 this->aeads->remove_at(this->aeads, enumerator);
500 free(entry);
501 }
502 }
503 enumerator->destroy(enumerator);
504 this->lock->unlock(this->lock);
505 }
506
507 METHOD(crypto_factory_t, add_signer, bool,
508 private_crypto_factory_t *this, integrity_algorithm_t algo,
509 const char *plugin_name, signer_constructor_t create)
510 {
511 u_int speed = 0;
512
513 if (!this->test_on_add ||
514 this->tester->test_signer(this->tester, algo, create,
515 this->bench ? &speed : NULL, plugin_name))
516 {
517 add_entry(this, this->signers, algo, plugin_name, speed, create);
518 return TRUE;
519 }
520 this->test_failures++;
521 return FALSE;
522 }
523
524 METHOD(crypto_factory_t, remove_signer, void,
525 private_crypto_factory_t *this, signer_constructor_t create)
526 {
527 entry_t *entry;
528 enumerator_t *enumerator;
529
530 this->lock->write_lock(this->lock);
531 enumerator = this->signers->create_enumerator(this->signers);
532 while (enumerator->enumerate(enumerator, &entry))
533 {
534 if (entry->create_signer == create)
535 {
536 this->signers->remove_at(this->signers, enumerator);
537 free(entry);
538 }
539 }
540 enumerator->destroy(enumerator);
541 this->lock->unlock(this->lock);
542 }
543
544 METHOD(crypto_factory_t, add_hasher, bool,
545 private_crypto_factory_t *this, hash_algorithm_t algo,
546 const char *plugin_name, hasher_constructor_t create)
547 {
548 u_int speed = 0;
549
550 if (!this->test_on_add ||
551 this->tester->test_hasher(this->tester, algo, create,
552 this->bench ? &speed : NULL, plugin_name))
553 {
554 add_entry(this, this->hashers, algo, plugin_name, speed, create);
555 return TRUE;
556 }
557 this->test_failures++;
558 return FALSE;
559 }
560
561 METHOD(crypto_factory_t, remove_hasher, void,
562 private_crypto_factory_t *this, hasher_constructor_t create)
563 {
564 entry_t *entry;
565 enumerator_t *enumerator;
566
567 this->lock->write_lock(this->lock);
568 enumerator = this->hashers->create_enumerator(this->hashers);
569 while (enumerator->enumerate(enumerator, &entry))
570 {
571 if (entry->create_hasher == create)
572 {
573 this->hashers->remove_at(this->hashers, enumerator);
574 free(entry);
575 }
576 }
577 enumerator->destroy(enumerator);
578 this->lock->unlock(this->lock);
579 }
580
581 METHOD(crypto_factory_t, add_prf, bool,
582 private_crypto_factory_t *this, pseudo_random_function_t algo,
583 const char *plugin_name, prf_constructor_t create)
584 {
585 u_int speed = 0;
586
587 if (!this->test_on_add ||
588 this->tester->test_prf(this->tester, algo, create,
589 this->bench ? &speed : NULL, plugin_name))
590 {
591 add_entry(this, this->prfs, algo, plugin_name, speed, create);
592 return TRUE;
593 }
594 this->test_failures++;
595 return FALSE;
596 }
597
598 METHOD(crypto_factory_t, remove_prf, void,
599 private_crypto_factory_t *this, prf_constructor_t create)
600 {
601 entry_t *entry;
602 enumerator_t *enumerator;
603
604 this->lock->write_lock(this->lock);
605 enumerator = this->prfs->create_enumerator(this->prfs);
606 while (enumerator->enumerate(enumerator, &entry))
607 {
608 if (entry->create_prf == create)
609 {
610 this->prfs->remove_at(this->prfs, enumerator);
611 free(entry);
612 }
613 }
614 enumerator->destroy(enumerator);
615 this->lock->unlock(this->lock);
616 }
617
618 METHOD(crypto_factory_t, add_rng, bool,
619 private_crypto_factory_t *this, rng_quality_t quality,
620 const char *plugin_name, rng_constructor_t create)
621 {
622 u_int speed = 0;
623
624 if (!this->test_on_add ||
625 this->tester->test_rng(this->tester, quality, create,
626 this->bench ? &speed : NULL, plugin_name))
627 {
628 add_entry(this, this->rngs, quality, plugin_name, speed, create);
629 return TRUE;
630 }
631 this->test_failures++;
632 return FALSE;
633 }
634
635 METHOD(crypto_factory_t, remove_rng, void,
636 private_crypto_factory_t *this, rng_constructor_t create)
637 {
638 entry_t *entry;
639 enumerator_t *enumerator;
640
641 this->lock->write_lock(this->lock);
642 enumerator = this->rngs->create_enumerator(this->rngs);
643 while (enumerator->enumerate(enumerator, &entry))
644 {
645 if (entry->create_rng == create)
646 {
647 this->rngs->remove_at(this->rngs, enumerator);
648 free(entry);
649 }
650 }
651 enumerator->destroy(enumerator);
652 this->lock->unlock(this->lock);
653 }
654
655 METHOD(crypto_factory_t, add_nonce_gen, bool,
656 private_crypto_factory_t *this, const char *plugin_name,
657 nonce_gen_constructor_t create)
658 {
659 add_entry(this, this->nonce_gens, 0, plugin_name, 0, create);
660 return TRUE;
661 }
662
663 METHOD(crypto_factory_t, remove_nonce_gen, void,
664 private_crypto_factory_t *this, nonce_gen_constructor_t create)
665 {
666 entry_t *entry;
667 enumerator_t *enumerator;
668
669 this->lock->write_lock(this->lock);
670 enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
671 while (enumerator->enumerate(enumerator, &entry))
672 {
673 if (entry->create_nonce_gen == create)
674 {
675 this->nonce_gens->remove_at(this->nonce_gens, enumerator);
676 free(entry);
677 }
678 }
679 enumerator->destroy(enumerator);
680 this->lock->unlock(this->lock);
681 }
682
683 METHOD(crypto_factory_t, add_dh, bool,
684 private_crypto_factory_t *this, diffie_hellman_group_t group,
685 const char *plugin_name, dh_constructor_t create)
686 {
687 add_entry(this, this->dhs, group, plugin_name, 0, create);
688 return TRUE;
689 }
690
691 METHOD(crypto_factory_t, remove_dh, void,
692 private_crypto_factory_t *this, dh_constructor_t create)
693 {
694 entry_t *entry;
695 enumerator_t *enumerator;
696
697 this->lock->write_lock(this->lock);
698 enumerator = this->dhs->create_enumerator(this->dhs);
699 while (enumerator->enumerate(enumerator, &entry))
700 {
701 if (entry->create_dh == create)
702 {
703 this->dhs->remove_at(this->dhs, enumerator);
704 free(entry);
705 }
706 }
707 enumerator->destroy(enumerator);
708 this->lock->unlock(this->lock);
709 }
710
711 /**
712 * match algorithms of an entry?
713 */
714 static bool entry_match(entry_t *a, entry_t *b)
715 {
716 return a->algo == b->algo;
717 }
718
719 /**
720 * check for uniqueness of an entry
721 */
722 static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out)
723 {
724 if (list->find_first(list, (void*)entry_match, NULL, *in) == SUCCESS)
725 {
726 return FALSE;
727 }
728 *out = *in;
729 list->insert_last(list, *in);
730 return TRUE;
731 }
732
733 /**
734 * create an enumerator over entry->algo in list with locking and unique check
735 */
736 static enumerator_t *create_enumerator(private_crypto_factory_t *this,
737 linked_list_t *list, void *filter)
738 {
739 this->lock->read_lock(this->lock);
740 return enumerator_create_filter(
741 enumerator_create_filter(
742 list->create_enumerator(list), (void*)unique_check,
743 linked_list_create(), (void*)list->destroy),
744 filter, this->lock, (void*)this->lock->unlock);
745 }
746
747 /**
748 * Filter function to enumerate algorithm, not entry
749 */
750 static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo,
751 void *i2, const char **plugin_name)
752 {
753 *algo = (*entry)->algo;
754 *plugin_name = (*entry)->plugin_name;
755 return TRUE;
756 }
757
758 METHOD(crypto_factory_t, create_crypter_enumerator, enumerator_t*,
759 private_crypto_factory_t *this)
760 {
761 return create_enumerator(this, this->crypters, crypter_filter);
762 }
763
764 METHOD(crypto_factory_t, create_aead_enumerator, enumerator_t*,
765 private_crypto_factory_t *this)
766 {
767 return create_enumerator(this, this->aeads, crypter_filter);
768 }
769
770 /**
771 * Filter function to enumerate algorithm, not entry
772 */
773 static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo,
774 void *i2, const char **plugin_name)
775 {
776 *algo = (*entry)->algo;
777 *plugin_name = (*entry)->plugin_name;
778 return TRUE;
779 }
780
781 METHOD(crypto_factory_t, create_signer_enumerator, enumerator_t*,
782 private_crypto_factory_t *this)
783 {
784 return create_enumerator(this, this->signers, signer_filter);
785 }
786
787 /**
788 * Filter function to enumerate algorithm, not entry
789 */
790 static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo,
791 void *i2, const char **plugin_name)
792 {
793 *algo = (*entry)->algo;
794 *plugin_name = (*entry)->plugin_name;
795 return TRUE;
796 }
797
798 METHOD(crypto_factory_t, create_hasher_enumerator, enumerator_t*,
799 private_crypto_factory_t *this)
800 {
801 return create_enumerator(this, this->hashers, hasher_filter);
802 }
803
804 /**
805 * Filter function to enumerate algorithm, not entry
806 */
807 static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo,
808 void *i2, const char **plugin_name)
809 {
810 *algo = (*entry)->algo;
811 *plugin_name = (*entry)->plugin_name;
812 return TRUE;
813 }
814
815 METHOD(crypto_factory_t, create_prf_enumerator, enumerator_t*,
816 private_crypto_factory_t *this)
817 {
818 return create_enumerator(this, this->prfs, prf_filter);
819 }
820
821 /**
822 * Filter function to enumerate group, not entry
823 */
824 static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group,
825 void *i2, const char **plugin_name)
826 {
827 *group = (*entry)->algo;
828 *plugin_name = (*entry)->plugin_name;
829 return TRUE;
830 }
831
832 METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
833 private_crypto_factory_t *this)
834 {
835 return create_enumerator(this, this->dhs, dh_filter);
836 }
837
838 /**
839 * Filter function to enumerate strength, not entry
840 */
841 static bool rng_filter(void *n, entry_t **entry, rng_quality_t *quality,
842 void *i2, const char **plugin_name)
843 {
844 *quality = (*entry)->algo;
845 *plugin_name = (*entry)->plugin_name;
846 return TRUE;
847 }
848
849 METHOD(crypto_factory_t, create_rng_enumerator, enumerator_t*,
850 private_crypto_factory_t *this)
851 {
852 return create_enumerator(this, this->rngs, rng_filter);
853 }
854
855 /**
856 * Filter function to enumerate plugin name, not entry
857 */
858 static bool nonce_gen_filter(void *n, entry_t **entry, const char **plugin_name)
859 {
860 *plugin_name = (*entry)->plugin_name;
861 return TRUE;
862 }
863
864 METHOD(crypto_factory_t, create_nonce_gen_enumerator, enumerator_t*,
865 private_crypto_factory_t *this)
866 {
867 return create_enumerator(this, this->nonce_gens, nonce_gen_filter);
868 }
869
870 METHOD(crypto_factory_t, add_test_vector, void,
871 private_crypto_factory_t *this, transform_type_t type, void *vector)
872 {
873 switch (type)
874 {
875 case ENCRYPTION_ALGORITHM:
876 return this->tester->add_crypter_vector(this->tester, vector);
877 case AEAD_ALGORITHM:
878 return this->tester->add_aead_vector(this->tester, vector);
879 case INTEGRITY_ALGORITHM:
880 return this->tester->add_signer_vector(this->tester, vector);
881 case HASH_ALGORITHM:
882 return this->tester->add_hasher_vector(this->tester, vector);
883 case PSEUDO_RANDOM_FUNCTION:
884 return this->tester->add_prf_vector(this->tester, vector);
885 case RANDOM_NUMBER_GENERATOR:
886 return this->tester->add_rng_vector(this->tester, vector);
887 default:
888 DBG1(DBG_LIB, "%N test vectors not supported, ignored",
889 transform_type_names, type);
890 }
891 }
892
893 METHOD(crypto_factory_t, get_test_vector_failures, u_int,
894 private_crypto_factory_t *this)
895 {
896 return this->test_failures;
897 }
898
899 METHOD(crypto_factory_t, destroy, void,
900 private_crypto_factory_t *this)
901 {
902 this->crypters->destroy(this->crypters);
903 this->aeads->destroy(this->aeads);
904 this->signers->destroy(this->signers);
905 this->hashers->destroy(this->hashers);
906 this->prfs->destroy(this->prfs);
907 this->rngs->destroy(this->rngs);
908 this->nonce_gens->destroy(this->nonce_gens);
909 this->dhs->destroy(this->dhs);
910 this->tester->destroy(this->tester);
911 this->lock->destroy(this->lock);
912 free(this);
913 }
914
915 /*
916 * see header file
917 */
918 crypto_factory_t *crypto_factory_create()
919 {
920 private_crypto_factory_t *this;
921
922 INIT(this,
923 .public = {
924 .create_crypter = _create_crypter,
925 .create_aead = _create_aead,
926 .create_signer = _create_signer,
927 .create_hasher = _create_hasher,
928 .create_prf = _create_prf,
929 .create_rng = _create_rng,
930 .create_nonce_gen = _create_nonce_gen,
931 .create_dh = _create_dh,
932 .add_crypter = _add_crypter,
933 .remove_crypter = _remove_crypter,
934 .add_aead = _add_aead,
935 .remove_aead = _remove_aead,
936 .add_signer = _add_signer,
937 .remove_signer = _remove_signer,
938 .add_hasher = _add_hasher,
939 .remove_hasher = _remove_hasher,
940 .add_prf = _add_prf,
941 .remove_prf = _remove_prf,
942 .add_rng = _add_rng,
943 .remove_rng = _remove_rng,
944 .add_nonce_gen = _add_nonce_gen,
945 .remove_nonce_gen = _remove_nonce_gen,
946 .add_dh = _add_dh,
947 .remove_dh = _remove_dh,
948 .create_crypter_enumerator = _create_crypter_enumerator,
949 .create_aead_enumerator = _create_aead_enumerator,
950 .create_signer_enumerator = _create_signer_enumerator,
951 .create_hasher_enumerator = _create_hasher_enumerator,
952 .create_prf_enumerator = _create_prf_enumerator,
953 .create_dh_enumerator = _create_dh_enumerator,
954 .create_rng_enumerator = _create_rng_enumerator,
955 .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
956 .add_test_vector = _add_test_vector,
957 .get_test_vector_failures = _get_test_vector_failures,
958 .destroy = _destroy,
959 },
960 .crypters = linked_list_create(),
961 .aeads = linked_list_create(),
962 .signers = linked_list_create(),
963 .hashers = linked_list_create(),
964 .prfs = linked_list_create(),
965 .rngs = linked_list_create(),
966 .nonce_gens = linked_list_create(),
967 .dhs = linked_list_create(),
968 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
969 .tester = crypto_tester_create(),
970 .test_on_add = lib->settings->get_bool(lib->settings,
971 "%s.crypto_test.on_add", FALSE, lib->ns),
972 .test_on_create = lib->settings->get_bool(lib->settings,
973 "%s.crypto_test.on_create", FALSE, lib->ns),
974 .bench = lib->settings->get_bool(lib->settings,
975 "%s.crypto_test.bench", FALSE, lib->ns),
976 );
977
978 return &this->public;
979 }
980
981 /**
982 * Manually verify all registered algorithms against test vectors
983 */
984 static u_int verify_registered_algorithms(crypto_factory_t *factory)
985 {
986 private_crypto_factory_t *this = (private_crypto_factory_t*)factory;
987 enumerator_t *enumerator;
988 entry_t *entry;
989 u_int failures = 0;
990
991 #define TEST_ALGORITHMS(test, ...) do { \
992 enumerator = this->test##s->create_enumerator(this->test##s); \
993 while (enumerator->enumerate(enumerator, &entry)) \
994 { \
995 if (!this->tester->test_##test(this->tester, entry->algo, ##__VA_ARGS__, \
996 entry->create_##test, NULL, entry->plugin_name)) \
997 { \
998 failures++; \
999 } \
1000 } \
1001 enumerator->destroy(enumerator); \
1002 } while (0)
1003
1004 this->lock->read_lock(this->lock);
1005 TEST_ALGORITHMS(crypter, 0);
1006 TEST_ALGORITHMS(aead, 0);
1007 TEST_ALGORITHMS(signer);
1008 TEST_ALGORITHMS(hasher);
1009 TEST_ALGORITHMS(prf);
1010 TEST_ALGORITHMS(rng);
1011 this->lock->unlock(this->lock);
1012 return failures;
1013 }
1014
1015 EXPORT_FUNCTION_FOR_TESTS(crypto, verify_registered_algorithms);