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); } \ 265 static_always_inline u32 \ 266 ipsecmb_ops_gcm_cipher_enc_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], \ 269 ipsecmb_main_t *imbm = &ipsecmb_main; \ 270 ipsecmb_per_thread_data_t *ptd = vec_elt_at_index (imbm->per_thread_data, \ 272 MB_MGR *m = ptd->mgr; \ 275 for (i = 0; i < n_ops; i++) \ 277 struct gcm_key_data *kd; \ 278 struct gcm_context_data ctx; \ 279 vnet_crypto_op_t *op = ops[i]; \ 281 kd = (struct gcm_key_data *) imbm->key_data[op->key_index]; \ 282 IMB_AES##b##_GCM_ENC (m, kd, &ctx, op->dst, op->src, op->len, op->iv, \ 283 op->aad, op->aad_len, op->tag, op->tag_len); \ 285 op->status = VNET_CRYPTO_OP_STATUS_COMPLETED; \ 291 static_always_inline u32 \ 292 ipsecmb_ops_gcm_cipher_dec_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], \ 295 ipsecmb_main_t *imbm = &ipsecmb_main; \ 296 ipsecmb_per_thread_data_t *ptd = vec_elt_at_index (imbm->per_thread_data, \ 298 MB_MGR *m = ptd->mgr; \ 299 u32 i, n_failed = 0; \ 301 for (i = 0; i < n_ops; i++) \ 303 struct gcm_key_data *kd; \ 304 struct gcm_context_data ctx; \ 305 vnet_crypto_op_t *op = ops[i]; \ 308 kd = (struct gcm_key_data *) imbm->key_data[op->key_index]; \ 309 IMB_AES##b##_GCM_DEC (m, kd, &ctx, op->dst, op->src, op->len, op->iv, \ 310 op->aad, op->aad_len, scratch, op->tag_len); \ 312 if ((memcmp (op->tag, scratch, op->tag_len))) \ 314 op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC; \ 318 op->status = VNET_CRYPTO_OP_STATUS_COMPLETED; \ 321 return n_ops - n_failed; \ 334 if ((fd = open (
"/dev/urandom", O_RDONLY)) < 0)
406 u64 pad[block_qw], key_hash[block_qw];
414 for (i = 0; i < block_qw; i++)
415 pad[i] = key_hash[i] ^ 0x3636363636363636;
418 for (i = 0; i < block_qw; i++)
419 pad[i] = key_hash[i] ^ 0x5c5c5c5c5c5c5c5c;
444 name =
format (0,
"Intel(R) Multi-Buffer Crypto for IPsec Library %s%c",
453 ptd->
mgr = alloc_mb_mgr (0);
454 if (clib_cpu_supports_avx512f ())
455 init_mb_mgr_avx512 (ptd->
mgr);
456 else if (clib_cpu_supports_avx2 ())
457 init_mb_mgr_avx2 (ptd->
mgr);
459 init_mb_mgr_sse (ptd->
mgr);
469 #define _(a, b, c, d, e, f) \ 470 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \ 471 ipsecmb_ops_hmac_##a); \ 472 ad = imbm->alg_data + VNET_CRYPTO_ALG_HMAC_##a; \ 473 ad->block_size = d; \ 474 ad->data_size = e * 2; \ 475 ad->hash_one_block = m-> c##_one_block; \ 476 ad->hash_fn = m-> c; \ 481 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_ENC, \ 482 ipsecmb_ops_cbc_cipher_enc_##a); \ 483 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_DEC, \ 484 ipsecmb_ops_cbc_cipher_dec_##a); \ 485 ad = imbm->alg_data + VNET_CRYPTO_ALG_##a; \ 486 ad->data_size = sizeof (ipsecmb_aes_cbc_key_data_t); \ 487 ad->keyexp = m->keyexp_##b; \ 492 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_ENC, \ 493 ipsecmb_ops_gcm_cipher_enc_##a); \ 494 vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_DEC, \ 495 ipsecmb_ops_gcm_cipher_dec_##a); \ 496 ad = imbm->alg_data + VNET_CRYPTO_ALG_##a; \ 497 ad->data_size = sizeof (struct gcm_key_data); \ 498 ad->aes_gcm_pre = m->gcm##b##_pre; \ 510 .runs_after =
VLIB_INITS (
"vnet_crypto_init"),
517 .version = VPP_BUILD_VER,
518 .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)
#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
#define foreach_ipsecmb_cbc_cipher_op
#define VNET_CRYPTO_OP_FLAG_INIT_IV
#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)
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 void clib_mem_free_s(void *p)
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)