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 <library.h>
#include <daemon.h> #include <daemon.h>
#include <sa/keymat_v1.h>
#include <encoding/generator.h> #include <encoding/generator.h>
#include <encoding/parser.h> #include <encoding/parser.h>
#include <encoding/payloads/encodings.h> #include <encoding/payloads/encodings.h>
@@ -1566,6 +1567,23 @@ static status_t parse_payloads(private_message_t *this)
payload_t *payload; payload_t *payload;
status_t status; 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) while (type != NO_PAYLOAD)
{ {
DBG2(DBG_ENC, "starting parsing a %N 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); 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; encryption_payload_t *encryption;
payload_t *encrypted; payload_t *encrypted;
chunk_t chunk; chunk_t chunk;
size_t bs;
encryption = (encryption_payload_t*)payload; encryption = (encryption_payload_t*)payload;
@@ -1643,15 +1662,29 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
break; break;
} }
aead = keymat->get_aead(keymat, TRUE); aead = keymat->get_aead(keymat, TRUE);
bs = aead->get_block_size(aead);
encryption->set_transform(encryption, aead); encryption->set_transform(encryption, aead);
chunk = this->packet->get_data(this->packet); 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"); DBG1(DBG_ENC, "invalid payload length");
status = VERIFY_ERROR; status = VERIFY_ERROR;
break; 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); status = encryption->decrypt(encryption, chunk);
if (status != SUCCESS) 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))); 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; return SUCCESS;
} }