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, ¤t))
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>