IV requirements vary wildly with the selected mode of operation. For
example, for AES-CBC the IV must be unpredictable whereas for AES
counter mode (CTR or GCM), it can be predictable but reusing an IV with
the same key material is catastrophic.
Because of that, it is hard to generate IV in a generic way, and it is
better left to the crypto user (eg. IPsec).
Type: improvement
Change-Id: I32689c591d8c6572b8d37c4d24f175ea6132d3ec
Signed-off-by: Benoît Ganne <bganne@cisco.com>
typedef struct
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
typedef struct
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
MB_MGR *mgr;
#if IMB_VERSION_NUM >= IMB_VERSION(1, 3, 0)
JOB_AES_HMAC burst_jobs[IMB_MAX_BURST_SIZE];
MB_MGR *mgr;
#if IMB_VERSION_NUM >= IMB_VERSION(1, 3, 0)
JOB_AES_HMAC burst_jobs[IMB_MAX_BURST_SIZE];
job->hash_alg = NULL_HASH;
job->hash_alg = NULL_HASH;
- if ((direction == ENCRYPT) &&
- (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV))
- {
- const __m128i iv = ptd->cbc_iv;
- _mm_storeu_si128 ((__m128i *) op->iv, iv);
- ptd->cbc_iv = _mm_aesenc_si128 (iv, iv);
- }
-
job->aes_enc_key_expanded = kd->enc_key_exp;
job->aes_dec_key_expanded = kd->dec_key_exp;
job->iv = op->iv;
job->aes_enc_key_expanded = kd->enc_key_exp;
job->aes_dec_key_expanded = kd->dec_key_exp;
job->iv = op->iv;
ipsecmb_aes_key_data_t *kd;
vnet_crypto_op_t *op = ops[i];
kd = (ipsecmb_aes_key_data_t *) imbm->key_data[op->key_index];
ipsecmb_aes_key_data_t *kd;
vnet_crypto_op_t *op = ops[i];
kd = (ipsecmb_aes_key_data_t *) imbm->key_data[op->key_index];
job = IMB_GET_NEXT_JOB (ptd->mgr);
job = IMB_GET_NEXT_JOB (ptd->mgr);
job->cipher_direction = direction;
job->chain_order = (direction == ENCRYPT ? CIPHER_HASH : HASH_CIPHER);
job->cipher_direction = direction;
job->chain_order = (direction == ENCRYPT ? CIPHER_HASH : HASH_CIPHER);
- if ((direction == ENCRYPT) && (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV))
- {
- iv = ptd->cbc_iv;
- _mm_storeu_si128 ((__m128i *) op->iv, iv);
- ptd->cbc_iv = _mm_aesenc_si128 (iv, iv);
- }
-
job->aes_key_len_in_bytes = key_len / 8;
job->aes_enc_key_expanded = kd->enc_key_exp;
job->aes_dec_key_expanded = kd->dec_key_exp;
job->aes_key_len_in_bytes = key_len / 8;
job->aes_enc_key_expanded = kd->enc_key_exp;
job->aes_dec_key_expanded = kd->dec_key_exp;
MB_MGR *m = ptd->mgr;
u32 i, n_fail = 0, last_key_index = ~0;
u8 scratch[VLIB_FRAME_SIZE][16];
MB_MGR *m = ptd->mgr;
u32 i, n_fail = 0, last_key_index = ~0;
u8 scratch[VLIB_FRAME_SIZE][16];
u8 *key = 0;
for (i = 0; i < n_ops; i++)
{
vnet_crypto_op_t *op = ops[i];
u8 *key = 0;
for (i = 0; i < n_ops; i++)
{
vnet_crypto_op_t *op = ops[i];
job = IMB_GET_NEXT_JOB (m);
if (last_key_index != op->key_index)
job = IMB_GET_NEXT_JOB (m);
if (last_key_index != op->key_index)
job->src = op->src;
job->dst = op->dst;
job->src = op->src;
job->dst = op->dst;
- if ((dir == IMB_DIR_ENCRYPT) &&
- (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV))
- {
- iv = ptd->cbc_iv;
- _mm_storeu_si128 ((__m128i *) iv_data, iv);
- clib_memcpy_fast (op->iv, iv_data, 12);
- ptd->cbc_iv = _mm_aesenc_si128 (iv, iv);
- }
-
job->iv = op->iv;
job->iv_len_in_bytes = 12;
job->msg_len_to_cipher_in_bytes = job->msg_len_to_hash_in_bytes =
job->iv = op->iv;
job->iv_len_in_bytes = 12;
job->msg_len_to_cipher_in_bytes = job->msg_len_to_hash_in_bytes =
vec_elt_at_index (imbm->per_thread_data, vm->thread_index);
MB_MGR *m = ptd->mgr;
u32 i, n_fail = 0, last_key_index = ~0;
vec_elt_at_index (imbm->per_thread_data, vm->thread_index);
MB_MGR *m = ptd->mgr;
u32 i, n_fail = 0, last_key_index = ~0;
u8 *key = 0;
if (dir == IMB_DIR_ENCRYPT)
u8 *key = 0;
if (dir == IMB_DIR_ENCRYPT)
vnet_crypto_op_t *op = ops[i];
struct chacha20_poly1305_context_data ctx;
vnet_crypto_op_chunk_t *chp;
vnet_crypto_op_t *op = ops[i];
struct chacha20_poly1305_context_data ctx;
vnet_crypto_op_chunk_t *chp;
u32 j;
ASSERT (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS);
u32 j;
ASSERT (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS);
last_key_index = op->key_index;
}
last_key_index = op->key_index;
}
- if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
- {
- iv = ptd->cbc_iv;
- _mm_storeu_si128 ((__m128i *) iv_data, iv);
- clib_memcpy_fast (op->iv, iv_data, 12);
- ptd->cbc_iv = _mm_aesenc_si128 (iv, iv);
- }
-
IMB_CHACHA20_POLY1305_INIT (m, key, &ctx, op->iv, op->aad,
op->aad_len);
IMB_CHACHA20_POLY1305_INIT (m, key, &ctx, op->iv, op->aad,
op->aad_len);
-clib_error_t *
-crypto_ipsecmb_iv_init (ipsecmb_main_t * imbm)
-{
- ipsecmb_per_thread_data_t *ptd;
- clib_error_t *err = 0;
- int fd;
-
- if ((fd = open ("/dev/urandom", O_RDONLY)) < 0)
- return clib_error_return_unix (0, "failed to open '/dev/urandom'");
-
- vec_foreach (ptd, imbm->per_thread_data)
- {
- if (read (fd, &ptd->cbc_iv, sizeof (ptd->cbc_iv)) != sizeof (ptd->cbc_iv))
- {
- err = clib_error_return_unix (0, "'/dev/urandom' read failure");
- close (fd);
- return (err);
- }
- }
-
- close (fd);
- return (NULL);
-}
-
static void
crypto_ipsecmb_key_handler (vlib_main_t * vm, vnet_crypto_key_op_t kop,
vnet_crypto_key_index_t idx)
static void
crypto_ipsecmb_key_handler (vlib_main_t * vm, vnet_crypto_key_op_t kop,
vnet_crypto_key_index_t idx)
ipsecmb_alg_data_t *ad;
ipsecmb_per_thread_data_t *ptd;
vlib_thread_main_t *tm = vlib_get_thread_main ();
ipsecmb_alg_data_t *ad;
ipsecmb_per_thread_data_t *ptd;
vlib_thread_main_t *tm = vlib_get_thread_main ();
MB_MGR *m = 0;
u32 eidx;
u8 *name;
MB_MGR *m = 0;
u32 eidx;
u8 *name;
- if (clib_cpu_supports_x86_aes () && (error = crypto_ipsecmb_iv_init (imbm)))
- return (error);
-
#define _(a, b, c, d, e, f) \
vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \
ipsecmb_ops_hmac_##a); \
#define _(a, b, c, d, e, f) \
vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \
ipsecmb_ops_hmac_##a); \
u32 n_ops, aes_key_size_t ks)
{
crypto_native_main_t *cm = &crypto_native_main;
u32 n_ops, aes_key_size_t ks)
{
crypto_native_main_t *cm = &crypto_native_main;
- crypto_native_per_thread_data_t *ptd =
- vec_elt_at_index (cm->per_thread_data, vm->thread_index);
int rounds = AES_KEY_ROUNDS (ks);
u8 placeholder[8192];
u32 i, j, count, n_left = n_ops;
int rounds = AES_KEY_ROUNDS (ks);
u8 placeholder[8192];
u32 i, j, count, n_left = n_ops;
- u8x16 t;
- if (ops[0]->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
- {
- t = ptd->cbc_iv[i];
- *(u8x16u *) ops[0]->iv = t;
- ptd->cbc_iv[i] = aes_enc_round (t, t);
- }
- else
- t = aes_block_load (ops[0]->iv);
+ u8x16 t = aes_block_load (ops[0]->iv);
#if __VAES__
rq[i] = t;
#else
#if __VAES__
rq[i] = t;
#else
#endif
{
crypto_native_main_t *cm = &crypto_native_main;
#endif
{
crypto_native_main_t *cm = &crypto_native_main;
- crypto_native_per_thread_data_t *ptd;
- clib_error_t *err = 0;
- int fd;
-
- if ((fd = open ("/dev/urandom", O_RDONLY)) < 0)
- return clib_error_return_unix (0, "failed to open '/dev/urandom'");
-
- /* *INDENT-OFF* */
- vec_foreach (ptd, cm->per_thread_data)
- {
- for (int i = 0; i < 4; i++)
- {
- if (read(fd, ptd->cbc_iv, sizeof (ptd->cbc_iv)) !=
- sizeof (ptd->cbc_iv))
- {
- err = clib_error_return_unix (0, "'/dev/urandom' read failure");
- goto error;
- }
- }
- }
- /* *INDENT-ON* */
#define _(x) \
vnet_crypto_register_ops_handler (vm, cm->crypto_engine_index, \
#define _(x) \
vnet_crypto_register_ops_handler (vm, cm->crypto_engine_index, \
foreach_aes_cbc_handler_type;
#undef _
foreach_aes_cbc_handler_type;
#undef _
-error:
- close (fd);
- return err;
typedef void *(crypto_native_key_fn_t) (vnet_crypto_key_t * key);
typedef void *(crypto_native_key_fn_t) (vnet_crypto_key_t * key);
-typedef struct
-{
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- u8x16 cbc_iv[16];
-} crypto_native_per_thread_data_t;
-
typedef struct
{
u32 crypto_engine_index;
typedef struct
{
u32 crypto_engine_index;
- crypto_native_per_thread_data_t *per_thread_data;
crypto_native_key_fn_t *key_fn[VNET_CRYPTO_N_ALGS];
void **key_data;
} crypto_native_main_t;
crypto_native_key_fn_t *key_fn[VNET_CRYPTO_N_ALGS];
void **key_data;
} crypto_native_main_t;
crypto_native_init (vlib_main_t * vm)
{
crypto_native_main_t *cm = &crypto_native_main;
crypto_native_init (vlib_main_t * vm)
{
crypto_native_main_t *cm = &crypto_native_main;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
clib_error_t *error = 0;
if (clib_cpu_supports_x86_aes () == 0 &&
clib_cpu_supports_aarch64_aes () == 0)
return 0;
clib_error_t *error = 0;
if (clib_cpu_supports_x86_aes () == 0 &&
clib_cpu_supports_aarch64_aes () == 0)
return 0;
- vec_validate_aligned (cm->per_thread_data, tm->n_vlib_mains - 1,
- CLIB_CACHE_LINE_BYTES);
-
cm->crypto_engine_index =
vnet_crypto_register_engine (vm, "native", 100,
"Native ISA Optimized Crypto");
cm->crypto_engine_index =
vnet_crypto_register_engine (vm, "native", 100,
"Native ISA Optimized Crypto");
error = clib_error_return (0, "No AES CBC implemenation available");
if (error)
error = clib_error_return (0, "No AES CBC implemenation available");
if (error)
#if __x86_64__
if (clib_cpu_supports_pclmulqdq ())
#if __x86_64__
if (clib_cpu_supports_pclmulqdq ())
error = clib_error_return (0, "No AES GCM implemenation available");
if (error)
error = clib_error_return (0, "No AES GCM implemenation available");
if (error)
error = clib_error_return (0, "No AES GCM implemenation available");
if (error)
error = clib_error_return (0, "No AES GCM implemenation available");
if (error)
#endif
vnet_crypto_register_key_handler (vm, cm->crypto_engine_index,
crypto_native_key_handler);
#endif
vnet_crypto_register_key_handler (vm, cm->crypto_engine_index,
crypto_native_key_handler);
-
-
-error:
- if (error)
- vec_free (cm->per_thread_data);
-
- return error;
vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
int out_len = 0;
vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
int out_len = 0;
- if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
- RAND_bytes (op->iv, iv_len);
-
EVP_EncryptInit_ex (ctx, cipher, NULL, key->data, op->iv);
if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
EVP_EncryptInit_ex (ctx, cipher, NULL, key->data, op->iv);
if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
int len = 0;
vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
int len = 0;
- if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
- RAND_bytes (op->iv, 8);
-
EVP_EncryptInit_ex (ctx, cipher, 0, 0, 0);
if (is_gcm)
EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
EVP_EncryptInit_ex (ctx, cipher, 0, 0, 0);
if (is_gcm)
EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
integ_op->digest = fe->digest;
integ_op->digest_len = digest_len;
integ_op->key_index = key->index_integ;
integ_op->digest = fe->digest;
integ_op->digest_len = digest_len;
integ_op->key_index = key->index_integ;
- integ_op->flags = fe->flags & ~VNET_CRYPTO_OP_FLAG_INIT_IV;
+ integ_op->flags = fe->flags;
crypto_op->user_data = integ_op->user_data = index;
}
crypto_op->user_data = integ_op->user_data = index;
}
ad->op_by_type[VNET_CRYPTO_OP_TYPE_ENCRYPT]);
vnet_crypto_op_init (op2,
ad->op_by_type[VNET_CRYPTO_OP_TYPE_DECRYPT]);
ad->op_by_type[VNET_CRYPTO_OP_TYPE_ENCRYPT]);
vnet_crypto_op_init (op2,
ad->op_by_type[VNET_CRYPTO_OP_TYPE_DECRYPT]);
- op1->flags = VNET_CRYPTO_OP_FLAG_INIT_IV;
op1->src = op2->src = op1->dst = op2->dst = b->data;
op1->key_index = op2->key_index = key_index;
op1->iv = op2->iv = b->data - 64;
op1->src = op2->src = op1->dst = op2->dst = b->data;
op1->key_index = op2->key_index = key_index;
op1->iv = op2->iv = b->data - 64;
vnet_crypto_op_id_t op:16;
vnet_crypto_op_status_t status:8;
u8 flags;
vnet_crypto_op_id_t op:16;
vnet_crypto_op_status_t status:8;
u8 flags;
-#define VNET_CRYPTO_OP_FLAG_INIT_IV (1 << 0)
-#define VNET_CRYPTO_OP_FLAG_HMAC_CHECK (1 << 1)
-#define VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS (1 << 2)
+#define VNET_CRYPTO_OP_FLAG_HMAC_CHECK (1 << 0)
+#define VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS (1 << 1)