2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
16 #include "crypto_factory.h"
19 #include <utils/mutex.h>
20 #include <utils/linked_list.h>
21 #include <crypto/crypto_tester.h>
23 typedef struct entry_t entry_t
;
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
;
38 typedef struct private_crypto_factory_t private_crypto_factory_t
;
41 * private data of crypto_factory
43 struct private_crypto_factory_t
{
48 crypto_factory_t
public;
51 * registered crypters, as entry_t
53 linked_list_t
*crypters
;
56 * registered signers, as entry_t
58 linked_list_t
*signers
;
61 * registered hashers, as entry_t
63 linked_list_t
*hashers
;
66 * registered prfs, as entry_t
71 * registered rngs, as entry_t
76 * registered diffie hellman, as entry_t
81 * test manager to test crypto algorithms
83 crypto_tester_t
*tester
;
86 * whether to test algorithms during registration
91 * whether to test algorithms on each crypto primitive construction
96 * rwlock to lock access to modules
102 * Implementation of crypto_factory_t.create_crypter.
104 static crypter_t
* create_crypter(private_crypto_factory_t
*this,
105 encryption_algorithm_t algo
, size_t key_size
)
107 enumerator_t
*enumerator
;
109 crypter_t
*crypter
= NULL
;
111 this->lock
->read_lock(this->lock
);
112 enumerator
= this->crypters
->create_enumerator(this->crypters
);
113 while (enumerator
->enumerate(enumerator
, &entry
))
115 if (entry
->algo
== algo
)
117 if (this->test_on_create
&&
118 !this->tester
->test_crypter(this->tester
, algo
, key_size
,
119 entry
->create_crypter
))
123 crypter
= entry
->create_crypter(algo
, key_size
);
130 enumerator
->destroy(enumerator
);
131 this->lock
->unlock(this->lock
);
136 * Implementation of crypto_factory_t.create_signer.
138 static signer_t
* create_signer(private_crypto_factory_t
*this,
139 integrity_algorithm_t algo
)
141 enumerator_t
*enumerator
;
143 signer_t
*signer
= NULL
;
145 this->lock
->read_lock(this->lock
);
146 enumerator
= this->signers
->create_enumerator(this->signers
);
147 while (enumerator
->enumerate(enumerator
, &entry
))
149 if (entry
->algo
== algo
)
151 if (this->test_on_create
&&
152 !this->tester
->test_signer(this->tester
, algo
,
153 entry
->create_signer
))
157 signer
= entry
->create_signer(algo
);
164 enumerator
->destroy(enumerator
);
165 this->lock
->unlock(this->lock
);
171 * Implementation of crypto_factory_t.create_hasher.
173 static hasher_t
* create_hasher(private_crypto_factory_t
*this,
174 hash_algorithm_t algo
)
176 enumerator_t
*enumerator
;
178 hasher_t
*hasher
= NULL
;
180 this->lock
->read_lock(this->lock
);
181 enumerator
= this->hashers
->create_enumerator(this->hashers
);
182 while (enumerator
->enumerate(enumerator
, &entry
))
184 if (algo
== HASH_PREFERRED
|| entry
->algo
== algo
)
186 if (this->test_on_create
&& algo
!= HASH_PREFERRED
&&
187 !this->tester
->test_hasher(this->tester
, algo
,
188 entry
->create_hasher
))
192 hasher
= entry
->create_hasher(entry
->algo
);
199 enumerator
->destroy(enumerator
);
200 this->lock
->unlock(this->lock
);
205 * Implementation of crypto_factory_t.create_prf.
207 static prf_t
* create_prf(private_crypto_factory_t
*this,
208 pseudo_random_function_t algo
)
210 enumerator_t
*enumerator
;
214 this->lock
->read_lock(this->lock
);
215 enumerator
= this->prfs
->create_enumerator(this->prfs
);
216 while (enumerator
->enumerate(enumerator
, &entry
))
218 if (entry
->algo
== algo
)
220 if (this->test_on_create
&&
221 !this->tester
->test_prf(this->tester
, algo
, entry
->create_prf
))
225 prf
= entry
->create_prf(algo
);
232 enumerator
->destroy(enumerator
);
233 this->lock
->unlock(this->lock
);
238 * Implementation of crypto_factory_t.create_rng.
240 static rng_t
* create_rng(private_crypto_factory_t
*this, rng_quality_t quality
)
242 enumerator_t
*enumerator
;
245 rng_constructor_t constr
= NULL
;
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
)
253 if (this->test_on_create
&&
254 !this->tester
->test_rng(this->tester
, quality
, entry
->create_rng
))
258 diff
= entry
->algo
- quality
;
259 constr
= entry
->create_rng
;
261 { /* perfect match, won't get better */
266 enumerator
->destroy(enumerator
);
267 this->lock
->unlock(this->lock
);
270 return constr(quality
);
276 * Implementation of crypto_factory_t.create_dh.
278 static diffie_hellman_t
* create_dh(private_crypto_factory_t
*this,
279 diffie_hellman_group_t group
)
281 enumerator_t
*enumerator
;
283 diffie_hellman_t
*diffie_hellman
= NULL
;
285 this->lock
->read_lock(this->lock
);
286 enumerator
= this->dhs
->create_enumerator(this->dhs
);
287 while (enumerator
->enumerate(enumerator
, &entry
))
289 if (entry
->algo
== group
)
291 diffie_hellman
= entry
->create_dh(group
);
298 enumerator
->destroy(enumerator
);
299 this->lock
->unlock(this->lock
);
300 return diffie_hellman
;
304 * Implementation of crypto_factory_t.add_crypter.
306 static void add_crypter(private_crypto_factory_t
*this,
307 encryption_algorithm_t algo
,
308 crypter_constructor_t create
)
310 if (!this->test_on_add
||
311 this->tester
->test_crypter(this->tester
, algo
, 0, create
))
313 entry_t
*entry
= malloc_thing(entry_t
);
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
);
324 * Implementation of crypto_factory_t.remove_crypter.
326 static void remove_crypter(private_crypto_factory_t
*this,
327 crypter_constructor_t create
)
330 enumerator_t
*enumerator
;
332 this->lock
->write_lock(this->lock
);
333 enumerator
= this->crypters
->create_enumerator(this->crypters
);
334 while (enumerator
->enumerate(enumerator
, &entry
))
336 if (entry
->create_crypter
== create
)
338 this->crypters
->remove_at(this->crypters
, enumerator
);
342 enumerator
->destroy(enumerator
);
343 this->lock
->unlock(this->lock
);
347 * Implementation of crypto_factory_t.add_signer.
349 static void add_signer(private_crypto_factory_t
*this,
350 integrity_algorithm_t algo
, signer_constructor_t create
)
352 if (!this->test_on_add
||
353 this->tester
->test_signer(this->tester
, algo
, create
))
355 entry_t
*entry
= malloc_thing(entry_t
);
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
);
366 * Implementation of crypto_factory_t.remove_signer.
368 static void remove_signer(private_crypto_factory_t
*this,
369 signer_constructor_t create
)
372 enumerator_t
*enumerator
;
374 this->lock
->write_lock(this->lock
);
375 enumerator
= this->signers
->create_enumerator(this->signers
);
376 while (enumerator
->enumerate(enumerator
, &entry
))
378 if (entry
->create_signer
== create
)
380 this->signers
->remove_at(this->signers
, enumerator
);
384 enumerator
->destroy(enumerator
);
385 this->lock
->unlock(this->lock
);
389 * Implementation of crypto_factory_t.add_hasher.
391 static void add_hasher(private_crypto_factory_t
*this, hash_algorithm_t algo
,
392 hasher_constructor_t create
)
394 if (!this->test_on_add
||
395 this->tester
->test_hasher(this->tester
, algo
, create
))
397 entry_t
*entry
= malloc_thing(entry_t
);
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
);
408 * Implementation of crypto_factory_t.remove_hasher.
410 static void remove_hasher(private_crypto_factory_t
*this,
411 hasher_constructor_t create
)
414 enumerator_t
*enumerator
;
416 this->lock
->write_lock(this->lock
);
417 enumerator
= this->hashers
->create_enumerator(this->hashers
);
418 while (enumerator
->enumerate(enumerator
, &entry
))
420 if (entry
->create_hasher
== create
)
422 this->hashers
->remove_at(this->hashers
, enumerator
);
426 enumerator
->destroy(enumerator
);
427 this->lock
->unlock(this->lock
);
431 * Implementation of crypto_factory_t.add_prf.
433 static void add_prf(private_crypto_factory_t
*this,
434 pseudo_random_function_t algo
, prf_constructor_t create
)
436 if (!this->test_on_add
||
437 this->tester
->test_prf(this->tester
, algo
, create
))
439 entry_t
*entry
= malloc_thing(entry_t
);
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
);
450 * Implementation of crypto_factory_t.remove_prf.
452 static void remove_prf(private_crypto_factory_t
*this, prf_constructor_t create
)
455 enumerator_t
*enumerator
;
457 this->lock
->write_lock(this->lock
);
458 enumerator
= this->prfs
->create_enumerator(this->prfs
);
459 while (enumerator
->enumerate(enumerator
, &entry
))
461 if (entry
->create_prf
== create
)
463 this->prfs
->remove_at(this->prfs
, enumerator
);
467 enumerator
->destroy(enumerator
);
468 this->lock
->unlock(this->lock
);
472 * Implementation of crypto_factory_t.add_rng.
474 static void add_rng(private_crypto_factory_t
*this, rng_quality_t quality
,
475 rng_constructor_t create
)
477 if (!this->test_on_add
||
478 this->tester
->test_rng(this->tester
, quality
, create
))
480 entry_t
*entry
= malloc_thing(entry_t
);
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
);
491 * Implementation of crypto_factory_t.remove_rng.
493 static void remove_rng(private_crypto_factory_t
*this, rng_constructor_t create
)
496 enumerator_t
*enumerator
;
498 this->lock
->write_lock(this->lock
);
499 enumerator
= this->rngs
->create_enumerator(this->rngs
);
500 while (enumerator
->enumerate(enumerator
, &entry
))
502 if (entry
->create_rng
== create
)
504 this->rngs
->remove_at(this->rngs
, enumerator
);
508 enumerator
->destroy(enumerator
);
509 this->lock
->unlock(this->lock
);
513 * Implementation of crypto_factory_t.add_dh.
515 static void add_dh(private_crypto_factory_t
*this, diffie_hellman_group_t group
,
516 dh_constructor_t create
)
518 entry_t
*entry
= malloc_thing(entry_t
);
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
);
528 * Implementation of crypto_factory_t.remove_dh.
530 static void remove_dh(private_crypto_factory_t
*this, dh_constructor_t create
)
533 enumerator_t
*enumerator
;
535 this->lock
->write_lock(this->lock
);
536 enumerator
= this->dhs
->create_enumerator(this->dhs
);
537 while (enumerator
->enumerate(enumerator
, &entry
))
539 if (entry
->create_dh
== create
)
541 this->dhs
->remove_at(this->dhs
, enumerator
);
545 enumerator
->destroy(enumerator
);
546 this->lock
->unlock(this->lock
);
550 * match algorithms of an entry?
552 static bool entry_match(entry_t
*a
, entry_t
*b
)
554 return a
->algo
== b
->algo
;
558 * check for uniqueness of an entry
560 static bool unique_check(linked_list_t
*list
, entry_t
**in
, entry_t
**out
)
562 if (list
->find_first(list
, (void*)entry_match
, NULL
, *in
) == SUCCESS
)
567 list
->insert_last(list
, *in
);
572 * create an enumerator over entry->algo in list with locking and unique check
574 static enumerator_t
*create_enumerator(private_crypto_factory_t
*this,
575 linked_list_t
*list
, void *filter
)
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
);
586 * Filter function to enumerate algorithm, not entry
588 static bool crypter_filter(void *n
, entry_t
**entry
, encryption_algorithm_t
*algo
)
590 *algo
= (*entry
)->algo
;
595 * Implementation of crypto_factory_t.create_crypter_enumerator
597 static enumerator_t
* create_crypter_enumerator(private_crypto_factory_t
*this)
599 return create_enumerator(this, this->crypters
, crypter_filter
);
603 * Filter function to enumerate algorithm, not entry
605 static bool signer_filter(void *n
, entry_t
**entry
, integrity_algorithm_t
*algo
)
607 *algo
= (*entry
)->algo
;
612 * Implementation of crypto_factory_t.create_signer_enumerator
614 static enumerator_t
* create_signer_enumerator(private_crypto_factory_t
*this)
616 return create_enumerator(this, this->signers
, signer_filter
);
620 * Filter function to enumerate algorithm, not entry
622 static bool hasher_filter(void *n
, entry_t
**entry
, hash_algorithm_t
*algo
)
624 *algo
= (*entry
)->algo
;
629 * Implementation of crypto_factory_t.create_hasher_enumerator
631 static enumerator_t
* create_hasher_enumerator(private_crypto_factory_t
*this)
633 return create_enumerator(this, this->hashers
, hasher_filter
);
637 * Filter function to enumerate algorithm, not entry
639 static bool prf_filter(void *n
, entry_t
**entry
, pseudo_random_function_t
*algo
)
641 *algo
= (*entry
)->algo
;
646 * Implementation of crypto_factory_t.create_prf_enumerator
648 static enumerator_t
* create_prf_enumerator(private_crypto_factory_t
*this)
650 return create_enumerator(this, this->prfs
, prf_filter
);
654 * Filter function to enumerate algorithm, not entry
656 static bool dh_filter(void *n
, entry_t
**entry
, diffie_hellman_group_t
*group
)
658 *group
= (*entry
)->algo
;
663 * Implementation of crypto_factory_t.create_dh_enumerator
665 static enumerator_t
* create_dh_enumerator(private_crypto_factory_t
*this)
667 return create_enumerator(this, this->dhs
, dh_filter
);
671 * Implementation of crypto_factory_t.add_test_vector
673 static void add_test_vector(private_crypto_factory_t
*this,
674 transform_type_t type
, void *vector
)
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
);
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
);
689 DBG1("%N test vectors not supported, ignored",
690 transform_type_names
, type
);
695 * Implementation of crypto_factory_t.destroy
697 static void destroy(private_crypto_factory_t
*this)
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
);
713 crypto_factory_t
*crypto_factory_create()
715 private_crypto_factory_t
*this = malloc_thing(private_crypto_factory_t
);
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
;
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
);
756 return &this->public;