kernel-interface: add an exchange initiator parameter to add_sa()
authorMartin Willi <martin@revosec.ch>
Wed, 8 May 2013 08:31:06 +0000 (10:31 +0200)
committerMartin Willi <martin@revosec.ch>
Tue, 11 Jun 2013 13:58:48 +0000 (15:58 +0200)
This new flag gives the kernel-interface a hint how it should priorize the
use of newly installed SAs during rekeying.

Consider the following rekey procedure in IKEv2:

Initiator  ---    Responder

I1 -------CREATE-------> R1
I2 <------CREATE--------
   -------DELETE-------> R2
I3 <------DELETE--------

SAs are always handled as pairs, the following happens at the SA level:

  * Initiator starts the exchange at I1
  * Responder installs new SA pair at R1
  * Initiator installs new SA pair at I2
  * Responder removes old SA pair at R2
  * Initiator removes old SA pair at I3

This makes sure SAs get installed/removed overlapping during rekeying. However,
to avoid any packet loss, it is crucial that the new outbound SA gets
activated at the correct position:

  * as exchange initiator, in I2
  * as exchange responder, in R2

This should guarantee that we don't use the new outbound SA before the peer
could install its corresponding inbound SA.

The new parameter allows the kernel backend to install the new SA with
appropriate priorities, i.e. it should:

  * as exchange inititator, have the new outbound SA installed with higher
    priority than the old SA
  * as exchange responder, have the new outbound SA installed with lower
    priority than the old SA

While we could split up the SA installation at the responder, this approach
has another advantage: it allows the kernel backend to switch SAs based on
other criteria, for example when receiving traffic on the new inbound SA.

14 files changed:
src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.c
src/libcharon/plugins/load_tester/load_tester_ipsec.c
src/libcharon/sa/child_sa.c
src/libcharon/sa/child_sa.h
src/libcharon/sa/ikev1/tasks/quick_mode.c
src/libcharon/sa/ikev2/tasks/child_create.c
src/libhydra/kernel/kernel_interface.c
src/libhydra/kernel/kernel_interface.h
src/libhydra/kernel/kernel_ipsec.h
src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
src/libipsec/ipsec_sa_mgr.c

index a276166..1d070fd 100644 (file)
@@ -92,7 +92,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
        u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
-       u_int16_t cpi, bool encap, bool esn, bool inbound,
+       u_int16_t cpi, bool _initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
 {
        esa_info_t esa;
@@ -120,6 +120,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        }
 
        /* Initiator if encr_r is passed as enc_key to the inbound add_sa call */
+       /* TODO: does the new _initiator parameter have the same meaning? */
        initiator = esa.is_encr_r && inbound;
        if (initiator)
        {
index c37ca26..d58e8d5 100644 (file)
@@ -65,7 +65,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
        u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
-       u_int16_t cpi, bool encap, bool esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark,
index 49e35c4..bf08d2c 100644 (file)
@@ -54,7 +54,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
        u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
-       u_int16_t cpi, bool encap, bool esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        return SUCCESS;
index a14b039..f50e32f 100644 (file)
@@ -607,9 +607,9 @@ METHOD(child_sa_t, alloc_cpi, u_int16_t,
 }
 
 METHOD(child_sa_t, install, status_t,
-          private_child_sa_t *this, chunk_t encr, chunk_t integ, u_int32_t spi,
-          u_int16_t cpi, bool inbound, bool tfcv3, linked_list_t *my_ts,
-          linked_list_t *other_ts)
+       private_child_sa_t *this, chunk_t encr, chunk_t integ, u_int32_t spi,
+       u_int16_t cpi, bool initiator, bool inbound, bool tfcv3,
+       linked_list_t *my_ts, linked_list_t *other_ts)
 {
        u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
        u_int16_t esn = NO_EXT_SEQ_NUMBERS;
@@ -703,7 +703,8 @@ METHOD(child_sa_t, install, status_t,
                                src, dst, spi, proto_ike2ip(this->protocol), this->reqid,
                                inbound ? this->mark_in : this->mark_out, tfc,
                                lifetime, enc_alg, encr, int_alg, integ, this->mode,
-                               this->ipcomp, cpi, this->encap, esn, update, src_ts, dst_ts);
+                               this->ipcomp, cpi, initiator, this->encap, esn, update,
+                               src_ts, dst_ts);
 
        free(lifetime);
 
index 44511ed..aa44dbf 100644 (file)
@@ -321,6 +321,7 @@ struct child_sa_t {
         * @param integ         integrity key
         * @param spi           SPI to use, allocated for inbound
         * @param cpi           CPI to use, allocated for outbound
+        * @param initiator     TRUE if initiator of exchange resulting in this SA
         * @param inbound       TRUE to install an inbound SA, FALSE for outbound
         * @param tfcv3         TRUE if peer supports ESPv3 TFC
         * @param my_ts         negotiated local traffic selector list
@@ -328,7 +329,8 @@ struct child_sa_t {
         * @return                      SUCCESS or FAILED
         */
        status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ,
-                                               u_int32_t spi, u_int16_t cpi, bool inbound, bool tfcv3,
+                                               u_int32_t spi, u_int16_t cpi,
+                                               bool initiator, bool inbound, bool tfcv3,
                                                linked_list_t *my_ts, linked_list_t *other_ts);
        /**
         * Install the policies using some traffic selectors.
index 47c844e..52ea34b 100644 (file)
@@ -306,17 +306,21 @@ static bool install(private_quick_mode_t *this)
        {
                if (this->initiator)
                {
-                       status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
-                                                       this->spi_i, this->cpi_i, TRUE, FALSE, tsi, tsr);
-                       status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
-                                                       this->spi_r, this->cpi_r, FALSE, FALSE, tsi, tsr);
+                       status_i = this->child_sa->install(this->child_sa,
+                                                                       encr_r, integ_r, this->spi_i, this->cpi_i,
+                                                                       this->initiator, TRUE, FALSE, tsi, tsr);
+                       status_o = this->child_sa->install(this->child_sa,
+                                                                       encr_i, integ_i, this->spi_r, this->cpi_r,
+                                                                       this->initiator, FALSE, FALSE, tsi, tsr);
                }
                else
                {
-                       status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
-                                                       this->spi_r, this->cpi_r, TRUE, FALSE, tsr, tsi);
-                       status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
-                                                       this->spi_i, this->cpi_i, FALSE, FALSE, tsr, tsi);
+                       status_i = this->child_sa->install(this->child_sa,
+                                                                       encr_i, integ_i, this->spi_r, this->cpi_r,
+                                                                       this->initiator, TRUE, FALSE, tsr, tsi);
+                       status_o = this->child_sa->install(this->child_sa,
+                                                                       encr_r, integ_r, this->spi_i, this->cpi_i,
+                                                                       this->initiator, FALSE, FALSE, tsr, tsi);
                }
        }
        chunk_clear(&integ_i);
index d1116d8..e4d762a 100644 (file)
@@ -526,20 +526,20 @@ static status_t select_and_install(private_child_create_t *this,
        {
                if (this->initiator)
                {
-                       status_i = this->child_sa->install(this->child_sa,
-                                                       encr_r, integ_r, this->my_spi, this->my_cpi,
+                       status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
+                                                       this->my_spi, this->my_cpi, this->initiator,
                                                        TRUE, this->tfcv3, my_ts, other_ts);
-                       status_o = this->child_sa->install(this->child_sa,
-                                                       encr_i, integ_i, this->other_spi, this->other_cpi,
+                       status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
+                                                       this->other_spi, this->other_cpi, this->initiator,
                                                        FALSE, this->tfcv3, my_ts, other_ts);
                }
                else
                {
-                       status_i = this->child_sa->install(this->child_sa,
-                                                       encr_i, integ_i, this->my_spi, this->my_cpi,
+                       status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
+                                                       this->my_spi, this->my_cpi, this->initiator,
                                                        TRUE, this->tfcv3, my_ts, other_ts);
-                       status_o = this->child_sa->install(this->child_sa,
-                                                       encr_r, integ_r, this->other_spi, this->other_cpi,
+                       status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
+                                                       this->other_spi, this->other_cpi, this->initiator,
                                                        FALSE, this->tfcv3, my_ts, other_ts);
                }
        }
index d81fa33..be247df 100644 (file)
@@ -180,7 +180,7 @@ METHOD(kernel_interface_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
        u_int16_t int_alg, chunk_t int_key,     ipsec_mode_t mode, u_int16_t ipcomp,
-       u_int16_t cpi, bool encap, bool esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        if (!this->ipsec)
@@ -189,7 +189,7 @@ METHOD(kernel_interface_t, add_sa, status_t,
        }
        return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
                        mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode,
-                       ipcomp, cpi, encap, esn, inbound, src_ts, dst_ts);
+                       ipcomp, cpi, initiator, encap, esn, inbound, src_ts, dst_ts);
 }
 
 METHOD(kernel_interface_t, update_sa, status_t,
index b333cae..ab2b382 100644 (file)
@@ -143,6 +143,7 @@ struct kernel_interface_t {
         * @param mode                  mode of the SA (tunnel, transport)
         * @param ipcomp                IPComp transform to use
         * @param cpi                   CPI for IPComp
+        * @param initiator             TRUE if initiator of the exchange creating this SA
         * @param encap                 enable UDP encapsulation for NAT traversal
         * @param esn                   TRUE to use Extended Sequence Numbers
         * @param inbound               TRUE if this is an inbound SA
@@ -157,7 +158,7 @@ struct kernel_interface_t {
                                                u_int16_t enc_alg, chunk_t enc_key,
                                                u_int16_t int_alg, chunk_t int_key,
                                                ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
-                                               bool encap, bool esn, bool inbound,
+                                               bool initiator, bool encap, bool esn, bool inbound,
                                                traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
 
        /**
index f61f3c3..413e592 100644 (file)
@@ -101,6 +101,7 @@ struct kernel_ipsec_t {
         * @param mode                  mode of the SA (tunnel, transport)
         * @param ipcomp                IPComp transform to use
         * @param cpi                   CPI for IPComp
+        * @param initiator             TRUE if initiator of the exchange creating this SA
         * @param encap                 enable UDP encapsulation for NAT traversal
         * @param esn                   TRUE to use Extended Sequence Numbers
         * @param inbound               TRUE if this is an inbound SA
@@ -115,7 +116,7 @@ struct kernel_ipsec_t {
                                                u_int16_t enc_alg, chunk_t enc_key,
                                                u_int16_t int_alg, chunk_t int_key,
                                                ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
-                                               bool encap, bool esn, bool inbound,
+                                               bool initiator, bool encap, bool esn, bool inbound,
                                                traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
 
        /**
index 32bea73..5ca5879 100644 (file)
@@ -1682,8 +1682,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc,
        lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
        u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       u_int16_t ipcomp, u_int16_t cpi, bool encap, bool esn, bool inbound,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+       u_int16_t ipcomp, u_int16_t cpi, bool initiator, bool encap, bool esn,
+       bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
index bfb8fa8..a208045 100644 (file)
@@ -1170,7 +1170,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
        u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
        u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
-       u_int16_t cpi, bool encap, bool esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
 {
        netlink_buf_t request;
@@ -1187,7 +1187,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
                add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
                           tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
-                          chunk_empty, mode, ipcomp, 0, FALSE, FALSE, inbound, NULL, NULL);
+                          chunk_empty, mode, ipcomp, 0, initiator, FALSE, FALSE, inbound,
+                          NULL, NULL);
                ipcomp = IPCOMP_NONE;
                /* use transport mode ESP SA, IPComp uses tunnel mode */
                mode = MODE_TRANSPORT;
index ecab282..f00210b 100644 (file)
@@ -1523,8 +1523,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
        u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc,
        lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
        u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
-       u_int16_t ipcomp, u_int16_t cpi, bool encap, bool esn, bool inbound,
-       traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+       u_int16_t ipcomp, u_int16_t cpi, bool initiator, bool encap, bool esn,
+       bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        unsigned char request[PFKEY_BUFFER_SIZE];
        struct sadb_msg *msg, *out;
index 2874897..1f5d5a3 100644 (file)
@@ -438,7 +438,7 @@ METHOD(ipsec_sa_mgr_t, add_sa, status_t,
        u_int8_t protocol, u_int32_t reqid,     mark_t mark, u_int32_t tfc,
        lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
        u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
-       u_int16_t cpi, bool encap, bool esn, bool inbound,
+       u_int16_t cpi, bool initiator, bool encap, bool esn, bool inbound,
        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
        ipsec_sa_entry_t *entry;