]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
charon-tkm: Pass ia and ea ids according to configured proposal mappings tkm-proposal-mapping
authorTobias Brunner <tobias@strongswan.org>
Tue, 10 May 2022 08:56:15 +0000 (10:56 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 19 Sep 2024 13:21:47 +0000 (15:21 +0200)
17 files changed:
src/charon-tkm/src/charon-tkm.c
src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
src/charon-tkm/src/tkm/tkm_keymat.c
src/charon-tkm/src/tkm/tkm_keymat.h
src/charon-tkm/src/tkm/tkm_types.h
src/charon-tkm/tests/tests.c
testing/tests/tkm/host2host-initiator-multi-ke/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/host2host-initiator/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/host2host-responder-multi-ke/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/host2host-responder/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/host2host-xfrmproxy/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/multi-level-ca/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/multiple-clients/hosts/sun/etc/strongswan.conf.in
testing/tests/tkm/net2net-initiator/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/net2net-xfrmproxy/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/xfrmproxy-expire/hosts/moon/etc/strongswan.conf.in
testing/tests/tkm/xfrmproxy-rekey/hosts/moon/etc/strongswan.conf.in

index 5f85276ff9fc0b57d08079e5f200af24375050f7..0575ed8164157fe58b04186eaf1f513a07a1659a 100644 (file)
@@ -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();
index 591b511a0dcb629595335280e815bf5d067d071c..cc3d7c745acbd769da62ce216123dc643daf60a4 100644 (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)
                {
index bfd56eb2f80512e047c7b7dbd667020b8447212e..582e7dea48c1752aedd501bef1b784d08de2edc7 100644 (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)
 {
index d5b17bd7db25d7720a992350d4036d86f6bc4c4c..43e4f1bb0a627d8f7ce0a365f0b8373105c9abb4 100644 (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.
  *
index b6f9f45a03da5ca106922aa23d5dc34673941c3a..bca533cb25fab48ceee085c010421fee39fb6610 100644 (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.
         */
index 82367aab9b68f135e2503cc677583341724c772d..f3bc7b0413f0b2b0222bb119297e7971743cf160 100644 (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;
index 243fa98a1396259a92481bfd47ab9a7f3494398e..0554bc34d3a5355dc7e71caf34b046081344f79c 100644 (file)
@@ -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
index 243fa98a1396259a92481bfd47ab9a7f3494398e..0554bc34d3a5355dc7e71caf34b046081344f79c 100644 (file)
@@ -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
index 243fa98a1396259a92481bfd47ab9a7f3494398e..0554bc34d3a5355dc7e71caf34b046081344f79c 100644 (file)
@@ -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
index 243fa98a1396259a92481bfd47ab9a7f3494398e..0554bc34d3a5355dc7e71caf34b046081344f79c 100644 (file)
@@ -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
index 243fa98a1396259a92481bfd47ab9a7f3494398e..0554bc34d3a5355dc7e71caf34b046081344f79c 100644 (file)
@@ -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
index 0712fae8fe7e0d95785f3af327be39d36f104190..9051db9690a2885c51438898afe9671a274e17a7 100644 (file)
@@ -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
index 243fa98a1396259a92481bfd47ab9a7f3494398e..0554bc34d3a5355dc7e71caf34b046081344f79c 100644 (file)
@@ -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
index 243fa98a1396259a92481bfd47ab9a7f3494398e..0554bc34d3a5355dc7e71caf34b046081344f79c 100644 (file)
@@ -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
index 243fa98a1396259a92481bfd47ab9a7f3494398e..0554bc34d3a5355dc7e71caf34b046081344f79c 100644 (file)
@@ -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
index 19db0b8db29e83704bcd57a65541e5b165f59764..9d7b528ecada3aa7ca1159428784eb7808b56e64 100644 (file)
@@ -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
index 19db0b8db29e83704bcd57a65541e5b165f59764..9d7b528ecada3aa7ca1159428784eb7808b56e64 100644 (file)
@@ -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