proposal: Generalize KE methods

This commit is contained in:
Tobias Brunner 2018-07-09 16:27:04 +02:00 committed by Andreas Steffen
parent ea1fb56281
commit 80ad22563a
6 changed files with 91 additions and 38 deletions

View File

@ -796,13 +796,13 @@ static linked_list_t *get_proposals(private_quick_mode_t *this,
{
if (group != MODP_NONE)
{
if (!proposal->has_ke_method(proposal, group))
if (!proposal->has_transform(proposal, KEY_EXCHANGE_METHOD, group))
{
list->remove_at(list, enumerator);
proposal->destroy(proposal);
continue;
}
proposal->promote_ke_method(proposal, group);
proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD, group);
}
proposal->set_spi(proposal, this->spi_i);
}

View File

@ -316,7 +316,8 @@ static bool update_and_check_proposals(private_child_create_t *this)
if (this->dh_group != MODP_NONE)
{ /* proposals that don't contain the selected group are
* moved to the back */
if (!proposal->promote_ke_method(proposal, this->dh_group))
if (!proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD,
this->dh_group))
{
this->proposals->remove_at(this->proposals, enumerator);
other_dh_groups->insert_last(other_dh_groups, proposal);
@ -598,7 +599,8 @@ static status_t select_and_install(private_child_create_t *this,
}
this->child_sa->set_proposal(this->child_sa, this->proposal);
if (!this->proposal->has_ke_method(this->proposal, this->dh_group))
if (!this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
this->dh_group))
{
uint16_t group;

View File

@ -332,7 +332,8 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
proposal->set_spi(proposal, id->get_initiator_spi(id));
}
/* move the selected DH group to the front of the proposal */
if (!proposal->promote_ke_method(proposal, this->dh_group))
if (!proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD,
this->dh_group))
{ /* the proposal does not include the group, move to the back */
proposal_list->remove_at(proposal_list, enumerator);
other_dh_groups->insert_last(other_dh_groups, proposal);
@ -616,7 +617,8 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
}
if (ke_payload && this->proposal &&
this->proposal->has_ke_method(this->proposal, this->dh_group))
this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
this->dh_group))
{
if (!this->initiator)
{
@ -828,7 +830,8 @@ METHOD(task_t, build_r, status_t,
}
if (this->dh == NULL ||
!this->proposal->has_ke_method(this->proposal, this->dh_group))
!this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
this->dh_group))
{
uint16_t group;
@ -1063,7 +1066,8 @@ METHOD(task_t, process_i, status_t,
}
if (this->dh == NULL ||
!this->proposal->has_ke_method(this->proposal, this->dh_group))
!this->proposal->has_transform(this->proposal, KEY_EXCHANGE_METHOD,
this->dh_group))
{
DBG1(DBG_IKE, "peer DH group selection invalid");
return FAILED;

View File

@ -251,18 +251,18 @@ METHOD(proposal_t, get_algorithm, bool,
return found;
}
METHOD(proposal_t, has_ke_method, bool,
private_proposal_t *this, key_exchange_method_t ke)
METHOD(proposal_t, has_transform, bool,
private_proposal_t *this, transform_type_t type, uint16_t alg)
{
bool found = FALSE, any = FALSE;
enumerator_t *enumerator;
uint16_t current;
enumerator = create_enumerator(this, KEY_EXCHANGE_METHOD);
enumerator = create_enumerator(this, type);
while (enumerator->enumerate(enumerator, &current, NULL))
{
any = TRUE;
if (current == ke)
if (current == alg)
{
found = TRUE;
break;
@ -270,15 +270,15 @@ METHOD(proposal_t, has_ke_method, bool,
}
enumerator->destroy(enumerator);
if (!any && ke == MODP_NONE)
if (!any && alg == 0)
{
found = TRUE;
}
return found;
}
METHOD(proposal_t, promote_ke_method, bool,
private_proposal_t *this, key_exchange_method_t method)
METHOD(proposal_t, promote_transform, bool,
private_proposal_t *this, transform_type_t type, uint16_t alg)
{
enumerator_t *enumerator;
entry_t *entry;
@ -287,8 +287,8 @@ METHOD(proposal_t, promote_ke_method, bool,
enumerator = array_create_enumerator(this->transforms);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->type == KEY_EXCHANGE_METHOD &&
entry->alg == method)
if (entry->type == type &&
entry->alg == alg)
{
array_remove_at(this->transforms, enumerator);
found = TRUE;
@ -299,8 +299,8 @@ METHOD(proposal_t, promote_ke_method, bool,
if (found)
{
entry_t entry = {
.type = KEY_EXCHANGE_METHOD,
.alg = method,
.type = type,
.alg = alg,
};
array_insert(this->transforms, ARRAY_HEAD, &entry);
}
@ -942,8 +942,8 @@ proposal_t *proposal_create_v1(protocol_id_t protocol, uint8_t number,
.add_algorithm = _add_algorithm,
.create_enumerator = _create_enumerator,
.get_algorithm = _get_algorithm,
.has_ke_method = _has_ke_method,
.promote_ke_method = _promote_ke_method,
.has_transform = _has_transform,
.promote_transform = _promote_transform,
.select = _select_proposal,
.matches = _matches,
.get_protocol = _get_protocol,

View File

@ -109,21 +109,26 @@ struct proposal_t {
uint16_t *alg, uint16_t *key_size);
/**
* Check if the proposal has a specific key exchange method.
* Check if the proposal has a specific transform.
*
* @param method key exchange method to check for
* @param type kind of algorithm
* @param alg algorithm to check for (if 0, TRUE is returned if
* no transform of the given type is found)
* @return TRUE if algorithm included
*/
bool (*has_ke_method)(proposal_t *this, key_exchange_method_t method);
bool (*has_transform)(proposal_t *this, transform_type_t type,
uint16_t alg);
/**
* Move the given key exchange method to the front of the list if it was
* contained in the proposal.
* Move the given transform to the front of the list if it was contained in
* the proposal.
*
* @param method key exchange method to promote
* @param type kind of algorithm
* @param alg algorithm to promote
* @return TRUE if algorithm included
*/
bool (*promote_ke_method)(proposal_t *this, key_exchange_method_t method);
bool (*promote_transform)(proposal_t *this, transform_type_t type,
uint16_t alg);
/**
* Compare two proposals and select a matching subset.

View File

@ -300,38 +300,75 @@ START_TEST(test_select_proposal)
}
END_TEST
START_TEST(test_promote_ke_method)
START_TEST(test_has_transform)
{
proposal_t *proposal;
proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha256-modp3072-ecp256");
ck_assert(proposal->promote_ke_method(proposal, ECP_256_BIT));
ck_assert(proposal->has_transform(proposal, KEY_EXCHANGE_METHOD,
MODP_3072_BIT));
ck_assert(proposal->has_transform(proposal, KEY_EXCHANGE_METHOD,
ECP_256_BIT));
ck_assert(!proposal->has_transform(proposal, KEY_EXCHANGE_METHOD,
MODP_2048_BIT));
proposal->destroy(proposal);
}
END_TEST
START_TEST(test_has_transform_none)
{
proposal_t *proposal;
proposal = proposal_create_from_string(PROTO_ESP,
"aes128-sha256");
ck_assert(proposal->has_transform(proposal, KEY_EXCHANGE_METHOD,
MODP_NONE));
proposal->destroy(proposal);
proposal = proposal_create_from_string(PROTO_ESP,
"aes128-sha256-modp3072");
ck_assert(!proposal->has_transform(proposal, KEY_EXCHANGE_METHOD,
MODP_NONE));
proposal->destroy(proposal);
}
END_TEST
START_TEST(test_promote_transform)
{
proposal_t *proposal;
proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha256-modp3072-ecp256");
ck_assert(proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD,
ECP_256_BIT));
assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/MODP_3072");
proposal->destroy(proposal);
}
END_TEST
START_TEST(test_promote_ke_method_already_front)
START_TEST(test_promote_transform_already_front)
{
proposal_t *proposal;
proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha256-modp3072-ecp256");
ck_assert(proposal->promote_ke_method(proposal, MODP_3072_BIT));
ck_assert(proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD,
MODP_3072_BIT));
assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256");
proposal->destroy(proposal);
}
END_TEST
START_TEST(test_promote_ke_method_not_contained)
START_TEST(test_promote_transform_not_contained)
{
proposal_t *proposal;
proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha256-modp3072-ecp256");
ck_assert(!proposal->promote_ke_method(proposal, MODP_2048_BIT));
ck_assert(!proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD,
MODP_2048_BIT));
assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256");
proposal->destroy(proposal);
}
@ -504,10 +541,15 @@ Suite *proposal_suite_create()
countof(select_proposal_data));
suite_add_tcase(s, tc);
tc = tcase_create("promote_ke_method");
tcase_add_test(tc, test_promote_ke_method);
tcase_add_test(tc, test_promote_ke_method_already_front);
tcase_add_test(tc, test_promote_ke_method_not_contained);
tc = tcase_create("has_transform");
tcase_add_test(tc, test_has_transform);
tcase_add_test(tc, test_has_transform_none);
suite_add_tcase(s, tc);
tc = tcase_create("promote_transform");
tcase_add_test(tc, test_promote_transform);
tcase_add_test(tc, test_promote_transform_already_front);
tcase_add_test(tc, test_promote_transform_not_contained);
suite_add_tcase(s, tc);
tc = tcase_create("unknown transform types");