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