iv_gen: Provide external sequence number (IKE, ESP)
This prevents duplicate sequential IVs in case of a HA failover.
This commit is contained in:
parent
d74c254dfd
commit
e8229ad558
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue