make use of the crypto_tester in the crypto_factory
[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 <utils/mutex.h>
20 #include <utils/linked_list.h>
21 #include <crypto/crypto_tester.h>
22
23 typedef struct entry_t entry_t;
24 struct entry_t {
25 /** algorithm */
26 u_int algo;
27 /* constructor */
28 union {
29 crypter_constructor_t create_crypter;
30 signer_constructor_t create_signer;
31 hasher_constructor_t create_hasher;
32 prf_constructor_t create_prf;
33 rng_constructor_t create_rng;
34 dh_constructor_t create_dh;
35 };
36 };
37
38 typedef struct private_crypto_factory_t private_crypto_factory_t;
39
40 /**
41 * private data of crypto_factory
42 */
43 struct private_crypto_factory_t {
44
45 /**
46 * public functions
47 */
48 crypto_factory_t public;
49
50 /**
51 * registered crypters, as entry_t
52 */
53 linked_list_t *crypters;
54
55 /**
56 * registered signers, as entry_t
57 */
58 linked_list_t *signers;
59
60 /**
61 * registered hashers, as entry_t
62 */
63 linked_list_t *hashers;
64
65 /**
66 * registered prfs, as entry_t
67 */
68 linked_list_t *prfs;
69
70 /**
71 * registered rngs, as entry_t
72 */
73 linked_list_t *rngs;
74
75 /**
76 * registered diffie hellman, as entry_t
77 */
78 linked_list_t *dhs;
79
80 /**
81 * test manager to test crypto algorithms
82 */
83 crypto_tester_t *tester;
84
85 /**
86 * whether to test algorithms during registration
87 */
88 bool test_on_add;
89
90 /**
91 * whether to test algorithms on each crypto primitive construction
92 */
93 bool test_on_create;
94
95 /**
96 * rwlock to lock access to modules
97 */
98 rwlock_t *lock;
99 };
100
101 /**
102 * Implementation of crypto_factory_t.create_crypter.
103 */
104 static crypter_t* create_crypter(private_crypto_factory_t *this,
105 encryption_algorithm_t algo, size_t key_size)
106 {
107 enumerator_t *enumerator;
108 entry_t *entry;
109 crypter_t *crypter = NULL;
110
111 this->lock->read_lock(this->lock);
112 enumerator = this->crypters->create_enumerator(this->crypters);
113 while (enumerator->enumerate(enumerator, &entry))
114 {
115 if (entry->algo == algo)
116 {
117 if (this->test_on_create &&
118 !this->tester->test_crypter(this->tester, algo, key_size,
119 entry->create_crypter))
120 {
121 continue;
122 }
123 crypter = entry->create_crypter(algo, key_size);
124 if (crypter)
125 {
126 break;
127 }
128 }
129 }
130 enumerator->destroy(enumerator);
131 this->lock->unlock(this->lock);
132 return crypter;
133 }
134
135 /**
136 * Implementation of crypto_factory_t.create_signer.
137 */
138 static signer_t* create_signer(private_crypto_factory_t *this,
139 integrity_algorithm_t algo)
140 {
141 enumerator_t *enumerator;
142 entry_t *entry;
143 signer_t *signer = NULL;
144
145 this->lock->read_lock(this->lock);
146 enumerator = this->signers->create_enumerator(this->signers);
147 while (enumerator->enumerate(enumerator, &entry))
148 {
149 if (entry->algo == algo)
150 {
151 if (this->test_on_create &&
152 !this->tester->test_signer(this->tester, algo,
153 entry->create_signer))
154 {
155 continue;
156 }
157 signer = entry->create_signer(algo);
158 if (signer)
159 {
160 break;
161 }
162 }
163 }
164 enumerator->destroy(enumerator);
165 this->lock->unlock(this->lock);
166
167 return signer;
168 }
169
170 /**
171 * Implementation of crypto_factory_t.create_hasher.
172 */
173 static hasher_t* create_hasher(private_crypto_factory_t *this,
174 hash_algorithm_t algo)
175 {
176 enumerator_t *enumerator;
177 entry_t *entry;
178 hasher_t *hasher = NULL;
179
180 this->lock->read_lock(this->lock);
181 enumerator = this->hashers->create_enumerator(this->hashers);
182 while (enumerator->enumerate(enumerator, &entry))
183 {
184 if (algo == HASH_PREFERRED || entry->algo == algo)
185 {
186 if (this->test_on_create && algo != HASH_PREFERRED &&
187 !this->tester->test_hasher(this->tester, algo,
188 entry->create_hasher))
189 {
190 continue;
191 }
192 hasher = entry->create_hasher(entry->algo);
193 if (hasher)
194 {
195 break;
196 }
197 }
198 }
199 enumerator->destroy(enumerator);
200 this->lock->unlock(this->lock);
201 return hasher;
202 }
203
204 /**
205 * Implementation of crypto_factory_t.create_prf.
206 */
207 static prf_t* create_prf(private_crypto_factory_t *this,
208 pseudo_random_function_t algo)
209 {
210 enumerator_t *enumerator;
211 entry_t *entry;
212 prf_t *prf = NULL;
213
214 this->lock->read_lock(this->lock);
215 enumerator = this->prfs->create_enumerator(this->prfs);
216 while (enumerator->enumerate(enumerator, &entry))
217 {
218 if (entry->algo == algo)
219 {
220 if (this->test_on_create &&
221 !this->tester->test_prf(this->tester, algo, entry->create_prf))
222 {
223 continue;
224 }
225 prf = entry->create_prf(algo);
226 if (prf)
227 {
228 break;
229 }
230 }
231 }
232 enumerator->destroy(enumerator);
233 this->lock->unlock(this->lock);
234 return prf;
235 }
236
237 /**
238 * Implementation of crypto_factory_t.create_rng.
239 */
240 static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality)
241 {
242 enumerator_t *enumerator;
243 entry_t *entry;
244 u_int diff = ~0;
245 rng_constructor_t constr = NULL;
246
247 this->lock->read_lock(this->lock);
248 enumerator = this->rngs->create_enumerator(this->rngs);
249 while (enumerator->enumerate(enumerator, &entry))
250 { /* find the best matching quality, but at least as good as requested */
251 if (entry->algo >= quality && diff > entry->algo - quality)
252 {
253 if (this->test_on_create &&
254 !this->tester->test_rng(this->tester, quality, entry->create_rng))
255 {
256 continue;
257 }
258 diff = entry->algo - quality;
259 constr = entry->create_rng;
260 if (diff == 0)
261 { /* perfect match, won't get better */
262 break;
263 }
264 }
265 }
266 enumerator->destroy(enumerator);
267 this->lock->unlock(this->lock);
268 if (constr)
269 {
270 return constr(quality);
271 }
272 return NULL;
273 }
274
275 /**
276 * Implementation of crypto_factory_t.create_dh.
277 */
278 static diffie_hellman_t* create_dh(private_crypto_factory_t *this,
279 diffie_hellman_group_t group)
280 {
281 enumerator_t *enumerator;
282 entry_t *entry;
283 diffie_hellman_t *diffie_hellman = NULL;
284
285 this->lock->read_lock(this->lock);
286 enumerator = this->dhs->create_enumerator(this->dhs);
287 while (enumerator->enumerate(enumerator, &entry))
288 {
289 if (entry->algo == group)
290 {
291 diffie_hellman = entry->create_dh(group);
292 if (diffie_hellman)
293 {
294 break;
295 }
296 }
297 }
298 enumerator->destroy(enumerator);
299 this->lock->unlock(this->lock);
300 return diffie_hellman;
301 }
302
303 /**
304 * Implementation of crypto_factory_t.add_crypter.
305 */
306 static void add_crypter(private_crypto_factory_t *this,
307 encryption_algorithm_t algo,
308 crypter_constructor_t create)
309 {
310 if (!this->test_on_add ||
311 this->tester->test_crypter(this->tester, algo, 0, create))
312 {
313 entry_t *entry = malloc_thing(entry_t);
314
315 entry->algo = algo;
316 entry->create_crypter = create;
317 this->lock->write_lock(this->lock);
318 this->crypters->insert_last(this->crypters, entry);
319 this->lock->unlock(this->lock);
320 }
321 }
322
323 /**
324 * Implementation of crypto_factory_t.remove_crypter.
325 */
326 static void remove_crypter(private_crypto_factory_t *this,
327 crypter_constructor_t create)
328 {
329 entry_t *entry;
330 enumerator_t *enumerator;
331
332 this->lock->write_lock(this->lock);
333 enumerator = this->crypters->create_enumerator(this->crypters);
334 while (enumerator->enumerate(enumerator, &entry))
335 {
336 if (entry->create_crypter == create)
337 {
338 this->crypters->remove_at(this->crypters, enumerator);
339 free(entry);
340 }
341 }
342 enumerator->destroy(enumerator);
343 this->lock->unlock(this->lock);
344 }
345
346 /**
347 * Implementation of crypto_factory_t.add_signer.
348 */
349 static void add_signer(private_crypto_factory_t *this,
350 integrity_algorithm_t algo, signer_constructor_t create)
351 {
352 if (!this->test_on_add ||
353 this->tester->test_signer(this->tester, algo, create))
354 {
355 entry_t *entry = malloc_thing(entry_t);
356
357 entry->algo = algo;
358 entry->create_signer = create;
359 this->lock->write_lock(this->lock);
360 this->signers->insert_last(this->signers, entry);
361 this->lock->unlock(this->lock);
362 }
363 }
364
365 /**
366 * Implementation of crypto_factory_t.remove_signer.
367 */
368 static void remove_signer(private_crypto_factory_t *this,
369 signer_constructor_t create)
370 {
371 entry_t *entry;
372 enumerator_t *enumerator;
373
374 this->lock->write_lock(this->lock);
375 enumerator = this->signers->create_enumerator(this->signers);
376 while (enumerator->enumerate(enumerator, &entry))
377 {
378 if (entry->create_signer == create)
379 {
380 this->signers->remove_at(this->signers, enumerator);
381 free(entry);
382 }
383 }
384 enumerator->destroy(enumerator);
385 this->lock->unlock(this->lock);
386 }
387
388 /**
389 * Implementation of crypto_factory_t.add_hasher.
390 */
391 static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo,
392 hasher_constructor_t create)
393 {
394 if (!this->test_on_add ||
395 this->tester->test_hasher(this->tester, algo, create))
396 {
397 entry_t *entry = malloc_thing(entry_t);
398
399 entry->algo = algo;
400 entry->create_hasher = create;
401 this->lock->write_lock(this->lock);
402 this->hashers->insert_last(this->hashers, entry);
403 this->lock->unlock(this->lock);
404 }
405 }
406
407 /**
408 * Implementation of crypto_factory_t.remove_hasher.
409 */
410 static void remove_hasher(private_crypto_factory_t *this,
411 hasher_constructor_t create)
412 {
413 entry_t *entry;
414 enumerator_t *enumerator;
415
416 this->lock->write_lock(this->lock);
417 enumerator = this->hashers->create_enumerator(this->hashers);
418 while (enumerator->enumerate(enumerator, &entry))
419 {
420 if (entry->create_hasher == create)
421 {
422 this->hashers->remove_at(this->hashers, enumerator);
423 free(entry);
424 }
425 }
426 enumerator->destroy(enumerator);
427 this->lock->unlock(this->lock);
428 }
429
430 /**
431 * Implementation of crypto_factory_t.add_prf.
432 */
433 static void add_prf(private_crypto_factory_t *this,
434 pseudo_random_function_t algo, prf_constructor_t create)
435 {
436 if (!this->test_on_add ||
437 this->tester->test_prf(this->tester, algo, create))
438 {
439 entry_t *entry = malloc_thing(entry_t);
440
441 entry->algo = algo;
442 entry->create_prf = create;
443 this->lock->write_lock(this->lock);
444 this->prfs->insert_last(this->prfs, entry);
445 this->lock->unlock(this->lock);
446 }
447 }
448
449 /**
450 * Implementation of crypto_factory_t.remove_prf.
451 */
452 static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create)
453 {
454 entry_t *entry;
455 enumerator_t *enumerator;
456
457 this->lock->write_lock(this->lock);
458 enumerator = this->prfs->create_enumerator(this->prfs);
459 while (enumerator->enumerate(enumerator, &entry))
460 {
461 if (entry->create_prf == create)
462 {
463 this->prfs->remove_at(this->prfs, enumerator);
464 free(entry);
465 }
466 }
467 enumerator->destroy(enumerator);
468 this->lock->unlock(this->lock);
469 }
470
471 /**
472 * Implementation of crypto_factory_t.add_rng.
473 */
474 static void add_rng(private_crypto_factory_t *this, rng_quality_t quality,
475 rng_constructor_t create)
476 {
477 if (!this->test_on_add ||
478 this->tester->test_rng(this->tester, quality, create))
479 {
480 entry_t *entry = malloc_thing(entry_t);
481
482 entry->algo = quality;
483 entry->create_rng = create;
484 this->lock->write_lock(this->lock);
485 this->rngs->insert_last(this->rngs, entry);
486 this->lock->unlock(this->lock);
487 }
488 }
489
490 /**
491 * Implementation of crypto_factory_t.remove_rng.
492 */
493 static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create)
494 {
495 entry_t *entry;
496 enumerator_t *enumerator;
497
498 this->lock->write_lock(this->lock);
499 enumerator = this->rngs->create_enumerator(this->rngs);
500 while (enumerator->enumerate(enumerator, &entry))
501 {
502 if (entry->create_rng == create)
503 {
504 this->rngs->remove_at(this->rngs, enumerator);
505 free(entry);
506 }
507 }
508 enumerator->destroy(enumerator);
509 this->lock->unlock(this->lock);
510 }
511
512 /**
513 * Implementation of crypto_factory_t.add_dh.
514 */
515 static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group,
516 dh_constructor_t create)
517 {
518 entry_t *entry = malloc_thing(entry_t);
519
520 entry->algo = group;
521 entry->create_dh = create;
522 this->lock->write_lock(this->lock);
523 this->dhs->insert_last(this->dhs, entry);
524 this->lock->unlock(this->lock);
525 }
526
527 /**
528 * Implementation of crypto_factory_t.remove_dh.
529 */
530 static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create)
531 {
532 entry_t *entry;
533 enumerator_t *enumerator;
534
535 this->lock->write_lock(this->lock);
536 enumerator = this->dhs->create_enumerator(this->dhs);
537 while (enumerator->enumerate(enumerator, &entry))
538 {
539 if (entry->create_dh == create)
540 {
541 this->dhs->remove_at(this->dhs, enumerator);
542 free(entry);
543 }
544 }
545 enumerator->destroy(enumerator);
546 this->lock->unlock(this->lock);
547 }
548
549 /**
550 * match algorithms of an entry?
551 */
552 static bool entry_match(entry_t *a, entry_t *b)
553 {
554 return a->algo == b->algo;
555 }
556
557 /**
558 * check for uniqueness of an entry
559 */
560 static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out)
561 {
562 if (list->find_first(list, (void*)entry_match, NULL, *in) == SUCCESS)
563 {
564 return FALSE;
565 }
566 *out = *in;
567 list->insert_last(list, *in);
568 return TRUE;
569 }
570
571 /**
572 * create an enumerator over entry->algo in list with locking and unique check
573 */
574 static enumerator_t *create_enumerator(private_crypto_factory_t *this,
575 linked_list_t *list, void *filter)
576 {
577 this->lock->read_lock(this->lock);
578 return enumerator_create_filter(
579 enumerator_create_filter(
580 list->create_enumerator(list), (void*)unique_check,
581 linked_list_create(), (void*)list->destroy),
582 filter, this->lock, (void*)this->lock->unlock);
583 }
584
585 /**
586 * Filter function to enumerate algorithm, not entry
587 */
588 static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo)
589 {
590 *algo = (*entry)->algo;
591 return TRUE;
592 }
593
594 /**
595 * Implementation of crypto_factory_t.create_crypter_enumerator
596 */
597 static enumerator_t* create_crypter_enumerator(private_crypto_factory_t *this)
598 {
599 return create_enumerator(this, this->crypters, crypter_filter);
600 }
601
602 /**
603 * Filter function to enumerate algorithm, not entry
604 */
605 static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo)
606 {
607 *algo = (*entry)->algo;
608 return TRUE;
609 }
610
611 /**
612 * Implementation of crypto_factory_t.create_signer_enumerator
613 */
614 static enumerator_t* create_signer_enumerator(private_crypto_factory_t *this)
615 {
616 return create_enumerator(this, this->signers, signer_filter);
617 }
618
619 /**
620 * Filter function to enumerate algorithm, not entry
621 */
622 static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo)
623 {
624 *algo = (*entry)->algo;
625 return TRUE;
626 }
627
628 /**
629 * Implementation of crypto_factory_t.create_hasher_enumerator
630 */
631 static enumerator_t* create_hasher_enumerator(private_crypto_factory_t *this)
632 {
633 return create_enumerator(this, this->hashers, hasher_filter);
634 }
635
636 /**
637 * Filter function to enumerate algorithm, not entry
638 */
639 static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo)
640 {
641 *algo = (*entry)->algo;
642 return TRUE;
643 }
644
645 /**
646 * Implementation of crypto_factory_t.create_prf_enumerator
647 */
648 static enumerator_t* create_prf_enumerator(private_crypto_factory_t *this)
649 {
650 return create_enumerator(this, this->prfs, prf_filter);
651 }
652
653 /**
654 * Filter function to enumerate algorithm, not entry
655 */
656 static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group)
657 {
658 *group = (*entry)->algo;
659 return TRUE;
660 }
661
662 /**
663 * Implementation of crypto_factory_t.create_dh_enumerator
664 */
665 static enumerator_t* create_dh_enumerator(private_crypto_factory_t *this)
666 {
667 return create_enumerator(this, this->dhs, dh_filter);
668 }
669
670 /**
671 * Implementation of crypto_factory_t.add_test_vector
672 */
673 static void add_test_vector(private_crypto_factory_t *this,
674 transform_type_t type, void *vector)
675 {
676 switch (type)
677 {
678 case ENCRYPTION_ALGORITHM:
679 return this->tester->add_crypter_vector(this->tester, vector);
680 case INTEGRITY_ALGORITHM:
681 return this->tester->add_signer_vector(this->tester, vector);
682 case HASH_ALGORITHM:
683 return this->tester->add_hasher_vector(this->tester, vector);
684 case PSEUDO_RANDOM_FUNCTION:
685 return this->tester->add_prf_vector(this->tester, vector);
686 case RANDOM_NUMBER_GENERATOR:
687 return this->tester->add_rng_vector(this->tester, vector);
688 default:
689 DBG1("%N test vectors not supported, ignored",
690 transform_type_names, type);
691 }
692 }
693
694 /**
695 * Implementation of crypto_factory_t.destroy
696 */
697 static void destroy(private_crypto_factory_t *this)
698 {
699 this->crypters->destroy_function(this->crypters, free);
700 this->signers->destroy_function(this->signers, free);
701 this->hashers->destroy_function(this->hashers, free);
702 this->prfs->destroy_function(this->prfs, free);
703 this->rngs->destroy_function(this->rngs, free);
704 this->dhs->destroy_function(this->dhs, free);
705 this->tester->destroy(this->tester);
706 this->lock->destroy(this->lock);
707 free(this);
708 }
709
710 /*
711 * see header file
712 */
713 crypto_factory_t *crypto_factory_create()
714 {
715 private_crypto_factory_t *this = malloc_thing(private_crypto_factory_t);
716
717 this->public.create_crypter = (crypter_t*(*)(crypto_factory_t*, encryption_algorithm_t, size_t))create_crypter;
718 this->public.create_signer = (signer_t*(*)(crypto_factory_t*, integrity_algorithm_t))create_signer;
719 this->public.create_hasher = (hasher_t*(*)(crypto_factory_t*, hash_algorithm_t))create_hasher;
720 this->public.create_prf = (prf_t*(*)(crypto_factory_t*, pseudo_random_function_t))create_prf;
721 this->public.create_rng = (rng_t*(*)(crypto_factory_t*, rng_quality_t quality))create_rng;
722 this->public.create_dh = (diffie_hellman_t*(*)(crypto_factory_t*, diffie_hellman_group_t group))create_dh;
723 this->public.add_crypter = (void(*)(crypto_factory_t*, encryption_algorithm_t algo, crypter_constructor_t create))add_crypter;
724 this->public.remove_crypter = (void(*)(crypto_factory_t*, crypter_constructor_t create))remove_crypter;
725 this->public.add_signer = (void(*)(crypto_factory_t*, integrity_algorithm_t algo, signer_constructor_t create))add_signer;
726 this->public.remove_signer = (void(*)(crypto_factory_t*, signer_constructor_t create))remove_signer;
727 this->public.add_hasher = (void(*)(crypto_factory_t*, hash_algorithm_t algo, hasher_constructor_t create))add_hasher;
728 this->public.remove_hasher = (void(*)(crypto_factory_t*, hasher_constructor_t create))remove_hasher;
729 this->public.add_prf = (void(*)(crypto_factory_t*, pseudo_random_function_t algo, prf_constructor_t create))add_prf;
730 this->public.remove_prf = (void(*)(crypto_factory_t*, prf_constructor_t create))remove_prf;
731 this->public.add_rng = (void(*)(crypto_factory_t*, rng_quality_t quality, rng_constructor_t create))add_rng;
732 this->public.remove_rng = (void(*)(crypto_factory_t*, rng_constructor_t create))remove_rng;
733 this->public.add_dh = (void(*)(crypto_factory_t*, diffie_hellman_group_t algo, dh_constructor_t create))add_dh;
734 this->public.remove_dh = (void(*)(crypto_factory_t*, dh_constructor_t create))remove_dh;
735 this->public.create_crypter_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_crypter_enumerator;
736 this->public.create_signer_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_signer_enumerator;
737 this->public.create_hasher_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_hasher_enumerator;
738 this->public.create_prf_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_prf_enumerator;
739 this->public.create_dh_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_dh_enumerator;
740 this->public.add_test_vector = (void(*)(crypto_factory_t*, transform_type_t type, ...))add_test_vector;
741 this->public.destroy = (void(*)(crypto_factory_t*))destroy;
742
743 this->crypters = linked_list_create();
744 this->signers = linked_list_create();
745 this->hashers = linked_list_create();
746 this->prfs = linked_list_create();
747 this->rngs = linked_list_create();
748 this->dhs = linked_list_create();
749 this->lock = rwlock_create(RWLOCK_DEFAULT);
750 this->tester = crypto_tester_create();
751 this->test_on_add = lib->settings->get_bool(lib->settings,
752 "libstrongswan.crypto.test.on_add", FALSE);
753 this->test_on_create = lib->settings->get_bool(lib->settings,
754 "libstrongswan.crypto.test.on_create", FALSE);
755
756 return &this->public;
757 }
758