2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
24 #include <utils/linked_list.h>
25 #include <utils/identification.h>
26 #include <utils/lexparser.h>
27 #include <crypto/prfs/prf.h>
28 #include <crypto/crypters/crypter.h>
29 #include <crypto/signers/signer.h>
32 ENUM(protocol_id_names
, PROTO_NONE
, PROTO_ESP
,
39 ENUM_BEGIN(transform_type_names
, UNDEFINED_TRANSFORM_TYPE
, UNDEFINED_TRANSFORM_TYPE
,
40 "UNDEFINED_TRANSFORM_TYPE");
41 ENUM_NEXT(transform_type_names
, ENCRYPTION_ALGORITHM
, EXTENDED_SEQUENCE_NUMBERS
, UNDEFINED_TRANSFORM_TYPE
,
42 "ENCRYPTION_ALGORITHM",
43 "PSEUDO_RANDOM_FUNCTION",
44 "INTEGRITY_ALGORITHM",
45 "DIFFIE_HELLMAN_GROUP",
46 "EXTENDED_SEQUENCE_NUMBERS");
47 ENUM_END(transform_type_names
, EXTENDED_SEQUENCE_NUMBERS
);
49 ENUM(extended_sequence_numbers_names
, NO_EXT_SEQ_NUMBERS
, EXT_SEQ_NUMBERS
,
54 typedef struct private_proposal_t private_proposal_t
;
55 typedef struct algorithm_t algorithm_t
;
58 * Private data of an proposal_t object
60 struct private_proposal_t
{
68 * protocol (ESP or AH)
70 protocol_id_t protocol
;
73 * priority ordered list of encryption algorithms
75 linked_list_t
*encryption_algos
;
78 * priority ordered list of integrity algorithms
80 linked_list_t
*integrity_algos
;
83 * priority ordered list of pseudo random functions
85 linked_list_t
*prf_algos
;
88 * priority ordered list of dh groups
90 linked_list_t
*dh_groups
;
93 * priority ordered list of extended sequence number flags
104 * Struct used to store different kinds of algorithms.
108 * Value from an encryption_algorithm_t/integrity_algorithm_t/...
113 * the associated key size in bits, or zero if not needed
119 * Add algorithm/keysize to a algorithm list
121 static void add_algo(linked_list_t
*list
, u_int16_t algo
, u_int16_t key_size
)
123 algorithm_t
*algo_key
;
125 algo_key
= malloc_thing(algorithm_t
);
126 algo_key
->algorithm
= algo
;
127 algo_key
->key_size
= key_size
;
128 list
->insert_last(list
, (void*)algo_key
);
132 * Implements proposal_t.add_algorithm
134 static void add_algorithm(private_proposal_t
*this, transform_type_t type
,
135 u_int16_t algo
, u_int16_t key_size
)
139 case ENCRYPTION_ALGORITHM
:
140 add_algo(this->encryption_algos
, algo
, key_size
);
142 case INTEGRITY_ALGORITHM
:
143 add_algo(this->integrity_algos
, algo
, key_size
);
145 case PSEUDO_RANDOM_FUNCTION
:
146 add_algo(this->prf_algos
, algo
, key_size
);
148 case DIFFIE_HELLMAN_GROUP
:
149 add_algo(this->dh_groups
, algo
, 0);
151 case EXTENDED_SEQUENCE_NUMBERS
:
152 add_algo(this->esns
, algo
, 0);
160 * filter function for peer configs
162 static bool alg_filter(void *null
, algorithm_t
**in
, u_int16_t
*alg
,
163 void **unused
, u_int16_t
*key_size
)
165 algorithm_t
*algo
= *in
;
166 *alg
= algo
->algorithm
;
169 *key_size
= algo
->key_size
;
175 * Implements proposal_t.create_enumerator.
177 static enumerator_t
*create_enumerator(private_proposal_t
*this,
178 transform_type_t type
)
184 case ENCRYPTION_ALGORITHM
:
185 list
= this->encryption_algos
;
187 case INTEGRITY_ALGORITHM
:
188 list
= this->integrity_algos
;
190 case PSEUDO_RANDOM_FUNCTION
:
191 list
= this->prf_algos
;
193 case DIFFIE_HELLMAN_GROUP
:
194 list
= this->dh_groups
;
196 case EXTENDED_SEQUENCE_NUMBERS
:
202 return enumerator_create_filter(list
->create_enumerator(list
),
203 (void*)alg_filter
, NULL
, NULL
);
207 * Implements proposal_t.get_algorithm.
209 static bool get_algorithm(private_proposal_t
*this, transform_type_t type
,
210 u_int16_t
*alg
, u_int16_t
*key_size
)
212 enumerator_t
*enumerator
;
215 enumerator
= create_enumerator(this, type
);
216 if (enumerator
->enumerate(enumerator
, alg
, key_size
))
220 enumerator
->destroy(enumerator
);
225 * Implements proposal_t.has_dh_group
227 static bool has_dh_group(private_proposal_t
*this, diffie_hellman_group_t group
)
231 if (this->dh_groups
->get_count(this->dh_groups
))
233 algorithm_t
*current
;
234 enumerator_t
*enumerator
;
236 enumerator
= this->dh_groups
->create_enumerator(this->dh_groups
);
237 while (enumerator
->enumerate(enumerator
, (void**)¤t
))
239 if (current
->algorithm
== group
)
245 enumerator
->destroy(enumerator
);
247 else if (group
== MODP_NONE
)
255 * Implementation of proposal_t.strip_dh.
257 static void strip_dh(private_proposal_t
*this)
261 while (this->dh_groups
->remove_last(this->dh_groups
, (void**)&alg
) == SUCCESS
)
268 * Returns true if the given alg is an authenticated encryption algorithm
270 static bool is_authenticated_encryption(u_int16_t alg
)
274 case ENCR_AES_CCM_ICV8
:
275 case ENCR_AES_CCM_ICV12
:
276 case ENCR_AES_CCM_ICV16
:
277 case ENCR_AES_GCM_ICV8
:
278 case ENCR_AES_GCM_ICV12
:
279 case ENCR_AES_GCM_ICV16
:
286 * Find a matching alg/keysize in two linked lists
288 static bool select_algo(linked_list_t
*first
, linked_list_t
*second
, bool *add
,
289 u_int16_t
*alg
, size_t *key_size
)
291 enumerator_t
*e1
, *e2
;
292 algorithm_t
*alg1
, *alg2
;
294 /* if in both are zero algorithms specified, we HAVE a match */
295 if (first
->get_count(first
) == 0 && second
->get_count(second
) == 0)
301 e1
= first
->create_enumerator(first
);
302 e2
= second
->create_enumerator(second
);
303 /* compare algs, order of algs in "first" is preferred */
304 while (e1
->enumerate(e1
, &alg1
))
307 e2
= second
->create_enumerator(second
);
308 while (e2
->enumerate(e2
, &alg2
))
310 if (alg1
->algorithm
== alg2
->algorithm
&&
311 alg1
->key_size
== alg2
->key_size
)
313 /* ok, we have an algorithm */
314 *alg
= alg1
->algorithm
;
315 *key_size
= alg1
->key_size
;
323 /* no match in all comparisons */
330 * Implements proposal_t.select.
332 static proposal_t
*select_proposal(private_proposal_t
*this, private_proposal_t
*other
)
334 proposal_t
*selected
;
339 DBG2(DBG_CFG
, "selecting proposal:");
342 if (this->protocol
!= other
->protocol
)
344 DBG2(DBG_CFG
, " protocol mismatch, skipping");
348 selected
= proposal_create(this->protocol
);
350 /* select encryption algorithm */
351 if (select_algo(this->encryption_algos
, other
->encryption_algos
,
352 &add
, &algo
, &key_size
))
356 selected
->add_algorithm(selected
, ENCRYPTION_ALGORITHM
,
362 selected
->destroy(selected
);
363 DBG2(DBG_CFG
, " no acceptable %N found",
364 transform_type_names
, ENCRYPTION_ALGORITHM
);
367 /* select integrity algorithm */
368 if (!is_authenticated_encryption(algo
))
370 if (select_algo(this->integrity_algos
, other
->integrity_algos
,
371 &add
, &algo
, &key_size
))
375 selected
->add_algorithm(selected
, INTEGRITY_ALGORITHM
,
381 selected
->destroy(selected
);
382 DBG2(DBG_CFG
, " no acceptable %N found",
383 transform_type_names
, INTEGRITY_ALGORITHM
);
387 /* select prf algorithm */
388 if (select_algo(this->prf_algos
, other
->prf_algos
,
389 &add
, &algo
, &key_size
))
393 selected
->add_algorithm(selected
, PSEUDO_RANDOM_FUNCTION
,
399 selected
->destroy(selected
);
400 DBG2(DBG_CFG
, " no acceptable %N found",
401 transform_type_names
, PSEUDO_RANDOM_FUNCTION
);
404 /* select a DH-group */
405 if (select_algo(this->dh_groups
, other
->dh_groups
, &add
, &algo
, &key_size
))
409 selected
->add_algorithm(selected
, DIFFIE_HELLMAN_GROUP
, algo
, 0);
414 selected
->destroy(selected
);
415 DBG2(DBG_CFG
, " no acceptable %N found",
416 transform_type_names
, DIFFIE_HELLMAN_GROUP
);
419 /* select if we use ESNs */
420 if (select_algo(this->esns
, other
->esns
, &add
, &algo
, &key_size
))
424 selected
->add_algorithm(selected
, EXTENDED_SEQUENCE_NUMBERS
, algo
, 0);
429 selected
->destroy(selected
);
430 DBG2(DBG_CFG
, " no acceptable %N found",
431 transform_type_names
, EXTENDED_SEQUENCE_NUMBERS
);
434 DBG2(DBG_CFG
, " proposal matches");
436 /* apply SPI from "other" */
437 selected
->set_spi(selected
, other
->spi
);
439 /* everything matched, return new proposal */
444 * Implements proposal_t.get_protocols.
446 static protocol_id_t
get_protocol(private_proposal_t
*this)
448 return this->protocol
;
452 * Implements proposal_t.set_spi.
454 static void set_spi(private_proposal_t
*this, u_int64_t spi
)
460 * Implements proposal_t.get_spi.
462 static u_int64_t
get_spi(private_proposal_t
*this)
468 * Clone a algorithm list
470 static void clone_algo_list(linked_list_t
*list
, linked_list_t
*clone_list
)
472 algorithm_t
*algo
, *clone_algo
;
473 enumerator_t
*enumerator
;
475 enumerator
= list
->create_enumerator(list
);
476 while (enumerator
->enumerate(enumerator
, &algo
))
478 clone_algo
= malloc_thing(algorithm_t
);
479 memcpy(clone_algo
, algo
, sizeof(algorithm_t
));
480 clone_list
->insert_last(clone_list
, (void*)clone_algo
);
482 enumerator
->destroy(enumerator
);
486 * check if an algorithm list equals
488 static bool algo_list_equals(linked_list_t
*l1
, linked_list_t
*l2
)
490 enumerator_t
*e1
, *e2
;
491 algorithm_t
*alg1
, *alg2
;
494 if (l1
->get_count(l1
) != l2
->get_count(l2
))
499 e1
= l1
->create_enumerator(l1
);
500 e2
= l2
->create_enumerator(l2
);
501 while (e1
->enumerate(e1
, &alg1
) && e2
->enumerate(e2
, &alg2
))
503 if (alg1
->algorithm
!= alg2
->algorithm
||
504 alg1
->key_size
!= alg2
->key_size
)
516 * Implementation of proposal_t.equals.
518 static bool equals(private_proposal_t
*this, private_proposal_t
*other
)
524 if (this->public.equals
!= other
->public.equals
)
529 algo_list_equals(this->encryption_algos
, other
->encryption_algos
) &&
530 algo_list_equals(this->integrity_algos
, other
->integrity_algos
) &&
531 algo_list_equals(this->prf_algos
, other
->prf_algos
) &&
532 algo_list_equals(this->dh_groups
, other
->dh_groups
) &&
533 algo_list_equals(this->esns
, other
->esns
));
537 * Implements proposal_t.clone
539 static proposal_t
*clone_(private_proposal_t
*this)
541 private_proposal_t
*clone
= (private_proposal_t
*)proposal_create(this->protocol
);
543 clone_algo_list(this->encryption_algos
, clone
->encryption_algos
);
544 clone_algo_list(this->integrity_algos
, clone
->integrity_algos
);
545 clone_algo_list(this->prf_algos
, clone
->prf_algos
);
546 clone_algo_list(this->dh_groups
, clone
->dh_groups
);
547 clone_algo_list(this->esns
, clone
->esns
);
549 clone
->spi
= this->spi
;
551 return &clone
->public;
555 * Checks the proposal read from a string.
557 static void check_proposal(private_proposal_t
*this)
561 bool all_aead
= TRUE
;
563 e
= this->encryption_algos
->create_enumerator(this->encryption_algos
);
564 while (e
->enumerate(e
, &alg
))
566 if (!is_authenticated_encryption(alg
->algorithm
))
576 /* if all encryption algorithms in the proposal are authenticated encryption
577 * algorithms we MUST NOT propose any integrity algorithms */
578 while (this->integrity_algos
->remove_last(this->integrity_algos
,
579 (void**)&alg
) == SUCCESS
)
587 * add a algorithm identified by a string to the proposal.
588 * TODO: we could use gperf here.
590 static status_t
add_string_algo(private_proposal_t
*this, chunk_t alg
)
592 if (strncmp(alg
.ptr
, "null", alg
.len
) == 0)
594 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_NULL
, 0);
596 else if (strncmp(alg
.ptr
, "aes128", alg
.len
) == 0)
598 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_AES_CBC
, 128);
600 else if (strncmp(alg
.ptr
, "aes192", alg
.len
) == 0)
602 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_AES_CBC
, 192);
604 else if (strncmp(alg
.ptr
, "aes256", alg
.len
) == 0)
606 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_AES_CBC
, 256);
608 else if (strstr(alg
.ptr
, "ccm"))
610 u_int16_t key_size
, icv_size
;
612 if (sscanf(alg
.ptr
, "aes%huccm%hu", &key_size
, &icv_size
) == 2)
614 if (key_size
== 128 || key_size
== 192 || key_size
== 256)
620 add_algorithm(this, ENCRYPTION_ALGORITHM
,
621 ENCR_AES_CCM_ICV8
, key_size
);
623 case 12: /* octets */
625 add_algorithm(this, ENCRYPTION_ALGORITHM
,
626 ENCR_AES_CCM_ICV12
, key_size
);
628 case 16: /* octets */
630 add_algorithm(this, ENCRYPTION_ALGORITHM
,
631 ENCR_AES_CCM_ICV16
, key_size
);
634 /* invalid ICV size */
640 else if (strstr(alg
.ptr
, "gcm"))
642 u_int16_t key_size
, icv_size
;
644 if (sscanf(alg
.ptr
, "aes%hugcm%hu", &key_size
, &icv_size
) == 2)
646 if (key_size
== 128 || key_size
== 192 || key_size
== 256)
652 add_algorithm(this, ENCRYPTION_ALGORITHM
,
653 ENCR_AES_GCM_ICV8
, key_size
);
655 case 12: /* octets */
657 add_algorithm(this, ENCRYPTION_ALGORITHM
,
658 ENCR_AES_GCM_ICV12
, key_size
);
660 case 16: /* octets */
662 add_algorithm(this, ENCRYPTION_ALGORITHM
,
663 ENCR_AES_GCM_ICV16
, key_size
);
666 /* invalid ICV size */
672 else if (strncmp(alg
.ptr
, "3des", alg
.len
) == 0)
674 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_3DES
, 0);
676 /* blowfish only uses some predefined key sizes yet */
677 else if (strncmp(alg
.ptr
, "blowfish128", alg
.len
) == 0)
679 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_BLOWFISH
, 128);
681 else if (strncmp(alg
.ptr
, "blowfish192", alg
.len
) == 0)
683 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_BLOWFISH
, 192);
685 else if (strncmp(alg
.ptr
, "blowfish256", alg
.len
) == 0)
687 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_BLOWFISH
, 256);
689 else if (strncmp(alg
.ptr
, "sha", alg
.len
) == 0 ||
690 strncmp(alg
.ptr
, "sha1", alg
.len
) == 0)
692 /* sha means we use SHA for both, PRF and AUTH */
693 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_SHA1_96
, 0);
694 if (this->protocol
== PROTO_IKE
)
696 add_algorithm(this, PSEUDO_RANDOM_FUNCTION
, PRF_HMAC_SHA1
, 0);
699 else if (strncmp(alg
.ptr
, "sha256", alg
.len
) == 0 ||
700 strncmp(alg
.ptr
, "sha2_256", alg
.len
) == 0)
702 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_SHA2_256_128
, 0);
703 if (this->protocol
== PROTO_IKE
)
705 add_algorithm(this, PSEUDO_RANDOM_FUNCTION
, PRF_HMAC_SHA2_256
, 0);
708 else if (strncmp(alg
.ptr
, "sha384", alg
.len
) == 0 ||
709 strncmp(alg
.ptr
, "sha2_384", alg
.len
) == 0)
711 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_SHA2_384_192
, 0);
712 if (this->protocol
== PROTO_IKE
)
714 add_algorithm(this, PSEUDO_RANDOM_FUNCTION
, PRF_HMAC_SHA2_384
, 0);
717 else if (strncmp(alg
.ptr
, "sha512", alg
.len
) == 0 ||
718 strncmp(alg
.ptr
, "sha2_512", alg
.len
) == 0)
720 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_SHA2_512_256
, 0);
721 if (this->protocol
== PROTO_IKE
)
723 add_algorithm(this, PSEUDO_RANDOM_FUNCTION
, PRF_HMAC_SHA2_512
, 0);
726 else if (strncmp(alg
.ptr
, "md5", alg
.len
) == 0)
728 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_MD5_96
, 0);
729 if (this->protocol
== PROTO_IKE
)
731 add_algorithm(this, PSEUDO_RANDOM_FUNCTION
, PRF_HMAC_MD5
, 0);
734 else if (strncmp(alg
.ptr
, "aesxcbc", alg
.len
) == 0)
736 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_AES_XCBC_96
, 0);
737 if (this->protocol
== PROTO_IKE
)
739 add_algorithm(this, PSEUDO_RANDOM_FUNCTION
, PRF_AES128_XCBC
, 0);
742 else if (strncmp(alg
.ptr
, "modp768", alg
.len
) == 0)
744 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, MODP_768_BIT
, 0);
746 else if (strncmp(alg
.ptr
, "modp1024", alg
.len
) == 0)
748 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, MODP_1024_BIT
, 0);
750 else if (strncmp(alg
.ptr
, "modp1536", alg
.len
) == 0)
752 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, MODP_1536_BIT
, 0);
754 else if (strncmp(alg
.ptr
, "modp2048", alg
.len
) == 0)
756 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, MODP_2048_BIT
, 0);
758 else if (strncmp(alg
.ptr
, "modp3072", alg
.len
) == 0)
760 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, MODP_3072_BIT
, 0);
762 else if (strncmp(alg
.ptr
, "modp4096", alg
.len
) == 0)
764 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, MODP_4096_BIT
, 0);
766 else if (strncmp(alg
.ptr
, "modp6144", alg
.len
) == 0)
768 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, MODP_6144_BIT
, 0);
770 else if (strncmp(alg
.ptr
, "modp8192", alg
.len
) == 0)
772 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, MODP_8192_BIT
, 0);
774 else if (strncmp(alg
.ptr
, "ecp192", alg
.len
) == 0)
776 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, ECP_192_BIT
, 0);
778 else if (strncmp(alg
.ptr
, "ecp224", alg
.len
) == 0)
780 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, ECP_224_BIT
, 0);
782 else if (strncmp(alg
.ptr
, "ecp256", alg
.len
) == 0)
784 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, ECP_256_BIT
, 0);
786 else if (strncmp(alg
.ptr
, "ecp384", alg
.len
) == 0)
788 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, ECP_384_BIT
, 0);
790 else if (strncmp(alg
.ptr
, "ecp521", alg
.len
) == 0)
792 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, ECP_521_BIT
, 0);
802 * print all algorithms of a kind to stream
804 static int print_alg(private_proposal_t
*this, FILE *stream
, u_int kind
,
805 void *names
, bool *first
)
807 enumerator_t
*enumerator
;
811 enumerator
= create_enumerator(this, kind
);
812 while (enumerator
->enumerate(enumerator
, &alg
, &size
))
816 written
+= fprintf(stream
, "%N", names
, alg
);
821 written
+= fprintf(stream
, "/%N", names
, alg
);
825 written
+= fprintf(stream
, "-%d", size
);
828 enumerator
->destroy(enumerator
);
833 * output handler in printf()
835 static int print(FILE *stream
, const struct printf_info
*info
,
836 const void *const *args
)
838 private_proposal_t
*this = *((private_proposal_t
**)(args
[0]));
839 linked_list_t
*list
= *((linked_list_t
**)(args
[0]));
840 enumerator_t
*enumerator
;
846 return fprintf(stream
, "(null)");
851 enumerator
= list
->create_enumerator(list
);
852 while (enumerator
->enumerate(enumerator
, &this))
853 { /* call recursivly */
856 written
+= fprintf(stream
, "%P", this);
861 written
+= fprintf(stream
, ", %P", this);
864 enumerator
->destroy(enumerator
);
868 written
= fprintf(stream
, "%N:", protocol_id_names
, this->protocol
);
869 written
+= print_alg(this, stream
, ENCRYPTION_ALGORITHM
,
870 encryption_algorithm_names
, &first
);
871 written
+= print_alg(this, stream
, INTEGRITY_ALGORITHM
,
872 integrity_algorithm_names
, &first
);
873 written
+= print_alg(this, stream
, PSEUDO_RANDOM_FUNCTION
,
874 pseudo_random_function_names
, &first
);
875 written
+= print_alg(this, stream
, DIFFIE_HELLMAN_GROUP
,
876 diffie_hellman_group_names
, &first
);
877 written
+= print_alg(this, stream
, EXTENDED_SEQUENCE_NUMBERS
,
878 extended_sequence_numbers_names
, &first
);
883 * arginfo handler for printf() proposal
885 static int arginfo(const struct printf_info
*info
, size_t n
, int *argtypes
)
889 argtypes
[0] = PA_POINTER
;
895 * return printf hook functions for a proposal
897 printf_hook_functions_t
proposal_get_printf_hooks()
899 printf_hook_functions_t hooks
= {print
, arginfo
};
905 * Implements proposal_t.destroy.
907 static void destroy(private_proposal_t
*this)
909 this->encryption_algos
->destroy_function(this->encryption_algos
, free
);
910 this->integrity_algos
->destroy_function(this->integrity_algos
, free
);
911 this->prf_algos
->destroy_function(this->prf_algos
, free
);
912 this->dh_groups
->destroy_function(this->dh_groups
, free
);
913 this->esns
->destroy_function(this->esns
, free
);
918 * Describtion in header-file
920 proposal_t
*proposal_create(protocol_id_t protocol
)
922 private_proposal_t
*this = malloc_thing(private_proposal_t
);
924 this->public.add_algorithm
= (void (*)(proposal_t
*,transform_type_t
,u_int16_t
,u_int16_t
))add_algorithm
;
925 this->public.create_enumerator
= (enumerator_t
* (*)(proposal_t
*,transform_type_t
))create_enumerator
;
926 this->public.get_algorithm
= (bool (*)(proposal_t
*,transform_type_t
,u_int16_t
*,u_int16_t
*))get_algorithm
;
927 this->public.has_dh_group
= (bool (*)(proposal_t
*,diffie_hellman_group_t
))has_dh_group
;
928 this->public.strip_dh
= (void(*)(proposal_t
*))strip_dh
;
929 this->public.select
= (proposal_t
* (*)(proposal_t
*,proposal_t
*))select_proposal
;
930 this->public.get_protocol
= (protocol_id_t(*)(proposal_t
*))get_protocol
;
931 this->public.set_spi
= (void(*)(proposal_t
*,u_int64_t
))set_spi
;
932 this->public.get_spi
= (u_int64_t(*)(proposal_t
*))get_spi
;
933 this->public.equals
= (bool(*)(proposal_t
*, proposal_t
*other
))equals
;
934 this->public.clone
= (proposal_t
*(*)(proposal_t
*))clone_
;
935 this->public.destroy
= (void(*)(proposal_t
*))destroy
;
938 this->protocol
= protocol
;
940 this->encryption_algos
= linked_list_create();
941 this->integrity_algos
= linked_list_create();
942 this->prf_algos
= linked_list_create();
943 this->dh_groups
= linked_list_create();
944 this->esns
= linked_list_create();
946 return &this->public;
950 * Add supported IKE algorithms to proposal
952 static void proposal_add_supported_ike(private_proposal_t
*this)
954 enumerator_t
*enumerator
;
955 encryption_algorithm_t encryption
;
956 integrity_algorithm_t integrity
;
957 pseudo_random_function_t prf
;
958 diffie_hellman_group_t group
;
960 enumerator
= lib
->crypto
->create_crypter_enumerator(lib
->crypto
);
961 while (enumerator
->enumerate(enumerator
, &encryption
))
966 /* we assume that we support all AES sizes */
967 add_algorithm(this, ENCRYPTION_ALGORITHM
, encryption
, 128);
968 add_algorithm(this, ENCRYPTION_ALGORITHM
, encryption
, 192);
969 add_algorithm(this, ENCRYPTION_ALGORITHM
, encryption
, 256);
973 case ENCR_AES_CCM_ICV8
:
974 case ENCR_AES_CCM_ICV12
:
975 case ENCR_AES_CCM_ICV16
:
976 case ENCR_AES_GCM_ICV8
:
977 case ENCR_AES_GCM_ICV12
:
978 case ENCR_AES_GCM_ICV16
:
979 add_algorithm(this, ENCRYPTION_ALGORITHM
, encryption
, 0);
988 enumerator
->destroy(enumerator
);
990 enumerator
= lib
->crypto
->create_signer_enumerator(lib
->crypto
);
991 while (enumerator
->enumerate(enumerator
, &integrity
))
995 case AUTH_HMAC_SHA1_96
:
996 case AUTH_HMAC_SHA2_256_128
:
997 case AUTH_HMAC_SHA2_384_192
:
998 case AUTH_HMAC_SHA2_512_256
:
999 case AUTH_HMAC_MD5_96
:
1000 case AUTH_AES_XCBC_96
:
1001 add_algorithm(this, INTEGRITY_ALGORITHM
, integrity
, 0);
1007 enumerator
->destroy(enumerator
);
1009 enumerator
= lib
->crypto
->create_prf_enumerator(lib
->crypto
);
1010 while (enumerator
->enumerate(enumerator
, &prf
))
1015 case PRF_HMAC_SHA2_256
:
1016 case PRF_HMAC_SHA2_384
:
1017 case PRF_HMAC_SHA2_512
:
1019 case PRF_AES128_XCBC
:
1020 add_algorithm(this, PSEUDO_RANDOM_FUNCTION
, prf
, 0);
1026 enumerator
->destroy(enumerator
);
1028 enumerator
= lib
->crypto
->create_dh_enumerator(lib
->crypto
);
1029 while (enumerator
->enumerate(enumerator
, &group
))
1046 add_algorithm(this, DIFFIE_HELLMAN_GROUP
, group
, 0);
1052 enumerator
->destroy(enumerator
);
1056 * Describtion in header-file
1058 proposal_t
*proposal_create_default(protocol_id_t protocol
)
1060 private_proposal_t
*this = (private_proposal_t
*)proposal_create(protocol
);
1065 proposal_add_supported_ike(this);
1068 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_AES_CBC
, 128);
1069 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_AES_CBC
, 192);
1070 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_AES_CBC
, 256);
1071 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_3DES
, 0);
1072 add_algorithm(this, ENCRYPTION_ALGORITHM
, ENCR_BLOWFISH
, 256);
1073 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_SHA1_96
, 0);
1074 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_AES_XCBC_96
, 0);
1075 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_MD5_96
, 0);
1076 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS
, NO_EXT_SEQ_NUMBERS
, 0);
1079 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_SHA1_96
, 0);
1080 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_AES_XCBC_96
, 0);
1081 add_algorithm(this, INTEGRITY_ALGORITHM
, AUTH_HMAC_MD5_96
, 0);
1082 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS
, NO_EXT_SEQ_NUMBERS
, 0);
1087 return &this->public;
1091 * Describtion in header-file
1093 proposal_t
*proposal_create_from_string(protocol_id_t protocol
, const char *algs
)
1095 private_proposal_t
*this = (private_proposal_t
*)proposal_create(protocol
);
1096 chunk_t string
= {(void*)algs
, strlen(algs
)};
1098 status_t status
= SUCCESS
;
1100 eat_whitespace(&string
);
1107 /* get all tokens, separated by '-' */
1108 while (extract_token(&alg
, '-', &string
))
1110 status
|= add_string_algo(this, alg
);
1114 status
|= add_string_algo(this, string
);
1116 if (status
!= SUCCESS
)
1122 check_proposal(this);
1124 if (protocol
== PROTO_AH
|| protocol
== PROTO_ESP
)
1126 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS
, NO_EXT_SEQ_NUMBERS
, 0);
1128 return &this->public;