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