diff options
author | Tobias Brunner <tobias@strongswan.org> | 2011-11-21 13:19:19 +0100 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2012-03-20 17:30:46 +0100 |
commit | 477e856a15da725a674aa5783ff563c5123d230e (patch) | |
tree | 404f52cbc1fea9365e8052ffc2a300db0e4c2f29 /src/libcharon/encoding/message.c | |
parent | b6f0029497c7aead1116c908f0b14b02a56a1769 (diff) | |
download | strongswan-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.c | 46 |
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; } |