From e8229ad558efcb7b07c6ef0f77269120d49500f9 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 5 Aug 2013 15:41:45 +0200 Subject: iv_gen: Provide external sequence number (IKE, ESP) This prevents duplicate sequential IVs in case of a HA failover. --- src/libcharon/encoding/message.c | 2 +- src/libcharon/encoding/payloads/encryption_payload.c | 6 +++--- src/libcharon/encoding/payloads/encryption_payload.h | 4 +++- src/libipsec/esp_packet.c | 2 +- src/libstrongswan/crypto/iv/iv_gen.h | 6 ++++-- src/libstrongswan/crypto/iv/iv_gen_rand.c | 4 ++-- src/libstrongswan/crypto/iv/iv_gen_seq.c | 17 ++++------------- 7 files changed, 18 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 9fc108b40..11e735a37 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1622,7 +1622,7 @@ METHOD(message_t, generate, status_t, htoun32(lenpos, chunk.len + encryption->get_length(encryption)); } this->payloads->insert_last(this->payloads, encryption); - if (encryption->encrypt(encryption, chunk) != SUCCESS) + if (encryption->encrypt(encryption, this->message_id, chunk) != SUCCESS) { generator->destroy(generator); return INVALID_STATE; diff --git a/src/libcharon/encoding/payloads/encryption_payload.c b/src/libcharon/encoding/payloads/encryption_payload.c index 302c4a45a..6a9f9c3bd 100644 --- a/src/libcharon/encoding/payloads/encryption_payload.c +++ b/src/libcharon/encoding/payloads/encryption_payload.c @@ -309,7 +309,7 @@ static chunk_t append_header(private_encryption_payload_t *this, chunk_t assoc) } METHOD(encryption_payload_t, encrypt, status_t, - private_encryption_payload_t *this, chunk_t assoc) + private_encryption_payload_t *this, u_int64_t mid, chunk_t assoc) { chunk_t iv, plain, padding, icv, crypt; generator_t *generator; @@ -364,7 +364,7 @@ METHOD(encryption_payload_t, encrypt, status_t, crypt = chunk_create(plain.ptr, plain.len + padding.len); generator->destroy(generator); - if (!iv_gen->get_iv(iv_gen, iv.len, iv.ptr) || + if (!iv_gen->get_iv(iv_gen, mid, iv.len, iv.ptr) || !rng->get_bytes(rng, padding.len - 1, padding.ptr)) { DBG1(DBG_ENC, "encrypting encryption payload failed, no IV or padding"); @@ -396,7 +396,7 @@ METHOD(encryption_payload_t, encrypt, status_t, } METHOD(encryption_payload_t, encrypt_v1, status_t, - private_encryption_payload_t *this, chunk_t iv) + private_encryption_payload_t *this, u_int64_t mid, chunk_t iv) { generator_t *generator; chunk_t plain, padding; diff --git a/src/libcharon/encoding/payloads/encryption_payload.h b/src/libcharon/encoding/payloads/encryption_payload.h index 5c6069339..f4fc7d667 100644 --- a/src/libcharon/encoding/payloads/encryption_payload.h +++ b/src/libcharon/encoding/payloads/encryption_payload.h @@ -71,13 +71,15 @@ struct encryption_payload_t { /** * Generate, encrypt and sign contained payloads. * + * @param mid message ID * @param assoc associated data * @return * - SUCCESS if encryption successful * - FAILED if encryption failed * - INVALID_STATE if aead not supplied, but needed */ - status_t (*encrypt) (encryption_payload_t *this, chunk_t assoc); + status_t (*encrypt) (encryption_payload_t *this, u_int64_t mid, + chunk_t assoc); /** * Decrypt, verify and parse contained payloads. diff --git a/src/libipsec/esp_packet.c b/src/libipsec/esp_packet.c index 1b8625ca7..db5ef3685 100644 --- a/src/libipsec/esp_packet.c +++ b/src/libipsec/esp_packet.c @@ -319,7 +319,7 @@ METHOD(esp_packet_t, encrypt, status_t, writer->write_uint32(writer, next_seqno); iv = writer->skip(writer, iv.len); - if (!iv_gen->get_iv(iv_gen, iv.len, iv.ptr)) + if (!iv_gen->get_iv(iv_gen, next_seqno, iv.len, iv.ptr)) { DBG1(DBG_ESP, "ESP encryption failed: could not generate IV"); writer->destroy(writer); diff --git a/src/libstrongswan/crypto/iv/iv_gen.h b/src/libstrongswan/crypto/iv/iv_gen.h index 641c1f133..f6bc6471f 100644 --- a/src/libstrongswan/crypto/iv/iv_gen.h +++ b/src/libstrongswan/crypto/iv/iv_gen.h @@ -33,21 +33,23 @@ struct iv_gen_t { /** * Generates an IV and writes it into the buffer. * + * @param seq external sequence number * @param size size of IV in bytes * @param buffer pointer where the generated IV will be written * @return TRUE if IV allocation was successful, FALSE otherwise */ - bool (*get_iv)(iv_gen_t *this, size_t size, + bool (*get_iv)(iv_gen_t *this, u_int64_t seq, size_t size, u_int8_t *buffer) __attribute__((warn_unused_result)); /** * Generates an IV and allocates space for it. * + * @param seq external sequence number * @param size size of IV in bytes * @param chunk chunk which will hold the generated IV * @return TRUE if IV allocation was successful, FALSE otherwise */ - bool (*allocate_iv)(iv_gen_t *this, size_t size, + bool (*allocate_iv)(iv_gen_t *this, u_int64_t seq, size_t size, chunk_t *chunk) __attribute__((warn_unused_result)); /** diff --git a/src/libstrongswan/crypto/iv/iv_gen_rand.c b/src/libstrongswan/crypto/iv/iv_gen_rand.c index 3448ee041..2bed63fcc 100644 --- a/src/libstrongswan/crypto/iv/iv_gen_rand.c +++ b/src/libstrongswan/crypto/iv/iv_gen_rand.c @@ -36,7 +36,7 @@ struct private_iv_gen_t { }; METHOD(iv_gen_t, get_iv, bool, - private_iv_gen_t *this, size_t size, u_int8_t *buffer) + private_iv_gen_t *this, u_int64_t seq, size_t size, u_int8_t *buffer) { if (!this->rng) { @@ -46,7 +46,7 @@ METHOD(iv_gen_t, get_iv, bool, } METHOD(iv_gen_t, allocate_iv, bool, - private_iv_gen_t *this, size_t size, chunk_t *chunk) + private_iv_gen_t *this, u_int64_t seq, size_t size, chunk_t *chunk) { if (!this->rng) { diff --git a/src/libstrongswan/crypto/iv/iv_gen_seq.c b/src/libstrongswan/crypto/iv/iv_gen_seq.c index d8a5a2909..cbbc2dc7e 100644 --- a/src/libstrongswan/crypto/iv/iv_gen_seq.c +++ b/src/libstrongswan/crypto/iv/iv_gen_seq.c @@ -26,38 +26,29 @@ struct private_iv_gen_t { * Public iv_gen_t interface. */ iv_gen_t public; - - /** - * sequence number - */ - u_int64_t seq; }; METHOD(iv_gen_t, get_iv, bool, - private_iv_gen_t *this, size_t size, u_int8_t *buffer) + private_iv_gen_t *this, u_int64_t seq, size_t size, u_int8_t *buffer) { u_int8_t iv[sizeof(u_int64_t)]; size_t len = size; - if (this->seq == UINT64_MAX || len < sizeof(u_int64_t)) - { - return FALSE; - } if (len > sizeof(u_int64_t)) { len = sizeof(u_int64_t); memset(buffer, 0, size - len); } - htoun64(iv, this->seq++); + htoun64(iv, seq); memcpy(buffer + size - len, iv + sizeof(u_int64_t) - len, len); return TRUE; } METHOD(iv_gen_t, allocate_iv, bool, - private_iv_gen_t *this, size_t size, chunk_t *chunk) + private_iv_gen_t *this, u_int64_t seq, size_t size, chunk_t *chunk) { *chunk = chunk_alloc(size); - if (!get_iv(this, chunk->len, chunk->ptr)) + if (!get_iv(this, seq, chunk->len, chunk->ptr)) { chunk_free(chunk); return FALSE; -- cgit v1.2.3