From: Tobias Brunner Date: Tue, 10 May 2022 08:56:15 +0000 (+0200) Subject: charon-tkm: Pass ia and ea ids according to configured proposal mappings X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Ftkm-proposal-mapping;p=thirdparty%2Fstrongswan.git charon-tkm: Pass ia and ea ids according to configured proposal mappings --- diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c index 5f85276ff9..0575ed8164 100644 --- a/src/charon-tkm/src/charon-tkm.c +++ b/src/charon-tkm/src/charon-tkm.c @@ -318,6 +318,12 @@ int main(int argc, char *argv[]) lib->plugins->add_static_features(lib->plugins, "tkm-backend", features, countof(features), TRUE, NULL, NULL); + if (!register_proposal_mapping()) + { + DBG1(DBG_DMN, "no proposal mapping defined - aborting %s", dmn_name); + goto deinit; + } + if (!register_ke_mapping()) { DBG1(DBG_DMN, "no KE group mapping defined - aborting %s", dmn_name); @@ -410,6 +416,7 @@ int main(int argc, char *argv[]) lib->encoding->remove_encoder(lib->encoding, tkm_encoder_encode); deinit: + destroy_proposal_mapping(); destroy_ke_mapping(); destroy_ca_mapping(); libcharon_deinit(); diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c index 591b511a0d..cc3d7c745a 100644 --- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c +++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c @@ -156,8 +156,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, nonce_loc_id = tkm->chunk_map->get_id(tkm->chunk_map, nonce_loc); if (nonce_loc_id == 0 && esa.ke_ids.size == 0) { - if (ike_esa_create_first(esa_id, esa.isa_id, data->reqid, 1, flags, - spi_loc, spi_rem) != TKM_OK) + if (ike_esa_create_first(esa_id, esa.isa_id, data->reqid, esa.ea_id, + flags, spi_loc, spi_rem) != TKM_OK) { DBG1(DBG_KNL, "child SA (%llu, first) creation failed", esa_id); goto failure; @@ -167,7 +167,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, else if (nonce_loc_id != 0 && esa.ke_ids.size == 0) { chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); - if (ike_esa_create_no_pfs(esa_id, esa.isa_id, data->reqid, 1, + if (ike_esa_create_no_pfs(esa_id, esa.isa_id, data->reqid, esa.ea_id, nonce_loc_id, nc_rem, flags, spi_loc, spi_rem) != TKM_OK) { @@ -181,7 +181,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, else { chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type)); - if (ike_esa_create(esa_id, esa.isa_id, data->reqid, 1, esa.ke_ids, + if (ike_esa_create(esa_id, esa.isa_id, data->reqid, esa.ea_id, esa.ke_ids, nonce_loc_id, nc_rem, flags, spi_loc, spi_rem) != TKM_OK) { diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c index bfd56eb2f8..582e7dea48 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.c +++ b/src/charon-tkm/src/tkm/tkm_keymat.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 Tobias Brunner + * Copyright (C) 2015-2022 Tobias Brunner * Copyright (C) 2012 Reto Buerki * Copyright (C) 2012 Adrian-Ken Rueegsegger * @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "tkm.h" @@ -30,6 +31,9 @@ typedef struct private_tkm_keymat_t private_tkm_keymat_t; +static array_t *ike_proposal_map = NULL; +static array_t *esp_proposal_map = NULL; + /** * Private data of a keymat_t object. */ @@ -94,6 +98,48 @@ METHOD(keymat_t, create_nonce_gen, nonce_gen_t*, return lib->crypto->create_nonce_gen(lib->crypto); } +/** + * Proposal mapping entry + */ +typedef struct { + /** Proposal */ + proposal_t *proposal; + /** Id */ + uint64_t id; +} entry_t; + +/** + * Determine the id for the given proposal + */ +static uint64_t get_proposal_id(proposal_t *proposal) +{ + array_t *map; + entry_t entry; + int i; + + switch (proposal->get_protocol(proposal)) + { + case PROTO_IKE: + map = ike_proposal_map; + break; + case PROTO_ESP: + map = esp_proposal_map; + break; + default: + return 0; + } + for (i = 0; i < array_count(map); i++) + { + array_get(map, i, &entry); + /* we never match DH groups as they are mapped and passed separately */ + if (entry.proposal->matches(entry.proposal, proposal, PROPOSAL_SKIP_KE)) + { + return entry.id; + } + } + return 0; +} + /** * Concatenate the TKM KE IDs of the passed key exchanges */ @@ -123,7 +169,7 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, pseudo_random_function_t rekey_function, chunk_t rekey_skd) { - uint64_t nc_id = 0, spi_loc, spi_rem; + uint64_t nc_id = 0, ia_id, spi_loc, spi_rem; chunk_t *nonce; ke_ids_type ke_ids; nonce_type nonce_rem; @@ -152,6 +198,13 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, spi_rem = id->get_initiator_spi(id); } + ia_id = get_proposal_id(proposal); + if (!ia_id) + { + DBG1(DBG_IKE, "unable to determine id for proposal %P", proposal); + return FALSE; + } + if (rekey_function == PRF_UNDEFINED) { /* Acquire nonce context id */ @@ -168,11 +221,12 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, DBG1(DBG_IKE, "unable to acquire ae context id"); return FALSE; } - DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, ke: %llu, spi_loc: %llx, " - "spi_rem: %llx)", nc_id, ke_ids.data[0], spi_loc, spi_rem); - res = ike_isa_create(this->isa_ctx_id, this->ae_ctx_id, 1, ke_ids.data[0], - nc_id, nonce_rem, this->initiator, spi_loc, spi_rem, - &block_len, &icv_len, &iv_len); + DBG1(DBG_IKE, "deriving IKE keys (nc: %llu, ia: %llu, ke: %llu, " + "spi_loc: %llx, spi_rem: %llx)", nc_id, ia_id, ke_ids.data[0], + spi_loc, spi_rem); + res = ike_isa_create(this->isa_ctx_id, this->ae_ctx_id, ia_id, + ke_ids.data[0], nc_id, nonce_rem, this->initiator, + spi_loc, spi_rem, &block_len, &icv_len, &iv_len); } else { @@ -187,9 +241,10 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, if (this->ae_ctx_id == isa_info.ae_id) { - DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, ae: %llu, " - "ke: %llu, spi_loc: %llx, spi_rem: %llx)", isa_info.parent_isa_id, - isa_info.ae_id, ke_ids.data[0], spi_loc, spi_rem); + DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, ae: %llu, ia: " + "%llu, ke: %llu, spi_loc: %llx, spi_rem: %llx)", + isa_info.parent_isa_id, isa_info.ae_id, ia_id, ke_ids.data[0], + spi_loc, spi_rem); res = ike_isa_update(this->isa_ctx_id, ke_ids.data[0]); } @@ -206,15 +261,16 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, } else { - DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, ae: %llu, nc: %llu, " - "ke: %llu, spi_loc: %llx, spi_rem: %llx)", isa_info.parent_isa_id, - isa_info.ae_id, nc_id, ke_ids.data[0], spi_loc, spi_rem); + DBG1(DBG_IKE, "deriving IKE keys (parent_isa: %llu, ae: %llu, nc: " + "%llu, ia: %llu, ke: %llu, spi_loc: %llx, spi_rem: %llx)", + isa_info.parent_isa_id, isa_info.ae_id, nc_id, ia_id, + ke_ids.data[0], spi_loc, spi_rem); this->ae_ctx_id = isa_info.ae_id; - res = ike_isa_create_child(this->isa_ctx_id, isa_info.parent_isa_id, 1, - ke_ids, nc_id, nonce_rem, this->initiator, - spi_loc, spi_rem, &block_len, &icv_len, - &iv_len); + res = ike_isa_create_child(this->isa_ctx_id, isa_info.parent_isa_id, + ia_id, ke_ids, nc_id, nonce_rem, + this->initiator, spi_loc, spi_rem, + &block_len, &icv_len, &iv_len); } chunk_free(&rekey_skd); @@ -254,18 +310,27 @@ METHOD(keymat_v2_t, derive_child_keys, bool, { esa_info_t *esa_info_i, *esa_info_r; ke_ids_type ke_ids = {}; + ea_id_type ea_id; if (kes && !concat_ke_ids(kes, &ke_ids)) { return FALSE; } + ea_id = get_proposal_id(proposal); + if (!ea_id) + { + DBG1(DBG_IKE, "unable to determine id for proposal %P", proposal); + return FALSE; + } + INIT(esa_info_i, .isa_id = this->isa_ctx_id, .spi_l = proposal->get_spi(proposal), .nonce_i = chunk_clone(nonce_i), .nonce_r = chunk_clone(nonce_r), .is_encr_r = FALSE, + .ea_id = ea_id, .ke_ids = ke_ids, ); @@ -275,12 +340,13 @@ METHOD(keymat_v2_t, derive_child_keys, bool, .nonce_i = chunk_clone(nonce_i), .nonce_r = chunk_clone(nonce_r), .is_encr_r = TRUE, + .ea_id = ea_id, .ke_ids = ke_ids, ); - DBG1(DBG_CHD, "passing on esa info (isa: %llu, spi_l: %x, " + DBG1(DBG_CHD, "passing on esa info (isa: %llu, spi_l: %x, ea_id: %llu, " "ke_id[%llu]: %llu)", esa_info_i->isa_id, ntohl(esa_info_i->spi_l), - esa_info_i->ke_ids.size, esa_info_i->ke_ids.data[0]); + esa_info_i->ea_id, esa_info_i->ke_ids.size, esa_info_i->ke_ids.data[0]); /* store ESA info in encr_i/r, which is passed to add_sa */ *encr_i = chunk_create((u_char *)esa_info_i, sizeof(esa_info_t)); @@ -445,7 +511,82 @@ METHOD(tkm_keymat_t, get_peer_init_msg, chunk_t*, } /** - * See header. + * Init proposal mappings for a specific protocol + */ +static int init_proposal_map(array_t *map, protocol_id_t proto) +{ + enumerator_t *enumerator; + entry_t entry; + char *id_str, *proposal_str; + + enumerator = lib->settings->create_key_value_enumerator(lib->settings, + "%s.proposal_mapping.%N", lib->ns, + protocol_id_lower_names, proto); + + while (enumerator->enumerate(enumerator, &id_str, &proposal_str)) + { + entry.proposal = proposal_create_from_string_unchecked(proto, + proposal_str); + if (!entry.proposal) + { + enumerator->destroy(enumerator); + return FALSE; + } + entry.id = settings_value_as_uint64(id_str, 0); + array_insert(map, ARRAY_TAIL, &entry); + } + enumerator->destroy(enumerator); + + if (!array_count(map)) + { + return FALSE; + } + return TRUE; +} + +/* + * Described in header + */ +int register_proposal_mapping() +{ + ike_proposal_map = array_create(sizeof(entry_t), 4); + esp_proposal_map = array_create(sizeof(entry_t), 4); + + if (!init_proposal_map(ike_proposal_map, PROTO_IKE) || + !init_proposal_map(esp_proposal_map, PROTO_ESP)) + { + return 0; + } + return array_count(ike_proposal_map) + array_count(esp_proposal_map); +} + +/** + * Destroy given proposal mappings + */ +static void destroy_proposal_map(array_t *map) +{ + entry_t entry; + + while (array_remove(map, ARRAY_HEAD, &entry)) + { + entry.proposal->destroy(entry.proposal); + } + array_destroy(map); +} + +/* + * Described in header + */ +void destroy_proposal_mapping() +{ + destroy_proposal_map(ike_proposal_map); + destroy_proposal_map(esp_proposal_map); + ike_proposal_map = NULL; + esp_proposal_map = NULL; +} + +/* + * Described in header */ tkm_keymat_t *tkm_keymat_create(bool initiator) { diff --git a/src/charon-tkm/src/tkm/tkm_keymat.h b/src/charon-tkm/src/tkm/tkm_keymat.h index d5b17bd7db..43e4f1bb0a 100644 --- a/src/charon-tkm/src/tkm/tkm_keymat.h +++ b/src/charon-tkm/src/tkm/tkm_keymat.h @@ -67,6 +67,18 @@ struct tkm_keymat_t { }; +/** + * Loads IKE/ESP proposal to TKM id mapping from config. + * + * @return number of registered mappings + */ +int register_proposal_mapping(); + +/** + * Destroy IKE/ESP proposal to TKM id mapping. + */ +void destroy_proposal_mapping(); + /** * Create TKM keymat instance. * diff --git a/src/charon-tkm/src/tkm/tkm_types.h b/src/charon-tkm/src/tkm/tkm_types.h index b6f9f45a03..bca533cb25 100644 --- a/src/charon-tkm/src/tkm/tkm_types.h +++ b/src/charon-tkm/src/tkm/tkm_types.h @@ -69,6 +69,11 @@ struct esa_info_t { */ bool is_encr_r; + /** + * ESP algorithm proposal id. + */ + ea_id_type ea_id; + /** * Key Exchange context ids. */ diff --git a/src/charon-tkm/tests/tests.c b/src/charon-tkm/tests/tests.c index 82367aab9b..f3bc7b0413 100644 --- a/src/charon-tkm/tests/tests.c +++ b/src/charon-tkm/tests/tests.c @@ -25,6 +25,7 @@ #include "tkm_nonceg.h" #include "tkm_key_exchange.h" #include "tkm_kernel_ipsec.h" +#include "tkm_keymat.h" /* declare test suite constructors */ #define TEST_SUITE(x) test_suite_t* x(); @@ -79,6 +80,11 @@ static bool test_runner_init(bool init) lib->ns, MODP_3072_BIT); lib->settings->set_int(lib->settings, "%s.ke_mapping.%d", 2, lib->ns, MODP_4096_BIT); + lib->settings->set_str(lib->settings, "%s.proposal_mapping.ike.%d", + "aes256-sha512-prfsha512", lib->ns, 1); + lib->settings->set_str(lib->settings, "%s.proposal_mapping.esp.%d", + "aes256-sha512-esn-noesn", lib->ns, 1); + register_proposal_mapping(); register_ke_mapping(); plugin_loader_add_plugindirs(BUILDDIR "/src/libstrongswan/plugins", @@ -100,6 +106,7 @@ static bool test_runner_init(bool init) result = FALSE; } + destroy_proposal_mapping(); destroy_ke_mapping(); libcharon_deinit(); return result; diff --git a/testing/tests/tkm/host2host-initiator-multi-ke/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/host2host-initiator-multi-ke/hosts/moon/etc/strongswan.conf.in index 243fa98a13..0554bc34d3 100644 --- a/testing/tests/tkm/host2host-initiator-multi-ke/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/host2host-initiator-multi-ke/hosts/moon/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/host2host-initiator/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/host2host-initiator/hosts/moon/etc/strongswan.conf.in index 243fa98a13..0554bc34d3 100644 --- a/testing/tests/tkm/host2host-initiator/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/host2host-initiator/hosts/moon/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/host2host-responder-multi-ke/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/host2host-responder-multi-ke/hosts/moon/etc/strongswan.conf.in index 243fa98a13..0554bc34d3 100644 --- a/testing/tests/tkm/host2host-responder-multi-ke/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/host2host-responder-multi-ke/hosts/moon/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/host2host-responder/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/host2host-responder/hosts/moon/etc/strongswan.conf.in index 243fa98a13..0554bc34d3 100644 --- a/testing/tests/tkm/host2host-responder/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/host2host-responder/hosts/moon/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/host2host-xfrmproxy/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/host2host-xfrmproxy/hosts/moon/etc/strongswan.conf.in index 243fa98a13..0554bc34d3 100644 --- a/testing/tests/tkm/host2host-xfrmproxy/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/host2host-xfrmproxy/hosts/moon/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/multi-level-ca/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/multi-level-ca/hosts/moon/etc/strongswan.conf.in index 0712fae8fe..9051db9690 100644 --- a/testing/tests/tkm/multi-level-ca/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/multi-level-ca/hosts/moon/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/multiple-clients/hosts/sun/etc/strongswan.conf.in b/testing/tests/tkm/multiple-clients/hosts/sun/etc/strongswan.conf.in index 243fa98a13..0554bc34d3 100644 --- a/testing/tests/tkm/multiple-clients/hosts/sun/etc/strongswan.conf.in +++ b/testing/tests/tkm/multiple-clients/hosts/sun/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/net2net-initiator/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/net2net-initiator/hosts/moon/etc/strongswan.conf.in index 243fa98a13..0554bc34d3 100644 --- a/testing/tests/tkm/net2net-initiator/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/net2net-initiator/hosts/moon/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/net2net-xfrmproxy/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/net2net-xfrmproxy/hosts/moon/etc/strongswan.conf.in index 243fa98a13..0554bc34d3 100644 --- a/testing/tests/tkm/net2net-xfrmproxy/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/net2net-xfrmproxy/hosts/moon/etc/strongswan.conf.in @@ -5,6 +5,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/xfrmproxy-expire/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/xfrmproxy-expire/hosts/moon/etc/strongswan.conf.in index 19db0b8db2..9d7b528eca 100644 --- a/testing/tests/tkm/xfrmproxy-expire/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/xfrmproxy-expire/hosts/moon/etc/strongswan.conf.in @@ -7,6 +7,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1 diff --git a/testing/tests/tkm/xfrmproxy-rekey/hosts/moon/etc/strongswan.conf.in b/testing/tests/tkm/xfrmproxy-rekey/hosts/moon/etc/strongswan.conf.in index 19db0b8db2..9d7b528eca 100644 --- a/testing/tests/tkm/xfrmproxy-rekey/hosts/moon/etc/strongswan.conf.in +++ b/testing/tests/tkm/xfrmproxy-rekey/hosts/moon/etc/strongswan.conf.in @@ -7,6 +7,14 @@ charon-tkm { 15 = 1 16 = 2 } + proposal_mapping { + ike { + 1 = aes256-sha512-prfsha512 + } + esp { + 1 = aes256-sha512-esn-noesn + } + } ca_mapping { strongswan_ca { id = 1