Merge branch 'iv-gen'

Modularizes the generation of initialization vectors, which allows to use
different methods depending on the algorithms.  For instance for AES-GCM
sequential IVs are now used instead of the earlier random IVs, which are
still used for other algorithms e.g. AES-CBC.
This commit is contained in:
Tobias Brunner
2013-10-11 15:55:49 +02:00
19 changed files with 416 additions and 17 deletions
+1 -1
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;
@@ -309,10 +309,11 @@ 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;
iv_gen_t *iv_gen;
rng_t *rng;
size_t bs;
@@ -329,6 +330,13 @@ METHOD(encryption_payload_t, encrypt, status_t,
return NOT_SUPPORTED;
}
iv_gen = this->aead->get_iv_gen(this->aead);
if (!iv_gen)
{
DBG1(DBG_ENC, "encrypting encryption payload failed, no IV generator");
return NOT_SUPPORTED;
}
assoc = append_header(this, assoc);
generator = generator_create();
@@ -356,7 +364,7 @@ METHOD(encryption_payload_t, encrypt, status_t,
crypt = chunk_create(plain.ptr, plain.len + padding.len);
generator->destroy(generator);
if (!rng->get_bytes(rng, 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");
@@ -388,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.
+8
View File
@@ -196,6 +196,13 @@ METHOD(aead_t, get_iv_size, size_t,
return 0;
}
METHOD(aead_t, get_iv_gen, iv_gen_t*,
private_aead_t *this)
{
/* IVs are retrieved via keymat_v1.get_iv() */
return NULL;
}
METHOD(aead_t, get_key_size, size_t,
private_aead_t *this)
{
@@ -304,6 +311,7 @@ static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e)
.get_block_size = _get_block_size,
.get_icv_size = _get_icv_size,
.get_iv_size = _get_iv_size,
.get_iv_gen = _get_iv_gen,
.get_key_size = _get_key_size,
.set_key = _set_key,
.destroy = _aead_destroy,
+6 -8
View File
@@ -283,7 +283,7 @@ METHOD(esp_packet_t, encrypt, status_t,
u_int32_t next_seqno;
size_t blocksize, plainlen;
aead_t *aead;
rng_t *rng;
iv_gen_t *iv_gen;
this->packet->set_data(this->packet, chunk_empty);
@@ -293,13 +293,13 @@ METHOD(esp_packet_t, encrypt, status_t,
return FAILED;
}
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
if (!rng)
aead = esp_context->get_aead(esp_context);
iv_gen = aead->get_iv_gen(aead);
if (!iv_gen)
{
DBG1(DBG_ESP, "ESP encryption failed: could not find RNG");
DBG1(DBG_ESP, "ESP encryption failed: no IV generator");
return NOT_FOUND;
}
aead = esp_context->get_aead(esp_context);
blocksize = aead->get_block_size(aead);
iv.len = aead->get_iv_size(aead);
@@ -319,14 +319,12 @@ METHOD(esp_packet_t, encrypt, status_t,
writer->write_uint32(writer, next_seqno);
iv = writer->skip(writer, iv.len);
if (!rng->get_bytes(rng, 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);
rng->destroy(rng);
return FAILED;
}
rng->destroy(rng);
/* plain-/ciphertext will start here */
ciphertext = writer->get_buf(writer);
+1 -1
View File
@@ -91,7 +91,7 @@ struct esp_packet_t {
* @return - SUCCESS if encrypted
* - FAILED if sequence number cycled or any of the
* cryptographic functions failed
* - NOT_FOUND if no suitable RNG could be found
* - NOT_FOUND if no suitable IV generator provided
*/
status_t (*encrypt)(esp_packet_t *this, esp_context_t *esp_context,
u_int32_t spi);
+1
View File
@@ -13,6 +13,7 @@ crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
crypto/rngs/rng.c crypto/prf_plus.c crypto/signers/signer.c \
crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
credentials/credential_factory.c credentials/builder.c \
credentials/cred_encoding.c credentials/keys/private_key.c \
credentials/keys/public_key.c credentials/keys/shared_key.c \
+2 -1
View File
@@ -11,6 +11,7 @@ crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
crypto/rngs/rng.c crypto/prf_plus.c crypto/signers/signer.c \
crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
credentials/credential_factory.c credentials/builder.c \
credentials/cred_encoding.c credentials/keys/private_key.c \
credentials/keys/public_key.c credentials/keys/shared_key.c \
@@ -47,7 +48,7 @@ crypto/proposal/proposal_keywords.h crypto/proposal/proposal_keywords_static.h \
crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
crypto/prf_plus.h crypto/signers/signer.h crypto/signers/mac_signer.h \
crypto/crypto_factory.h crypto/crypto_tester.h crypto/diffie_hellman.h \
crypto/aead.h crypto/transform.h crypto/pkcs5.h \
crypto/aead.h crypto/transform.h crypto/pkcs5.h crypto/iv/iv_gen.h \
credentials/credential_factory.h credentials/builder.h \
credentials/cred_encoding.h credentials/keys/private_key.h \
credentials/keys/public_key.h credentials/keys/shared_key.h \
+19 -1
View File
@@ -1,4 +1,7 @@
/*
* Copyright (C) 2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@@ -16,6 +19,7 @@
#include "aead.h"
#include <utils/debug.h>
#include <crypto/iv/iv_gen_rand.h>
typedef struct private_aead_t private_aead_t;
@@ -35,9 +39,14 @@ struct private_aead_t {
crypter_t *crypter;
/**
* draditional signer
* traditional signer
*/
signer_t *signer;
/**
* IV generator
*/
iv_gen_t *iv_gen;
};
METHOD(aead_t, encrypt, bool,
@@ -126,6 +135,12 @@ METHOD(aead_t, get_iv_size, size_t,
return this->crypter->get_iv_size(this->crypter);
}
METHOD(aead_t, get_iv_gen, iv_gen_t*,
private_aead_t *this)
{
return this->iv_gen;
}
METHOD(aead_t, get_key_size, size_t,
private_aead_t *this)
{
@@ -148,6 +163,7 @@ METHOD(aead_t, set_key, bool,
METHOD(aead_t, destroy, void,
private_aead_t *this)
{
this->iv_gen->destroy(this->iv_gen);
this->crypter->destroy(this->crypter);
this->signer->destroy(this->signer);
free(this);
@@ -167,12 +183,14 @@ aead_t *aead_create(crypter_t *crypter, signer_t *signer)
.get_block_size = _get_block_size,
.get_icv_size = _get_icv_size,
.get_iv_size = _get_iv_size,
.get_iv_gen = _get_iv_gen,
.get_key_size = _get_key_size,
.set_key = _set_key,
.destroy = _destroy,
},
.crypter = crypter,
.signer = signer,
.iv_gen = iv_gen_rand_create(),
);
return &this->public;
+11
View File
@@ -1,4 +1,7 @@
/*
* Copyright (C) 2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@@ -26,6 +29,7 @@ typedef struct aead_t aead_t;
#include <library.h>
#include <crypto/crypters/crypter.h>
#include <crypto/signers/signer.h>
#include <crypto/iv/iv_gen.h>
/**
* Authenticated encryption / authentication decryption interface.
@@ -88,6 +92,13 @@ struct aead_t {
*/
size_t (*get_iv_size)(aead_t *this);
/**
* Get the IV generator implementation
*
* @return IV generator
*/
iv_gen_t *(*get_iv_gen)(aead_t *this);
/**
* Get the size of the key material (for encryption and authentication).
*
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup iv iv
* @{ @ingroup crypto
*/
#ifndef IV_GEN_H_
#define IV_GEN_H_
typedef struct iv_gen_t iv_gen_t;
#include <library.h>
/**
* Generic interface for initialization vector (IV) generators.
*/
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, 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, u_int64_t seq, size_t size,
chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Destroys an IV generator object.
*/
void (*destroy)(iv_gen_t *this);
};
#endif /** IV_GEN_H_ @}*/
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "iv_gen_rand.h"
#include <library.h>
typedef struct private_iv_gen_t private_iv_gen_t;
/**
* Private data of an iv_gen_t object.
*/
struct private_iv_gen_t {
/**
* Public iv_gen_t interface.
*/
iv_gen_t public;
/**
* rng_t object
*/
rng_t *rng;
};
METHOD(iv_gen_t, get_iv, bool,
private_iv_gen_t *this, u_int64_t seq, size_t size, u_int8_t *buffer)
{
if (!this->rng)
{
return FALSE;
}
return this->rng->get_bytes(this->rng, size, buffer);
}
METHOD(iv_gen_t, allocate_iv, bool,
private_iv_gen_t *this, u_int64_t seq, size_t size, chunk_t *chunk)
{
if (!this->rng)
{
return FALSE;
}
return this->rng->allocate_bytes(this->rng, size, chunk);
}
METHOD(iv_gen_t, destroy, void,
private_iv_gen_t *this)
{
DESTROY_IF(this->rng);
free(this);
}
iv_gen_t *iv_gen_rand_create()
{
private_iv_gen_t *this;
INIT(this,
.public = {
.get_iv = _get_iv,
.allocate_iv = _allocate_iv,
.destroy = _destroy,
},
.rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
);
return &this->public;
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @{ @ingroup iv
*/
#ifndef IV_GEN_RAND_H_
#define IV_GEN_RAND_H_
#include <crypto/iv/iv_gen.h>
/**
* Create an IV generator that generates random IVs.
*
* @return IV generator
*/
iv_gen_t *iv_gen_rand_create();
#endif /** IV_GEN_RAND_H_ @}*/
+102
View File
@@ -0,0 +1,102 @@
/*
* Copyright (C) 2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "iv_gen_seq.h"
typedef struct private_iv_gen_t private_iv_gen_t;
/**
* Private data of an iv_gen_t object.
*/
struct private_iv_gen_t {
/**
* Public iv_gen_t interface.
*/
iv_gen_t public;
/**
* Salt to mask counter
*/
u_int8_t *salt;
};
METHOD(iv_gen_t, get_iv, bool,
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->salt)
{
return FALSE;
}
if (len > sizeof(u_int64_t))
{
len = sizeof(u_int64_t);
memset(buffer, 0, size - len);
}
htoun64(iv, seq);
memxor(iv, this->salt, sizeof(u_int64_t));
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, u_int64_t seq, size_t size, chunk_t *chunk)
{
*chunk = chunk_alloc(size);
if (!get_iv(this, seq, chunk->len, chunk->ptr))
{
chunk_free(chunk);
return FALSE;
}
return TRUE;
}
METHOD(iv_gen_t, destroy, void,
private_iv_gen_t *this)
{
free(this->salt);
free(this);
}
iv_gen_t *iv_gen_seq_create()
{
private_iv_gen_t *this;
rng_t *rng;
INIT(this,
.public = {
.get_iv = _get_iv,
.allocate_iv = _allocate_iv,
.destroy = _destroy,
},
);
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
if (rng)
{
this->salt = malloc(sizeof(u_int64_t));
if (!rng->get_bytes(rng, sizeof(u_int64_t), this->salt))
{
free(this->salt);
this->salt = NULL;
}
rng->destroy(rng);
}
return &this->public;
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2013 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @{ @ingroup iv
*/
#ifndef IV_GEN_SEQ_H_
#define IV_GEN_SEQ_H_
#include <crypto/iv/iv_gen.h>
/**
* Create an IV generator that generates sequential IVs (counter).
*
* @return IV generator
*/
iv_gen_t *iv_gen_seq_create();
#endif /** IV_GEN_SEQ_H_ @}*/
+1 -1
View File
@@ -15,7 +15,7 @@
/**
* @defgroup mac_prf mac_prf
* @{ @ingroup crypto
* @{ @ingroup prf
*/
#ifndef MAC_PRF_H_
+16
View File
@@ -15,6 +15,8 @@
#include "ccm_aead.h"
#include <crypto/iv/iv_gen_seq.h>
#define BLOCK_SIZE 16
#define SALT_SIZE 3
#define IV_SIZE 8
@@ -38,6 +40,11 @@ struct private_ccm_aead_t {
*/
crypter_t *crypter;
/**
* IV generator.
*/
iv_gen_t *iv_gen;
/**
* Length of the integrity check value
*/
@@ -305,6 +312,12 @@ METHOD(aead_t, get_iv_size, size_t,
return IV_SIZE;
}
METHOD(aead_t, get_iv_gen, iv_gen_t*
private_ccm_aead_t *this)
{
return this->iv_gen;
}
METHOD(aead_t, get_key_size, size_t,
private_ccm_aead_t *this)
{
@@ -323,6 +336,7 @@ METHOD(aead_t, destroy, void,
private_ccm_aead_t *this)
{
this->crypter->destroy(this->crypter);
this->iv_gen->destroy(this->iv_gen);
free(this);
}
@@ -384,12 +398,14 @@ ccm_aead_t *ccm_aead_create(encryption_algorithm_t algo, size_t key_size)
.get_block_size = _get_block_size,
.get_icv_size = _get_icv_size,
.get_iv_size = _get_iv_size,
.get_iv_gen = _get_iv_gen,
.get_key_size = _get_key_size,
.set_key = _set_key,
.destroy = _destroy,
},
},
.crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size),
.iv_gen = iv_gen_seq_create(),
.icv_size = icv_size,
);
+15
View File
@@ -16,6 +16,7 @@
#include "gcm_aead.h"
#include <limits.h>
#include <crypto/iv/iv_gen_seq.h>
#define BLOCK_SIZE 16
#define NONCE_SIZE 12
@@ -39,6 +40,11 @@ struct private_gcm_aead_t {
*/
crypter_t *crypter;
/**
* IV generator.
*/
iv_gen_t *iv_gen;
/**
* Size of the integrity check value
*/
@@ -337,6 +343,12 @@ METHOD(aead_t, get_iv_size, size_t,
return IV_SIZE;
}
METHOD(aead_t, get_iv_gen, iv_gen_t*,
private_gcm_aead_t *this)
{
return this->iv_gen;
}
METHOD(aead_t, get_key_size, size_t,
private_gcm_aead_t *this)
{
@@ -356,6 +368,7 @@ METHOD(aead_t, destroy, void,
private_gcm_aead_t *this)
{
this->crypter->destroy(this->crypter);
this->iv_gen->destroy(this->iv_gen);
free(this);
}
@@ -405,12 +418,14 @@ gcm_aead_t *gcm_aead_create(encryption_algorithm_t algo, size_t key_size)
.get_block_size = _get_block_size,
.get_icv_size = _get_icv_size,
.get_iv_size = _get_iv_size,
.get_iv_gen = _get_iv_gen,
.get_key_size = _get_key_size,
.set_key = _set_key,
.destroy = _destroy,
},
},
.crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size),
.iv_gen = iv_gen_seq_create(),
.icv_size = icv_size,
);
@@ -20,6 +20,7 @@
#include "openssl_gcm.h"
#include <openssl/evp.h>
#include <crypto/iv/iv_gen_seq.h>
/** as defined in RFC 4106 */
#define IV_LEN 8
@@ -53,6 +54,11 @@ struct private_aead_t {
*/
size_t icv_size;
/**
* IV generator
*/
iv_gen_t *iv_gen;
/**
* The cipher to use
*/
@@ -161,6 +167,12 @@ METHOD(aead_t, get_iv_size, size_t,
return IV_LEN;
}
METHOD(aead_t, get_iv_gen, iv_gen_t*,
private_aead_t *this)
{
return this->iv_gen;
}
METHOD(aead_t, get_key_size, size_t,
private_aead_t *this)
{
@@ -183,6 +195,7 @@ METHOD(aead_t, destroy, void,
private_aead_t *this)
{
chunk_clear(&this->key);
this->iv_gen->destroy(this->iv_gen);
free(this);
}
@@ -200,6 +213,7 @@ aead_t *openssl_gcm_create(encryption_algorithm_t algo, size_t key_size)
.get_block_size = _get_block_size,
.get_icv_size = _get_icv_size,
.get_iv_size = _get_iv_size,
.get_iv_gen = _get_iv_gen,
.get_key_size = _get_key_size,
.set_key = _set_key,
.destroy = _destroy,
@@ -258,6 +272,7 @@ aead_t *openssl_gcm_create(encryption_algorithm_t algo, size_t key_size)
}
this->key = chunk_alloc(key_size);
this->iv_gen = iv_gen_seq_create();
return &this->public;
}