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