added API for random number generators, served through credential 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 * $Id$
16 */
17
18 #include "crypto_factory.h"
19
20 #include <utils/linked_list.h>
21 #include <utils/mutex.h>
22
23 typedef struct crypter_entry_t crypter_entry_t;
24 struct crypter_entry_t {
25 /** encryption algorithm */
26 encryption_algorithm_t algo;
27 /** associated constructor */
28 crypter_constructor_t create;
29 };
30
31 typedef struct signer_entry_t signer_entry_t;
32 struct signer_entry_t {
33 /** integrity algorithm */
34 integrity_algorithm_t algo;
35 /** associated constructor */
36 signer_constructor_t create;
37 };
38
39 typedef struct hasher_entry_t hasher_entry_t;
40 struct hasher_entry_t {
41 /** hash algorithm */
42 hash_algorithm_t algo;
43 /** associated constructor */
44 hasher_constructor_t create;
45 };
46
47 typedef struct prf_entry_t prf_entry_t;
48 struct prf_entry_t {
49 /** hash algorithm */
50 pseudo_random_function_t algo;
51 /** associated constructor */
52 prf_constructor_t create;
53 };
54
55 typedef struct rng_entry_t rng_entry_t;
56 struct rng_entry_t {
57 /** quality of randomness */
58 rng_quality_t quality;
59 /** associated constructor */
60 rng_constructor_t create;
61 };
62
63 typedef struct dh_entry_t dh_entry_t;
64 struct dh_entry_t {
65 /** hash algorithm */
66 diffie_hellman_group_t group;
67 /** associated constructor */
68 dh_constructor_t create;
69 };
70
71 typedef struct private_crypto_factory_t private_crypto_factory_t;
72
73 /**
74 * private data of crypto_factory
75 */
76 struct private_crypto_factory_t {
77
78 /**
79 * public functions
80 */
81 crypto_factory_t public;
82
83 /**
84 * registered crypters, as crypter_entry_t
85 */
86 linked_list_t *crypters;
87
88 /**
89 * registered signers, as signer_entry_t
90 */
91 linked_list_t *signers;
92
93 /**
94 * registered hashers, as hasher_entry_t
95 */
96 linked_list_t *hashers;
97
98 /**
99 * registered prfs, as prf_entry_t
100 */
101 linked_list_t *prfs;
102
103 /**
104 * registered rngs, as rng_entry_t
105 */
106 linked_list_t *rngs;
107
108 /**
109 * registered diffie hellman, as dh_entry_t
110 */
111 linked_list_t *dhs;
112
113 /**
114 * mutex to lock access to modules
115 */
116 mutex_t *mutex;
117 };
118
119 /**
120 * Implementation of crypto_factory_t.create_crypter.
121 */
122 static crypter_t* create_crypter(private_crypto_factory_t *this,
123 encryption_algorithm_t algo, size_t key_size)
124 {
125 enumerator_t *enumerator;
126 crypter_entry_t *entry;
127 crypter_t *crypter = NULL;
128
129 this->mutex->lock(this->mutex);
130 enumerator = this->crypters->create_enumerator(this->crypters);
131 while (enumerator->enumerate(enumerator, &entry))
132 {
133 if (entry->algo == algo)
134 {
135 crypter = entry->create(algo, key_size);
136 if (crypter)
137 {
138 break;
139 }
140 }
141 }
142 enumerator->destroy(enumerator);
143 this->mutex->unlock(this->mutex);
144 return crypter;
145 }
146
147 /**
148 * Implementation of crypto_factory_t.create_signer.
149 */
150 static signer_t* create_signer(private_crypto_factory_t *this,
151 integrity_algorithm_t algo)
152 {
153 enumerator_t *enumerator;
154 signer_entry_t *entry;
155 signer_t *signer = NULL;
156
157 this->mutex->lock(this->mutex);
158 enumerator = this->signers->create_enumerator(this->signers);
159 while (enumerator->enumerate(enumerator, &entry))
160 {
161 if (entry->algo == algo)
162 {
163 signer = entry->create(algo);
164 if (signer)
165 {
166 break;
167 }
168 }
169 }
170 enumerator->destroy(enumerator);
171 this->mutex->unlock(this->mutex);
172
173 return signer;
174 }
175
176 /**
177 * Implementation of crypto_factory_t.create_hasher.
178 */
179 static hasher_t* create_hasher(private_crypto_factory_t *this,
180 hash_algorithm_t algo)
181 {
182 enumerator_t *enumerator;
183 hasher_entry_t *entry;
184 hasher_t *hasher = NULL;
185
186 this->mutex->lock(this->mutex);
187 enumerator = this->hashers->create_enumerator(this->hashers);
188 while (enumerator->enumerate(enumerator, &entry))
189 {
190 if (algo == HASH_PREFERRED || entry->algo == algo)
191 {
192 hasher = entry->create(entry->algo);
193 if (hasher)
194 {
195 break;
196 }
197 }
198 }
199 enumerator->destroy(enumerator);
200 this->mutex->unlock(this->mutex);
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 prf_entry_t *entry;
212 prf_t *prf = NULL;
213
214 this->mutex->lock(this->mutex);
215 enumerator = this->prfs->create_enumerator(this->prfs);
216 while (enumerator->enumerate(enumerator, &entry))
217 {
218 if (entry->algo == algo)
219 {
220 prf = entry->create(algo);
221 if (prf)
222 {
223 break;
224 }
225 }
226 }
227 enumerator->destroy(enumerator);
228 this->mutex->unlock(this->mutex);
229 return prf;
230 }
231
232 /**
233 * Implementation of crypto_factory_t.create_rng.
234 */
235 static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality)
236 {
237 enumerator_t *enumerator;
238 rng_entry_t *entry;
239 u_int diff = ~0;
240 rng_constructor_t constr = NULL;
241
242 this->mutex->lock(this->mutex);
243 enumerator = this->rngs->create_enumerator(this->rngs);
244 while (enumerator->enumerate(enumerator, &entry))
245 { /* find the best matching quality, but at least as good as requested */
246 if (entry->quality >= quality && diff > entry->quality - quality)
247 {
248 diff = entry->quality - quality;
249 constr = entry->create;
250 if (diff == 0)
251 { /* perfect match, won't get better */
252 break;
253 }
254 }
255 }
256 enumerator->destroy(enumerator);
257 this->mutex->unlock(this->mutex);
258 if (constr)
259 {
260 return constr(quality);
261 }
262 return NULL;
263 }
264
265 /**
266 * Implementation of crypto_factory_t.create_dh.
267 */
268 static diffie_hellman_t* create_dh(private_crypto_factory_t *this,
269 diffie_hellman_group_t group)
270 {
271 enumerator_t *enumerator;
272 dh_entry_t *entry;
273 diffie_hellman_t *diffie_hellman = NULL;
274
275 this->mutex->lock(this->mutex);
276 enumerator = this->dhs->create_enumerator(this->dhs);
277 while (enumerator->enumerate(enumerator, &entry))
278 {
279 if (entry->group == group)
280 {
281 diffie_hellman = entry->create(group);
282 if (diffie_hellman)
283 {
284 break;
285 }
286 }
287 }
288 enumerator->destroy(enumerator);
289 this->mutex->unlock(this->mutex);
290 return diffie_hellman;
291 }
292
293 /**
294 * Implementation of crypto_factory_t.add_crypter.
295 */
296 static void add_crypter(private_crypto_factory_t *this,
297 encryption_algorithm_t algo,
298 crypter_constructor_t create)
299 {
300 crypter_entry_t *entry = malloc_thing(crypter_entry_t);
301
302 entry->algo = algo;
303 entry->create = create;
304 this->mutex->lock(this->mutex);
305 this->crypters->insert_last(this->crypters, entry);
306 this->mutex->unlock(this->mutex);
307 }
308
309 /**
310 * Implementation of crypto_factory_t.remove_crypter.
311 */
312 static void remove_crypter(private_crypto_factory_t *this,
313 crypter_constructor_t create)
314 {
315 crypter_entry_t *entry;
316 enumerator_t *enumerator;
317
318 this->mutex->lock(this->mutex);
319 enumerator = this->crypters->create_enumerator(this->crypters);
320 while (enumerator->enumerate(enumerator, &entry))
321 {
322 if (entry->create == create)
323 {
324 this->crypters->remove_at(this->crypters, enumerator);
325 free(entry);
326 }
327 }
328 enumerator->destroy(enumerator);
329 this->mutex->unlock(this->mutex);
330 }
331
332 /**
333 * Implementation of crypto_factory_t.add_signer.
334 */
335 static void add_signer(private_crypto_factory_t *this,
336 integrity_algorithm_t algo, signer_constructor_t create)
337 {
338 signer_entry_t *entry = malloc_thing(signer_entry_t);
339
340 entry->algo = algo;
341 entry->create = create;
342 this->mutex->lock(this->mutex);
343 this->signers->insert_last(this->signers, entry);
344 this->mutex->unlock(this->mutex);
345 }
346
347 /**
348 * Implementation of crypto_factory_t.remove_signer.
349 */
350 static void remove_signer(private_crypto_factory_t *this,
351 signer_constructor_t create)
352 {
353 signer_entry_t *entry;
354 enumerator_t *enumerator;
355
356 this->mutex->lock(this->mutex);
357 enumerator = this->signers->create_enumerator(this->signers);
358 while (enumerator->enumerate(enumerator, &entry))
359 {
360 if (entry->create == create)
361 {
362 this->signers->remove_at(this->signers, enumerator);
363 free(entry);
364 }
365 }
366 enumerator->destroy(enumerator);
367 this->mutex->unlock(this->mutex);
368 }
369
370 /**
371 * Implementation of crypto_factory_t.add_hasher.
372 */
373 static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo,
374 hasher_constructor_t create)
375 {
376 hasher_entry_t *entry = malloc_thing(hasher_entry_t);
377
378 entry->algo = algo;
379 entry->create = create;
380 this->mutex->lock(this->mutex);
381 this->hashers->insert_last(this->hashers, entry);
382 this->mutex->unlock(this->mutex);
383 }
384
385 /**
386 * Implementation of crypto_factory_t.remove_hasher.
387 */
388 static void remove_hasher(private_crypto_factory_t *this,
389 hasher_constructor_t create)
390 {
391 hasher_entry_t *entry;
392 enumerator_t *enumerator;
393
394 this->mutex->lock(this->mutex);
395 enumerator = this->hashers->create_enumerator(this->hashers);
396 while (enumerator->enumerate(enumerator, &entry))
397 {
398 if (entry->create == create)
399 {
400 this->hashers->remove_at(this->hashers, enumerator);
401 free(entry);
402 }
403 }
404 enumerator->destroy(enumerator);
405 this->mutex->unlock(this->mutex);
406 }
407
408 /**
409 * Implementation of crypto_factory_t.add_prf.
410 */
411 static void add_prf(private_crypto_factory_t *this,
412 pseudo_random_function_t algo, prf_constructor_t create)
413 {
414 prf_entry_t *entry = malloc_thing(prf_entry_t);
415
416 entry->algo = algo;
417 entry->create = create;
418 this->mutex->lock(this->mutex);
419 this->prfs->insert_last(this->prfs, entry);
420 this->mutex->unlock(this->mutex);
421 }
422
423 /**
424 * Implementation of crypto_factory_t.remove_prf.
425 */
426 static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create)
427 {
428 prf_entry_t *entry;
429 enumerator_t *enumerator;
430
431 this->mutex->lock(this->mutex);
432 enumerator = this->prfs->create_enumerator(this->prfs);
433 while (enumerator->enumerate(enumerator, &entry))
434 {
435 if (entry->create == create)
436 {
437 this->prfs->remove_at(this->prfs, enumerator);
438 free(entry);
439 }
440 }
441 enumerator->destroy(enumerator);
442 this->mutex->unlock(this->mutex);
443 }
444
445 /**
446 * Implementation of crypto_factory_t.add_rng.
447 */
448 static void add_rng(private_crypto_factory_t *this, rng_quality_t quality,
449 rng_constructor_t create)
450 {
451 rng_entry_t *entry = malloc_thing(rng_entry_t);
452
453 entry->quality = quality;
454 entry->create = create;
455 this->mutex->lock(this->mutex);
456 this->rngs->insert_last(this->rngs, entry);
457 this->mutex->unlock(this->mutex);
458 }
459
460 /**
461 * Implementation of crypto_factory_t.remove_rng.
462 */
463 static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create)
464 {
465 rng_entry_t *entry;
466 enumerator_t *enumerator;
467
468 this->mutex->lock(this->mutex);
469 enumerator = this->rngs->create_enumerator(this->rngs);
470 while (enumerator->enumerate(enumerator, &entry))
471 {
472 if (entry->create == create)
473 {
474 this->rngs->remove_at(this->rngs, enumerator);
475 free(entry);
476 }
477 }
478 enumerator->destroy(enumerator);
479 this->mutex->unlock(this->mutex);
480 }
481
482 /**
483 * Implementation of crypto_factory_t.add_dh.
484 */
485 static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group,
486 dh_constructor_t create)
487 {
488 dh_entry_t *entry = malloc_thing(dh_entry_t);
489
490 entry->group = group;
491 entry->create = create;
492 this->mutex->lock(this->mutex);
493 this->dhs->insert_last(this->dhs, entry);
494 this->mutex->unlock(this->mutex);
495 }
496
497 /**
498 * Implementation of crypto_factory_t.remove_dh.
499 */
500 static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create)
501 {
502 dh_entry_t *entry;
503 enumerator_t *enumerator;
504
505 this->mutex->lock(this->mutex);
506 enumerator = this->dhs->create_enumerator(this->dhs);
507 while (enumerator->enumerate(enumerator, &entry))
508 {
509 if (entry->create == create)
510 {
511 this->dhs->remove_at(this->dhs, enumerator);
512 free(entry);
513 }
514 }
515 enumerator->destroy(enumerator);
516 this->mutex->unlock(this->mutex);
517 }
518
519 /**
520 * Implementation of crypto_factory_t.destroy
521 */
522 static void destroy(private_crypto_factory_t *this)
523 {
524 this->crypters->destroy_function(this->crypters, free);
525 this->signers->destroy_function(this->signers, free);
526 this->hashers->destroy_function(this->hashers, free);
527 this->prfs->destroy_function(this->prfs, free);
528 this->rngs->destroy_function(this->rngs, free);
529 this->dhs->destroy_function(this->dhs, free);
530 this->mutex->destroy(this->mutex);
531 free(this);
532 }
533
534 /*
535 * see header file
536 */
537 crypto_factory_t *crypto_factory_create()
538 {
539 private_crypto_factory_t *this = malloc_thing(private_crypto_factory_t);
540
541 this->public.create_crypter = (crypter_t*(*)(crypto_factory_t*, encryption_algorithm_t, size_t))create_crypter;
542 this->public.create_signer = (signer_t*(*)(crypto_factory_t*, integrity_algorithm_t))create_signer;
543 this->public.create_hasher = (hasher_t*(*)(crypto_factory_t*, hash_algorithm_t))create_hasher;
544 this->public.create_prf = (prf_t*(*)(crypto_factory_t*, pseudo_random_function_t))create_prf;
545 this->public.create_rng = (rng_t*(*)(crypto_factory_t*, rng_quality_t quality))create_rng;
546 this->public.create_dh = (diffie_hellman_t*(*)(crypto_factory_t*, diffie_hellman_group_t group))create_dh;
547 this->public.add_crypter = (void(*)(crypto_factory_t*, encryption_algorithm_t algo, crypter_constructor_t create))add_crypter;
548 this->public.remove_crypter = (void(*)(crypto_factory_t*, crypter_constructor_t create))remove_crypter;
549 this->public.add_signer = (void(*)(crypto_factory_t*, integrity_algorithm_t algo, signer_constructor_t create))add_signer;
550 this->public.remove_signer = (void(*)(crypto_factory_t*, signer_constructor_t create))remove_signer;
551 this->public.add_hasher = (void(*)(crypto_factory_t*, hash_algorithm_t algo, hasher_constructor_t create))add_hasher;
552 this->public.remove_hasher = (void(*)(crypto_factory_t*, hasher_constructor_t create))remove_hasher;
553 this->public.add_prf = (void(*)(crypto_factory_t*, pseudo_random_function_t algo, prf_constructor_t create))add_prf;
554 this->public.remove_prf = (void(*)(crypto_factory_t*, prf_constructor_t create))remove_prf;
555 this->public.add_rng = (void(*)(crypto_factory_t*, rng_quality_t quality, rng_constructor_t create))add_rng;
556 this->public.remove_rng = (void(*)(crypto_factory_t*, rng_constructor_t create))remove_rng;
557 this->public.add_dh = (void(*)(crypto_factory_t*, diffie_hellman_group_t algo, dh_constructor_t create))add_dh;
558 this->public.remove_dh = (void(*)(crypto_factory_t*, dh_constructor_t create))remove_dh;
559 this->public.destroy = (void(*)(crypto_factory_t*))destroy;
560
561 this->crypters = linked_list_create();
562 this->signers = linked_list_create();
563 this->hashers = linked_list_create();
564 this->prfs = linked_list_create();
565 this->rngs = linked_list_create();
566 this->dhs = linked_list_create();
567 this->mutex = mutex_create(MUTEX_RECURSIVE);
568
569 return &this->public;
570 }
571