summaryrefslogtreecommitdiff
path: root/src/libcharon/config
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/config')
-rw-r--r--src/libcharon/config/child_cfg.c31
-rw-r--r--src/libcharon/config/child_cfg.h10
-rw-r--r--src/libcharon/config/peer_cfg.c12
-rw-r--r--src/libcharon/config/peer_cfg.h4
-rw-r--r--src/libcharon/config/proposal.c505
5 files changed, 229 insertions, 333 deletions
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 33d47a41e..6fe7d44b8 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -286,15 +286,17 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
DBG2(DBG_CFG, " %R", ts1);
result->insert_last(result, ts1);
}
+ derived->destroy(derived);
}
else
{
- e1 = supplied->create_enumerator(supplied);
+ e1 = derived->create_enumerator(derived);
+ e2 = supplied->create_enumerator(supplied);
/* enumerate all configured/derived selectors */
- while (derived->remove_first(derived, (void**)&ts1) == SUCCESS)
+ while (e1->enumerate(e1, &ts1))
{
/* enumerate all supplied traffic selectors */
- while (e1->enumerate(e1, &ts2))
+ while (e2->enumerate(e2, &ts2))
{
selected = ts1->get_subset(ts1, ts2);
if (selected)
@@ -309,12 +311,28 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
ts1, ts2);
}
}
- supplied->reset_enumerator(supplied, e1);
- ts1->destroy(ts1);
+ supplied->reset_enumerator(supplied, e2);
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ /* check if we/peer did any narrowing, raise alert */
+ e1 = derived->create_enumerator(derived);
+ e2 = result->create_enumerator(result);
+ while (e1->enumerate(e1, &ts1))
+ {
+ if (!e2->enumerate(e2, &ts2) || !ts1->equals(ts1, ts2))
+ {
+ charon->bus->alert(charon->bus, ALERT_TS_NARROWED,
+ local, result, this);
+ break;
+ }
}
e1->destroy(e1);
+ e2->destroy(e2);
+
+ derived->destroy_offset(derived, offsetof(traffic_selector_t, destroy));
}
- derived->destroy(derived);
/* remove any redundant traffic selectors in the list */
e1 = result->create_enumerator(result);
@@ -573,4 +591,3 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
return &this->public;
}
-
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index 6e8829a47..20d1fa811 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -213,14 +213,14 @@ struct child_cfg_t {
u_int32_t (*get_inactivity)(child_cfg_t *this);
/**
- * Specific reqid to use for CHILD_SA
+ * Specific reqid to use for CHILD_SA.
*
* @return reqid
*/
u_int32_t (*get_reqid)(child_cfg_t *this);
/**
- * Optional mark for CHILD_SA
+ * Optional mark for CHILD_SA.
*
* @param inbound TRUE for inbound, FALSE for outbound
* @return mark
@@ -235,7 +235,7 @@ struct child_cfg_t {
u_int32_t (*get_tfc)(child_cfg_t *this);
/**
- * Sets two options needed for Mobile IPv6 interoperability
+ * Sets two options needed for Mobile IPv6 interoperability.
*
* @param proxy_mode use IPsec transport proxy mode (default FALSE)
* @param install_policy install IPsec kernel policies (default TRUE)
@@ -244,7 +244,7 @@ struct child_cfg_t {
bool install_policy);
/**
- * Check whether IPsec transport SA should be set up in proxy mode
+ * Check whether IPsec transport SA should be set up in proxy mode.
*
* @return TRUE, if proxy mode should be used
* FALSE, otherwise
@@ -252,7 +252,7 @@ struct child_cfg_t {
bool (*use_proxy_mode)(child_cfg_t *this);
/**
- * Check whether IPsec policies should be installed in the kernel
+ * Check whether IPsec policies should be installed in the kernel.
*
* @return TRUE, if IPsec kernel policies should be installed
* FALSE, otherwise
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index 8de7d1289..eb983199b 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -249,7 +249,7 @@ static int get_ts_match(child_cfg_t *cfg, bool local,
{
linked_list_t *cfg_list;
enumerator_t *sup_enum, *cfg_enum;
- traffic_selector_t *sup_ts, *cfg_ts;
+ traffic_selector_t *sup_ts, *cfg_ts, *subset;
int match = 0, round;
/* fetch configured TS list, narrowing dynamic TS */
@@ -268,10 +268,14 @@ static int get_ts_match(child_cfg_t *cfg, bool local,
{ /* equality is honored better than matches */
match += round * 5;
}
- else if (cfg_ts->is_contained_in(cfg_ts, sup_ts) ||
- sup_ts->is_contained_in(sup_ts, cfg_ts))
+ else
{
- match += round * 1;
+ subset = cfg_ts->get_subset(cfg_ts, sup_ts);
+ if (subset)
+ {
+ subset->destroy(subset);
+ match += round * 1;
+ }
}
}
cfg_enum->destroy(cfg_enum);
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index 80913beba..e62e03ec5 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -176,7 +176,7 @@ struct peer_cfg_t {
/**
* Add an authentication config to the peer configuration.
*
- * @param config config to add
+ * @param cfg config to add
* @param local TRUE for local rules, FALSE for remote constraints
*/
void (*add_auth_cfg)(peer_cfg_t *this, auth_cfg_t *cfg, bool local);
@@ -190,7 +190,7 @@ struct peer_cfg_t {
enumerator_t* (*create_auth_cfg_enumerator)(peer_cfg_t *this, bool local);
/**
- * Should be sent a certificate for this connection?
+ * Should a certificate be sent for this connection?
*
* @return certificate sending policy
*/
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index 4803c7be2..0b702e014 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -19,7 +19,7 @@
#include "proposal.h"
#include <daemon.h>
-#include <collections/linked_list.h>
+#include <collections/array.h>
#include <utils/identification.h>
#include <crypto/transform.h>
@@ -36,7 +36,6 @@ ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP,
);
typedef struct private_proposal_t private_proposal_t;
-typedef struct algorithm_t algorithm_t;
/**
* Private data of an proposal_t object
@@ -54,29 +53,9 @@ struct private_proposal_t {
protocol_id_t protocol;
/**
- * priority ordered list of encryption algorithms
+ * Priority ordered list of transforms, as entry_t
*/
- linked_list_t *encryption_algos;
-
- /**
- * priority ordered list of integrity algorithms
- */
- linked_list_t *integrity_algos;
-
- /**
- * priority ordered list of pseudo random functions
- */
- linked_list_t *prf_algos;
-
- /**
- * priority ordered list of dh groups
- */
- linked_list_t *dh_groups;
-
- /**
- * priority ordered list of extended sequence number flags
- */
- linked_list_t *esns;
+ array_t *transforms;
/**
* senders SPI
@@ -92,68 +71,47 @@ struct private_proposal_t {
/**
* Struct used to store different kinds of algorithms.
*/
-struct algorithm_t {
- /**
- * Value from an encryption_algorithm_t/integrity_algorithm_t/...
- */
- u_int16_t algorithm;
-
- /**
- * the associated key size in bits, or zero if not needed
- */
+typedef struct {
+ /** Type of the transform */
+ transform_type_t type;
+ /** algorithm identifier */
+ u_int16_t alg;
+ /** key size in bits, or zero if not needed */
u_int16_t key_size;
-};
-
-/**
- * Add algorithm/keysize to a algorithm list
- */
-static void add_algo(linked_list_t *list, u_int16_t algo, u_int16_t key_size)
-{
- algorithm_t *algo_key;
-
- algo_key = malloc_thing(algorithm_t);
- algo_key->algorithm = algo;
- algo_key->key_size = key_size;
- list->insert_last(list, (void*)algo_key);
-}
+} entry_t;
METHOD(proposal_t, add_algorithm, void,
private_proposal_t *this, transform_type_t type,
- u_int16_t algo, u_int16_t key_size)
+ u_int16_t alg, u_int16_t key_size)
{
- switch (type)
- {
- case ENCRYPTION_ALGORITHM:
- add_algo(this->encryption_algos, algo, key_size);
- break;
- case INTEGRITY_ALGORITHM:
- add_algo(this->integrity_algos, algo, key_size);
- break;
- case PSEUDO_RANDOM_FUNCTION:
- add_algo(this->prf_algos, algo, key_size);
- break;
- case DIFFIE_HELLMAN_GROUP:
- add_algo(this->dh_groups, algo, 0);
- break;
- case EXTENDED_SEQUENCE_NUMBERS:
- add_algo(this->esns, algo, 0);
- break;
- default:
- break;
- }
+ entry_t entry = {
+ .type = type,
+ .alg = alg,
+ .key_size = key_size,
+ };
+
+ array_insert(this->transforms, ARRAY_TAIL, &entry);
}
/**
* filter function for peer configs
*/
-static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg,
+static bool alg_filter(uintptr_t type, entry_t **in, u_int16_t *alg,
void **unused, u_int16_t *key_size)
{
- algorithm_t *algo = *in;
- *alg = algo->algorithm;
+ entry_t *entry = *in;
+
+ if (entry->type != type)
+ {
+ return FALSE;
+ }
+ if (alg)
+ {
+ *alg = entry->alg;
+ }
if (key_size)
{
- *key_size = algo->key_size;
+ *key_size = entry->key_size;
}
return TRUE;
}
@@ -161,30 +119,9 @@ static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg,
METHOD(proposal_t, create_enumerator, enumerator_t*,
private_proposal_t *this, transform_type_t type)
{
- linked_list_t *list;
-
- switch (type)
- {
- case ENCRYPTION_ALGORITHM:
- list = this->encryption_algos;
- break;
- case INTEGRITY_ALGORITHM:
- list = this->integrity_algos;
- break;
- case PSEUDO_RANDOM_FUNCTION:
- list = this->prf_algos;
- break;
- case DIFFIE_HELLMAN_GROUP:
- list = this->dh_groups;
- break;
- case EXTENDED_SEQUENCE_NUMBERS:
- list = this->esns;
- break;
- default:
- return NULL;
- }
- return enumerator_create_filter(list->create_enumerator(list),
- (void*)alg_filter, NULL, NULL);
+ return enumerator_create_filter(
+ array_create_enumerator(this->transforms),
+ (void*)alg_filter, (void*)(uintptr_t)type, NULL);
}
METHOD(proposal_t, get_algorithm, bool,
@@ -200,84 +137,91 @@ METHOD(proposal_t, get_algorithm, bool,
found = TRUE;
}
enumerator->destroy(enumerator);
+
return found;
}
METHOD(proposal_t, has_dh_group, bool,
private_proposal_t *this, diffie_hellman_group_t group)
{
- bool result = FALSE;
+ bool found = FALSE, any = FALSE;
+ enumerator_t *enumerator;
+ u_int16_t current;
- if (this->dh_groups->get_count(this->dh_groups))
+ enumerator = create_enumerator(this, DIFFIE_HELLMAN_GROUP);
+ while (enumerator->enumerate(enumerator, &current, NULL))
{
- algorithm_t *current;
- enumerator_t *enumerator;
-
- enumerator = this->dh_groups->create_enumerator(this->dh_groups);
- while (enumerator->enumerate(enumerator, (void**)&current))
+ any = TRUE;
+ if (current == group)
{
- if (current->algorithm == group)
- {
- result = TRUE;
- break;
- }
+ found = TRUE;
+ break;
}
- enumerator->destroy(enumerator);
}
- else if (group == MODP_NONE)
+ enumerator->destroy(enumerator);
+
+ if (!any && group == MODP_NONE)
{
- result = TRUE;
+ found = TRUE;
}
- return result;
+ return found;
}
METHOD(proposal_t, strip_dh, void,
private_proposal_t *this, diffie_hellman_group_t keep)
{
enumerator_t *enumerator;
- algorithm_t *alg;
+ entry_t *entry;
- enumerator = this->dh_groups->create_enumerator(this->dh_groups);
- while (enumerator->enumerate(enumerator, (void**)&alg))
+ enumerator = array_create_enumerator(this->transforms);
+ while (enumerator->enumerate(enumerator, &entry))
{
- if (alg->algorithm != keep)
+ if (entry->type == DIFFIE_HELLMAN_GROUP &&
+ entry->alg != keep)
{
- this->dh_groups->remove_at(this->dh_groups, enumerator);
- free(alg);
+ array_remove_at(this->transforms, enumerator);
}
}
enumerator->destroy(enumerator);
}
/**
- * Find a matching alg/keysize in two linked lists
+ * Select a matching proposal from this and other, insert into selected.
*/
-static bool select_algo(linked_list_t *first, linked_list_t *second, bool priv,
- bool *add, u_int16_t *alg, size_t *key_size)
+static bool select_algo(private_proposal_t *this, proposal_t *other,
+ proposal_t *selected, transform_type_t type, bool priv)
{
enumerator_t *e1, *e2;
- algorithm_t *alg1, *alg2;
+ u_int16_t alg1, alg2, ks1, ks2;
+ bool found = FALSE;
- /* if in both are zero algorithms specified, we HAVE a match */
- if (first->get_count(first) == 0 && second->get_count(second) == 0)
+ if (type == INTEGRITY_ALGORITHM &&
+ selected->get_algorithm(selected, ENCRYPTION_ALGORITHM, &alg1, NULL) &&
+ encryption_algorithm_is_aead(alg1))
{
- *add = FALSE;
+ /* no integrity algorithm required, we have an AEAD */
return TRUE;
}
- e1 = first->create_enumerator(first);
- e2 = second->create_enumerator(second);
+ e1 = create_enumerator(this, type);
+ e2 = other->create_enumerator(other, type);
+ if (!e1->enumerate(e1, NULL, NULL) && !e2->enumerate(e2, NULL, NULL))
+ {
+ found = TRUE;
+ }
+
+ e1->destroy(e1);
+ e1 = create_enumerator(this, type);
/* compare algs, order of algs in "first" is preferred */
- while (e1->enumerate(e1, &alg1))
+ while (!found && e1->enumerate(e1, &alg1, &ks1))
{
e2->destroy(e2);
- e2 = second->create_enumerator(second);
- while (e2->enumerate(e2, &alg2))
+ e2 = other->create_enumerator(other, type);
+ while (e2->enumerate(e2, &alg2, &ks2))
{
- if (alg1->algorithm == alg2->algorithm &&
- alg1->key_size == alg2->key_size)
+ if (alg1 == alg2 && ks1 == ks2)
{
- if (!priv && alg1->algorithm >= 1024)
+ if (!priv && alg1 >= 1024)
{
/* accept private use algorithms only if requested */
DBG1(DBG_CFG, "an algorithm from private space would match, "
@@ -285,132 +229,52 @@ static bool select_algo(linked_list_t *first, linked_list_t *second, bool priv,
continue;
}
/* ok, we have an algorithm */
- *alg = alg1->algorithm;
- *key_size = alg1->key_size;
- *add = TRUE;
- e1->destroy(e1);
- e2->destroy(e2);
- return TRUE;
+ selected->add_algorithm(selected, type, alg1, ks1);
+ found = TRUE;
+ break;
}
}
}
/* no match in all comparisons */
e1->destroy(e1);
e2->destroy(e2);
- return FALSE;
+
+ 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_pub, bool private)
+ private_proposal_t *this, proposal_t *other, bool private)
{
- private_proposal_t *other = (private_proposal_t*)other_pub;
proposal_t *selected;
- u_int16_t algo;
- size_t key_size;
- bool add;
DBG2(DBG_CFG, "selecting proposal:");
- /* check protocol */
- if (this->protocol != other->protocol)
+ if (this->protocol != other->get_protocol(other))
{
DBG2(DBG_CFG, " protocol mismatch, skipping");
return NULL;
}
- selected = proposal_create(this->protocol, other->number);
+ selected = proposal_create(this->protocol, other->get_number(other));
- /* select encryption algorithm */
- if (select_algo(this->encryption_algos, other->encryption_algos, private,
- &add, &algo, &key_size))
- {
- if (add)
- {
- selected->add_algorithm(selected, ENCRYPTION_ALGORITHM,
- algo, key_size);
- }
- }
- else
+ 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);
- DBG2(DBG_CFG, " no acceptable %N found",
- transform_type_names, ENCRYPTION_ALGORITHM);
- return NULL;
- }
- /* select integrity algorithm */
- if (!encryption_algorithm_is_aead(algo))
- {
- if (select_algo(this->integrity_algos, other->integrity_algos, private,
- &add, &algo, &key_size))
- {
- if (add)
- {
- selected->add_algorithm(selected, INTEGRITY_ALGORITHM,
- algo, key_size);
- }
- }
- else
- {
- selected->destroy(selected);
- DBG2(DBG_CFG, " no acceptable %N found",
- transform_type_names, INTEGRITY_ALGORITHM);
- return NULL;
- }
- }
- /* select prf algorithm */
- if (select_algo(this->prf_algos, other->prf_algos, private,
- &add, &algo, &key_size))
- {
- if (add)
- {
- selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION,
- algo, key_size);
- }
- }
- else
- {
- selected->destroy(selected);
- DBG2(DBG_CFG, " no acceptable %N found",
- transform_type_names, PSEUDO_RANDOM_FUNCTION);
- return NULL;
- }
- /* select a DH-group */
- if (select_algo(this->dh_groups, other->dh_groups, private,
- &add, &algo, &key_size))
- {
- if (add)
- {
- selected->add_algorithm(selected, DIFFIE_HELLMAN_GROUP, algo, 0);
- }
- }
- else
- {
- selected->destroy(selected);
- DBG2(DBG_CFG, " no acceptable %N found",
- transform_type_names, DIFFIE_HELLMAN_GROUP);
- return NULL;
- }
- /* select if we use ESNs (has no private use space) */
- if (select_algo(this->esns, other->esns, TRUE, &add, &algo, &key_size))
- {
- if (add)
- {
- selected->add_algorithm(selected, EXTENDED_SEQUENCE_NUMBERS, algo, 0);
- }
- }
- else
- {
- selected->destroy(selected);
- DBG2(DBG_CFG, " no acceptable %N found",
- transform_type_names, EXTENDED_SEQUENCE_NUMBERS);
return NULL;
}
+
DBG2(DBG_CFG, " proposal matches");
- /* apply SPI from "other" */
- selected->set_spi(selected, other->spi);
+ selected->set_spi(selected, other->get_spi(other));
- /* everything matched, return new proposal */
return selected;
}
@@ -433,50 +297,39 @@ METHOD(proposal_t, get_spi, u_int64_t,
}
/**
- * Clone a algorithm list
+ * Check if two proposals have the same algorithms for a given transform type
*/
-static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list)
-{
- algorithm_t *algo, *clone_algo;
- enumerator_t *enumerator;
-
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &algo))
- {
- clone_algo = malloc_thing(algorithm_t);
- memcpy(clone_algo, algo, sizeof(algorithm_t));
- clone_list->insert_last(clone_list, (void*)clone_algo);
- }
- enumerator->destroy(enumerator);
-}
-
-/**
- * check if an algorithm list equals
- */
-static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2)
+static bool algo_list_equals(private_proposal_t *this, proposal_t *other,
+ transform_type_t type)
{
enumerator_t *e1, *e2;
- algorithm_t *alg1, *alg2;
+ u_int16_t alg1, alg2, ks1, ks2;
bool equals = TRUE;
- if (l1->get_count(l1) != l2->get_count(l2))
- {
- return FALSE;
- }
-
- e1 = l1->create_enumerator(l1);
- e2 = l2->create_enumerator(l2);
- while (e1->enumerate(e1, &alg1) && e2->enumerate(e2, &alg2))
+ e1 = create_enumerator(this, type);
+ e2 = other->create_enumerator(other, type);
+ while (e1->enumerate(e1, &alg1, &ks1))
{
- if (alg1->algorithm != alg2->algorithm ||
- alg1->key_size != alg2->key_size)
+ 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;
}
@@ -487,33 +340,35 @@ METHOD(proposal_t, get_number, u_int,
}
METHOD(proposal_t, equals, bool,
- private_proposal_t *this, proposal_t *other_pub)
+ private_proposal_t *this, proposal_t *other)
{
- private_proposal_t *other = (private_proposal_t*)other_pub;
-
- if (this == other)
+ if (&this->public == other)
{
return TRUE;
}
return (
- algo_list_equals(this->encryption_algos, other->encryption_algos) &&
- algo_list_equals(this->integrity_algos, other->integrity_algos) &&
- algo_list_equals(this->prf_algos, other->prf_algos) &&
- algo_list_equals(this->dh_groups, other->dh_groups) &&
- algo_list_equals(this->esns, other->esns));
+ 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);
- clone_algo_list(this->encryption_algos, clone->encryption_algos);
- clone_algo_list(this->integrity_algos, clone->integrity_algos);
- clone_algo_list(this->prf_algos, clone->prf_algos);
- clone_algo_list(this->dh_groups, clone->dh_groups);
- clone_algo_list(this->esns, clone->esns);
+
+ 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;
@@ -544,34 +399,40 @@ static const struct {
static void check_proposal(private_proposal_t *this)
{
enumerator_t *e;
- algorithm_t *alg;
+ entry_t *entry;
+ u_int16_t alg, ks;
bool all_aead = TRUE;
int i;
- if (this->protocol == PROTO_IKE &&
- this->prf_algos->get_count(this->prf_algos) == 0)
- { /* No explicit PRF found. We assume the same algorithm as used
- * for integrity checking */
- e = this->integrity_algos->create_enumerator(this->integrity_algos);
- while (e->enumerate(e, &alg))
+ if (this->protocol == PROTO_IKE)
+ {
+ e = create_enumerator(this, PSEUDO_RANDOM_FUNCTION);
+ if (!e->enumerate(e, &alg, &ks))
{
- for (i = 0; i < countof(integ_prf_map); i++)
+ /* No explicit PRF found. We assume the same algorithm as used
+ * for integrity checking */
+ e->destroy(e);
+ e = create_enumerator(this, INTEGRITY_ALGORITHM);
+ while (e->enumerate(e, &alg, &ks))
{
- if (alg->algorithm == integ_prf_map[i].integ)
+ for (i = 0; i < countof(integ_prf_map); i++)
{
- add_algorithm(this, PSEUDO_RANDOM_FUNCTION,
- integ_prf_map[i].prf, 0);
- break;
+ if (alg == integ_prf_map[i].integ)
+ {
+ add_algorithm(this, PSEUDO_RANDOM_FUNCTION,
+ integ_prf_map[i].prf, 0);
+ break;
+ }
}
}
}
e->destroy(e);
}
- e = this->encryption_algos->create_enumerator(this->encryption_algos);
- while (e->enumerate(e, &alg))
+ e = create_enumerator(this, ENCRYPTION_ALGORITHM);
+ while (e->enumerate(e, &alg, &ks))
{
- if (!encryption_algorithm_is_aead(alg->algorithm))
+ if (!encryption_algorithm_is_aead(alg))
{
all_aead = FALSE;
break;
@@ -581,24 +442,30 @@ static void check_proposal(private_proposal_t *this)
if (all_aead)
{
- /* if all encryption algorithms in the proposal are authenticated encryption
- * algorithms we MUST NOT propose any integrity algorithms */
- while (this->integrity_algos->remove_last(this->integrity_algos,
- (void**)&alg) == SUCCESS)
+ /* if all encryption algorithms in the proposal are AEADs,
+ * we MUST NOT propose any integrity algorithms */
+ e = array_create_enumerator(this->transforms);
+ while (e->enumerate(e, &entry))
{
- free(alg);
+ if (entry->type == INTEGRITY_ALGORITHM)
+ {
+ array_remove_at(this->transforms, e);
+ }
}
+ e->destroy(e);
}
if (this->protocol == PROTO_AH || this->protocol == PROTO_ESP)
{
- e = this->esns->create_enumerator(this->esns);
- if (!e->enumerate(e, &alg))
+ e = create_enumerator(this, EXTENDED_SEQUENCE_NUMBERS);
+ if (!e->enumerate(e, NULL, NULL))
{ /* ESN not specified, assume not supported */
add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
}
e->destroy(e);
}
+
+ array_compress(this->transforms);
}
/**
@@ -704,11 +571,7 @@ int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
METHOD(proposal_t, destroy, void,
private_proposal_t *this)
{
- this->encryption_algos->destroy_function(this->encryption_algos, free);
- this->integrity_algos->destroy_function(this->integrity_algos, free);
- this->prf_algos->destroy_function(this->prf_algos, free);
- this->dh_groups->destroy_function(this->dh_groups, free);
- this->esns->destroy_function(this->esns, free);
+ array_destroy(this->transforms);
free(this);
}
@@ -737,11 +600,7 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number)
},
.protocol = protocol,
.number = number,
- .encryption_algos = linked_list_create(),
- .integrity_algos = linked_list_create(),
- .prf_algos = linked_list_create(),
- .dh_groups = linked_list_create(),
- .esns = linked_list_create(),
+ .transforms = array_create(sizeof(entry_t), 0),
);
return &this->public;
@@ -768,6 +627,28 @@ static void proposal_add_supported_ike(private_proposal_t *this)
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;
+ case ENCR_3DES:
+ add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
+ break;
+ case ENCR_DES:
+ /* no, thanks */
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
+ while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
+ {
+ switch (encryption)
+ {
case ENCR_AES_CCM_ICV8:
case ENCR_AES_CCM_ICV12:
case ENCR_AES_CCM_ICV16:
@@ -782,12 +663,6 @@ static void proposal_add_supported_ike(private_proposal_t *this)
add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
break;
- case ENCR_3DES:
- add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
- break;
- case ENCR_DES:
- /* no, thanks */
- break;
default:
break;
}