The introduced SHA1_NOFINAL hasher was not sufficient for EAP-AKA,
[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 dh_entry_t dh_entry_t;
56 struct dh_entry_t {
57 /** hash algorithm */
58 diffie_hellman_group_t group;
59 /** associated constructor */
60 dh_constructor_t create;
61 };
62
63 typedef struct private_crypto_factory_t private_crypto_factory_t;
64
65 /**
66 * private data of crypto_factory
67 */
68 struct private_crypto_factory_t {
69
70 /**
71 * public functions
72 */
73 crypto_factory_t public;
74
75 /**
76 * registered crypters, as crypter_entry_t
77 */
78 linked_list_t *crypters;
79
80 /**
81 * registered signers, as signer_entry_t
82 */
83 linked_list_t *signers;
84
85 /**
86 * registered hashers, as hasher_entry_t
87 */
88 linked_list_t *hashers;
89
90 /**
91 * registered perfs, as prf_entry_t
92 */
93 linked_list_t *prfs;
94
95 /**
96 * registered diffie hellman, as dh_entry_t
97 */
98 linked_list_t *dhs;
99
100 /**
101 * mutex to lock access to modules
102 */
103 mutex_t *mutex;
104 };
105
106 /**
107 * Implementation of crypto_factory_t.create_crypter.
108 */
109 static crypter_t* create_crypter(private_crypto_factory_t *this,
110 encryption_algorithm_t algo, size_t key_size)
111 {
112 enumerator_t *enumerator;
113 crypter_entry_t *entry;
114 crypter_t *crypter = NULL;
115
116 this->mutex->lock(this->mutex);
117 enumerator = this->crypters->create_enumerator(this->crypters);
118 while (enumerator->enumerate(enumerator, &entry))
119 {
120 if (entry->algo == algo)
121 {
122 crypter = entry->create(algo, key_size);
123 if (crypter)
124 {
125 break;
126 }
127 }
128 }
129 enumerator->destroy(enumerator);
130 this->mutex->unlock(this->mutex);
131 return crypter;
132 }
133
134 /**
135 * Implementation of crypto_factory_t.create_signer.
136 */
137 static signer_t* create_signer(private_crypto_factory_t *this,
138 integrity_algorithm_t algo)
139 {
140 enumerator_t *enumerator;
141 signer_entry_t *entry;
142 signer_t *signer = NULL;
143
144 this->mutex->lock(this->mutex);
145 enumerator = this->signers->create_enumerator(this->signers);
146 while (enumerator->enumerate(enumerator, &entry))
147 {
148 if (entry->algo == algo)
149 {
150 signer = entry->create(algo);
151 if (signer)
152 {
153 break;
154 }
155 }
156 }
157 enumerator->destroy(enumerator);
158 this->mutex->unlock(this->mutex);
159
160 return signer;
161 }
162
163 /**
164 * Implementation of crypto_factory_t.create_hasher.
165 */
166 static hasher_t* create_hasher(private_crypto_factory_t *this,
167 hash_algorithm_t algo)
168 {
169 enumerator_t *enumerator;
170 hasher_entry_t *entry;
171 hasher_t *hasher = NULL;
172
173 this->mutex->lock(this->mutex);
174 enumerator = this->hashers->create_enumerator(this->hashers);
175 while (enumerator->enumerate(enumerator, &entry))
176 {
177 if (algo == HASH_PREFERRED || entry->algo == algo)
178 {
179 hasher = entry->create(entry->algo);
180 if (hasher)
181 {
182 break;
183 }
184 }
185 }
186 enumerator->destroy(enumerator);
187 this->mutex->unlock(this->mutex);
188 return hasher;
189 }
190
191 /**
192 * Implementation of crypto_factory_t.create_prf.
193 */
194 static prf_t* create_prf(private_crypto_factory_t *this,
195 pseudo_random_function_t algo)
196 {
197 enumerator_t *enumerator;
198 prf_entry_t *entry;
199 prf_t *prf = NULL;
200
201 this->mutex->lock(this->mutex);
202 enumerator = this->prfs->create_enumerator(this->prfs);
203 while (enumerator->enumerate(enumerator, &entry))
204 {
205 if (entry->algo == algo)
206 {
207 prf = entry->create(algo);
208 if (prf)
209 {
210 break;
211 }
212 }
213 }
214 enumerator->destroy(enumerator);
215 this->mutex->unlock(this->mutex);
216 return prf;
217 }
218
219 /**
220 * Implementation of crypto_factory_t.create_dh.
221 */
222 static diffie_hellman_t* create_dh(private_crypto_factory_t *this,
223 diffie_hellman_group_t group)
224 {
225 enumerator_t *enumerator;
226 dh_entry_t *entry;
227 diffie_hellman_t *diffie_hellman = NULL;
228
229 this->mutex->lock(this->mutex);
230 enumerator = this->dhs->create_enumerator(this->dhs);
231 while (enumerator->enumerate(enumerator, &entry))
232 {
233 if (entry->group == group)
234 {
235 diffie_hellman = entry->create(group);
236 if (diffie_hellman)
237 {
238 break;
239 }
240 }
241 }
242 enumerator->destroy(enumerator);
243 this->mutex->unlock(this->mutex);
244 return diffie_hellman;
245 }
246
247 /**
248 * Implementation of crypto_factory_t.add_crypter.
249 */
250 static void add_crypter(private_crypto_factory_t *this,
251 encryption_algorithm_t algo,
252 crypter_constructor_t create)
253 {
254 crypter_entry_t *entry = malloc_thing(crypter_entry_t);
255
256 entry->algo = algo;
257 entry->create = create;
258 this->mutex->lock(this->mutex);
259 this->crypters->insert_last(this->crypters, entry);
260 this->mutex->unlock(this->mutex);
261 }
262
263 /**
264 * Implementation of crypto_factory_t.remove_crypter.
265 */
266 static void remove_crypter(private_crypto_factory_t *this,
267 crypter_constructor_t create)
268 {
269 crypter_entry_t *entry;
270 enumerator_t *enumerator;
271
272 this->mutex->lock(this->mutex);
273 enumerator = this->crypters->create_enumerator(this->crypters);
274 while (enumerator->enumerate(enumerator, &entry))
275 {
276 if (entry->create == create)
277 {
278 this->crypters->remove_at(this->crypters, enumerator);
279 free(entry);
280 }
281 }
282 enumerator->destroy(enumerator);
283 this->mutex->unlock(this->mutex);
284 }
285
286 /**
287 * Implementation of crypto_factory_t.add_signer.
288 */
289 static void add_signer(private_crypto_factory_t *this,
290 integrity_algorithm_t algo, signer_constructor_t create)
291 {
292 signer_entry_t *entry = malloc_thing(signer_entry_t);
293
294 entry->algo = algo;
295 entry->create = create;
296 this->mutex->lock(this->mutex);
297 this->signers->insert_last(this->signers, entry);
298 this->mutex->unlock(this->mutex);
299 }
300
301 /**
302 * Implementation of crypto_factory_t.remove_signer.
303 */
304 static void remove_signer(private_crypto_factory_t *this,
305 signer_constructor_t create)
306 {
307 signer_entry_t *entry;
308 enumerator_t *enumerator;
309
310 this->mutex->lock(this->mutex);
311 enumerator = this->signers->create_enumerator(this->signers);
312 while (enumerator->enumerate(enumerator, &entry))
313 {
314 if (entry->create == create)
315 {
316 this->signers->remove_at(this->signers, enumerator);
317 free(entry);
318 }
319 }
320 enumerator->destroy(enumerator);
321 this->mutex->unlock(this->mutex);
322 }
323
324 /**
325 * Implementation of crypto_factory_t.add_hasher.
326 */
327 static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo,
328 hasher_constructor_t create)
329 {
330 hasher_entry_t *entry = malloc_thing(hasher_entry_t);
331
332 entry->algo = algo;
333 entry->create = create;
334 this->mutex->lock(this->mutex);
335 this->hashers->insert_last(this->hashers, entry);
336 this->mutex->unlock(this->mutex);
337 }
338
339 /**
340 * Implementation of crypto_factory_t.remove_hasher.
341 */
342 static void remove_hasher(private_crypto_factory_t *this,
343 hasher_constructor_t create)
344 {
345 hasher_entry_t *entry;
346 enumerator_t *enumerator;
347
348 this->mutex->lock(this->mutex);
349 enumerator = this->hashers->create_enumerator(this->hashers);
350 while (enumerator->enumerate(enumerator, &entry))
351 {
352 if (entry->create == create)
353 {
354 this->hashers->remove_at(this->hashers, enumerator);
355 free(entry);
356 }
357 }
358 enumerator->destroy(enumerator);
359 this->mutex->unlock(this->mutex);
360 }
361
362 /**
363 * Implementation of crypto_factory_t.add_prf.
364 */
365 static void add_prf(private_crypto_factory_t *this,
366 pseudo_random_function_t algo, prf_constructor_t create)
367 {
368 prf_entry_t *entry = malloc_thing(prf_entry_t);
369
370 entry->algo = algo;
371 entry->create = create;
372 this->mutex->lock(this->mutex);
373 this->prfs->insert_last(this->prfs, entry);
374 this->mutex->unlock(this->mutex);
375 }
376
377 /**
378 * Implementation of crypto_factory_t.remove_prf.
379 */
380 static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create)
381 {
382 prf_entry_t *entry;
383 enumerator_t *enumerator;
384
385 this->mutex->lock(this->mutex);
386 enumerator = this->prfs->create_enumerator(this->prfs);
387 while (enumerator->enumerate(enumerator, &entry))
388 {
389 if (entry->create == create)
390 {
391 this->prfs->remove_at(this->prfs, enumerator);
392 free(entry);
393 }
394 }
395 enumerator->destroy(enumerator);
396 this->mutex->unlock(this->mutex);
397 }
398
399 /**
400 * Implementation of crypto_factory_t.add_dh.
401 */
402 static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group,
403 dh_constructor_t create)
404 {
405 dh_entry_t *entry = malloc_thing(dh_entry_t);
406
407 entry->group = group;
408 entry->create = create;
409 this->mutex->lock(this->mutex);
410 this->dhs->insert_last(this->dhs, entry);
411 this->mutex->unlock(this->mutex);
412 }
413
414 /**
415 * Implementation of crypto_factory_t.remove_dh.
416 */
417 static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create)
418 {
419 dh_entry_t *entry;
420 enumerator_t *enumerator;
421
422 this->mutex->lock(this->mutex);
423 enumerator = this->dhs->create_enumerator(this->dhs);
424 while (enumerator->enumerate(enumerator, &entry))
425 {
426 if (entry->create == create)
427 {
428 this->dhs->remove_at(this->dhs, enumerator);
429 free(entry);
430 }
431 }
432 enumerator->destroy(enumerator);
433 this->mutex->unlock(this->mutex);
434 }
435
436 /**
437 * Implementation of crypto_factory_t.destroy
438 */
439 static void destroy(private_crypto_factory_t *this)
440 {
441 this->crypters->destroy_function(this->crypters, free);
442 this->signers->destroy_function(this->signers, free);
443 this->hashers->destroy_function(this->hashers, free);
444 this->prfs->destroy_function(this->prfs, free);
445 this->dhs->destroy_function(this->dhs, free);
446 this->mutex->destroy(this->mutex);
447 free(this);
448 }
449
450 /*
451 * see header file
452 */
453 crypto_factory_t *crypto_factory_create()
454 {
455 private_crypto_factory_t *this = malloc_thing(private_crypto_factory_t);
456
457 this->public.create_crypter = (crypter_t*(*)(crypto_factory_t*, encryption_algorithm_t, size_t))create_crypter;
458 this->public.create_signer = (signer_t*(*)(crypto_factory_t*, integrity_algorithm_t))create_signer;
459 this->public.create_hasher = (hasher_t*(*)(crypto_factory_t*, hash_algorithm_t))create_hasher;
460 this->public.create_prf = (prf_t*(*)(crypto_factory_t*, pseudo_random_function_t))create_prf;
461 this->public.create_dh = (diffie_hellman_t*(*)(crypto_factory_t*, diffie_hellman_group_t group))create_dh;
462 this->public.add_crypter = (void(*)(crypto_factory_t*, encryption_algorithm_t algo, crypter_constructor_t create))add_crypter;
463 this->public.remove_crypter = (void(*)(crypto_factory_t*, crypter_constructor_t create))remove_crypter;
464 this->public.add_signer = (void(*)(crypto_factory_t*, integrity_algorithm_t algo, signer_constructor_t create))add_signer;
465 this->public.remove_signer = (void(*)(crypto_factory_t*, signer_constructor_t create))remove_signer;
466 this->public.add_hasher = (void(*)(crypto_factory_t*, hash_algorithm_t algo, hasher_constructor_t create))add_hasher;
467 this->public.remove_hasher = (void(*)(crypto_factory_t*, hasher_constructor_t create))remove_hasher;
468 this->public.add_prf = (void(*)(crypto_factory_t*, pseudo_random_function_t algo, prf_constructor_t create))add_prf;
469 this->public.remove_prf = (void(*)(crypto_factory_t*, prf_constructor_t create))remove_prf;
470 this->public.add_dh = (void(*)(crypto_factory_t*, diffie_hellman_group_t algo, dh_constructor_t create))add_dh;
471 this->public.remove_dh = (void(*)(crypto_factory_t*, dh_constructor_t create))remove_dh;
472 this->public.destroy = (void(*)(crypto_factory_t*))destroy;
473
474 this->crypters = linked_list_create();
475 this->signers = linked_list_create();
476 this->hashers = linked_list_create();
477 this->prfs = linked_list_create();
478 this->dhs = linked_list_create();
479 this->mutex = mutex_create(MUTEX_RECURSIVE);
480
481 return &this->public;
482 }
483