aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/encoding/message.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2011-11-21 13:24:17 +0100
committerTobias Brunner <tobias@strongswan.org>2012-03-20 17:30:46 +0100
commitc92f2cf36deca2d3917020fc8c41abb8ada316ca (patch)
treea6d559b52cd9ede3f40c4678ea6ea0c36e34d879 /src/libcharon/encoding/message.c
parent477e856a15da725a674aa5783ff563c5123d230e (diff)
downloadstrongswan-c92f2cf36deca2d3917020fc8c41abb8ada316ca.tar.bz2
strongswan-c92f2cf36deca2d3917020fc8c41abb8ada316ca.tar.xz
Encrypt IKEv1 messages.
Diffstat (limited to 'src/libcharon/encoding/message.c')
-rw-r--r--src/libcharon/encoding/message.c83
1 files changed, 66 insertions, 17 deletions
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index a368d96cd..d088a7bf7 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -1279,9 +1279,10 @@ static void order_payloads(private_message_t *this)
}
/**
- * Wrap payloads in a encryption payload
+ * Wrap payloads in an encryption payload
*/
-static encryption_payload_t* wrap_payloads(private_message_t *this)
+static encryption_payload_t* wrap_payloads(private_message_t *this,
+ payload_type_t encryption_type)
{
encryption_payload_t *encryption;
linked_list_t *payloads;
@@ -1295,7 +1296,7 @@ static encryption_payload_t* wrap_payloads(private_message_t *this)
payloads->insert_last(payloads, current);
}
- encryption = encryption_payload_create();
+ encryption = encryption_payload_create(encryption_type);
while (payloads->remove_first(payloads, (void**)&current) == SUCCESS)
{
payload_rule_t *rule;
@@ -1308,8 +1309,8 @@ static encryption_payload_t* wrap_payloads(private_message_t *this)
{
encrypt = rule->encrypted;
}
- if (encrypt)
- {
+ if (encrypt || this->is_encrypted)
+ { /* encryption is forced for IKEv1 */
DBG2(DBG_ENC, "insert payload %N to encryption payload",
payload_type_names, type);
encryption->add_payload(encryption, current);
@@ -1335,16 +1336,18 @@ METHOD(message_t, disable_sort, void,
METHOD(message_t, generate, status_t,
private_message_t *this, keymat_t *keymat, packet_t **packet)
{
+ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
generator_t *generator;
ike_header_t *ike_header;
payload_t *payload, *next;
encryption_payload_t *encryption = NULL;
+ payload_type_t next_type;
enumerator_t *enumerator;
aead_t *aead;
chunk_t chunk;
char str[BUF_LEN];
u_int32_t *lenpos;
- bool *reserved;
+ bool encrypted = FALSE, *reserved;
int i;
if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
@@ -1374,10 +1377,33 @@ METHOD(message_t, generate, status_t,
DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str)));
+ if (this->major_version == IKEV2_MAJOR_VERSION)
+ {
+ encrypted = this->rule->encrypted;
+ }
+ else
+ { /* if at least one payload requires encryption, encrypt the message */
+ /* TODO-IKEV1: set is_encrypted externally instead of this check? */
+ enumerator = this->payloads->create_enumerator(this->payloads);
+ while (enumerator->enumerate(enumerator, (void**)&payload))
+ {
+ payload_rule_t *rule;
+ rule = get_payload_rule(this, payload->get_type(payload));
+ if (rule && rule->encrypted)
+ {
+ this->is_encrypted = TRUE;
+ encrypted = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
aead = keymat->get_aead(keymat, FALSE);
- if (aead && this->rule->encrypted)
+ if (aead && encrypted)
{
- encryption = wrap_payloads(this);
+ encryption = wrap_payloads(this, this->is_encrypted ? ENCRYPTED_V1
+ : ENCRYPTED);
}
else
{
@@ -1395,6 +1421,10 @@ METHOD(message_t, generate, status_t,
ike_header->set_initiator_flag(ike_header,
this->ike_sa_id->is_initiator(this->ike_sa_id));
}
+ else
+ {
+ ike_header->set_encryption_flag(ike_header, this->is_encrypted);
+ }
ike_header->set_initiator_spi(ike_header,
this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
ike_header->set_responder_spi(ike_header,
@@ -1422,20 +1452,32 @@ METHOD(message_t, generate, status_t,
payload = next;
}
enumerator->destroy(enumerator);
- payload->set_next_type(payload, encryption ? ENCRYPTED : NO_PAYLOAD);
+ if (this->is_encrypted)
+ { /* for encrypted IKEv1 messages */
+ next_type = encryption->payload_interface.get_next_type(
+ (payload_t*)encryption);
+ }
+ else
+ {
+ next_type = encryption ? ENCRYPTED : NO_PAYLOAD;
+ }
+ payload->set_next_type(payload, next_type);
generator->generate_payload(generator, payload);
ike_header->destroy(ike_header);
if (encryption)
{
- u_int32_t *lenpos;
-
- /* build associated data (without header of encryption payload) */
- chunk = generator->get_chunk(generator, &lenpos);
+ if (this->is_encrypted)
+ { /* for IKEv1 instead of associated data we provide the IV */
+ chunk = keymat_v1->get_iv(keymat_v1, this->message_id);
+ }
+ else
+ { /* build associated data (without header of encryption payload) */
+ chunk = generator->get_chunk(generator, &lenpos);
+ /* fill in length, including encryption payload */
+ htoun32(lenpos, chunk.len + encryption->get_length(encryption));
+ }
encryption->set_transform(encryption, aead);
- /* fill in length, including encryption payload */
- htoun32(lenpos, chunk.len + encryption->get_length(encryption));
-
this->payloads->insert_last(this->payloads, encryption);
if (!encryption->encrypt(encryption, chunk))
{
@@ -1447,8 +1489,15 @@ METHOD(message_t, generate, status_t,
chunk = generator->get_chunk(generator, &lenpos);
htoun32(lenpos, chunk.len);
this->packet->set_data(this->packet, chunk_clone(chunk));
+ if (this->is_encrypted)
+ { /* update the IV for the next IKEv1 message */
+ chunk_t last_block;
+ size_t 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);
+ }
generator->destroy(generator);
-
*packet = this->packet->clone(this->packet);
return SUCCESS;
}