20 #include <intel-ipsec-mb.h> 24 #include <vpp/app/version.h> 28 #define HMAC_MAX_BLOCK_SIZE SHA_512_BLOCK_SIZE 29 #define EXPANDED_KEY_N_BYTES (16 * 15) 65 #define foreach_ipsecmb_hmac_op \ 66 _(SHA1, SHA1, sha1, 64, 20, 20) \ 67 _(SHA224, SHA_224, sha224, 64, 32, 28) \ 68 _(SHA256, SHA_256, sha256, 64, 32, 32) \ 69 _(SHA384, SHA_384, sha384, 128, 64, 48) \ 70 _(SHA512, SHA_512, sha512, 128, 64, 64) 75 #define foreach_ipsecmb_cbc_cipher_op \ 83 #define foreach_ipsecmb_gcm_cipher_op \ 94 if (STS_COMPLETED != job->status)
96 op->
status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
97 *n_fail = *n_fail + 1;
103 if ((memcmp (op->
digest, job->auth_tag_output, len)))
105 *n_fail = *n_fail + 1;
106 op->
status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
110 else if (len == digest_size)
115 op->
status = VNET_CRYPTO_OP_STATUS_COMPLETED;
120 u32 n_ops,
u32 block_size,
u32 hash_size,
121 u32 digest_size, JOB_HASH_ALG alg)
128 u8 scratch[n_ops][digest_size];
133 for (i = 0; i < n_ops; i++)
138 job = IMB_GET_NEXT_JOB (ptd->
mgr);
141 job->hash_start_src_offset_in_bytes = 0;
142 job->msg_len_to_hash_in_bytes = op->
len;
144 job->auth_tag_output_len_in_bytes = digest_size;
145 job->auth_tag_output = scratch[
i];
147 job->cipher_mode = NULL_CIPHER;
148 job->cipher_direction = DECRYPT;
149 job->chain_order = HASH_CIPHER;
151 job->u.HMAC._hashed_auth_key_xor_ipad = kd;
152 job->u.HMAC._hashed_auth_key_xor_opad = kd + hash_size;
155 job = IMB_SUBMIT_JOB (ptd->
mgr);
161 while ((job = IMB_FLUSH_JOB (ptd->
mgr)))
164 return n_ops - n_fail;
167 #define _(a, b, c, d, e, f) \ 168 static_always_inline u32 \ 169 ipsecmb_ops_hmac_##a (vlib_main_t * vm, \ 170 vnet_crypto_op_t * ops[], \ 172 { return ipsecmb_ops_hmac_inline (vm, ops, n_ops, d, e, f, b); } \ 182 if (STS_COMPLETED != job->status)
184 op->
status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
185 *n_fail = *n_fail + 1;
188 op->
status = VNET_CRYPTO_OP_STATUS_COMPLETED;
194 JOB_CIPHER_DIRECTION direction)
202 for (i = 0; i < n_ops; i++)
209 job = IMB_GET_NEXT_JOB (ptd->
mgr);
213 job->msg_len_to_cipher_in_bytes = op->
len;
214 job->cipher_start_src_offset_in_bytes = 0;
216 job->hash_alg = NULL_HASH;
217 job->cipher_mode = CBC;
218 job->cipher_direction = direction;
219 job->chain_order = (direction == ENCRYPT ? CIPHER_HASH : HASH_CIPHER);
224 _mm_storeu_si128 ((__m128i *) op->
iv,
iv);
228 job->aes_key_len_in_bytes = key_len / 8;
232 job->iv_len_in_bytes = AES_BLOCK_SIZE;
236 job = IMB_SUBMIT_JOB (ptd->
mgr);
242 while ((job = IMB_FLUSH_JOB (ptd->
mgr)))
245 return n_ops - n_fail;
249 static_always_inline u32 \ 250 ipsecmb_ops_cbc_cipher_enc_##a (vlib_main_t * vm, \ 251 vnet_crypto_op_t * ops[], \ 253 { return ipsecmb_ops_cbc_cipher_inline (vm, ops, n_ops, b, ENCRYPT); } \ 255 static_always_inline u32 \ 256 ipsecmb_ops_cbc_cipher_dec_##a (vlib_main_t * vm, \ 257 vnet_crypto_op_t * ops[], \ 259 { return ipsecmb_ops_cbc_cipher_inline (vm, ops, n_ops, b, DECRYPT); } \ 266 u32 * n_fail, JOB_CIPHER_DIRECTION direction)
270 if (STS_COMPLETED != job->status)
272 op->
status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
273 *n_fail = *n_fail + 1;
277 op->
status = VNET_CRYPTO_OP_STATUS_COMPLETED;
279 if (DECRYPT == direction)
281 if ((memcmp (op->
tag, job->auth_tag_output, op->
tag_len)))
283 *n_fail = *n_fail + 1;
284 op->
status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
292 JOB_CIPHER_DIRECTION direction)
299 u8 scratch[n_ops][64];
304 for (i = 0; i < n_ops; i++)
306 struct gcm_key_data *kd;
310 job = IMB_GET_NEXT_JOB (ptd->
mgr);
314 job->msg_len_to_cipher_in_bytes = op->
len;
315 job->cipher_start_src_offset_in_bytes = 0;
317 job->hash_alg = AES_GMAC;
318 job->cipher_mode = GCM;
319 job->cipher_direction = direction;
320 job->chain_order = (direction == ENCRYPT ? CIPHER_HASH : HASH_CIPHER);
323 job->aes_key_len_in_bytes = key_len / 8;
324 job->aes_enc_key_expanded = kd;
325 job->aes_dec_key_expanded = kd;
326 job->iv_len_in_bytes = 12;
328 job->u.GCM.aad = op->
aad;
329 job->u.GCM.aad_len_in_bytes = op->
aad_len;
330 job->auth_tag_output_len_in_bytes = op->
tag_len;
331 if (DECRYPT == direction)
332 job->auth_tag_output = scratch[
i];
334 job->auth_tag_output = op->
tag;
337 job = IMB_SUBMIT_JOB (ptd->
mgr);
343 while ((job = IMB_FLUSH_JOB (ptd->
mgr)))
346 return n_ops - n_fail;
350 static_always_inline u32 \ 351 ipsecmb_ops_gcm_cipher_enc_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], \ 353 { return ipsecmb_ops_gcm_cipher_inline (vm, ops, n_ops, b, ENCRYPT); } \ 355 static_always_inline u32 \ 356 ipsecmb_ops_gcm_cipher_dec_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], \ 358 { return ipsecmb_ops_gcm_cipher_inline (vm, ops, n_ops, b, DECRYPT); } \ 370 if ((fd = open (
"/dev/urandom", O_RDONLY)) < 0)
446 u64 pad[block_qw], key_hash[block_qw];
454 for (i = 0; i < block_qw; i++)
455 pad[i] = key_hash[i] ^ 0x3636363636363636;
458 for (i = 0; i < block_qw; i++)
459 pad[i] = key_hash[i] ^ 0x5c5c5c5c5c5c5c5c;
484 name =
format (0,
"Intel(R) Multi-Buffer Crypto for IPsec Library %s%c",
493 ptd->
mgr = alloc_mb_mgr (0);
494 if (clib_cpu_supports_avx512f ())
495 init_mb_mgr_avx512 (ptd->
mgr);
496 else if (clib_cpu_supports_avx2 ())
497 init_mb_mgr_avx2 (ptd->
mgr);
499 init_mb_mgr_sse (ptd->
mgr);
509 #define _(a, b, c, d, e, f) \ 510 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \ 511 ipsecmb_ops_hmac_##a); \ 512 ad = imbm->alg_data + VNET_CRYPTO_ALG_HMAC_##a; \ 513 ad->block_size = d; \ 514 ad->data_size = e * 2; \ 515 ad->hash_one_block = m-> c##_one_block; \ 516 ad->hash_fn = m-> c; \ 521 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_ENC, \ 522 ipsecmb_ops_cbc_cipher_enc_##a); \ 523 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_DEC, \ 524 ipsecmb_ops_cbc_cipher_dec_##a); \ 525 ad = imbm->alg_data + VNET_CRYPTO_ALG_##a; \ 526 ad->data_size = sizeof (ipsecmb_aes_cbc_key_data_t); \ 527 ad->keyexp = m->keyexp_##b; \ 532 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_ENC, \ 533 ipsecmb_ops_gcm_cipher_enc_##a); \ 534 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_DEC, \ 535 ipsecmb_ops_gcm_cipher_dec_##a); \ 536 ad = imbm->alg_data + VNET_CRYPTO_ALG_##a; \ 537 ad->data_size = sizeof (struct gcm_key_data); \ 538 ad->aes_gcm_pre = m->gcm##b##_pre; \ 550 .runs_after =
VLIB_INITS (
"vnet_crypto_init"),
557 .version = VPP_BUILD_VER,
558 .description =
"Intel IPSEC Multi-buffer Crypto Engine",
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
u8 pad[3]
log2 (size of the packing page block)
#define EXPANDED_KEY_N_BYTES
#define clib_memcpy_fast(a, b, c)
static void ipsecmb_retire_hmac_job(JOB_AES_HMAC *job, u32 *n_fail, u32 digest_size)
static void ipsecmb_retire_gcm_cipher_job(JOB_AES_HMAC *job, u32 *n_fail, JOB_CIPHER_DIRECTION direction)
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
#define foreach_ipsecmb_hmac_op
static ipsecmb_main_t ipsecmb_main
u8 dec_key_exp[EXPANDED_KEY_N_BYTES]
void vnet_crypto_register_key_handler(vlib_main_t *vm, u32 engine_index, vnet_crypto_key_handler_t *key_handler)
clib_error_t * crypto_ipsecmb_iv_init(ipsecmb_main_t *imbm)
#define static_always_inline
#define VLIB_INIT_FUNCTION(x)
struct ipsecmb_main_t_ ipsecmb_main_t
static clib_error_t * crypto_ipsecmb_init(vlib_main_t *vm)
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static void ipsecmb_retire_cipher_job(JOB_AES_HMAC *job, u32 *n_fail)
static_always_inline u32 ipsecmb_ops_hmac_inline(vlib_main_t *vm, vnet_crypto_op_t *ops[], u32 n_ops, u32 block_size, u32 hash_size, u32 digest_size, JOB_HASH_ALG alg)
ipsecmb_per_thread_data_t * per_thread_data
#define clib_error_return_unix(e, args...)
#define VNET_CRYPTO_OP_FLAG_HMAC_CHECK
static_always_inline u32 ipsecmb_ops_gcm_cipher_inline(vlib_main_t *vm, vnet_crypto_op_t *ops[], u32 n_ops, u32 key_len, JOB_CIPHER_DIRECTION direction)
#define foreach_ipsecmb_cbc_cipher_op
#define VNET_CRYPTO_OP_FLAG_INIT_IV
static uword clib_mem_size(void *p)
#define foreach_ipsecmb_gcm_cipher_op
static void crypto_ipsecmb_key_handler(vlib_main_t *vm, vnet_crypto_key_op_t kop, vnet_crypto_key_index_t idx)
static void clib_mem_free(void *p)
ipsecmb_alg_data_t alg_data[VNET_CRYPTO_N_ALGS]
u32 vnet_crypto_key_index_t
u8 enc_key_exp[EXPANDED_KEY_N_BYTES]
static_always_inline void clib_memset_u8(void *p, u8 val, uword count)
hash_one_block_t hash_one_block
static foreach_aarch64_flags int clib_cpu_supports_aes()
static_always_inline vnet_crypto_key_t * vnet_crypto_get_key(vnet_crypto_key_index_t index)
#define HMAC_MAX_BLOCK_SIZE
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
aes_gcm_pre_t aes_gcm_pre
vnet_crypto_op_status_t status
static void * clib_mem_alloc_aligned(uword size, uword align)
static_always_inline u32 ipsecmb_ops_cbc_cipher_inline(vlib_main_t *vm, vnet_crypto_op_t *ops[], u32 n_ops, u32 key_len, JOB_CIPHER_DIRECTION direction)
static vlib_thread_main_t * vlib_get_thread_main()
#define vec_foreach(var, vec)
Vector iterator.
#define CLIB_CACHE_LINE_BYTES
u32 vnet_crypto_register_engine(vlib_main_t *vm, char *name, int prio, char *desc)