diff options
Diffstat (limited to 'src/libcharon/config')
-rw-r--r-- | src/libcharon/config/child_cfg.c | 8 | ||||
-rw-r--r-- | src/libcharon/config/child_cfg.h | 2 | ||||
-rw-r--r-- | src/libcharon/config/ike_cfg.h | 4 | ||||
-rw-r--r-- | src/libcharon/config/peer_cfg.h | 2 | ||||
-rw-r--r-- | src/libcharon/config/proposal.c | 1103 | ||||
-rw-r--r-- | src/libcharon/config/proposal.h | 237 |
6 files changed, 11 insertions, 1345 deletions
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index ec2a12431..3d110e9a2 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -224,6 +224,10 @@ METHOD(child_cfg_t, select_proposal, proposal_t*, while (prefer_enum->enumerate(prefer_enum, &proposal)) { proposal = proposal->clone(proposal); + if (strip_dh) + { + proposal->strip_dh(proposal, MODP_NONE); + } if (prefer_self) { proposals->reset_enumerator(proposals, match_enum); @@ -234,11 +238,13 @@ METHOD(child_cfg_t, select_proposal, proposal_t*, } while (match_enum->enumerate(match_enum, &match)) { + match = match->clone(match); if (strip_dh) { - proposal->strip_dh(proposal, MODP_NONE); + match->strip_dh(match, MODP_NONE); } selected = proposal->select(proposal, match, prefer_self, private); + match->destroy(match); if (selected) { DBG2(DBG_CFG, "received proposals: %#P", proposals); diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h index 93904ec71..e2834fa8f 100644 --- a/src/libcharon/config/child_cfg.h +++ b/src/libcharon/config/child_cfg.h @@ -31,7 +31,7 @@ typedef struct child_cfg_create_t child_cfg_create_t; #include <library.h> #include <selectors/traffic_selector.h> -#include <config/proposal.h> +#include <crypto/proposal/proposal.h> #include <kernel/kernel_ipsec.h> /** diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h index 034996f60..81f2b6906 100644 --- a/src/libcharon/config/ike_cfg.h +++ b/src/libcharon/config/ike_cfg.h @@ -31,7 +31,7 @@ typedef struct ike_cfg_t ike_cfg_t; #include <networking/host.h> #include <collections/linked_list.h> #include <utils/identification.h> -#include <config/proposal.h> +#include <crypto/proposal/proposal.h> #include <crypto/diffie_hellman.h> /** @@ -61,7 +61,7 @@ enum fragmentation_t { }; /** - * enum strings fro ike_version_t + * enum strings for ike_version_t */ extern enum_name_t *ike_version_names; diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h index b294ae72f..6074a7cd4 100644 --- a/src/libcharon/config/peer_cfg.h +++ b/src/libcharon/config/peer_cfg.h @@ -32,7 +32,7 @@ typedef struct peer_cfg_create_t peer_cfg_create_t; #include <utils/identification.h> #include <collections/enumerator.h> #include <selectors/traffic_selector.h> -#include <config/proposal.h> +#include <crypto/proposal/proposal.h> #include <config/ike_cfg.h> #include <config/child_cfg.h> #include <credentials/auth_cfg.h> diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c deleted file mode 100644 index 46c3c9400..000000000 --- a/src/libcharon/config/proposal.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * Copyright (C) 2008-2016 Tobias Brunner - * Copyright (C) 2006-2010 Martin Willi - * Copyright (C) 2013-2015 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> - -#include "proposal.h" - -#include <daemon.h> -#include <collections/array.h> -#include <utils/identification.h> - -#include <crypto/transform.h> -#include <crypto/prfs/prf.h> -#include <crypto/crypters/crypter.h> -#include <crypto/signers/signer.h> - -ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP, - "PROTO_NONE", - "IKE", - "AH", - "ESP", - "IPCOMP", -); - -typedef struct private_proposal_t private_proposal_t; - -/** - * Private data of an proposal_t object - */ -struct private_proposal_t { - - /** - * Public part - */ - proposal_t public; - - /** - * protocol (ESP or AH) - */ - protocol_id_t protocol; - - /** - * Priority ordered list of transforms, as entry_t - */ - array_t *transforms; - - /** - * senders SPI - */ - uint64_t spi; - - /** - * Proposal number - */ - u_int number; -}; - -/** - * Struct used to store different kinds of algorithms. - */ -typedef struct { - /** Type of the transform */ - transform_type_t type; - /** algorithm identifier */ - uint16_t alg; - /** key size in bits, or zero if not needed */ - uint16_t key_size; -} entry_t; - -METHOD(proposal_t, add_algorithm, void, - private_proposal_t *this, transform_type_t type, - uint16_t alg, uint16_t key_size) -{ - entry_t entry = { - .type = type, - .alg = alg, - .key_size = key_size, - }; - - array_insert(this->transforms, ARRAY_TAIL, &entry); -} - -CALLBACK(alg_filter, bool, - uintptr_t type, enumerator_t *orig, va_list args) -{ - entry_t *entry; - uint16_t *alg, *key_size; - - VA_ARGS_VGET(args, alg, key_size); - - while (orig->enumerate(orig, &entry)) - { - if (entry->type != type) - { - continue; - } - if (alg) - { - *alg = entry->alg; - } - if (key_size) - { - *key_size = entry->key_size; - } - return TRUE; - } - return FALSE; -} - -METHOD(proposal_t, create_enumerator, enumerator_t*, - private_proposal_t *this, transform_type_t type) -{ - return enumerator_create_filter( - array_create_enumerator(this->transforms), - alg_filter, (void*)(uintptr_t)type, NULL); -} - -METHOD(proposal_t, get_algorithm, bool, - private_proposal_t *this, transform_type_t type, - uint16_t *alg, uint16_t *key_size) -{ - enumerator_t *enumerator; - bool found = FALSE; - - enumerator = create_enumerator(this, type); - if (enumerator->enumerate(enumerator, alg, key_size)) - { - found = TRUE; - } - enumerator->destroy(enumerator); - - return found; -} - -METHOD(proposal_t, has_dh_group, bool, - private_proposal_t *this, diffie_hellman_group_t group) -{ - bool found = FALSE, any = FALSE; - enumerator_t *enumerator; - uint16_t current; - - enumerator = create_enumerator(this, DIFFIE_HELLMAN_GROUP); - while (enumerator->enumerate(enumerator, ¤t, NULL)) - { - any = TRUE; - if (current == group) - { - found = TRUE; - break; - } - } - enumerator->destroy(enumerator); - - if (!any && group == MODP_NONE) - { - found = TRUE; - } - return found; -} - -METHOD(proposal_t, strip_dh, void, - private_proposal_t *this, diffie_hellman_group_t keep) -{ - enumerator_t *enumerator; - entry_t *entry; - - enumerator = array_create_enumerator(this->transforms); - while (enumerator->enumerate(enumerator, &entry)) - { - if (entry->type == DIFFIE_HELLMAN_GROUP && - entry->alg != keep) - { - array_remove_at(this->transforms, enumerator); - } - } - enumerator->destroy(enumerator); -} - -/** - * Select a matching proposal from this and other, insert into selected. - */ -static bool select_algo(private_proposal_t *this, proposal_t *other, - proposal_t *selected, transform_type_t type, bool priv) -{ - enumerator_t *e1, *e2; - uint16_t alg1, alg2, ks1, ks2; - bool found = FALSE, optional = FALSE; - - if (type == INTEGRITY_ALGORITHM && - selected->get_algorithm(selected, ENCRYPTION_ALGORITHM, &alg1, NULL) && - encryption_algorithm_is_aead(alg1)) - { - /* no integrity algorithm required, we have an AEAD */ - return TRUE; - } - if (type == DIFFIE_HELLMAN_GROUP) - { - optional = this->protocol == PROTO_ESP || this->protocol == PROTO_AH; - } - - e1 = create_enumerator(this, type); - e2 = other->create_enumerator(other, type); - if (!e1->enumerate(e1, &alg1, NULL)) - { - if (!e2->enumerate(e2, &alg2, NULL)) - { - found = TRUE; - } - else if (optional) - { - do - { /* if NONE is proposed, we accept the proposal */ - found = !alg2; - } - while (!found && e2->enumerate(e2, &alg2, NULL)); - } - } - else if (!e2->enumerate(e2, NULL, NULL)) - { - if (optional) - { - do - { /* if NONE is proposed, we accept the proposal */ - found = !alg1; - } - while (!found && e1->enumerate(e1, &alg1, NULL)); - } - } - - e1->destroy(e1); - e1 = create_enumerator(this, type); - /* compare algs, order of algs in "first" is preferred */ - while (!found && e1->enumerate(e1, &alg1, &ks1)) - { - e2->destroy(e2); - e2 = other->create_enumerator(other, type); - while (e2->enumerate(e2, &alg2, &ks2)) - { - if (alg1 == alg2 && ks1 == ks2) - { - if (!priv && alg1 >= 1024) - { - /* accept private use algorithms only if requested */ - DBG1(DBG_CFG, "an algorithm from private space would match, " - "but peer implementation is unknown, skipped"); - continue; - } - selected->add_algorithm(selected, type, alg1, ks1); - found = TRUE; - break; - } - } - } - /* no match in all comparisons */ - e1->destroy(e1); - e2->destroy(e2); - - if (!found) - { - DBG2(DBG_CFG, " no acceptable %N found", transform_type_names, type); - } - return found; -} - -METHOD(proposal_t, select_proposal, proposal_t*, - private_proposal_t *this, proposal_t *other, bool other_remote, - bool private) -{ - proposal_t *selected; - - DBG2(DBG_CFG, "selecting proposal:"); - - if (this->protocol != other->get_protocol(other)) - { - DBG2(DBG_CFG, " protocol mismatch, skipping"); - return NULL; - } - - if (other_remote) - { - selected = proposal_create(this->protocol, other->get_number(other)); - selected->set_spi(selected, other->get_spi(other)); - } - else - { - selected = proposal_create(this->protocol, this->number); - selected->set_spi(selected, this->spi); - - } - - if (!select_algo(this, other, selected, ENCRYPTION_ALGORITHM, private) || - !select_algo(this, other, selected, PSEUDO_RANDOM_FUNCTION, private) || - !select_algo(this, other, selected, INTEGRITY_ALGORITHM, private) || - !select_algo(this, other, selected, DIFFIE_HELLMAN_GROUP, private) || - !select_algo(this, other, selected, EXTENDED_SEQUENCE_NUMBERS, private)) - { - selected->destroy(selected); - return NULL; - } - - DBG2(DBG_CFG, " proposal matches"); - return selected; -} - -METHOD(proposal_t, get_protocol, protocol_id_t, - private_proposal_t *this) -{ - return this->protocol; -} - -METHOD(proposal_t, set_spi, void, - private_proposal_t *this, uint64_t spi) -{ - this->spi = spi; -} - -METHOD(proposal_t, get_spi, uint64_t, - private_proposal_t *this) -{ - return this->spi; -} - -/** - * Check if two proposals have the same algorithms for a given transform type - */ -static bool algo_list_equals(private_proposal_t *this, proposal_t *other, - transform_type_t type) -{ - enumerator_t *e1, *e2; - uint16_t alg1, alg2, ks1, ks2; - bool equals = TRUE; - - e1 = create_enumerator(this, type); - e2 = other->create_enumerator(other, type); - while (e1->enumerate(e1, &alg1, &ks1)) - { - if (!e2->enumerate(e2, &alg2, &ks2)) - { - /* this has more algs */ - equals = FALSE; - break; - } - if (alg1 != alg2 || ks1 != ks2) - { - equals = FALSE; - break; - } - } - if (e2->enumerate(e2, &alg2, &ks2)) - { - /* other has more algs */ - equals = FALSE; - } - e1->destroy(e1); - e2->destroy(e2); - - return equals; -} - -METHOD(proposal_t, get_number, u_int, - private_proposal_t *this) -{ - return this->number; -} - -METHOD(proposal_t, equals, bool, - private_proposal_t *this, proposal_t *other) -{ - if (&this->public == other) - { - return TRUE; - } - return ( - algo_list_equals(this, other, ENCRYPTION_ALGORITHM) && - algo_list_equals(this, other, INTEGRITY_ALGORITHM) && - algo_list_equals(this, other, PSEUDO_RANDOM_FUNCTION) && - algo_list_equals(this, other, DIFFIE_HELLMAN_GROUP) && - algo_list_equals(this, other, EXTENDED_SEQUENCE_NUMBERS)); -} - -METHOD(proposal_t, clone_, proposal_t*, - private_proposal_t *this) -{ - private_proposal_t *clone; - enumerator_t *enumerator; - entry_t *entry; - - clone = (private_proposal_t*)proposal_create(this->protocol, 0); - - enumerator = array_create_enumerator(this->transforms); - while (enumerator->enumerate(enumerator, &entry)) - { - array_insert(clone->transforms, ARRAY_TAIL, entry); - } - enumerator->destroy(enumerator); - - clone->spi = this->spi; - clone->number = this->number; - - return &clone->public; -} - -/** - * Map integrity algorithms to the PRF functions using the same algorithm. - */ -static const struct { - integrity_algorithm_t integ; - pseudo_random_function_t prf; -} integ_prf_map[] = { - {AUTH_HMAC_SHA1_96, PRF_HMAC_SHA1 }, - {AUTH_HMAC_SHA1_160, PRF_HMAC_SHA1 }, - {AUTH_HMAC_SHA2_256_128, PRF_HMAC_SHA2_256 }, - {AUTH_HMAC_SHA2_384_192, PRF_HMAC_SHA2_384 }, - {AUTH_HMAC_SHA2_512_256, PRF_HMAC_SHA2_512 }, - {AUTH_HMAC_MD5_96, PRF_HMAC_MD5 }, - {AUTH_HMAC_MD5_128, PRF_HMAC_MD5 }, - {AUTH_AES_XCBC_96, PRF_AES128_XCBC }, - {AUTH_CAMELLIA_XCBC_96, PRF_CAMELLIA128_XCBC }, - {AUTH_AES_CMAC_96, PRF_AES128_CMAC }, -}; - -/** - * Remove all entries of the given transform type - */ -static void remove_transform(private_proposal_t *this, transform_type_t type) -{ - enumerator_t *e; - entry_t *entry; - - e = array_create_enumerator(this->transforms); - while (e->enumerate(e, &entry)) - { - if (entry->type == type) - { - array_remove_at(this->transforms, e); - } - } - e->destroy(e); -} - -/** - * Checks the proposal read from a string. - */ -static bool check_proposal(private_proposal_t *this) -{ - enumerator_t *e; - entry_t *entry; - uint16_t alg, ks; - bool all_aead = TRUE, any_aead = FALSE, any_enc = FALSE; - int i; - - if (this->protocol == PROTO_IKE) - { - if (!get_algorithm(this, PSEUDO_RANDOM_FUNCTION, NULL, NULL)) - { /* No explicit PRF found. We assume the same algorithm as used - * for integrity checking. */ - e = create_enumerator(this, INTEGRITY_ALGORITHM); - while (e->enumerate(e, &alg, &ks)) - { - for (i = 0; i < countof(integ_prf_map); i++) - { - if (alg == integ_prf_map[i].integ) - { - add_algorithm(this, PSEUDO_RANDOM_FUNCTION, - integ_prf_map[i].prf, 0); - break; - } - } - } - e->destroy(e); - } - if (!get_algorithm(this, PSEUDO_RANDOM_FUNCTION, NULL, NULL)) - { - DBG1(DBG_CFG, "a PRF algorithm is mandatory in IKE proposals"); - return FALSE; - } - /* remove MODP_NONE from IKE proposal */ - e = array_create_enumerator(this->transforms); - while (e->enumerate(e, &entry)) - { - if (entry->type == DIFFIE_HELLMAN_GROUP && !entry->alg) - { - array_remove_at(this->transforms, e); - } - } - e->destroy(e); - if (!get_algorithm(this, DIFFIE_HELLMAN_GROUP, NULL, NULL)) - { - DBG1(DBG_CFG, "a DH group is mandatory in IKE proposals"); - return FALSE; - } - } - else - { /* remove PRFs from ESP/AH proposals */ - remove_transform(this, PSEUDO_RANDOM_FUNCTION); - } - - if (this->protocol == PROTO_IKE || this->protocol == PROTO_ESP) - { - e = create_enumerator(this, ENCRYPTION_ALGORITHM); - while (e->enumerate(e, &alg, &ks)) - { - any_enc = TRUE; - if (encryption_algorithm_is_aead(alg)) - { - any_aead = TRUE; - continue; - } - all_aead = FALSE; - } - e->destroy(e); - - if (!any_enc) - { - DBG1(DBG_CFG, "an encryption algorithm is mandatory in %N proposals", - protocol_id_names, this->protocol); - return FALSE; - } - else if (any_aead && !all_aead) - { - DBG1(DBG_CFG, "classic and combined-mode (AEAD) encryption " - "algorithms can't be contained in the same %N proposal", - protocol_id_names, this->protocol); - return FALSE; - } - else if (all_aead) - { /* if all encryption algorithms in the proposal are AEADs, - * we MUST NOT propose any integrity algorithms */ - remove_transform(this, INTEGRITY_ALGORITHM); - } - } - else - { /* AES-GMAC is parsed as encryption algorithm, so we map that to the - * proper integrity algorithm */ - e = array_create_enumerator(this->transforms); - while (e->enumerate(e, &entry)) - { - if (entry->type == ENCRYPTION_ALGORITHM) - { - if (entry->alg == ENCR_NULL_AUTH_AES_GMAC) - { - entry->type = INTEGRITY_ALGORITHM; - ks = entry->key_size; - entry->key_size = 0; - switch (ks) - { - case 128: - entry->alg = AUTH_AES_128_GMAC; - continue; - case 192: - entry->alg = AUTH_AES_192_GMAC; - continue; - case 256: - entry->alg = AUTH_AES_256_GMAC; - continue; - default: - break; - } - } - /* remove all other encryption algorithms */ - array_remove_at(this->transforms, e); - } - } - e->destroy(e); - - if (!get_algorithm(this, INTEGRITY_ALGORITHM, NULL, NULL)) - { - DBG1(DBG_CFG, "an integrity algorithm is mandatory in AH " - "proposals"); - return FALSE; - } - } - - if (this->protocol == PROTO_AH || this->protocol == PROTO_ESP) - { - if (!get_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NULL, NULL)) - { /* ESN not specified, assume not supported */ - add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); - } - } - - array_compress(this->transforms); - return TRUE; -} - -/** - * add a algorithm identified by a string to the proposal. - */ -static bool add_string_algo(private_proposal_t *this, const char *alg) -{ - const proposal_token_t *token; - - token = lib->proposal->get_token(lib->proposal, alg); - if (token == NULL) - { - DBG1(DBG_CFG, "algorithm '%s' not recognized", alg); - return FALSE; - } - - add_algorithm(this, token->type, token->algorithm, token->keysize); - - return TRUE; -} - -/** - * print all algorithms of a kind to buffer - */ -static int print_alg(private_proposal_t *this, printf_hook_data_t *data, - u_int kind, void *names, bool *first) -{ - enumerator_t *enumerator; - size_t written = 0; - uint16_t alg, size; - - enumerator = create_enumerator(this, kind); - while (enumerator->enumerate(enumerator, &alg, &size)) - { - if (*first) - { - written += print_in_hook(data, "%N", names, alg); - *first = FALSE; - } - else - { - written += print_in_hook(data, "/%N", names, alg); - } - if (size) - { - written += print_in_hook(data, "_%u", size); - } - } - enumerator->destroy(enumerator); - return written; -} - -/** - * Described in header. - */ -int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, - const void *const *args) -{ - private_proposal_t *this = *((private_proposal_t**)(args[0])); - linked_list_t *list = *((linked_list_t**)(args[0])); - enumerator_t *enumerator; - size_t written = 0; - bool first = TRUE; - - if (this == NULL) - { - return print_in_hook(data, "(null)"); - } - - if (spec->hash) - { - enumerator = list->create_enumerator(list); - while (enumerator->enumerate(enumerator, &this)) - { /* call recursivly */ - if (first) - { - written += print_in_hook(data, "%P", this); - first = FALSE; - } - else - { - written += print_in_hook(data, ", %P", this); - } - } - enumerator->destroy(enumerator); - return written; - } - - written = print_in_hook(data, "%N:", protocol_id_names, this->protocol); - written += print_alg(this, data, ENCRYPTION_ALGORITHM, - encryption_algorithm_names, &first); - written += print_alg(this, data, INTEGRITY_ALGORITHM, - integrity_algorithm_names, &first); - written += print_alg(this, data, PSEUDO_RANDOM_FUNCTION, - pseudo_random_function_names, &first); - written += print_alg(this, data, DIFFIE_HELLMAN_GROUP, - diffie_hellman_group_names, &first); - written += print_alg(this, data, EXTENDED_SEQUENCE_NUMBERS, - extended_sequence_numbers_names, &first); - return written; -} - -METHOD(proposal_t, destroy, void, - private_proposal_t *this) -{ - array_destroy(this->transforms); - free(this); -} - -/* - * Described in header - */ -proposal_t *proposal_create(protocol_id_t protocol, u_int number) -{ - private_proposal_t *this; - - INIT(this, - .public = { - .add_algorithm = _add_algorithm, - .create_enumerator = _create_enumerator, - .get_algorithm = _get_algorithm, - .has_dh_group = _has_dh_group, - .strip_dh = _strip_dh, - .select = _select_proposal, - .get_protocol = _get_protocol, - .set_spi = _set_spi, - .get_spi = _get_spi, - .get_number = _get_number, - .equals = _equals, - .clone = _clone_, - .destroy = _destroy, - }, - .protocol = protocol, - .number = number, - .transforms = array_create(sizeof(entry_t), 0), - ); - - return &this->public; -} - -/** - * Add supported IKE algorithms to proposal - */ -static bool proposal_add_supported_ike(private_proposal_t *this, bool aead) -{ - enumerator_t *enumerator; - encryption_algorithm_t encryption; - integrity_algorithm_t integrity; - pseudo_random_function_t prf; - diffie_hellman_group_t group; - const char *plugin_name; - - if (aead) - { - /* Round 1 adds algorithms with at least 128 bit security strength */ - enumerator = lib->crypto->create_aead_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) - { - switch (encryption) - { - case ENCR_AES_GCM_ICV16: - case ENCR_AES_CCM_ICV16: - case ENCR_CAMELLIA_CCM_ICV16: - /* we assume that we support all AES/Camellia sizes */ - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128); - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); - break; - case ENCR_CHACHA20_POLY1305: - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - /* Round 2 adds algorithms with less than 128 bit security strength */ - enumerator = lib->crypto->create_aead_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) - { - switch (encryption) - { - case ENCR_AES_GCM_ICV12: - case ENCR_AES_GCM_ICV8: - case ENCR_AES_CCM_ICV12: - case ENCR_AES_CCM_ICV8: - case ENCR_CAMELLIA_CCM_ICV12: - case ENCR_CAMELLIA_CCM_ICV8: - /* we assume that we support all AES/Camellia sizes */ - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128); - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - if (!array_count(this->transforms)) - { - return FALSE; - } - } - else - { - /* Round 1 adds algorithms with at least 128 bit security strength */ - enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) - { - switch (encryption) - { - case ENCR_AES_CBC: - case ENCR_AES_CTR: - case ENCR_CAMELLIA_CBC: - case ENCR_CAMELLIA_CTR: - /* we assume that we support all AES/Camellia sizes */ - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128); - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192); - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256); - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - /* Round 2 adds algorithms with less than 128 bit security strength */ - enumerator = lib->crypto->create_crypter_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &encryption, &plugin_name)) - { - switch (encryption) - { - case ENCR_3DES: - add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0); - break; - case ENCR_DES: - /* no, thanks */ - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - if (!array_count(this->transforms)) - { - return FALSE; - } - - /* Round 1 adds algorithms with at least 128 bit security strength */ - enumerator = lib->crypto->create_signer_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) - { - switch (integrity) - { - case AUTH_HMAC_SHA2_256_128: - case AUTH_HMAC_SHA2_384_192: - case AUTH_HMAC_SHA2_512_256: - add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0); - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - /* Round 2 adds algorithms with less than 128 bit security strength */ - enumerator = lib->crypto->create_signer_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &integrity, &plugin_name)) - { - switch (integrity) - { - case AUTH_AES_XCBC_96: - case AUTH_AES_CMAC_96: - case AUTH_HMAC_SHA1_96: - add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0); - break; - case AUTH_HMAC_MD5_96: - /* no, thanks */ - default: - break; - } - } - enumerator->destroy(enumerator); - } - - /* Round 1 adds algorithms with at least 128 bit security strength */ - enumerator = lib->crypto->create_prf_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &prf, &plugin_name)) - { - switch (prf) - { - case PRF_HMAC_SHA2_256: - case PRF_HMAC_SHA2_384: - case PRF_HMAC_SHA2_512: - case PRF_AES128_XCBC: - case PRF_AES128_CMAC: - add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0); - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - /* Round 2 adds algorithms with less than 128 bit security strength */ - enumerator = lib->crypto->create_prf_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &prf, &plugin_name)) - { - switch (prf) - { - case PRF_HMAC_SHA1: - add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0); - break; - case PRF_HMAC_MD5: - /* no, thanks */ - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - /* Round 1 adds ECC and NTRU algorithms with at least 128 bit security strength */ - enumerator = lib->crypto->create_dh_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &group, &plugin_name)) - { - switch (group) - { - case ECP_256_BIT: - case ECP_384_BIT: - case ECP_521_BIT: - case ECP_256_BP: - case ECP_384_BP: - case ECP_512_BP: - case CURVE_25519: - case CURVE_448: - case NTRU_128_BIT: - case NTRU_192_BIT: - case NTRU_256_BIT: - case NH_128_BIT: - add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - /* Round 2 adds other algorithms with at least 128 bit security strength */ - enumerator = lib->crypto->create_dh_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &group, &plugin_name)) - { - switch (group) - { - case MODP_3072_BIT: - case MODP_4096_BIT: - case MODP_8192_BIT: - add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - /* Round 3 adds algorithms with less than 128 bit security strength */ - enumerator = lib->crypto->create_dh_enumerator(lib->crypto); - while (enumerator->enumerate(enumerator, &group, &plugin_name)) - { - switch (group) - { - case MODP_NULL: - /* only for testing purposes */ - break; - case MODP_768_BIT: - case MODP_1024_BIT: - case MODP_1536_BIT: - /* weak */ - break; - case MODP_1024_160: - case MODP_2048_224: - case MODP_2048_256: - /* RFC 5114 primes are of questionable source */ - break; - case ECP_224_BIT: - case ECP_224_BP: - case ECP_192_BIT: - case NTRU_112_BIT: - /* rarely used */ - break; - case MODP_2048_BIT: - add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0); - break; - default: - break; - } - } - enumerator->destroy(enumerator); - - return TRUE; -} - -/* - * Described in header - */ -proposal_t *proposal_create_default(protocol_id_t protocol) -{ - private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0); - - switch (protocol) - { - case PROTO_IKE: - if (!proposal_add_supported_ike(this, FALSE)) - { - destroy(this); - return NULL; - } - break; - case PROTO_ESP: - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); - add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); - add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); - break; - case PROTO_AH: - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0); - add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); - break; - default: - break; - } - return &this->public; -} - -/* - * Described in header - */ -proposal_t *proposal_create_default_aead(protocol_id_t protocol) -{ - private_proposal_t *this; - - switch (protocol) - { - case PROTO_IKE: - this = (private_proposal_t*)proposal_create(protocol, 0); - if (!proposal_add_supported_ike(this, TRUE)) - { - destroy(this); - return NULL; - } - return &this->public; - case PROTO_ESP: - /* we currently don't include any AEAD proposal for ESP, as we - * don't know if our kernel backend actually supports it. */ - return NULL; - case PROTO_AH: - default: - return NULL; - } -} - -/* - * Described in header - */ -proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs) -{ - private_proposal_t *this; - enumerator_t *enumerator; - bool failed = TRUE; - char *alg; - - this = (private_proposal_t*)proposal_create(protocol, 0); - - /* get all tokens, separated by '-' */ - enumerator = enumerator_create_token(algs, "-", " "); - while (enumerator->enumerate(enumerator, &alg)) - { - if (!add_string_algo(this, alg)) - { - failed = TRUE; - break; - } - failed = FALSE; - } - enumerator->destroy(enumerator); - - if (failed || !check_proposal(this)) - { - destroy(this); - return NULL; - } - - return &this->public; -} diff --git a/src/libcharon/config/proposal.h b/src/libcharon/config/proposal.h deleted file mode 100644 index 0dc70f4c5..000000000 --- a/src/libcharon/config/proposal.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2009-2016 Tobias Brunner - * Copyright (C) 2006 Martin Willi - * HSR Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup proposal proposal - * @{ @ingroup config - */ - -#ifndef PROPOSAL_H_ -#define PROPOSAL_H_ - -typedef enum protocol_id_t protocol_id_t; -typedef enum extended_sequence_numbers_t extended_sequence_numbers_t; -typedef struct proposal_t proposal_t; - -#include <library.h> -#include <utils/identification.h> -#include <collections/linked_list.h> -#include <networking/host.h> -#include <crypto/transform.h> -#include <crypto/crypters/crypter.h> -#include <crypto/signers/signer.h> -#include <crypto/diffie_hellman.h> -#include <selectors/traffic_selector.h> - -/** - * Protocol ID of a proposal. - */ -enum protocol_id_t { - PROTO_NONE = 0, - PROTO_IKE = 1, - PROTO_AH = 2, - PROTO_ESP = 3, - PROTO_IPCOMP = 4, /* IKEv1 only */ -}; - -/** - * enum names for protocol_id_t - */ -extern enum_name_t *protocol_id_names; - -/** - * Stores a set of algorithms used for an SA. - * - * A proposal stores algorithms for a specific - * protocol. It can store algorithms for one protocol. - * Proposals with multiple protocols are not supported, - * as it's not specified in RFC4301 anymore. - */ -struct proposal_t { - - /** - * Add an algorithm to the proposal. - * - * The algorithms are stored by priority, first added - * is the most preferred. - * Key size is only needed for encryption algorithms - * with variable key size (such as AES). Must be set - * to zero if key size is not specified. - * The alg parameter accepts encryption_algorithm_t, - * integrity_algorithm_t, dh_group_number_t and - * extended_sequence_numbers_t. - * - * @param type kind of algorithm - * @param alg identifier for algorithm - * @param key_size key size to use - */ - void (*add_algorithm) (proposal_t *this, transform_type_t type, - uint16_t alg, uint16_t key_size); - - /** - * Get an enumerator over algorithms for a specific algo type. - * - * @param type kind of algorithm - * @return enumerator over uint16_t alg, uint16_t key_size - */ - enumerator_t *(*create_enumerator) (proposal_t *this, transform_type_t type); - - /** - * Get the algorithm for a type to use. - * - * If there are multiple algorithms, only the first is returned. - * - * @param type kind of algorithm - * @param alg pointer which receives algorithm - * @param key_size pointer which receives the key size - * @return TRUE if algorithm of this kind available - */ - bool (*get_algorithm) (proposal_t *this, transform_type_t type, - uint16_t *alg, uint16_t *key_size); - - /** - * Check if the proposal has a specific DH group. - * - * @param group group to check for - * @return TRUE if algorithm included - */ - bool (*has_dh_group) (proposal_t *this, diffie_hellman_group_t group); - - /** - * Strip DH groups from proposal to use it without PFS. - * - * @param keep group to keep (MODP_NONE to remove all) - */ - void (*strip_dh)(proposal_t *this, diffie_hellman_group_t keep); - - /** - * Compare two proposal, and select a matching subset. - * - * If the proposals are for the same protocols (AH/ESP), they are - * compared. If they have at least one algorithm of each type - * in common, a resulting proposal of this kind is created. - * - * @param other proposal to compare against - * @param other_remote whether other is the remote proposal from which to - * copy SPI and proposal number to the result, - * otherwise copy from this proposal - * @param private accepts algorithms allocated in a private range - * @return selected proposal, NULL if proposals don't match - */ - proposal_t *(*select)(proposal_t *this, proposal_t *other, - bool other_remote, bool private); - - /** - * Get the protocol ID of the proposal. - * - * @return protocol of the proposal - */ - protocol_id_t (*get_protocol) (proposal_t *this); - - /** - * Get the SPI of the proposal. - * - * @return spi for proto - */ - uint64_t (*get_spi) (proposal_t *this); - - /** - * Set the SPI of the proposal. - * - * @param spi spi to set for proto - */ - void (*set_spi) (proposal_t *this, uint64_t spi); - - /** - * Get the proposal number, as encoded in SA payload - * - * @return proposal number - */ - u_int (*get_number)(proposal_t *this); - - /** - * Check for the eqality of two proposals. - * - * @param other other proposal to check for equality - * @return TRUE if other equal to this - */ - bool (*equals)(proposal_t *this, proposal_t *other); - - /** - * Clone a proposal. - * - * @return clone of proposal - */ - proposal_t *(*clone) (proposal_t *this); - - /** - * Destroys the proposal object. - */ - void (*destroy) (proposal_t *this); -}; - -/** - * Create a child proposal for AH, ESP or IKE. - * - * @param protocol protocol, such as PROTO_ESP - * @param number proposal number, as encoded in SA payload - * @return proposal_t object - */ -proposal_t *proposal_create(protocol_id_t protocol, u_int number); - -/** - * Create a default proposal if nothing further specified. - * - * @param protocol protocol, such as PROTO_ESP - * @return proposal_t object - */ -proposal_t *proposal_create_default(protocol_id_t protocol); - -/** - * Create a default proposal for supported AEAD algorithms - * - * @param protocol protocol, such as PROTO_ESP - * @return proposal_t object, NULL if none supported - */ -proposal_t *proposal_create_default_aead(protocol_id_t protocol); - -/** - * Create a proposal from a string identifying the algorithms. - * - * The string is in the same form as a in the ipsec.conf file. - * E.g.: aes128-sha2_256-modp2048 - * 3des-md5 - * An additional '!' at the end of the string forces this proposal, - * without it the peer may choose another algorithm we support. - * - * @param protocol protocol, such as PROTO_ESP - * @param algs algorithms as string - * @return proposal_t object - */ -proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs); - -/** - * printf hook function for proposal_t. - * - * Arguments are: - * proposal_t *proposal - * With the #-specifier, arguments are: - * linked_list_t *list containing proposal_t* - */ -int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, - const void *const *args); - -#endif /** PROPOSAL_H_ @}*/ |