Add a return value to keymat_v1_t.{get,update,confirm}_iv
authorMartin Willi <martin@revosec.ch>
Mon, 9 Jul 2012 14:27:09 +0000 (16:27 +0200)
committerMartin Willi <martin@revosec.ch>
Mon, 16 Jul 2012 12:55:06 +0000 (14:55 +0200)
src/libcharon/encoding/message.c
src/libcharon/plugins/ha/ha_dispatcher.c
src/libcharon/plugins/ha/ha_ike.c
src/libcharon/sa/ikev1/keymat_v1.c
src/libcharon/sa/ikev1/keymat_v1.h

index 1aef7c2..7e4c6e0 100644 (file)
@@ -1568,7 +1568,11 @@ METHOD(message_t, generate, status_t,
                encryption->set_transform(encryption, aead);
                if (this->is_encrypted)
                {       /* for IKEv1 instead of associated data we provide the IV */
-                       chunk = keymat_v1->get_iv(keymat_v1, this->message_id);
+                       if (!keymat_v1->get_iv(keymat_v1, this->message_id, &chunk))
+                       {
+                               generator->destroy(generator);
+                               return FAILED;
+                       }
                }
                else
                {       /* build associated data (without header of encryption payload) */
@@ -1579,9 +1583,17 @@ METHOD(message_t, generate, status_t,
                this->payloads->insert_last(this->payloads, encryption);
                if (!encryption->encrypt(encryption, chunk))
                {
+                       if (this->is_encrypted)
+                       {
+                               free(chunk.ptr);
+                       }
                        generator->destroy(generator);
                        return INVALID_STATE;
                }
+               if (this->is_encrypted)
+               {
+                       free(chunk.ptr);
+               }
                generator->generate_payload(generator, &encryption->payload_interface);
        }
        chunk = generator->get_chunk(generator, &lenpos);
@@ -1595,8 +1607,12 @@ METHOD(message_t, generate, status_t,
 
                bs = aead->get_block_size(aead);
                last_block = chunk_create(chunk.ptr + chunk.len - bs, bs);
-               keymat_v1->update_iv(keymat_v1, this->message_id, last_block);
-               keymat_v1->confirm_iv(keymat_v1, this->message_id);
+               if (!keymat_v1->update_iv(keymat_v1, this->message_id, last_block) ||
+                       !keymat_v1->confirm_iv(keymat_v1, this->message_id))
+               {
+                       generator->destroy(generator);
+                       return FAILED;
+               }
        }
        generator->destroy(generator);
        *packet = this->packet->clone(this->packet);
@@ -1846,17 +1862,25 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
                        {       /* instead of associated data we provide the IV, we also update
                                 * the IV with the last encrypted block */
                                keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
-                               chunk_t last_block;
+                               chunk_t iv = chunk_empty;
 
-                               last_block = chunk_create(chunk.ptr + chunk.len - bs, bs);
-                               chunk = keymat_v1->get_iv(keymat_v1, this->message_id);
-                               keymat_v1->update_iv(keymat_v1, this->message_id, last_block);
+                               if (keymat_v1->get_iv(keymat_v1, this->message_id, &iv) &&
+                                       keymat_v1->update_iv(keymat_v1, this->message_id,
+                                                       chunk_create(chunk.ptr + chunk.len - bs, bs)))
+                               {
+                                       status = encryption->decrypt(encryption, iv);
+                               }
+                               else
+                               {
+                                       status = FAILED;
+                               }
+                               free(chunk.ptr);
                        }
                        else
                        {
                                chunk.len -= encryption->get_length(encryption);
+                               status = encryption->decrypt(encryption, chunk);
                        }
-                       status = encryption->decrypt(encryption, chunk);
                        if (status != SUCCESS)
                        {
                                break;
@@ -2035,7 +2059,10 @@ METHOD(message_t, parse_body, status_t,
                }
                if (this->is_encrypted)
                {       /* message verified, confirm IV */
-                       keymat_v1->confirm_iv(keymat_v1, this->message_id);
+                       if (!keymat_v1->confirm_iv(keymat_v1, this->message_id))
+                       {
+                               return FAILED;
+                       }
                }
        }
        return SUCCESS;
index 98055fa..8b6ec91 100644 (file)
@@ -525,8 +525,10 @@ static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message)
                                keymat_v1_t *keymat;
 
                                keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
-                               keymat->update_iv(keymat, 0, iv);
-                               keymat->confirm_iv(keymat, 0);
+                               if (keymat->update_iv(keymat, 0, iv))
+                               {
+                                       keymat->confirm_iv(keymat, 0);
+                               }
                        }
                }
                this->cache->cache(this->cache, ike_sa, message);
index 2819b9d..2d02917 100644 (file)
@@ -302,13 +302,15 @@ METHOD(listener_t, message_hook, bool,
                if (mid == 0)
                {
                        keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
-                       iv = keymat->get_iv(keymat, mid);
-                       m = ha_message_create(HA_IKE_IV);
-                       m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
-                       m->add_attribute(m, HA_IV, iv);
-                       free(iv.ptr);
-                       this->socket->push(this->socket, m);
-                       this->cache->cache(this->cache, ike_sa, m);
+                       if (keymat->get_iv(keymat, mid, &iv))
+                       {
+                               m = ha_message_create(HA_IKE_IV);
+                               m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+                               m->add_attribute(m, HA_IV, iv);
+                               free(iv.ptr);
+                               this->socket->push(this->socket, m);
+                               this->cache->cache(this->cache, ike_sa, m);
+                       }
                }
                if (!incoming && message->get_exchange_type(message) == TRANSACTION)
                {
index 9540075..8f6da3c 100644 (file)
@@ -964,7 +964,7 @@ METHOD(keymat_v1_t, get_hash_phase2, bool,
 /**
  * Generate an IV
  */
-static void generate_iv(private_keymat_v1_t *this, iv_data_t *iv)
+static bool generate_iv(private_keymat_v1_t *this, iv_data_t *iv)
 {
        if (iv->mid == 0 || iv->iv.ptr)
        {       /* use last block of previous encrypted message */
@@ -985,6 +985,7 @@ static void generate_iv(private_keymat_v1_t *this, iv_data_t *iv)
                }
        }
        DBG4(DBG_IKE, "next IV for MID %u %B", iv->mid, &iv->iv);
+       return TRUE;
 }
 
 /**
@@ -1016,7 +1017,11 @@ static iv_data_t *lookup_iv(private_keymat_v1_t *this, u_int32_t mid)
                INIT(found,
                        .mid = mid,
                );
-               generate_iv(this, found);
+               if (!generate_iv(this, found))
+               {
+                       iv_data_destroy(found);
+                       return NULL;
+               }
        }
        this->ivs->insert_first(this->ivs, found);
        /* remove least recently used IV if maximum reached */
@@ -1028,13 +1033,21 @@ static iv_data_t *lookup_iv(private_keymat_v1_t *this, u_int32_t mid)
        return found;
 }
 
-METHOD(keymat_v1_t, get_iv, chunk_t,
-       private_keymat_v1_t *this, u_int32_t mid)
+METHOD(keymat_v1_t, get_iv, bool,
+       private_keymat_v1_t *this, u_int32_t mid, chunk_t *out)
 {
-       return chunk_clone(lookup_iv(this, mid)->iv);
+       iv_data_t *iv;
+
+       iv = lookup_iv(this, mid);
+       if (iv)
+       {
+               *out = iv->iv;
+               return TRUE;
+       }
+       return FALSE;
 }
 
-METHOD(keymat_v1_t, update_iv, void,
+METHOD(keymat_v1_t, update_iv, bool,
        private_keymat_v1_t *this, u_int32_t mid, chunk_t last_block)
 {
        iv_data_t *iv = lookup_iv(this, mid);
@@ -1042,17 +1055,20 @@ METHOD(keymat_v1_t, update_iv, void,
        {       /* update last block */
                chunk_free(&iv->last_block);
                iv->last_block = chunk_clone(last_block);
+               return TRUE;
        }
+       return FALSE;
 }
 
-METHOD(keymat_v1_t, confirm_iv, void,
+METHOD(keymat_v1_t, confirm_iv, bool,
        private_keymat_v1_t *this, u_int32_t mid)
 {
        iv_data_t *iv = lookup_iv(this, mid);
        if (iv)
        {
-               generate_iv(this, iv);
+               return generate_iv(this, iv);
        }
+       return FALSE;
 }
 
 METHOD(keymat_t, get_version, ike_version_t,
index 8acbf58..a25bc98 100644 (file)
@@ -121,9 +121,10 @@ struct keymat_v1_t {
         * Returns the IV for a message with the given message ID.
         *
         * @param mid                   message ID
-        * @return                              IV (needs to be freed)
+        * @param iv                    chunk receiving allocated IV
+        * @return                              TRUE if IV allocated successfully
         */
-       chunk_t (*get_iv)(keymat_v1_t *this, u_int32_t mid);
+       bool (*get_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t *iv);
 
        /**
         * Updates the IV for the next message with the given message ID.
@@ -135,8 +136,9 @@ struct keymat_v1_t {
         *
         * @param mid                   message ID
         * @param last_block    last block of encrypted message (gets cloned)
+        * @return                              TRUE if IV updated successfully
         */
-       void (*update_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t last_block);
+       bool (*update_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t last_block);
 
        /**
         * Confirms the updated IV for the given message ID.
@@ -145,9 +147,9 @@ struct keymat_v1_t {
         * be called after update_iv.
         *
         * @param mid                   message ID
+        * @return                              TRUE if IV confirmed successfully
         */
-       void (*confirm_iv)(keymat_v1_t *this, u_int32_t mid);
-
+       bool (*confirm_iv)(keymat_v1_t *this, u_int32_t mid);
 };
 
 /**