iv_gen: Provide external sequence number (IKE, ESP)

This prevents duplicate sequential IVs in case of a HA failover.
This commit is contained in:
Tobias Brunner 2013-08-05 15:41:45 +02:00
parent d74c254dfd
commit e8229ad558
7 changed files with 18 additions and 23 deletions

View 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;

View 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;

View 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.

View 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);

View 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));
/**

View 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)
{

View 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;