iv_gen: Provide external sequence number (IKE, ESP)
authorTobias Brunner <tobias@strongswan.org>
Mon, 5 Aug 2013 13:41:45 +0000 (15:41 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 11 Oct 2013 13:55:40 +0000 (15:55 +0200)
This prevents duplicate sequential IVs in case of a HA failover.

src/libcharon/encoding/message.c
src/libcharon/encoding/payloads/encryption_payload.c
src/libcharon/encoding/payloads/encryption_payload.h
src/libipsec/esp_packet.c
src/libstrongswan/crypto/iv/iv_gen.h
src/libstrongswan/crypto/iv/iv_gen_rand.c
src/libstrongswan/crypto/iv/iv_gen_seq.c

index 9fc108b..11e735a 100644 (file)
@@ -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;
index 302c4a4..6a9f9c3 100644 (file)
@@ -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;
index 5c60693..f4fc7d6 100644 (file)
@@ -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.
index 1b8625c..db5ef36 100644 (file)
@@ -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);
index 641c1f1..f6bc647 100644 (file)
@@ -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));
 
        /**
index 3448ee0..2bed63f 100644 (file)
@@ -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)
        {
index d8a5a29..cbbc2dc 100644 (file)
@@ -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;