xof: Defined Extended Output Functions
[strongswan.git] / src / libstrongswan / crypto / crypto_factory.c
1 /*
2 * Copyright (C) 2013-2014 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Copyright (C) 2016 Andreas Steffen
5 * HSR Hochschule fuer Technik Rapperswil
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 #include "crypto_factory.h"
19
20 #include <utils/debug.h>
21 #include <threading/rwlock.h>
22 #include <collections/linked_list.h>
23 #include <crypto/crypto_tester.h>
24 #include <utils/test.h>
25
26 const char *default_plugin_name = "default";
27
28 typedef struct entry_t entry_t;
29
30 struct entry_t {
31 /**
32 * algorithm
33 */
34 u_int algo;
35
36 /**
37 * plugin that registered this algorithm
38 */
39 const char *plugin_name;
40
41 /**
42 * benchmarked speed
43 */
44 u_int speed;
45
46 /**
47 * constructor
48 */
49 union {
50 crypter_constructor_t create_crypter;
51 aead_constructor_t create_aead;
52 signer_constructor_t create_signer;
53 hasher_constructor_t create_hasher;
54 prf_constructor_t create_prf;
55 xof_constructor_t create_xof;
56 rng_constructor_t create_rng;
57 nonce_gen_constructor_t create_nonce_gen;
58 dh_constructor_t create_dh;
59 void *create;
60 };
61 };
62
63 typedef struct private_crypto_factory_t private_crypto_factory_t;
64
65 /**
66 * private data of crypto_factory
67 */
68 struct private_crypto_factory_t {
69
70 /**
71 * public functions
72 */
73 crypto_factory_t public;
74
75 /**
76 * registered crypters, as entry_t
77 */
78 linked_list_t *crypters;
79
80 /**
81 * registered aead transforms, as entry_t
82 */
83 linked_list_t *aeads;
84
85 /**
86 * registered signers, as entry_t
87 */
88 linked_list_t *signers;
89
90 /**
91 * registered hashers, as entry_t
92 */
93 linked_list_t *hashers;
94
95 /**
96 * registered prfs, as entry_t
97 */
98 linked_list_t *prfs;
99
100 /**
101 * registered xofs, as entry_t
102 */
103 linked_list_t *xofs;
104
105 /**
106 * registered rngs, as entry_t
107 */
108 linked_list_t *rngs;
109
110 /**
111 * registered nonce generators, as entry_t
112 */
113 linked_list_t *nonce_gens;
114
115 /**
116 * registered diffie hellman, as entry_t
117 */
118 linked_list_t *dhs;
119
120 /**
121 * test manager to test crypto algorithms
122 */
123 crypto_tester_t *tester;
124
125 /**
126 * whether to test algorithms during registration
127 */
128 bool test_on_add;
129
130 /**
131 * whether to test algorithms on each crypto primitive construction
132 */
133 bool test_on_create;
134
135 /**
136 * run algorithm benchmark during registration
137 */
138 bool bench;
139
140 /**
141 * Number of failed test vectors during "add".
142 */
143 u_int test_failures;
144
145 /**
146 * rwlock to lock access to modules
147 */
148 rwlock_t *lock;
149 };
150
151 METHOD(crypto_factory_t, create_crypter, crypter_t*,
152 private_crypto_factory_t *this, encryption_algorithm_t algo,
153 size_t key_size)
154 {
155 enumerator_t *enumerator;
156 entry_t *entry;
157 crypter_t *crypter = NULL;
158
159 this->lock->read_lock(this->lock);
160 enumerator = this->crypters->create_enumerator(this->crypters);
161 while (enumerator->enumerate(enumerator, &entry))
162 {
163 if (entry->algo == algo)
164 {
165 if (this->test_on_create &&
166 !this->tester->test_crypter(this->tester, algo, key_size,
167 entry->create_crypter, NULL,
168 default_plugin_name))
169 {
170 continue;
171 }
172 crypter = entry->create_crypter(algo, key_size);
173 if (crypter)
174 {
175 break;
176 }
177 }
178 }
179 enumerator->destroy(enumerator);
180 this->lock->unlock(this->lock);
181 return crypter;
182 }
183
184 METHOD(crypto_factory_t, create_aead, aead_t*,
185 private_crypto_factory_t *this, encryption_algorithm_t algo,
186 size_t key_size, size_t salt_size)
187 {
188 enumerator_t *enumerator;
189 entry_t *entry;
190 aead_t *aead = NULL;
191
192 this->lock->read_lock(this->lock);
193 enumerator = this->aeads->create_enumerator(this->aeads);
194 while (enumerator->enumerate(enumerator, &entry))
195 {
196 if (entry->algo == algo)
197 {
198 if (this->test_on_create &&
199 !this->tester->test_aead(this->tester, algo, key_size,
200 salt_size, entry->create_aead, NULL,
201 default_plugin_name))
202 {
203 continue;
204 }
205 aead = entry->create_aead(algo, key_size, salt_size);
206 if (aead)
207 {
208 break;
209 }
210 }
211 }
212 enumerator->destroy(enumerator);
213 this->lock->unlock(this->lock);
214 return aead;
215 }
216
217 METHOD(crypto_factory_t, create_signer, signer_t*,
218 private_crypto_factory_t *this, integrity_algorithm_t algo)
219 {
220 enumerator_t *enumerator;
221 entry_t *entry;
222 signer_t *signer = NULL;
223
224 this->lock->read_lock(this->lock);
225 enumerator = this->signers->create_enumerator(this->signers);
226 while (enumerator->enumerate(enumerator, &entry))
227 {
228 if (entry->algo == algo)
229 {
230 if (this->test_on_create &&
231 !this->tester->test_signer(this->tester, algo,
232 entry->create_signer, NULL,
233 default_plugin_name))
234 {
235 continue;
236 }
237 signer = entry->create_signer(algo);
238 if (signer)
239 {
240 break;
241 }
242 }
243 }
244 enumerator->destroy(enumerator);
245 this->lock->unlock(this->lock);
246 return signer;
247 }
248
249 METHOD(crypto_factory_t, create_hasher, hasher_t*,
250 private_crypto_factory_t *this, hash_algorithm_t algo)
251 {
252 enumerator_t *enumerator;
253 entry_t *entry;
254 hasher_t *hasher = NULL;
255
256 this->lock->read_lock(this->lock);
257 enumerator = this->hashers->create_enumerator(this->hashers);
258 while (enumerator->enumerate(enumerator, &entry))
259 {
260 if (entry->algo == algo)
261 {
262 if (this->test_on_create &&
263 !this->tester->test_hasher(this->tester, algo,
264 entry->create_hasher, NULL,
265 default_plugin_name))
266 {
267 continue;
268 }
269 hasher = entry->create_hasher(entry->algo);
270 if (hasher)
271 {
272 break;
273 }
274 }
275 }
276 enumerator->destroy(enumerator);
277 this->lock->unlock(this->lock);
278 return hasher;
279 }
280
281 METHOD(crypto_factory_t, create_prf, prf_t*,
282 private_crypto_factory_t *this, pseudo_random_function_t algo)
283 {
284 enumerator_t *enumerator;
285 entry_t *entry;
286 prf_t *prf = NULL;
287
288 this->lock->read_lock(this->lock);
289 enumerator = this->prfs->create_enumerator(this->prfs);
290 while (enumerator->enumerate(enumerator, &entry))
291 {
292 if (entry->algo == algo)
293 {
294 if (this->test_on_create &&
295 !this->tester->test_prf(this->tester, algo,
296 entry->create_prf, NULL,
297 default_plugin_name))
298 {
299 continue;
300 }
301 prf = entry->create_prf(algo);
302 if (prf)
303 {
304 break;
305 }
306 }
307 }
308 enumerator->destroy(enumerator);
309 this->lock->unlock(this->lock);
310 return prf;
311 }
312
313 METHOD(crypto_factory_t, create_xof, xof_t*,
314 private_crypto_factory_t *this, ext_out_function_t algo)
315 {
316 enumerator_t *enumerator;
317 entry_t *entry;
318 xof_t *xof = NULL;
319
320 this->lock->read_lock(this->lock);
321 enumerator = this->xofs->create_enumerator(this->xofs);
322 while (enumerator->enumerate(enumerator, &entry))
323 {
324 if (entry->algo == algo)
325 {
326 if (this->test_on_create &&
327 !this->tester->test_xof(this->tester, algo,
328 entry->create_xof, NULL,
329 default_plugin_name))
330 {
331 continue;
332 }
333 xof = entry->create_xof(algo);
334 if (xof)
335 {
336 break;
337 }
338 }
339 }
340 enumerator->destroy(enumerator);
341 this->lock->unlock(this->lock);
342 return xof;
343 }
344
345 METHOD(crypto_factory_t, create_rng, rng_t*,
346 private_crypto_factory_t *this, rng_quality_t quality)
347 {
348 enumerator_t *enumerator;
349 entry_t *entry;
350 rng_t *rng = NULL;
351
352 this->lock->read_lock(this->lock);
353 enumerator = this->rngs->create_enumerator(this->rngs);
354 while (enumerator->enumerate(enumerator, &entry))
355 { /* find the best matching quality, but at least as good as requested */
356 if (entry->algo >= quality)
357 {
358 if (this->test_on_create &&
359 !this->tester->test_rng(this->tester, quality,
360 entry->create_rng, NULL,
361 default_plugin_name))
362 {
363 continue;
364 }
365 rng = entry->create_rng(quality);
366 if (rng)
367 {
368 break;
369 }
370 }
371 }
372 enumerator->destroy(enumerator);
373 this->lock->unlock(this->lock);
374 return rng;
375 }
376
377 METHOD(crypto_factory_t, create_nonce_gen, nonce_gen_t*,
378 private_crypto_factory_t *this)
379 {
380 enumerator_t *enumerator;
381 entry_t *entry;
382 nonce_gen_t *nonce_gen = NULL;
383
384 this->lock->read_lock(this->lock);
385 enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
386 while (enumerator->enumerate(enumerator, &entry))
387 {
388 nonce_gen = entry->create_nonce_gen();
389 if (nonce_gen)
390 {
391 break;
392 }
393 }
394 enumerator->destroy(enumerator);
395 this->lock->unlock(this->lock);
396
397 return nonce_gen;
398 }
399
400 METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
401 private_crypto_factory_t *this, diffie_hellman_group_t group, ...)
402 {
403 enumerator_t *enumerator;
404 entry_t *entry;
405 va_list args;
406 chunk_t g = chunk_empty, p = chunk_empty;
407 diffie_hellman_t *diffie_hellman = NULL;
408
409 if (group == MODP_CUSTOM)
410 {
411 va_start(args, group);
412 g = va_arg(args, chunk_t);
413 p = va_arg(args, chunk_t);
414 va_end(args);
415 }
416
417 this->lock->read_lock(this->lock);
418 enumerator = this->dhs->create_enumerator(this->dhs);
419 while (enumerator->enumerate(enumerator, &entry))
420 {
421 if (entry->algo == group)
422 {
423 if (this->test_on_create && group != MODP_CUSTOM &&
424 !this->tester->test_dh(this->tester, group,
425 entry->create_dh, NULL, default_plugin_name))
426 {
427 continue;
428 }
429 diffie_hellman = entry->create_dh(group, g, p);
430 if (diffie_hellman)
431 {
432 break;
433 }
434 }
435 }
436 enumerator->destroy(enumerator);
437 this->lock->unlock(this->lock);
438 return diffie_hellman;
439 }
440
441 /**
442 * Insert an algorithm entry to a list
443 *
444 * Entries maintain the order in which algorithms were added, unless they were
445 * benchmarked and speed is provided, which then is used to order entries of
446 * the same algorithm.
447 * An exception are RNG entries, which are sorted by algorithm identifier.
448 */
449 static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
450 int algo, const char *plugin_name,
451 u_int speed, void *create)
452 {
453 enumerator_t *enumerator;
454 entry_t *entry, *current;
455 bool sort = (list == this->rngs), found = FALSE;
456
457 INIT(entry,
458 .algo = algo,
459 .plugin_name = plugin_name,
460 .speed = speed,
461 );
462 entry->create = create;
463
464 this->lock->write_lock(this->lock);
465 enumerator = list->create_enumerator(list);
466 while (enumerator->enumerate(enumerator, &current))
467 {
468 if (sort && current->algo > algo)
469 {
470 break;
471 }
472 else if (current->algo == algo)
473 {
474 if (speed > current->speed)
475 {
476 break;
477 }
478 found = TRUE;
479 }
480 else if (found)
481 {
482 break;
483 }
484 }
485 list->insert_before(list, enumerator, entry);
486 enumerator->destroy(enumerator);
487 this->lock->unlock(this->lock);
488 }
489
490 METHOD(crypto_factory_t, add_crypter, bool,
491 private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size,
492 const char *plugin_name, crypter_constructor_t create)
493 {
494 u_int speed = 0;
495
496 if (!this->test_on_add ||
497 this->tester->test_crypter(this->tester, algo, key_size, create,
498 this->bench ? &speed : NULL, plugin_name))
499 {
500 add_entry(this, this->crypters, algo, plugin_name, speed, create);
501 return TRUE;
502 }
503 this->test_failures++;
504 return FALSE;
505 }
506
507 METHOD(crypto_factory_t, remove_crypter, void,
508 private_crypto_factory_t *this, crypter_constructor_t create)
509 {
510 entry_t *entry;
511 enumerator_t *enumerator;
512
513 this->lock->write_lock(this->lock);
514 enumerator = this->crypters->create_enumerator(this->crypters);
515 while (enumerator->enumerate(enumerator, &entry))
516 {
517 if (entry->create_crypter == create)
518 {
519 this->crypters->remove_at(this->crypters, enumerator);
520 free(entry);
521 }
522 }
523 enumerator->destroy(enumerator);
524 this->lock->unlock(this->lock);
525 }
526
527 METHOD(crypto_factory_t, add_aead, bool,
528 private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size,
529 const char *plugin_name, aead_constructor_t create)
530 {
531 u_int speed = 0;
532
533 if (!this->test_on_add ||
534 this->tester->test_aead(this->tester, algo, key_size, 0, create,
535 this->bench ? &speed : NULL, plugin_name))
536 {
537 add_entry(this, this->aeads, algo, plugin_name, speed, create);
538 return TRUE;
539 }
540 this->test_failures++;
541 return FALSE;
542 }
543
544 METHOD(crypto_factory_t, remove_aead, void,
545 private_crypto_factory_t *this, aead_constructor_t create)
546 {
547 entry_t *entry;
548 enumerator_t *enumerator;
549
550 this->lock->write_lock(this->lock);
551 enumerator = this->aeads->create_enumerator(this->aeads);
552 while (enumerator->enumerate(enumerator, &entry))
553 {
554 if (entry->create_aead == create)
555 {
556 this->aeads->remove_at(this->aeads, enumerator);
557 free(entry);
558 }
559 }
560 enumerator->destroy(enumerator);
561 this->lock->unlock(this->lock);
562 }
563
564 METHOD(crypto_factory_t, add_signer, bool,
565 private_crypto_factory_t *this, integrity_algorithm_t algo,
566 const char *plugin_name, signer_constructor_t create)
567 {
568 u_int speed = 0;
569
570 if (!this->test_on_add ||
571 this->tester->test_signer(this->tester, algo, create,
572 this->bench ? &speed : NULL, plugin_name))
573 {
574 add_entry(this, this->signers, algo, plugin_name, speed, create);
575 return TRUE;
576 }
577 this->test_failures++;
578 return FALSE;
579 }
580
581 METHOD(crypto_factory_t, remove_signer, void,
582 private_crypto_factory_t *this, signer_constructor_t create)
583 {
584 entry_t *entry;
585 enumerator_t *enumerator;
586
587 this->lock->write_lock(this->lock);
588 enumerator = this->signers->create_enumerator(this->signers);
589 while (enumerator->enumerate(enumerator, &entry))
590 {
591 if (entry->create_signer == create)
592 {
593 this->signers->remove_at(this->signers, enumerator);
594 free(entry);
595 }
596 }
597 enumerator->destroy(enumerator);
598 this->lock->unlock(this->lock);
599 }
600
601 METHOD(crypto_factory_t, add_hasher, bool,
602 private_crypto_factory_t *this, hash_algorithm_t algo,
603 const char *plugin_name, hasher_constructor_t create)
604 {
605 u_int speed = 0;
606
607 if (!this->test_on_add ||
608 this->tester->test_hasher(this->tester, algo, create,
609 this->bench ? &speed : NULL, plugin_name))
610 {
611 add_entry(this, this->hashers, algo, plugin_name, speed, create);
612 return TRUE;
613 }
614 this->test_failures++;
615 return FALSE;
616 }
617
618 METHOD(crypto_factory_t, remove_hasher, void,
619 private_crypto_factory_t *this, hasher_constructor_t create)
620 {
621 entry_t *entry;
622 enumerator_t *enumerator;
623
624 this->lock->write_lock(this->lock);
625 enumerator = this->hashers->create_enumerator(this->hashers);
626 while (enumerator->enumerate(enumerator, &entry))
627 {
628 if (entry->create_hasher == create)
629 {
630 this->hashers->remove_at(this->hashers, enumerator);
631 free(entry);
632 }
633 }
634 enumerator->destroy(enumerator);
635 this->lock->unlock(this->lock);
636 }
637
638 METHOD(crypto_factory_t, add_prf, bool,
639 private_crypto_factory_t *this, pseudo_random_function_t algo,
640 const char *plugin_name, prf_constructor_t create)
641 {
642 u_int speed = 0;
643
644 if (!this->test_on_add ||
645 this->tester->test_prf(this->tester, algo, create,
646 this->bench ? &speed : NULL, plugin_name))
647 {
648 add_entry(this, this->prfs, algo, plugin_name, speed, create);
649 return TRUE;
650 }
651 this->test_failures++;
652 return FALSE;
653 }
654
655 METHOD(crypto_factory_t, remove_prf, void,
656 private_crypto_factory_t *this, prf_constructor_t create)
657 {
658 entry_t *entry;
659 enumerator_t *enumerator;
660
661 this->lock->write_lock(this->lock);
662 enumerator = this->prfs->create_enumerator(this->prfs);
663 while (enumerator->enumerate(enumerator, &entry))
664 {
665 if (entry->create_prf == create)
666 {
667 this->prfs->remove_at(this->prfs, enumerator);
668 free(entry);
669 }
670 }
671 enumerator->destroy(enumerator);
672 this->lock->unlock(this->lock);
673 }
674
675 METHOD(crypto_factory_t, add_xof, bool,
676 private_crypto_factory_t *this, ext_out_function_t algo,
677 const char *plugin_name, xof_constructor_t create)
678 {
679 u_int speed = 0;
680
681 if (!this->test_on_add ||
682 this->tester->test_xof(this->tester, algo, create,
683 this->bench ? &speed : NULL, plugin_name))
684 {
685 add_entry(this, this->xofs, algo, plugin_name, speed, create);
686 return TRUE;
687 }
688 this->test_failures++;
689 return FALSE;
690 }
691
692 METHOD(crypto_factory_t, remove_xof, void,
693 private_crypto_factory_t *this, xof_constructor_t create)
694 {
695 entry_t *entry;
696 enumerator_t *enumerator;
697
698 this->lock->write_lock(this->lock);
699 enumerator = this->xofs->create_enumerator(this->xofs);
700 while (enumerator->enumerate(enumerator, &entry))
701 {
702 if (entry->create_xof == create)
703 {
704 this->xofs->remove_at(this->xofs, enumerator);
705 free(entry);
706 }
707 }
708 enumerator->destroy(enumerator);
709 this->lock->unlock(this->lock);
710 }
711
712 METHOD(crypto_factory_t, add_rng, bool,
713 private_crypto_factory_t *this, rng_quality_t quality,
714 const char *plugin_name, rng_constructor_t create)
715 {
716 u_int speed = 0;
717
718 if (!this->test_on_add ||
719 this->tester->test_rng(this->tester, quality, create,
720 this->bench ? &speed : NULL, plugin_name))
721 {
722 add_entry(this, this->rngs, quality, plugin_name, speed, create);
723 return TRUE;
724 }
725 this->test_failures++;
726 return FALSE;
727 }
728
729 METHOD(crypto_factory_t, remove_rng, void,
730 private_crypto_factory_t *this, rng_constructor_t create)
731 {
732 entry_t *entry;
733 enumerator_t *enumerator;
734
735 this->lock->write_lock(this->lock);
736 enumerator = this->rngs->create_enumerator(this->rngs);
737 while (enumerator->enumerate(enumerator, &entry))
738 {
739 if (entry->create_rng == create)
740 {
741 this->rngs->remove_at(this->rngs, enumerator);
742 free(entry);
743 }
744 }
745 enumerator->destroy(enumerator);
746 this->lock->unlock(this->lock);
747 }
748
749 METHOD(crypto_factory_t, add_nonce_gen, bool,
750 private_crypto_factory_t *this, const char *plugin_name,
751 nonce_gen_constructor_t create)
752 {
753 add_entry(this, this->nonce_gens, 0, plugin_name, 0, create);
754 return TRUE;
755 }
756
757 METHOD(crypto_factory_t, remove_nonce_gen, void,
758 private_crypto_factory_t *this, nonce_gen_constructor_t create)
759 {
760 entry_t *entry;
761 enumerator_t *enumerator;
762
763 this->lock->write_lock(this->lock);
764 enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
765 while (enumerator->enumerate(enumerator, &entry))
766 {
767 if (entry->create_nonce_gen == create)
768 {
769 this->nonce_gens->remove_at(this->nonce_gens, enumerator);
770 free(entry);
771 }
772 }
773 enumerator->destroy(enumerator);
774 this->lock->unlock(this->lock);
775 }
776
777 METHOD(crypto_factory_t, add_dh, bool,
778 private_crypto_factory_t *this, diffie_hellman_group_t group,
779 const char *plugin_name, dh_constructor_t create)
780 {
781 u_int speed = 0;
782
783 if (!this->test_on_add ||
784 this->tester->test_dh(this->tester, group, create,
785 this->bench ? &speed : NULL, plugin_name))
786 {
787 add_entry(this, this->dhs, group, plugin_name, 0, create);
788 return TRUE;
789 }
790 this->test_failures++;
791 return FALSE;
792 }
793
794 METHOD(crypto_factory_t, remove_dh, void,
795 private_crypto_factory_t *this, dh_constructor_t create)
796 {
797 entry_t *entry;
798 enumerator_t *enumerator;
799
800 this->lock->write_lock(this->lock);
801 enumerator = this->dhs->create_enumerator(this->dhs);
802 while (enumerator->enumerate(enumerator, &entry))
803 {
804 if (entry->create_dh == create)
805 {
806 this->dhs->remove_at(this->dhs, enumerator);
807 free(entry);
808 }
809 }
810 enumerator->destroy(enumerator);
811 this->lock->unlock(this->lock);
812 }
813
814 /**
815 * match algorithms of an entry?
816 */
817 static bool entry_match(entry_t *a, entry_t *b)
818 {
819 return a->algo == b->algo;
820 }
821
822 /**
823 * check for uniqueness of an entry
824 */
825 static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out)
826 {
827 if (list->find_first(list, (void*)entry_match, NULL, *in) == SUCCESS)
828 {
829 return FALSE;
830 }
831 *out = *in;
832 list->insert_last(list, *in);
833 return TRUE;
834 }
835
836 /**
837 * create an enumerator over entry->algo in list with locking and unique check
838 */
839 static enumerator_t *create_enumerator(private_crypto_factory_t *this,
840 linked_list_t *list, void *filter)
841 {
842 this->lock->read_lock(this->lock);
843 return enumerator_create_filter(
844 enumerator_create_filter(
845 list->create_enumerator(list), (void*)unique_check,
846 linked_list_create(), (void*)list->destroy),
847 filter, this->lock, (void*)this->lock->unlock);
848 }
849
850 /**
851 * Filter function to enumerate algorithm, not entry
852 */
853 static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo,
854 void *i2, const char **plugin_name)
855 {
856 *algo = (*entry)->algo;
857 *plugin_name = (*entry)->plugin_name;
858 return TRUE;
859 }
860
861 METHOD(crypto_factory_t, create_crypter_enumerator, enumerator_t*,
862 private_crypto_factory_t *this)
863 {
864 return create_enumerator(this, this->crypters, crypter_filter);
865 }
866
867 METHOD(crypto_factory_t, create_aead_enumerator, enumerator_t*,
868 private_crypto_factory_t *this)
869 {
870 return create_enumerator(this, this->aeads, crypter_filter);
871 }
872
873 /**
874 * Filter function to enumerate algorithm, not entry
875 */
876 static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo,
877 void *i2, const char **plugin_name)
878 {
879 *algo = (*entry)->algo;
880 *plugin_name = (*entry)->plugin_name;
881 return TRUE;
882 }
883
884 METHOD(crypto_factory_t, create_signer_enumerator, enumerator_t*,
885 private_crypto_factory_t *this)
886 {
887 return create_enumerator(this, this->signers, signer_filter);
888 }
889
890 /**
891 * Filter function to enumerate algorithm, not entry
892 */
893 static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo,
894 void *i2, const char **plugin_name)
895 {
896 *algo = (*entry)->algo;
897 *plugin_name = (*entry)->plugin_name;
898 return TRUE;
899 }
900
901 METHOD(crypto_factory_t, create_hasher_enumerator, enumerator_t*,
902 private_crypto_factory_t *this)
903 {
904 return create_enumerator(this, this->hashers, hasher_filter);
905 }
906
907 /**
908 * Filter function to enumerate algorithm, not entry
909 */
910 static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo,
911 void *i2, const char **plugin_name)
912 {
913 *algo = (*entry)->algo;
914 *plugin_name = (*entry)->plugin_name;
915 return TRUE;
916 }
917
918 METHOD(crypto_factory_t, create_prf_enumerator, enumerator_t*,
919 private_crypto_factory_t *this)
920 {
921 return create_enumerator(this, this->prfs, prf_filter);
922 }
923
924 /**
925 * Filter function to enumerate algorithm, not entry
926 */
927 static bool xof_filter(void *n, entry_t **entry, ext_out_function_t *algo,
928 void *i2, const char **plugin_name)
929 {
930 *algo = (*entry)->algo;
931 *plugin_name = (*entry)->plugin_name;
932 return TRUE;
933 }
934
935 METHOD(crypto_factory_t, create_xof_enumerator, enumerator_t*,
936 private_crypto_factory_t *this)
937 {
938 return create_enumerator(this, this->xofs, xof_filter);
939 }
940
941 /**
942 * Filter function to enumerate group, not entry
943 */
944 static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group,
945 void *i2, const char **plugin_name)
946 {
947 *group = (*entry)->algo;
948 *plugin_name = (*entry)->plugin_name;
949 return TRUE;
950 }
951
952 METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
953 private_crypto_factory_t *this)
954 {
955 return create_enumerator(this, this->dhs, dh_filter);
956 }
957
958 /**
959 * Filter function to enumerate strength, not entry
960 */
961 static bool rng_filter(void *n, entry_t **entry, rng_quality_t *quality,
962 void *i2, const char **plugin_name)
963 {
964 *quality = (*entry)->algo;
965 *plugin_name = (*entry)->plugin_name;
966 return TRUE;
967 }
968
969 METHOD(crypto_factory_t, create_rng_enumerator, enumerator_t*,
970 private_crypto_factory_t *this)
971 {
972 return create_enumerator(this, this->rngs, rng_filter);
973 }
974
975 /**
976 * Filter function to enumerate plugin name, not entry
977 */
978 static bool nonce_gen_filter(void *n, entry_t **entry, const char **plugin_name)
979 {
980 *plugin_name = (*entry)->plugin_name;
981 return TRUE;
982 }
983
984 METHOD(crypto_factory_t, create_nonce_gen_enumerator, enumerator_t*,
985 private_crypto_factory_t *this)
986 {
987 return create_enumerator(this, this->nonce_gens, nonce_gen_filter);
988 }
989
990 METHOD(crypto_factory_t, add_test_vector, void,
991 private_crypto_factory_t *this, transform_type_t type, void *vector)
992 {
993 switch (type)
994 {
995 case ENCRYPTION_ALGORITHM:
996 return this->tester->add_crypter_vector(this->tester, vector);
997 case AEAD_ALGORITHM:
998 return this->tester->add_aead_vector(this->tester, vector);
999 case INTEGRITY_ALGORITHM:
1000 return this->tester->add_signer_vector(this->tester, vector);
1001 case HASH_ALGORITHM:
1002 return this->tester->add_hasher_vector(this->tester, vector);
1003 case PSEUDO_RANDOM_FUNCTION:
1004 return this->tester->add_prf_vector(this->tester, vector);
1005 case EXTENDED_OUTPUT_FUNCTION:
1006 return this->tester->add_xof_vector(this->tester, vector);
1007 case RANDOM_NUMBER_GENERATOR:
1008 return this->tester->add_rng_vector(this->tester, vector);
1009 case DIFFIE_HELLMAN_GROUP:
1010 return this->tester->add_dh_vector(this->tester, vector);
1011 default:
1012 DBG1(DBG_LIB, "%N test vectors not supported, ignored",
1013 transform_type_names, type);
1014 }
1015 }
1016
1017 /**
1018 * Private enumerator for create_verify_enumerator()
1019 */
1020 typedef struct {
1021 enumerator_t public;
1022 enumerator_t *inner;
1023 transform_type_t type;
1024 crypto_tester_t *tester;
1025 rwlock_t *lock;
1026 } verify_enumerator_t;
1027
1028 METHOD(enumerator_t, verify_enumerate, bool,
1029 verify_enumerator_t *this, u_int *alg, const char **plugin, bool *valid)
1030 {
1031 entry_t *entry;
1032
1033 if (!this->inner->enumerate(this->inner, &entry))
1034 {
1035 return FALSE;
1036 }
1037 switch (this->type)
1038 {
1039 case ENCRYPTION_ALGORITHM:
1040 *valid = this->tester->test_crypter(this->tester, entry->algo, 0,
1041 entry->create_crypter, NULL, entry->plugin_name);
1042 break;
1043 case AEAD_ALGORITHM:
1044 *valid = this->tester->test_aead(this->tester, entry->algo, 0, 0,
1045 entry->create_aead, NULL, entry->plugin_name);
1046 break;
1047 case INTEGRITY_ALGORITHM:
1048 *valid = this->tester->test_signer(this->tester, entry->algo,
1049 entry->create_signer, NULL, entry->plugin_name);
1050 break;
1051 case HASH_ALGORITHM:
1052 *valid = this->tester->test_hasher(this->tester, entry->algo,
1053 entry->create_hasher, NULL, entry->plugin_name);
1054 break;
1055 case PSEUDO_RANDOM_FUNCTION:
1056 *valid = this->tester->test_prf(this->tester, entry->algo,
1057 entry->create_prf, NULL, entry->plugin_name);
1058 break;
1059 case EXTENDED_OUTPUT_FUNCTION:
1060 *valid = this->tester->test_xof(this->tester, entry->algo,
1061 entry->create_xof, NULL, entry->plugin_name);
1062 break;
1063 case RANDOM_NUMBER_GENERATOR:
1064 *valid = this->tester->test_rng(this->tester, entry->algo,
1065 entry->create_rng, NULL, entry->plugin_name);
1066 break;
1067 case DIFFIE_HELLMAN_GROUP:
1068 *valid = this->tester->test_dh(this->tester, entry->algo,
1069 entry->create_dh, NULL, entry->plugin_name);
1070 break;
1071 default:
1072 return FALSE;
1073 }
1074 *plugin = entry->plugin_name;
1075 *alg = entry->algo;
1076 return TRUE;
1077 }
1078
1079 METHOD(enumerator_t, verify_destroy, void,
1080 verify_enumerator_t *this)
1081 {
1082 this->inner->destroy(this->inner);
1083 this->lock->unlock(this->lock);
1084 free(this);
1085 }
1086
1087 METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
1088 private_crypto_factory_t *this, transform_type_t type)
1089 {
1090 verify_enumerator_t *enumerator;
1091 enumerator_t *inner;
1092
1093 this->lock->read_lock(this->lock);
1094 switch (type)
1095 {
1096 case ENCRYPTION_ALGORITHM:
1097 inner = this->crypters->create_enumerator(this->crypters);
1098 break;
1099 case AEAD_ALGORITHM:
1100 inner = this->aeads->create_enumerator(this->aeads);
1101 break;
1102 case INTEGRITY_ALGORITHM:
1103 inner = this->signers->create_enumerator(this->signers);
1104 break;
1105 case HASH_ALGORITHM:
1106 inner = this->hashers->create_enumerator(this->hashers);
1107 break;
1108 case PSEUDO_RANDOM_FUNCTION:
1109 inner = this->prfs->create_enumerator(this->prfs);
1110 break;
1111 case EXTENDED_OUTPUT_FUNCTION:
1112 inner = this->xofs->create_enumerator(this->xofs);
1113 break;
1114 case RANDOM_NUMBER_GENERATOR:
1115 inner = this->rngs->create_enumerator(this->rngs);
1116 break;
1117 case DIFFIE_HELLMAN_GROUP:
1118 inner = this->dhs->create_enumerator(this->dhs);
1119 break;
1120 default:
1121 this->lock->unlock(this->lock);
1122 return enumerator_create_empty();
1123 }
1124 INIT(enumerator,
1125 .public = {
1126 .enumerate = (void*)_verify_enumerate,
1127 .destroy = _verify_destroy,
1128 },
1129 .inner = inner,
1130 .type = type,
1131 .tester = this->tester,
1132 .lock = this->lock,
1133 );
1134 return &enumerator->public;
1135 }
1136
1137 METHOD(crypto_factory_t, destroy, void,
1138 private_crypto_factory_t *this)
1139 {
1140 this->crypters->destroy(this->crypters);
1141 this->aeads->destroy(this->aeads);
1142 this->signers->destroy(this->signers);
1143 this->hashers->destroy(this->hashers);
1144 this->prfs->destroy(this->prfs);
1145 this->xofs->destroy(this->xofs);
1146 this->rngs->destroy(this->rngs);
1147 this->nonce_gens->destroy(this->nonce_gens);
1148 this->dhs->destroy(this->dhs);
1149 this->tester->destroy(this->tester);
1150 this->lock->destroy(this->lock);
1151 free(this);
1152 }
1153
1154 /*
1155 * see header file
1156 */
1157 crypto_factory_t *crypto_factory_create()
1158 {
1159 private_crypto_factory_t *this;
1160
1161 INIT(this,
1162 .public = {
1163 .create_crypter = _create_crypter,
1164 .create_aead = _create_aead,
1165 .create_signer = _create_signer,
1166 .create_hasher = _create_hasher,
1167 .create_prf = _create_prf,
1168 .create_xof = _create_xof,
1169 .create_rng = _create_rng,
1170 .create_nonce_gen = _create_nonce_gen,
1171 .create_dh = _create_dh,
1172 .add_crypter = _add_crypter,
1173 .remove_crypter = _remove_crypter,
1174 .add_aead = _add_aead,
1175 .remove_aead = _remove_aead,
1176 .add_signer = _add_signer,
1177 .remove_signer = _remove_signer,
1178 .add_hasher = _add_hasher,
1179 .remove_hasher = _remove_hasher,
1180 .add_prf = _add_prf,
1181 .remove_prf = _remove_prf,
1182 .add_xof = _add_xof,
1183 .remove_xof = _remove_xof,
1184 .add_rng = _add_rng,
1185 .remove_rng = _remove_rng,
1186 .add_nonce_gen = _add_nonce_gen,
1187 .remove_nonce_gen = _remove_nonce_gen,
1188 .add_dh = _add_dh,
1189 .remove_dh = _remove_dh,
1190 .create_crypter_enumerator = _create_crypter_enumerator,
1191 .create_aead_enumerator = _create_aead_enumerator,
1192 .create_signer_enumerator = _create_signer_enumerator,
1193 .create_hasher_enumerator = _create_hasher_enumerator,
1194 .create_prf_enumerator = _create_prf_enumerator,
1195 .create_xof_enumerator = _create_xof_enumerator,
1196 .create_dh_enumerator = _create_dh_enumerator,
1197 .create_rng_enumerator = _create_rng_enumerator,
1198 .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
1199 .add_test_vector = _add_test_vector,
1200 .create_verify_enumerator = _create_verify_enumerator,
1201 .destroy = _destroy,
1202 },
1203 .crypters = linked_list_create(),
1204 .aeads = linked_list_create(),
1205 .signers = linked_list_create(),
1206 .hashers = linked_list_create(),
1207 .prfs = linked_list_create(),
1208 .xofs = linked_list_create(),
1209 .rngs = linked_list_create(),
1210 .nonce_gens = linked_list_create(),
1211 .dhs = linked_list_create(),
1212 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1213 .tester = crypto_tester_create(),
1214 .test_on_add = lib->settings->get_bool(lib->settings,
1215 "%s.crypto_test.on_add", FALSE, lib->ns),
1216 .test_on_create = lib->settings->get_bool(lib->settings,
1217 "%s.crypto_test.on_create", FALSE, lib->ns),
1218 .bench = lib->settings->get_bool(lib->settings,
1219 "%s.crypto_test.bench", FALSE, lib->ns),
1220 );
1221
1222 return &this->public;
1223 }