]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
keymat_v2: Use plugin-provided KDF_PRF to derive SKEYSEED
authorTobias Brunner <tobias@strongswan.org>
Tue, 15 Mar 2022 08:49:43 +0000 (09:49 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 14 Apr 2022 17:02:56 +0000 (19:02 +0200)
src/libcharon/sa/ikev2/keymat_v2.c

index d5c6f88209a9187a06f6dc5c82b57242b456e819..fe58de5e0331e7aeafafd2ee8d42cbde284cc455 100644 (file)
@@ -244,9 +244,8 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
        chunk_t prf_plus_seed, spi_i, spi_r, keymat = chunk_empty;
        chunk_t sk_ei = chunk_empty, sk_er = chunk_empty;
        chunk_t sk_ai = chunk_empty, sk_ar = chunk_empty, sk_pi, sk_pr;
-       kdf_t *prf_plus = NULL;
+       kdf_t *prf = NULL, *prf_plus = NULL;
        uint16_t prf_alg, key_size, enc_alg, enc_size, int_alg;
-       prf_t *rekey_prf = NULL;
        bool success = FALSE;
 
        spi_i = chunk_alloca(sizeof(uint64_t));
@@ -328,19 +327,24 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
                        break;
        }
        fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
-       *((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
-       *((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
-       prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
 
-       /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
-        *
-        * if we are rekeying, SKEYSEED is built on another way
-        */
-       if (rekey_function == PRF_UNDEFINED) /* not rekeying */
+       if (rekey_function == PRF_UNDEFINED)
        {
                /* SKEYSEED = prf(Ni | Nr, g^ir) */
-               if (this->prf->set_key(this->prf, fixed_nonce) &&
-                       this->prf->allocate_bytes(this->prf, secret, &skeyseed))
+               prf = lib->crypto->create_kdf(lib->crypto, KDF_PRF, this->prf_alg);
+               if (!prf)
+               {
+                       DBG1(DBG_IKE, "%N with %N not supported",
+                                key_derivation_function_names, KDF_PRF,
+                                pseudo_random_function_names, rekey_function);
+                       chunk_clear(&secret);
+                       chunk_free(&full_nonce);
+                       chunk_free(&fixed_nonce);
+                       return FALSE;
+               }
+               if (prf->set_param(prf, KDF_PARAM_KEY, secret) &&
+                       prf->set_param(prf, KDF_PARAM_SALT, fixed_nonce) &&
+                       prf->allocate_bytes(prf, 0, &skeyseed))
                {
                        prf_plus = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS,
                                                                                           this->prf_alg);
@@ -350,26 +354,36 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
        {
                /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
                 * use OLD SAs PRF functions for both prf_plus and prf */
-               rekey_prf = lib->crypto->create_prf(lib->crypto, rekey_function);
-               if (!rekey_prf)
+               prf = lib->crypto->create_kdf(lib->crypto, KDF_PRF, rekey_function);
+               if (!prf)
                {
-                       DBG1(DBG_IKE, "PRF of old SA %N not supported!",
+                       DBG1(DBG_IKE, "%N with PRF of old SA %N not supported",
+                                key_derivation_function_names, KDF_PRF,
                                 pseudo_random_function_names, rekey_function);
                        chunk_clear(&secret);
                        chunk_free(&full_nonce);
                        chunk_free(&fixed_nonce);
-                       chunk_clear(&prf_plus_seed);
                        return FALSE;
                }
                secret = chunk_cat("sc", secret, full_nonce);
-               if (rekey_prf->set_key(rekey_prf, rekey_skd) &&
-                       rekey_prf->allocate_bytes(rekey_prf, secret, &skeyseed))
+               if (prf->set_param(prf, KDF_PARAM_KEY, secret) &&
+                       prf->set_param(prf, KDF_PARAM_SALT, rekey_skd) &&
+                       prf->allocate_bytes(prf, 0, &skeyseed))
                {
                        prf_plus = lib->crypto->create_kdf(lib->crypto, KDF_PRF_PLUS,
                                                                                           rekey_function);
                }
        }
        DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
+       chunk_clear(&secret);
+       chunk_free(&fixed_nonce);
+       DESTROY_IF(prf);
+
+       /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
+        */
+       *((uint64_t*)spi_i.ptr) = id->get_initiator_spi(id);
+       *((uint64_t*)spi_r.ptr) = id->get_responder_spi(id);
+       prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
 
        if (prf_plus &&
                (!prf_plus->set_param(prf_plus, KDF_PARAM_KEY, skeyseed) ||
@@ -378,13 +392,9 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
                prf_plus->destroy(prf_plus);
                prf_plus = NULL;
        }
-
        chunk_clear(&skeyseed);
-       chunk_clear(&secret);
        chunk_free(&full_nonce);
-       chunk_free(&fixed_nonce);
-       chunk_clear(&prf_plus_seed);
-       DESTROY_IF(rekey_prf);
+       chunk_free(&prf_plus_seed);
 
        if (!prf_plus)
        {