crypto: add chacha20-poly1305 support to ipsecmb
Type: feature This patch adds chacha20-poly1305 single and chained algorithm support to ipsecmb crypto engine. Signed-off-by: DariuszX Kazimierski <dariuszx.kazimierski@intel.com> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com> Change-Id: If04ee0c8f985b07fd31dad1ce29000ec6f1733c5
This commit is contained in:
@@ -426,6 +426,243 @@ ipsecmb_ops_gcm_cipher_dec_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], \
|
||||
foreach_ipsecmb_gcm_cipher_op;
|
||||
#undef _
|
||||
|
||||
always_inline void
|
||||
ipsecmb_retire_aead_job (JOB_AES_HMAC *job, u32 *n_fail)
|
||||
{
|
||||
vnet_crypto_op_t *op = job->user_data;
|
||||
u32 len = op->tag_len;
|
||||
|
||||
if (PREDICT_FALSE (STS_COMPLETED != job->status))
|
||||
{
|
||||
op->status = ipsecmb_status_job (job->status);
|
||||
*n_fail = *n_fail + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (op->flags & VNET_CRYPTO_OP_FLAG_HMAC_CHECK)
|
||||
{
|
||||
if (memcmp (op->tag, job->auth_tag_output, len))
|
||||
{
|
||||
*n_fail = *n_fail + 1;
|
||||
op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
clib_memcpy_fast (op->tag, job->auth_tag_output, len);
|
||||
|
||||
op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
|
||||
}
|
||||
|
||||
static_always_inline u32
|
||||
ipsecmb_ops_chacha_poly (vlib_main_t *vm, vnet_crypto_op_t *ops[], u32 n_ops,
|
||||
IMB_CIPHER_DIRECTION dir)
|
||||
{
|
||||
ipsecmb_main_t *imbm = &ipsecmb_main;
|
||||
ipsecmb_per_thread_data_t *ptd =
|
||||
vec_elt_at_index (imbm->per_thread_data, vm->thread_index);
|
||||
struct IMB_JOB *job;
|
||||
MB_MGR *m = ptd->mgr;
|
||||
u32 i, n_fail = 0, last_key_index = ~0;
|
||||
u8 scratch[VLIB_FRAME_SIZE][16];
|
||||
u8 iv_data[16];
|
||||
u8 *key = 0;
|
||||
|
||||
for (i = 0; i < n_ops; i++)
|
||||
{
|
||||
vnet_crypto_op_t *op = ops[i];
|
||||
__m128i iv;
|
||||
|
||||
job = IMB_GET_NEXT_JOB (m);
|
||||
if (last_key_index != op->key_index)
|
||||
{
|
||||
vnet_crypto_key_t *kd = vnet_crypto_get_key (op->key_index);
|
||||
|
||||
key = kd->data;
|
||||
last_key_index = op->key_index;
|
||||
}
|
||||
|
||||
job->cipher_direction = dir;
|
||||
job->chain_order = IMB_ORDER_HASH_CIPHER;
|
||||
job->cipher_mode = IMB_CIPHER_CHACHA20_POLY1305;
|
||||
job->hash_alg = IMB_AUTH_CHACHA20_POLY1305;
|
||||
job->enc_keys = job->dec_keys = key;
|
||||
job->key_len_in_bytes = 32;
|
||||
|
||||
job->u.CHACHA20_POLY1305.aad = op->aad;
|
||||
job->u.CHACHA20_POLY1305.aad_len_in_bytes = op->aad_len;
|
||||
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 =
|
||||
op->len;
|
||||
job->cipher_start_src_offset_in_bytes =
|
||||
job->hash_start_src_offset_in_bytes = 0;
|
||||
|
||||
job->auth_tag_output = scratch[i];
|
||||
job->auth_tag_output_len_in_bytes = 16;
|
||||
|
||||
job->user_data = op;
|
||||
|
||||
job = IMB_SUBMIT_JOB_NOCHECK (ptd->mgr);
|
||||
if (job)
|
||||
ipsecmb_retire_aead_job (job, &n_fail);
|
||||
|
||||
op++;
|
||||
}
|
||||
|
||||
while ((job = IMB_FLUSH_JOB (ptd->mgr)))
|
||||
ipsecmb_retire_aead_job (job, &n_fail);
|
||||
|
||||
return n_ops - n_fail;
|
||||
}
|
||||
|
||||
static_always_inline u32
|
||||
ipsecmb_ops_chacha_poly_enc (vlib_main_t *vm, vnet_crypto_op_t *ops[],
|
||||
u32 n_ops)
|
||||
{
|
||||
return ipsecmb_ops_chacha_poly (vm, ops, n_ops, IMB_DIR_ENCRYPT);
|
||||
}
|
||||
|
||||
static_always_inline u32
|
||||
ipsecmb_ops_chacha_poly_dec (vlib_main_t *vm, vnet_crypto_op_t *ops[],
|
||||
u32 n_ops)
|
||||
{
|
||||
return ipsecmb_ops_chacha_poly (vm, ops, n_ops, IMB_DIR_DECRYPT);
|
||||
}
|
||||
|
||||
static_always_inline u32
|
||||
ipsecmb_ops_chacha_poly_chained (vlib_main_t *vm, vnet_crypto_op_t *ops[],
|
||||
vnet_crypto_op_chunk_t *chunks, u32 n_ops,
|
||||
IMB_CIPHER_DIRECTION dir)
|
||||
{
|
||||
ipsecmb_main_t *imbm = &ipsecmb_main;
|
||||
ipsecmb_per_thread_data_t *ptd =
|
||||
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 iv_data[16];
|
||||
u8 *key = 0;
|
||||
|
||||
if (dir == IMB_DIR_ENCRYPT)
|
||||
{
|
||||
for (i = 0; i < n_ops; i++)
|
||||
{
|
||||
vnet_crypto_op_t *op = ops[i];
|
||||
struct chacha20_poly1305_context_data ctx;
|
||||
vnet_crypto_op_chunk_t *chp;
|
||||
__m128i iv;
|
||||
u32 j;
|
||||
|
||||
ASSERT (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS);
|
||||
|
||||
if (last_key_index != op->key_index)
|
||||
{
|
||||
vnet_crypto_key_t *kd = vnet_crypto_get_key (op->key_index);
|
||||
|
||||
key = kd->data;
|
||||
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);
|
||||
|
||||
chp = chunks + op->chunk_index;
|
||||
for (j = 0; j < op->n_chunks; j++)
|
||||
{
|
||||
IMB_CHACHA20_POLY1305_ENC_UPDATE (m, key, &ctx, chp->dst,
|
||||
chp->src, chp->len);
|
||||
chp += 1;
|
||||
}
|
||||
|
||||
IMB_CHACHA20_POLY1305_ENC_FINALIZE (m, &ctx, op->tag, op->tag_len);
|
||||
|
||||
op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
|
||||
}
|
||||
}
|
||||
else /* dir == IMB_DIR_DECRYPT */
|
||||
{
|
||||
for (i = 0; i < n_ops; i++)
|
||||
{
|
||||
vnet_crypto_op_t *op = ops[i];
|
||||
struct chacha20_poly1305_context_data ctx;
|
||||
vnet_crypto_op_chunk_t *chp;
|
||||
u8 scratch[16];
|
||||
u32 j;
|
||||
|
||||
ASSERT (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS);
|
||||
|
||||
if (last_key_index != op->key_index)
|
||||
{
|
||||
vnet_crypto_key_t *kd = vnet_crypto_get_key (op->key_index);
|
||||
|
||||
key = kd->data;
|
||||
last_key_index = op->key_index;
|
||||
}
|
||||
|
||||
IMB_CHACHA20_POLY1305_INIT (m, key, &ctx, op->iv, op->aad,
|
||||
op->aad_len);
|
||||
|
||||
chp = chunks + op->chunk_index;
|
||||
for (j = 0; j < op->n_chunks; j++)
|
||||
{
|
||||
IMB_CHACHA20_POLY1305_DEC_UPDATE (m, key, &ctx, chp->dst,
|
||||
chp->src, chp->len);
|
||||
chp += 1;
|
||||
}
|
||||
|
||||
IMB_CHACHA20_POLY1305_DEC_FINALIZE (m, &ctx, scratch, op->tag_len);
|
||||
|
||||
if (memcmp (op->tag, scratch, op->tag_len))
|
||||
{
|
||||
n_fail = n_fail + 1;
|
||||
op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
|
||||
}
|
||||
else
|
||||
op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
|
||||
}
|
||||
}
|
||||
|
||||
return n_ops - n_fail;
|
||||
}
|
||||
|
||||
static_always_inline u32
|
||||
ipsec_mb_ops_chacha_poly_enc_chained (vlib_main_t *vm, vnet_crypto_op_t *ops[],
|
||||
vnet_crypto_op_chunk_t *chunks,
|
||||
u32 n_ops)
|
||||
{
|
||||
return ipsecmb_ops_chacha_poly_chained (vm, ops, chunks, n_ops,
|
||||
IMB_DIR_ENCRYPT);
|
||||
}
|
||||
|
||||
static_always_inline u32
|
||||
ipsec_mb_ops_chacha_poly_dec_chained (vlib_main_t *vm, vnet_crypto_op_t *ops[],
|
||||
vnet_crypto_op_chunk_t *chunks,
|
||||
u32 n_ops)
|
||||
{
|
||||
return ipsecmb_ops_chacha_poly_chained (vm, ops, chunks, n_ops,
|
||||
IMB_DIR_DECRYPT);
|
||||
}
|
||||
|
||||
clib_error_t *
|
||||
crypto_ipsecmb_iv_init (ipsecmb_main_t * imbm)
|
||||
{
|
||||
@@ -613,6 +850,21 @@ crypto_ipsecmb_init (vlib_main_t * vm)
|
||||
foreach_ipsecmb_gcm_cipher_op;
|
||||
#undef _
|
||||
|
||||
vnet_crypto_register_ops_handler (vm, eidx,
|
||||
VNET_CRYPTO_OP_CHACHA20_POLY1305_ENC,
|
||||
ipsecmb_ops_chacha_poly_enc);
|
||||
vnet_crypto_register_ops_handler (vm, eidx,
|
||||
VNET_CRYPTO_OP_CHACHA20_POLY1305_DEC,
|
||||
ipsecmb_ops_chacha_poly_dec);
|
||||
vnet_crypto_register_chained_ops_handler (
|
||||
vm, eidx, VNET_CRYPTO_OP_CHACHA20_POLY1305_ENC,
|
||||
ipsec_mb_ops_chacha_poly_enc_chained);
|
||||
vnet_crypto_register_chained_ops_handler (
|
||||
vm, eidx, VNET_CRYPTO_OP_CHACHA20_POLY1305_DEC,
|
||||
ipsec_mb_ops_chacha_poly_dec_chained);
|
||||
ad = imbm->alg_data + VNET_CRYPTO_ALG_CHACHA20_POLY1305;
|
||||
ad->data_size = 0;
|
||||
|
||||
vnet_crypto_register_key_handler (vm, eidx, crypto_ipsecmb_key_handler);
|
||||
return (NULL);
|
||||
}
|
||||
|
Reference in New Issue
Block a user