Derive IKEv1 CHILD_SA keymat twice, once for each IPsec SA
authorMartin Willi <martin@revosec.ch>
Wed, 23 Nov 2011 13:26:24 +0000 (14:26 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 20 Mar 2012 16:30:50 +0000 (17:30 +0100)
src/libcharon/sa/keymat_v1.c
src/libcharon/sa/keymat_v1.h
src/libcharon/sa/tasks/quick_mode.c

index 3ec8083..97a21e0 100644 (file)
@@ -503,32 +503,14 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
 
 METHOD(keymat_v1_t, derive_child_keys, bool,
        private_keymat_v1_t *this, proposal_t *proposal, diffie_hellman_t *dh,
-       chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i,
-       chunk_t *encr_r, chunk_t *integ_r)
+       u_int32_t spi_i, u_int32_t spi_r, chunk_t nonce_i, chunk_t nonce_r,
+       chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r)
 {
        u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
        u_int8_t protocol;
-       u_int32_t spi;
        prf_plus_t *prf_plus;
        chunk_t seed, secret = chunk_empty;
 
-       /* KEYMAT = prf+(SKEYID_d, [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b) */
-
-       protocol = proposal->get_protocol(proposal);
-       spi = proposal->get_spi(proposal);
-
-       if (dh)
-       {
-               if (dh->get_shared_secret(dh, &secret) != SUCCESS)
-               {
-                       return FALSE;
-               }
-               DBG4(DBG_CHD, "DH secret %B", &secret);
-       }
-       seed = chunk_cata("mcccc", secret, chunk_from_thing(protocol),
-                                         chunk_from_thing(spi), nonce_i, nonce_r);
-       DBG4(DBG_CHD, "seed %B", &seed);
-
        if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
                                                                &enc_alg, &enc_size))
        {
@@ -591,16 +573,37 @@ METHOD(keymat_v1_t, derive_child_keys, bool,
                int_size /= 8;
        }
 
+       /* KEYMAT = prf+(SKEYID_d, [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b) */
        this->prf->set_key(this->prf, this->skeyid_d);
-       prf_plus = prf_plus_create(this->prf, FALSE, seed);
+       protocol = proposal->get_protocol(proposal);
+       if (dh)
+       {
+               if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+               {
+                       return FALSE;
+               }
+               DBG4(DBG_CHD, "DH secret %B", &secret);
+       }
 
+       seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
+                                         chunk_from_thing(spi_r), nonce_i, nonce_r);
+       DBG4(DBG_CHD, "initiator SA seed %B", &seed);
+
+       prf_plus = prf_plus_create(this->prf, FALSE, seed);
        prf_plus->allocate_bytes(prf_plus, enc_size, encr_i);
        prf_plus->allocate_bytes(prf_plus, int_size, integ_i);
+       prf_plus->destroy(prf_plus);
+
+       seed = chunk_cata("ccccc", secret, chunk_from_thing(protocol),
+                                         chunk_from_thing(spi_i), nonce_i, nonce_r);
+       DBG4(DBG_CHD, "responder SA seed %B", &seed);
+       prf_plus = prf_plus_create(this->prf, FALSE, seed);
        prf_plus->allocate_bytes(prf_plus, enc_size, encr_r);
        prf_plus->allocate_bytes(prf_plus, int_size, integ_r);
-
        prf_plus->destroy(prf_plus);
 
+       chunk_clear(&secret);
+
        if (enc_size)
        {
                DBG4(DBG_CHD, "encryption initiator key %B", encr_i);
index e2d5cf6..eb07e3a 100644 (file)
@@ -61,6 +61,8 @@ struct keymat_v1_t {
         *
         * @param proposal              selected algorithms
         * @param dh                    diffie hellman key, NULL if none used
+        * @param spi_i                 SPI chosen by initiatior
+        * @param spi_r                 SPI chosen by responder
         * @param nonce_i               quick mode initiator nonce
         * @param nonce_r               quick mode responder nonce
         * @param encr_i                allocated initiators encryption key
@@ -69,7 +71,8 @@ struct keymat_v1_t {
         * @param integ_r               allocated responders integrity key
         */
        bool (*derive_child_keys)(keymat_v1_t *this, proposal_t *proposal,
-                                               diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
+                                               diffie_hellman_t *dh, u_int32_t spi_i, u_int32_t spi_r,
+                                               chunk_t nonce_i, chunk_t nonce_r,
                                                chunk_t *encr_i, chunk_t *integ_i,
                                                chunk_t *encr_r, chunk_t *integ_r);
 
index 987b8d5..8586d9a 100644 (file)
@@ -124,7 +124,8 @@ static bool install(private_quick_mode_t *this)
        tsi->insert_last(tsi, this->tsi);
        tsr->insert_last(tsr, this->tsr);
        if (this->keymat->derive_child_keys(this->keymat, this->proposal, NULL,
-                       this->nonce_i, this->nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
+                                               this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
+                                               &encr_i, &integ_i, &encr_r, &integ_r))
        {
                if (this->initiator)
                {