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