xref: /dpdk/drivers/crypto/ipsec_mb/pmd_aesni_mb.c (revision 665b49c51639a10c553433bc2bcd85c7331c631e)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2021 Intel Corporation
3  */
4 
5 #include "pmd_aesni_mb_priv.h"
6 
7 struct aesni_mb_op_buf_data {
8 	struct rte_mbuf *m;
9 	uint32_t offset;
10 };
11 
12 /**
13  * Calculate the authentication pre-computes
14  *
15  * @param one_block_hash	Function pointer
16  *				to calculate digest on ipad/opad
17  * @param ipad			Inner pad output byte array
18  * @param opad			Outer pad output byte array
19  * @param hkey			Authentication key
20  * @param hkey_len		Authentication key length
21  * @param blocksize		Block size of selected hash algo
22  */
23 static void
24 calculate_auth_precomputes(hash_one_block_t one_block_hash,
25 		uint8_t *ipad, uint8_t *opad,
26 		const uint8_t *hkey, uint16_t hkey_len,
27 		uint16_t blocksize)
28 {
29 	uint32_t i, length;
30 
31 	uint8_t ipad_buf[blocksize] __rte_aligned(16);
32 	uint8_t opad_buf[blocksize] __rte_aligned(16);
33 
34 	/* Setup inner and outer pads */
35 	memset(ipad_buf, HMAC_IPAD_VALUE, blocksize);
36 	memset(opad_buf, HMAC_OPAD_VALUE, blocksize);
37 
38 	/* XOR hash key with inner and outer pads */
39 	length = hkey_len > blocksize ? blocksize : hkey_len;
40 
41 	for (i = 0; i < length; i++) {
42 		ipad_buf[i] ^= hkey[i];
43 		opad_buf[i] ^= hkey[i];
44 	}
45 
46 	/* Compute partial hashes */
47 	(*one_block_hash)(ipad_buf, ipad);
48 	(*one_block_hash)(opad_buf, opad);
49 
50 	/* Clean up stack */
51 	memset(ipad_buf, 0, blocksize);
52 	memset(opad_buf, 0, blocksize);
53 }
54 
55 static inline int
56 is_aead_algo(IMB_HASH_ALG hash_alg, IMB_CIPHER_MODE cipher_mode)
57 {
58 	return (hash_alg == IMB_AUTH_CHACHA20_POLY1305 ||
59 		hash_alg == IMB_AUTH_AES_CCM ||
60 		(hash_alg == IMB_AUTH_AES_GMAC &&
61 		cipher_mode == IMB_CIPHER_GCM));
62 }
63 
64 /** Set session authentication parameters */
65 static int
66 aesni_mb_set_session_auth_parameters(const IMB_MGR *mb_mgr,
67 		struct aesni_mb_session *sess,
68 		const struct rte_crypto_sym_xform *xform)
69 {
70 	hash_one_block_t hash_oneblock_fn = NULL;
71 	unsigned int key_larger_block_size = 0;
72 	uint8_t hashed_key[HMAC_MAX_BLOCK_SIZE] = { 0 };
73 	uint32_t auth_precompute = 1;
74 
75 	if (xform == NULL) {
76 		sess->auth.algo = IMB_AUTH_NULL;
77 		return 0;
78 	}
79 
80 	if (xform->type != RTE_CRYPTO_SYM_XFORM_AUTH) {
81 		IPSEC_MB_LOG(ERR, "Crypto xform struct not of type auth");
82 		return -1;
83 	}
84 
85 	/* Set IV parameters */
86 	sess->auth_iv.offset = xform->auth.iv.offset;
87 	sess->auth_iv.length = xform->auth.iv.length;
88 
89 	/* Set the request digest size */
90 	sess->auth.req_digest_len = xform->auth.digest_length;
91 
92 	/* Select auth generate/verify */
93 	sess->auth.operation = xform->auth.op;
94 
95 	/* Set Authentication Parameters */
96 	if (xform->auth.algo == RTE_CRYPTO_AUTH_NULL) {
97 		sess->auth.algo = IMB_AUTH_NULL;
98 		sess->auth.gen_digest_len = 0;
99 		return 0;
100 	}
101 
102 	if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
103 		sess->auth.algo = IMB_AUTH_AES_XCBC;
104 
105 		uint16_t xcbc_mac_digest_len =
106 			get_truncated_digest_byte_length(IMB_AUTH_AES_XCBC);
107 		if (sess->auth.req_digest_len != xcbc_mac_digest_len) {
108 			IPSEC_MB_LOG(ERR, "Invalid digest size\n");
109 			return -EINVAL;
110 		}
111 		sess->auth.gen_digest_len = sess->auth.req_digest_len;
112 
113 		IMB_AES_XCBC_KEYEXP(mb_mgr, xform->auth.key.data,
114 				sess->auth.xcbc.k1_expanded,
115 				sess->auth.xcbc.k2, sess->auth.xcbc.k3);
116 		return 0;
117 	}
118 
119 	if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_CMAC) {
120 		uint32_t dust[4*15];
121 
122 		sess->auth.algo = IMB_AUTH_AES_CMAC;
123 
124 		uint16_t cmac_digest_len =
125 				get_digest_byte_length(IMB_AUTH_AES_CMAC);
126 
127 		if (sess->auth.req_digest_len > cmac_digest_len) {
128 			IPSEC_MB_LOG(ERR, "Invalid digest size\n");
129 			return -EINVAL;
130 		}
131 		/*
132 		 * Multi-buffer lib supports digest sizes from 4 to 16 bytes
133 		 * in version 0.50 and sizes of 12 and 16 bytes,
134 		 * in version 0.49.
135 		 * If size requested is different, generate the full digest
136 		 * (16 bytes) in a temporary location and then memcpy
137 		 * the requested number of bytes.
138 		 */
139 		if (sess->auth.req_digest_len < 4)
140 			sess->auth.gen_digest_len = cmac_digest_len;
141 		else
142 			sess->auth.gen_digest_len = sess->auth.req_digest_len;
143 
144 		IMB_AES_KEYEXP_128(mb_mgr, xform->auth.key.data,
145 				sess->auth.cmac.expkey, dust);
146 		IMB_AES_CMAC_SUBKEY_GEN_128(mb_mgr, sess->auth.cmac.expkey,
147 				sess->auth.cmac.skey1, sess->auth.cmac.skey2);
148 		return 0;
149 	}
150 
151 	if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
152 		if (xform->auth.op == RTE_CRYPTO_AUTH_OP_GENERATE) {
153 			sess->cipher.direction = IMB_DIR_ENCRYPT;
154 			sess->chain_order = IMB_ORDER_CIPHER_HASH;
155 		} else
156 			sess->cipher.direction = IMB_DIR_DECRYPT;
157 
158 		sess->auth.algo = IMB_AUTH_AES_GMAC;
159 		if (sess->auth.req_digest_len >
160 			get_digest_byte_length(IMB_AUTH_AES_GMAC)) {
161 			IPSEC_MB_LOG(ERR, "Invalid digest size\n");
162 			return -EINVAL;
163 		}
164 		sess->auth.gen_digest_len = sess->auth.req_digest_len;
165 		sess->iv.length = xform->auth.iv.length;
166 		sess->iv.offset = xform->auth.iv.offset;
167 
168 		switch (xform->auth.key.length) {
169 		case IMB_KEY_128_BYTES:
170 			IMB_AES128_GCM_PRE(mb_mgr, xform->auth.key.data,
171 				&sess->cipher.gcm_key);
172 			sess->cipher.key_length_in_bytes = IMB_KEY_128_BYTES;
173 			break;
174 		case IMB_KEY_192_BYTES:
175 			IMB_AES192_GCM_PRE(mb_mgr, xform->auth.key.data,
176 				&sess->cipher.gcm_key);
177 			sess->cipher.key_length_in_bytes = IMB_KEY_192_BYTES;
178 			break;
179 		case IMB_KEY_256_BYTES:
180 			IMB_AES256_GCM_PRE(mb_mgr, xform->auth.key.data,
181 				&sess->cipher.gcm_key);
182 			sess->cipher.key_length_in_bytes = IMB_KEY_256_BYTES;
183 			break;
184 		default:
185 			IPSEC_MB_LOG(ERR, "Invalid authentication key length\n");
186 			return -EINVAL;
187 		}
188 
189 		return 0;
190 	}
191 
192 	if (xform->auth.algo == RTE_CRYPTO_AUTH_ZUC_EIA3) {
193 		if (xform->auth.key.length == 16) {
194 			sess->auth.algo = IMB_AUTH_ZUC_EIA3_BITLEN;
195 
196 			if (sess->auth.req_digest_len != 4) {
197 				IPSEC_MB_LOG(ERR, "Invalid digest size\n");
198 				return -EINVAL;
199 			}
200 		} else if (xform->auth.key.length == 32) {
201 			sess->auth.algo = IMB_AUTH_ZUC256_EIA3_BITLEN;
202 #if IMB_VERSION(1, 2, 0) < IMB_VERSION_NUM
203 			if (sess->auth.req_digest_len != 4 &&
204 					sess->auth.req_digest_len != 8 &&
205 					sess->auth.req_digest_len != 16) {
206 #else
207 			if (sess->auth.req_digest_len != 4) {
208 #endif
209 				IPSEC_MB_LOG(ERR, "Invalid digest size\n");
210 				return -EINVAL;
211 			}
212 		} else {
213 			IPSEC_MB_LOG(ERR, "Invalid authentication key length\n");
214 			return -EINVAL;
215 		}
216 
217 		sess->auth.gen_digest_len = sess->auth.req_digest_len;
218 
219 		memcpy(sess->auth.zuc_auth_key, xform->auth.key.data,
220 			xform->auth.key.length);
221 		return 0;
222 	} else if (xform->auth.algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2) {
223 		sess->auth.algo = IMB_AUTH_SNOW3G_UIA2_BITLEN;
224 		uint16_t snow3g_uia2_digest_len =
225 			get_truncated_digest_byte_length(
226 						IMB_AUTH_SNOW3G_UIA2_BITLEN);
227 		if (sess->auth.req_digest_len != snow3g_uia2_digest_len) {
228 			IPSEC_MB_LOG(ERR, "Invalid digest size\n");
229 			return -EINVAL;
230 		}
231 		sess->auth.gen_digest_len = sess->auth.req_digest_len;
232 
233 		IMB_SNOW3G_INIT_KEY_SCHED(mb_mgr, xform->auth.key.data,
234 					&sess->auth.pKeySched_snow3g_auth);
235 		return 0;
236 	} else if (xform->auth.algo == RTE_CRYPTO_AUTH_KASUMI_F9) {
237 		sess->auth.algo = IMB_AUTH_KASUMI_UIA1;
238 		uint16_t kasumi_f9_digest_len =
239 			get_truncated_digest_byte_length(IMB_AUTH_KASUMI_UIA1);
240 		if (sess->auth.req_digest_len != kasumi_f9_digest_len) {
241 			IPSEC_MB_LOG(ERR, "Invalid digest size\n");
242 			return -EINVAL;
243 		}
244 		sess->auth.gen_digest_len = sess->auth.req_digest_len;
245 
246 		IMB_KASUMI_INIT_F9_KEY_SCHED(mb_mgr, xform->auth.key.data,
247 					&sess->auth.pKeySched_kasumi_auth);
248 		return 0;
249 	}
250 
251 	switch (xform->auth.algo) {
252 	case RTE_CRYPTO_AUTH_MD5_HMAC:
253 		sess->auth.algo = IMB_AUTH_MD5;
254 		hash_oneblock_fn = mb_mgr->md5_one_block;
255 		break;
256 	case RTE_CRYPTO_AUTH_SHA1_HMAC:
257 		sess->auth.algo = IMB_AUTH_HMAC_SHA_1;
258 		hash_oneblock_fn = mb_mgr->sha1_one_block;
259 		if (xform->auth.key.length > get_auth_algo_blocksize(
260 				IMB_AUTH_HMAC_SHA_1)) {
261 			IMB_SHA1(mb_mgr,
262 				xform->auth.key.data,
263 				xform->auth.key.length,
264 				hashed_key);
265 			key_larger_block_size = 1;
266 		}
267 		break;
268 	case RTE_CRYPTO_AUTH_SHA1:
269 		sess->auth.algo = IMB_AUTH_SHA_1;
270 		auth_precompute = 0;
271 		break;
272 	case RTE_CRYPTO_AUTH_SHA224_HMAC:
273 		sess->auth.algo = IMB_AUTH_HMAC_SHA_224;
274 		hash_oneblock_fn = mb_mgr->sha224_one_block;
275 		if (xform->auth.key.length > get_auth_algo_blocksize(
276 				IMB_AUTH_HMAC_SHA_224)) {
277 			IMB_SHA224(mb_mgr,
278 				xform->auth.key.data,
279 				xform->auth.key.length,
280 				hashed_key);
281 			key_larger_block_size = 1;
282 		}
283 		break;
284 	case RTE_CRYPTO_AUTH_SHA224:
285 		sess->auth.algo = IMB_AUTH_SHA_224;
286 		auth_precompute = 0;
287 		break;
288 	case RTE_CRYPTO_AUTH_SHA256_HMAC:
289 		sess->auth.algo = IMB_AUTH_HMAC_SHA_256;
290 		hash_oneblock_fn = mb_mgr->sha256_one_block;
291 		if (xform->auth.key.length > get_auth_algo_blocksize(
292 				IMB_AUTH_HMAC_SHA_256)) {
293 			IMB_SHA256(mb_mgr,
294 				xform->auth.key.data,
295 				xform->auth.key.length,
296 				hashed_key);
297 			key_larger_block_size = 1;
298 		}
299 		break;
300 	case RTE_CRYPTO_AUTH_SHA256:
301 		sess->auth.algo = IMB_AUTH_SHA_256;
302 		auth_precompute = 0;
303 		break;
304 	case RTE_CRYPTO_AUTH_SHA384_HMAC:
305 		sess->auth.algo = IMB_AUTH_HMAC_SHA_384;
306 		hash_oneblock_fn = mb_mgr->sha384_one_block;
307 		if (xform->auth.key.length > get_auth_algo_blocksize(
308 				IMB_AUTH_HMAC_SHA_384)) {
309 			IMB_SHA384(mb_mgr,
310 				xform->auth.key.data,
311 				xform->auth.key.length,
312 				hashed_key);
313 			key_larger_block_size = 1;
314 		}
315 		break;
316 	case RTE_CRYPTO_AUTH_SHA384:
317 		sess->auth.algo = IMB_AUTH_SHA_384;
318 		auth_precompute = 0;
319 		break;
320 	case RTE_CRYPTO_AUTH_SHA512_HMAC:
321 		sess->auth.algo = IMB_AUTH_HMAC_SHA_512;
322 		hash_oneblock_fn = mb_mgr->sha512_one_block;
323 		if (xform->auth.key.length > get_auth_algo_blocksize(
324 				IMB_AUTH_HMAC_SHA_512)) {
325 			IMB_SHA512(mb_mgr,
326 				xform->auth.key.data,
327 				xform->auth.key.length,
328 				hashed_key);
329 			key_larger_block_size = 1;
330 		}
331 		break;
332 	case RTE_CRYPTO_AUTH_SHA512:
333 		sess->auth.algo = IMB_AUTH_SHA_512;
334 		auth_precompute = 0;
335 		break;
336 	default:
337 		IPSEC_MB_LOG(ERR,
338 			"Unsupported authentication algorithm selection");
339 		return -ENOTSUP;
340 	}
341 	uint16_t trunc_digest_size =
342 			get_truncated_digest_byte_length(sess->auth.algo);
343 	uint16_t full_digest_size =
344 			get_digest_byte_length(sess->auth.algo);
345 
346 	if (sess->auth.req_digest_len > full_digest_size ||
347 			sess->auth.req_digest_len == 0) {
348 		IPSEC_MB_LOG(ERR, "Invalid digest size\n");
349 		return -EINVAL;
350 	}
351 
352 	if (sess->auth.req_digest_len != trunc_digest_size &&
353 			sess->auth.req_digest_len != full_digest_size)
354 		sess->auth.gen_digest_len = full_digest_size;
355 	else
356 		sess->auth.gen_digest_len = sess->auth.req_digest_len;
357 
358 	/* Plain SHA does not require precompute key */
359 	if (auth_precompute == 0)
360 		return 0;
361 
362 	/* Calculate Authentication precomputes */
363 	if (key_larger_block_size) {
364 		calculate_auth_precomputes(hash_oneblock_fn,
365 			sess->auth.pads.inner, sess->auth.pads.outer,
366 			hashed_key,
367 			xform->auth.key.length,
368 			get_auth_algo_blocksize(sess->auth.algo));
369 	} else {
370 		calculate_auth_precomputes(hash_oneblock_fn,
371 			sess->auth.pads.inner, sess->auth.pads.outer,
372 			xform->auth.key.data,
373 			xform->auth.key.length,
374 			get_auth_algo_blocksize(sess->auth.algo));
375 	}
376 
377 	return 0;
378 }
379 
380 /** Set session cipher parameters */
381 static int
382 aesni_mb_set_session_cipher_parameters(const IMB_MGR *mb_mgr,
383 		struct aesni_mb_session *sess,
384 		const struct rte_crypto_sym_xform *xform)
385 {
386 	uint8_t is_aes = 0;
387 	uint8_t is_3DES = 0;
388 	uint8_t is_docsis = 0;
389 	uint8_t is_zuc = 0;
390 	uint8_t is_snow3g = 0;
391 	uint8_t is_kasumi = 0;
392 
393 	if (xform == NULL) {
394 		sess->cipher.mode = IMB_CIPHER_NULL;
395 		return 0;
396 	}
397 
398 	if (xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER) {
399 		IPSEC_MB_LOG(ERR, "Crypto xform struct not of type cipher");
400 		return -EINVAL;
401 	}
402 
403 	/* Select cipher direction */
404 	switch (xform->cipher.op) {
405 	case RTE_CRYPTO_CIPHER_OP_ENCRYPT:
406 		sess->cipher.direction = IMB_DIR_ENCRYPT;
407 		break;
408 	case RTE_CRYPTO_CIPHER_OP_DECRYPT:
409 		sess->cipher.direction = IMB_DIR_DECRYPT;
410 		break;
411 	default:
412 		IPSEC_MB_LOG(ERR, "Invalid cipher operation parameter");
413 		return -EINVAL;
414 	}
415 
416 	/* Select cipher mode */
417 	switch (xform->cipher.algo) {
418 	case RTE_CRYPTO_CIPHER_AES_CBC:
419 		sess->cipher.mode = IMB_CIPHER_CBC;
420 		is_aes = 1;
421 		break;
422 	case RTE_CRYPTO_CIPHER_AES_CTR:
423 		sess->cipher.mode = IMB_CIPHER_CNTR;
424 		is_aes = 1;
425 		break;
426 	case RTE_CRYPTO_CIPHER_AES_DOCSISBPI:
427 		sess->cipher.mode = IMB_CIPHER_DOCSIS_SEC_BPI;
428 		is_docsis = 1;
429 		break;
430 	case RTE_CRYPTO_CIPHER_DES_CBC:
431 		sess->cipher.mode = IMB_CIPHER_DES;
432 		break;
433 	case RTE_CRYPTO_CIPHER_DES_DOCSISBPI:
434 		sess->cipher.mode = IMB_CIPHER_DOCSIS_DES;
435 		break;
436 	case RTE_CRYPTO_CIPHER_3DES_CBC:
437 		sess->cipher.mode = IMB_CIPHER_DES3;
438 		is_3DES = 1;
439 		break;
440 	case RTE_CRYPTO_CIPHER_AES_ECB:
441 		sess->cipher.mode = IMB_CIPHER_ECB;
442 		is_aes = 1;
443 		break;
444 	case RTE_CRYPTO_CIPHER_ZUC_EEA3:
445 		sess->cipher.mode = IMB_CIPHER_ZUC_EEA3;
446 		is_zuc = 1;
447 		break;
448 	case RTE_CRYPTO_CIPHER_SNOW3G_UEA2:
449 		sess->cipher.mode = IMB_CIPHER_SNOW3G_UEA2_BITLEN;
450 		is_snow3g = 1;
451 		break;
452 	case RTE_CRYPTO_CIPHER_KASUMI_F8:
453 		sess->cipher.mode = IMB_CIPHER_KASUMI_UEA1_BITLEN;
454 		is_kasumi = 1;
455 		break;
456 	case RTE_CRYPTO_CIPHER_NULL:
457 		sess->cipher.mode = IMB_CIPHER_NULL;
458 		sess->cipher.key_length_in_bytes = 0;
459 		sess->iv.offset = xform->cipher.iv.offset;
460 		sess->iv.length = xform->cipher.iv.length;
461 		return 0;
462 	default:
463 		IPSEC_MB_LOG(ERR, "Unsupported cipher mode parameter");
464 		return -ENOTSUP;
465 	}
466 
467 	/* Set IV parameters */
468 	sess->iv.offset = xform->cipher.iv.offset;
469 	sess->iv.length = xform->cipher.iv.length;
470 
471 	/* Check key length and choose key expansion function for AES */
472 	if (is_aes) {
473 		switch (xform->cipher.key.length) {
474 		case IMB_KEY_128_BYTES:
475 			sess->cipher.key_length_in_bytes = IMB_KEY_128_BYTES;
476 			IMB_AES_KEYEXP_128(mb_mgr, xform->cipher.key.data,
477 					sess->cipher.expanded_aes_keys.encode,
478 					sess->cipher.expanded_aes_keys.decode);
479 			break;
480 		case IMB_KEY_192_BYTES:
481 			sess->cipher.key_length_in_bytes = IMB_KEY_192_BYTES;
482 			IMB_AES_KEYEXP_192(mb_mgr, xform->cipher.key.data,
483 					sess->cipher.expanded_aes_keys.encode,
484 					sess->cipher.expanded_aes_keys.decode);
485 			break;
486 		case IMB_KEY_256_BYTES:
487 			sess->cipher.key_length_in_bytes = IMB_KEY_256_BYTES;
488 			IMB_AES_KEYEXP_256(mb_mgr, xform->cipher.key.data,
489 					sess->cipher.expanded_aes_keys.encode,
490 					sess->cipher.expanded_aes_keys.decode);
491 			break;
492 		default:
493 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
494 			return -EINVAL;
495 		}
496 	} else if (is_docsis) {
497 		switch (xform->cipher.key.length) {
498 		case IMB_KEY_128_BYTES:
499 			sess->cipher.key_length_in_bytes = IMB_KEY_128_BYTES;
500 			IMB_AES_KEYEXP_128(mb_mgr, xform->cipher.key.data,
501 					sess->cipher.expanded_aes_keys.encode,
502 					sess->cipher.expanded_aes_keys.decode);
503 			break;
504 		case IMB_KEY_256_BYTES:
505 			sess->cipher.key_length_in_bytes = IMB_KEY_256_BYTES;
506 			IMB_AES_KEYEXP_256(mb_mgr, xform->cipher.key.data,
507 					sess->cipher.expanded_aes_keys.encode,
508 					sess->cipher.expanded_aes_keys.decode);
509 			break;
510 		default:
511 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
512 			return -EINVAL;
513 		}
514 	} else if (is_3DES) {
515 		uint64_t *keys[3] = {sess->cipher.exp_3des_keys.key[0],
516 				sess->cipher.exp_3des_keys.key[1],
517 				sess->cipher.exp_3des_keys.key[2]};
518 
519 		switch (xform->cipher.key.length) {
520 		case  24:
521 			IMB_DES_KEYSCHED(mb_mgr, keys[0],
522 					xform->cipher.key.data);
523 			IMB_DES_KEYSCHED(mb_mgr, keys[1],
524 					xform->cipher.key.data + 8);
525 			IMB_DES_KEYSCHED(mb_mgr, keys[2],
526 					xform->cipher.key.data + 16);
527 
528 			/* Initialize keys - 24 bytes: [K1-K2-K3] */
529 			sess->cipher.exp_3des_keys.ks_ptr[0] = keys[0];
530 			sess->cipher.exp_3des_keys.ks_ptr[1] = keys[1];
531 			sess->cipher.exp_3des_keys.ks_ptr[2] = keys[2];
532 			break;
533 		case 16:
534 			IMB_DES_KEYSCHED(mb_mgr, keys[0],
535 					xform->cipher.key.data);
536 			IMB_DES_KEYSCHED(mb_mgr, keys[1],
537 					xform->cipher.key.data + 8);
538 			/* Initialize keys - 16 bytes: [K1=K1,K2=K2,K3=K1] */
539 			sess->cipher.exp_3des_keys.ks_ptr[0] = keys[0];
540 			sess->cipher.exp_3des_keys.ks_ptr[1] = keys[1];
541 			sess->cipher.exp_3des_keys.ks_ptr[2] = keys[0];
542 			break;
543 		case 8:
544 			IMB_DES_KEYSCHED(mb_mgr, keys[0],
545 					xform->cipher.key.data);
546 
547 			/* Initialize keys - 8 bytes: [K1 = K2 = K3] */
548 			sess->cipher.exp_3des_keys.ks_ptr[0] = keys[0];
549 			sess->cipher.exp_3des_keys.ks_ptr[1] = keys[0];
550 			sess->cipher.exp_3des_keys.ks_ptr[2] = keys[0];
551 			break;
552 		default:
553 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
554 			return -EINVAL;
555 		}
556 
557 		sess->cipher.key_length_in_bytes = 24;
558 	} else if (is_zuc) {
559 		if (xform->cipher.key.length != 16 &&
560 				xform->cipher.key.length != 32) {
561 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
562 			return -EINVAL;
563 		}
564 		sess->cipher.key_length_in_bytes = xform->cipher.key.length;
565 		memcpy(sess->cipher.zuc_cipher_key, xform->cipher.key.data,
566 			xform->cipher.key.length);
567 	} else if (is_snow3g) {
568 		if (xform->cipher.key.length != 16) {
569 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
570 			return -EINVAL;
571 		}
572 		sess->cipher.key_length_in_bytes = 16;
573 		IMB_SNOW3G_INIT_KEY_SCHED(mb_mgr, xform->cipher.key.data,
574 					&sess->cipher.pKeySched_snow3g_cipher);
575 	} else if (is_kasumi) {
576 		if (xform->cipher.key.length != 16) {
577 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
578 			return -EINVAL;
579 		}
580 		sess->cipher.key_length_in_bytes = 16;
581 		IMB_KASUMI_INIT_F8_KEY_SCHED(mb_mgr, xform->cipher.key.data,
582 					&sess->cipher.pKeySched_kasumi_cipher);
583 	} else {
584 		if (xform->cipher.key.length != 8) {
585 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
586 			return -EINVAL;
587 		}
588 		sess->cipher.key_length_in_bytes = 8;
589 
590 		IMB_DES_KEYSCHED(mb_mgr,
591 			(uint64_t *)sess->cipher.expanded_aes_keys.encode,
592 				xform->cipher.key.data);
593 		IMB_DES_KEYSCHED(mb_mgr,
594 			(uint64_t *)sess->cipher.expanded_aes_keys.decode,
595 				xform->cipher.key.data);
596 	}
597 
598 	return 0;
599 }
600 
601 static int
602 aesni_mb_set_session_aead_parameters(const IMB_MGR *mb_mgr,
603 		struct aesni_mb_session *sess,
604 		const struct rte_crypto_sym_xform *xform)
605 {
606 	switch (xform->aead.op) {
607 	case RTE_CRYPTO_AEAD_OP_ENCRYPT:
608 		sess->cipher.direction = IMB_DIR_ENCRYPT;
609 		sess->auth.operation = RTE_CRYPTO_AUTH_OP_GENERATE;
610 		break;
611 	case RTE_CRYPTO_AEAD_OP_DECRYPT:
612 		sess->cipher.direction = IMB_DIR_DECRYPT;
613 		sess->auth.operation = RTE_CRYPTO_AUTH_OP_VERIFY;
614 		break;
615 	default:
616 		IPSEC_MB_LOG(ERR, "Invalid aead operation parameter");
617 		return -EINVAL;
618 	}
619 
620 	/* Set IV parameters */
621 	sess->iv.offset = xform->aead.iv.offset;
622 	sess->iv.length = xform->aead.iv.length;
623 
624 	/* Set digest sizes */
625 	sess->auth.req_digest_len = xform->aead.digest_length;
626 	sess->auth.gen_digest_len = sess->auth.req_digest_len;
627 
628 	switch (xform->aead.algo) {
629 	case RTE_CRYPTO_AEAD_AES_CCM:
630 		sess->cipher.mode = IMB_CIPHER_CCM;
631 		sess->auth.algo = IMB_AUTH_AES_CCM;
632 
633 		/* Check key length and choose key expansion function for AES */
634 		switch (xform->aead.key.length) {
635 		case IMB_KEY_128_BYTES:
636 			sess->cipher.key_length_in_bytes = IMB_KEY_128_BYTES;
637 			IMB_AES_KEYEXP_128(mb_mgr, xform->aead.key.data,
638 					sess->cipher.expanded_aes_keys.encode,
639 					sess->cipher.expanded_aes_keys.decode);
640 			break;
641 		case IMB_KEY_256_BYTES:
642 			sess->cipher.key_length_in_bytes = IMB_KEY_256_BYTES;
643 			IMB_AES_KEYEXP_256(mb_mgr, xform->aead.key.data,
644 					sess->cipher.expanded_aes_keys.encode,
645 					sess->cipher.expanded_aes_keys.decode);
646 			break;
647 		default:
648 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
649 			return -EINVAL;
650 		}
651 
652 		/* CCM digests must be between 4 and 16 and an even number */
653 		if (sess->auth.req_digest_len < AES_CCM_DIGEST_MIN_LEN ||
654 			sess->auth.req_digest_len > AES_CCM_DIGEST_MAX_LEN ||
655 			(sess->auth.req_digest_len & 1) == 1) {
656 			IPSEC_MB_LOG(ERR, "Invalid digest size\n");
657 			return -EINVAL;
658 		}
659 		break;
660 
661 	case RTE_CRYPTO_AEAD_AES_GCM:
662 		sess->cipher.mode = IMB_CIPHER_GCM;
663 		sess->auth.algo = IMB_AUTH_AES_GMAC;
664 
665 		switch (xform->aead.key.length) {
666 		case IMB_KEY_128_BYTES:
667 			sess->cipher.key_length_in_bytes = IMB_KEY_128_BYTES;
668 			IMB_AES128_GCM_PRE(mb_mgr, xform->aead.key.data,
669 				&sess->cipher.gcm_key);
670 			break;
671 		case IMB_KEY_192_BYTES:
672 			sess->cipher.key_length_in_bytes = IMB_KEY_192_BYTES;
673 			IMB_AES192_GCM_PRE(mb_mgr, xform->aead.key.data,
674 				&sess->cipher.gcm_key);
675 			break;
676 		case IMB_KEY_256_BYTES:
677 			sess->cipher.key_length_in_bytes = IMB_KEY_256_BYTES;
678 			IMB_AES256_GCM_PRE(mb_mgr, xform->aead.key.data,
679 				&sess->cipher.gcm_key);
680 			break;
681 		default:
682 			IPSEC_MB_LOG(ERR, "Invalid cipher key length");
683 			return -EINVAL;
684 		}
685 
686 		/* GCM digest size must be between 1 and 16 */
687 		if (sess->auth.req_digest_len == 0 ||
688 				sess->auth.req_digest_len > 16) {
689 			IPSEC_MB_LOG(ERR, "Invalid digest size\n");
690 			return -EINVAL;
691 		}
692 		break;
693 
694 	case RTE_CRYPTO_AEAD_CHACHA20_POLY1305:
695 		sess->cipher.mode = IMB_CIPHER_CHACHA20_POLY1305;
696 		sess->auth.algo = IMB_AUTH_CHACHA20_POLY1305;
697 
698 		if (xform->aead.key.length != 32) {
699 			IPSEC_MB_LOG(ERR, "Invalid key length");
700 			return -EINVAL;
701 		}
702 		sess->cipher.key_length_in_bytes = 32;
703 		memcpy(sess->cipher.expanded_aes_keys.encode,
704 			xform->aead.key.data, 32);
705 		if (sess->auth.req_digest_len != 16) {
706 			IPSEC_MB_LOG(ERR, "Invalid digest size\n");
707 			return -EINVAL;
708 		}
709 		break;
710 	default:
711 		IPSEC_MB_LOG(ERR, "Unsupported aead mode parameter");
712 		return -ENOTSUP;
713 	}
714 
715 	return 0;
716 }
717 
718 /** Configure a aesni multi-buffer session from a crypto xform chain */
719 static int
720 aesni_mb_session_configure(IMB_MGR *mb_mgr,
721 		void *priv_sess,
722 		const struct rte_crypto_sym_xform *xform)
723 {
724 	const struct rte_crypto_sym_xform *auth_xform = NULL;
725 	const struct rte_crypto_sym_xform *cipher_xform = NULL;
726 	const struct rte_crypto_sym_xform *aead_xform = NULL;
727 	enum ipsec_mb_operation mode;
728 	struct aesni_mb_session *sess = (struct aesni_mb_session *) priv_sess;
729 	int ret;
730 
731 	ret = ipsec_mb_parse_xform(xform, &mode, &auth_xform,
732 				&cipher_xform, &aead_xform);
733 	if (ret)
734 		return ret;
735 
736 	/* Select Crypto operation - hash then cipher / cipher then hash */
737 	switch (mode) {
738 	case IPSEC_MB_OP_HASH_VERIFY_THEN_DECRYPT:
739 		sess->chain_order = IMB_ORDER_HASH_CIPHER;
740 		break;
741 	case IPSEC_MB_OP_ENCRYPT_THEN_HASH_GEN:
742 	case IPSEC_MB_OP_DECRYPT_THEN_HASH_VERIFY:
743 		sess->chain_order = IMB_ORDER_CIPHER_HASH;
744 		break;
745 	case IPSEC_MB_OP_HASH_GEN_ONLY:
746 	case IPSEC_MB_OP_HASH_VERIFY_ONLY:
747 	case IPSEC_MB_OP_HASH_GEN_THEN_ENCRYPT:
748 		sess->chain_order = IMB_ORDER_HASH_CIPHER;
749 		break;
750 	/*
751 	 * Multi buffer library operates only at two modes,
752 	 * IMB_ORDER_CIPHER_HASH and IMB_ORDER_HASH_CIPHER.
753 	 * When doing ciphering only, chain order depends
754 	 * on cipher operation: encryption is always
755 	 * the first operation and decryption the last one.
756 	 */
757 	case IPSEC_MB_OP_ENCRYPT_ONLY:
758 		sess->chain_order = IMB_ORDER_CIPHER_HASH;
759 		break;
760 	case IPSEC_MB_OP_DECRYPT_ONLY:
761 		sess->chain_order = IMB_ORDER_HASH_CIPHER;
762 		break;
763 	case IPSEC_MB_OP_AEAD_AUTHENTICATED_ENCRYPT:
764 		sess->chain_order = IMB_ORDER_CIPHER_HASH;
765 		sess->aead.aad_len = xform->aead.aad_length;
766 		break;
767 	case IPSEC_MB_OP_AEAD_AUTHENTICATED_DECRYPT:
768 		sess->chain_order = IMB_ORDER_HASH_CIPHER;
769 		sess->aead.aad_len = xform->aead.aad_length;
770 		break;
771 	case IPSEC_MB_OP_NOT_SUPPORTED:
772 	default:
773 		IPSEC_MB_LOG(ERR,
774 			"Unsupported operation chain order parameter");
775 		return -ENOTSUP;
776 	}
777 
778 	/* Default IV length = 0 */
779 	sess->iv.length = 0;
780 	sess->auth_iv.length = 0;
781 
782 	ret = aesni_mb_set_session_auth_parameters(mb_mgr, sess, auth_xform);
783 	if (ret != 0) {
784 		IPSEC_MB_LOG(ERR,
785 			"Invalid/unsupported authentication parameters");
786 		return ret;
787 	}
788 
789 	ret = aesni_mb_set_session_cipher_parameters(mb_mgr, sess,
790 			cipher_xform);
791 	if (ret != 0) {
792 		IPSEC_MB_LOG(ERR, "Invalid/unsupported cipher parameters");
793 		return ret;
794 	}
795 
796 	if (aead_xform) {
797 		ret = aesni_mb_set_session_aead_parameters(mb_mgr, sess,
798 				aead_xform);
799 		if (ret != 0) {
800 			IPSEC_MB_LOG(ERR,
801 				"Invalid/unsupported aead parameters");
802 			return ret;
803 		}
804 	}
805 
806 	return 0;
807 }
808 
809 #ifdef AESNI_MB_DOCSIS_SEC_ENABLED
810 /** Check DOCSIS security session configuration is valid */
811 static int
812 check_docsis_sec_session(struct rte_security_session_conf *conf)
813 {
814 	struct rte_crypto_sym_xform *crypto_sym = conf->crypto_xform;
815 	struct rte_security_docsis_xform *docsis = &conf->docsis;
816 
817 	/* Downlink: CRC generate -> Cipher encrypt */
818 	if (docsis->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
819 
820 		if (crypto_sym != NULL &&
821 		    crypto_sym->type ==	RTE_CRYPTO_SYM_XFORM_CIPHER &&
822 		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
823 		    crypto_sym->cipher.algo ==
824 					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
825 		    (crypto_sym->cipher.key.length == IMB_KEY_128_BYTES ||
826 		     crypto_sym->cipher.key.length == IMB_KEY_256_BYTES) &&
827 		    crypto_sym->cipher.iv.length == IMB_AES_BLOCK_SIZE &&
828 		    crypto_sym->next == NULL) {
829 			return 0;
830 		}
831 	/* Uplink: Cipher decrypt -> CRC verify */
832 	} else if (docsis->direction == RTE_SECURITY_DOCSIS_UPLINK) {
833 
834 		if (crypto_sym != NULL &&
835 		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
836 		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT &&
837 		    crypto_sym->cipher.algo ==
838 					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
839 		    (crypto_sym->cipher.key.length == IMB_KEY_128_BYTES ||
840 		     crypto_sym->cipher.key.length == IMB_KEY_256_BYTES) &&
841 		    crypto_sym->cipher.iv.length == IMB_AES_BLOCK_SIZE &&
842 		    crypto_sym->next == NULL) {
843 			return 0;
844 		}
845 	}
846 
847 	return -EINVAL;
848 }
849 
850 /** Set DOCSIS security session auth (CRC) parameters */
851 static int
852 aesni_mb_set_docsis_sec_session_auth_parameters(struct aesni_mb_session *sess,
853 		struct rte_security_docsis_xform *xform)
854 {
855 	if (xform == NULL) {
856 		IPSEC_MB_LOG(ERR, "Invalid DOCSIS xform");
857 		return -EINVAL;
858 	}
859 
860 	/* Select CRC generate/verify */
861 	if (xform->direction == RTE_SECURITY_DOCSIS_UPLINK) {
862 		sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
863 		sess->auth.operation = RTE_CRYPTO_AUTH_OP_VERIFY;
864 	} else if (xform->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
865 		sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
866 		sess->auth.operation = RTE_CRYPTO_AUTH_OP_GENERATE;
867 	} else {
868 		IPSEC_MB_LOG(ERR, "Unsupported DOCSIS direction");
869 		return -ENOTSUP;
870 	}
871 
872 	sess->auth.req_digest_len = RTE_ETHER_CRC_LEN;
873 	sess->auth.gen_digest_len = RTE_ETHER_CRC_LEN;
874 
875 	return 0;
876 }
877 
878 /**
879  * Parse DOCSIS security session configuration and set private session
880  * parameters
881  */
882 static int
883 aesni_mb_set_docsis_sec_session_parameters(
884 		__rte_unused struct rte_cryptodev *dev,
885 		struct rte_security_session_conf *conf,
886 		void *sess)
887 {
888 	IMB_MGR  *mb_mgr = alloc_init_mb_mgr();
889 	struct rte_security_docsis_xform *docsis_xform;
890 	struct rte_crypto_sym_xform *cipher_xform;
891 	struct aesni_mb_session *ipsec_sess = sess;
892 	int ret = 0;
893 
894 	if (!mb_mgr)
895 		return -ENOMEM;
896 
897 	ret = check_docsis_sec_session(conf);
898 	if (ret) {
899 		IPSEC_MB_LOG(ERR, "Unsupported DOCSIS security configuration");
900 		goto error_exit;
901 	}
902 
903 	switch (conf->docsis.direction) {
904 	case RTE_SECURITY_DOCSIS_UPLINK:
905 		ipsec_sess->chain_order = IMB_ORDER_CIPHER_HASH;
906 		docsis_xform = &conf->docsis;
907 		cipher_xform = conf->crypto_xform;
908 		break;
909 	case RTE_SECURITY_DOCSIS_DOWNLINK:
910 		ipsec_sess->chain_order = IMB_ORDER_HASH_CIPHER;
911 		cipher_xform = conf->crypto_xform;
912 		docsis_xform = &conf->docsis;
913 		break;
914 	default:
915 		IPSEC_MB_LOG(ERR, "Unsupported DOCSIS security configuration");
916 		ret = -EINVAL;
917 		goto error_exit;
918 	}
919 
920 	/* Default IV length = 0 */
921 	ipsec_sess->iv.length = 0;
922 
923 	ret = aesni_mb_set_docsis_sec_session_auth_parameters(ipsec_sess,
924 			docsis_xform);
925 	if (ret != 0) {
926 		IPSEC_MB_LOG(ERR, "Invalid/unsupported DOCSIS parameters");
927 		goto error_exit;
928 	}
929 
930 	ret = aesni_mb_set_session_cipher_parameters(mb_mgr,
931 			ipsec_sess, cipher_xform);
932 
933 	if (ret != 0) {
934 		IPSEC_MB_LOG(ERR, "Invalid/unsupported cipher parameters");
935 		goto error_exit;
936 	}
937 
938 error_exit:
939 	free_mb_mgr(mb_mgr);
940 	return ret;
941 }
942 #endif
943 
944 static inline uint64_t
945 auth_start_offset(struct rte_crypto_op *op, struct aesni_mb_session *session,
946 		uint32_t oop, const uint32_t auth_offset,
947 		const uint32_t cipher_offset, const uint32_t auth_length,
948 		const uint32_t cipher_length, uint8_t lb_sgl)
949 {
950 	struct rte_mbuf *m_src, *m_dst;
951 	uint8_t *p_src, *p_dst;
952 	uintptr_t u_src, u_dst;
953 	uint32_t cipher_end, auth_end;
954 
955 	/* Only cipher then hash needs special calculation. */
956 	if (!oop || session->chain_order != IMB_ORDER_CIPHER_HASH || lb_sgl)
957 		return auth_offset;
958 
959 	m_src = op->sym->m_src;
960 	m_dst = op->sym->m_dst;
961 
962 	p_src = rte_pktmbuf_mtod(m_src, uint8_t *);
963 	p_dst = rte_pktmbuf_mtod(m_dst, uint8_t *);
964 	u_src = (uintptr_t)p_src;
965 	u_dst = (uintptr_t)p_dst + auth_offset;
966 
967 	/**
968 	 * Copy the content between cipher offset and auth offset for generating
969 	 * correct digest.
970 	 */
971 	if (cipher_offset > auth_offset)
972 		memcpy(p_dst + auth_offset,
973 				p_src + auth_offset,
974 				cipher_offset -
975 				auth_offset);
976 
977 	/**
978 	 * Copy the content between (cipher offset + length) and (auth offset +
979 	 * length) for generating correct digest
980 	 */
981 	cipher_end = cipher_offset + cipher_length;
982 	auth_end = auth_offset + auth_length;
983 	if (cipher_end < auth_end)
984 		memcpy(p_dst + cipher_end, p_src + cipher_end,
985 				auth_end - cipher_end);
986 
987 	/**
988 	 * Since intel-ipsec-mb only supports positive values,
989 	 * we need to deduct the correct offset between src and dst.
990 	 */
991 
992 	return u_src < u_dst ? (u_dst - u_src) :
993 			(UINT64_MAX - u_src + u_dst + 1);
994 }
995 
996 static inline void
997 set_cpu_mb_job_params(IMB_JOB *job, struct aesni_mb_session *session,
998 		union rte_crypto_sym_ofs sofs, void *buf, uint32_t len,
999 		struct rte_crypto_va_iova_ptr *iv,
1000 		struct rte_crypto_va_iova_ptr *aad, void *digest, void *udata)
1001 {
1002 	/* Set crypto operation */
1003 	job->chain_order = session->chain_order;
1004 
1005 	/* Set cipher parameters */
1006 	job->cipher_direction = session->cipher.direction;
1007 	job->cipher_mode = session->cipher.mode;
1008 
1009 	job->key_len_in_bytes = session->cipher.key_length_in_bytes;
1010 
1011 	/* Set authentication parameters */
1012 	job->hash_alg = session->auth.algo;
1013 	job->iv = iv->va;
1014 
1015 	switch (job->hash_alg) {
1016 	case IMB_AUTH_AES_XCBC:
1017 		job->u.XCBC._k1_expanded = session->auth.xcbc.k1_expanded;
1018 		job->u.XCBC._k2 = session->auth.xcbc.k2;
1019 		job->u.XCBC._k3 = session->auth.xcbc.k3;
1020 
1021 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1022 		job->dec_keys = session->cipher.expanded_aes_keys.decode;
1023 		break;
1024 
1025 	case IMB_AUTH_AES_CCM:
1026 		job->u.CCM.aad = (uint8_t *)aad->va + 18;
1027 		job->u.CCM.aad_len_in_bytes = session->aead.aad_len;
1028 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1029 		job->dec_keys = session->cipher.expanded_aes_keys.decode;
1030 		job->iv++;
1031 		break;
1032 
1033 	case IMB_AUTH_AES_CMAC:
1034 		job->u.CMAC._key_expanded = session->auth.cmac.expkey;
1035 		job->u.CMAC._skey1 = session->auth.cmac.skey1;
1036 		job->u.CMAC._skey2 = session->auth.cmac.skey2;
1037 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1038 		job->dec_keys = session->cipher.expanded_aes_keys.decode;
1039 		break;
1040 
1041 	case IMB_AUTH_AES_GMAC:
1042 		if (session->cipher.mode == IMB_CIPHER_GCM) {
1043 			job->u.GCM.aad = aad->va;
1044 			job->u.GCM.aad_len_in_bytes = session->aead.aad_len;
1045 		} else {
1046 			/* For GMAC */
1047 			job->u.GCM.aad = buf;
1048 			job->u.GCM.aad_len_in_bytes = len;
1049 			job->cipher_mode = IMB_CIPHER_GCM;
1050 		}
1051 		job->enc_keys = &session->cipher.gcm_key;
1052 		job->dec_keys = &session->cipher.gcm_key;
1053 		break;
1054 
1055 	case IMB_AUTH_CHACHA20_POLY1305:
1056 		job->u.CHACHA20_POLY1305.aad = aad->va;
1057 		job->u.CHACHA20_POLY1305.aad_len_in_bytes =
1058 			session->aead.aad_len;
1059 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1060 		job->dec_keys = session->cipher.expanded_aes_keys.encode;
1061 		break;
1062 	default:
1063 		job->u.HMAC._hashed_auth_key_xor_ipad =
1064 				session->auth.pads.inner;
1065 		job->u.HMAC._hashed_auth_key_xor_opad =
1066 				session->auth.pads.outer;
1067 
1068 		if (job->cipher_mode == IMB_CIPHER_DES3) {
1069 			job->enc_keys = session->cipher.exp_3des_keys.ks_ptr;
1070 			job->dec_keys = session->cipher.exp_3des_keys.ks_ptr;
1071 		} else {
1072 			job->enc_keys = session->cipher.expanded_aes_keys.encode;
1073 			job->dec_keys = session->cipher.expanded_aes_keys.decode;
1074 		}
1075 	}
1076 
1077 	/*
1078 	 * Multi-buffer library current only support returning a truncated
1079 	 * digest length as specified in the relevant IPsec RFCs
1080 	 */
1081 
1082 	/* Set digest location and length */
1083 	job->auth_tag_output = digest;
1084 	job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len;
1085 
1086 	/* Set IV parameters */
1087 	job->iv_len_in_bytes = session->iv.length;
1088 
1089 	/* Data Parameters */
1090 	job->src = buf;
1091 	job->dst = (uint8_t *)buf + sofs.ofs.cipher.head;
1092 	job->cipher_start_src_offset_in_bytes = sofs.ofs.cipher.head;
1093 	job->hash_start_src_offset_in_bytes = sofs.ofs.auth.head;
1094 	if (job->hash_alg == IMB_AUTH_AES_GMAC &&
1095 			session->cipher.mode != IMB_CIPHER_GCM) {
1096 		job->msg_len_to_hash_in_bytes = 0;
1097 		job->msg_len_to_cipher_in_bytes = 0;
1098 	} else {
1099 		job->msg_len_to_hash_in_bytes = len - sofs.ofs.auth.head -
1100 			sofs.ofs.auth.tail;
1101 		job->msg_len_to_cipher_in_bytes = len - sofs.ofs.cipher.head -
1102 			sofs.ofs.cipher.tail;
1103 	}
1104 
1105 	job->user_data = udata;
1106 }
1107 
1108 static int
1109 handle_aead_sgl_job(IMB_JOB *job, IMB_MGR *mb_mgr,
1110 		uint32_t *total_len,
1111 		struct aesni_mb_op_buf_data *src_data,
1112 		struct aesni_mb_op_buf_data *dst_data)
1113 {
1114 	uint32_t data_len, part_len;
1115 
1116 	if (*total_len == 0) {
1117 		job->sgl_state = IMB_SGL_COMPLETE;
1118 		return 0;
1119 	}
1120 
1121 	if (src_data->m == NULL) {
1122 		IPSEC_MB_LOG(ERR, "Invalid source buffer");
1123 		return -EINVAL;
1124 	}
1125 
1126 	job->sgl_state = IMB_SGL_UPDATE;
1127 
1128 	data_len = src_data->m->data_len - src_data->offset;
1129 
1130 	job->src = rte_pktmbuf_mtod_offset(src_data->m, uint8_t *,
1131 			src_data->offset);
1132 
1133 	if (dst_data->m != NULL) {
1134 		if (dst_data->m->data_len - dst_data->offset == 0) {
1135 			dst_data->m = dst_data->m->next;
1136 			if (dst_data->m == NULL) {
1137 				IPSEC_MB_LOG(ERR, "Invalid destination buffer");
1138 				return -EINVAL;
1139 			}
1140 			dst_data->offset = 0;
1141 		}
1142 		part_len = RTE_MIN(data_len, (dst_data->m->data_len -
1143 				dst_data->offset));
1144 		job->dst = rte_pktmbuf_mtod_offset(dst_data->m,
1145 				uint8_t *, dst_data->offset);
1146 		dst_data->offset += part_len;
1147 	} else {
1148 		part_len = RTE_MIN(data_len, *total_len);
1149 		job->dst = rte_pktmbuf_mtod_offset(src_data->m, uint8_t *,
1150 			src_data->offset);
1151 	}
1152 
1153 	job->msg_len_to_cipher_in_bytes = part_len;
1154 	job->msg_len_to_hash_in_bytes = part_len;
1155 
1156 	job = IMB_SUBMIT_JOB(mb_mgr);
1157 
1158 	*total_len -= part_len;
1159 
1160 	if (part_len != data_len) {
1161 		src_data->offset += part_len;
1162 	} else {
1163 		src_data->m = src_data->m->next;
1164 		src_data->offset = 0;
1165 	}
1166 
1167 	return 0;
1168 }
1169 
1170 static uint64_t
1171 sgl_linear_cipher_auth_len(IMB_JOB *job, uint64_t *auth_len)
1172 {
1173 	uint64_t cipher_len;
1174 
1175 	if (job->cipher_mode == IMB_CIPHER_SNOW3G_UEA2_BITLEN ||
1176 			job->cipher_mode == IMB_CIPHER_KASUMI_UEA1_BITLEN)
1177 		cipher_len = (job->msg_len_to_cipher_in_bits >> 3) +
1178 				(job->cipher_start_src_offset_in_bits >> 3);
1179 	else
1180 		cipher_len = job->msg_len_to_cipher_in_bytes +
1181 				job->cipher_start_src_offset_in_bytes;
1182 
1183 	if (job->hash_alg == IMB_AUTH_SNOW3G_UIA2_BITLEN ||
1184 			job->hash_alg == IMB_AUTH_ZUC_EIA3_BITLEN)
1185 		*auth_len = (job->msg_len_to_hash_in_bits >> 3) +
1186 				job->hash_start_src_offset_in_bytes;
1187 	else if (job->hash_alg == IMB_AUTH_AES_GMAC)
1188 		*auth_len = job->u.GCM.aad_len_in_bytes;
1189 	else
1190 		*auth_len = job->msg_len_to_hash_in_bytes +
1191 				job->hash_start_src_offset_in_bytes;
1192 
1193 	return RTE_MAX(*auth_len, cipher_len);
1194 }
1195 
1196 static int
1197 handle_sgl_linear(IMB_JOB *job, struct rte_crypto_op *op, uint32_t dst_offset,
1198 		struct aesni_mb_session *session)
1199 {
1200 	uint64_t auth_len, total_len;
1201 	uint8_t *src, *linear_buf = NULL;
1202 	int lb_offset = 0;
1203 	struct rte_mbuf *src_seg;
1204 	uint16_t src_len;
1205 
1206 	total_len = sgl_linear_cipher_auth_len(job, &auth_len);
1207 	linear_buf = rte_zmalloc(NULL, total_len + job->auth_tag_output_len_in_bytes, 0);
1208 	if (linear_buf == NULL) {
1209 		IPSEC_MB_LOG(ERR, "Error allocating memory for SGL Linear Buffer\n");
1210 		return -1;
1211 	}
1212 
1213 	for (src_seg = op->sym->m_src; (src_seg != NULL) &&
1214 			(total_len - lb_offset > 0);
1215 			src_seg = src_seg->next) {
1216 		src = rte_pktmbuf_mtod(src_seg, uint8_t *);
1217 		src_len =  RTE_MIN(src_seg->data_len, total_len - lb_offset);
1218 		rte_memcpy(linear_buf + lb_offset, src, src_len);
1219 		lb_offset += src_len;
1220 	}
1221 
1222 	job->src = linear_buf;
1223 	job->dst = linear_buf + dst_offset;
1224 	job->user_data2 = linear_buf;
1225 
1226 	if (job->hash_alg == IMB_AUTH_AES_GMAC)
1227 		job->u.GCM.aad = linear_buf;
1228 
1229 	if (session->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY)
1230 		job->auth_tag_output = linear_buf + lb_offset;
1231 	else
1232 		job->auth_tag_output = linear_buf + auth_len;
1233 
1234 	return 0;
1235 }
1236 
1237 static inline int
1238 imb_lib_support_sgl_algo(IMB_CIPHER_MODE alg)
1239 {
1240 	if (alg == IMB_CIPHER_CHACHA20_POLY1305
1241 			|| alg == IMB_CIPHER_GCM)
1242 		return 1;
1243 	return 0;
1244 }
1245 
1246 /**
1247  * Process a crypto operation and complete a IMB_JOB job structure for
1248  * submission to the multi buffer library for processing.
1249  *
1250  * @param	qp		queue pair
1251  * @param	job		IMB_JOB structure to fill
1252  * @param	op		crypto op to process
1253  * @param	digest_idx	ID for digest to use
1254  *
1255  * @return
1256  * - 0 on success, the IMB_JOB will be filled
1257  * - -1 if invalid session or errors allocationg SGL linear buffer,
1258  *   IMB_JOB will not be filled
1259  */
1260 static inline int
1261 set_mb_job_params(IMB_JOB *job, struct ipsec_mb_qp *qp,
1262 		struct rte_crypto_op *op, uint8_t *digest_idx,
1263 		IMB_MGR *mb_mgr)
1264 {
1265 	struct rte_mbuf *m_src = op->sym->m_src, *m_dst;
1266 	struct aesni_mb_qp_data *qp_data = ipsec_mb_get_qp_private_data(qp);
1267 	struct aesni_mb_op_buf_data src_sgl = {0};
1268 	struct aesni_mb_op_buf_data dst_sgl = {0};
1269 	struct aesni_mb_session *session;
1270 	uint32_t m_offset, oop;
1271 	uint32_t auth_off_in_bytes;
1272 	uint32_t ciph_off_in_bytes;
1273 	uint32_t auth_len_in_bytes;
1274 	uint32_t ciph_len_in_bytes;
1275 	uint32_t total_len;
1276 	IMB_JOB base_job;
1277 	uint8_t sgl = 0;
1278 	uint8_t lb_sgl = 0;
1279 	int ret;
1280 
1281 	session = ipsec_mb_get_session_private(qp, op);
1282 	if (session == NULL) {
1283 		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
1284 		return -1;
1285 	}
1286 
1287 	/* Set crypto operation */
1288 	job->chain_order = session->chain_order;
1289 
1290 	/* Set cipher parameters */
1291 	job->cipher_direction = session->cipher.direction;
1292 	job->cipher_mode = session->cipher.mode;
1293 
1294 	job->key_len_in_bytes = session->cipher.key_length_in_bytes;
1295 
1296 	/* Set authentication parameters */
1297 	job->hash_alg = session->auth.algo;
1298 
1299 	const int aead = is_aead_algo(job->hash_alg, job->cipher_mode);
1300 
1301 	if (job->cipher_mode == IMB_CIPHER_DES3) {
1302 		job->enc_keys = session->cipher.exp_3des_keys.ks_ptr;
1303 		job->dec_keys = session->cipher.exp_3des_keys.ks_ptr;
1304 	} else {
1305 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1306 		job->dec_keys = session->cipher.expanded_aes_keys.decode;
1307 	}
1308 
1309 	if (!op->sym->m_dst) {
1310 		/* in-place operation */
1311 		m_dst = m_src;
1312 		oop = 0;
1313 	} else if (op->sym->m_dst == op->sym->m_src) {
1314 		/* in-place operation */
1315 		m_dst = m_src;
1316 		oop = 0;
1317 	} else {
1318 		/* out-of-place operation */
1319 		m_dst = op->sym->m_dst;
1320 		oop = 1;
1321 	}
1322 
1323 	if (m_src->nb_segs > 1 || m_dst->nb_segs > 1) {
1324 		sgl = 1;
1325 		if (!imb_lib_support_sgl_algo(session->cipher.mode))
1326 			lb_sgl = 1;
1327 	}
1328 
1329 	switch (job->hash_alg) {
1330 	case IMB_AUTH_AES_XCBC:
1331 		job->u.XCBC._k1_expanded = session->auth.xcbc.k1_expanded;
1332 		job->u.XCBC._k2 = session->auth.xcbc.k2;
1333 		job->u.XCBC._k3 = session->auth.xcbc.k3;
1334 
1335 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1336 		job->dec_keys = session->cipher.expanded_aes_keys.decode;
1337 		break;
1338 
1339 	case IMB_AUTH_AES_CCM:
1340 		job->u.CCM.aad = op->sym->aead.aad.data + 18;
1341 		job->u.CCM.aad_len_in_bytes = session->aead.aad_len;
1342 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1343 		job->dec_keys = session->cipher.expanded_aes_keys.decode;
1344 		break;
1345 
1346 	case IMB_AUTH_AES_CMAC:
1347 		job->u.CMAC._key_expanded = session->auth.cmac.expkey;
1348 		job->u.CMAC._skey1 = session->auth.cmac.skey1;
1349 		job->u.CMAC._skey2 = session->auth.cmac.skey2;
1350 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1351 		job->dec_keys = session->cipher.expanded_aes_keys.decode;
1352 		break;
1353 
1354 	case IMB_AUTH_AES_GMAC:
1355 		if (session->cipher.mode == IMB_CIPHER_GCM) {
1356 			job->u.GCM.aad = op->sym->aead.aad.data;
1357 			job->u.GCM.aad_len_in_bytes = session->aead.aad_len;
1358 			if (sgl) {
1359 				job->u.GCM.ctx = &qp_data->gcm_sgl_ctx;
1360 				job->cipher_mode = IMB_CIPHER_GCM_SGL;
1361 				job->hash_alg = IMB_AUTH_GCM_SGL;
1362 			}
1363 		} else {
1364 			/* For GMAC */
1365 			job->u.GCM.aad = rte_pktmbuf_mtod_offset(m_src,
1366 					uint8_t *, op->sym->auth.data.offset);
1367 			job->u.GCM.aad_len_in_bytes = op->sym->auth.data.length;
1368 			job->cipher_mode = IMB_CIPHER_GCM;
1369 		}
1370 		job->enc_keys = &session->cipher.gcm_key;
1371 		job->dec_keys = &session->cipher.gcm_key;
1372 		break;
1373 	case IMB_AUTH_ZUC_EIA3_BITLEN:
1374 	case IMB_AUTH_ZUC256_EIA3_BITLEN:
1375 		job->u.ZUC_EIA3._key = session->auth.zuc_auth_key;
1376 		job->u.ZUC_EIA3._iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1377 						session->auth_iv.offset);
1378 		break;
1379 	case IMB_AUTH_SNOW3G_UIA2_BITLEN:
1380 		job->u.SNOW3G_UIA2._key = (void *)
1381 			&session->auth.pKeySched_snow3g_auth;
1382 		job->u.SNOW3G_UIA2._iv =
1383 			rte_crypto_op_ctod_offset(op, uint8_t *,
1384 						session->auth_iv.offset);
1385 		break;
1386 	case IMB_AUTH_KASUMI_UIA1:
1387 		job->u.KASUMI_UIA1._key = (void *)
1388 			&session->auth.pKeySched_kasumi_auth;
1389 		break;
1390 	case IMB_AUTH_CHACHA20_POLY1305:
1391 		job->u.CHACHA20_POLY1305.aad = op->sym->aead.aad.data;
1392 		job->u.CHACHA20_POLY1305.aad_len_in_bytes =
1393 			session->aead.aad_len;
1394 		if (sgl) {
1395 			job->u.CHACHA20_POLY1305.ctx = &qp_data->chacha_sgl_ctx;
1396 			job->cipher_mode = IMB_CIPHER_CHACHA20_POLY1305_SGL;
1397 			job->hash_alg = IMB_AUTH_CHACHA20_POLY1305_SGL;
1398 		}
1399 		job->enc_keys = session->cipher.expanded_aes_keys.encode;
1400 		job->dec_keys = session->cipher.expanded_aes_keys.encode;
1401 		break;
1402 	default:
1403 		job->u.HMAC._hashed_auth_key_xor_ipad =
1404 			session->auth.pads.inner;
1405 		job->u.HMAC._hashed_auth_key_xor_opad =
1406 			session->auth.pads.outer;
1407 
1408 	}
1409 
1410 	if (aead)
1411 		m_offset = op->sym->aead.data.offset;
1412 	else
1413 		m_offset = op->sym->cipher.data.offset;
1414 
1415 	if (job->cipher_mode == IMB_CIPHER_ZUC_EEA3) {
1416 		job->enc_keys = session->cipher.zuc_cipher_key;
1417 		job->dec_keys = session->cipher.zuc_cipher_key;
1418 		m_offset >>= 3;
1419 	} else if (job->cipher_mode == IMB_CIPHER_SNOW3G_UEA2_BITLEN) {
1420 		job->enc_keys = &session->cipher.pKeySched_snow3g_cipher;
1421 		m_offset = 0;
1422 	} else if (job->cipher_mode == IMB_CIPHER_KASUMI_UEA1_BITLEN) {
1423 		job->enc_keys = &session->cipher.pKeySched_kasumi_cipher;
1424 		m_offset = 0;
1425 	}
1426 
1427 	/* Set digest output location */
1428 	if (job->hash_alg != IMB_AUTH_NULL &&
1429 			session->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY) {
1430 		job->auth_tag_output = qp_data->temp_digests[*digest_idx];
1431 		*digest_idx = (*digest_idx + 1) % IMB_MAX_JOBS;
1432 	} else {
1433 		if (aead)
1434 			job->auth_tag_output = op->sym->aead.digest.data;
1435 		else
1436 			job->auth_tag_output = op->sym->auth.digest.data;
1437 
1438 		if (session->auth.req_digest_len !=
1439 				session->auth.gen_digest_len) {
1440 			job->auth_tag_output =
1441 				qp_data->temp_digests[*digest_idx];
1442 			*digest_idx = (*digest_idx + 1) % IMB_MAX_JOBS;
1443 		}
1444 	}
1445 	/*
1446 	 * Multi-buffer library current only support returning a truncated
1447 	 * digest length as specified in the relevant IPsec RFCs
1448 	 */
1449 
1450 	/* Set digest length */
1451 	job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len;
1452 
1453 	/* Set IV parameters */
1454 	job->iv_len_in_bytes = session->iv.length;
1455 
1456 	/* Data Parameters */
1457 	if (sgl) {
1458 		job->src = NULL;
1459 		job->dst = NULL;
1460 	} else {
1461 		job->src = rte_pktmbuf_mtod(m_src, uint8_t *);
1462 		job->dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *, m_offset);
1463 	}
1464 
1465 	switch (job->hash_alg) {
1466 	case IMB_AUTH_AES_CCM:
1467 		job->hash_start_src_offset_in_bytes = op->sym->aead.data.offset;
1468 		job->msg_len_to_hash_in_bytes = op->sym->aead.data.length;
1469 
1470 		job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1471 			session->iv.offset + 1);
1472 		break;
1473 
1474 	case IMB_AUTH_AES_GMAC:
1475 		if (session->cipher.mode == IMB_CIPHER_GCM) {
1476 			job->hash_start_src_offset_in_bytes =
1477 					op->sym->aead.data.offset;
1478 			job->msg_len_to_hash_in_bytes =
1479 					op->sym->aead.data.length;
1480 		} else { /* AES-GMAC only, only AAD used */
1481 			job->msg_len_to_hash_in_bytes = 0;
1482 			job->hash_start_src_offset_in_bytes = 0;
1483 		}
1484 
1485 		job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1486 				session->iv.offset);
1487 		break;
1488 
1489 	case IMB_AUTH_GCM_SGL:
1490 	case IMB_AUTH_CHACHA20_POLY1305_SGL:
1491 		job->hash_start_src_offset_in_bytes = 0;
1492 		job->msg_len_to_hash_in_bytes = 0;
1493 		job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1494 			session->iv.offset);
1495 		break;
1496 
1497 	case IMB_AUTH_CHACHA20_POLY1305:
1498 		job->hash_start_src_offset_in_bytes =
1499 			op->sym->aead.data.offset;
1500 		job->msg_len_to_hash_in_bytes =
1501 					op->sym->aead.data.length;
1502 		job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1503 				session->iv.offset);
1504 		break;
1505 	/* ZUC and SNOW3G require length in bits and offset in bytes */
1506 	case IMB_AUTH_ZUC_EIA3_BITLEN:
1507 	case IMB_AUTH_ZUC256_EIA3_BITLEN:
1508 	case IMB_AUTH_SNOW3G_UIA2_BITLEN:
1509 		auth_off_in_bytes = op->sym->auth.data.offset >> 3;
1510 		ciph_off_in_bytes = op->sym->cipher.data.offset >> 3;
1511 		auth_len_in_bytes = op->sym->auth.data.length >> 3;
1512 		ciph_len_in_bytes = op->sym->cipher.data.length >> 3;
1513 
1514 		job->hash_start_src_offset_in_bytes = auth_start_offset(op,
1515 				session, oop, auth_off_in_bytes,
1516 				ciph_off_in_bytes, auth_len_in_bytes,
1517 				ciph_len_in_bytes, lb_sgl);
1518 		job->msg_len_to_hash_in_bits = op->sym->auth.data.length;
1519 
1520 		job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1521 			session->iv.offset);
1522 		break;
1523 
1524 	/* KASUMI requires lengths and offset in bytes */
1525 	case IMB_AUTH_KASUMI_UIA1:
1526 		auth_off_in_bytes = op->sym->auth.data.offset >> 3;
1527 		ciph_off_in_bytes = op->sym->cipher.data.offset >> 3;
1528 		auth_len_in_bytes = op->sym->auth.data.length >> 3;
1529 		ciph_len_in_bytes = op->sym->cipher.data.length >> 3;
1530 
1531 		job->hash_start_src_offset_in_bytes = auth_start_offset(op,
1532 				session, oop, auth_off_in_bytes,
1533 				ciph_off_in_bytes, auth_len_in_bytes,
1534 				ciph_len_in_bytes, lb_sgl);
1535 		job->msg_len_to_hash_in_bytes = auth_len_in_bytes;
1536 
1537 		job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1538 			session->iv.offset);
1539 		break;
1540 
1541 	default:
1542 		job->hash_start_src_offset_in_bytes = auth_start_offset(op,
1543 				session, oop, op->sym->auth.data.offset,
1544 				op->sym->cipher.data.offset,
1545 				op->sym->auth.data.length,
1546 				op->sym->cipher.data.length, lb_sgl);
1547 		job->msg_len_to_hash_in_bytes = op->sym->auth.data.length;
1548 
1549 		job->iv = rte_crypto_op_ctod_offset(op, uint8_t *,
1550 			session->iv.offset);
1551 	}
1552 
1553 	switch (job->cipher_mode) {
1554 	/* ZUC requires length and offset in bytes */
1555 	case IMB_CIPHER_ZUC_EEA3:
1556 		job->cipher_start_src_offset_in_bytes =
1557 					op->sym->cipher.data.offset >> 3;
1558 		job->msg_len_to_cipher_in_bytes =
1559 					op->sym->cipher.data.length >> 3;
1560 		break;
1561 	/* ZUC and SNOW3G require length and offset in bits */
1562 	case IMB_CIPHER_SNOW3G_UEA2_BITLEN:
1563 	case IMB_CIPHER_KASUMI_UEA1_BITLEN:
1564 		job->cipher_start_src_offset_in_bits =
1565 					op->sym->cipher.data.offset;
1566 		job->msg_len_to_cipher_in_bits =
1567 					op->sym->cipher.data.length;
1568 		break;
1569 	case IMB_CIPHER_GCM:
1570 		if (session->cipher.mode == IMB_CIPHER_NULL) {
1571 			/* AES-GMAC only (only AAD used) */
1572 			job->msg_len_to_cipher_in_bytes = 0;
1573 			job->cipher_start_src_offset_in_bytes = 0;
1574 		} else {
1575 			job->cipher_start_src_offset_in_bytes =
1576 					op->sym->aead.data.offset;
1577 			job->msg_len_to_cipher_in_bytes = op->sym->aead.data.length;
1578 		}
1579 		break;
1580 	case IMB_CIPHER_CCM:
1581 	case IMB_CIPHER_CHACHA20_POLY1305:
1582 		job->cipher_start_src_offset_in_bytes =
1583 				op->sym->aead.data.offset;
1584 		job->msg_len_to_cipher_in_bytes = op->sym->aead.data.length;
1585 		break;
1586 	case IMB_CIPHER_GCM_SGL:
1587 	case IMB_CIPHER_CHACHA20_POLY1305_SGL:
1588 		job->msg_len_to_cipher_in_bytes = 0;
1589 		job->cipher_start_src_offset_in_bytes = 0;
1590 		break;
1591 	default:
1592 		job->cipher_start_src_offset_in_bytes =
1593 					op->sym->cipher.data.offset;
1594 		job->msg_len_to_cipher_in_bytes = op->sym->cipher.data.length;
1595 	}
1596 
1597 	if (job->cipher_mode == IMB_CIPHER_NULL && oop) {
1598 		memcpy(job->dst + job->cipher_start_src_offset_in_bytes,
1599 			job->src + job->cipher_start_src_offset_in_bytes,
1600 			job->msg_len_to_cipher_in_bytes);
1601 	}
1602 
1603 	/* Set user data to be crypto operation data struct */
1604 	job->user_data = op;
1605 
1606 	if (sgl) {
1607 
1608 		if (lb_sgl)
1609 			return handle_sgl_linear(job, op, m_offset, session);
1610 
1611 		base_job = *job;
1612 		job->sgl_state = IMB_SGL_INIT;
1613 		job = IMB_SUBMIT_JOB(mb_mgr);
1614 		total_len = op->sym->aead.data.length;
1615 
1616 		src_sgl.m = m_src;
1617 		src_sgl.offset = m_offset;
1618 
1619 		while (src_sgl.offset >= src_sgl.m->data_len) {
1620 			src_sgl.offset -= src_sgl.m->data_len;
1621 			src_sgl.m = src_sgl.m->next;
1622 
1623 			RTE_ASSERT(src_sgl.m != NULL);
1624 		}
1625 
1626 		if (oop) {
1627 			dst_sgl.m = m_dst;
1628 			dst_sgl.offset = m_offset;
1629 
1630 			while (dst_sgl.offset >= dst_sgl.m->data_len) {
1631 				dst_sgl.offset -= dst_sgl.m->data_len;
1632 				dst_sgl.m = dst_sgl.m->next;
1633 
1634 				RTE_ASSERT(dst_sgl.m != NULL);
1635 			}
1636 		}
1637 
1638 		while (job->sgl_state != IMB_SGL_COMPLETE) {
1639 			job = IMB_GET_NEXT_JOB(mb_mgr);
1640 			*job = base_job;
1641 			ret = handle_aead_sgl_job(job, mb_mgr, &total_len,
1642 				&src_sgl, &dst_sgl);
1643 			if (ret < 0)
1644 				return ret;
1645 		}
1646 	}
1647 
1648 	return 0;
1649 }
1650 
1651 #ifdef AESNI_MB_DOCSIS_SEC_ENABLED
1652 /**
1653  * Process a crypto operation containing a security op and complete a
1654  * IMB_JOB job structure for submission to the multi buffer library for
1655  * processing.
1656  */
1657 static inline int
1658 set_sec_mb_job_params(IMB_JOB *job, struct ipsec_mb_qp *qp,
1659 			struct rte_crypto_op *op, uint8_t *digest_idx)
1660 {
1661 	struct aesni_mb_qp_data *qp_data = ipsec_mb_get_qp_private_data(qp);
1662 	struct rte_mbuf *m_src, *m_dst;
1663 	struct rte_crypto_sym_op *sym;
1664 	struct aesni_mb_session *session = NULL;
1665 
1666 	if (unlikely(op->sess_type != RTE_CRYPTO_OP_SECURITY_SESSION)) {
1667 		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
1668 		return -1;
1669 	}
1670 	session = SECURITY_GET_SESS_PRIV(op->sym->session);
1671 
1672 	if (unlikely(session == NULL)) {
1673 		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
1674 		return -1;
1675 	}
1676 	/* Only DOCSIS protocol operations supported now */
1677 	if (session->cipher.mode != IMB_CIPHER_DOCSIS_SEC_BPI ||
1678 			session->auth.algo != IMB_AUTH_DOCSIS_CRC32) {
1679 		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
1680 		return -1;
1681 	}
1682 
1683 	sym = op->sym;
1684 	m_src = sym->m_src;
1685 
1686 	if (likely(sym->m_dst == NULL || sym->m_dst == m_src)) {
1687 		/* in-place operation */
1688 		m_dst = m_src;
1689 	} else {
1690 		/* out-of-place operation not supported */
1691 		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
1692 		return -ENOTSUP;
1693 	}
1694 
1695 	/* Set crypto operation */
1696 	job->chain_order = session->chain_order;
1697 
1698 	/* Set cipher parameters */
1699 	job->cipher_direction = session->cipher.direction;
1700 	job->cipher_mode = session->cipher.mode;
1701 
1702 	job->key_len_in_bytes = session->cipher.key_length_in_bytes;
1703 	job->enc_keys = session->cipher.expanded_aes_keys.encode;
1704 	job->dec_keys = session->cipher.expanded_aes_keys.decode;
1705 
1706 	/* Set IV parameters */
1707 	job->iv_len_in_bytes = session->iv.length;
1708 	job->iv = (uint8_t *)op + session->iv.offset;
1709 
1710 	/* Set authentication parameters */
1711 	job->hash_alg = session->auth.algo;
1712 
1713 	/* Set digest output location */
1714 	job->auth_tag_output = qp_data->temp_digests[*digest_idx];
1715 	*digest_idx = (*digest_idx + 1) % IMB_MAX_JOBS;
1716 
1717 	/* Set digest length */
1718 	job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len;
1719 
1720 	/* Set data parameters */
1721 	job->src = rte_pktmbuf_mtod(m_src, uint8_t *);
1722 	job->dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *,
1723 						sym->cipher.data.offset);
1724 
1725 	job->cipher_start_src_offset_in_bytes = sym->cipher.data.offset;
1726 	job->msg_len_to_cipher_in_bytes = sym->cipher.data.length;
1727 
1728 	job->hash_start_src_offset_in_bytes = sym->auth.data.offset;
1729 	job->msg_len_to_hash_in_bytes = sym->auth.data.length;
1730 
1731 	job->user_data = op;
1732 
1733 	return 0;
1734 }
1735 
1736 static inline void
1737 verify_docsis_sec_crc(IMB_JOB *job, uint8_t *status)
1738 {
1739 	uint16_t crc_offset;
1740 	uint8_t *crc;
1741 
1742 	if (!job->msg_len_to_hash_in_bytes)
1743 		return;
1744 
1745 	crc_offset = job->hash_start_src_offset_in_bytes +
1746 			job->msg_len_to_hash_in_bytes -
1747 			job->cipher_start_src_offset_in_bytes;
1748 	crc = job->dst + crc_offset;
1749 
1750 	/* Verify CRC (at the end of the message) */
1751 	if (memcmp(job->auth_tag_output, crc, RTE_ETHER_CRC_LEN) != 0)
1752 		*status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
1753 }
1754 #endif
1755 
1756 static inline void
1757 verify_digest(IMB_JOB *job, void *digest, uint16_t len, uint8_t *status)
1758 {
1759 	/* Verify digest if required */
1760 	if (memcmp(job->auth_tag_output, digest, len) != 0)
1761 		*status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
1762 }
1763 
1764 static inline void
1765 generate_digest(IMB_JOB *job, struct rte_crypto_op *op,
1766 		struct aesni_mb_session *sess)
1767 {
1768 	/* No extra copy needed */
1769 	if (likely(sess->auth.req_digest_len == sess->auth.gen_digest_len))
1770 		return;
1771 
1772 	/*
1773 	 * This can only happen for HMAC, so only digest
1774 	 * for authentication algos is required
1775 	 */
1776 	memcpy(op->sym->auth.digest.data, job->auth_tag_output,
1777 			sess->auth.req_digest_len);
1778 }
1779 
1780 static void
1781 post_process_sgl_linear(struct rte_crypto_op *op, IMB_JOB *job,
1782 		struct aesni_mb_session *sess, uint8_t *linear_buf)
1783 {
1784 
1785 	int lb_offset = 0;
1786 	struct rte_mbuf *m_dst = op->sym->m_dst == NULL ?
1787 			op->sym->m_src : op->sym->m_dst;
1788 	uint16_t total_len, dst_len;
1789 	uint64_t auth_len;
1790 	uint8_t *dst;
1791 
1792 	total_len = sgl_linear_cipher_auth_len(job, &auth_len);
1793 
1794 	if (sess->auth.operation != RTE_CRYPTO_AUTH_OP_VERIFY)
1795 		total_len += job->auth_tag_output_len_in_bytes;
1796 
1797 	for (; (m_dst != NULL) && (total_len - lb_offset > 0); m_dst = m_dst->next) {
1798 		dst = rte_pktmbuf_mtod(m_dst, uint8_t *);
1799 		dst_len = RTE_MIN(m_dst->data_len, total_len - lb_offset);
1800 		rte_memcpy(dst, linear_buf + lb_offset, dst_len);
1801 		lb_offset += dst_len;
1802 	}
1803 }
1804 
1805 /**
1806  * Process a completed job and return rte_mbuf which job processed
1807  *
1808  * @param qp	Queue Pair to process
1809  * @param job	IMB_JOB job to process
1810  *
1811  * @return
1812  * - Returns processed crypto operation.
1813  * - Returns NULL on invalid job
1814  */
1815 static inline struct rte_crypto_op *
1816 post_process_mb_job(struct ipsec_mb_qp *qp, IMB_JOB *job)
1817 {
1818 	struct rte_crypto_op *op = (struct rte_crypto_op *)job->user_data;
1819 	struct aesni_mb_session *sess = NULL;
1820 	uint8_t *linear_buf = NULL;
1821 
1822 #ifdef AESNI_MB_DOCSIS_SEC_ENABLED
1823 	uint8_t is_docsis_sec = 0;
1824 
1825 	if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
1826 		/*
1827 		 * Assuming at this point that if it's a security type op, that
1828 		 * this is for DOCSIS
1829 		 */
1830 		is_docsis_sec = 1;
1831 		sess = SECURITY_GET_SESS_PRIV(op->sym->session);
1832 	} else
1833 #endif
1834 		sess = CRYPTODEV_GET_SYM_SESS_PRIV(op->sym->session);
1835 
1836 	if (likely(op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)) {
1837 		switch (job->status) {
1838 		case IMB_STATUS_COMPLETED:
1839 			op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
1840 
1841 			if ((op->sym->m_src->nb_segs > 1 ||
1842 					(op->sym->m_dst != NULL &&
1843 					op->sym->m_dst->nb_segs > 1)) &&
1844 					!imb_lib_support_sgl_algo(sess->cipher.mode)) {
1845 				linear_buf = (uint8_t *) job->user_data2;
1846 				post_process_sgl_linear(op, job, sess, linear_buf);
1847 			}
1848 
1849 			if (job->hash_alg == IMB_AUTH_NULL)
1850 				break;
1851 
1852 			if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY) {
1853 				if (is_aead_algo(job->hash_alg,
1854 						sess->cipher.mode))
1855 					verify_digest(job,
1856 						op->sym->aead.digest.data,
1857 						sess->auth.req_digest_len,
1858 						&op->status);
1859 #ifdef AESNI_MB_DOCSIS_SEC_ENABLED
1860 				else if (is_docsis_sec)
1861 					verify_docsis_sec_crc(job,
1862 						&op->status);
1863 #endif
1864 				else
1865 					verify_digest(job,
1866 						op->sym->auth.digest.data,
1867 						sess->auth.req_digest_len,
1868 						&op->status);
1869 			} else
1870 				generate_digest(job, op, sess);
1871 			break;
1872 		default:
1873 			op->status = RTE_CRYPTO_OP_STATUS_ERROR;
1874 		}
1875 		rte_free(linear_buf);
1876 	}
1877 
1878 	/* Free session if a session-less crypto op */
1879 	if (op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) {
1880 		memset(sess, 0, sizeof(struct aesni_mb_session));
1881 		rte_mempool_put(qp->sess_mp, op->sym->session);
1882 		op->sym->session = NULL;
1883 	}
1884 
1885 	return op;
1886 }
1887 
1888 static inline void
1889 post_process_mb_sync_job(IMB_JOB *job)
1890 {
1891 	uint32_t *st;
1892 
1893 	st = job->user_data;
1894 	st[0] = (job->status == IMB_STATUS_COMPLETED) ? 0 : EBADMSG;
1895 }
1896 
1897 /**
1898  * Process a completed IMB_JOB job and keep processing jobs until
1899  * get_completed_job return NULL
1900  *
1901  * @param qp		Queue Pair to process
1902  * @param mb_mgr	IMB_MGR to use
1903  * @param job		IMB_JOB job
1904  * @param ops		crypto ops to fill
1905  * @param nb_ops	number of crypto ops
1906  *
1907  * @return
1908  * - Number of processed jobs
1909  */
1910 static unsigned
1911 handle_completed_jobs(struct ipsec_mb_qp *qp, IMB_MGR *mb_mgr,
1912 		IMB_JOB *job, struct rte_crypto_op **ops,
1913 		uint16_t nb_ops)
1914 {
1915 	struct rte_crypto_op *op = NULL;
1916 	uint16_t processed_jobs = 0;
1917 
1918 	while (job != NULL) {
1919 		op = post_process_mb_job(qp, job);
1920 
1921 		if (op) {
1922 			ops[processed_jobs++] = op;
1923 			qp->stats.dequeued_count++;
1924 		} else {
1925 			qp->stats.dequeue_err_count++;
1926 			break;
1927 		}
1928 		if (processed_jobs == nb_ops)
1929 			break;
1930 
1931 		job = IMB_GET_COMPLETED_JOB(mb_mgr);
1932 	}
1933 
1934 	return processed_jobs;
1935 }
1936 
1937 static inline uint32_t
1938 handle_completed_sync_jobs(IMB_JOB *job, IMB_MGR *mb_mgr)
1939 {
1940 	uint32_t i;
1941 
1942 	for (i = 0; job != NULL; i++, job = IMB_GET_COMPLETED_JOB(mb_mgr))
1943 		post_process_mb_sync_job(job);
1944 
1945 	return i;
1946 }
1947 
1948 static inline uint32_t
1949 flush_mb_sync_mgr(IMB_MGR *mb_mgr)
1950 {
1951 	IMB_JOB *job;
1952 
1953 	job = IMB_FLUSH_JOB(mb_mgr);
1954 	return handle_completed_sync_jobs(job, mb_mgr);
1955 }
1956 
1957 static inline uint16_t
1958 flush_mb_mgr(struct ipsec_mb_qp *qp, IMB_MGR *mb_mgr,
1959 		struct rte_crypto_op **ops, uint16_t nb_ops)
1960 {
1961 	int processed_ops = 0;
1962 
1963 	/* Flush the remaining jobs */
1964 	IMB_JOB *job = IMB_FLUSH_JOB(mb_mgr);
1965 
1966 	if (job)
1967 		processed_ops += handle_completed_jobs(qp, mb_mgr, job,
1968 				&ops[processed_ops], nb_ops - processed_ops);
1969 
1970 	return processed_ops;
1971 }
1972 
1973 static inline IMB_JOB *
1974 set_job_null_op(IMB_JOB *job, struct rte_crypto_op *op)
1975 {
1976 	job->chain_order = IMB_ORDER_HASH_CIPHER;
1977 	job->cipher_mode = IMB_CIPHER_NULL;
1978 	job->hash_alg = IMB_AUTH_NULL;
1979 	job->cipher_direction = IMB_DIR_DECRYPT;
1980 
1981 	/* Set user data to be crypto operation data struct */
1982 	job->user_data = op;
1983 
1984 	return job;
1985 }
1986 
1987 static uint16_t
1988 aesni_mb_dequeue_burst(void *queue_pair, struct rte_crypto_op **ops,
1989 		uint16_t nb_ops)
1990 {
1991 	struct ipsec_mb_qp *qp = queue_pair;
1992 	IMB_MGR *mb_mgr = qp->mb_mgr;
1993 	struct rte_crypto_op *op;
1994 	IMB_JOB *job;
1995 	int retval, processed_jobs = 0;
1996 
1997 	if (unlikely(nb_ops == 0 || mb_mgr == NULL))
1998 		return 0;
1999 
2000 	uint8_t digest_idx = qp->digest_idx;
2001 
2002 	do {
2003 		/* Get next free mb job struct from mb manager */
2004 		job = IMB_GET_NEXT_JOB(mb_mgr);
2005 		if (unlikely(job == NULL)) {
2006 			/* if no free mb job structs we need to flush mb_mgr */
2007 			processed_jobs += flush_mb_mgr(qp, mb_mgr,
2008 					&ops[processed_jobs],
2009 					nb_ops - processed_jobs);
2010 
2011 			if (nb_ops == processed_jobs)
2012 				break;
2013 
2014 			job = IMB_GET_NEXT_JOB(mb_mgr);
2015 		}
2016 
2017 		/*
2018 		 * Get next operation to process from ingress queue.
2019 		 * There is no need to return the job to the IMB_MGR
2020 		 * if there are no more operations to process, since the IMB_MGR
2021 		 * can use that pointer again in next get_next calls.
2022 		 */
2023 		retval = rte_ring_dequeue(qp->ingress_queue, (void **)&op);
2024 		if (retval < 0)
2025 			break;
2026 
2027 #ifdef AESNI_MB_DOCSIS_SEC_ENABLED
2028 		if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION)
2029 			retval = set_sec_mb_job_params(job, qp, op,
2030 						&digest_idx);
2031 		else
2032 #endif
2033 			retval = set_mb_job_params(job, qp, op,
2034 				&digest_idx, mb_mgr);
2035 
2036 		if (unlikely(retval != 0)) {
2037 			qp->stats.dequeue_err_count++;
2038 			set_job_null_op(job, op);
2039 		}
2040 
2041 		/* Submit job to multi-buffer for processing */
2042 #ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
2043 		job = IMB_SUBMIT_JOB(mb_mgr);
2044 #else
2045 		job = IMB_SUBMIT_JOB_NOCHECK(mb_mgr);
2046 #endif
2047 		/*
2048 		 * If submit returns a processed job then handle it,
2049 		 * before submitting subsequent jobs
2050 		 */
2051 		if (job)
2052 			processed_jobs += handle_completed_jobs(qp, mb_mgr,
2053 					job, &ops[processed_jobs],
2054 					nb_ops - processed_jobs);
2055 
2056 	} while (processed_jobs < nb_ops);
2057 
2058 	qp->digest_idx = digest_idx;
2059 
2060 	if (processed_jobs < 1)
2061 		processed_jobs += flush_mb_mgr(qp, mb_mgr,
2062 				&ops[processed_jobs],
2063 				nb_ops - processed_jobs);
2064 
2065 	return processed_jobs;
2066 }
2067 
2068 static inline int
2069 check_crypto_sgl(union rte_crypto_sym_ofs so, const struct rte_crypto_sgl *sgl)
2070 {
2071 	/* no multi-seg support with current AESNI-MB PMD */
2072 	if (sgl->num != 1)
2073 		return -ENOTSUP;
2074 	else if (so.ofs.cipher.head + so.ofs.cipher.tail > sgl->vec[0].len)
2075 		return -EINVAL;
2076 	return 0;
2077 }
2078 
2079 static inline IMB_JOB *
2080 submit_sync_job(IMB_MGR *mb_mgr)
2081 {
2082 #ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
2083 	return IMB_SUBMIT_JOB(mb_mgr);
2084 #else
2085 	return IMB_SUBMIT_JOB_NOCHECK(mb_mgr);
2086 #endif
2087 }
2088 
2089 static inline uint32_t
2090 generate_sync_dgst(struct rte_crypto_sym_vec *vec,
2091 	const uint8_t dgst[][DIGEST_LENGTH_MAX], uint32_t len)
2092 {
2093 	uint32_t i, k;
2094 
2095 	for (i = 0, k = 0; i != vec->num; i++) {
2096 		if (vec->status[i] == 0) {
2097 			memcpy(vec->digest[i].va, dgst[i], len);
2098 			k++;
2099 		}
2100 	}
2101 
2102 	return k;
2103 }
2104 
2105 static inline uint32_t
2106 verify_sync_dgst(struct rte_crypto_sym_vec *vec,
2107 	const uint8_t dgst[][DIGEST_LENGTH_MAX], uint32_t len)
2108 {
2109 	uint32_t i, k;
2110 
2111 	for (i = 0, k = 0; i != vec->num; i++) {
2112 		if (vec->status[i] == 0) {
2113 			if (memcmp(vec->digest[i].va, dgst[i], len) != 0)
2114 				vec->status[i] = EBADMSG;
2115 			else
2116 				k++;
2117 		}
2118 	}
2119 
2120 	return k;
2121 }
2122 
2123 static uint32_t
2124 aesni_mb_process_bulk(struct rte_cryptodev *dev __rte_unused,
2125 	struct rte_cryptodev_sym_session *sess, union rte_crypto_sym_ofs sofs,
2126 	struct rte_crypto_sym_vec *vec)
2127 {
2128 	int32_t ret;
2129 	uint32_t i, j, k, len;
2130 	void *buf;
2131 	IMB_JOB *job;
2132 	IMB_MGR *mb_mgr;
2133 	struct aesni_mb_session *s = CRYPTODEV_GET_SYM_SESS_PRIV(sess);
2134 	uint8_t tmp_dgst[vec->num][DIGEST_LENGTH_MAX];
2135 
2136 	/* get per-thread MB MGR, create one if needed */
2137 	mb_mgr = get_per_thread_mb_mgr();
2138 	if (unlikely(mb_mgr == NULL))
2139 		return 0;
2140 
2141 	for (i = 0, j = 0, k = 0; i != vec->num; i++) {
2142 		ret = check_crypto_sgl(sofs, vec->src_sgl + i);
2143 		if (ret != 0) {
2144 			vec->status[i] = ret;
2145 			continue;
2146 		}
2147 
2148 		buf = vec->src_sgl[i].vec[0].base;
2149 		len = vec->src_sgl[i].vec[0].len;
2150 
2151 		job = IMB_GET_NEXT_JOB(mb_mgr);
2152 		if (job == NULL) {
2153 			k += flush_mb_sync_mgr(mb_mgr);
2154 			job = IMB_GET_NEXT_JOB(mb_mgr);
2155 			RTE_ASSERT(job != NULL);
2156 		}
2157 
2158 		/* Submit job for processing */
2159 		set_cpu_mb_job_params(job, s, sofs, buf, len, &vec->iv[i],
2160 			&vec->aad[i], tmp_dgst[i], &vec->status[i]);
2161 		job = submit_sync_job(mb_mgr);
2162 		j++;
2163 
2164 		/* handle completed jobs */
2165 		k += handle_completed_sync_jobs(job, mb_mgr);
2166 	}
2167 
2168 	/* flush remaining jobs */
2169 	while (k != j)
2170 		k += flush_mb_sync_mgr(mb_mgr);
2171 
2172 	/* finish processing for successful jobs: check/update digest */
2173 	if (k != 0) {
2174 		if (s->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY)
2175 			k = verify_sync_dgst(vec,
2176 				(const uint8_t (*)[DIGEST_LENGTH_MAX])tmp_dgst,
2177 				s->auth.req_digest_len);
2178 		else
2179 			k = generate_sync_dgst(vec,
2180 				(const uint8_t (*)[DIGEST_LENGTH_MAX])tmp_dgst,
2181 				s->auth.req_digest_len);
2182 	}
2183 
2184 	return k;
2185 }
2186 
2187 struct rte_cryptodev_ops aesni_mb_pmd_ops = {
2188 	.dev_configure = ipsec_mb_config,
2189 	.dev_start = ipsec_mb_start,
2190 	.dev_stop = ipsec_mb_stop,
2191 	.dev_close = ipsec_mb_close,
2192 
2193 	.stats_get = ipsec_mb_stats_get,
2194 	.stats_reset = ipsec_mb_stats_reset,
2195 
2196 	.dev_infos_get = ipsec_mb_info_get,
2197 
2198 	.queue_pair_setup = ipsec_mb_qp_setup,
2199 	.queue_pair_release = ipsec_mb_qp_release,
2200 
2201 	.sym_cpu_process = aesni_mb_process_bulk,
2202 
2203 	.sym_session_get_size = ipsec_mb_sym_session_get_size,
2204 	.sym_session_configure = ipsec_mb_sym_session_configure,
2205 	.sym_session_clear = ipsec_mb_sym_session_clear
2206 };
2207 
2208 #ifdef AESNI_MB_DOCSIS_SEC_ENABLED
2209 /**
2210  * Configure a aesni multi-buffer session from a security session
2211  * configuration
2212  */
2213 static int
2214 aesni_mb_pmd_sec_sess_create(void *dev, struct rte_security_session_conf *conf,
2215 		struct rte_security_session *sess)
2216 {
2217 	void *sess_private_data = SECURITY_GET_SESS_PRIV(sess);
2218 	struct rte_cryptodev *cdev = (struct rte_cryptodev *)dev;
2219 	int ret;
2220 
2221 	if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL ||
2222 			conf->protocol != RTE_SECURITY_PROTOCOL_DOCSIS) {
2223 		IPSEC_MB_LOG(ERR, "Invalid security protocol");
2224 		return -EINVAL;
2225 	}
2226 
2227 	ret = aesni_mb_set_docsis_sec_session_parameters(cdev, conf,
2228 			sess_private_data);
2229 
2230 	if (ret != 0) {
2231 		IPSEC_MB_LOG(ERR, "Failed to configure session parameters");
2232 		return ret;
2233 	}
2234 
2235 	return ret;
2236 }
2237 
2238 /** Clear the memory of session so it does not leave key material behind */
2239 static int
2240 aesni_mb_pmd_sec_sess_destroy(void *dev __rte_unused,
2241 		struct rte_security_session *sess)
2242 {
2243 	void *sess_priv = SECURITY_GET_SESS_PRIV(sess);
2244 
2245 	if (sess_priv) {
2246 		memset(sess_priv, 0, sizeof(struct aesni_mb_session));
2247 	}
2248 	return 0;
2249 }
2250 
2251 static unsigned int
2252 aesni_mb_pmd_sec_sess_get_size(void *device __rte_unused)
2253 {
2254 	return sizeof(struct aesni_mb_session);
2255 }
2256 
2257 /** Get security capabilities for aesni multi-buffer */
2258 static const struct rte_security_capability *
2259 aesni_mb_pmd_sec_capa_get(void *device __rte_unused)
2260 {
2261 	return aesni_mb_pmd_security_cap;
2262 }
2263 
2264 static struct rte_security_ops aesni_mb_pmd_sec_ops = {
2265 		.session_create = aesni_mb_pmd_sec_sess_create,
2266 		.session_update = NULL,
2267 		.session_get_size = aesni_mb_pmd_sec_sess_get_size,
2268 		.session_stats_get = NULL,
2269 		.session_destroy = aesni_mb_pmd_sec_sess_destroy,
2270 		.set_pkt_metadata = NULL,
2271 		.capabilities_get = aesni_mb_pmd_sec_capa_get
2272 };
2273 
2274 struct rte_security_ops *rte_aesni_mb_pmd_sec_ops = &aesni_mb_pmd_sec_ops;
2275 
2276 static int
2277 aesni_mb_configure_dev(struct rte_cryptodev *dev)
2278 {
2279 	struct rte_security_ctx *security_instance;
2280 
2281 	security_instance = rte_malloc("aesni_mb_sec",
2282 				sizeof(struct rte_security_ctx),
2283 				RTE_CACHE_LINE_SIZE);
2284 	if (security_instance != NULL) {
2285 		security_instance->device = (void *)dev;
2286 		security_instance->ops = rte_aesni_mb_pmd_sec_ops;
2287 		security_instance->sess_cnt = 0;
2288 		dev->security_ctx = security_instance;
2289 
2290 		return 0;
2291 	}
2292 
2293 	return -ENOMEM;
2294 }
2295 
2296 #endif
2297 
2298 static int
2299 aesni_mb_probe(struct rte_vdev_device *vdev)
2300 {
2301 	return ipsec_mb_create(vdev, IPSEC_MB_PMD_TYPE_AESNI_MB);
2302 }
2303 
2304 static struct rte_vdev_driver cryptodev_aesni_mb_pmd_drv = {
2305 	.probe = aesni_mb_probe,
2306 	.remove = ipsec_mb_remove
2307 };
2308 
2309 static struct cryptodev_driver aesni_mb_crypto_drv;
2310 
2311 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_AESNI_MB_PMD,
2312 	cryptodev_aesni_mb_pmd_drv);
2313 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_AESNI_MB_PMD, cryptodev_aesni_mb_pmd);
2314 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_AESNI_MB_PMD,
2315 			"max_nb_queue_pairs=<int> socket_id=<int>");
2316 RTE_PMD_REGISTER_CRYPTO_DRIVER(
2317 	aesni_mb_crypto_drv,
2318 	cryptodev_aesni_mb_pmd_drv.driver,
2319 	pmd_driver_id_aesni_mb);
2320 
2321 /* Constructor function to register aesni-mb PMD */
2322 RTE_INIT(ipsec_mb_register_aesni_mb)
2323 {
2324 	struct ipsec_mb_internals *aesni_mb_data =
2325 		&ipsec_mb_pmds[IPSEC_MB_PMD_TYPE_AESNI_MB];
2326 
2327 	aesni_mb_data->caps = aesni_mb_capabilities;
2328 	aesni_mb_data->dequeue_burst = aesni_mb_dequeue_burst;
2329 	aesni_mb_data->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
2330 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
2331 			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
2332 			RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO |
2333 			RTE_CRYPTODEV_FF_NON_BYTE_ALIGNED_DATA |
2334 			RTE_CRYPTODEV_FF_SYM_SESSIONLESS |
2335 			RTE_CRYPTODEV_FF_IN_PLACE_SGL |
2336 			RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT |
2337 			RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
2338 			RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT;
2339 
2340 	aesni_mb_data->internals_priv_size = 0;
2341 	aesni_mb_data->ops = &aesni_mb_pmd_ops;
2342 	aesni_mb_data->qp_priv_size = sizeof(struct aesni_mb_qp_data);
2343 	aesni_mb_data->queue_pair_configure = NULL;
2344 #ifdef AESNI_MB_DOCSIS_SEC_ENABLED
2345 	aesni_mb_data->security_ops = &aesni_mb_pmd_sec_ops;
2346 	aesni_mb_data->dev_config = aesni_mb_configure_dev;
2347 	aesni_mb_data->feature_flags |= RTE_CRYPTODEV_FF_SECURITY;
2348 #endif
2349 	aesni_mb_data->session_configure = aesni_mb_session_configure;
2350 	aesni_mb_data->session_priv_size = sizeof(struct aesni_mb_session);
2351 }
2352