diff --git a/src/charon/config/child_cfg.c b/src/charon/config/child_cfg.c index b4bc95707..9a22dcf4f 100644 --- a/src/charon/config/child_cfg.c +++ b/src/charon/config/child_cfg.c @@ -113,43 +113,26 @@ static void add_proposal(private_child_cfg_t *this, proposal_t *proposal) this->proposals->insert_last(this->proposals, proposal); } -/** - * strip out DH groups from a proposal - */ -static void strip_dh_from_proposal(proposal_t *proposal) -{ - iterator_t *iterator; - algorithm_t *algo; - - iterator = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP); - while (iterator->iterate(iterator, (void**)&algo)) - { - iterator->remove(iterator); - free(algo); - } - iterator->destroy(iterator); -} - /** * Implementation of child_cfg_t.get_proposals */ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *current; linked_list_t *proposals = linked_list_create(); - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, ¤t)) { current = current->clone(current); if (strip_dh) { - strip_dh_from_proposal(current); + current->strip_dh(current); } proposals->insert_last(proposals, current); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return proposals; } @@ -160,22 +143,21 @@ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh) static proposal_t* select_proposal(private_child_cfg_t*this, linked_list_t *proposals, bool strip_dh) { - iterator_t *stored_iter, *supplied_iter; + enumerator_t *stored_enum, *supplied_enum; proposal_t *stored, *supplied, *selected = NULL; - stored_iter = this->proposals->create_iterator(this->proposals, TRUE); - supplied_iter = proposals->create_iterator(proposals, TRUE); + stored_enum = this->proposals->create_enumerator(this->proposals); + supplied_enum = proposals->create_enumerator(proposals); /* compare all stored proposals with all supplied. Stored ones are preferred. */ - while (stored_iter->iterate(stored_iter, (void**)&stored)) + while (stored_enum->enumerate(stored_enum, &stored)) { stored = stored->clone(stored); - supplied_iter->reset(supplied_iter); - while (supplied_iter->iterate(supplied_iter, (void**)&supplied)) + while (supplied_enum->enumerate(supplied_enum, &supplied)) { if (strip_dh) { - strip_dh_from_proposal(stored); + stored->strip_dh(stored); } selected = stored->select(stored, supplied); if (selected) @@ -188,9 +170,11 @@ static proposal_t* select_proposal(private_child_cfg_t*this, { break; } + supplied_enum->destroy(supplied_enum); + supplied_enum = proposals->create_enumerator(proposals); } - stored_iter->destroy(stored_iter); - supplied_iter->destroy(supplied_iter); + stored_enum->destroy(stored_enum); + supplied_enum->destroy(supplied_enum); return selected; } @@ -217,17 +201,17 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca linked_list_t *supplied, host_t *host) { - iterator_t *i1, *i2; + enumerator_t *e1, *e2; traffic_selector_t *ts1, *ts2, *selected; linked_list_t *result = linked_list_create(); if (local) { - i1 = this->my_ts->create_iterator(this->my_ts, TRUE); + e1 = this->my_ts->create_enumerator(this->my_ts); } else { - i1 = this->other_ts->create_iterator(this->other_ts, FALSE); + e1 = this->other_ts->create_enumerator(this->other_ts); } /* no list supplied, just fetch the stored traffic selectors */ @@ -235,7 +219,7 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca { DBG2(DBG_CFG, "proposing traffic selectors for %s:", local ? "us" : "other"); - while (i1->iterate(i1, (void**)&ts1)) + while (e1->enumerate(e1, &ts1)) { /* we make a copy of the TS, this allows us to update dynamic TS' */ selected = ts1->clone(ts1); @@ -246,15 +230,15 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca DBG2(DBG_CFG, " %R (derived from %R)", selected, ts1); result->insert_last(result, selected); } - i1->destroy(i1); + e1->destroy(e1); } else { DBG2(DBG_CFG, "selecting traffic selectors for %s:", local ? "us" : "other"); - i2 = supplied->create_iterator(supplied, TRUE); + e2 = supplied->create_enumerator(supplied); /* iterate over all stored selectors */ - while (i1->iterate(i1, (void**)&ts1)) + while (e1->enumerate(e1, &ts1)) { /* we make a copy of the TS, as we have to update dynamic TS' */ ts1 = ts1->clone(ts1); @@ -263,9 +247,8 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca ts1->set_address(ts1, host); } - i2->reset(i2); /* iterate over all supplied traffic selectors */ - while (i2->iterate(i2, (void**)&ts2)) + while (e2->enumerate(e2, &ts2)) { selected = ts1->get_subset(ts1, ts2); if (selected) @@ -280,40 +263,44 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca ts1, ts2, selected); } } + e2->destroy(e2); + e2 = supplied->create_enumerator(supplied); ts1->destroy(ts1); } - i1->destroy(i1); - i2->destroy(i2); + e1->destroy(e1); + e2->destroy(e2); } /* remove any redundant traffic selectors in the list */ - i1 = result->create_iterator(result, TRUE); - i2 = result->create_iterator(result, TRUE); - while (i1->iterate(i1, (void**)&ts1)) + e1 = result->create_enumerator(result); + e2 = result->create_enumerator(result); + while (e1->enumerate(e1, &ts1)) { - while (i2->iterate(i2, (void**)&ts2)) + while (e2->enumerate(e2, &ts2)) { if (ts1 != ts2) { if (ts2->is_contained_in(ts2, ts1)) { - i2->remove(i2); + result->remove_at(result, e2); ts2->destroy(ts2); - i1->reset(i1); + e1->destroy(e1); + e1 = result->create_enumerator(result); break; } if (ts1->is_contained_in(ts1, ts2)) { - i1->remove(i1); + result->remove_at(result, e1); ts1->destroy(ts1); - i2->reset(i2); + e2->destroy(e2); + e2 = result->create_enumerator(result); break; } } } } - i1->destroy(i1); - i2->destroy(i2); + e1->destroy(e1); + e2->destroy(e2); return result; } @@ -363,21 +350,19 @@ static mode_t get_mode(private_child_cfg_t *this) */ static diffie_hellman_group_t get_dh_group(private_child_cfg_t *this) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *proposal; - algorithm_t *algo; - diffie_hellman_group_t dh_group = MODP_NONE; + u_int16_t dh_group = MODP_NONE; - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)&proposal)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, &proposal)) { - if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo)) + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL)) { - dh_group = algo->algorithm; break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return dh_group; } diff --git a/src/charon/config/ike_cfg.c b/src/charon/config/ike_cfg.c index 5c994ae3c..ec08b9730 100644 --- a/src/charon/config/ike_cfg.c +++ b/src/charon/config/ike_cfg.c @@ -165,24 +165,64 @@ static proposal_t *select_proposal(private_ike_cfg_t *this, */ static diffie_hellman_group_t get_dh_group(private_ike_cfg_t *this) { - iterator_t *iterator; + enumerator_t *enumerator; proposal_t *proposal; - algorithm_t *algo; - diffie_hellman_group_t dh_group = MODP_NONE; + u_int16_t dh_group = MODP_NONE; - iterator = this->proposals->create_iterator(this->proposals, TRUE); - while (iterator->iterate(iterator, (void**)&proposal)) + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, &proposal)) { - if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo)) + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL)) { - dh_group = algo->algorithm; break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return dh_group; } +/** + * Implementation of ike_cfg_t.equals. + */ +static bool equals(private_ike_cfg_t *this, private_ike_cfg_t *other) +{ + enumerator_t *e1, *e2; + proposal_t *p1, *p2; + bool eq = TRUE; + + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + if (this->proposals->get_count(this->proposals) != + other->proposals->get_count(other->proposals)) + { + return FALSE; + } + e1 = this->proposals->create_enumerator(this->proposals); + e2 = this->proposals->create_enumerator(this->proposals); + while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2)) + { + if (!p1->equals(p1, p2)) + { + eq = FALSE; + break; + } + } + e1->destroy(e1); + e2->destroy(e2); + + return (eq && + this->certreq == other->certreq && + this->force_encap == other->force_encap && + this->my_host->equals(this->my_host, other->my_host) && + this->other_host->equals(this->other_host, other->other_host)); +} + /** * Implementation of ike_cfg_t.get_ref. */ @@ -223,6 +263,7 @@ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals; this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal; this->public.get_dh_group = (diffie_hellman_group_t(*)(ike_cfg_t*)) get_dh_group; + this->public.equals = (bool(*)(ike_cfg_t*,ike_cfg_t*)) equals; this->public.get_ref = (void(*)(ike_cfg_t*))get_ref; this->public.destroy = (void(*)(ike_cfg_t*))destroy; diff --git a/src/charon/config/ike_cfg.h b/src/charon/config/ike_cfg.h index d28da9b8d..3bd64f27f 100644 --- a/src/charon/config/ike_cfg.h +++ b/src/charon/config/ike_cfg.h @@ -104,6 +104,14 @@ struct ike_cfg_t { */ diffie_hellman_group_t (*get_dh_group)(ike_cfg_t *this); + /** + * Check if two IKE configs are equal. + * + * @param other other to check for equality + * @return TRUE if other equal to this + */ + bool (*equals)(ike_cfg_t *this, ike_cfg_t *other); + /** * Get a new reference to this ike_cfg. * diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c index 1547f53aa..3b6febc93 100644 --- a/src/charon/config/peer_cfg.c +++ b/src/charon/config/peer_cfg.c @@ -465,6 +465,53 @@ static identification_t* get_peer_id(private_peer_cfg_t *this) } #endif /* P2P */ +/** + * Implementation of peer_cfg_t.equals. + */ +static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other) +{ + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + + return ( + this->ike_version == other->ike_version && + this->my_id->equals(this->my_id, other->my_id) && + this->other_id->equals(this->other_id, other->other_id) && + this->cert_policy == other->cert_policy && + this->auth_method == other->auth_method && + this->eap_type == other->eap_type && + this->eap_vendor == other->eap_vendor && + this->keyingtries == other->keyingtries && + this->use_mobike == other->use_mobike && + this->rekey_time == other->rekey_time && + this->reauth_time == other->reauth_time && + this->jitter_time == other->jitter_time && + this->over_time == other->over_time && + this->dpd_delay == other->dpd_delay && + this->dpd_action == other->dpd_action && + (this->my_virtual_ip == other->my_virtual_ip || + (this->my_virtual_ip && other->my_virtual_ip && + this->my_virtual_ip->equals(this->my_virtual_ip, other->my_virtual_ip))) && + (this->other_virtual_ip == other->other_virtual_ip || + (this->other_virtual_ip && other->other_virtual_ip && + this->other_virtual_ip->equals(this->other_virtual_ip, other->other_virtual_ip))) && + this->auth->equals(this->auth, other->auth) +#ifdef P2P + && this->p2p_mediation == other->p2p_mediation && + this->p2p_mediated_by == other->p2p_mediated_by && + (this->peer_id == other->peer_id || + (this->peer_id && other->peer_id && + this->peer_id->equals(this->peer_id, other->peer_id))) +#endif /* P2P */ + ); +} + /** * Implements peer_cfg_t.get_ref. */ @@ -537,6 +584,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg, this->public.get_my_virtual_ip = (host_t* (*) (peer_cfg_t *))get_my_virtual_ip; this->public.get_other_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_other_virtual_ip; this->public.get_auth = (auth_info_t*(*)(peer_cfg_t*))get_auth; + this->public.equals = (bool(*)(peer_cfg_t*, peer_cfg_t *other))equals; this->public.get_ref = (void(*)(peer_cfg_t *))get_ref; this->public.destroy = (void(*)(peer_cfg_t *))destroy; #ifdef P2P diff --git a/src/charon/config/peer_cfg.h b/src/charon/config/peer_cfg.h index 6c0601ff6..2053ce8e3 100644 --- a/src/charon/config/peer_cfg.h +++ b/src/charon/config/peer_cfg.h @@ -319,6 +319,16 @@ struct peer_cfg_t { */ identification_t* (*get_peer_id) (peer_cfg_t *this); #endif /* P2P */ + + /** + * Check if two peer configurations are equal. + * + * This method does not compare associated ike/child_cfg. + * + * @param other candidate to check for equality against this + * @return TRUE if peer_cfg and ike_cfg are equal + */ + bool (*equals)(peer_cfg_t *this, peer_cfg_t *other); /** * Get a new reference. diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c index 04ec28a61..b7552fc47 100644 --- a/src/charon/config/proposal.c +++ b/src/charon/config/proposal.c @@ -51,6 +51,7 @@ ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS, ); typedef struct private_proposal_t private_proposal_t; +typedef struct algorithm_t algorithm_t; /** * Private data of an proposal_t object @@ -98,10 +99,25 @@ struct private_proposal_t { u_int64_t spi; }; +/** + * 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 + */ + u_int16_t key_size; +}; + /** * Add algorithm/keysize to a algorithm list */ -static void add_algo(linked_list_t *list, u_int16_t algo, size_t key_size) +static void add_algo(linked_list_t *list, u_int16_t algo, u_int16_t key_size) { algorithm_t *algo_key; @@ -114,7 +130,8 @@ static void add_algo(linked_list_t *list, u_int16_t algo, size_t key_size) /** * Implements proposal_t.add_algorithm */ -static void add_algorithm(private_proposal_t *this, transform_type_t type, u_int16_t algo, size_t key_size) +static void add_algorithm(private_proposal_t *this, transform_type_t type, + u_int16_t algo, u_int16_t key_size) { switch (type) { @@ -139,41 +156,68 @@ static void add_algorithm(private_proposal_t *this, transform_type_t type, u_int } /** - * Implements proposal_t.create_algorithm_iterator. + * filter function for peer configs */ -static iterator_t *create_algorithm_iterator(private_proposal_t *this, transform_type_t type) +static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg, + void **unused, u_int16_t *key_size) { + algorithm_t *algo = *in; + *alg = algo->algorithm; + if (key_size) + { + *key_size = algo->key_size; + } + return TRUE; +} + +/** + * Implements proposal_t.create_enumerator. + */ +static enumerator_t *create_enumerator(private_proposal_t *this, + transform_type_t type) +{ + linked_list_t *list; + switch (type) { case ENCRYPTION_ALGORITHM: - return this->encryption_algos->create_iterator(this->encryption_algos, TRUE); - case INTEGRITY_ALGORITHM: - return this->integrity_algos->create_iterator(this->integrity_algos, TRUE); - case PSEUDO_RANDOM_FUNCTION: - return this->prf_algos->create_iterator(this->prf_algos, TRUE); - case DIFFIE_HELLMAN_GROUP: - return this->dh_groups->create_iterator(this->dh_groups, TRUE); - case EXTENDED_SEQUENCE_NUMBERS: - return this->esns->create_iterator(this->esns, TRUE); - default: + 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 NULL; + return enumerator_create_filter(list->create_enumerator(list), + (void*)alg_filter, NULL, NULL); } /** * Implements proposal_t.get_algorithm. */ -static bool get_algorithm(private_proposal_t *this, transform_type_t type, algorithm_t** algo) +static bool get_algorithm(private_proposal_t *this, transform_type_t type, + u_int16_t *alg, u_int16_t *key_size) { - iterator_t *iterator = create_algorithm_iterator(this, type); - if (iterator->iterate(iterator, (void**)algo)) + enumerator_t *enumerator; + bool found = FALSE; + + enumerator = create_enumerator(this, type); + if (enumerator->enumerate(enumerator, alg, key_size)) { - iterator->destroy(iterator); - return TRUE; + found = TRUE; } - iterator->destroy(iterator); - return FALSE; + enumerator->destroy(enumerator); + return found; } /** @@ -181,14 +225,15 @@ static bool get_algorithm(private_proposal_t *this, transform_type_t type, algor */ static bool has_dh_group(private_proposal_t *this, diffie_hellman_group_t group) { - algorithm_t *current; - iterator_t *iterator; bool result = FALSE; - iterator = this->dh_groups->create_iterator(this->dh_groups, TRUE); - if (iterator->get_count(iterator)) + if (this->dh_groups->get_count(this->dh_groups)) { - while (iterator->iterate(iterator, (void**)¤t)) + algorithm_t *current; + enumerator_t *enumerator; + + enumerator = this->dh_groups->create_enumerator(this->dh_groups); + while (enumerator->enumerate(enumerator, (void**)¤t)) { if (current->algorithm == group) { @@ -196,22 +241,36 @@ static bool has_dh_group(private_proposal_t *this, diffie_hellman_group_t group) break; } } + enumerator->destroy(enumerator); } else if (group == MODP_NONE) { result = TRUE; } - iterator->destroy(iterator); return result; } +/** + * Implementation of proposal_t.strip_dh. + */ +static void strip_dh(private_proposal_t *this) +{ + algorithm_t *alg; + + while (this->dh_groups->remove_last(this->dh_groups, (void**)&alg) == SUCCESS) + { + free(alg); + } +} + /** * Find a matching alg/keysize in two linked lists */ -static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, u_int16_t *alg, size_t *key_size) +static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, + u_int16_t *alg, size_t *key_size) { - iterator_t *first_iter, *second_iter; - algorithm_t *first_alg, *second_alg; + enumerator_t *e1, *e2; + algorithm_t *alg1, *alg2; /* if in both are zero algorithms specified, we HAVE a match */ if (first->get_count(first) == 0 && second->get_count(second) == 0) @@ -220,30 +279,31 @@ static bool select_algo(linked_list_t *first, linked_list_t *second, bool *add, return TRUE; } - first_iter = first->create_iterator(first, TRUE); - second_iter = second->create_iterator(second, TRUE); + e1 = first->create_enumerator(first); + e2 = second->create_enumerator(second); /* compare algs, order of algs in "first" is preferred */ - while (first_iter->iterate(first_iter, (void**)&first_alg)) + while (e1->enumerate(e1, &alg1)) { - second_iter->reset(second_iter); - while (second_iter->iterate(second_iter, (void**)&second_alg)) + e2->destroy(e2); + e2 = second->create_enumerator(second); + while (e2->enumerate(e2, &alg2)) { - if (first_alg->algorithm == second_alg->algorithm && - first_alg->key_size == second_alg->key_size) + if (alg1->algorithm == alg2->algorithm && + alg1->key_size == alg2->key_size) { /* ok, we have an algorithm */ - *alg = first_alg->algorithm; - *key_size = first_alg->key_size; + *alg = alg1->algorithm; + *key_size = alg1->key_size; *add = TRUE; - first_iter->destroy(first_iter); - second_iter->destroy(second_iter); + e1->destroy(e1); + e2->destroy(e2); return TRUE; } } } /* no match in all comparisons */ - first_iter->destroy(first_iter); - second_iter->destroy(second_iter); + e1->destroy(e1); + e2->destroy(e2); return FALSE; } @@ -377,14 +437,67 @@ static u_int64_t get_spi(private_proposal_t *this) static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list) { algorithm_t *algo, *clone_algo; - iterator_t *iterator = list->create_iterator(list, TRUE); - while (iterator->iterate(iterator, (void**)&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); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); +} + +/** + * check if an algorithm list equals + */ +static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2) +{ + enumerator_t *e1, *e2; + algorithm_t *alg1, *alg2; + 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)) + { + if (alg1->algorithm != alg2->algorithm || + alg1->key_size != alg2->key_size) + { + equals = FALSE; + break; + } + } + e1->destroy(e1); + e2->destroy(e2); + return equals; +} + +/** + * Implementation of proposal_t.equals. + */ +static bool equals(private_proposal_t *this, private_proposal_t *other) +{ + if (this == other) + { + return TRUE; + } + if (this->public.equals != other->public.equals) + { + return FALSE; + } + 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)); } /** @@ -548,14 +661,16 @@ proposal_t *proposal_create(protocol_id_t protocol) { private_proposal_t *this = malloc_thing(private_proposal_t); - this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,size_t))add_algorithm; - this->public.create_algorithm_iterator = (iterator_t* (*)(proposal_t*,transform_type_t))create_algorithm_iterator; - this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,algorithm_t**))get_algorithm; + this->public.add_algorithm = (void (*)(proposal_t*,transform_type_t,u_int16_t,u_int16_t))add_algorithm; + this->public.create_enumerator = (enumerator_t* (*)(proposal_t*,transform_type_t))create_enumerator; + this->public.get_algorithm = (bool (*)(proposal_t*,transform_type_t,u_int16_t*,u_int16_t*))get_algorithm; this->public.has_dh_group = (bool (*)(proposal_t*,diffie_hellman_group_t))has_dh_group; + this->public.strip_dh = (void(*)(proposal_t*))strip_dh; this->public.select = (proposal_t* (*)(proposal_t*,proposal_t*))select_proposal; this->public.get_protocol = (protocol_id_t(*)(proposal_t*))get_protocol; this->public.set_spi = (void(*)(proposal_t*,u_int64_t))set_spi; this->public.get_spi = (u_int64_t(*)(proposal_t*))get_spi; + this->public.equals = (bool(*)(proposal_t*, proposal_t *other))equals; this->public.clone = (proposal_t*(*)(proposal_t*))clone_; this->public.destroy = (void(*)(proposal_t*))destroy; diff --git a/src/charon/config/proposal.h b/src/charon/config/proposal.h index 0f3559012..8a05a0cfd 100644 --- a/src/charon/config/proposal.h +++ b/src/charon/config/proposal.h @@ -26,7 +26,6 @@ typedef enum protocol_id_t protocol_id_t; typedef enum transform_type_t transform_type_t; typedef enum extended_sequence_numbers_t extended_sequence_numbers_t; -typedef struct algorithm_t algorithm_t; typedef struct proposal_t proposal_t; #include @@ -85,24 +84,6 @@ enum extended_sequence_numbers_t { */ extern enum_name_t *extended_sequence_numbers_names; - - -/** - * Struct used to store different kinds of algorithms. The internal - * lists of algorithms contain such structures. - */ -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 - */ - u_int16_t key_size; -}; - /** * Stores a set of algorithms used for an SA. * @@ -129,15 +110,16 @@ struct proposal_t { * @param alg identifier for algorithm * @param key_size key size to use */ - void (*add_algorithm) (proposal_t *this, transform_type_t type, u_int16_t alg, size_t key_size); + void (*add_algorithm) (proposal_t *this, transform_type_t type, + u_int16_t alg, u_int16_t key_size); /** - * Get an iterator over algorithms for a specifc algo type. + * Get an enumerator over algorithms for a specifc algo type. * * @param type kind of algorithm - * @return iterator over algorithm_t's + * @return enumerator over u_int16_t alg, u_int16_t key_size */ - iterator_t *(*create_algorithm_iterator) (proposal_t *this, transform_type_t type); + enumerator_t *(*create_enumerator) (proposal_t *this, transform_type_t type); /** * Get the algorithm for a type to use. @@ -145,10 +127,12 @@ struct proposal_t { * If there are multiple algorithms, only the first is returned. * * @param type kind of algorithm - * @param algo pointer which receives algorithm and key size + * @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, algorithm_t** algo); + bool (*get_algorithm) (proposal_t *this, transform_type_t type, + u_int16_t *alg, u_int16_t *key_size); /** * Check if the proposal has a specific DH group. @@ -157,6 +141,11 @@ struct proposal_t { * @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. + */ + void (*strip_dh)(proposal_t *this); /** * Compare two proposal, and select a matching subset. @@ -191,6 +180,14 @@ struct proposal_t { */ void (*set_spi) (proposal_t *this, u_int64_t spi); + /** + * 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. * diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c index 02a74a1b7..3b706882e 100644 --- a/src/charon/config/traffic_selector.c +++ b/src/charon/config/traffic_selector.c @@ -718,6 +718,7 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, } default: { + net->destroy(net); free(this); return NULL; } @@ -727,6 +728,7 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, this->from_port = port; this->to_port = port; } + net->destroy(net); return (&this->public); } @@ -779,12 +781,11 @@ traffic_selector_t *traffic_selector_create_from_string( /* * see header */ -traffic_selector_t *traffic_selector_create_dynamic( - u_int8_t protocol, ts_type_t type, +traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol, u_int16_t from_port, u_int16_t to_port) { - private_traffic_selector_t *this = traffic_selector_create(protocol, type, - from_port, to_port); + private_traffic_selector_t *this = traffic_selector_create( + protocol, TS_IPV4_ADDR_RANGE, from_port, to_port); memset(this->from6, 0, sizeof(this->from6)); memset(this->to6, 0xFF, sizeof(this->to6)); @@ -827,4 +828,3 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, return this; } -/* vim: set ts=4 sw=4 noet: */ diff --git a/src/charon/config/traffic_selector.h b/src/charon/config/traffic_selector.h index 4b8b91ac7..a9fa9d7b1 100644 --- a/src/charon/config/traffic_selector.h +++ b/src/charon/config/traffic_selector.h @@ -263,15 +263,13 @@ traffic_selector_t *traffic_selector_create_from_subnet( * * * @param protocol upper layer protocl to allow - * @param type family type * @param from_port start of allowed port range * @param to_port end of range * @return * - traffic_selector_t object * - NULL if type not supported */ -traffic_selector_t *traffic_selector_create_dynamic( - u_int8_t protocol, ts_type_t type, +traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol, u_int16_t from_port, u_int16_t to_port); /** diff --git a/src/charon/credentials/auth_info.c b/src/charon/credentials/auth_info.c index 1148473ee..5e5ba045b 100644 --- a/src/charon/credentials/auth_info.c +++ b/src/charon/credentials/auth_info.c @@ -26,12 +26,14 @@ ENUM(auth_item_names, AUTHN_CA_CERT, AUTHZ_AC_GROUP, "AUTHN_CA_CERT", "AUTHN_CA_CERT_KEYID", + "AUTHN_CA_CERT_NAME", "AUTHN_IM_CERT", "AUTHN_SUBJECT_CERT", "AUTHZ_PUBKEY", "AUTHZ_PSK", "AUTHZ_EAP", "AUTHZ_CA_CERT", + "AUTHZ_CA_CERT_NAME", "AUTHZ_IM_CERT", "AUTHZ_SUBJECT_CERT", "AUTHZ_CRL_VALIDATION", @@ -164,6 +166,8 @@ static void add_item(private_auth_info_t *this, auth_item_t type, void *value) break; } case AUTHN_CA_CERT_KEYID: + case AUTHN_CA_CERT_NAME: + case AUTHZ_CA_CERT_NAME: case AUTHZ_AC_GROUP: { identification_t *id = (identification_t*)value; @@ -193,6 +197,7 @@ static bool complies(private_auth_info_t *this, auth_info_t *constraints) { case AUTHN_CA_CERT_KEYID: case AUTHN_CA_CERT: + case AUTHN_CA_CERT_NAME: case AUTHN_IM_CERT: case AUTHN_SUBJECT_CERT: { /* skip non-authorization tokens */ @@ -237,6 +242,7 @@ static bool complies(private_auth_info_t *this, auth_info_t *constraints) } break; } + case AUTHZ_CA_CERT_NAME: case AUTHZ_PUBKEY: case AUTHZ_PSK: case AUTHZ_IM_CERT: @@ -284,6 +290,97 @@ static void merge(private_auth_info_t *this, private_auth_info_t *other) } } +/** + * Implementation of auth_info_t.equals. + */ +static bool equals(private_auth_info_t *this, private_auth_info_t *other) +{ + enumerator_t *e1, *e2; + item_t *i1, *i2; + bool equal = TRUE, found; + + e1 = this->items->create_enumerator(this->items); + while (e1->enumerate(e1, &i1)) + { + found = FALSE; + e2 = this->items->create_enumerator(this->items); + while (e2->enumerate(e2, &i2)) + { + if (i1->type == i2->type) + { + switch (i1->type) + { + case AUTHZ_CRL_VALIDATION: + case AUTHZ_OCSP_VALIDATION: + { + cert_validation_t c1, c2; + + c1 = *(cert_validation_t*)i1->value; + c2 = *(cert_validation_t*)i2->value; + + if (c1 == c2) + { + found = TRUE; + break; + } + continue; + } + case AUTHN_CA_CERT: + case AUTHN_IM_CERT: + case AUTHN_SUBJECT_CERT: + case AUTHZ_CA_CERT: + case AUTHZ_IM_CERT: + case AUTHZ_SUBJECT_CERT: + { + certificate_t *c1, *c2; + + c1 = (certificate_t*)i1->value; + c2 = (certificate_t*)i2->value; + + if (c1->equals(c1, c2)) + { + found = TRUE; + break; + } + continue; + } + case AUTHN_CA_CERT_KEYID: + case AUTHN_CA_CERT_NAME: + case AUTHZ_CA_CERT_NAME: + { + identification_t *c1, *c2; + + c1 = (identification_t*)i1->value; + c2 = (identification_t*)i2->value; + + if (c1->equals(c1, c2)) + { + found = TRUE; + break; + } + continue; + } + case AUTHZ_PUBKEY: + case AUTHZ_PSK: + case AUTHZ_EAP: + case AUTHZ_AC_GROUP: + /* TODO: implement value comparison */ + break; + } + break; + } + } + e2->destroy(e2); + if (!found) + { + equal = FALSE; + break; + } + } + e1->destroy(e1); + return equal; +} + /** * Implementation of auth_info_t.destroy */ @@ -326,6 +423,8 @@ static void destroy(private_auth_info_t *this) break; } case AUTHN_CA_CERT_KEYID: + case AUTHN_CA_CERT_NAME: + case AUTHZ_CA_CERT_NAME: case AUTHZ_AC_GROUP: { identification_t *id = (identification_t*)item->value; @@ -351,6 +450,7 @@ auth_info_t *auth_info_create() this->public.create_item_enumerator = (enumerator_t*(*)(auth_info_t*))create_item_enumerator; this->public.complies = (bool(*)(auth_info_t*, auth_info_t *))complies; this->public.merge = (void(*)(auth_info_t*, auth_info_t *other))merge; + this->public.equals = (bool(*)(auth_info_t*, auth_info_t *other))equals; this->public.destroy = (void(*)(auth_info_t*))destroy; this->items = linked_list_create(); diff --git a/src/charon/credentials/auth_info.h b/src/charon/credentials/auth_info.h index 15cae4fcd..5a4ecf90e 100644 --- a/src/charon/credentials/auth_info.h +++ b/src/charon/credentials/auth_info.h @@ -63,6 +63,8 @@ enum auth_item_t { AUTHN_CA_CERT, /** Keyid of a CA certificate to use, value is identification_t* */ AUTHN_CA_CERT_KEYID, + /** subject DN of a CA certificate to use, value is identification_t* */ + AUTHN_CA_CERT_NAME, /** intermediate certificate, value is certificate_t* */ AUTHN_IM_CERT, /** certificate for trustchain verification, value is certificate_t* */ @@ -80,6 +82,8 @@ enum auth_item_t { AUTHZ_EAP, /** certificate authority, value is certificate_t* */ AUTHZ_CA_CERT, + /** subject DN of a certificate authority, value is identification_t* */ + AUTHZ_CA_CERT_NAME, /** intermediate certificate in trustchain, value is certificate_t* */ AUTHZ_IM_CERT, /** subject certificate, value is certificate_t* */ @@ -146,6 +150,14 @@ struct auth_info_t { */ void (*merge)(auth_info_t *this, auth_info_t *other); + /** + * Check two auth_infos for equality. + * + * @param other other item to compaire against this + * @return TRUE if auth infos identical + */ + bool (*equals)(auth_info_t *this, auth_info_t *other); + /** * Destroy a auth_info instance with all associated values. */ diff --git a/src/charon/encoding/payloads/proposal_substructure.c b/src/charon/encoding/payloads/proposal_substructure.c index 0baa5c286..65398e087 100644 --- a/src/charon/encoding/payloads/proposal_substructure.c +++ b/src/charon/encoding/payloads/proposal_substructure.c @@ -516,60 +516,62 @@ proposal_substructure_t *proposal_substructure_create() */ proposal_substructure_t *proposal_substructure_create_from_proposal(proposal_t *proposal) { - private_proposal_substructure_t *this = (private_proposal_substructure_t*) - proposal_substructure_create(); - iterator_t *iterator; - algorithm_t *algo; transform_substructure_t *transform; + private_proposal_substructure_t *this; + u_int16_t alg, key_size; + enumerator_t *enumerator; + + this = (private_proposal_substructure_t*)proposal_substructure_create(); /* encryption algorithm is only availble in ESP */ - iterator = proposal->create_algorithm_iterator(proposal, ENCRYPTION_ALGORITHM); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM); + while (enumerator->enumerate(enumerator, &alg, &key_size)) { transform = transform_substructure_create_type(ENCRYPTION_ALGORITHM, - algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); + alg, key_size); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* integrity algorithms */ - iterator = proposal->create_algorithm_iterator(proposal, INTEGRITY_ALGORITHM); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM); + while (enumerator->enumerate(enumerator, &alg, &key_size)) { transform = transform_substructure_create_type(INTEGRITY_ALGORITHM, - algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); + alg, key_size); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* prf algorithms */ - iterator = proposal->create_algorithm_iterator(proposal, PSEUDO_RANDOM_FUNCTION); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION); + while (enumerator->enumerate(enumerator, &alg, &key_size)) { transform = transform_substructure_create_type(PSEUDO_RANDOM_FUNCTION, - algo->algorithm, algo->key_size); - this->public.add_transform_substructure(&(this->public), transform); + alg, key_size); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* dh groups */ - iterator = proposal->create_algorithm_iterator(proposal, DIFFIE_HELLMAN_GROUP); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP); + while (enumerator->enumerate(enumerator, &alg, NULL)) { - transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP, algo->algorithm, 0); - this->public.add_transform_substructure(&(this->public), transform); + transform = transform_substructure_create_type(DIFFIE_HELLMAN_GROUP, + alg, 0); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* extended sequence numbers */ - iterator = proposal->create_algorithm_iterator(proposal, EXTENDED_SEQUENCE_NUMBERS); - while (iterator->iterate(iterator, (void**)&algo)) + enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS); + while (enumerator->enumerate(enumerator, &alg, NULL)) { transform = transform_substructure_create_type(EXTENDED_SEQUENCE_NUMBERS, - algo->algorithm, 0); - this->public.add_transform_substructure(&(this->public), transform); + alg, 0); + add_transform_substructure(this, transform); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); /* add SPI, if necessary */ switch (proposal->get_protocol(proposal)) diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index 88df4f3d2..9a6ff1a52 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -146,19 +146,15 @@ kernel_algorithm_t integrity_algs[] = { * Look up a kernel algorithm name and its key size */ char* lookup_algorithm(kernel_algorithm_t *kernel_algo, - algorithm_t *ikev2_algo, u_int *key_size) + u_int16_t ikev2_algo, u_int16_t *key_size) { while (kernel_algo->ikev2_id != END_OF_LIST) { - if (ikev2_algo->algorithm == kernel_algo->ikev2_id) + if (ikev2_algo == kernel_algo->ikev2_id) { /* match, evaluate key length */ - if (ikev2_algo->key_size) - { /* variable length */ - *key_size = ikev2_algo->key_size; - } - else - { /* fixed length */ + if (*key_size == 0) + { /* update key size of not set */ *key_size = kernel_algo->key_size; } return kernel_algo->name; @@ -1901,13 +1897,13 @@ static status_t add_sa(private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, u_int64_t expire_soft, u_int64_t expire_hard, - algorithm_t *enc_alg, algorithm_t *int_alg, + u_int16_t enc_alg, u_int16_t enc_size, + u_int16_t int_alg, u_int16_t int_size, prf_plus_t *prf_plus, mode_t mode, bool encap, bool replace) { unsigned char request[BUFFER_SIZE]; char *alg_name; - u_int key_size; struct nlmsghdr *hdr; struct xfrm_usersa_info *sa; @@ -1942,20 +1938,20 @@ static status_t add_sa(private_kernel_interface_t *this, struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_info); - if (enc_alg->algorithm != ENCR_UNDEFINED) + if (enc_alg != ENCR_UNDEFINED) { rthdr->rta_type = XFRMA_ALG_CRYPT; - alg_name = lookup_algorithm(encryption_algs, enc_alg, &key_size); + alg_name = lookup_algorithm(encryption_algs, enc_alg, &enc_size); if (alg_name == NULL) { DBG1(DBG_KNL, "algorithm %N not supported by kernel!", - encryption_algorithm_names, enc_alg->algorithm); + encryption_algorithm_names, enc_alg); return FAILED; } DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", - encryption_algorithm_names, enc_alg->algorithm, key_size); + encryption_algorithm_names, enc_alg, enc_size); - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + key_size); + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_size); hdr->nlmsg_len += rthdr->rta_len; if (hdr->nlmsg_len > sizeof(request)) { @@ -1963,27 +1959,27 @@ static status_t add_sa(private_kernel_interface_t *this, } struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); - algo->alg_key_len = key_size; + algo->alg_key_len = enc_size; strcpy(algo->alg_name, alg_name); - prf_plus->get_bytes(prf_plus, key_size / 8, algo->alg_key); + prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key); rthdr = XFRM_RTA_NEXT(rthdr); } - if (int_alg->algorithm != AUTH_UNDEFINED) + if (int_alg != AUTH_UNDEFINED) { rthdr->rta_type = XFRMA_ALG_AUTH; - alg_name = lookup_algorithm(integrity_algs, int_alg, &key_size); + alg_name = lookup_algorithm(integrity_algs, int_alg, &int_size); if (alg_name == NULL) { DBG1(DBG_KNL, "algorithm %N not supported by kernel!", - integrity_algorithm_names, int_alg->algorithm); + integrity_algorithm_names, int_alg); return FAILED; } DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", - integrity_algorithm_names, int_alg->algorithm, key_size); + integrity_algorithm_names, int_alg, int_size); - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + key_size); + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_size); hdr->nlmsg_len += rthdr->rta_len; if (hdr->nlmsg_len > sizeof(request)) { @@ -1991,9 +1987,9 @@ static status_t add_sa(private_kernel_interface_t *this, } struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); - algo->alg_key_len = key_size; + algo->alg_key_len = int_size; strcpy(algo->alg_name, alg_name); - prf_plus->get_bytes(prf_plus, key_size / 8, algo->alg_key); + prf_plus->get_bytes(prf_plus, int_size / 8, algo->alg_key); rthdr = XFRM_RTA_NEXT(rthdr); } @@ -2592,7 +2588,7 @@ kernel_interface_t *kernel_interface_create() /* public functions */ this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; - this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,mode_t,bool,bool))add_sa; + this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,mode_t,bool,bool))add_sa; this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa; this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa; this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa; diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h index 624316d97..5e2bff5d8 100644 --- a/src/charon/kernel/kernel_interface.h +++ b/src/charon/kernel/kernel_interface.h @@ -96,7 +96,9 @@ struct kernel_interface_t { * @param expire_soft lifetime in seconds before rekeying * @param expire_hard lieftime in seconds before delete * @param enc_alg Algorithm to use for encryption (ESP only) + * @param enc_size key length of encryption algorithm, if dynamic * @param int_alg Algorithm to use for integrity protection + * @param int_size key length of integrity algorithm, if dynamic * @param prf_plus PRF to derive keys from * @param mode mode of the SA (tunnel, transport) * @param encap enable UDP encapsulation for NAT traversal @@ -107,7 +109,8 @@ struct kernel_interface_t { host_t *src, host_t *dst, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, u_int64_t expire_soft, u_int64_t expire_hard, - algorithm_t *enc_alg, algorithm_t *int_alg, + u_int16_t enc_alg, u_int16_t enc_size, + u_int16_t int_alg, u_int16_t int_size, prf_plus_t *prf_plus, mode_t mode, bool encap, bool update); diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index 225b8902d..7cd36d68e 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -110,12 +110,22 @@ struct private_child_sa_t { /** * encryption algorithm used for this SA */ - algorithm_t encryption; + u_int16_t enc_alg; + + /** + * key size of enc_alg + */ + u_int16_t enc_size; /** * integrity protection algorithm used for this SA */ - algorithm_t integrity; + u_int16_t int_alg; + + /** + * key size of int_alg + */ + u_int16_t int_size; /** * time, on which SA was installed @@ -246,10 +256,10 @@ static void get_stats(private_child_sa_t *this, mode_t *mode, iterator->destroy(iterator); *mode = this->mode; - *encr_algo = this->encryption.algorithm; - *encr_len = this->encryption.key_size; - *int_algo = this->integrity.algorithm; - *int_len = this->integrity.key_size; + *encr_algo = this->enc_alg; + *encr_len = this->enc_size; + *int_algo = this->int_alg; + *int_len = this->int_size; *rekey = this->rekey_time; *use_in = in; *use_out = out; @@ -493,10 +503,7 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) static status_t install(private_child_sa_t *this, proposal_t *proposal, mode_t mode, prf_plus_t *prf_plus, bool mine) { - u_int32_t spi, soft, hard;; - algorithm_t *enc_algo, *int_algo; - algorithm_t enc_algo_none = {ENCR_UNDEFINED, 0}; - algorithm_t int_algo_none = {AUTH_UNDEFINED, 0}; + u_int32_t spi, soft, hard; host_t *src; host_t *dst; status_t status; @@ -544,43 +551,32 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, protocol_id_names, this->protocol); /* select encryption algo */ - if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_algo)) + if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, + &this->enc_alg, &this->enc_size)) { - DBG2(DBG_CHD, " using %N for encryption", - encryption_algorithm_names, enc_algo->algorithm); - } - else - { - enc_algo = &enc_algo_none; + DBG2(DBG_CHD, " using %N for encryption", + encryption_algorithm_names, this->enc_alg); } /* select integrity algo */ - if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_algo)) + if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, + &this->int_alg, &this->int_size)) { DBG2(DBG_CHD, " using %N for integrity", - integrity_algorithm_names, int_algo->algorithm); + integrity_algorithm_names, this->int_alg); } - else - { - int_algo = &int_algo_none; - } - soft = this->config->get_lifetime(this->config, TRUE); hard = this->config->get_lifetime(this->config, FALSE); /* send SA down to the kernel */ DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst); status = charon->kernel_interface->add_sa(charon->kernel_interface, - src, dst, spi, this->protocol, - this->reqid, mine ? soft : 0, - hard, enc_algo, int_algo, - prf_plus, mode, this->encap, mine); - - this->encryption = *enc_algo; - this->integrity = *int_algo; + src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard, + this->enc_alg, this->enc_size, this->int_alg, this->int_size, + prf_plus, mode, this->encap, mine); + this->install_time = time(NULL); this->rekey_time = this->install_time + soft; - return status; } @@ -987,10 +983,10 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->state = CHILD_CREATED; /* reuse old reqid if we are rekeying an existing CHILD_SA */ this->reqid = rekey ? rekey : ++reqid; - this->encryption.algorithm = ENCR_UNDEFINED; - this->encryption.key_size = 0; - this->integrity.algorithm = AUTH_UNDEFINED; - this->encryption.key_size = 0; + this->enc_alg = ENCR_UNDEFINED; + this->enc_size = 0; + this->int_alg = AUTH_UNDEFINED; + this->int_size = 0; this->policies = linked_list_create(); this->my_ts = linked_list_create(); this->other_ts = linked_list_create(); diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 4e28b27dc..33537bc74 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -1639,8 +1639,7 @@ static status_t derive_keys(private_ike_sa_t *this, { prf_plus_t *prf_plus; chunk_t skeyseed, key, nonces, prf_plus_seed; - algorithm_t *algo; - size_t key_size; + u_int16_t alg, key_size; crypter_t *crypter_i, *crypter_r; signer_t *signer_i, *signer_r; u_int8_t spi_i_buf[sizeof(u_int64_t)], spi_r_buf[sizeof(u_int64_t)]; @@ -1648,18 +1647,18 @@ static status_t derive_keys(private_ike_sa_t *this, chunk_t spi_r = chunk_from_buf(spi_r_buf); /* Create SAs general purpose PRF first, we may use it here */ - if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo)) + if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL)) { DBG1(DBG_IKE, "no %N selected", transform_type_names, PSEUDO_RANDOM_FUNCTION); return FAILED; } - this->prf = lib->crypto->create_prf(lib->crypto, algo->algorithm); + this->prf = lib->crypto->create_prf(lib->crypto, alg); if (this->prf == NULL) { DBG1(DBG_IKE, "%N %N not supported!", transform_type_names, PSEUDO_RANDOM_FUNCTION, - pseudo_random_function_names, algo->algorithm); + pseudo_random_function_names, alg); return FAILED; } @@ -1702,8 +1701,8 @@ static status_t derive_keys(private_ike_sa_t *this, /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */ /* SK_d is used for generating CHILD_SA key mat => child_prf */ - proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo); - this->child_prf = lib->crypto->create_prf(lib->crypto, algo->algorithm); + proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL); + this->child_prf = lib->crypto->create_prf(lib->crypto, alg); key_size = this->child_prf->get_key_size(this->child_prf); prf_plus->allocate_bytes(prf_plus, key_size, &key); DBG4(DBG_IKE, "Sk_d secret %B", &key); @@ -1711,19 +1710,19 @@ static status_t derive_keys(private_ike_sa_t *this, chunk_free(&key); /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */ - if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo)) + if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)) { DBG1(DBG_IKE, "no %N selected", transform_type_names, INTEGRITY_ALGORITHM); return FAILED; } - signer_i = lib->crypto->create_signer(lib->crypto, algo->algorithm); - signer_r = lib->crypto->create_signer(lib->crypto, algo->algorithm); + signer_i = lib->crypto->create_signer(lib->crypto, alg); + signer_r = lib->crypto->create_signer(lib->crypto, alg); if (signer_i == NULL || signer_r == NULL) { DBG1(DBG_IKE, "%N %N not supported!", transform_type_names, INTEGRITY_ALGORITHM, - integrity_algorithm_names ,algo->algorithm); + integrity_algorithm_names ,alg); prf_plus->destroy(prf_plus); return FAILED; } @@ -1751,22 +1750,20 @@ static status_t derive_keys(private_ike_sa_t *this, } /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */ - if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo)) + if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size)) { DBG1(DBG_IKE, "no %N selected", transform_type_names, ENCRYPTION_ALGORITHM); prf_plus->destroy(prf_plus); return FAILED; } - crypter_i = lib->crypto->create_crypter(lib->crypto, algo->algorithm, - algo->key_size / 8); - crypter_r = lib->crypto->create_crypter(lib->crypto, algo->algorithm, - algo->key_size / 8); + crypter_i = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8); + crypter_r = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8); if (crypter_i == NULL || crypter_r == NULL) { DBG1(DBG_IKE, "%N %N (key size %d) not supported!", transform_type_names, ENCRYPTION_ALGORITHM, - encryption_algorithm_names, algo->algorithm, algo->key_size); + encryption_algorithm_names, alg, key_size); prf_plus->destroy(prf_plus); return FAILED; } diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index d933d6267..8b711e8f3 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -222,11 +222,11 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) if (!this->proposal->has_dh_group(this->proposal, this->dh_group)) { - algorithm_t *algo; + u_int16_t group; + if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, - &algo)) + &group, NULL)) { - u_int16_t group = algo->algorithm; SIG(CHILD_UP_FAILED, "DH group %N inacceptable, requesting %N", diffie_hellman_group_names, this->dh_group, diffie_hellman_group_names, group); diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c index 6bb3688ea..27d2d40a7 100644 --- a/src/charon/sa/tasks/ike_init.c +++ b/src/charon/sa/tasks/ike_init.c @@ -316,11 +316,11 @@ static status_t build_r(private_ike_init_t *this, message_t *message) !this->proposal->has_dh_group(this->proposal, this->dh_group) || this->dh->get_shared_secret(this->dh, &secret) != SUCCESS) { - algorithm_t *algo; + u_int16_t group; + if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, - &algo)) + &group, NULL)) { - u_int16_t group = algo->algorithm; SIG(CHILD_UP_FAILED, "DH group %N inacceptable, requesting %N", diffie_hellman_group_names, this->dh_group, diffie_hellman_group_names, group);