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) */
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);
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);
{ /* 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;
}
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;
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);
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)
{
/**
* 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 */
}
}
DBG4(DBG_IKE, "next IV for MID %u %B", iv->mid, &iv->iv);
+ return TRUE;
}
/**
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 */
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);
{ /* 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,
* 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.
*
* @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.
* 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);
};
/**