Add a return value to hasher_t.get_hash()
[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 diffie_hellman_t *diffie_hellman = NULL;
363
364 this->lock->read_lock(this->lock);
365 enumerator = this->dhs->create_enumerator(this->dhs);
366 while (enumerator->enumerate(enumerator, &entry))
367 {
368 if (entry->algo == group)
369 {
370 if (group == MODP_CUSTOM)
371 {
372 va_list args;
373 chunk_t g, p;
374
375 va_start(args, group);
376 g = va_arg(args, chunk_t);
377 p = va_arg(args, chunk_t);
378 va_end(args);
379 diffie_hellman = entry->create_dh(MODP_CUSTOM, g, p);
380 }
381 else
382 {
383 diffie_hellman = entry->create_dh(group);
384 }
385 if (diffie_hellman)
386 {
387 break;
388 }
389 }
390 }
391 enumerator->destroy(enumerator);
392 this->lock->unlock(this->lock);
393 return diffie_hellman;
394 }
395
396 /**
397 * Insert an algorithm entry to a list
398 */
399 static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
400 int algo, const char *plugin_name,
401 u_int speed, void *create)
402 {
403 entry_t *entry, *current;
404 linked_list_t *tmp;
405 bool inserted = FALSE;
406
407 INIT(entry,
408 .algo = algo,
409 .plugin_name = plugin_name,
410 .speed = speed,
411 );
412 entry->create = create;
413
414 this->lock->write_lock(this->lock);
415 if (speed)
416 { /* insert sorted by speed using a temporary list */
417 tmp = linked_list_create();
418 while (list->remove_first(list, (void**)&current) == SUCCESS)
419 {
420 tmp->insert_last(tmp, current);
421 }
422 while (tmp->remove_first(tmp, (void**)&current) == SUCCESS)
423 {
424 if (!inserted &&
425 current->algo == algo &&
426 current->speed < speed)
427 {
428 list->insert_last(list, entry);
429 inserted = TRUE;
430 }
431 list->insert_last(list, current);
432 }
433 tmp->destroy(tmp);
434 }
435 if (!inserted)
436 {
437 list->insert_last(list, entry);
438 }
439 this->lock->unlock(this->lock);
440 }
441
442 METHOD(crypto_factory_t, add_crypter, void,
443 private_crypto_factory_t *this, encryption_algorithm_t algo,
444 const char *plugin_name, crypter_constructor_t create)
445 {
446 u_int speed = 0;
447
448 if (!this->test_on_add ||
449 this->tester->test_crypter(this->tester, algo, 0, create,
450 this->bench ? &speed : NULL, plugin_name))
451 {
452 add_entry(this, this->crypters, algo, plugin_name, speed, create);
453 }
454 }
455
456 METHOD(crypto_factory_t, remove_crypter, void,
457 private_crypto_factory_t *this, crypter_constructor_t create)
458 {
459 entry_t *entry;
460 enumerator_t *enumerator;
461
462 this->lock->write_lock(this->lock);
463 enumerator = this->crypters->create_enumerator(this->crypters);
464 while (enumerator->enumerate(enumerator, &entry))
465 {
466 if (entry->create_crypter == create)
467 {
468 this->crypters->remove_at(this->crypters, enumerator);
469 free(entry);
470 }
471 }
472 enumerator->destroy(enumerator);
473 this->lock->unlock(this->lock);
474 }
475
476 METHOD(crypto_factory_t, add_aead, void,
477 private_crypto_factory_t *this, encryption_algorithm_t algo,
478 const char *plugin_name, aead_constructor_t create)
479 {
480 u_int speed = 0;
481
482 if (!this->test_on_add ||
483 this->tester->test_aead(this->tester, algo, 0, create,
484 this->bench ? &speed : NULL, plugin_name))
485 {
486 add_entry(this, this->aeads, algo, plugin_name, speed, create);
487 }
488 }
489
490 METHOD(crypto_factory_t, remove_aead, void,
491 private_crypto_factory_t *this, aead_constructor_t create)
492 {
493 entry_t *entry;
494 enumerator_t *enumerator;
495
496 this->lock->write_lock(this->lock);
497 enumerator = this->aeads->create_enumerator(this->aeads);
498 while (enumerator->enumerate(enumerator, &entry))
499 {
500 if (entry->create_aead == create)
501 {
502 this->aeads->remove_at(this->aeads, enumerator);
503 free(entry);
504 }
505 }
506 enumerator->destroy(enumerator);
507 this->lock->unlock(this->lock);
508 }
509
510 METHOD(crypto_factory_t, add_signer, void,
511 private_crypto_factory_t *this, integrity_algorithm_t algo,
512 const char *plugin_name, signer_constructor_t create)
513 {
514 u_int speed = 0;
515
516 if (!this->test_on_add ||
517 this->tester->test_signer(this->tester, algo, create,
518 this->bench ? &speed : NULL, plugin_name))
519 {
520 add_entry(this, this->signers, algo, plugin_name, speed, create);
521 }
522 }
523
524 METHOD(crypto_factory_t, remove_signer, void,
525 private_crypto_factory_t *this, signer_constructor_t create)
526 {
527 entry_t *entry;
528 enumerator_t *enumerator;
529
530 this->lock->write_lock(this->lock);
531 enumerator = this->signers->create_enumerator(this->signers);
532 while (enumerator->enumerate(enumerator, &entry))
533 {
534 if (entry->create_signer == create)
535 {
536 this->signers->remove_at(this->signers, enumerator);
537 free(entry);
538 }
539 }
540 enumerator->destroy(enumerator);
541 this->lock->unlock(this->lock);
542 }
543
544 METHOD(crypto_factory_t, add_hasher, void,
545 private_crypto_factory_t *this, hash_algorithm_t algo,
546 const char *plugin_name, hasher_constructor_t create)
547 {
548 u_int speed = 0;
549
550 if (!this->test_on_add ||
551 this->tester->test_hasher(this->tester, algo, create,
552 this->bench ? &speed : NULL, plugin_name))
553 {
554 add_entry(this, this->hashers, algo, plugin_name, speed, create);
555 }
556 }
557
558 METHOD(crypto_factory_t, remove_hasher, void,
559 private_crypto_factory_t *this, hasher_constructor_t create)
560 {
561 entry_t *entry;
562 enumerator_t *enumerator;
563
564 this->lock->write_lock(this->lock);
565 enumerator = this->hashers->create_enumerator(this->hashers);
566 while (enumerator->enumerate(enumerator, &entry))
567 {
568 if (entry->create_hasher == create)
569 {
570 this->hashers->remove_at(this->hashers, enumerator);
571 free(entry);
572 }
573 }
574 enumerator->destroy(enumerator);
575 this->lock->unlock(this->lock);
576 }
577
578 METHOD(crypto_factory_t, add_prf, void,
579 private_crypto_factory_t *this, pseudo_random_function_t algo,
580 const char *plugin_name, prf_constructor_t create)
581 {
582 u_int speed = 0;
583
584 if (!this->test_on_add ||
585 this->tester->test_prf(this->tester, algo, create,
586 this->bench ? &speed : NULL, plugin_name))
587 {
588 add_entry(this, this->prfs, algo, plugin_name, speed, create);
589 }
590 }
591
592 METHOD(crypto_factory_t, remove_prf, void,
593 private_crypto_factory_t *this, prf_constructor_t create)
594 {
595 entry_t *entry;
596 enumerator_t *enumerator;
597
598 this->lock->write_lock(this->lock);
599 enumerator = this->prfs->create_enumerator(this->prfs);
600 while (enumerator->enumerate(enumerator, &entry))
601 {
602 if (entry->create_prf == create)
603 {
604 this->prfs->remove_at(this->prfs, enumerator);
605 free(entry);
606 }
607 }
608 enumerator->destroy(enumerator);
609 this->lock->unlock(this->lock);
610 }
611
612 METHOD(crypto_factory_t, add_rng, void,
613 private_crypto_factory_t *this, rng_quality_t quality,
614 const char *plugin_name, rng_constructor_t create)
615 {
616 u_int speed = 0;
617
618 if (!this->test_on_add ||
619 this->tester->test_rng(this->tester, quality, create,
620 this->bench ? &speed : NULL, plugin_name))
621 {
622 add_entry(this, this->rngs, quality, plugin_name, speed, create);
623 }
624 }
625
626 METHOD(crypto_factory_t, remove_rng, void,
627 private_crypto_factory_t *this, rng_constructor_t create)
628 {
629 entry_t *entry;
630 enumerator_t *enumerator;
631
632 this->lock->write_lock(this->lock);
633 enumerator = this->rngs->create_enumerator(this->rngs);
634 while (enumerator->enumerate(enumerator, &entry))
635 {
636 if (entry->create_rng == create)
637 {
638 this->rngs->remove_at(this->rngs, enumerator);
639 free(entry);
640 }
641 }
642 enumerator->destroy(enumerator);
643 this->lock->unlock(this->lock);
644 }
645
646 METHOD(crypto_factory_t, add_nonce_gen, void,
647 private_crypto_factory_t *this, const char *plugin_name,
648 nonce_gen_constructor_t create)
649 {
650 add_entry(this, this->nonce_gens, 0, plugin_name, 0, create);
651 }
652
653 METHOD(crypto_factory_t, remove_nonce_gen, void,
654 private_crypto_factory_t *this, nonce_gen_constructor_t create)
655 {
656 entry_t *entry;
657 enumerator_t *enumerator;
658
659 this->lock->write_lock(this->lock);
660 enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
661 while (enumerator->enumerate(enumerator, &entry))
662 {
663 if (entry->create_nonce_gen == create)
664 {
665 this->nonce_gens->remove_at(this->nonce_gens, enumerator);
666 free(entry);
667 }
668 }
669 enumerator->destroy(enumerator);
670 this->lock->unlock(this->lock);
671 }
672
673 METHOD(crypto_factory_t, add_dh, void,
674 private_crypto_factory_t *this, diffie_hellman_group_t group,
675 const char *plugin_name, dh_constructor_t create)
676 {
677 add_entry(this, this->dhs, group, plugin_name, 0, create);
678 }
679
680 METHOD(crypto_factory_t, remove_dh, void,
681 private_crypto_factory_t *this, dh_constructor_t create)
682 {
683 entry_t *entry;
684 enumerator_t *enumerator;
685
686 this->lock->write_lock(this->lock);
687 enumerator = this->dhs->create_enumerator(this->dhs);
688 while (enumerator->enumerate(enumerator, &entry))
689 {
690 if (entry->create_dh == create)
691 {
692 this->dhs->remove_at(this->dhs, enumerator);
693 free(entry);
694 }
695 }
696 enumerator->destroy(enumerator);
697 this->lock->unlock(this->lock);
698 }
699
700 /**
701 * match algorithms of an entry?
702 */
703 static bool entry_match(entry_t *a, entry_t *b)
704 {
705 return a->algo == b->algo;
706 }
707
708 /**
709 * check for uniqueness of an entry
710 */
711 static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out)
712 {
713 if (list->find_first(list, (void*)entry_match, NULL, *in) == SUCCESS)
714 {
715 return FALSE;
716 }
717 *out = *in;
718 list->insert_last(list, *in);
719 return TRUE;
720 }
721
722 /**
723 * create an enumerator over entry->algo in list with locking and unique check
724 */
725 static enumerator_t *create_enumerator(private_crypto_factory_t *this,
726 linked_list_t *list, void *filter)
727 {
728 this->lock->read_lock(this->lock);
729 return enumerator_create_filter(
730 enumerator_create_filter(
731 list->create_enumerator(list), (void*)unique_check,
732 linked_list_create(), (void*)list->destroy),
733 filter, this->lock, (void*)this->lock->unlock);
734 }
735
736 /**
737 * Filter function to enumerate algorithm, not entry
738 */
739 static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo,
740 void *i2, const char **plugin_name)
741 {
742 *algo = (*entry)->algo;
743 *plugin_name = (*entry)->plugin_name;
744 return TRUE;
745 }
746
747 METHOD(crypto_factory_t, create_crypter_enumerator, enumerator_t*,
748 private_crypto_factory_t *this)
749 {
750 return create_enumerator(this, this->crypters, crypter_filter);
751 }
752
753 METHOD(crypto_factory_t, create_aead_enumerator, enumerator_t*,
754 private_crypto_factory_t *this)
755 {
756 return create_enumerator(this, this->aeads, crypter_filter);
757 }
758
759 /**
760 * Filter function to enumerate algorithm, not entry
761 */
762 static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo,
763 void *i2, const char **plugin_name)
764 {
765 *algo = (*entry)->algo;
766 *plugin_name = (*entry)->plugin_name;
767 return TRUE;
768 }
769
770 METHOD(crypto_factory_t, create_signer_enumerator, enumerator_t*,
771 private_crypto_factory_t *this)
772 {
773 return create_enumerator(this, this->signers, signer_filter);
774 }
775
776 /**
777 * Filter function to enumerate algorithm, not entry
778 */
779 static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo,
780 void *i2, const char **plugin_name)
781 {
782 *algo = (*entry)->algo;
783 *plugin_name = (*entry)->plugin_name;
784 return TRUE;
785 }
786
787 METHOD(crypto_factory_t, create_hasher_enumerator, enumerator_t*,
788 private_crypto_factory_t *this)
789 {
790 return create_enumerator(this, this->hashers, hasher_filter);
791 }
792
793 /**
794 * Filter function to enumerate algorithm, not entry
795 */
796 static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo,
797 void *i2, const char **plugin_name)
798 {
799 *algo = (*entry)->algo;
800 *plugin_name = (*entry)->plugin_name;
801 return TRUE;
802 }
803
804 METHOD(crypto_factory_t, create_prf_enumerator, enumerator_t*,
805 private_crypto_factory_t *this)
806 {
807 return create_enumerator(this, this->prfs, prf_filter);
808 }
809
810 /**
811 * Filter function to enumerate group, not entry
812 */
813 static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group,
814 void *i2, const char **plugin_name)
815 {
816 *group = (*entry)->algo;
817 *plugin_name = (*entry)->plugin_name;
818 return TRUE;
819 }
820
821 METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
822 private_crypto_factory_t *this)
823 {
824 return create_enumerator(this, this->dhs, dh_filter);
825 }
826
827 /**
828 * Filter function to enumerate strength, not entry
829 */
830 static bool rng_filter(void *n, entry_t **entry, rng_quality_t *quality,
831 void *i2, const char **plugin_name)
832 {
833 *quality = (*entry)->algo;
834 *plugin_name = (*entry)->plugin_name;
835 return TRUE;
836 }
837
838 METHOD(crypto_factory_t, create_rng_enumerator, enumerator_t*,
839 private_crypto_factory_t *this)
840 {
841 return create_enumerator(this, this->rngs, rng_filter);
842 }
843
844 /**
845 * Filter function to enumerate plugin name, not entry
846 */
847 static bool nonce_gen_filter(void *n, entry_t **entry, const char **plugin_name)
848 {
849 *plugin_name = (*entry)->plugin_name;
850 return TRUE;
851 }
852
853 METHOD(crypto_factory_t, create_nonce_gen_enumerator, enumerator_t*,
854 private_crypto_factory_t *this)
855 {
856 return create_enumerator(this, this->nonce_gens, nonce_gen_filter);
857 }
858
859 METHOD(crypto_factory_t, add_test_vector, void,
860 private_crypto_factory_t *this, transform_type_t type, void *vector)
861 {
862 switch (type)
863 {
864 case ENCRYPTION_ALGORITHM:
865 return this->tester->add_crypter_vector(this->tester, vector);
866 case AEAD_ALGORITHM:
867 return this->tester->add_aead_vector(this->tester, vector);
868 case INTEGRITY_ALGORITHM:
869 return this->tester->add_signer_vector(this->tester, vector);
870 case HASH_ALGORITHM:
871 return this->tester->add_hasher_vector(this->tester, vector);
872 case PSEUDO_RANDOM_FUNCTION:
873 return this->tester->add_prf_vector(this->tester, vector);
874 case RANDOM_NUMBER_GENERATOR:
875 return this->tester->add_rng_vector(this->tester, vector);
876 default:
877 DBG1(DBG_LIB, "%N test vectors not supported, ignored",
878 transform_type_names, type);
879 }
880 }
881
882 METHOD(crypto_factory_t, destroy, void,
883 private_crypto_factory_t *this)
884 {
885 this->crypters->destroy(this->crypters);
886 this->aeads->destroy(this->aeads);
887 this->signers->destroy(this->signers);
888 this->hashers->destroy(this->hashers);
889 this->prfs->destroy(this->prfs);
890 this->rngs->destroy(this->rngs);
891 this->nonce_gens->destroy(this->nonce_gens);
892 this->dhs->destroy(this->dhs);
893 this->tester->destroy(this->tester);
894 this->lock->destroy(this->lock);
895 free(this);
896 }
897
898 /*
899 * see header file
900 */
901 crypto_factory_t *crypto_factory_create()
902 {
903 private_crypto_factory_t *this;
904
905 INIT(this,
906 .public = {
907 .create_crypter = _create_crypter,
908 .create_aead = _create_aead,
909 .create_signer = _create_signer,
910 .create_hasher = _create_hasher,
911 .create_prf = _create_prf,
912 .create_rng = _create_rng,
913 .create_nonce_gen = _create_nonce_gen,
914 .create_dh = _create_dh,
915 .add_crypter = _add_crypter,
916 .remove_crypter = _remove_crypter,
917 .add_aead = _add_aead,
918 .remove_aead = _remove_aead,
919 .add_signer = _add_signer,
920 .remove_signer = _remove_signer,
921 .add_hasher = _add_hasher,
922 .remove_hasher = _remove_hasher,
923 .add_prf = _add_prf,
924 .remove_prf = _remove_prf,
925 .add_rng = _add_rng,
926 .remove_rng = _remove_rng,
927 .add_nonce_gen = _add_nonce_gen,
928 .remove_nonce_gen = _remove_nonce_gen,
929 .add_dh = _add_dh,
930 .remove_dh = _remove_dh,
931 .create_crypter_enumerator = _create_crypter_enumerator,
932 .create_aead_enumerator = _create_aead_enumerator,
933 .create_signer_enumerator = _create_signer_enumerator,
934 .create_hasher_enumerator = _create_hasher_enumerator,
935 .create_prf_enumerator = _create_prf_enumerator,
936 .create_dh_enumerator = _create_dh_enumerator,
937 .create_rng_enumerator = _create_rng_enumerator,
938 .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
939 .add_test_vector = _add_test_vector,
940 .destroy = _destroy,
941 },
942 .crypters = linked_list_create(),
943 .aeads = linked_list_create(),
944 .signers = linked_list_create(),
945 .hashers = linked_list_create(),
946 .prfs = linked_list_create(),
947 .rngs = linked_list_create(),
948 .nonce_gens = linked_list_create(),
949 .dhs = linked_list_create(),
950 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
951 .tester = crypto_tester_create(),
952 .test_on_add = lib->settings->get_bool(lib->settings,
953 "libstrongswan.crypto_test.on_add", FALSE),
954 .test_on_create = lib->settings->get_bool(lib->settings,
955 "libstrongswan.crypto_test.on_create", FALSE),
956 .bench = lib->settings->get_bool(lib->settings,
957 "libstrongswan.crypto_test.bench", FALSE),
958 );
959
960 return &this->public;
961 }
962