From: Tobias Brunner Date: Fri, 2 Feb 2018 10:32:39 +0000 (+0100) Subject: proposal: Add method to move a given DH group to the front X-Git-Tag: 5.6.2rc1~19^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d9c9b7b832cd5978477de0f6f15e0924e2d0927d;p=thirdparty%2Fstrongswan.git proposal: Add method to move a given DH group to the front This way a responder (like strongSwan) selecting a proposal first and then checking if the KE payload matches sees the peer's preferred group first. --- diff --git a/src/libstrongswan/crypto/proposal/proposal.c b/src/libstrongswan/crypto/proposal/proposal.c index 221375f7b8..7d857bff0c 100644 --- a/src/libstrongswan/crypto/proposal/proposal.c +++ b/src/libstrongswan/crypto/proposal/proposal.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2008-2016 Tobias Brunner + * Copyright (C) 2008-2018 Tobias Brunner * Copyright (C) 2006-2010 Martin Willi * Copyright (C) 2013-2015 Andreas Steffen - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -171,6 +171,36 @@ METHOD(proposal_t, has_dh_group, bool, return found; } +METHOD(proposal_t, promote_dh_group, bool, + private_proposal_t *this, diffie_hellman_group_t group) +{ + enumerator_t *enumerator; + entry_t *entry; + bool found = FALSE; + + enumerator = array_create_enumerator(this->transforms); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->type == DIFFIE_HELLMAN_GROUP && + entry->alg == group) + { + array_remove_at(this->transforms, enumerator); + found = TRUE; + } + } + enumerator->destroy(enumerator); + + if (found) + { + entry_t entry = { + .type = DIFFIE_HELLMAN_GROUP, + .alg = group, + }; + array_insert(this->transforms, ARRAY_HEAD, &entry); + } + return found; +} + METHOD(proposal_t, strip_dh, void, private_proposal_t *this, diffie_hellman_group_t keep) { @@ -716,6 +746,7 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number) .create_enumerator = _create_enumerator, .get_algorithm = _get_algorithm, .has_dh_group = _has_dh_group, + .promote_dh_group = _promote_dh_group, .strip_dh = _strip_dh, .select = _select_proposal, .get_protocol = _get_protocol, diff --git a/src/libstrongswan/crypto/proposal/proposal.h b/src/libstrongswan/crypto/proposal/proposal.h index d9a2af79fc..0052674b90 100644 --- a/src/libstrongswan/crypto/proposal/proposal.h +++ b/src/libstrongswan/crypto/proposal/proposal.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 Tobias Brunner + * Copyright (C) 2009-2018 Tobias Brunner * Copyright (C) 2006 Martin Willi * HSR Hochschule fuer Technik Rapperswil * @@ -108,7 +108,16 @@ struct proposal_t { * @param group group to check for * @return TRUE if algorithm included */ - bool (*has_dh_group) (proposal_t *this, diffie_hellman_group_t group); + bool (*has_dh_group)(proposal_t *this, diffie_hellman_group_t group); + + /** + * Move the given DH group to the front of the list if it was contained in + * the proposal. + * + * @param group group to promote + * @return TRUE if algorithm included + */ + bool (*promote_dh_group)(proposal_t *this, diffie_hellman_group_t group); /** * Strip DH groups from proposal to use it without PFS. diff --git a/src/libstrongswan/tests/suites/test_proposal.c b/src/libstrongswan/tests/suites/test_proposal.c index 91766266d0..1a2f97d5fd 100644 --- a/src/libstrongswan/tests/suites/test_proposal.c +++ b/src/libstrongswan/tests/suites/test_proposal.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Tobias Brunner + * Copyright (C) 2016-2018 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -57,21 +57,27 @@ static struct { { PROTO_AH, "sha256-esn-noesn", "AH:HMAC_SHA2_256_128/EXT_SEQ/NO_EXT_SEQ" }, }; -START_TEST(test_create_from_string) +static void assert_proposal_eq(proposal_t *proposal, char *expected) { - proposal_t *proposal; char str[BUF_LEN]; - proposal = proposal_create_from_string(create_data[_i].proto, - create_data[_i].proposal); - if (!create_data[_i].expected) + if (!expected) { ck_assert(!proposal); return; } snprintf(str, sizeof(str), "%P", proposal); - ck_assert_str_eq(create_data[_i].expected, str); - proposal->destroy(proposal); + ck_assert_str_eq(expected, str); +} + +START_TEST(test_create_from_string) +{ + proposal_t *proposal; + + proposal = proposal_create_from_string(create_data[_i].proto, + create_data[_i].proposal); + assert_proposal_eq(proposal, create_data[_i].expected); + DESTROY_IF(proposal); } END_TEST @@ -151,6 +157,43 @@ START_TEST(test_select_spi) } END_TEST +START_TEST(test_promote_dh_group) +{ + proposal_t *proposal; + + proposal = proposal_create_from_string(PROTO_IKE, + "aes128-sha256-modp3072-ecp256"); + ck_assert(proposal->promote_dh_group(proposal, 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) +{ + proposal_t *proposal; + + proposal = proposal_create_from_string(PROTO_IKE, + "aes128-sha256-modp3072-ecp256"); + ck_assert(proposal->promote_dh_group(proposal, 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) +{ + proposal_t *proposal; + + proposal = proposal_create_from_string(PROTO_IKE, + "aes128-sha256-modp3072-ecp256"); + + ck_assert(!proposal->promote_dh_group(proposal, 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 + Suite *proposal_suite_create() { Suite *s; @@ -167,5 +210,11 @@ Suite *proposal_suite_create() tcase_add_test(tc, test_select_spi); 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); + suite_add_tcase(s, tc); + return s; }