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