Extend esa_info_t struct
authorAdrian-Ken Rueegsegger <ken@codelabs.ch>
Fri, 14 Sep 2012 15:29:21 +0000 (17:29 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 19 Mar 2013 14:23:48 +0000 (15:23 +0100)
Add additional fields to the esa_info_t struct so the necessary data can
be passed from the keymat to the kernel ipsec interface, where ESA
creation and key generation using the TKM takes place.

The information is used during the inbound add_sa call to create an ESP
SA. This makes the hack of storing the local SPI in a kernel interface
variable between subsequent add_sa calls unnecessary.

src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
src/charon-tkm/src/tkm/tkm_keymat.c
src/charon-tkm/src/tkm/tkm_types.h

index c97869d..eaec4c2 100644 (file)
@@ -46,11 +46,6 @@ struct private_tkm_kernel_ipsec_t {
        rng_t *rng;
 
        /**
-        * Local CHILD SA SPI.
-        */
-       uint32_t esp_spi_loc;
-
-       /**
         * CHILD/ESP SA database.
         */
        tkm_kernel_sad_t *sad;
@@ -82,31 +77,28 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int16_t cpi, bool encap, bool esn, bool inbound,
        traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
 {
-       if (inbound && this->esp_spi_loc == 0)
+       if (!inbound)
        {
-               DBG1(DBG_KNL, "store local child SA SPI for installation", ntohl(spi));
-               this->esp_spi_loc = spi;
                return SUCCESS;
        }
        const esa_info_t esa = *(esa_info_t *)(enc_key.ptr);
        const esa_id_type esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA);
-       DBG1(DBG_KNL, "adding child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, esp_spi_rem:"
-                " %x)", esa_id, esa.isa_id, ntohl(this->esp_spi_loc), ntohl(spi));
+       DBG1(DBG_KNL, "adding child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, "
+                "esp_spi_rem: %x)", esa_id, esa.isa_id, ntohl(spi), ntohl(esa.spi_r));
        if (!this->sad->insert(this->sad, esa_id, src, dst, spi, protocol))
        {
                DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id);
                tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id);
                return FAILED;
        }
-       if (ike_esa_create_first(esa_id, esa.isa_id, 1, 1, ntohl(this->esp_spi_loc),
-                                                        ntohl(spi)) != TKM_OK)
+       if (ike_esa_create_first(esa_id, esa.isa_id, 1, 1, ntohl(spi),
+                                                        ntohl(esa.spi_r)) != TKM_OK)
        {
                DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id);
                this->sad->remove(this->sad, esa_id);
                tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id);
                return FAILED;
        }
-       this->esp_spi_loc = 0;
        return SUCCESS;
 }
 
@@ -275,7 +267,6 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create()
                        },
                },
                .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
-               .esp_spi_loc = 0,
                .sad = tkm_kernel_sad_create(),
        );
 
index 0b9612c..f9fd57a 100644 (file)
@@ -280,9 +280,41 @@ METHOD(tkm_keymat_t, derive_child_keys, bool,
        chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
        chunk_t *encr_r, chunk_t *integ_r)
 {
-       DBG1(DBG_CHD, "deriving child keys");
-       *encr_i = chunk_alloc(sizeof(esa_info_t));
-       (*(esa_info_t*)(encr_i->ptr)).isa_id = this->isa_ctx_id;
+       esa_info_t *esa_info_i, *esa_info_r;
+
+       dh_id_type dh_id = 0;
+       if (dh)
+       {
+               dh_id = ((tkm_diffie_hellman_t *)dh)->get_id((tkm_diffie_hellman_t *)dh);
+       }
+
+       INIT(esa_info_i,
+                .isa_id = this->isa_ctx_id,
+                .spi_r = proposal->get_spi(proposal),
+                .nonce_i = chunk_clone(nonce_i),
+                .nonce_r = chunk_clone(nonce_r),
+                .is_encr_r = FALSE,
+                .dh_id = dh_id,
+       );
+
+       INIT(esa_info_r,
+                .isa_id = this->isa_ctx_id,
+                .spi_r = proposal->get_spi(proposal),
+                .nonce_i = chunk_clone(nonce_i),
+                .nonce_r = chunk_clone(nonce_r),
+                .is_encr_r = TRUE,
+                .dh_id = dh_id,
+       );
+
+       DBG1(DBG_CHD, "passing on esa info (isa: %llu, spi_r: %x, dh_id: %llu)",
+                esa_info_i->isa_id, ntohl(esa_info_i->spi_r), esa_info_i->dh_id);
+
+       /* 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));
+       *encr_r = chunk_create((u_char *)esa_info_r, sizeof(esa_info_t));
+       *integ_i = chunk_empty;
+       *integ_r = chunk_empty;
+
        return TRUE;
 }
 
index a330664..65f45cf 100644 (file)
 #ifndef TKM_TYPES_H_
 #define TKM_TYPES_H_
 
+#include <tkm/types.h>
+#include <utils/chunk.h>
+
 typedef struct esa_info_t esa_info_t;
 
+/**
+ * ESP SA info data structure.
+ *
+ * This type is used to transfer ESA information from the keymat
+ * derive_child_keys to the kernel IPsec interface add_sa operation. This is
+ * necessary because the CHILD SA key derivation and installation is handled
+ * by a single exchange with the TKM (esa_create*) in add_sa.
+ * For this purpose the out parameters encr_i and encr_r of the
+ * derive_child_keys function are (ab)used and the data is stored in these
+ * data chunks. This is possible since the child SA keys are treated as opaque
+ * values and handed to the add_sa procedure of the kernel interface as-is
+ * without any processing.
+ */
 struct esa_info_t {
+
+       /**
+        * ISA context id.
+        */
        isa_id_type isa_id;
+
+       /**
+        * Responder SPI of child SA.
+        */
+       esp_spi_type spi_r;
+
+       /**
+        * Initiator nonce.
+        */
+       chunk_t nonce_i;
+
+       /**
+        * Responder nonce.
+        */
+       chunk_t nonce_r;
+
+       /**
+        * Flag specifying if this esa info struct is contained in encr_r.
+        * It is set to TRUE for encr_r and FALSE for encr_i.
+        */
+       bool is_encr_r;
+
+       /**
+        * Diffie-Hellman context id.
+        */
+       dh_id_type dh_id;
+
 };
 
 #endif /** TKM_TYPES_H_ */