implemented XCBC algorithms (signer, prf) for IKE on top of a crypter
[strongswan.git] / src / charon / config / proposal.c
1 /*
2 * Copyright (C) 2006 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include <string.h>
19
20 #include "proposal.h"
21
22 #include <daemon.h>
23 #include <utils/linked_list.h>
24 #include <utils/identification.h>
25 #include <utils/lexparser.h>
26 #include <crypto/prfs/prf.h>
27 #include <crypto/crypters/crypter.h>
28 #include <crypto/signers/signer.h>
29
30
31 ENUM(protocol_id_names, PROTO_NONE, PROTO_ESP,
32 "PROTO_NONE",
33 "IKE",
34 "AH",
35 "ESP",
36 );
37
38 ENUM_BEGIN(transform_type_names, UNDEFINED_TRANSFORM_TYPE, UNDEFINED_TRANSFORM_TYPE,
39 "UNDEFINED_TRANSFORM_TYPE");
40 ENUM_NEXT(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, UNDEFINED_TRANSFORM_TYPE,
41 "ENCRYPTION_ALGORITHM",
42 "PSEUDO_RANDOM_FUNCTION",
43 "INTEGRITY_ALGORITHM",
44 "DIFFIE_HELLMAN_GROUP",
45 "EXTENDED_SEQUENCE_NUMBERS");
46 ENUM_END(transform_type_names, EXTENDED_SEQUENCE_NUMBERS);
47
48 ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS,
49 "NO_EXT_SEQ_NUMBERS",
50 "EXT_SEQ_NUMBERS",
51 );
52
53 typedef struct private_proposal_t private_proposal_t;
54 typedef struct algorithm_t algorithm_t;
55
56 /**
57 * Private data of an proposal_t object
58 */
59 struct private_proposal_t {
60
61 /**
62 * Public part
63 */
64 proposal_t public;
65
66 /**
67 * protocol (ESP or AH)
68 */
69 protocol_id_t protocol;
70
71 /**
72 * priority ordered list of encryption algorithms
73 */
74 linked_list_t *encryption_algos;
75
76 /**
77 * priority ordered list of integrity algorithms
78 */
79 linked_list_t *integrity_algos;
80
81 /**
82 * priority ordered list of pseudo random functions
83 */
84 linked_list_t *prf_algos;
85
86 /**
87 * priority ordered list of dh groups
88 */
89 linked_list_t *dh_groups;
90
91 /**
92 * priority ordered list of extended sequence number flags
93 */
94 linked_list_t *esns;
95
96 /**
97 * senders SPI
98 */
99 u_int64_t spi;
100 };
101
102 /**
103 * Struct used to store different kinds of algorithms.
104 */
105 struct algorithm_t {
106 /**
107 * Value from an encryption_algorithm_t/integrity_algorithm_t/...
108 */
109 u_int16_t algorithm;
110
111 /**
112 * the associated key size in bits, or zero if not needed
113 */
114 u_int16_t key_size;
115 };
116
117 /**
118 * Add algorithm/keysize to a algorithm list
119 */
120 static void add_algo(linked_list_t *list, u_int16_t algo, u_int16_t key_size)
121 {
122 algorithm_t *algo_key;
123
124 algo_key = malloc_thing(algorithm_t);
125 algo_key->algorithm = algo;
126 algo_key->key_size = key_size;
127 list->insert_last(list, (void*)algo_key);
128 }
129
130 /**
131 * Implements proposal_t.add_algorithm
132 */
133 static void add_algorithm(private_proposal_t *this, transform_type_t type,
134 u_int16_t algo, u_int16_t key_size)
135 {
136 switch (type)
137 {
138 case ENCRYPTION_ALGORITHM:
139 add_algo(this->encryption_algos, algo, key_size);
140 break;
141 case INTEGRITY_ALGORITHM:
142 add_algo(this->integrity_algos, algo, key_size);
143 break;
144 case PSEUDO_RANDOM_FUNCTION:
145 add_algo(this->prf_algos, algo, key_size);
146 break;
147 case DIFFIE_HELLMAN_GROUP:
148 add_algo(this->dh_groups, algo, 0);
149 break;
150 case EXTENDED_SEQUENCE_NUMBERS:
151 add_algo(this->esns, algo, 0);
152 break;
153 default:
154 break;
155 }
156 }
157
158 /**
159 * filter function for peer configs
160 */
161 static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg,
162 void **unused, u_int16_t *key_size)
163 {
164 algorithm_t *algo = *in;
165 *alg = algo->algorithm;
166 if (key_size)
167 {
168 *key_size = algo->key_size;
169 }
170 return TRUE;
171 }
172
173 /**
174 * Implements proposal_t.create_enumerator.
175 */
176 static enumerator_t *create_enumerator(private_proposal_t *this,
177 transform_type_t type)
178 {
179 linked_list_t *list;
180
181 switch (type)
182 {
183 case ENCRYPTION_ALGORITHM:
184 list = this->encryption_algos;
185 break;
186 case INTEGRITY_ALGORITHM:
187 list = this->integrity_algos;
188 break;
189 case PSEUDO_RANDOM_FUNCTION:
190 list = this->prf_algos;
191 break;
192 case DIFFIE_HELLMAN_GROUP:
193 list = this->dh_groups;
194 break;
195 case EXTENDED_SEQUENCE_NUMBERS:
196 list = this->esns;
197 break;
198 default:
199 return NULL;
200 }
201 return enumerator_create_filter(list->create_enumerator(list),
202 (void*)alg_filter, NULL, NULL);
203 }
204
205 /**
206 * Implements proposal_t.get_algorithm.
207 */
208 static bool get_algorithm(private_proposal_t *this, transform_type_t type,
209 u_int16_t *alg, u_int16_t *key_size)
210 {
211 enumerator_t *enumerator;
212 bool found = FALSE;
213
214 enumerator = create_enumerator(this, type);
215 if (enumerator->enumerate(enumerator, alg, key_size))
216 {
217 found = TRUE;
218 }
219 enumerator->destroy(enumerator);
220 return found;
221 }
222
223 /**
224 * Implements proposal_t.has_dh_group
225 */
226 static bool has_dh_group(private_proposal_t *this, diffie_hellman_group_t group)
227 {
228 bool result = FALSE;
229
230 if (this->dh_groups->get_count(this->dh_groups))
231 {
232 algorithm_t *current;
233 enumerator_t *enumerator;
234
235 enumerator = this->dh_groups->create_enumerator(this->dh_groups);
236 while (enumerator->enumerate(enumerator, (void**)&current))
237 {
238 if (current->algorithm == group)
239 {
240 result = TRUE;
241 break;
242 }
243 }
244 enumerator->destroy(enumerator);
245 }
246 else if (group == MODP_NONE)
247 {
248 result = TRUE;
249 }
250 return result;
251 }
252
253 /**
254 * Implementation of proposal_t.strip_dh.
255 */
256 static void strip_dh(private_proposal_t *this)
257 {
258 algorithm_t *alg;
259
260 while (this->dh_groups->remove_last(this->dh_groups, (void**)&alg) == SUCCESS)
261 {
262 free(alg);
263 }
264 }
265
266 /**
267 * Find a matching alg/keysize in two linked lists
268 */
269 static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add,
270 u_int16_t *alg, size_t *key_size)
271 {
272 enumerator_t *e1, *e2;
273 algorithm_t *alg1, *alg2;
274
275 /* if in both are zero algorithms specified, we HAVE a match */
276 if (first->get_count(first) == 0 && second->get_count(second) == 0)
277 {
278 *add = FALSE;
279 return TRUE;
280 }
281
282 e1 = first->create_enumerator(first);
283 e2 = second->create_enumerator(second);
284 /* compare algs, order of algs in "first" is preferred */
285 while (e1->enumerate(e1, &alg1))
286 {
287 e2->destroy(e2);
288 e2 = second->create_enumerator(second);
289 while (e2->enumerate(e2, &alg2))
290 {
291 if (alg1->algorithm == alg2->algorithm &&
292 alg1->key_size == alg2->key_size)
293 {
294 /* ok, we have an algorithm */
295 *alg = alg1->algorithm;
296 *key_size = alg1->key_size;
297 *add = TRUE;
298 e1->destroy(e1);
299 e2->destroy(e2);
300 return TRUE;
301 }
302 }
303 }
304 /* no match in all comparisons */
305 e1->destroy(e1);
306 e2->destroy(e2);
307 return FALSE;
308 }
309
310 /**
311 * Implements proposal_t.select.
312 */
313 static proposal_t *select_proposal(private_proposal_t *this, private_proposal_t *other)
314 {
315 proposal_t *selected;
316 u_int16_t algo;
317 size_t key_size;
318 bool add;
319
320 DBG2(DBG_CFG, "selecting proposal:");
321
322 /* check protocol */
323 if (this->protocol != other->protocol)
324 {
325 DBG2(DBG_CFG, " protocol mismatch, skipping");
326 return NULL;
327 }
328
329 selected = proposal_create(this->protocol);
330
331 /* select encryption algorithm */
332 if (select_algo(this->encryption_algos, other->encryption_algos, &add, &algo, &key_size))
333 {
334 if (add)
335 {
336 selected->add_algorithm(selected, ENCRYPTION_ALGORITHM, algo, key_size);
337 }
338 }
339 else
340 {
341 selected->destroy(selected);
342 DBG2(DBG_CFG, " no acceptable ENCRYPTION_ALGORITHM found, skipping");
343 return NULL;
344 }
345 /* select integrity algorithm */
346 if (select_algo(this->integrity_algos, other->integrity_algos, &add, &algo, &key_size))
347 {
348 if (add)
349 {
350 selected->add_algorithm(selected, INTEGRITY_ALGORITHM, algo, key_size);
351 }
352 }
353 else
354 {
355 selected->destroy(selected);
356 DBG2(DBG_CFG, " no acceptable INTEGRITY_ALGORITHM found, skipping");
357 return NULL;
358 }
359 /* select prf algorithm */
360 if (select_algo(this->prf_algos, other->prf_algos, &add, &algo, &key_size))
361 {
362 if (add)
363 {
364 selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION, algo, key_size);
365 }
366 }
367 else
368 {
369 selected->destroy(selected);
370 DBG2(DBG_CFG, " no acceptable PSEUDO_RANDOM_FUNCTION found, skipping");
371 return NULL;
372 }
373 /* select a DH-group */
374 if (select_algo(this->dh_groups, other->dh_groups, &add, &algo, &key_size))
375 {
376 if (add)
377 {
378 selected->add_algorithm(selected, DIFFIE_HELLMAN_GROUP, algo, 0);
379 }
380 }
381 else
382 {
383 selected->destroy(selected);
384 DBG2(DBG_CFG, " no acceptable DIFFIE_HELLMAN_GROUP found, skipping");
385 return NULL;
386 }
387 /* select if we use ESNs */
388 if (select_algo(this->esns, other->esns, &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 EXTENDED_SEQUENCE_NUMBERS found, skipping");
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 /**
411 * Implements proposal_t.get_protocols.
412 */
413 static protocol_id_t get_protocol(private_proposal_t *this)
414 {
415 return this->protocol;
416 }
417
418 /**
419 * Implements proposal_t.set_spi.
420 */
421 static void set_spi(private_proposal_t *this, u_int64_t spi)
422 {
423 this->spi = spi;
424 }
425
426 /**
427 * Implements proposal_t.get_spi.
428 */
429 static u_int64_t get_spi(private_proposal_t *this)
430 {
431 return this->spi;
432 }
433
434 /**
435 * Clone a algorithm list
436 */
437 static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list)
438 {
439 algorithm_t *algo, *clone_algo;
440 enumerator_t *enumerator;
441
442 enumerator = list->create_enumerator(list);
443 while (enumerator->enumerate(enumerator, &algo))
444 {
445 clone_algo = malloc_thing(algorithm_t);
446 memcpy(clone_algo, algo, sizeof(algorithm_t));
447 clone_list->insert_last(clone_list, (void*)clone_algo);
448 }
449 enumerator->destroy(enumerator);
450 }
451
452 /**
453 * check if an algorithm list equals
454 */
455 static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2)
456 {
457 enumerator_t *e1, *e2;
458 algorithm_t *alg1, *alg2;
459 bool equals = TRUE;
460
461 if (l1->get_count(l1) != l2->get_count(l2))
462 {
463 return FALSE;
464 }
465
466 e1 = l1->create_enumerator(l1);
467 e2 = l2->create_enumerator(l2);
468 while (e1->enumerate(e1, &alg1) && e2->enumerate(e2, &alg2))
469 {
470 if (alg1->algorithm != alg2->algorithm ||
471 alg1->key_size != alg2->key_size)
472 {
473 equals = FALSE;
474 break;
475 }
476 }
477 e1->destroy(e1);
478 e2->destroy(e2);
479 return equals;
480 }
481
482 /**
483 * Implementation of proposal_t.equals.
484 */
485 static bool equals(private_proposal_t *this, private_proposal_t *other)
486 {
487 if (this == other)
488 {
489 return TRUE;
490 }
491 if (this->public.equals != other->public.equals)
492 {
493 return FALSE;
494 }
495 return (
496 algo_list_equals(this->encryption_algos, other->encryption_algos) &&
497 algo_list_equals(this->integrity_algos, other->integrity_algos) &&
498 algo_list_equals(this->prf_algos, other->prf_algos) &&
499 algo_list_equals(this->dh_groups, other->dh_groups) &&
500 algo_list_equals(this->esns, other->esns));
501 }
502
503 /**
504 * Implements proposal_t.clone
505 */
506 static proposal_t *clone_(private_proposal_t *this)
507 {
508 private_proposal_t *clone = (private_proposal_t*)proposal_create(this->protocol);
509
510 clone_algo_list(this->encryption_algos, clone->encryption_algos);
511 clone_algo_list(this->integrity_algos, clone->integrity_algos);
512 clone_algo_list(this->prf_algos, clone->prf_algos);
513 clone_algo_list(this->dh_groups, clone->dh_groups);
514 clone_algo_list(this->esns, clone->esns);
515
516 clone->spi = this->spi;
517
518 return &clone->public;
519 }
520
521 /**
522 * add a algorithm identified by a string to the proposal.
523 * TODO: we could use gperf here.
524 */
525 static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
526 {
527 if (strncmp(alg.ptr, "null", alg.len) == 0)
528 {
529 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_NULL, 0);
530 }
531 else if (strncmp(alg.ptr, "aes128", alg.len) == 0)
532 {
533 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
534 }
535 else if (strncmp(alg.ptr, "aes192", alg.len) == 0)
536 {
537 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
538 }
539 else if (strncmp(alg.ptr, "aes256", alg.len) == 0)
540 {
541 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
542 }
543 else if (strncmp(alg.ptr, "3des", alg.len) == 0)
544 {
545 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
546 }
547 /* blowfish only uses some predefined key sizes yet */
548 else if (strncmp(alg.ptr, "blowfish128", alg.len) == 0)
549 {
550 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128);
551 }
552 else if (strncmp(alg.ptr, "blowfish192", alg.len) == 0)
553 {
554 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192);
555 }
556 else if (strncmp(alg.ptr, "blowfish256", alg.len) == 0)
557 {
558 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
559 }
560 else if (strncmp(alg.ptr, "sha", alg.len) == 0 ||
561 strncmp(alg.ptr, "sha1", alg.len) == 0)
562 {
563 /* sha means we use SHA for both, PRF and AUTH */
564 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
565 if (this->protocol == PROTO_IKE)
566 {
567 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
568 }
569 }
570 else if (strncmp(alg.ptr, "sha256", alg.len) == 0 ||
571 strncmp(alg.ptr, "sha2_256", alg.len) == 0)
572 {
573 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0);
574 if (this->protocol == PROTO_IKE)
575 {
576 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_256, 0);
577 }
578 }
579 else if (strncmp(alg.ptr, "sha384", alg.len) == 0 ||
580 strncmp(alg.ptr, "sha2_384", alg.len) == 0)
581 {
582 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0);
583 if (this->protocol == PROTO_IKE)
584 {
585 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_384, 0);
586 }
587 }
588 else if (strncmp(alg.ptr, "sha512", alg.len) == 0 ||
589 strncmp(alg.ptr, "sha2_512", alg.len) == 0)
590 {
591 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0);
592 if (this->protocol == PROTO_IKE)
593 {
594 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_512, 0);
595 }
596 }
597 else if (strncmp(alg.ptr, "md5", alg.len) == 0)
598 {
599 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
600 if (this->protocol == PROTO_IKE)
601 {
602 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
603 }
604 }
605 else if (strncmp(alg.ptr, "aesxcbc", alg.len) == 0)
606 {
607 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
608 if (this->protocol == PROTO_IKE)
609 {
610 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_CBC, 0);
611 }
612 }
613 else if (strncmp(alg.ptr, "modp768", alg.len) == 0)
614 {
615 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0);
616 }
617 else if (strncmp(alg.ptr, "modp1024", alg.len) == 0)
618 {
619 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
620 }
621 else if (strncmp(alg.ptr, "modp1536", alg.len) == 0)
622 {
623 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0);
624 }
625 else if (strncmp(alg.ptr, "modp2048", alg.len) == 0)
626 {
627 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
628 }
629 else if (strncmp(alg.ptr, "modp4096", alg.len) == 0)
630 {
631 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0);
632 }
633 else if (strncmp(alg.ptr, "modp8192", alg.len) == 0)
634 {
635 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0);
636 }
637 else
638 {
639 return FAILED;
640 }
641 return SUCCESS;
642 }
643
644 /**
645 * Implements proposal_t.destroy.
646 */
647 static void destroy(private_proposal_t *this)
648 {
649 this->encryption_algos->destroy_function(this->encryption_algos, free);
650 this->integrity_algos->destroy_function(this->integrity_algos, free);
651 this->prf_algos->destroy_function(this->prf_algos, free);
652 this->dh_groups->destroy_function(this->dh_groups, free);
653 this->esns->destroy_function(this->esns, free);
654 free(this);
655 }
656
657 /*
658 * Describtion in header-file
659 */
660 proposal_t *proposal_create(protocol_id_t protocol)
661 {
662 private_proposal_t *this = malloc_thing(private_proposal_t);
663
664 this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,u_int16_t))add_algorithm;
665 this->public.create_enumerator = (enumerator_t* (*)(proposal_t*,transform_type_t))create_enumerator;
666 this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,u_int16_t*,u_int16_t*))get_algorithm;
667 this->public.has_dh_group = (bool (*)(proposal_t*,diffie_hellman_group_t))has_dh_group;
668 this->public.strip_dh = (void(*)(proposal_t*))strip_dh;
669 this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal;
670 this->public.get_protocol = (protocol_id_t(*)(proposal_t*))get_protocol;
671 this->public.set_spi = (void(*)(proposal_t*,u_int64_t))set_spi;
672 this->public.get_spi = (u_int64_t(*)(proposal_t*))get_spi;
673 this->public.equals = (bool(*)(proposal_t*, proposal_t *other))equals;
674 this->public.clone = (proposal_t*(*)(proposal_t*))clone_;
675 this->public.destroy = (void(*)(proposal_t*))destroy;
676
677 this->spi = 0;
678 this->protocol = protocol;
679
680 this->encryption_algos = linked_list_create();
681 this->integrity_algos = linked_list_create();
682 this->prf_algos = linked_list_create();
683 this->dh_groups = linked_list_create();
684 this->esns = linked_list_create();
685
686 return &this->public;
687 }
688
689 /*
690 * Describtion in header-file
691 */
692 proposal_t *proposal_create_default(protocol_id_t protocol)
693 {
694 private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
695
696 switch (protocol)
697 {
698 case PROTO_IKE:
699 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
700 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
701 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
702 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
703 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
704 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0);
705 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
706 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
707 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0);
708 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0);
709 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_CBC, 0);
710 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_256, 0);
711 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
712 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
713 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_384, 0);
714 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_512, 0);
715 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
716 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0);
717 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
718 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0);
719 add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0);
720 break;
721 case PROTO_ESP:
722 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
723 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
724 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
725 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
726 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256);
727 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
728 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
729 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
730 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
731 break;
732 case PROTO_AH:
733 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
734 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
735 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
736 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
737 break;
738 default:
739 break;
740 }
741
742 return &this->public;
743 }
744
745 /*
746 * Describtion in header-file
747 */
748 proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
749 {
750 private_proposal_t *this = (private_proposal_t*)proposal_create(protocol);
751 chunk_t string = {(void*)algs, strlen(algs)};
752 chunk_t alg;
753 status_t status = SUCCESS;
754
755 eat_whitespace(&string);
756 if (string.len < 1)
757 {
758 destroy(this);
759 return NULL;
760 }
761
762 /* get all tokens, separated by '-' */
763 while (extract_token(&alg, '-', &string))
764 {
765 status |= add_string_algo(this, alg);
766 }
767 if (string.len)
768 {
769 status |= add_string_algo(this, string);
770 }
771 if (status != SUCCESS)
772 {
773 destroy(this);
774 return NULL;
775 }
776
777 if (protocol == PROTO_AH || protocol == PROTO_ESP)
778 {
779 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
780 }
781 return &this->public;
782 }