Removed len argument from proposal_get_token()
[strongswan.git] / src / libcharon / config / proposal.c
1 /*
2 * Copyright (C) 2008-2012 Tobias Brunner
3 * Copyright (C) 2006-2010 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <string.h>
18
19 #include "proposal.h"
20
21 #include <daemon.h>
22 #include <utils/linked_list.h>
23 #include <utils/identification.h>
24
25 #include <crypto/transform.h>
26 #include <crypto/prfs/prf.h>
27 #include <crypto/crypters/crypter.h>
28 #include <crypto/signers/signer.h>
29 #include <crypto/proposal/proposal_keywords.h>
30
31 ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP,
32 "PROTO_NONE",
33 "IKE",
34 "AH",
35 "ESP",
36 "IPCOMP",
37 );
38
39 typedef struct private_proposal_t private_proposal_t;
40 typedef struct algorithm_t algorithm_t;
41
42 /**
43 * Private data of an proposal_t object
44 */
45 struct private_proposal_t {
46
47 /**
48 * Public part
49 */
50 proposal_t public;
51
52 /**
53 * protocol (ESP or AH)
54 */
55 protocol_id_t protocol;
56
57 /**
58 * priority ordered list of encryption algorithms
59 */
60 linked_list_t *encryption_algos;
61
62 /**
63 * priority ordered list of integrity algorithms
64 */
65 linked_list_t *integrity_algos;
66
67 /**
68 * priority ordered list of pseudo random functions
69 */
70 linked_list_t *prf_algos;
71
72 /**
73 * priority ordered list of dh groups
74 */
75 linked_list_t *dh_groups;
76
77 /**
78 * priority ordered list of extended sequence number flags
79 */
80 linked_list_t *esns;
81
82 /**
83 * senders SPI
84 */
85 u_int64_t spi;
86
87 /**
88 * Proposal number
89 */
90 u_int number;
91 };
92
93 /**
94 * Struct used to store different kinds of algorithms.
95 */
96 struct algorithm_t {
97 /**
98 * Value from an encryption_algorithm_t/integrity_algorithm_t/...
99 */
100 u_int16_t algorithm;
101
102 /**
103 * the associated key size in bits, or zero if not needed
104 */
105 u_int16_t key_size;
106 };
107
108 /**
109 * Add algorithm/keysize to a algorithm list
110 */
111 static void add_algo(linked_list_t *list, u_int16_t algo, u_int16_t key_size)
112 {
113 algorithm_t *algo_key;
114
115 algo_key = malloc_thing(algorithm_t);
116 algo_key->algorithm = algo;
117 algo_key->key_size = key_size;
118 list->insert_last(list, (void*)algo_key);
119 }
120
121 METHOD(proposal_t, add_algorithm, void,
122 private_proposal_t *this, transform_type_t type,
123 u_int16_t algo, u_int16_t key_size)
124 {
125 switch (type)
126 {
127 case ENCRYPTION_ALGORITHM:
128 add_algo(this->encryption_algos, algo, key_size);
129 break;
130 case INTEGRITY_ALGORITHM:
131 add_algo(this->integrity_algos, algo, key_size);
132 break;
133 case PSEUDO_RANDOM_FUNCTION:
134 add_algo(this->prf_algos, algo, key_size);
135 break;
136 case DIFFIE_HELLMAN_GROUP:
137 add_algo(this->dh_groups, algo, 0);
138 break;
139 case EXTENDED_SEQUENCE_NUMBERS:
140 add_algo(this->esns, algo, 0);
141 break;
142 default:
143 break;
144 }
145 }
146
147 /**
148 * filter function for peer configs
149 */
150 static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg,
151 void **unused, u_int16_t *key_size)
152 {
153 algorithm_t *algo = *in;
154 *alg = algo->algorithm;
155 if (key_size)
156 {
157 *key_size = algo->key_size;
158 }
159 return TRUE;
160 }
161
162 METHOD(proposal_t, create_enumerator, enumerator_t*,
163 private_proposal_t *this, transform_type_t type)
164 {
165 linked_list_t *list;
166
167 switch (type)
168 {
169 case ENCRYPTION_ALGORITHM:
170 list = this->encryption_algos;
171 break;
172 case INTEGRITY_ALGORITHM:
173 list = this->integrity_algos;
174 break;
175 case PSEUDO_RANDOM_FUNCTION:
176 list = this->prf_algos;
177 break;
178 case DIFFIE_HELLMAN_GROUP:
179 list = this->dh_groups;
180 break;
181 case EXTENDED_SEQUENCE_NUMBERS:
182 list = this->esns;
183 break;
184 default:
185 return NULL;
186 }
187 return enumerator_create_filter(list->create_enumerator(list),
188 (void*)alg_filter, NULL, NULL);
189 }
190
191 METHOD(proposal_t, get_algorithm, bool,
192 private_proposal_t *this, transform_type_t type,
193 u_int16_t *alg, u_int16_t *key_size)
194 {
195 enumerator_t *enumerator;
196 bool found = FALSE;
197
198 enumerator = create_enumerator(this, type);
199 if (enumerator->enumerate(enumerator, alg, key_size))
200 {
201 found = TRUE;
202 }
203 enumerator->destroy(enumerator);
204 return found;
205 }
206
207 METHOD(proposal_t, has_dh_group, bool,
208 private_proposal_t *this, diffie_hellman_group_t group)
209 {
210 bool result = FALSE;
211
212 if (this->dh_groups->get_count(this->dh_groups))
213 {
214 algorithm_t *current;
215 enumerator_t *enumerator;
216
217 enumerator = this->dh_groups->create_enumerator(this->dh_groups);
218 while (enumerator->enumerate(enumerator, (void**)&current))
219 {
220 if (current->algorithm == group)
221 {
222 result = TRUE;
223 break;
224 }
225 }
226 enumerator->destroy(enumerator);
227 }
228 else if (group == MODP_NONE)
229 {
230 result = TRUE;
231 }
232 return result;
233 }
234
235 METHOD(proposal_t, strip_dh, void,
236 private_proposal_t *this)
237 {
238 algorithm_t *alg;
239
240 while (this->dh_groups->remove_last(this->dh_groups, (void**)&alg) == SUCCESS)
241 {
242 free(alg);
243 }
244 }
245
246 /**
247 * Find a matching alg/keysize in two linked lists
248 */
249 static bool select_algo(linked_list_t *first, linked_list_t *second, bool priv,
250 bool *add, u_int16_t *alg, size_t *key_size)
251 {
252 enumerator_t *e1, *e2;
253 algorithm_t *alg1, *alg2;
254
255 /* if in both are zero algorithms specified, we HAVE a match */
256 if (first->get_count(first) == 0 && second->get_count(second) == 0)
257 {
258 *add = FALSE;
259 return TRUE;
260 }
261
262 e1 = first->create_enumerator(first);
263 e2 = second->create_enumerator(second);
264 /* compare algs, order of algs in "first" is preferred */
265 while (e1->enumerate(e1, &alg1))
266 {
267 e2->destroy(e2);
268 e2 = second->create_enumerator(second);
269 while (e2->enumerate(e2, &alg2))
270 {
271 if (alg1->algorithm == alg2->algorithm &&
272 alg1->key_size == alg2->key_size)
273 {
274 if (!priv && alg1->algorithm >= 1024)
275 {
276 /* accept private use algorithms only if requested */
277 DBG1(DBG_CFG, "an algorithm from private space would match, "
278 "but peer implementation is unknown, skipped");
279 continue;
280 }
281 /* ok, we have an algorithm */
282 *alg = alg1->algorithm;
283 *key_size = alg1->key_size;
284 *add = TRUE;
285 e1->destroy(e1);
286 e2->destroy(e2);
287 return TRUE;
288 }
289 }
290 }
291 /* no match in all comparisons */
292 e1->destroy(e1);
293 e2->destroy(e2);
294 return FALSE;
295 }
296
297 METHOD(proposal_t, select_proposal, proposal_t*,
298 private_proposal_t *this, proposal_t *other_pub, bool private)
299 {
300 private_proposal_t *other = (private_proposal_t*)other_pub;
301 proposal_t *selected;
302 u_int16_t algo;
303 size_t key_size;
304 bool add;
305
306 DBG2(DBG_CFG, "selecting proposal:");
307
308 /* check protocol */
309 if (this->protocol != other->protocol)
310 {
311 DBG2(DBG_CFG, " protocol mismatch, skipping");
312 return NULL;
313 }
314
315 selected = proposal_create(this->protocol, other->number);
316
317 /* select encryption algorithm */
318 if (select_algo(this->encryption_algos, other->encryption_algos, private,
319 &add, &algo, &key_size))
320 {
321 if (add)
322 {
323 selected->add_algorithm(selected, ENCRYPTION_ALGORITHM,
324 algo, key_size);
325 }
326 }
327 else
328 {
329 selected->destroy(selected);
330 DBG2(DBG_CFG, " no acceptable %N found",
331 transform_type_names, ENCRYPTION_ALGORITHM);
332 return NULL;
333 }
334 /* select integrity algorithm */
335 if (!encryption_algorithm_is_aead(algo))
336 {
337 if (select_algo(this->integrity_algos, other->integrity_algos, private,
338 &add, &algo, &key_size))
339 {
340 if (add)
341 {
342 selected->add_algorithm(selected, INTEGRITY_ALGORITHM,
343 algo, key_size);
344 }
345 }
346 else
347 {
348 selected->destroy(selected);
349 DBG2(DBG_CFG, " no acceptable %N found",
350 transform_type_names, INTEGRITY_ALGORITHM);
351 return NULL;
352 }
353 }
354 /* select prf algorithm */
355 if (select_algo(this->prf_algos, other->prf_algos, private,
356 &add, &algo, &key_size))
357 {
358 if (add)
359 {
360 selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION,
361 algo, key_size);
362 }
363 }
364 else
365 {
366 selected->destroy(selected);
367 DBG2(DBG_CFG, " no acceptable %N found",
368 transform_type_names, PSEUDO_RANDOM_FUNCTION);
369 return NULL;
370 }
371 /* select a DH-group */
372 if (select_algo(this->dh_groups, other->dh_groups, private,
373 &add, &algo, &key_size))
374 {
375 if (add)
376 {
377 selected->add_algorithm(selected, DIFFIE_HELLMAN_GROUP, algo, 0);
378 }
379 }
380 else
381 {
382 selected->destroy(selected);
383 DBG2(DBG_CFG, " no acceptable %N found",
384 transform_type_names, DIFFIE_HELLMAN_GROUP);
385 return NULL;
386 }
387 /* select if we use ESNs (has no private use space) */
388 if (select_algo(this->esns, other->esns, TRUE, &add, &algo, &key_size))
389 {
390 if (add)
391 {
392 selected->add_algorithm(selected, EXTENDED_SEQUENCE_NUMBERS, algo, 0);
393 }
394 }
395 else
396 {
397 selected->destroy(selected);
398 DBG2(DBG_CFG, " no acceptable %N found",
399 transform_type_names, EXTENDED_SEQUENCE_NUMBERS);
400 return NULL;
401 }
402 DBG2(DBG_CFG, " proposal matches");
403
404 /* apply SPI from "other" */
405 selected->set_spi(selected, other->spi);
406
407 /* everything matched, return new proposal */
408 return selected;
409 }
410
411 METHOD(proposal_t, get_protocol, protocol_id_t,
412 private_proposal_t *this)
413 {
414 return this->protocol;
415 }
416
417 METHOD(proposal_t, set_spi, void,
418 private_proposal_t *this, u_int64_t spi)
419 {
420 this->spi = spi;
421 }
422
423 METHOD(proposal_t, get_spi, u_int64_t,
424 private_proposal_t *this)
425 {
426 return this->spi;
427 }
428
429 /**
430 * Clone a algorithm list
431 */
432 static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list)
433 {
434 algorithm_t *algo, *clone_algo;
435 enumerator_t *enumerator;
436
437 enumerator = list->create_enumerator(list);
438 while (enumerator->enumerate(enumerator, &algo))
439 {
440 clone_algo = malloc_thing(algorithm_t);
441 memcpy(clone_algo, algo, sizeof(algorithm_t));
442 clone_list->insert_last(clone_list, (void*)clone_algo);
443 }
444 enumerator->destroy(enumerator);
445 }
446
447 /**
448 * check if an algorithm list equals
449 */
450 static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2)
451 {
452 enumerator_t *e1, *e2;
453 algorithm_t *alg1, *alg2;
454 bool equals = TRUE;
455
456 if (l1->get_count(l1) != l2->get_count(l2))
457 {
458 return FALSE;
459 }
460
461 e1 = l1->create_enumerator(l1);
462 e2 = l2->create_enumerator(l2);
463 while (e1->enumerate(e1, &alg1) && e2->enumerate(e2, &alg2))
464 {
465 if (alg1->algorithm != alg2->algorithm ||
466 alg1->key_size != alg2->key_size)
467 {
468 equals = FALSE;
469 break;
470 }
471 }
472 e1->destroy(e1);
473 e2->destroy(e2);
474 return equals;
475 }
476
477 METHOD(proposal_t, get_number, u_int,
478 private_proposal_t *this)
479 {
480 return this->number;
481 }
482
483 METHOD(proposal_t, equals, bool,
484 private_proposal_t *this, proposal_t *other_pub)
485 {
486 private_proposal_t *other = (private_proposal_t*)other_pub;
487
488 if (this == other)
489 {
490 return TRUE;
491 }
492 return (
493 algo_list_equals(this->encryption_algos, other->encryption_algos) &&
494 algo_list_equals(this->integrity_algos, other->integrity_algos) &&
495 algo_list_equals(this->prf_algos, other->prf_algos) &&
496 algo_list_equals(this->dh_groups, other->dh_groups) &&
497 algo_list_equals(this->esns, other->esns));
498 }
499
500 METHOD(proposal_t, clone_, proposal_t*,
501 private_proposal_t *this)
502 {
503 private_proposal_t *clone;
504
505 clone = (private_proposal_t*)proposal_create(this->protocol, 0);
506 clone_algo_list(this->encryption_algos, clone->encryption_algos);
507 clone_algo_list(this->integrity_algos, clone->integrity_algos);
508 clone_algo_list(this->prf_algos, clone->prf_algos);
509 clone_algo_list(this->dh_groups, clone->dh_groups);
510 clone_algo_list(this->esns, clone->esns);
511
512 clone->spi = this->spi;
513 clone->number = this->number;
514
515 return &clone->public;
516 }
517
518 /**
519 * Checks the proposal read from a string.
520 */
521 static void check_proposal(private_proposal_t *this)
522 {
523 enumerator_t *e;
524 algorithm_t *alg;
525 bool all_aead = TRUE;
526
527 e = this->encryption_algos->create_enumerator(this->encryption_algos);
528 while (e->enumerate(e, &alg))
529 {
530 if (!encryption_algorithm_is_aead(alg->algorithm))
531 {
532 all_aead = FALSE;
533 break;
534 }
535 }
536 e->destroy(e);
537
538 if (all_aead)
539 {
540 /* if all encryption algorithms in the proposal are authenticated encryption
541 * algorithms we MUST NOT propose any integrity algorithms */
542 while (this->integrity_algos->remove_last(this->integrity_algos,
543 (void**)&alg) == SUCCESS)
544 {
545 free(alg);
546 }
547 }
548
549 if (this->protocol == PROTO_AH || this->protocol == PROTO_ESP)
550 {
551 e = this->esns->create_enumerator(this->esns);
552 if (!e->enumerate(e, &alg))
553 { /* ESN not specified, assume not supported */
554 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
555 }
556 e->destroy(e);
557 }
558 }
559
560 /**
561 * add a algorithm identified by a string to the proposal.
562 */
563 static bool add_string_algo(private_proposal_t *this, const char *alg)
564 {
565 const proposal_token_t *token = proposal_get_token(alg);
566
567 if (token == NULL)
568 {
569 DBG1(DBG_CFG, "algorithm '%s' not recognized", alg);
570 return FALSE;
571 }
572
573 add_algorithm(this, token->type, token->algorithm, token->keysize);
574
575 if (this->protocol == PROTO_IKE && token->type == INTEGRITY_ALGORITHM)
576 {
577 pseudo_random_function_t prf;
578
579 switch (token->algorithm)
580 {
581 case AUTH_HMAC_SHA1_96:
582 prf = PRF_HMAC_SHA1;
583 break;
584 case AUTH_HMAC_SHA2_256_128:
585 prf = PRF_HMAC_SHA2_256;
586 break;
587 case AUTH_HMAC_SHA2_384_192:
588 prf = PRF_HMAC_SHA2_384;
589 break;
590 case AUTH_HMAC_SHA2_512_256:
591 prf = PRF_HMAC_SHA2_512;
592 break;
593 case AUTH_HMAC_MD5_96:
594 prf = PRF_HMAC_MD5;
595 break;
596 case AUTH_AES_XCBC_96:
597 prf = PRF_AES128_XCBC;
598 break;
599 case AUTH_CAMELLIA_XCBC_96:
600 prf = PRF_CAMELLIA128_XCBC;
601 break;
602 case AUTH_AES_CMAC_96:
603 prf = PRF_AES128_CMAC;
604 break;
605 default:
606 prf = PRF_UNDEFINED;
607 }
608 if (prf != PRF_UNDEFINED)
609 {
610 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
611 }
612 }
613 return TRUE;
614 }
615
616 /**
617 * print all algorithms of a kind to buffer
618 */
619 static int print_alg(private_proposal_t *this, printf_hook_data_t *data,
620 u_int kind, void *names, bool *first)
621 {
622 enumerator_t *enumerator;
623 size_t written = 0;
624 u_int16_t alg, size;
625
626 enumerator = create_enumerator(this, kind);
627 while (enumerator->enumerate(enumerator, &alg, &size))
628 {
629 if (*first)
630 {
631 written += print_in_hook(data, "%N", names, alg);
632 *first = FALSE;
633 }
634 else
635 {
636 written += print_in_hook(data, "/%N", names, alg);
637 }
638 if (size)
639 {
640 written += print_in_hook(data, "_%u", size);
641 }
642 }
643 enumerator->destroy(enumerator);
644 return written;
645 }
646
647 /**
648 * Described in header.
649 */
650 int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
651 const void *const *args)
652 {
653 private_proposal_t *this = *((private_proposal_t**)(args[0]));
654 linked_list_t *list = *((linked_list_t**)(args[0]));
655 enumerator_t *enumerator;
656 size_t written = 0;
657 bool first = TRUE;
658
659 if (this == NULL)
660 {
661 return print_in_hook(data, "(null)");
662 }
663
664 if (spec->hash)
665 {
666 enumerator = list->create_enumerator(list);
667 while (enumerator->enumerate(enumerator, &this))
668 { /* call recursivly */
669 if (first)
670 {
671 written += print_in_hook(data, "%P", this);
672 first = FALSE;
673 }
674 else
675 {
676 written += print_in_hook(data, ", %P", this);
677 }
678 }
679 enumerator->destroy(enumerator);
680 return written;
681 }
682
683 written = print_in_hook(data, "%N:", protocol_id_names, this->protocol);
684 written += print_alg(this, data, ENCRYPTION_ALGORITHM,
685 encryption_algorithm_names, &first);
686 written += print_alg(this, data, INTEGRITY_ALGORITHM,
687 integrity_algorithm_names, &first);
688 written += print_alg(this, data, PSEUDO_RANDOM_FUNCTION,
689 pseudo_random_function_names, &first);
690 written += print_alg(this, data, DIFFIE_HELLMAN_GROUP,
691 diffie_hellman_group_names, &first);
692 written += print_alg(this, data, EXTENDED_SEQUENCE_NUMBERS,
693 extended_sequence_numbers_names, &first);
694 return written;
695 }
696
697 METHOD(proposal_t, destroy, void,
698 private_proposal_t *this)
699 {
700 this->encryption_algos->destroy_function(this->encryption_algos, free);
701 this->integrity_algos->destroy_function(this->integrity_algos, free);
702 this->prf_algos->destroy_function(this->prf_algos, free);
703 this->dh_groups->destroy_function(this->dh_groups, free);
704 this->esns->destroy_function(this->esns, free);
705 free(this);
706 }
707
708 /*
709 * Describtion in header-file
710 */
711 proposal_t *proposal_create(protocol_id_t protocol, u_int number)
712 {
713 private_proposal_t *this;
714
715 INIT(this,
716 .public = {
717 .add_algorithm = _add_algorithm,
718 .create_enumerator = _create_enumerator,
719 .get_algorithm = _get_algorithm,
720 .has_dh_group = _has_dh_group,
721 .strip_dh = _strip_dh,
722 .select = _select_proposal,
723 .get_protocol = _get_protocol,
724 .set_spi = _set_spi,
725 .get_spi = _get_spi,
726 .get_number = _get_number,
727 .equals = _equals,
728 .clone = _clone_,
729 .destroy = _destroy,
730 },
731 .protocol = protocol,
732 .number = number,
733 .encryption_algos = linked_list_create(),
734 .integrity_algos = linked_list_create(),
735 .prf_algos = linked_list_create(),
736 .dh_groups = linked_list_create(),
737 .esns = linked_list_create(),
738 );
739
740 return &this->public;
741 }
742
743 /**
744 * Add supported IKE algorithms to proposal
745 */
746 static void proposal_add_supported_ike(private_proposal_t *this)
747 {
748 enumerator_t *enumerator;
749 encryption_algorithm_t encryption;
750 integrity_algorithm_t integrity;
751 pseudo_random_function_t prf;
752 diffie_hellman_group_t group;
753 const char *plugin_name;
754
755 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
756 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
757 {
758 switch (encryption)
759 {
760 case ENCR_AES_CBC:
761 case ENCR_AES_CTR:
762 case ENCR_CAMELLIA_CBC:
763 case ENCR_CAMELLIA_CTR:
764 case ENCR_AES_CCM_ICV8:
765 case ENCR_AES_CCM_ICV12:
766 case ENCR_AES_CCM_ICV16:
767 case ENCR_AES_GCM_ICV8:
768 case ENCR_AES_GCM_ICV12:
769 case ENCR_AES_GCM_ICV16:
770 case ENCR_CAMELLIA_CCM_ICV8:
771 case ENCR_CAMELLIA_CCM_ICV12:
772 case ENCR_CAMELLIA_CCM_ICV16:
773 /* we assume that we support all AES/Camellia sizes */
774 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128);
775 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
776 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
777 break;
778 case ENCR_3DES:
779 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
780 break;
781 case ENCR_DES:
782 /* no, thanks */
783 break;
784 default:
785 break;
786 }
787 }
788 enumerator->destroy(enumerator);
789
790 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
791 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
792 {
793 switch (integrity)
794 {
795 case AUTH_HMAC_SHA1_96:
796 case AUTH_HMAC_SHA2_256_128:
797 case AUTH_HMAC_SHA2_384_192:
798 case AUTH_HMAC_SHA2_512_256:
799 case AUTH_HMAC_MD5_96:
800 case AUTH_AES_XCBC_96:
801 case AUTH_AES_CMAC_96:
802 add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
803 break;
804 default:
805 break;
806 }
807 }
808 enumerator->destroy(enumerator);
809
810 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
811 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
812 {
813 switch (prf)
814 {
815 case PRF_HMAC_SHA1:
816 case PRF_HMAC_SHA2_256:
817 case PRF_HMAC_SHA2_384:
818 case PRF_HMAC_SHA2_512:
819 case PRF_HMAC_MD5:
820 case PRF_AES128_XCBC:
821 case PRF_AES128_CMAC:
822 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
823 break;
824 default:
825 break;
826 }
827 }
828 enumerator->destroy(enumerator);
829
830 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
831 while (enumerator->enumerate(enumerator, &group, &plugin_name))
832 {
833 switch (group)
834 {
835 case MODP_NULL:
836 /* only for testing purposes */
837 break;
838 case MODP_768_BIT:
839 /* weak */
840 break;
841 case MODP_1024_BIT:
842 case MODP_1536_BIT:
843 case MODP_2048_BIT:
844 case MODP_3072_BIT:
845 case MODP_4096_BIT:
846 case MODP_8192_BIT:
847 case ECP_256_BIT:
848 case ECP_384_BIT:
849 case ECP_521_BIT:
850 case MODP_1024_160:
851 case MODP_2048_224:
852 case MODP_2048_256:
853 case ECP_192_BIT:
854 case ECP_224_BIT:
855 add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
856 break;
857 default:
858 break;
859 }
860 }
861 enumerator->destroy(enumerator);
862 }
863
864 /*
865 * Describtion in header-file
866 */
867 proposal_t *proposal_create_default(protocol_id_t protocol)
868 {
869 private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0);
870
871 switch (protocol)
872 {
873 case PROTO_IKE:
874 proposal_add_supported_ike(this);
875 break;
876 case PROTO_ESP:
877 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
878 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
879 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
880 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
881 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
882 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
883 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
884 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
885 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
886 break;
887 case PROTO_AH:
888 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
889 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
890 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
891 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
892 break;
893 default:
894 break;
895 }
896 return &this->public;
897 }
898
899 /*
900 * Describtion in header-file
901 */
902 proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
903 {
904 private_proposal_t *this;
905 enumerator_t *enumerator;
906 bool failed = TRUE;
907 char *alg;
908
909 this = (private_proposal_t*)proposal_create(protocol, 0);
910
911 /* get all tokens, separated by '-' */
912 enumerator = enumerator_create_token(algs, "-", " ");
913 while (enumerator->enumerate(enumerator, &alg))
914 {
915 if (!add_string_algo(this, alg))
916 {
917 failed = TRUE;
918 break;
919 }
920 failed = FALSE;
921 }
922 enumerator->destroy(enumerator);
923
924 if (failed)
925 {
926 destroy(this);
927 return NULL;
928 }
929
930 check_proposal(this);
931
932 return &this->public;
933 }