crypto-factory: Remove obsolete transform testing functions
[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, size_t salt_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 salt_size, entry->create_aead, NULL,
194 default_plugin_name))
195 {
196 continue;
197 }
198 aead = entry->create_aead(algo, key_size, salt_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 if (this->test_on_create && group != MODP_CUSTOM &&
381 !this->tester->test_dh(this->tester, group,
382 entry->create_dh, NULL, default_plugin_name))
383 {
384 continue;
385 }
386 diffie_hellman = entry->create_dh(group, g, p);
387 if (diffie_hellman)
388 {
389 break;
390 }
391 }
392 }
393 enumerator->destroy(enumerator);
394 this->lock->unlock(this->lock);
395 return diffie_hellman;
396 }
397
398 /**
399 * Insert an algorithm entry to a list
400 *
401 * Entries maintain the order in which algorithms were added, unless they were
402 * benchmarked and speed is provided, which then is used to order entries of
403 * the same algorithm.
404 * An exception are RNG entries, which are sorted by algorithm identifier.
405 */
406 static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
407 int algo, const char *plugin_name,
408 u_int speed, void *create)
409 {
410 enumerator_t *enumerator;
411 entry_t *entry, *current;
412 bool sort = (list == this->rngs), found = FALSE;
413
414 INIT(entry,
415 .algo = algo,
416 .plugin_name = plugin_name,
417 .speed = speed,
418 );
419 entry->create = create;
420
421 this->lock->write_lock(this->lock);
422 enumerator = list->create_enumerator(list);
423 while (enumerator->enumerate(enumerator, &current))
424 {
425 if (sort && current->algo > algo)
426 {
427 break;
428 }
429 else if (current->algo == algo)
430 {
431 if (speed > current->speed)
432 {
433 break;
434 }
435 found = TRUE;
436 }
437 else if (found)
438 {
439 break;
440 }
441 }
442 list->insert_before(list, enumerator, entry);
443 enumerator->destroy(enumerator);
444 this->lock->unlock(this->lock);
445 }
446
447 METHOD(crypto_factory_t, add_crypter, bool,
448 private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size,
449 const char *plugin_name, crypter_constructor_t create)
450 {
451 u_int speed = 0;
452
453 if (!this->test_on_add ||
454 this->tester->test_crypter(this->tester, algo, key_size, create,
455 this->bench ? &speed : NULL, plugin_name))
456 {
457 add_entry(this, this->crypters, algo, plugin_name, speed, create);
458 return TRUE;
459 }
460 this->test_failures++;
461 return FALSE;
462 }
463
464 METHOD(crypto_factory_t, remove_crypter, void,
465 private_crypto_factory_t *this, crypter_constructor_t create)
466 {
467 entry_t *entry;
468 enumerator_t *enumerator;
469
470 this->lock->write_lock(this->lock);
471 enumerator = this->crypters->create_enumerator(this->crypters);
472 while (enumerator->enumerate(enumerator, &entry))
473 {
474 if (entry->create_crypter == create)
475 {
476 this->crypters->remove_at(this->crypters, enumerator);
477 free(entry);
478 }
479 }
480 enumerator->destroy(enumerator);
481 this->lock->unlock(this->lock);
482 }
483
484 METHOD(crypto_factory_t, add_aead, bool,
485 private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size,
486 const char *plugin_name, aead_constructor_t create)
487 {
488 u_int speed = 0;
489
490 if (!this->test_on_add ||
491 this->tester->test_aead(this->tester, algo, key_size, 0, create,
492 this->bench ? &speed : NULL, plugin_name))
493 {
494 add_entry(this, this->aeads, algo, plugin_name, speed, create);
495 return TRUE;
496 }
497 this->test_failures++;
498 return FALSE;
499 }
500
501 METHOD(crypto_factory_t, remove_aead, void,
502 private_crypto_factory_t *this, aead_constructor_t create)
503 {
504 entry_t *entry;
505 enumerator_t *enumerator;
506
507 this->lock->write_lock(this->lock);
508 enumerator = this->aeads->create_enumerator(this->aeads);
509 while (enumerator->enumerate(enumerator, &entry))
510 {
511 if (entry->create_aead == create)
512 {
513 this->aeads->remove_at(this->aeads, enumerator);
514 free(entry);
515 }
516 }
517 enumerator->destroy(enumerator);
518 this->lock->unlock(this->lock);
519 }
520
521 METHOD(crypto_factory_t, add_signer, bool,
522 private_crypto_factory_t *this, integrity_algorithm_t algo,
523 const char *plugin_name, signer_constructor_t create)
524 {
525 u_int speed = 0;
526
527 if (!this->test_on_add ||
528 this->tester->test_signer(this->tester, algo, create,
529 this->bench ? &speed : NULL, plugin_name))
530 {
531 add_entry(this, this->signers, algo, plugin_name, speed, create);
532 return TRUE;
533 }
534 this->test_failures++;
535 return FALSE;
536 }
537
538 METHOD(crypto_factory_t, remove_signer, void,
539 private_crypto_factory_t *this, signer_constructor_t create)
540 {
541 entry_t *entry;
542 enumerator_t *enumerator;
543
544 this->lock->write_lock(this->lock);
545 enumerator = this->signers->create_enumerator(this->signers);
546 while (enumerator->enumerate(enumerator, &entry))
547 {
548 if (entry->create_signer == create)
549 {
550 this->signers->remove_at(this->signers, enumerator);
551 free(entry);
552 }
553 }
554 enumerator->destroy(enumerator);
555 this->lock->unlock(this->lock);
556 }
557
558 METHOD(crypto_factory_t, add_hasher, bool,
559 private_crypto_factory_t *this, hash_algorithm_t algo,
560 const char *plugin_name, hasher_constructor_t create)
561 {
562 u_int speed = 0;
563
564 if (!this->test_on_add ||
565 this->tester->test_hasher(this->tester, algo, create,
566 this->bench ? &speed : NULL, plugin_name))
567 {
568 add_entry(this, this->hashers, algo, plugin_name, speed, create);
569 return TRUE;
570 }
571 this->test_failures++;
572 return FALSE;
573 }
574
575 METHOD(crypto_factory_t, remove_hasher, void,
576 private_crypto_factory_t *this, hasher_constructor_t create)
577 {
578 entry_t *entry;
579 enumerator_t *enumerator;
580
581 this->lock->write_lock(this->lock);
582 enumerator = this->hashers->create_enumerator(this->hashers);
583 while (enumerator->enumerate(enumerator, &entry))
584 {
585 if (entry->create_hasher == create)
586 {
587 this->hashers->remove_at(this->hashers, enumerator);
588 free(entry);
589 }
590 }
591 enumerator->destroy(enumerator);
592 this->lock->unlock(this->lock);
593 }
594
595 METHOD(crypto_factory_t, add_prf, bool,
596 private_crypto_factory_t *this, pseudo_random_function_t algo,
597 const char *plugin_name, prf_constructor_t create)
598 {
599 u_int speed = 0;
600
601 if (!this->test_on_add ||
602 this->tester->test_prf(this->tester, algo, create,
603 this->bench ? &speed : NULL, plugin_name))
604 {
605 add_entry(this, this->prfs, algo, plugin_name, speed, create);
606 return TRUE;
607 }
608 this->test_failures++;
609 return FALSE;
610 }
611
612 METHOD(crypto_factory_t, remove_prf, void,
613 private_crypto_factory_t *this, prf_constructor_t create)
614 {
615 entry_t *entry;
616 enumerator_t *enumerator;
617
618 this->lock->write_lock(this->lock);
619 enumerator = this->prfs->create_enumerator(this->prfs);
620 while (enumerator->enumerate(enumerator, &entry))
621 {
622 if (entry->create_prf == create)
623 {
624 this->prfs->remove_at(this->prfs, enumerator);
625 free(entry);
626 }
627 }
628 enumerator->destroy(enumerator);
629 this->lock->unlock(this->lock);
630 }
631
632 METHOD(crypto_factory_t, add_rng, bool,
633 private_crypto_factory_t *this, rng_quality_t quality,
634 const char *plugin_name, rng_constructor_t create)
635 {
636 u_int speed = 0;
637
638 if (!this->test_on_add ||
639 this->tester->test_rng(this->tester, quality, create,
640 this->bench ? &speed : NULL, plugin_name))
641 {
642 add_entry(this, this->rngs, quality, plugin_name, speed, create);
643 return TRUE;
644 }
645 this->test_failures++;
646 return FALSE;
647 }
648
649 METHOD(crypto_factory_t, remove_rng, void,
650 private_crypto_factory_t *this, rng_constructor_t create)
651 {
652 entry_t *entry;
653 enumerator_t *enumerator;
654
655 this->lock->write_lock(this->lock);
656 enumerator = this->rngs->create_enumerator(this->rngs);
657 while (enumerator->enumerate(enumerator, &entry))
658 {
659 if (entry->create_rng == create)
660 {
661 this->rngs->remove_at(this->rngs, enumerator);
662 free(entry);
663 }
664 }
665 enumerator->destroy(enumerator);
666 this->lock->unlock(this->lock);
667 }
668
669 METHOD(crypto_factory_t, add_nonce_gen, bool,
670 private_crypto_factory_t *this, const char *plugin_name,
671 nonce_gen_constructor_t create)
672 {
673 add_entry(this, this->nonce_gens, 0, plugin_name, 0, create);
674 return TRUE;
675 }
676
677 METHOD(crypto_factory_t, remove_nonce_gen, void,
678 private_crypto_factory_t *this, nonce_gen_constructor_t create)
679 {
680 entry_t *entry;
681 enumerator_t *enumerator;
682
683 this->lock->write_lock(this->lock);
684 enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
685 while (enumerator->enumerate(enumerator, &entry))
686 {
687 if (entry->create_nonce_gen == create)
688 {
689 this->nonce_gens->remove_at(this->nonce_gens, enumerator);
690 free(entry);
691 }
692 }
693 enumerator->destroy(enumerator);
694 this->lock->unlock(this->lock);
695 }
696
697 METHOD(crypto_factory_t, add_dh, bool,
698 private_crypto_factory_t *this, diffie_hellman_group_t group,
699 const char *plugin_name, dh_constructor_t create)
700 {
701 u_int speed = 0;
702
703 if (!this->test_on_add ||
704 this->tester->test_dh(this->tester, group, create,
705 this->bench ? &speed : NULL, plugin_name))
706 {
707 add_entry(this, this->dhs, group, plugin_name, 0, create);
708 return TRUE;
709 }
710 this->test_failures++;
711 return FALSE;
712 }
713
714 METHOD(crypto_factory_t, remove_dh, void,
715 private_crypto_factory_t *this, dh_constructor_t create)
716 {
717 entry_t *entry;
718 enumerator_t *enumerator;
719
720 this->lock->write_lock(this->lock);
721 enumerator = this->dhs->create_enumerator(this->dhs);
722 while (enumerator->enumerate(enumerator, &entry))
723 {
724 if (entry->create_dh == create)
725 {
726 this->dhs->remove_at(this->dhs, enumerator);
727 free(entry);
728 }
729 }
730 enumerator->destroy(enumerator);
731 this->lock->unlock(this->lock);
732 }
733
734 /**
735 * match algorithms of an entry?
736 */
737 static bool entry_match(entry_t *a, entry_t *b)
738 {
739 return a->algo == b->algo;
740 }
741
742 /**
743 * check for uniqueness of an entry
744 */
745 static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out)
746 {
747 if (list->find_first(list, (void*)entry_match, NULL, *in) == SUCCESS)
748 {
749 return FALSE;
750 }
751 *out = *in;
752 list->insert_last(list, *in);
753 return TRUE;
754 }
755
756 /**
757 * create an enumerator over entry->algo in list with locking and unique check
758 */
759 static enumerator_t *create_enumerator(private_crypto_factory_t *this,
760 linked_list_t *list, void *filter)
761 {
762 this->lock->read_lock(this->lock);
763 return enumerator_create_filter(
764 enumerator_create_filter(
765 list->create_enumerator(list), (void*)unique_check,
766 linked_list_create(), (void*)list->destroy),
767 filter, this->lock, (void*)this->lock->unlock);
768 }
769
770 /**
771 * Filter function to enumerate algorithm, not entry
772 */
773 static bool crypter_filter(void *n, entry_t **entry, encryption_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_crypter_enumerator, enumerator_t*,
782 private_crypto_factory_t *this)
783 {
784 return create_enumerator(this, this->crypters, crypter_filter);
785 }
786
787 METHOD(crypto_factory_t, create_aead_enumerator, enumerator_t*,
788 private_crypto_factory_t *this)
789 {
790 return create_enumerator(this, this->aeads, crypter_filter);
791 }
792
793 /**
794 * Filter function to enumerate algorithm, not entry
795 */
796 static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo,
797 void *i2, const char **plugin_name)
798 {
799 *algo = (*entry)->algo;
800 *plugin_name = (*entry)->plugin_name;
801 return TRUE;
802 }
803
804 METHOD(crypto_factory_t, create_signer_enumerator, enumerator_t*,
805 private_crypto_factory_t *this)
806 {
807 return create_enumerator(this, this->signers, signer_filter);
808 }
809
810 /**
811 * Filter function to enumerate algorithm, not entry
812 */
813 static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo,
814 void *i2, const char **plugin_name)
815 {
816 *algo = (*entry)->algo;
817 *plugin_name = (*entry)->plugin_name;
818 return TRUE;
819 }
820
821 METHOD(crypto_factory_t, create_hasher_enumerator, enumerator_t*,
822 private_crypto_factory_t *this)
823 {
824 return create_enumerator(this, this->hashers, hasher_filter);
825 }
826
827 /**
828 * Filter function to enumerate algorithm, not entry
829 */
830 static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo,
831 void *i2, const char **plugin_name)
832 {
833 *algo = (*entry)->algo;
834 *plugin_name = (*entry)->plugin_name;
835 return TRUE;
836 }
837
838 METHOD(crypto_factory_t, create_prf_enumerator, enumerator_t*,
839 private_crypto_factory_t *this)
840 {
841 return create_enumerator(this, this->prfs, prf_filter);
842 }
843
844 /**
845 * Filter function to enumerate group, not entry
846 */
847 static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group,
848 void *i2, const char **plugin_name)
849 {
850 *group = (*entry)->algo;
851 *plugin_name = (*entry)->plugin_name;
852 return TRUE;
853 }
854
855 METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
856 private_crypto_factory_t *this)
857 {
858 return create_enumerator(this, this->dhs, dh_filter);
859 }
860
861 /**
862 * Filter function to enumerate strength, not entry
863 */
864 static bool rng_filter(void *n, entry_t **entry, rng_quality_t *quality,
865 void *i2, const char **plugin_name)
866 {
867 *quality = (*entry)->algo;
868 *plugin_name = (*entry)->plugin_name;
869 return TRUE;
870 }
871
872 METHOD(crypto_factory_t, create_rng_enumerator, enumerator_t*,
873 private_crypto_factory_t *this)
874 {
875 return create_enumerator(this, this->rngs, rng_filter);
876 }
877
878 /**
879 * Filter function to enumerate plugin name, not entry
880 */
881 static bool nonce_gen_filter(void *n, entry_t **entry, const char **plugin_name)
882 {
883 *plugin_name = (*entry)->plugin_name;
884 return TRUE;
885 }
886
887 METHOD(crypto_factory_t, create_nonce_gen_enumerator, enumerator_t*,
888 private_crypto_factory_t *this)
889 {
890 return create_enumerator(this, this->nonce_gens, nonce_gen_filter);
891 }
892
893 METHOD(crypto_factory_t, add_test_vector, void,
894 private_crypto_factory_t *this, transform_type_t type, void *vector)
895 {
896 switch (type)
897 {
898 case ENCRYPTION_ALGORITHM:
899 return this->tester->add_crypter_vector(this->tester, vector);
900 case AEAD_ALGORITHM:
901 return this->tester->add_aead_vector(this->tester, vector);
902 case INTEGRITY_ALGORITHM:
903 return this->tester->add_signer_vector(this->tester, vector);
904 case HASH_ALGORITHM:
905 return this->tester->add_hasher_vector(this->tester, vector);
906 case PSEUDO_RANDOM_FUNCTION:
907 return this->tester->add_prf_vector(this->tester, vector);
908 case RANDOM_NUMBER_GENERATOR:
909 return this->tester->add_rng_vector(this->tester, vector);
910 case DIFFIE_HELLMAN_GROUP:
911 return this->tester->add_dh_vector(this->tester, vector);
912 default:
913 DBG1(DBG_LIB, "%N test vectors not supported, ignored",
914 transform_type_names, type);
915 }
916 }
917
918 /**
919 * Private enumerator for create_verify_enumerator()
920 */
921 typedef struct {
922 enumerator_t public;
923 enumerator_t *inner;
924 transform_type_t type;
925 crypto_tester_t *tester;
926 rwlock_t *lock;
927 } verify_enumerator_t;
928
929 METHOD(enumerator_t, verify_enumerate, bool,
930 verify_enumerator_t *this, u_int *alg, const char **plugin, bool *valid)
931 {
932 entry_t *entry;
933
934 if (!this->inner->enumerate(this->inner, &entry))
935 {
936 return FALSE;
937 }
938 switch (this->type)
939 {
940 case ENCRYPTION_ALGORITHM:
941 *valid = this->tester->test_crypter(this->tester, entry->algo, 0,
942 entry->create_crypter, NULL, entry->plugin_name);
943 break;
944 case AEAD_ALGORITHM:
945 *valid = this->tester->test_aead(this->tester, entry->algo, 0, 0,
946 entry->create_aead, NULL, entry->plugin_name);
947 break;
948 case INTEGRITY_ALGORITHM:
949 *valid = this->tester->test_signer(this->tester, entry->algo,
950 entry->create_signer, NULL, entry->plugin_name);
951 break;
952 case HASH_ALGORITHM:
953 *valid = this->tester->test_hasher(this->tester, entry->algo,
954 entry->create_hasher, NULL, entry->plugin_name);
955 break;
956 case PSEUDO_RANDOM_FUNCTION:
957 *valid = this->tester->test_prf(this->tester, entry->algo,
958 entry->create_prf, NULL, entry->plugin_name);
959 break;
960 case RANDOM_NUMBER_GENERATOR:
961 *valid = this->tester->test_rng(this->tester, entry->algo,
962 entry->create_rng, NULL, entry->plugin_name);
963 break;
964 case DIFFIE_HELLMAN_GROUP:
965 *valid = this->tester->test_dh(this->tester, entry->algo,
966 entry->create_dh, NULL, entry->plugin_name);
967 break;
968 default:
969 return FALSE;
970 }
971 *plugin = entry->plugin_name;
972 *alg = entry->algo;
973 return TRUE;
974 }
975
976 METHOD(enumerator_t, verify_destroy, void,
977 verify_enumerator_t *this)
978 {
979 this->inner->destroy(this->inner);
980 this->lock->unlock(this->lock);
981 free(this);
982 }
983
984 METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
985 private_crypto_factory_t *this, transform_type_t type)
986 {
987 verify_enumerator_t *enumerator;
988 enumerator_t *inner;
989
990 this->lock->read_lock(this->lock);
991 switch (type)
992 {
993 case ENCRYPTION_ALGORITHM:
994 inner = this->crypters->create_enumerator(this->crypters);
995 break;
996 case AEAD_ALGORITHM:
997 inner = this->aeads->create_enumerator(this->aeads);
998 break;
999 case INTEGRITY_ALGORITHM:
1000 inner = this->signers->create_enumerator(this->signers);
1001 break;
1002 case HASH_ALGORITHM:
1003 inner = this->hashers->create_enumerator(this->hashers);
1004 break;
1005 case PSEUDO_RANDOM_FUNCTION:
1006 inner = this->prfs->create_enumerator(this->prfs);
1007 break;
1008 case RANDOM_NUMBER_GENERATOR:
1009 inner = this->rngs->create_enumerator(this->rngs);
1010 break;
1011 case DIFFIE_HELLMAN_GROUP:
1012 inner = this->dhs->create_enumerator(this->dhs);
1013 break;
1014 default:
1015 this->lock->unlock(this->lock);
1016 return enumerator_create_empty();
1017 }
1018 INIT(enumerator,
1019 .public = {
1020 .enumerate = (void*)_verify_enumerate,
1021 .destroy = _verify_destroy,
1022 },
1023 .inner = inner,
1024 .type = type,
1025 .tester = this->tester,
1026 .lock = this->lock,
1027 );
1028 return &enumerator->public;
1029 }
1030
1031 METHOD(crypto_factory_t, destroy, void,
1032 private_crypto_factory_t *this)
1033 {
1034 this->crypters->destroy(this->crypters);
1035 this->aeads->destroy(this->aeads);
1036 this->signers->destroy(this->signers);
1037 this->hashers->destroy(this->hashers);
1038 this->prfs->destroy(this->prfs);
1039 this->rngs->destroy(this->rngs);
1040 this->nonce_gens->destroy(this->nonce_gens);
1041 this->dhs->destroy(this->dhs);
1042 this->tester->destroy(this->tester);
1043 this->lock->destroy(this->lock);
1044 free(this);
1045 }
1046
1047 /*
1048 * see header file
1049 */
1050 crypto_factory_t *crypto_factory_create()
1051 {
1052 private_crypto_factory_t *this;
1053
1054 INIT(this,
1055 .public = {
1056 .create_crypter = _create_crypter,
1057 .create_aead = _create_aead,
1058 .create_signer = _create_signer,
1059 .create_hasher = _create_hasher,
1060 .create_prf = _create_prf,
1061 .create_rng = _create_rng,
1062 .create_nonce_gen = _create_nonce_gen,
1063 .create_dh = _create_dh,
1064 .add_crypter = _add_crypter,
1065 .remove_crypter = _remove_crypter,
1066 .add_aead = _add_aead,
1067 .remove_aead = _remove_aead,
1068 .add_signer = _add_signer,
1069 .remove_signer = _remove_signer,
1070 .add_hasher = _add_hasher,
1071 .remove_hasher = _remove_hasher,
1072 .add_prf = _add_prf,
1073 .remove_prf = _remove_prf,
1074 .add_rng = _add_rng,
1075 .remove_rng = _remove_rng,
1076 .add_nonce_gen = _add_nonce_gen,
1077 .remove_nonce_gen = _remove_nonce_gen,
1078 .add_dh = _add_dh,
1079 .remove_dh = _remove_dh,
1080 .create_crypter_enumerator = _create_crypter_enumerator,
1081 .create_aead_enumerator = _create_aead_enumerator,
1082 .create_signer_enumerator = _create_signer_enumerator,
1083 .create_hasher_enumerator = _create_hasher_enumerator,
1084 .create_prf_enumerator = _create_prf_enumerator,
1085 .create_dh_enumerator = _create_dh_enumerator,
1086 .create_rng_enumerator = _create_rng_enumerator,
1087 .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
1088 .add_test_vector = _add_test_vector,
1089 .create_verify_enumerator = _create_verify_enumerator,
1090 .destroy = _destroy,
1091 },
1092 .crypters = linked_list_create(),
1093 .aeads = linked_list_create(),
1094 .signers = linked_list_create(),
1095 .hashers = linked_list_create(),
1096 .prfs = linked_list_create(),
1097 .rngs = linked_list_create(),
1098 .nonce_gens = linked_list_create(),
1099 .dhs = linked_list_create(),
1100 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1101 .tester = crypto_tester_create(),
1102 .test_on_add = lib->settings->get_bool(lib->settings,
1103 "%s.crypto_test.on_add", FALSE, lib->ns),
1104 .test_on_create = lib->settings->get_bool(lib->settings,
1105 "%s.crypto_test.on_create", FALSE, lib->ns),
1106 .bench = lib->settings->get_bool(lib->settings,
1107 "%s.crypto_test.bench", FALSE, lib->ns),
1108 );
1109
1110 return &this->public;
1111 }