prepare CAMELLIA_CCM ESP encryption
[strongswan.git] / src / charon / 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 return TRUE;
273 }
274 return FALSE;
275 }
276
277 /**
278 * Find a matching alg/keysize in two linked lists
279 */
280 static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add,
281 u_int16_t *alg, size_t *key_size)
282 {
283 enumerator_t *e1, *e2;
284 algorithm_t *alg1, *alg2;
285
286 /* if in both are zero algorithms specified, we HAVE a match */
287 if (first->get_count(first) == 0 && second->get_count(second) == 0)
288 {
289 *add = FALSE;
290 return TRUE;
291 }
292
293 e1 = first->create_enumerator(first);
294 e2 = second->create_enumerator(second);
295 /* compare algs, order of algs in "first" is preferred */
296 while (e1->enumerate(e1, &alg1))
297 {
298 e2->destroy(e2);
299 e2 = second->create_enumerator(second);
300 while (e2->enumerate(e2, &alg2))
301 {
302 if (alg1->algorithm == alg2->algorithm &&
303 alg1->key_size == alg2->key_size)
304 {
305 /* ok, we have an algorithm */
306 *alg = alg1->algorithm;
307 *key_size = alg1->key_size;
308 *add = TRUE;
309 e1->destroy(e1);
310 e2->destroy(e2);
311 return TRUE;
312 }
313 }
314 }
315 /* no match in all comparisons */
316 e1->destroy(e1);
317 e2->destroy(e2);
318 return FALSE;
319 }
320
321 /**
322 * Implements proposal_t.select.
323 */
324 static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t *other)
325 {
326 proposal_t *selected;
327 u_int16_t algo;
328 size_t key_size;
329 bool add;
330
331 DBG2(DBG_CFG, "selecting proposal:");
332
333 /* check protocol */
334 if (this->protocol != other->protocol)
335 {
336 DBG2(DBG_CFG, " protocol mismatch, skipping");
337 return NULL;
338 }
339
340 selected = proposal_create(this->protocol);
341
342 /* select encryption algorithm */
343 if (select_algo(this->encryption_algos, other->encryption_algos,
344 &add, &algo, &key_size))
345 {
346 if (add)
347 {
348 selected->add_algorithm(selected, ENCRYPTION_ALGORITHM,
349 algo, key_size);
350 }
351 }
352 else
353 {
354 selected->destroy(selected);
355 DBG2(DBG_CFG, " no acceptable %N found",
356 transform_type_names, ENCRYPTION_ALGORITHM);
357 return NULL;
358 }
359 /* select integrity algorithm */
360 if (!is_authenticated_encryption(algo))
361 {
362 if (select_algo(this->integrity_algos, other->integrity_algos,
363 &add, &algo, &key_size))
364 {
365 if (add)
366 {
367 selected->add_algorithm(selected, INTEGRITY_ALGORITHM,
368 algo, key_size);
369 }
370 }
371 else
372 {
373 selected->destroy(selected);
374 DBG2(DBG_CFG, " no acceptable %N found",
375 transform_type_names, INTEGRITY_ALGORITHM);
376 return NULL;
377 }
378 }
379 /* select prf algorithm */
380 if (select_algo(this->prf_algos, other->prf_algos,
381 &add, &algo, &key_size))
382 {
383 if (add)
384 {
385 selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION,
386 algo, key_size);
387 }
388 }
389 else
390 {
391 selected->destroy(selected);
392 DBG2(DBG_CFG, " no acceptable %N found",
393 transform_type_names, PSEUDO_RANDOM_FUNCTION);
394 return NULL;
395 }
396 /* select a DH-group */
397 if (select_algo(this->dh_groups, other->dh_groups, &add, &algo, &key_size))
398 {
399 if (add)
400 {
401 selected->add_algorithm(selected, DIFFIE_HELLMAN_GROUP, algo, 0);
402 }
403 }
404 else
405 {
406 selected->destroy(selected);
407 DBG2(DBG_CFG, " no acceptable %N found",
408 transform_type_names, DIFFIE_HELLMAN_GROUP);
409 return NULL;
410 }
411 /* select if we use ESNs */
412 if (select_algo(this->esns, other->esns, &add, &algo, &key_size))
413 {
414 if (add)
415 {
416 selected->add_algorithm(selected, EXTENDED_SEQUENCE_NUMBERS, algo, 0);
417 }
418 }
419 else
420 {
421 selected->destroy(selected);
422 DBG2(DBG_CFG, " no acceptable %N found",
423 transform_type_names, EXTENDED_SEQUENCE_NUMBERS);
424 return NULL;
425 }
426 DBG2(DBG_CFG, " proposal matches");
427
428 /* apply SPI from "other" */
429 selected->set_spi(selected, other->spi);
430
431 /* everything matched, return new proposal */
432 return selected;
433 }
434
435 /**
436 * Implements proposal_t.get_protocols.
437 */
438 static protocol_id_t get_protocol(private_proposal_t *this)
439 {
440 return this->protocol;
441 }
442
443 /**
444 * Implements proposal_t.set_spi.
445 */
446 static void set_spi(private_proposal_t *this, u_int64_t spi)
447 {
448 this->spi = spi;
449 }
450
451 /**
452 * Implements proposal_t.get_spi.
453 */
454 static u_int64_t get_spi(private_proposal_t *this)
455 {
456 return this->spi;
457 }
458
459 /**
460 * Clone a algorithm list
461 */
462 static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list)
463 {
464 algorithm_t *algo, *clone_algo;
465 enumerator_t *enumerator;
466
467 enumerator = list->create_enumerator(list);
468 while (enumerator->enumerate(enumerator, &algo))
469 {
470 clone_algo = malloc_thing(algorithm_t);
471 memcpy(clone_algo, algo, sizeof(algorithm_t));
472 clone_list->insert_last(clone_list, (void*)clone_algo);
473 }
474 enumerator->destroy(enumerator);
475 }
476
477 /**
478 * check if an algorithm list equals
479 */
480 static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2)
481 {
482 enumerator_t *e1, *e2;
483 algorithm_t *alg1, *alg2;
484 bool equals = TRUE;
485
486 if (l1->get_count(l1) != l2->get_count(l2))
487 {
488 return FALSE;
489 }
490
491 e1 = l1->create_enumerator(l1);
492 e2 = l2->create_enumerator(l2);
493 while (e1->enumerate(e1, &alg1) && e2->enumerate(e2, &alg2))
494 {
495 if (alg1->algorithm != alg2->algorithm ||
496 alg1->key_size != alg2->key_size)
497 {
498 equals = FALSE;
499 break;
500 }
501 }
502 e1->destroy(e1);
503 e2->destroy(e2);
504 return equals;
505 }
506
507 /**
508 * Implementation of proposal_t.equals.
509 */
510 static bool equals(private_proposal_t *this, private_proposal_t *other)
511 {
512 if (this == other)
513 {
514 return TRUE;
515 }
516 if (this->public.equals != other->public.equals)
517 {
518 return FALSE;
519 }
520 return (
521 algo_list_equals(this->encryption_algos, other->encryption_algos) &&
522 algo_list_equals(this->integrity_algos, other->integrity_algos) &&
523 algo_list_equals(this->prf_algos, other->prf_algos) &&
524 algo_list_equals(this->dh_groups, other->dh_groups) &&
525 algo_list_equals(this->esns, other->esns));
526 }
527
528 /**
529 * Implements proposal_t.clone
530 */
531 static proposal_t *clone_(private_proposal_t *this)
532 {
533 private_proposal_t *clone = (private_proposal_t*)proposal_create(this->protocol);
534
535 clone_algo_list(this->encryption_algos, clone->encryption_algos);
536 clone_algo_list(this->integrity_algos, clone->integrity_algos);
537 clone_algo_list(this->prf_algos, clone->prf_algos);
538 clone_algo_list(this->dh_groups, clone->dh_groups);
539 clone_algo_list(this->esns, clone->esns);
540
541 clone->spi = this->spi;
542
543 return &clone->public;
544 }
545
546 /**
547 * Checks the proposal read from a string.
548 */
549 static void check_proposal(private_proposal_t *this)
550 {
551 enumerator_t *e;
552 algorithm_t *alg;
553 bool all_aead = TRUE;
554
555 e = this->encryption_algos->create_enumerator(this->encryption_algos);
556 while (e->enumerate(e, &alg))
557 {
558 if (!is_authenticated_encryption(alg->algorithm))
559 {
560 all_aead = FALSE;
561 break;
562 }
563 }
564 e->destroy(e);
565
566 if (all_aead)
567 {
568 /* if all encryption algorithms in the proposal are authenticated encryption
569 * algorithms we MUST NOT propose any integrity algorithms */
570 while (this->integrity_algos->remove_last(this->integrity_algos,
571 (void**)&alg) == SUCCESS)
572 {
573 free(alg);
574 }
575 }
576 }
577
578 /**
579 * add a algorithm identified by a string to the proposal.
580 */
581 static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
582 {
583 const proposal_token_t *token = proposal_get_token(alg.ptr, alg.len);
584
585 if (token == NULL)
586 {
587 return FAILED;
588 }
589
590 add_algorithm(this, token->type, token->algorithm, token->keysize);
591
592 if (this->protocol == PROTO_IKE && token->type == INTEGRITY_ALGORITHM)
593 {
594 pseudo_random_function_t prf;
595
596 switch (token->algorithm)
597 {
598 case AUTH_HMAC_SHA1_96:
599 prf = PRF_HMAC_SHA1;
600 break;
601 case AUTH_HMAC_SHA2_256_128:
602 prf = PRF_HMAC_SHA2_256;
603 break;
604 case AUTH_HMAC_SHA2_384_192:
605 prf = PRF_HMAC_SHA2_384;
606 break;
607 case AUTH_HMAC_SHA2_512_256:
608 prf = PRF_HMAC_SHA2_512;
609 break;
610 case AUTH_HMAC_MD5_96:
611 prf = PRF_HMAC_MD5;
612 break;
613 case AUTH_AES_XCBC_96:
614 prf = PRF_AES128_XCBC;
615 break;
616 default:
617 prf = PRF_UNDEFINED;
618 }
619 if (prf != PRF_UNDEFINED)
620 {
621 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
622 }
623 }
624 return SUCCESS;
625 }
626
627 /**
628 * print all algorithms of a kind to buffer
629 */
630 static int print_alg(private_proposal_t *this, char **dst, size_t *len,
631 u_int kind, void *names, bool *first)
632 {
633 enumerator_t *enumerator;
634 size_t written = 0;
635 u_int16_t alg, size;
636
637 enumerator = create_enumerator(this, kind);
638 while (enumerator->enumerate(enumerator, &alg, &size))
639 {
640 if (*first)
641 {
642 written += print_in_hook(*dst, *len, "%N", names, alg);
643 *first = FALSE;
644 }
645 else
646 {
647 written += print_in_hook(*dst, *len, "/%N", names, alg);
648 }
649 if (size)
650 {
651 written += print_in_hook(*dst, *len, "_%u", size);
652 }
653 }
654 enumerator->destroy(enumerator);
655 return written;
656 }
657
658 /**
659 * Described in header.
660 */
661 int proposal_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
662 const void *const *args)
663 {
664 private_proposal_t *this = *((private_proposal_t**)(args[0]));
665 linked_list_t *list = *((linked_list_t**)(args[0]));
666 enumerator_t *enumerator;
667 size_t written = 0;
668 bool first = TRUE;
669
670 if (this == NULL)
671 {
672 return print_in_hook(dst, len, "(null)");
673 }
674
675 if (spec->hash)
676 {
677 enumerator = list->create_enumerator(list);
678 while (enumerator->enumerate(enumerator, &this))
679 { /* call recursivly */
680 if (first)
681 {
682 written += print_in_hook(dst, len, "%P", this);
683 first = FALSE;
684 }
685 else
686 {
687 written += print_in_hook(dst, len, ", %P", this);
688 }
689 }
690 enumerator->destroy(enumerator);
691 return written;
692 }
693
694 written = print_in_hook(dst, len, "%N:", protocol_id_names, this->protocol);
695 written += print_alg(this, &dst, &len, ENCRYPTION_ALGORITHM,
696 encryption_algorithm_names, &first);
697 written += print_alg(this, &dst, &len, INTEGRITY_ALGORITHM,
698 integrity_algorithm_names, &first);
699 written += print_alg(this, &dst, &len, PSEUDO_RANDOM_FUNCTION,
700 pseudo_random_function_names, &first);
701 written += print_alg(this, &dst, &len, DIFFIE_HELLMAN_GROUP,
702 diffie_hellman_group_names, &first);
703 written += print_alg(this, &dst, &len, EXTENDED_SEQUENCE_NUMBERS,
704 extended_sequence_numbers_names, &first);
705 return written;
706 }
707
708 /**
709 * Implements proposal_t.destroy.
710 */
711 static void destroy(private_proposal_t *this)
712 {
713 this->encryption_algos->destroy_function(this->encryption_algos, free);
714 this->integrity_algos->destroy_function(this->integrity_algos, free);
715 this->prf_algos->destroy_function(this->prf_algos, free);
716 this->dh_groups->destroy_function(this->dh_groups, free);
717 this->esns->destroy_function(this->esns, free);
718 free(this);
719 }
720
721 /*
722 * Describtion in header-file
723 */
724 proposal_t *proposal_create(protocol_id_t protocol)
725 {
726 private_proposal_t *this = malloc_thing(private_proposal_t);
727
728 this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,u_int16_t))add_algorithm;
729 this->public.create_enumerator = (enumerator_t* (*)(proposal_t*,transform_type_t))create_enumerator;
730 this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,u_int16_t*,u_int16_t*))get_algorithm;
731 this->public.has_dh_group = (bool (*)(proposal_t*,diffie_hellman_group_t))has_dh_group;
732 this->public.strip_dh = (void(*)(proposal_t*))strip_dh;
733 this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal;
734 this->public.get_protocol = (protocol_id_t(*)(proposal_t*))get_protocol;
735 this->public.set_spi = (void(*)(proposal_t*,u_int64_t))set_spi;
736 this->public.get_spi = (u_int64_t(*)(proposal_t*))get_spi;
737 this->public.equals = (bool(*)(proposal_t*, proposal_t *other))equals;
738 this->public.clone = (proposal_t*(*)(proposal_t*))clone_;
739 this->public.destroy = (void(*)(proposal_t*))destroy;
740
741 this->spi = 0;
742 this->protocol = protocol;
743
744 this->encryption_algos = linked_list_create();
745 this->integrity_algos = linked_list_create();
746 this->prf_algos = linked_list_create();
747 this->dh_groups = linked_list_create();
748 this->esns = linked_list_create();
749
750 return &this->public;
751 }
752
753 /**
754 * Add supported IKE algorithms to proposal
755 */
756 static void proposal_add_supported_ike(private_proposal_t *this)
757 {
758 enumerator_t *enumerator;
759 encryption_algorithm_t encryption;
760 integrity_algorithm_t integrity;
761 pseudo_random_function_t prf;
762 diffie_hellman_group_t group;
763
764 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
765 while (enumerator->enumerate(enumerator, &encryption))
766 {
767 switch (encryption)
768 {
769 case ENCR_AES_CBC:
770 /* we assume that we support all AES sizes */
771 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128);
772 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
773 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
774 break;
775 case ENCR_3DES:
776 case ENCR_AES_CTR:
777 case ENCR_AES_CCM_ICV8:
778 case ENCR_AES_CCM_ICV12:
779 case ENCR_AES_CCM_ICV16:
780 case ENCR_AES_GCM_ICV8:
781 case ENCR_AES_GCM_ICV12:
782 case ENCR_AES_GCM_ICV16:
783 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
784 break;
785 case ENCR_DES:
786 /* no, thanks */
787 break;
788 default:
789 break;
790 }
791 }
792 enumerator->destroy(enumerator);
793
794 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
795 while (enumerator->enumerate(enumerator, &integrity))
796 {
797 switch (integrity)
798 {
799 case AUTH_HMAC_SHA1_96:
800 case AUTH_HMAC_SHA2_256_128:
801 case AUTH_HMAC_SHA2_384_192:
802 case AUTH_HMAC_SHA2_512_256:
803 case AUTH_HMAC_MD5_96:
804 case AUTH_AES_XCBC_96:
805 add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
806 break;
807 default:
808 break;
809 }
810 }
811 enumerator->destroy(enumerator);
812
813 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
814 while (enumerator->enumerate(enumerator, &prf))
815 {
816 switch (prf)
817 {
818 case PRF_HMAC_SHA1:
819 case PRF_HMAC_SHA2_256:
820 case PRF_HMAC_SHA2_384:
821 case PRF_HMAC_SHA2_512:
822 case PRF_HMAC_MD5:
823 case PRF_AES128_XCBC:
824 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
825 break;
826 default:
827 break;
828 }
829 }
830 enumerator->destroy(enumerator);
831
832 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
833 while (enumerator->enumerate(enumerator, &group))
834 {
835 switch (group)
836 {
837 case MODP_NULL:
838 /* only for testing purposes */
839 break;
840 case MODP_768_BIT:
841 /* weak */
842 break;
843 case MODP_1024_BIT:
844 case MODP_1536_BIT:
845 case MODP_2048_BIT:
846 case MODP_4096_BIT:
847 case MODP_8192_BIT:
848 case ECP_256_BIT:
849 case ECP_384_BIT:
850 case ECP_521_BIT:
851 case ECP_192_BIT:
852 case ECP_224_BIT:
853 add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
854 break;
855 default:
856 break;
857 }
858 }
859 enumerator->destroy(enumerator);
860 }
861
862 /*
863 * Describtion in header-file
864 */
865 proposal_t *proposal_create_default(protocol_id_t protocol)
866 {
867 private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
868
869 switch (protocol)
870 {
871 case PROTO_IKE:
872 proposal_add_supported_ike(this);
873 break;
874 case PROTO_ESP:
875 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
876 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
877 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
878 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
879 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
880 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
881 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
882 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
883 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
884 break;
885 case PROTO_AH:
886 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
887 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
888 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
889 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
890 break;
891 default:
892 break;
893 }
894 return &this->public;
895 }
896
897 /*
898 * Describtion in header-file
899 */
900 proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
901 {
902 private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
903 chunk_t string = {(void*)algs, strlen(algs)};
904 chunk_t alg;
905 status_t status = SUCCESS;
906
907 eat_whitespace(&string);
908 if (string.len < 1)
909 {
910 destroy(this);
911 return NULL;
912 }
913
914 /* get all tokens, separated by '-' */
915 while (extract_token(&alg, '-', &string))
916 {
917 status |= add_string_algo(this, alg);
918 }
919 if (string.len)
920 {
921 status |= add_string_algo(this, string);
922 }
923 if (status != SUCCESS)
924 {
925 destroy(this);
926 return NULL;
927 }
928
929 check_proposal(this);
930
931 if (protocol == PROTO_AH || protocol == PROTO_ESP)
932 {
933 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
934 }
935 return &this->public;
936 }