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