From: Tobias Brunner Date: Mon, 9 Jul 2018 14:27:04 +0000 (+0200) Subject: proposal: Generalize DH methods X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=77ae91c37b9ec9ed839186827dce9f2e586dc9e8;p=thirdparty%2Fstrongswan.git proposal: Generalize DH methods --- diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index 73cb02bd9a..1e3d2e1dff 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -217,7 +217,7 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*, current = current->clone(current); if (strip_dh) { - current->strip_dh(current, MODP_NONE); + current->strip_transform(current, DIFFIE_HELLMAN_GROUP, MODP_NONE); } if (proposals->find_first(proposals, match_proposal, NULL, current)) { @@ -256,7 +256,7 @@ METHOD(child_cfg_t, select_proposal, proposal_t*, proposal = proposal->clone(proposal); if (strip_dh) { - proposal->strip_dh(proposal, MODP_NONE); + proposal->strip_transform(proposal, DIFFIE_HELLMAN_GROUP, MODP_NONE); } if (prefer_self) { @@ -271,7 +271,7 @@ METHOD(child_cfg_t, select_proposal, proposal_t*, match = match->clone(match); if (strip_dh) { - match->strip_dh(match, MODP_NONE); + match->strip_transform(match, DIFFIE_HELLMAN_GROUP, MODP_NONE); } selected = proposal->select(proposal, match, prefer_self, private); match->destroy(match); diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index 3309a5ddc1..1b941589df 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -796,13 +796,13 @@ static linked_list_t *get_proposals(private_quick_mode_t *this, { if (group != MODP_NONE) { - if (!proposal->has_dh_group(proposal, group)) + if (!proposal->has_transform(proposal, DIFFIE_HELLMAN_GROUP, group)) { list->remove_at(list, enumerator); proposal->destroy(proposal); continue; } - proposal->strip_dh(proposal, group); + proposal->strip_transform(proposal, DIFFIE_HELLMAN_GROUP, group); } proposal->set_spi(proposal, this->spi_i); } diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index ad01535814..9901e85078 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -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_dh_group(proposal, this->dh_group)) + if (!proposal->promote_transform(proposal, DIFFIE_HELLMAN_GROUP, + this->dh_group)) { this->proposals->remove_at(this->proposals, enumerator); other_dh_groups->insert_last(other_dh_groups, proposal); @@ -586,7 +587,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_dh_group(this->proposal, this->dh_group)) + if (!this->proposal->has_transform(this->proposal, DIFFIE_HELLMAN_GROUP, + this->dh_group)) { uint16_t group; diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c index 00ec9f4564..8d0d863a1a 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_init.c +++ b/src/libcharon/sa/ikev2/tasks/ike_init.c @@ -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_dh_group(proposal, this->dh_group)) + if (!proposal->promote_transform(proposal, DIFFIE_HELLMAN_GROUP, + 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); @@ -610,7 +611,8 @@ static void process_payloads(private_ike_init_t *this, message_t *message) } if (ke_payload && this->proposal && - this->proposal->has_dh_group(this->proposal, this->dh_group)) + this->proposal->has_transform(this->proposal, DIFFIE_HELLMAN_GROUP, + this->dh_group)) { if (!this->initiator) { @@ -822,7 +824,8 @@ METHOD(task_t, build_r, status_t, } if (this->dh == NULL || - !this->proposal->has_dh_group(this->proposal, this->dh_group)) + !this->proposal->has_transform(this->proposal, DIFFIE_HELLMAN_GROUP, + this->dh_group)) { uint16_t group; @@ -1057,7 +1060,8 @@ METHOD(task_t, process_i, status_t, } if (this->dh == NULL || - !this->proposal->has_dh_group(this->proposal, this->dh_group)) + !this->proposal->has_transform(this->proposal, DIFFIE_HELLMAN_GROUP, + this->dh_group)) { DBG1(DBG_IKE, "peer DH group selection invalid"); return FAILED; diff --git a/src/libstrongswan/crypto/proposal/proposal.c b/src/libstrongswan/crypto/proposal/proposal.c index 3ca78c92f5..60bd2cd367 100644 --- a/src/libstrongswan/crypto/proposal/proposal.c +++ b/src/libstrongswan/crypto/proposal/proposal.c @@ -246,18 +246,18 @@ METHOD(proposal_t, get_algorithm, bool, return found; } -METHOD(proposal_t, has_dh_group, bool, - private_proposal_t *this, diffie_hellman_group_t group) +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, DIFFIE_HELLMAN_GROUP); + enumerator = create_enumerator(this, type); while (enumerator->enumerate(enumerator, ¤t, NULL)) { any = TRUE; - if (current == group) + if (current == alg) { found = TRUE; break; @@ -265,15 +265,15 @@ METHOD(proposal_t, has_dh_group, bool, } enumerator->destroy(enumerator); - if (!any && group == MODP_NONE) + if (!any && alg == 0) { found = TRUE; } return found; } -METHOD(proposal_t, promote_dh_group, bool, - private_proposal_t *this, diffie_hellman_group_t group) +METHOD(proposal_t, promote_transform, bool, + private_proposal_t *this, transform_type_t type, uint16_t alg) { enumerator_t *enumerator; entry_t *entry; @@ -282,8 +282,8 @@ METHOD(proposal_t, promote_dh_group, bool, enumerator = array_create_enumerator(this->transforms); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->type == DIFFIE_HELLMAN_GROUP && - entry->alg == group) + if (entry->type == type && + entry->alg == alg) { array_remove_at(this->transforms, enumerator); found = TRUE; @@ -294,16 +294,16 @@ METHOD(proposal_t, promote_dh_group, bool, if (found) { entry_t entry = { - .type = DIFFIE_HELLMAN_GROUP, - .alg = group, + .type = type, + .alg = alg, }; array_insert(this->transforms, ARRAY_HEAD, &entry); } return found; } -METHOD(proposal_t, strip_dh, void, - private_proposal_t *this, diffie_hellman_group_t keep) +METHOD(proposal_t, strip_transform, void, + private_proposal_t *this, transform_type_t type, uint16_t keep) { enumerator_t *enumerator; entry_t *entry; @@ -312,7 +312,7 @@ METHOD(proposal_t, strip_dh, void, enumerator = array_create_enumerator(this->transforms); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->type == DIFFIE_HELLMAN_GROUP) + if (entry->type == type) { if (entry->alg != keep) { @@ -327,9 +327,9 @@ METHOD(proposal_t, strip_dh, void, enumerator->destroy(enumerator); array_compress(this->transforms); - if (keep == MODP_NONE || !found) + if (keep == 0 || !found) { - remove_type(this, DIFFIE_HELLMAN_GROUP); + remove_type(this, type); array_compress(this->types); } } @@ -952,9 +952,9 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number) .add_algorithm = _add_algorithm, .create_enumerator = _create_enumerator, .get_algorithm = _get_algorithm, - .has_dh_group = _has_dh_group, - .promote_dh_group = _promote_dh_group, - .strip_dh = _strip_dh, + .has_transform = _has_transform, + .promote_transform = _promote_transform, + .strip_transform = _strip_transform, .select = _select_proposal, .matches = _matches, .get_protocol = _get_protocol, diff --git a/src/libstrongswan/crypto/proposal/proposal.h b/src/libstrongswan/crypto/proposal/proposal.h index 3383243264..f3e1b49ce7 100644 --- a/src/libstrongswan/crypto/proposal/proposal.h +++ b/src/libstrongswan/crypto/proposal/proposal.h @@ -102,28 +102,36 @@ struct proposal_t { uint16_t *alg, uint16_t *key_size); /** - * Check if the proposal has a specific DH group. + * Check if the proposal has a specific transform. * - * @param group group 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_dh_group)(proposal_t *this, diffie_hellman_group_t group); + bool (*has_transform)(proposal_t *this, transform_type_t type, + uint16_t alg); /** - * Move the given DH group to the front of the list if it was contained in + * Move the given transform to the front of the list if it was contained in * the proposal. * - * @param group group to promote + * @param type kind of algorithm + * @param alg algorithm to promote * @return TRUE if algorithm included */ - bool (*promote_dh_group)(proposal_t *this, diffie_hellman_group_t group); + bool (*promote_transform)(proposal_t *this, transform_type_t type, + uint16_t alg); /** - * Strip DH groups from proposal to use it without PFS. + * Strip transforms from proposal (e.g. for DH groups to use it without PFS + * or during IKE_AUTH). * - * @param keep group to keep (MODP_NONE to remove all) + * @param type kind of algorithm + * @param keep algorithm to keep (0 to remove all) */ - void (*strip_dh)(proposal_t *this, diffie_hellman_group_t keep); + void (*strip_transform)(proposal_t *this, transform_type_t type, + uint16_t keep); /** * Compare two proposal, and select a matching subset. diff --git a/src/libstrongswan/tests/suites/test_proposal.c b/src/libstrongswan/tests/suites/test_proposal.c index 099cd19c7f..ff49c3863e 100644 --- a/src/libstrongswan/tests/suites/test_proposal.c +++ b/src/libstrongswan/tests/suites/test_proposal.c @@ -187,43 +187,140 @@ START_TEST(test_matches) } END_TEST -START_TEST(test_promote_dh_group) +START_TEST(test_has_transform) { proposal_t *proposal; proposal = proposal_create_from_string(PROTO_IKE, "aes128-sha256-modp3072-ecp256"); - ck_assert(proposal->promote_dh_group(proposal, ECP_256_BIT)); + ck_assert(proposal->has_transform(proposal, DIFFIE_HELLMAN_GROUP, + MODP_3072_BIT)); + ck_assert(proposal->has_transform(proposal, DIFFIE_HELLMAN_GROUP, + ECP_256_BIT)); + ck_assert(!proposal->has_transform(proposal, DIFFIE_HELLMAN_GROUP, + 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, DIFFIE_HELLMAN_GROUP, + MODP_NONE)); + proposal->destroy(proposal); + + proposal = proposal_create_from_string(PROTO_ESP, + "aes128-sha256-modp3072"); + ck_assert(!proposal->has_transform(proposal, DIFFIE_HELLMAN_GROUP, + 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, DIFFIE_HELLMAN_GROUP, + 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_dh_group_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_dh_group(proposal, MODP_3072_BIT)); + ck_assert(proposal->promote_transform(proposal, DIFFIE_HELLMAN_GROUP, + 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_dh_group_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_dh_group(proposal, MODP_2048_BIT)); + ck_assert(!proposal->promote_transform(proposal, DIFFIE_HELLMAN_GROUP, + 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); } END_TEST +START_TEST(test_promote_transform_qske) +{ + proposal_t *proposal; + + proposal = proposal_create_from_string(PROTO_IKE, + "aes128-sha256-ecp256-qskenewhope1-qskenewhope5"); + ck_assert(proposal->promote_transform(proposal, QSKE_MECHANISM, + QSKE_NEWHOPE_L5)); + assert_proposal_eq(proposal, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/QSKE_NEWHOPE_L5/QSKE_NEWHOPE_L1"); + proposal->destroy(proposal); +} +END_TEST + +START_TEST(test_strip_transform) +{ + proposal_t *proposal; + + proposal = proposal_create_from_string(PROTO_ESP, + "aes128-sha256-modp3072-ecp256"); + proposal->strip_transform(proposal, DIFFIE_HELLMAN_GROUP, MODP_NONE); + ck_assert(proposal->has_transform(proposal, DIFFIE_HELLMAN_GROUP, + MODP_NONE)); + assert_proposal_eq(proposal, "ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ"); + proposal->destroy(proposal); +} +END_TEST + +START_TEST(test_strip_transform_keep) +{ + proposal_t *proposal; + + proposal = proposal_create_from_string(PROTO_ESP, + "aes128-sha256-modp3072-ecp256"); + proposal->strip_transform(proposal, DIFFIE_HELLMAN_GROUP, MODP_3072_BIT); + ck_assert(proposal->has_transform(proposal, DIFFIE_HELLMAN_GROUP, + MODP_3072_BIT)); + assert_proposal_eq(proposal, "ESP:AES_CBC_128/HMAC_SHA2_256_128/MODP_3072/NO_EXT_SEQ"); + proposal->destroy(proposal); +} +END_TEST + +START_TEST(test_strip_transform_qske) +{ + proposal_t *proposal; + + proposal = proposal_create_from_string(PROTO_ESP, + "aes128-sha256-qskenewhope1-qskenewhope5"); + proposal->strip_transform(proposal, QSKE_MECHANISM, QSKE_NEWHOPE_L5); + ck_assert(proposal->has_transform(proposal, QSKE_MECHANISM, + QSKE_NEWHOPE_L5)); + proposal->strip_transform(proposal, QSKE_MECHANISM, QSKE_NONE); + ck_assert(!proposal->has_transform(proposal, QSKE_MECHANISM, + QSKE_NEWHOPE_L5)); + ck_assert(proposal->has_transform(proposal, QSKE_MECHANISM, + QSKE_NONE)); + assert_proposal_eq(proposal, "ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ"); + proposal->destroy(proposal); +} +END_TEST + START_TEST(test_unknown_transform_types_print) { proposal_t *proposal; @@ -344,10 +441,22 @@ Suite *proposal_suite_create() tcase_add_loop_test(tc, test_matches, 0, countof(select_data)); suite_add_tcase(s, tc); - tc = tcase_create("promote_dh_group"); - tcase_add_test(tc, test_promote_dh_group); - tcase_add_test(tc, test_promote_dh_group_already_front); - tcase_add_test(tc, test_promote_dh_group_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); + tcase_add_test(tc, test_promote_transform_qske); + suite_add_tcase(s, tc); + + tc = tcase_create("strip_transform"); + tcase_add_test(tc, test_strip_transform); + tcase_add_test(tc, test_strip_transform_keep); + tcase_add_test(tc, test_strip_transform_qske); suite_add_tcase(s, tc); tc = tcase_create("unknown transform types");