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"
18 #include <utils/linked_list.h>
19 #include <utils/mutex.h>
21 typedef struct entry_t entry_t
;
27 crypter_constructor_t create_crypter
;
28 signer_constructor_t create_signer
;
29 hasher_constructor_t create_hasher
;
30 prf_constructor_t create_prf
;
31 rng_constructor_t create_rng
;
32 dh_constructor_t create_dh
;
36 typedef struct private_crypto_factory_t private_crypto_factory_t
;
39 * private data of crypto_factory
41 struct private_crypto_factory_t
{
46 crypto_factory_t
public;
49 * registered crypters, as entry_t
51 linked_list_t
*crypters
;
54 * registered signers, as entry_t
56 linked_list_t
*signers
;
59 * registered hashers, as entry_t
61 linked_list_t
*hashers
;
64 * registered prfs, as entry_t
69 * registered rngs, as entry_t
74 * registered diffie hellman, as entry_t
79 * rwlock to lock access to modules
85 * Implementation of crypto_factory_t.create_crypter.
87 static crypter_t
* create_crypter(private_crypto_factory_t
*this,
88 encryption_algorithm_t algo
, size_t key_size
)
90 enumerator_t
*enumerator
;
92 crypter_t
*crypter
= NULL
;
94 this->lock
->read_lock(this->lock
);
95 enumerator
= this->crypters
->create_enumerator(this->crypters
);
96 while (enumerator
->enumerate(enumerator
, &entry
))
98 if (entry
->algo
== algo
)
100 crypter
= entry
->create_crypter(algo
, key_size
);
107 enumerator
->destroy(enumerator
);
108 this->lock
->unlock(this->lock
);
113 * Implementation of crypto_factory_t.create_signer.
115 static signer_t
* create_signer(private_crypto_factory_t
*this,
116 integrity_algorithm_t algo
)
118 enumerator_t
*enumerator
;
120 signer_t
*signer
= NULL
;
122 this->lock
->read_lock(this->lock
);
123 enumerator
= this->signers
->create_enumerator(this->signers
);
124 while (enumerator
->enumerate(enumerator
, &entry
))
126 if (entry
->algo
== algo
)
128 signer
= entry
->create_signer(algo
);
135 enumerator
->destroy(enumerator
);
136 this->lock
->unlock(this->lock
);
142 * Implementation of crypto_factory_t.create_hasher.
144 static hasher_t
* create_hasher(private_crypto_factory_t
*this,
145 hash_algorithm_t algo
)
147 enumerator_t
*enumerator
;
149 hasher_t
*hasher
= NULL
;
151 this->lock
->read_lock(this->lock
);
152 enumerator
= this->hashers
->create_enumerator(this->hashers
);
153 while (enumerator
->enumerate(enumerator
, &entry
))
155 if (algo
== HASH_PREFERRED
|| entry
->algo
== algo
)
157 hasher
= entry
->create_hasher(entry
->algo
);
164 enumerator
->destroy(enumerator
);
165 this->lock
->unlock(this->lock
);
170 * Implementation of crypto_factory_t.create_prf.
172 static prf_t
* create_prf(private_crypto_factory_t
*this,
173 pseudo_random_function_t algo
)
175 enumerator_t
*enumerator
;
179 this->lock
->read_lock(this->lock
);
180 enumerator
= this->prfs
->create_enumerator(this->prfs
);
181 while (enumerator
->enumerate(enumerator
, &entry
))
183 if (entry
->algo
== algo
)
185 prf
= entry
->create_prf(algo
);
192 enumerator
->destroy(enumerator
);
193 this->lock
->unlock(this->lock
);
198 * Implementation of crypto_factory_t.create_rng.
200 static rng_t
* create_rng(private_crypto_factory_t
*this, rng_quality_t quality
)
202 enumerator_t
*enumerator
;
205 rng_constructor_t constr
= NULL
;
207 this->lock
->read_lock(this->lock
);
208 enumerator
= this->rngs
->create_enumerator(this->rngs
);
209 while (enumerator
->enumerate(enumerator
, &entry
))
210 { /* find the best matching quality, but at least as good as requested */
211 if (entry
->algo
>= quality
&& diff
> entry
->algo
- quality
)
213 diff
= entry
->algo
- quality
;
214 constr
= entry
->create_rng
;
216 { /* perfect match, won't get better */
221 enumerator
->destroy(enumerator
);
222 this->lock
->unlock(this->lock
);
225 return constr(quality
);
231 * Implementation of crypto_factory_t.create_dh.
233 static diffie_hellman_t
* create_dh(private_crypto_factory_t
*this,
234 diffie_hellman_group_t group
)
236 enumerator_t
*enumerator
;
238 diffie_hellman_t
*diffie_hellman
= NULL
;
240 this->lock
->read_lock(this->lock
);
241 enumerator
= this->dhs
->create_enumerator(this->dhs
);
242 while (enumerator
->enumerate(enumerator
, &entry
))
244 if (entry
->algo
== group
)
246 diffie_hellman
= entry
->create_dh(group
);
253 enumerator
->destroy(enumerator
);
254 this->lock
->unlock(this->lock
);
255 return diffie_hellman
;
259 * Implementation of crypto_factory_t.add_crypter.
261 static void add_crypter(private_crypto_factory_t
*this,
262 encryption_algorithm_t algo
,
263 crypter_constructor_t create
)
265 entry_t
*entry
= malloc_thing(entry_t
);
268 entry
->create_crypter
= create
;
269 this->lock
->write_lock(this->lock
);
270 this->crypters
->insert_last(this->crypters
, entry
);
271 this->lock
->unlock(this->lock
);
275 * Implementation of crypto_factory_t.remove_crypter.
277 static void remove_crypter(private_crypto_factory_t
*this,
278 crypter_constructor_t create
)
281 enumerator_t
*enumerator
;
283 this->lock
->write_lock(this->lock
);
284 enumerator
= this->crypters
->create_enumerator(this->crypters
);
285 while (enumerator
->enumerate(enumerator
, &entry
))
287 if (entry
->create_crypter
== create
)
289 this->crypters
->remove_at(this->crypters
, enumerator
);
293 enumerator
->destroy(enumerator
);
294 this->lock
->unlock(this->lock
);
298 * Implementation of crypto_factory_t.add_signer.
300 static void add_signer(private_crypto_factory_t
*this,
301 integrity_algorithm_t algo
, signer_constructor_t create
)
303 entry_t
*entry
= malloc_thing(entry_t
);
306 entry
->create_signer
= create
;
307 this->lock
->write_lock(this->lock
);
308 this->signers
->insert_last(this->signers
, entry
);
309 this->lock
->unlock(this->lock
);
313 * Implementation of crypto_factory_t.remove_signer.
315 static void remove_signer(private_crypto_factory_t
*this,
316 signer_constructor_t create
)
319 enumerator_t
*enumerator
;
321 this->lock
->write_lock(this->lock
);
322 enumerator
= this->signers
->create_enumerator(this->signers
);
323 while (enumerator
->enumerate(enumerator
, &entry
))
325 if (entry
->create_signer
== create
)
327 this->signers
->remove_at(this->signers
, enumerator
);
331 enumerator
->destroy(enumerator
);
332 this->lock
->unlock(this->lock
);
336 * Implementation of crypto_factory_t.add_hasher.
338 static void add_hasher(private_crypto_factory_t
*this, hash_algorithm_t algo
,
339 hasher_constructor_t create
)
341 entry_t
*entry
= malloc_thing(entry_t
);
344 entry
->create_hasher
= create
;
345 this->lock
->write_lock(this->lock
);
346 this->hashers
->insert_last(this->hashers
, entry
);
347 this->lock
->unlock(this->lock
);
351 * Implementation of crypto_factory_t.remove_hasher.
353 static void remove_hasher(private_crypto_factory_t
*this,
354 hasher_constructor_t create
)
357 enumerator_t
*enumerator
;
359 this->lock
->write_lock(this->lock
);
360 enumerator
= this->hashers
->create_enumerator(this->hashers
);
361 while (enumerator
->enumerate(enumerator
, &entry
))
363 if (entry
->create_hasher
== create
)
365 this->hashers
->remove_at(this->hashers
, enumerator
);
369 enumerator
->destroy(enumerator
);
370 this->lock
->unlock(this->lock
);
374 * Implementation of crypto_factory_t.add_prf.
376 static void add_prf(private_crypto_factory_t
*this,
377 pseudo_random_function_t algo
, prf_constructor_t create
)
379 entry_t
*entry
= malloc_thing(entry_t
);
382 entry
->create_prf
= create
;
383 this->lock
->write_lock(this->lock
);
384 this->prfs
->insert_last(this->prfs
, entry
);
385 this->lock
->unlock(this->lock
);
389 * Implementation of crypto_factory_t.remove_prf.
391 static void remove_prf(private_crypto_factory_t
*this, prf_constructor_t create
)
394 enumerator_t
*enumerator
;
396 this->lock
->write_lock(this->lock
);
397 enumerator
= this->prfs
->create_enumerator(this->prfs
);
398 while (enumerator
->enumerate(enumerator
, &entry
))
400 if (entry
->create_prf
== create
)
402 this->prfs
->remove_at(this->prfs
, enumerator
);
406 enumerator
->destroy(enumerator
);
407 this->lock
->unlock(this->lock
);
411 * Implementation of crypto_factory_t.add_rng.
413 static void add_rng(private_crypto_factory_t
*this, rng_quality_t quality
,
414 rng_constructor_t create
)
416 entry_t
*entry
= malloc_thing(entry_t
);
418 entry
->algo
= quality
;
419 entry
->create_rng
= create
;
420 this->lock
->write_lock(this->lock
);
421 this->rngs
->insert_last(this->rngs
, entry
);
422 this->lock
->unlock(this->lock
);
426 * Implementation of crypto_factory_t.remove_rng.
428 static void remove_rng(private_crypto_factory_t
*this, rng_constructor_t create
)
431 enumerator_t
*enumerator
;
433 this->lock
->write_lock(this->lock
);
434 enumerator
= this->rngs
->create_enumerator(this->rngs
);
435 while (enumerator
->enumerate(enumerator
, &entry
))
437 if (entry
->create_rng
== create
)
439 this->rngs
->remove_at(this->rngs
, enumerator
);
443 enumerator
->destroy(enumerator
);
444 this->lock
->unlock(this->lock
);
448 * Implementation of crypto_factory_t.add_dh.
450 static void add_dh(private_crypto_factory_t
*this, diffie_hellman_group_t group
,
451 dh_constructor_t create
)
453 entry_t
*entry
= malloc_thing(entry_t
);
456 entry
->create_dh
= create
;
457 this->lock
->write_lock(this->lock
);
458 this->dhs
->insert_last(this->dhs
, entry
);
459 this->lock
->unlock(this->lock
);
463 * Implementation of crypto_factory_t.remove_dh.
465 static void remove_dh(private_crypto_factory_t
*this, dh_constructor_t create
)
468 enumerator_t
*enumerator
;
470 this->lock
->write_lock(this->lock
);
471 enumerator
= this->dhs
->create_enumerator(this->dhs
);
472 while (enumerator
->enumerate(enumerator
, &entry
))
474 if (entry
->create_dh
== create
)
476 this->dhs
->remove_at(this->dhs
, enumerator
);
480 enumerator
->destroy(enumerator
);
481 this->lock
->unlock(this->lock
);
485 * match algorithms of an entry?
487 static bool entry_match(entry_t
*a
, entry_t
*b
)
489 return a
->algo
== b
->algo
;
493 * check for uniqueness of an entry
495 static bool unique_check(linked_list_t
*list
, entry_t
**in
, entry_t
**out
)
497 if (list
->find_first(list
, (void*)entry_match
, NULL
, *in
) == SUCCESS
)
502 list
->insert_last(list
, *in
);
507 * create an enumerator over entry->algo in list with locking and unique check
509 static enumerator_t
*create_enumerator(private_crypto_factory_t
*this,
510 linked_list_t
*list
, void *filter
)
512 this->lock
->read_lock(this->lock
);
513 return enumerator_create_filter(
514 enumerator_create_filter(
515 list
->create_enumerator(list
), (void*)unique_check
,
516 linked_list_create(), (void*)list
->destroy
),
517 filter
, this->lock
, (void*)this->lock
->unlock
);
521 * Filter function to enumerate algorithm, not entry
523 static bool crypter_filter(void *n
, entry_t
**entry
, encryption_algorithm_t
*algo
)
525 *algo
= (*entry
)->algo
;
530 * Implementation of crypto_factory_t.create_crypter_enumerator
532 static enumerator_t
* create_crypter_enumerator(private_crypto_factory_t
*this)
534 return create_enumerator(this, this->crypters
, crypter_filter
);
538 * Filter function to enumerate algorithm, not entry
540 static bool signer_filter(void *n
, entry_t
**entry
, integrity_algorithm_t
*algo
)
542 *algo
= (*entry
)->algo
;
547 * Implementation of crypto_factory_t.create_signer_enumerator
549 static enumerator_t
* create_signer_enumerator(private_crypto_factory_t
*this)
551 return create_enumerator(this, this->signers
, signer_filter
);
555 * Filter function to enumerate algorithm, not entry
557 static bool hasher_filter(void *n
, entry_t
**entry
, hash_algorithm_t
*algo
)
559 *algo
= (*entry
)->algo
;
564 * Implementation of crypto_factory_t.create_hasher_enumerator
566 static enumerator_t
* create_hasher_enumerator(private_crypto_factory_t
*this)
568 return create_enumerator(this, this->hashers
, hasher_filter
);
572 * Filter function to enumerate algorithm, not entry
574 static bool prf_filter(void *n
, entry_t
**entry
, pseudo_random_function_t
*algo
)
576 *algo
= (*entry
)->algo
;
581 * Implementation of crypto_factory_t.create_prf_enumerator
583 static enumerator_t
* create_prf_enumerator(private_crypto_factory_t
*this)
585 return create_enumerator(this, this->prfs
, prf_filter
);
589 * Filter function to enumerate algorithm, not entry
591 static bool dh_filter(void *n
, entry_t
**entry
, diffie_hellman_group_t
*group
)
593 *group
= (*entry
)->algo
;
598 * Implementation of crypto_factory_t.create_dh_enumerator
600 static enumerator_t
* create_dh_enumerator(private_crypto_factory_t
*this)
602 return create_enumerator(this, this->dhs
, dh_filter
);
606 * Implementation of crypto_factory_t.destroy
608 static void destroy(private_crypto_factory_t
*this)
610 this->crypters
->destroy_function(this->crypters
, free
);
611 this->signers
->destroy_function(this->signers
, free
);
612 this->hashers
->destroy_function(this->hashers
, free
);
613 this->prfs
->destroy_function(this->prfs
, free
);
614 this->rngs
->destroy_function(this->rngs
, free
);
615 this->dhs
->destroy_function(this->dhs
, free
);
616 this->lock
->destroy(this->lock
);
623 crypto_factory_t
*crypto_factory_create()
625 private_crypto_factory_t
*this = malloc_thing(private_crypto_factory_t
);
627 this->public.create_crypter
= (crypter_t
*(*)(crypto_factory_t
*, encryption_algorithm_t
, size_t))create_crypter
;
628 this->public.create_signer
= (signer_t
*(*)(crypto_factory_t
*, integrity_algorithm_t
))create_signer
;
629 this->public.create_hasher
= (hasher_t
*(*)(crypto_factory_t
*, hash_algorithm_t
))create_hasher
;
630 this->public.create_prf
= (prf_t
*(*)(crypto_factory_t
*, pseudo_random_function_t
))create_prf
;
631 this->public.create_rng
= (rng_t
*(*)(crypto_factory_t
*, rng_quality_t quality
))create_rng
;
632 this->public.create_dh
= (diffie_hellman_t
*(*)(crypto_factory_t
*, diffie_hellman_group_t group
))create_dh
;
633 this->public.add_crypter
= (void(*)(crypto_factory_t
*, encryption_algorithm_t algo
, crypter_constructor_t create
))add_crypter
;
634 this->public.remove_crypter
= (void(*)(crypto_factory_t
*, crypter_constructor_t create
))remove_crypter
;
635 this->public.add_signer
= (void(*)(crypto_factory_t
*, integrity_algorithm_t algo
, signer_constructor_t create
))add_signer
;
636 this->public.remove_signer
= (void(*)(crypto_factory_t
*, signer_constructor_t create
))remove_signer
;
637 this->public.add_hasher
= (void(*)(crypto_factory_t
*, hash_algorithm_t algo
, hasher_constructor_t create
))add_hasher
;
638 this->public.remove_hasher
= (void(*)(crypto_factory_t
*, hasher_constructor_t create
))remove_hasher
;
639 this->public.add_prf
= (void(*)(crypto_factory_t
*, pseudo_random_function_t algo
, prf_constructor_t create
))add_prf
;
640 this->public.remove_prf
= (void(*)(crypto_factory_t
*, prf_constructor_t create
))remove_prf
;
641 this->public.add_rng
= (void(*)(crypto_factory_t
*, rng_quality_t quality
, rng_constructor_t create
))add_rng
;
642 this->public.remove_rng
= (void(*)(crypto_factory_t
*, rng_constructor_t create
))remove_rng
;
643 this->public.add_dh
= (void(*)(crypto_factory_t
*, diffie_hellman_group_t algo
, dh_constructor_t create
))add_dh
;
644 this->public.remove_dh
= (void(*)(crypto_factory_t
*, dh_constructor_t create
))remove_dh
;
645 this->public.create_crypter_enumerator
= (enumerator_t
*(*)(crypto_factory_t
*))create_crypter_enumerator
;
646 this->public.create_signer_enumerator
= (enumerator_t
*(*)(crypto_factory_t
*))create_signer_enumerator
;
647 this->public.create_hasher_enumerator
= (enumerator_t
*(*)(crypto_factory_t
*))create_hasher_enumerator
;
648 this->public.create_prf_enumerator
= (enumerator_t
*(*)(crypto_factory_t
*))create_prf_enumerator
;
649 this->public.create_dh_enumerator
= (enumerator_t
*(*)(crypto_factory_t
*))create_dh_enumerator
;
650 this->public.destroy
= (void(*)(crypto_factory_t
*))destroy
;
652 this->crypters
= linked_list_create();
653 this->signers
= linked_list_create();
654 this->hashers
= linked_list_create();
655 this->prfs
= linked_list_create();
656 this->rngs
= linked_list_create();
657 this->dhs
= linked_list_create();
658 this->lock
= rwlock_create(RWLOCK_DEFAULT
);
660 return &this->public;