Decrypt IKEv1 messages.

This commit is contained in:
Tobias Brunner
2012-03-20 17:30:46 +01:00
parent b6f0029497
commit 477e856a15
+43 -3
View File
@@ -24,6 +24,7 @@
#include <library.h>
#include <daemon.h>
#include <sa/keymat_v1.h>
#include <encoding/generator.h>
#include <encoding/parser.h>
#include <encoding/payloads/encodings.h>
@@ -1566,6 +1567,23 @@ static status_t parse_payloads(private_message_t *this)
payload_t *payload;
status_t status;
if (this->is_encrypted)
{ /* wrap the whole encrypted IKEv1 message in a special encryption
* payload which is then handled just like a regular payload */
encryption_payload_t *encryption;
status = this->parser->parse_payload(this->parser, ENCRYPTED_V1,
(payload_t**)&encryption);
if (status != SUCCESS)
{
DBG1(DBG_ENC, "failed to wrap encrypted IKEv1 message");
return PARSE_ERROR;
}
encryption->payload_interface.set_next_type((payload_t*)encryption,
this->first_payload);
this->payloads->insert_last(this->payloads, encryption);
return SUCCESS;
}
while (type != NO_PAYLOAD)
{
DBG2(DBG_ENC, "starting parsing a %N payload",
@@ -1626,11 +1644,12 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
DBG2(DBG_ENC, "process payload of type %N", payload_type_names, type);
if (type == ENCRYPTED)
if (type == ENCRYPTED || type == ENCRYPTED_V1)
{
encryption_payload_t *encryption;
payload_t *encrypted;
chunk_t chunk;
size_t bs;
encryption = (encryption_payload_t*)payload;
@@ -1643,15 +1662,29 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
break;
}
aead = keymat->get_aead(keymat, TRUE);
bs = aead->get_block_size(aead);
encryption->set_transform(encryption, aead);
chunk = this->packet->get_data(this->packet);
if (chunk.len < encryption->get_length(encryption))
if (chunk.len < encryption->get_length(encryption) ||
chunk.len < bs)
{
DBG1(DBG_ENC, "invalid payload length");
status = VERIFY_ERROR;
break;
}
chunk.len -= encryption->get_length(encryption);
if (type == ENCRYPTED_V1)
{ /* 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_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);
}
else
{
chunk.len -= encryption->get_length(encryption);
}
status = encryption->decrypt(encryption, chunk);
if (status != SUCCESS)
{
@@ -1792,6 +1825,13 @@ METHOD(message_t, parse_body, status_t,
DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str)));
if (this->is_encrypted)
{ /* TODO-IKEv1: this should be done later when we know this is no
* retransmit */
keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
keymat_v1->confirm_iv(keymat_v1, this->message_id);
}
return SUCCESS;
}