]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
bus: Support multiple key exchanges in ike/child_keys() events
authorTobias Brunner <tobias@strongswan.org>
Thu, 9 Apr 2020 09:53:45 +0000 (11:53 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 22 Mar 2023 10:35:11 +0000 (11:35 +0100)
src/libcharon/bus/bus.c
src/libcharon/bus/bus.h
src/libcharon/bus/listeners/listener.h
src/libcharon/plugins/ha/ha_child.c
src/libcharon/plugins/ha/ha_ike.c
src/libcharon/sa/ikev1/phase1.c
src/libcharon/sa/ikev1/tasks/quick_mode.c
src/libcharon/sa/ikev2/tasks/child_create.c
src/libcharon/sa/ikev2/tasks/ike_init.c

index 57eaaac8953ddb363fd1e58247ecd6e86fe0e9fa..99387d5e06f8077682a99741c20021b088fc8acc 100644 (file)
@@ -574,7 +574,7 @@ METHOD(bus_t, message, void,
 }
 
 METHOD(bus_t, ike_keys, void,
-       private_bus_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
+       private_bus_t *this, ike_sa_t *ike_sa, array_t *kes,
        chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
        ike_sa_t *rekey, shared_key_t *shared, auth_method_t method)
 {
@@ -591,7 +591,7 @@ METHOD(bus_t, ike_keys, void,
                        continue;
                }
                entry->calling++;
-               keep = entry->listener->ike_keys(entry->listener, ike_sa, dh, dh_other,
+               keep = entry->listener->ike_keys(entry->listener, ike_sa, kes, dh_other,
                                                                                 nonce_i, nonce_r, rekey, shared,
                                                                                 method);
                entry->calling--;
@@ -639,7 +639,7 @@ METHOD(bus_t, ike_derived_keys, void,
 
 METHOD(bus_t, child_keys, void,
        private_bus_t *this, child_sa_t *child_sa, bool initiator,
-       key_exchange_t *dh, chunk_t nonce_i, chunk_t nonce_r)
+       array_t *kes, chunk_t nonce_i, chunk_t nonce_r)
 {
        enumerator_t *enumerator;
        ike_sa_t *ike_sa;
@@ -658,7 +658,7 @@ METHOD(bus_t, child_keys, void,
                }
                entry->calling++;
                keep = entry->listener->child_keys(entry->listener, ike_sa,
-                                                               child_sa, initiator, dh, nonce_i, nonce_r);
+                                                               child_sa, initiator, kes, nonce_i, nonce_r);
                entry->calling--;
                if (!keep)
                {
index 5e809f04fcf38c36430ccbebdd75c511c4d3e754..d814d09e3490f4cdc9d3a9bbfea71550afe67195 100644 (file)
@@ -30,6 +30,7 @@ typedef struct bus_t bus_t;
 #include <stdarg.h>
 
 #include <utils/debug.h>
+#include <collections/array.h>
 #include <sa/ike_sa.h>
 #include <sa/child_sa.h>
 #include <processing/jobs/job.h>
@@ -348,7 +349,7 @@ struct bus_t {
         * IKE_SA keymat hook.
         *
         * @param ike_sa        IKE_SA this keymat belongs to
-        * @param dh            diffie hellman shared secret
+        * @param kes           array of key_exchange_t*
         * @param dh_other      others DH public value (IKEv1 only)
         * @param nonce_i       initiator's nonce
         * @param nonce_r       responder's nonce
@@ -356,7 +357,7 @@ struct bus_t {
         * @param shared        shared key used for key derivation (IKEv1-PSK only)
         * @param method        auth method for key derivation (IKEv1-non-PSK only)
         */
-       void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
+       void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, array_t *kes,
                                         chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
                                         ike_sa_t *rekey, shared_key_t *shared,
                                         auth_method_t method);
@@ -381,12 +382,12 @@ struct bus_t {
         *
         * @param child_sa      CHILD_SA this keymat is used for
         * @param initiator     initiator of the CREATE_CHILD_SA exchange
-        * @param dh            diffie hellman shared secret
+        * @param kes           array of key_exchange_t*, or NULL
         * @param nonce_i       initiator's nonce
         * @param nonce_r       responder's nonce
         */
        void (*child_keys)(bus_t *this, child_sa_t *child_sa, bool initiator,
-                                          key_exchange_t *dh, chunk_t nonce_i, chunk_t nonce_r);
+                                          array_t *kes, chunk_t nonce_i, chunk_t nonce_r);
 
        /**
         * CHILD_SA derived keys hook.
index bec48d187790b22547dd3464bda59c6564905fef..42297e2f4c51d3f9104d04963230f6aefeb4762d 100644 (file)
@@ -83,7 +83,7 @@ struct listener_t {
         * Hook called with IKE_SA key material.
         *
         * @param ike_sa        IKE_SA this keymat belongs to
-        * @param dh            diffie hellman shared secret
+        * @param kes           array of key_exchange_t*
         * @param dh_other      others DH public value (IKEv1 only)
         * @param nonce_i       initiator's nonce
         * @param nonce_r       responder's nonce
@@ -92,7 +92,7 @@ struct listener_t {
         * @param method        auth method for key derivation (IKEv1-non-PSK only)
         * @return                      TRUE to stay registered, FALSE to unregister
         */
-       bool (*ike_keys)(listener_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
+       bool (*ike_keys)(listener_t *this, ike_sa_t *ike_sa, array_t *kes,
                                         chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
                                         ike_sa_t *rekey, shared_key_t *shared,
                                         auth_method_t method);
@@ -119,13 +119,13 @@ struct listener_t {
         * @param ike_sa        IKE_SA the child sa belongs to
         * @param child_sa      CHILD_SA this keymat is used for
         * @param initiator     initiator of the CREATE_CHILD_SA exchange
-        * @param dh            diffie hellman shared secret
+        * @param kes           array of key_exchange_t*, or NULL
         * @param nonce_i       initiator's nonce
         * @param nonce_r       responder's nonce
         * @return                      TRUE to stay registered, FALSE to unregister
         */
        bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
-                                          bool initiator, key_exchange_t *dh,
+                                          bool initiator, array_t *kes,
                                           chunk_t nonce_i, chunk_t nonce_r);
 
        /**
index 2485b49bbf3d6e8a44a329b7d48b17f505a06e3e..3fb84477d78775b063d983071858b2f7841c0652 100644 (file)
@@ -51,10 +51,10 @@ struct private_ha_child_t {
 
 METHOD(listener_t, child_keys, bool,
        private_ha_child_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
-       bool initiator, key_exchange_t *dh, chunk_t nonce_i, chunk_t nonce_r)
+       bool initiator, array_t *kes, chunk_t nonce_i, chunk_t nonce_r)
 {
        ha_message_t *m;
-       chunk_t secret;
+       chunk_t secret, add_secret = chunk_empty;
        proposal_t *proposal;
        uint16_t alg, len;
        linked_list_t *local_ts, *remote_ts;
@@ -102,10 +102,11 @@ METHOD(listener_t, child_keys, bool,
        }
        m->add_attribute(m, HA_NONCE_I, nonce_i);
        m->add_attribute(m, HA_NONCE_R, nonce_r);
-       if (dh && dh->get_shared_secret(dh, &secret))
+       if (kes && key_exchange_concat_secrets(kes, &secret, &add_secret))
        {
                m->add_attribute(m, HA_SECRET, secret);
                chunk_clear(&secret);
+               chunk_clear(&add_secret);
        }
 
        local_ts = linked_list_create();
index 6535e4a1e0847cf3b81b8933433332ec4be5e53c..e6dab84579ce39993ef317e3cb3c3fdeeaaa8e3a 100644 (file)
@@ -82,12 +82,13 @@ static void copy_extensions(ha_message_t *m, ike_sa_t *ike_sa)
 }
 
 METHOD(listener_t, ike_keys, bool,
-       private_ha_ike_t *this, ike_sa_t *ike_sa, key_exchange_t *dh,
+       private_ha_ike_t *this, ike_sa_t *ike_sa, array_t *kes,
        chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey,
        shared_key_t *shared, auth_method_t method)
 {
        ha_message_t *m;
-       chunk_t secret;
+       key_exchange_t *ke;
+       chunk_t secret = chunk_empty, add_secret = chunk_empty;
        proposal_t *proposal;
        uint16_t alg, len;
 
@@ -95,8 +96,12 @@ METHOD(listener_t, ike_keys, bool,
        {       /* do not sync SA between nodes */
                return TRUE;
        }
-       if (!dh->get_shared_secret(dh, &secret))
+       if (!key_exchange_concat_secrets(kes, &secret, &add_secret) ||
+               !array_get(kes, ARRAY_HEAD, &ke) ||
+               add_secret.len > 0)
        {
+               chunk_clear(&secret);
+               chunk_clear(&add_secret);
                return TRUE;
        }
 
@@ -142,7 +147,7 @@ METHOD(listener_t, ike_keys, bool,
        chunk_clear(&secret);
        if (ike_sa->get_version(ike_sa) == IKEV1)
        {
-               if (dh->get_public_key(dh, &secret))
+               if (ke->get_public_key(ke, &secret))
                {
                        m->add_attribute(m, HA_LOCAL_DH, secret);
                        chunk_free(&secret);
index 2520b6a93e16e92eb921e4f4cbdda2c5739915f7..61c400580b0b0eba48d2848d628e6f7c041ad1ec 100644 (file)
@@ -220,6 +220,7 @@ METHOD(phase1_t, derive_keys, bool,
        private_phase1_t *this, peer_cfg_t *peer_cfg, auth_method_t method)
 {
        shared_key_t *shared_key = NULL;
+       array_t *kes = NULL;
 
        switch (method)
        {
@@ -245,9 +246,11 @@ METHOD(phase1_t, derive_keys, bool,
                DBG1(DBG_IKE, "key derivation for %N failed", auth_method_names, method);
                return FALSE;
        }
-       charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, this->dh_value,
+       array_insert_create(&kes, ARRAY_HEAD, this->dh);
+       charon->bus->ike_keys(charon->bus, this->ike_sa, kes, this->dh_value,
                                                  this->nonce_i, this->nonce_r, NULL, shared_key,
                                                  method);
+       array_destroy(kes);
        DESTROY_IF(shared_key);
        return TRUE;
 }
index 3d2e3efbe4e5ca0c4ddfbbf1b67d9c285d2cb71a..95fcaa7cfa28045f1314fe49ff53228e68591241 100644 (file)
@@ -270,6 +270,7 @@ static bool install(private_quick_mode_t *this)
        chunk_t encr_i, encr_r, integ_i, integ_r;
        linked_list_t *tsi, *tsr, *my_ts, *other_ts;
        child_sa_t *old = NULL;
+       array_t *kes = NULL;
 
        this->child_sa->set_proposal(this->child_sa, this->proposal);
        this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
@@ -377,8 +378,13 @@ static bool install(private_quick_mode_t *this)
                return FALSE;
        }
 
+       if (this->dh)
+       {
+               array_insert_create(&kes, ARRAY_HEAD, this->dh);
+       }
        charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
-                                                       this->dh, this->nonce_i, this->nonce_r);
+                                                       kes, this->nonce_i, this->nonce_r);
+       array_destroy(kes);
 
        my_ts = linked_list_create_from_enumerator(
                                this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
index 8a784af66369824b4183bd6bd725a4ddc703febb..3c7f6554c2322e9ced4266b025e2afb14eb7f2e2 100644 (file)
@@ -769,6 +769,8 @@ static status_t select_and_install(private_child_create_t *this,
                        charon->bus->child_derived_keys(charon->bus, this->child_sa,
                                                                                        this->initiator, encr_i, encr_r,
                                                                                        integ_i, integ_r);
+                       charon->bus->child_keys(charon->bus, this->child_sa,
+                                                                       this->initiator, kes, nonce_i, nonce_r);
                }
        }
        chunk_clear(&integ_i);
@@ -782,9 +784,6 @@ static status_t select_and_install(private_child_create_t *this,
                return status;
        }
 
-       charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
-                                                       this->dh, nonce_i, nonce_r);
-
        my_ts = linked_list_create_from_enumerator(
                                this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
        other_ts = linked_list_create_from_enumerator(
index 3d12e3848a6f8fe6311a43ff93cd6c003553695e..7e7fd3b6866f28b9af332bd39695ad4464991e36 100644 (file)
@@ -802,7 +802,7 @@ static bool derive_keys_internal(private_ike_init_t *this, chunk_t nonce_i,
        pseudo_random_function_t prf_alg = PRF_UNDEFINED;
        chunk_t skd = chunk_empty;
        ike_sa_id_t *id;
-       array_t *kes;
+       array_t *kes = NULL;
 
        id = this->ike_sa->get_id(this->ike_sa);
        if (this->old_sa)
@@ -818,9 +818,9 @@ static bool derive_keys_internal(private_ike_init_t *this, chunk_t nonce_i,
                array_destroy(kes);
                return FALSE;
        }
-       array_destroy(kes);
-       charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, chunk_empty,
+       charon->bus->ike_keys(charon->bus, this->ike_sa, kes, chunk_empty,
                                                  nonce_i, nonce_r, this->old_sa, NULL, AUTH_NONE);
+       array_destroy(kes);
        return TRUE;
 }