aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/encoding/message.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2011-11-21 13:19:19 +0100
committerTobias Brunner <tobias@strongswan.org>2012-03-20 17:30:46 +0100
commit477e856a15da725a674aa5783ff563c5123d230e (patch)
tree404f52cbc1fea9365e8052ffc2a300db0e4c2f29 /src/libcharon/encoding/message.c
parentb6f0029497c7aead1116c908f0b14b02a56a1769 (diff)
downloadstrongswan-477e856a15da725a674aa5783ff563c5123d230e.tar.bz2
strongswan-477e856a15da725a674aa5783ff563c5123d230e.tar.xz
Decrypt IKEv1 messages.
Diffstat (limited to 'src/libcharon/encoding/message.c')
-rw-r--r--src/libcharon/encoding/message.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 79cc86ed4..a368d96cd 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -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;
}