proposal: Generalize KE methods

This commit is contained in:
Tobias Brunner
2022-06-29 10:28:50 +02:00
parent b7c167f972
commit 3bebf5bf8d
6 changed files with 111 additions and 41 deletions
+2 -2
View File
@@ -797,13 +797,13 @@ static linked_list_t *get_proposals(private_quick_mode_t *this,
{ {
if (group != KE_NONE) if (group != KE_NONE)
{ {
if (!proposal->has_ke_method(proposal, group)) if (!proposal->has_transform(proposal, KEY_EXCHANGE_METHOD, group))
{ {
list->remove_at(list, enumerator); list->remove_at(list, enumerator);
proposal->destroy(proposal); proposal->destroy(proposal);
continue; continue;
} }
proposal->promote_ke_method(proposal, group); proposal->promote_transform(proposal, KEY_EXCHANGE_METHOD, group);
} }
proposal->set_spi(proposal, this->spi_i); proposal->set_spi(proposal, this->spi_i);
} }
+4 -2
View File
@@ -328,7 +328,8 @@ static bool update_and_check_proposals(private_child_create_t *this)
if (this->dh_group != KE_NONE) if (this->dh_group != KE_NONE)
{ /* proposals that don't contain the selected group are { /* proposals that don't contain the selected group are
* moved to the back */ * 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); this->proposals->remove_at(this->proposals, enumerator);
other_dh_groups->insert_last(other_dh_groups, proposal); other_dh_groups->insert_last(other_dh_groups, proposal);
@@ -554,7 +555,8 @@ static status_t select_and_install(private_child_create_t *this,
} }
this->child_sa->set_proposal(this->child_sa, this->proposal); 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; uint16_t group;
+8 -4
View File
@@ -333,7 +333,8 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
proposal->set_spi(proposal, id->get_initiator_spi(id)); proposal->set_spi(proposal, id->get_initiator_spi(id));
} }
/* move the selected DH group to the front of the proposal */ /* 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 */ { /* the proposal does not include the group, move to the back */
proposal_list->remove_at(proposal_list, enumerator); proposal_list->remove_at(proposal_list, enumerator);
other_dh_groups->insert_last(other_dh_groups, proposal); other_dh_groups->insert_last(other_dh_groups, proposal);
@@ -617,7 +618,8 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
} }
if (ke_payload && this->proposal && 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) if (!this->initiator)
{ {
@@ -829,7 +831,8 @@ METHOD(task_t, build_r, status_t,
} }
if (this->dh == NULL || 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; uint16_t group;
@@ -1064,7 +1067,8 @@ METHOD(task_t, process_i, status_t,
} }
if (this->dh == NULL || 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"); DBG1(DBG_IKE, "peer DH group selection invalid");
return FAILED; return FAILED;
+19 -16
View File
@@ -252,34 +252,37 @@ METHOD(proposal_t, get_algorithm, bool,
return found; return found;
} }
METHOD(proposal_t, has_ke_method, bool, METHOD(proposal_t, has_transform, bool,
private_proposal_t *this, key_exchange_method_t ke) private_proposal_t *this, transform_type_t type, uint16_t alg)
{ {
bool found = FALSE, any = FALSE; bool found = FALSE, any = FALSE;
enumerator_t *enumerator; enumerator_t *enumerator;
uint16_t current; uint16_t current;
enumerator = create_enumerator(this, KEY_EXCHANGE_METHOD); enumerator = create_enumerator(this, type);
while (enumerator->enumerate(enumerator, &current, NULL)) while (enumerator->enumerate(enumerator, &current, NULL))
{ {
any = TRUE; if (current)
if (current == ke)
{ {
found = TRUE; any = TRUE;
break; if (alg && current == alg)
{
found = TRUE;
break;
}
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
if (!any && ke == KE_NONE) if (!any && !alg)
{ {
found = TRUE; found = TRUE;
} }
return found; return found;
} }
METHOD(proposal_t, promote_ke_method, bool, METHOD(proposal_t, promote_transform, bool,
private_proposal_t *this, key_exchange_method_t method) private_proposal_t *this, transform_type_t type, uint16_t alg)
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
entry_t *entry; entry_t *entry;
@@ -288,8 +291,8 @@ METHOD(proposal_t, promote_ke_method, bool,
enumerator = array_create_enumerator(this->transforms); enumerator = array_create_enumerator(this->transforms);
while (enumerator->enumerate(enumerator, &entry)) while (enumerator->enumerate(enumerator, &entry))
{ {
if (entry->type == KEY_EXCHANGE_METHOD && if (entry->type == type &&
entry->alg == method) entry->alg == alg)
{ {
array_remove_at(this->transforms, enumerator); array_remove_at(this->transforms, enumerator);
found = TRUE; found = TRUE;
@@ -300,8 +303,8 @@ METHOD(proposal_t, promote_ke_method, bool,
if (found) if (found)
{ {
entry_t entry = { entry_t entry = {
.type = KEY_EXCHANGE_METHOD, .type = type,
.alg = method, .alg = alg,
}; };
array_insert(this->transforms, ARRAY_HEAD, &entry); array_insert(this->transforms, ARRAY_HEAD, &entry);
} }
@@ -943,8 +946,8 @@ proposal_t *proposal_create_v1(protocol_id_t protocol, uint8_t number,
.add_algorithm = _add_algorithm, .add_algorithm = _add_algorithm,
.create_enumerator = _create_enumerator, .create_enumerator = _create_enumerator,
.get_algorithm = _get_algorithm, .get_algorithm = _get_algorithm,
.has_ke_method = _has_ke_method, .has_transform = _has_transform,
.promote_ke_method = _promote_ke_method, .promote_transform = _promote_transform,
.select = _select_proposal, .select = _select_proposal,
.matches = _matches, .matches = _matches,
.get_protocol = _get_protocol, .get_protocol = _get_protocol,
+12 -7
View File
@@ -110,21 +110,26 @@ struct proposal_t {
uint16_t *alg, uint16_t *key_size); 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 * @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 * Move the given transform to the front of the list if it was contained in
* contained in the proposal. * the proposal.
* *
* @param method key exchange method to promote * @param type kind of algorithm
* @param alg algorithm to promote
* @return TRUE if algorithm included * @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. * Compare two proposals and select a matching subset.
+66 -10
View File
@@ -301,38 +301,89 @@ START_TEST(test_select_proposal)
} }
END_TEST END_TEST
START_TEST(test_promote_ke_method) START_TEST(test_has_transform)
{ {
proposal_t *proposal; proposal_t *proposal;
proposal = proposal_create_from_string(PROTO_IKE, proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha256-modp3072-ecp256"); "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,
KE_NONE));
proposal->destroy(proposal);
proposal = proposal_create_from_string(PROTO_ESP,
"aes128-sha256-none");
ck_assert(proposal->has_transform(proposal, KEY_EXCHANGE_METHOD,
KE_NONE));
proposal->destroy(proposal);
proposal = proposal_create_from_string(PROTO_ESP,
"aes128-sha256-modp3072");
ck_assert(!proposal->has_transform(proposal, KEY_EXCHANGE_METHOD,
KE_NONE));
proposal->destroy(proposal);
/* while actually contained in the proposal, KE_NONE is 0 so we expect
* has_transform() to return FALSE if there are other algorithms */
proposal = proposal_create_from_string(PROTO_ESP,
"aes128-sha256-modp3072-none");
ck_assert(!proposal->has_transform(proposal, KEY_EXCHANGE_METHOD,
KE_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"); assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/MODP_3072");
proposal->destroy(proposal); proposal->destroy(proposal);
} }
END_TEST END_TEST
START_TEST(test_promote_ke_method_already_front) START_TEST(test_promote_transform_already_front)
{ {
proposal_t *proposal; proposal_t *proposal;
proposal = proposal_create_from_string(PROTO_IKE, proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha256-modp3072-ecp256"); "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"); assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256");
proposal->destroy(proposal); proposal->destroy(proposal);
} }
END_TEST END_TEST
START_TEST(test_promote_ke_method_not_contained) START_TEST(test_promote_transform_not_contained)
{ {
proposal_t *proposal; proposal_t *proposal;
proposal = proposal_create_from_string(PROTO_IKE, proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha256-modp3072-ecp256"); "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"); assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256");
proposal->destroy(proposal); proposal->destroy(proposal);
} }
@@ -505,10 +556,15 @@ Suite *proposal_suite_create()
countof(select_proposal_data)); countof(select_proposal_data));
suite_add_tcase(s, tc); suite_add_tcase(s, tc);
tc = tcase_create("promote_ke_method"); tc = tcase_create("has_transform");
tcase_add_test(tc, test_promote_ke_method); tcase_add_test(tc, test_has_transform);
tcase_add_test(tc, test_promote_ke_method_already_front); tcase_add_test(tc, test_has_transform_none);
tcase_add_test(tc, test_promote_ke_method_not_contained); 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); suite_add_tcase(s, tc);
tc = tcase_create("unknown transform types"); tc = tcase_create("unknown transform types");