1cfc02786c382a6e84ccb84be919e3bbf7adc54a
[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 <utils/linked_list.h>
19 #include <utils/mutex.h>
20
21 typedef struct entry_t entry_t;
22 struct entry_t {
23 /** algorithm */
24 u_int algo;
25 /* constructor */
26 union {
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;
33 };
34 };
35
36 typedef struct private_crypto_factory_t private_crypto_factory_t;
37
38 /**
39 * private data of crypto_factory
40 */
41 struct private_crypto_factory_t {
42
43 /**
44 * public functions
45 */
46 crypto_factory_t public;
47
48 /**
49 * registered crypters, as entry_t
50 */
51 linked_list_t *crypters;
52
53 /**
54 * registered signers, as entry_t
55 */
56 linked_list_t *signers;
57
58 /**
59 * registered hashers, as entry_t
60 */
61 linked_list_t *hashers;
62
63 /**
64 * registered prfs, as entry_t
65 */
66 linked_list_t *prfs;
67
68 /**
69 * registered rngs, as entry_t
70 */
71 linked_list_t *rngs;
72
73 /**
74 * registered diffie hellman, as entry_t
75 */
76 linked_list_t *dhs;
77
78 /**
79 * rwlock to lock access to modules
80 */
81 rwlock_t *lock;
82 };
83
84 /**
85 * Implementation of crypto_factory_t.create_crypter.
86 */
87 static crypter_t* create_crypter(private_crypto_factory_t *this,
88 encryption_algorithm_t algo, size_t key_size)
89 {
90 enumerator_t *enumerator;
91 entry_t *entry;
92 crypter_t *crypter = NULL;
93
94 this->lock->read_lock(this->lock);
95 enumerator = this->crypters->create_enumerator(this->crypters);
96 while (enumerator->enumerate(enumerator, &entry))
97 {
98 if (entry->algo == algo)
99 {
100 crypter = entry->create_crypter(algo, key_size);
101 if (crypter)
102 {
103 break;
104 }
105 }
106 }
107 enumerator->destroy(enumerator);
108 this->lock->unlock(this->lock);
109 return crypter;
110 }
111
112 /**
113 * Implementation of crypto_factory_t.create_signer.
114 */
115 static signer_t* create_signer(private_crypto_factory_t *this,
116 integrity_algorithm_t algo)
117 {
118 enumerator_t *enumerator;
119 entry_t *entry;
120 signer_t *signer = NULL;
121
122 this->lock->read_lock(this->lock);
123 enumerator = this->signers->create_enumerator(this->signers);
124 while (enumerator->enumerate(enumerator, &entry))
125 {
126 if (entry->algo == algo)
127 {
128 signer = entry->create_signer(algo);
129 if (signer)
130 {
131 break;
132 }
133 }
134 }
135 enumerator->destroy(enumerator);
136 this->lock->unlock(this->lock);
137
138 return signer;
139 }
140
141 /**
142 * Implementation of crypto_factory_t.create_hasher.
143 */
144 static hasher_t* create_hasher(private_crypto_factory_t *this,
145 hash_algorithm_t algo)
146 {
147 enumerator_t *enumerator;
148 entry_t *entry;
149 hasher_t *hasher = NULL;
150
151 this->lock->read_lock(this->lock);
152 enumerator = this->hashers->create_enumerator(this->hashers);
153 while (enumerator->enumerate(enumerator, &entry))
154 {
155 if (algo == HASH_PREFERRED || entry->algo == algo)
156 {
157 hasher = entry->create_hasher(entry->algo);
158 if (hasher)
159 {
160 break;
161 }
162 }
163 }
164 enumerator->destroy(enumerator);
165 this->lock->unlock(this->lock);
166 return hasher;
167 }
168
169 /**
170 * Implementation of crypto_factory_t.create_prf.
171 */
172 static prf_t* create_prf(private_crypto_factory_t *this,
173 pseudo_random_function_t algo)
174 {
175 enumerator_t *enumerator;
176 entry_t *entry;
177 prf_t *prf = NULL;
178
179 this->lock->read_lock(this->lock);
180 enumerator = this->prfs->create_enumerator(this->prfs);
181 while (enumerator->enumerate(enumerator, &entry))
182 {
183 if (entry->algo == algo)
184 {
185 prf = entry->create_prf(algo);
186 if (prf)
187 {
188 break;
189 }
190 }
191 }
192 enumerator->destroy(enumerator);
193 this->lock->unlock(this->lock);
194 return prf;
195 }
196
197 /**
198 * Implementation of crypto_factory_t.create_rng.
199 */
200 static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality)
201 {
202 enumerator_t *enumerator;
203 entry_t *entry;
204 u_int diff = ~0;
205 rng_constructor_t constr = NULL;
206
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)
212 {
213 diff = entry->algo - quality;
214 constr = entry->create_rng;
215 if (diff == 0)
216 { /* perfect match, won't get better */
217 break;
218 }
219 }
220 }
221 enumerator->destroy(enumerator);
222 this->lock->unlock(this->lock);
223 if (constr)
224 {
225 return constr(quality);
226 }
227 return NULL;
228 }
229
230 /**
231 * Implementation of crypto_factory_t.create_dh.
232 */
233 static diffie_hellman_t* create_dh(private_crypto_factory_t *this,
234 diffie_hellman_group_t group)
235 {
236 enumerator_t *enumerator;
237 entry_t *entry;
238 diffie_hellman_t *diffie_hellman = NULL;
239
240 this->lock->read_lock(this->lock);
241 enumerator = this->dhs->create_enumerator(this->dhs);
242 while (enumerator->enumerate(enumerator, &entry))
243 {
244 if (entry->algo == group)
245 {
246 diffie_hellman = entry->create_dh(group);
247 if (diffie_hellman)
248 {
249 break;
250 }
251 }
252 }
253 enumerator->destroy(enumerator);
254 this->lock->unlock(this->lock);
255 return diffie_hellman;
256 }
257
258 /**
259 * Implementation of crypto_factory_t.add_crypter.
260 */
261 static void add_crypter(private_crypto_factory_t *this,
262 encryption_algorithm_t algo,
263 crypter_constructor_t create)
264 {
265 entry_t *entry = malloc_thing(entry_t);
266
267 entry->algo = algo;
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);
272 }
273
274 /**
275 * Implementation of crypto_factory_t.remove_crypter.
276 */
277 static void remove_crypter(private_crypto_factory_t *this,
278 crypter_constructor_t create)
279 {
280 entry_t *entry;
281 enumerator_t *enumerator;
282
283 this->lock->write_lock(this->lock);
284 enumerator = this->crypters->create_enumerator(this->crypters);
285 while (enumerator->enumerate(enumerator, &entry))
286 {
287 if (entry->create_crypter == create)
288 {
289 this->crypters->remove_at(this->crypters, enumerator);
290 free(entry);
291 }
292 }
293 enumerator->destroy(enumerator);
294 this->lock->unlock(this->lock);
295 }
296
297 /**
298 * Implementation of crypto_factory_t.add_signer.
299 */
300 static void add_signer(private_crypto_factory_t *this,
301 integrity_algorithm_t algo, signer_constructor_t create)
302 {
303 entry_t *entry = malloc_thing(entry_t);
304
305 entry->algo = algo;
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);
310 }
311
312 /**
313 * Implementation of crypto_factory_t.remove_signer.
314 */
315 static void remove_signer(private_crypto_factory_t *this,
316 signer_constructor_t create)
317 {
318 entry_t *entry;
319 enumerator_t *enumerator;
320
321 this->lock->write_lock(this->lock);
322 enumerator = this->signers->create_enumerator(this->signers);
323 while (enumerator->enumerate(enumerator, &entry))
324 {
325 if (entry->create_signer == create)
326 {
327 this->signers->remove_at(this->signers, enumerator);
328 free(entry);
329 }
330 }
331 enumerator->destroy(enumerator);
332 this->lock->unlock(this->lock);
333 }
334
335 /**
336 * Implementation of crypto_factory_t.add_hasher.
337 */
338 static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo,
339 hasher_constructor_t create)
340 {
341 entry_t *entry = malloc_thing(entry_t);
342
343 entry->algo = algo;
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);
348 }
349
350 /**
351 * Implementation of crypto_factory_t.remove_hasher.
352 */
353 static void remove_hasher(private_crypto_factory_t *this,
354 hasher_constructor_t create)
355 {
356 entry_t *entry;
357 enumerator_t *enumerator;
358
359 this->lock->write_lock(this->lock);
360 enumerator = this->hashers->create_enumerator(this->hashers);
361 while (enumerator->enumerate(enumerator, &entry))
362 {
363 if (entry->create_hasher == create)
364 {
365 this->hashers->remove_at(this->hashers, enumerator);
366 free(entry);
367 }
368 }
369 enumerator->destroy(enumerator);
370 this->lock->unlock(this->lock);
371 }
372
373 /**
374 * Implementation of crypto_factory_t.add_prf.
375 */
376 static void add_prf(private_crypto_factory_t *this,
377 pseudo_random_function_t algo, prf_constructor_t create)
378 {
379 entry_t *entry = malloc_thing(entry_t);
380
381 entry->algo = algo;
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);
386 }
387
388 /**
389 * Implementation of crypto_factory_t.remove_prf.
390 */
391 static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create)
392 {
393 entry_t *entry;
394 enumerator_t *enumerator;
395
396 this->lock->write_lock(this->lock);
397 enumerator = this->prfs->create_enumerator(this->prfs);
398 while (enumerator->enumerate(enumerator, &entry))
399 {
400 if (entry->create_prf == create)
401 {
402 this->prfs->remove_at(this->prfs, enumerator);
403 free(entry);
404 }
405 }
406 enumerator->destroy(enumerator);
407 this->lock->unlock(this->lock);
408 }
409
410 /**
411 * Implementation of crypto_factory_t.add_rng.
412 */
413 static void add_rng(private_crypto_factory_t *this, rng_quality_t quality,
414 rng_constructor_t create)
415 {
416 entry_t *entry = malloc_thing(entry_t);
417
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);
423 }
424
425 /**
426 * Implementation of crypto_factory_t.remove_rng.
427 */
428 static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create)
429 {
430 entry_t *entry;
431 enumerator_t *enumerator;
432
433 this->lock->write_lock(this->lock);
434 enumerator = this->rngs->create_enumerator(this->rngs);
435 while (enumerator->enumerate(enumerator, &entry))
436 {
437 if (entry->create_rng == create)
438 {
439 this->rngs->remove_at(this->rngs, enumerator);
440 free(entry);
441 }
442 }
443 enumerator->destroy(enumerator);
444 this->lock->unlock(this->lock);
445 }
446
447 /**
448 * Implementation of crypto_factory_t.add_dh.
449 */
450 static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group,
451 dh_constructor_t create)
452 {
453 entry_t *entry = malloc_thing(entry_t);
454
455 entry->algo = group;
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);
460 }
461
462 /**
463 * Implementation of crypto_factory_t.remove_dh.
464 */
465 static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create)
466 {
467 entry_t *entry;
468 enumerator_t *enumerator;
469
470 this->lock->write_lock(this->lock);
471 enumerator = this->dhs->create_enumerator(this->dhs);
472 while (enumerator->enumerate(enumerator, &entry))
473 {
474 if (entry->create_dh == create)
475 {
476 this->dhs->remove_at(this->dhs, enumerator);
477 free(entry);
478 }
479 }
480 enumerator->destroy(enumerator);
481 this->lock->unlock(this->lock);
482 }
483
484 /**
485 * match algorithms of an entry?
486 */
487 static bool entry_match(entry_t *a, entry_t *b)
488 {
489 return a->algo == b->algo;
490 }
491
492 /**
493 * check for uniqueness of an entry
494 */
495 static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out)
496 {
497 if (list->find_first(list, (void*)entry_match, NULL, *in) == SUCCESS)
498 {
499 return FALSE;
500 }
501 *out = *in;
502 list->insert_last(list, *in);
503 return TRUE;
504 }
505
506 /**
507 * create an enumerator over entry->algo in list with locking and unique check
508 */
509 static enumerator_t *create_enumerator(private_crypto_factory_t *this,
510 linked_list_t *list, void *filter)
511 {
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);
518 }
519
520 /**
521 * Filter function to enumerate algorithm, not entry
522 */
523 static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo)
524 {
525 *algo = (*entry)->algo;
526 return TRUE;
527 }
528
529 /**
530 * Implementation of crypto_factory_t.create_crypter_enumerator
531 */
532 static enumerator_t* create_crypter_enumerator(private_crypto_factory_t *this)
533 {
534 return create_enumerator(this, this->crypters, crypter_filter);
535 }
536
537 /**
538 * Filter function to enumerate algorithm, not entry
539 */
540 static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo)
541 {
542 *algo = (*entry)->algo;
543 return TRUE;
544 }
545
546 /**
547 * Implementation of crypto_factory_t.create_signer_enumerator
548 */
549 static enumerator_t* create_signer_enumerator(private_crypto_factory_t *this)
550 {
551 return create_enumerator(this, this->signers, signer_filter);
552 }
553
554 /**
555 * Filter function to enumerate algorithm, not entry
556 */
557 static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo)
558 {
559 *algo = (*entry)->algo;
560 return TRUE;
561 }
562
563 /**
564 * Implementation of crypto_factory_t.create_hasher_enumerator
565 */
566 static enumerator_t* create_hasher_enumerator(private_crypto_factory_t *this)
567 {
568 return create_enumerator(this, this->hashers, hasher_filter);
569 }
570
571 /**
572 * Filter function to enumerate algorithm, not entry
573 */
574 static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo)
575 {
576 *algo = (*entry)->algo;
577 return TRUE;
578 }
579
580 /**
581 * Implementation of crypto_factory_t.create_prf_enumerator
582 */
583 static enumerator_t* create_prf_enumerator(private_crypto_factory_t *this)
584 {
585 return create_enumerator(this, this->prfs, prf_filter);
586 }
587
588 /**
589 * Filter function to enumerate algorithm, not entry
590 */
591 static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group)
592 {
593 *group = (*entry)->algo;
594 return TRUE;
595 }
596
597 /**
598 * Implementation of crypto_factory_t.create_dh_enumerator
599 */
600 static enumerator_t* create_dh_enumerator(private_crypto_factory_t *this)
601 {
602 return create_enumerator(this, this->dhs, dh_filter);
603 }
604
605 /**
606 * Implementation of crypto_factory_t.destroy
607 */
608 static void destroy(private_crypto_factory_t *this)
609 {
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);
617 free(this);
618 }
619
620 /*
621 * see header file
622 */
623 crypto_factory_t *crypto_factory_create()
624 {
625 private_crypto_factory_t *this = malloc_thing(private_crypto_factory_t);
626
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;
651
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);
659
660 return &this->public;
661 }
662