charon-tkm: Pass ia and ea ids according to configured proposal mappings

This commit is contained in:
Tobias Brunner
2026-07-31 16:10:36 +02:00
parent 14fa2d45d8
commit 3b58c67202
17 changed files with 284 additions and 24 deletions
+7
View File
@@ -336,6 +336,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);
@@ -428,6 +434,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();
+4 -4
View File
@@ -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)
{
+161 -20
View File
@@ -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 <daemon.h>
#include <tkm/constants.h>
#include <tkm/client.h>
#include <collections/array.h>
#include <crypto/hashers/hash_algorithm_set.h>
#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)
{
+12
View File
@@ -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.
*
+5
View File
@@ -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.
*/
+7
View File
@@ -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;
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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