1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2017 Intel Corporation
3  */
4 
5 #include <rte_common.h>
6 #include <rte_hexdump.h>
7 #include <rte_mbuf.h>
8 #include <rte_malloc.h>
9 #include <rte_memcpy.h>
10 #include <rte_pause.h>
11 
12 #include <rte_crypto.h>
13 #include <rte_cryptodev.h>
14 #include <rte_cryptodev_pmd.h>
15 
16 #include "test.h"
17 #include "test_cryptodev.h"
18 #include "test_cryptodev_blockcipher.h"
19 #include "test_cryptodev_aes_test_vectors.h"
20 #include "test_cryptodev_des_test_vectors.h"
21 #include "test_cryptodev_hash_test_vectors.h"
22 
23 static int
24 test_blockcipher_one_case(const struct blockcipher_test_case *t,
25 	struct rte_mempool *mbuf_pool,
26 	struct rte_mempool *op_mpool,
27 	struct rte_mempool *sess_mpool,
28 	struct rte_mempool *sess_priv_mpool,
29 	uint8_t dev_id,
30 	int driver_id,
31 	char *test_msg)
32 {
33 	struct rte_mbuf *ibuf = NULL;
34 	struct rte_mbuf *obuf = NULL;
35 	struct rte_mbuf *iobuf;
36 	struct rte_crypto_sym_xform *cipher_xform = NULL;
37 	struct rte_crypto_sym_xform *auth_xform = NULL;
38 	struct rte_crypto_sym_xform *init_xform = NULL;
39 	struct rte_crypto_sym_op *sym_op = NULL;
40 	struct rte_crypto_op *op = NULL;
41 	struct rte_cryptodev_info dev_info;
42 	struct rte_cryptodev_sym_session *sess = NULL;
43 
44 	int status = TEST_SUCCESS;
45 	const struct blockcipher_test_data *tdata = t->test_data;
46 	uint8_t cipher_key[tdata->cipher_key.len];
47 	uint8_t auth_key[tdata->auth_key.len];
48 	uint32_t buf_len = tdata->ciphertext.len;
49 	uint32_t digest_len = 0;
50 	char *buf_p = NULL;
51 	uint8_t src_pattern = 0xa5;
52 	uint8_t dst_pattern = 0xb6;
53 	uint8_t tmp_src_buf[MBUF_SIZE];
54 	uint8_t tmp_dst_buf[MBUF_SIZE];
55 
56 	int openssl_pmd = rte_cryptodev_driver_id_get(
57 			RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD));
58 	int ccp_pmd = rte_cryptodev_driver_id_get(
59 			RTE_STR(CRYPTODEV_NAME_CCP_PMD));
60 	int scheduler_pmd = rte_cryptodev_driver_id_get(
61 			RTE_STR(CRYPTODEV_NAME_SCHEDULER_PMD));
62 	int armv8_pmd = rte_cryptodev_driver_id_get(
63 			RTE_STR(CRYPTODEV_NAME_ARMV8_PMD));
64 	int aesni_mb_pmd = rte_cryptodev_driver_id_get(
65 			RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD));
66 	int qat_pmd = rte_cryptodev_driver_id_get(
67 			RTE_STR(CRYPTODEV_NAME_QAT_SYM_PMD));
68 	int dpaa2_sec_pmd = rte_cryptodev_driver_id_get(
69 			RTE_STR(CRYPTODEV_NAME_DPAA2_SEC_PMD));
70 	int dpaa_sec_pmd = rte_cryptodev_driver_id_get(
71 			RTE_STR(CRYPTODEV_NAME_DPAA_SEC_PMD));
72 	int caam_jr_pmd = rte_cryptodev_driver_id_get(
73 			RTE_STR(CRYPTODEV_NAME_CAAM_JR_PMD));
74 	int mrvl_pmd = rte_cryptodev_driver_id_get(
75 			RTE_STR(CRYPTODEV_NAME_MVSAM_PMD));
76 	int virtio_pmd = rte_cryptodev_driver_id_get(
77 			RTE_STR(CRYPTODEV_NAME_VIRTIO_PMD));
78 	int octeontx_pmd = rte_cryptodev_driver_id_get(
79 			RTE_STR(CRYPTODEV_NAME_OCTEONTX_SYM_PMD));
80 	int null_pmd = rte_cryptodev_driver_id_get(
81 				RTE_STR(CRYPTODEV_NAME_NULL_PMD));
82 
83 	int nb_segs = 1;
84 	uint32_t nb_iterates = 0;
85 
86 	rte_cryptodev_info_get(dev_id, &dev_info);
87 
88 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
89 		uint64_t feat_flags = dev_info.feature_flags;
90 		uint64_t oop_flag = RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT;
91 
92 		if (t->feature_mask && BLOCKCIPHER_TEST_FEATURE_OOP) {
93 			if (!(feat_flags & oop_flag)) {
94 				printf("Device doesn't support out-of-place "
95 					"scatter-gather in input mbuf. "
96 					"Test Skipped.\n");
97 				return 0;
98 			}
99 		} else {
100 			if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
101 				printf("Device doesn't support in-place "
102 					"scatter-gather mbufs. "
103 					"Test Skipped.\n");
104 				return 0;
105 			}
106 		}
107 
108 		nb_segs = 3;
109 	}
110 
111 	if (tdata->cipher_key.len)
112 		memcpy(cipher_key, tdata->cipher_key.data,
113 			tdata->cipher_key.len);
114 	if (tdata->auth_key.len)
115 		memcpy(auth_key, tdata->auth_key.data,
116 			tdata->auth_key.len);
117 
118 	if (driver_id == dpaa2_sec_pmd ||
119 			driver_id == dpaa_sec_pmd ||
120 			driver_id == caam_jr_pmd ||
121 			driver_id == qat_pmd ||
122 			driver_id == openssl_pmd ||
123 			driver_id == armv8_pmd ||
124 			driver_id == mrvl_pmd ||
125 			driver_id == ccp_pmd ||
126 			driver_id == virtio_pmd ||
127 			driver_id == octeontx_pmd ||
128 			driver_id == null_pmd) { /* Fall through */
129 		digest_len = tdata->digest.len;
130 	} else if (driver_id == aesni_mb_pmd ||
131 			driver_id == scheduler_pmd) {
132 		digest_len = tdata->digest.truncated_len;
133 	} else {
134 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
135 			"line %u FAILED: %s",
136 			__LINE__, "Unsupported PMD type");
137 		status = TEST_FAILED;
138 		goto error_exit;
139 	}
140 
141 	/* preparing data */
142 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
143 		buf_len += digest_len;
144 
145 	/* for contiguous mbuf, nb_segs is 1 */
146 	ibuf = create_segmented_mbuf(mbuf_pool,
147 			tdata->ciphertext.len, nb_segs, src_pattern);
148 	if (ibuf == NULL) {
149 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
150 			"line %u FAILED: %s",
151 			__LINE__, "Cannot create source mbuf");
152 		status = TEST_FAILED;
153 		goto error_exit;
154 	}
155 
156 	/* only encryption requires plaintext.data input,
157 	 * decryption/(digest gen)/(digest verify) use ciphertext.data
158 	 * to be computed
159 	 */
160 	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
161 		pktmbuf_write(ibuf, 0, tdata->plaintext.len,
162 				tdata->plaintext.data);
163 	else
164 		pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
165 				tdata->ciphertext.data);
166 
167 	buf_p = rte_pktmbuf_append(ibuf, digest_len);
168 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
169 		rte_memcpy(buf_p, tdata->digest.data, digest_len);
170 	else
171 		memset(buf_p, 0, digest_len);
172 
173 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
174 		obuf = rte_pktmbuf_alloc(mbuf_pool);
175 		if (!obuf) {
176 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
177 				"FAILED: %s", __LINE__,
178 				"Allocation of rte_mbuf failed");
179 			status = TEST_FAILED;
180 			goto error_exit;
181 		}
182 		memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
183 
184 		buf_p = rte_pktmbuf_append(obuf, buf_len);
185 		if (!buf_p) {
186 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
187 				"FAILED: %s", __LINE__,
188 				"No room to append mbuf");
189 			status = TEST_FAILED;
190 			goto error_exit;
191 		}
192 		memset(buf_p, 0, buf_len);
193 	}
194 
195 	/* Generate Crypto op data structure */
196 	op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
197 	if (!op) {
198 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
199 			"line %u FAILED: %s",
200 			__LINE__, "Failed to allocate symmetric crypto "
201 			"operation struct");
202 		status = TEST_FAILED;
203 		goto error_exit;
204 	}
205 
206 	sym_op = op->sym;
207 
208 iterate:
209 	if (nb_iterates) {
210 		struct rte_mbuf *tmp_buf = ibuf;
211 
212 		ibuf = obuf;
213 		obuf = tmp_buf;
214 
215 		rte_pktmbuf_reset(ibuf);
216 		rte_pktmbuf_reset(obuf);
217 
218 		rte_pktmbuf_append(ibuf, tdata->ciphertext.len);
219 
220 		/* only encryption requires plaintext.data input,
221 		 * decryption/(digest gen)/(digest verify) use ciphertext.data
222 		 * to be computed
223 		 */
224 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
225 			pktmbuf_write(ibuf, 0, tdata->plaintext.len,
226 					tdata->plaintext.data);
227 		else
228 			pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
229 					tdata->ciphertext.data);
230 
231 		buf_p = rte_pktmbuf_append(ibuf, digest_len);
232 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
233 			rte_memcpy(buf_p, tdata->digest.data, digest_len);
234 		else
235 			memset(buf_p, 0, digest_len);
236 
237 		memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
238 
239 		buf_p = rte_pktmbuf_append(obuf, buf_len);
240 		if (!buf_p) {
241 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
242 				"FAILED: %s", __LINE__,
243 				"No room to append mbuf");
244 			status = TEST_FAILED;
245 			goto error_exit;
246 		}
247 		memset(buf_p, 0, buf_len);
248 	}
249 
250 	sym_op->m_src = ibuf;
251 
252 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
253 		sym_op->m_dst = obuf;
254 		iobuf = obuf;
255 	} else {
256 		sym_op->m_dst = NULL;
257 		iobuf = ibuf;
258 	}
259 
260 	/* sessionless op requires allocate xform using
261 	 * rte_crypto_op_sym_xforms_alloc(), otherwise rte_zmalloc()
262 	 * is used
263 	 */
264 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
265 		uint32_t n_xforms = 0;
266 
267 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
268 			n_xforms++;
269 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
270 			n_xforms++;
271 
272 		if (rte_crypto_op_sym_xforms_alloc(op, n_xforms)
273 			== NULL) {
274 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
275 				"FAILED: %s", __LINE__, "Failed to "
276 				"allocate space for crypto transforms");
277 			status = TEST_FAILED;
278 			goto error_exit;
279 		}
280 	} else {
281 		cipher_xform = rte_zmalloc(NULL,
282 			sizeof(struct rte_crypto_sym_xform), 0);
283 
284 		auth_xform = rte_zmalloc(NULL,
285 			sizeof(struct rte_crypto_sym_xform), 0);
286 
287 		if (!cipher_xform || !auth_xform) {
288 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
289 				"FAILED: %s", __LINE__, "Failed to "
290 				"allocate memory for crypto transforms");
291 			status = TEST_FAILED;
292 			goto error_exit;
293 		}
294 	}
295 
296 	/* preparing xform, for sessioned op, init_xform is initialized
297 	 * here and later as param in rte_cryptodev_sym_session_create() call
298 	 */
299 	if (t->op_mask == BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN) {
300 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
301 			cipher_xform = op->sym->xform;
302 			auth_xform = cipher_xform->next;
303 			auth_xform->next = NULL;
304 		} else {
305 			cipher_xform->next = auth_xform;
306 			auth_xform->next = NULL;
307 			init_xform = cipher_xform;
308 		}
309 	} else if (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC) {
310 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
311 			auth_xform = op->sym->xform;
312 			cipher_xform = auth_xform->next;
313 			cipher_xform->next = NULL;
314 		} else {
315 			auth_xform->next = cipher_xform;
316 			cipher_xform->next = NULL;
317 			init_xform = auth_xform;
318 		}
319 	} else if ((t->op_mask == BLOCKCIPHER_TEST_OP_ENCRYPT) ||
320 			(t->op_mask == BLOCKCIPHER_TEST_OP_DECRYPT)) {
321 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
322 			cipher_xform = op->sym->xform;
323 		else
324 			init_xform = cipher_xform;
325 		cipher_xform->next = NULL;
326 	} else if ((t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_GEN) ||
327 			(t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY)) {
328 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
329 			auth_xform = op->sym->xform;
330 		else
331 			init_xform = auth_xform;
332 		auth_xform->next = NULL;
333 	} else {
334 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
335 			"line %u FAILED: %s",
336 			__LINE__, "Unrecognized operation");
337 		status = TEST_FAILED;
338 		goto error_exit;
339 	}
340 
341 	/*configure xforms & sym_op cipher and auth data*/
342 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
343 		cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
344 		cipher_xform->cipher.algo = tdata->crypto_algo;
345 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
346 			cipher_xform->cipher.op =
347 				RTE_CRYPTO_CIPHER_OP_ENCRYPT;
348 		else
349 			cipher_xform->cipher.op =
350 				RTE_CRYPTO_CIPHER_OP_DECRYPT;
351 		cipher_xform->cipher.key.data = cipher_key;
352 		cipher_xform->cipher.key.length = tdata->cipher_key.len;
353 		cipher_xform->cipher.iv.offset = IV_OFFSET;
354 		cipher_xform->cipher.iv.length = tdata->iv.len;
355 
356 		sym_op->cipher.data.offset = tdata->cipher_offset;
357 		sym_op->cipher.data.length = tdata->ciphertext.len -
358 				tdata->cipher_offset;
359 		rte_memcpy(rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET),
360 				tdata->iv.data,
361 				tdata->iv.len);
362 	}
363 
364 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
365 		uint32_t digest_offset = tdata->ciphertext.len;
366 
367 		auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
368 		auth_xform->auth.algo = tdata->auth_algo;
369 		auth_xform->auth.key.length = tdata->auth_key.len;
370 		auth_xform->auth.key.data = auth_key;
371 		auth_xform->auth.digest_length = digest_len;
372 
373 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
374 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
375 			sym_op->auth.digest.data = pktmbuf_mtod_offset
376 				(iobuf, digest_offset);
377 			sym_op->auth.digest.phys_addr =
378 				pktmbuf_iova_offset(iobuf,
379 					digest_offset);
380 		} else {
381 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
382 			sym_op->auth.digest.data = pktmbuf_mtod_offset
383 				(sym_op->m_src, digest_offset);
384 			sym_op->auth.digest.phys_addr =
385 				pktmbuf_iova_offset(sym_op->m_src,
386 					digest_offset);
387 		}
388 
389 		sym_op->auth.data.offset = tdata->auth_offset;
390 		sym_op->auth.data.length = tdata->ciphertext.len -
391 				tdata->auth_offset;
392 	}
393 
394 	/**
395 	 * Create session for sessioned op. For mbuf iteration test,
396 	 * skip the session creation for the second iteration.
397 	 */
398 	if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) &&
399 			nb_iterates == 0) {
400 		sess = rte_cryptodev_sym_session_create(sess_mpool);
401 
402 		rte_cryptodev_sym_session_init(dev_id, sess, init_xform,
403 				sess_priv_mpool);
404 		if (!sess) {
405 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
406 				"FAILED: %s", __LINE__,
407 				"Session creation failed");
408 			status = TEST_FAILED;
409 			goto error_exit;
410 		}
411 
412 		/* attach symmetric crypto session to crypto operations */
413 		rte_crypto_op_attach_sym_session(op, sess);
414 	}
415 
416 	debug_hexdump(stdout, "m_src(before):",
417 			sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
418 	rte_memcpy(tmp_src_buf, sym_op->m_src->buf_addr,
419 						sym_op->m_src->buf_len);
420 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
421 		debug_hexdump(stdout, "m_dst(before):",
422 			sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
423 		rte_memcpy(tmp_dst_buf, sym_op->m_dst->buf_addr,
424 						sym_op->m_dst->buf_len);
425 	}
426 
427 	/* Process crypto operation */
428 	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
429 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
430 			"line %u FAILED: %s",
431 			__LINE__, "Error sending packet for encryption");
432 		status = TEST_FAILED;
433 		goto error_exit;
434 	}
435 
436 	op = NULL;
437 
438 	while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
439 		rte_pause();
440 
441 	if (!op) {
442 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
443 			"line %u FAILED: %s",
444 			__LINE__, "Failed to process sym crypto op");
445 		status = TEST_FAILED;
446 		goto error_exit;
447 	}
448 
449 	debug_hexdump(stdout, "m_src(after):",
450 			sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
451 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
452 		debug_hexdump(stdout, "m_dst(after):",
453 			sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
454 
455 	/* Verify results */
456 	if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
457 		if ((t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY) &&
458 			(op->status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED))
459 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
460 				"FAILED: Digest verification failed "
461 				"(0x%X)", __LINE__, op->status);
462 		else
463 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
464 				"FAILED: Operation failed "
465 				"(0x%X)", __LINE__, op->status);
466 		status = TEST_FAILED;
467 		goto error_exit;
468 	}
469 
470 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
471 		uint8_t buffer[2048];
472 		const uint8_t *compare_ref;
473 		uint32_t compare_len;
474 
475 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
476 			compare_ref = tdata->ciphertext.data +
477 					tdata->cipher_offset;
478 			compare_len = tdata->ciphertext.len -
479 					tdata->cipher_offset;
480 		} else {
481 			compare_ref = tdata->plaintext.data +
482 					tdata->cipher_offset;
483 			compare_len = tdata->plaintext.len -
484 					tdata->cipher_offset;
485 		}
486 
487 		if (memcmp(rte_pktmbuf_read(iobuf, tdata->cipher_offset,
488 				compare_len, buffer), compare_ref,
489 				compare_len)) {
490 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
491 				"FAILED: %s", __LINE__,
492 				"Crypto data not as expected");
493 			status = TEST_FAILED;
494 			goto error_exit;
495 		}
496 	}
497 
498 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
499 		uint8_t *auth_res = pktmbuf_mtod_offset(iobuf,
500 					tdata->ciphertext.len);
501 
502 		if (memcmp(auth_res, tdata->digest.data, digest_len)) {
503 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
504 				"FAILED: %s", __LINE__, "Generated "
505 				"digest data not as expected");
506 			status = TEST_FAILED;
507 			goto error_exit;
508 		}
509 	}
510 
511 	/* The only parts that should have changed in the buffer are
512 	 * plaintext/ciphertext and digest.
513 	 * In OOP only the dest buffer should change.
514 	 */
515 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
516 		struct rte_mbuf *mbuf;
517 		uint8_t value;
518 		uint32_t head_unchanged_len, changed_len = 0;
519 		uint32_t i;
520 		uint32_t hdroom_used = 0, tlroom_used = 0;
521 		uint32_t hdroom = 0;
522 
523 		mbuf = sym_op->m_src;
524 		/*
525 		 * Crypto PMDs specify the headroom & tailroom it would use
526 		 * when processing the crypto operation. PMD is free to modify
527 		 * this space, and so the verification check should skip that
528 		 * block.
529 		 */
530 		hdroom_used = dev_info.min_mbuf_headroom_req;
531 		tlroom_used = dev_info.min_mbuf_tailroom_req;
532 
533 		/* Get headroom */
534 		hdroom = rte_pktmbuf_headroom(mbuf);
535 
536 		head_unchanged_len = mbuf->buf_len;
537 
538 		for (i = 0; i < mbuf->buf_len; i++) {
539 
540 			/* Skip headroom used by PMD */
541 			if (i == hdroom - hdroom_used)
542 				i += hdroom_used;
543 
544 			/* Skip tailroom used by PMD */
545 			if (i == (hdroom + mbuf->data_len))
546 				i += tlroom_used;
547 
548 			value = *((uint8_t *)(mbuf->buf_addr)+i);
549 			if (value != tmp_src_buf[i]) {
550 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
551 	"line %u FAILED: OOP src outer mbuf data (0x%x) not as expected (0x%x)",
552 					__LINE__, value, tmp_src_buf[i]);
553 				status = TEST_FAILED;
554 				goto error_exit;
555 			}
556 		}
557 
558 		mbuf = sym_op->m_dst;
559 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
560 			head_unchanged_len = hdroom + sym_op->auth.data.offset;
561 			changed_len = sym_op->auth.data.length;
562 			if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
563 				changed_len += digest_len;
564 		} else {
565 			/* cipher-only */
566 			head_unchanged_len = hdroom +
567 					sym_op->cipher.data.offset;
568 			changed_len = sym_op->cipher.data.length;
569 		}
570 
571 		for (i = 0; i < mbuf->buf_len; i++) {
572 			if (i == head_unchanged_len)
573 				i += changed_len;
574 			value = *((uint8_t *)(mbuf->buf_addr)+i);
575 			if (value != tmp_dst_buf[i]) {
576 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
577 				"line %u FAILED: OOP dst outer mbuf data "
578 				"(0x%x) not as expected (0x%x)",
579 				__LINE__, value, tmp_dst_buf[i]);
580 				status = TEST_FAILED;
581 				goto error_exit;
582 			}
583 		}
584 
585 		if (!nb_iterates) {
586 			nb_iterates++;
587 			goto iterate;
588 		}
589 	} else {
590 		/* In-place operation */
591 		struct rte_mbuf *mbuf;
592 		uint8_t value;
593 		uint32_t head_unchanged_len = 0, changed_len = 0;
594 		uint32_t i;
595 		uint32_t hdroom_used = 0, tlroom_used = 0;
596 		uint32_t hdroom = 0;
597 
598 		/*
599 		 * Crypto PMDs specify the headroom & tailroom it would use
600 		 * when processing the crypto operation. PMD is free to modify
601 		 * this space, and so the verification check should skip that
602 		 * block.
603 		 */
604 		hdroom_used = dev_info.min_mbuf_headroom_req;
605 		tlroom_used = dev_info.min_mbuf_tailroom_req;
606 
607 		mbuf = sym_op->m_src;
608 
609 		/* Get headroom */
610 		hdroom = rte_pktmbuf_headroom(mbuf);
611 
612 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
613 			head_unchanged_len = hdroom +
614 					sym_op->cipher.data.offset;
615 			changed_len = sym_op->cipher.data.length;
616 		} else {
617 			/* auth-only */
618 			head_unchanged_len = hdroom +
619 					sym_op->auth.data.offset +
620 					sym_op->auth.data.length;
621 			changed_len = 0;
622 		}
623 
624 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
625 			changed_len += digest_len;
626 
627 		for (i = 0; i < mbuf->buf_len; i++) {
628 
629 			/* Skip headroom used by PMD */
630 			if (i == hdroom - hdroom_used)
631 				i += hdroom_used;
632 
633 			if (i == head_unchanged_len)
634 				i += changed_len;
635 
636 			/* Skip tailroom used by PMD */
637 			if (i == (hdroom + mbuf->data_len))
638 				i += tlroom_used;
639 
640 			value = *((uint8_t *)(mbuf->buf_addr)+i);
641 			if (value != tmp_src_buf[i]) {
642 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
643 				"line %u FAILED: outer mbuf data (0x%x) "
644 				"not as expected (0x%x)",
645 				__LINE__, value, tmp_src_buf[i]);
646 				status = TEST_FAILED;
647 				goto error_exit;
648 			}
649 		}
650 	}
651 
652 	snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "PASS");
653 
654 error_exit:
655 	if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
656 		if (sess) {
657 			rte_cryptodev_sym_session_clear(dev_id, sess);
658 			rte_cryptodev_sym_session_free(sess);
659 		}
660 		if (cipher_xform)
661 			rte_free(cipher_xform);
662 		if (auth_xform)
663 			rte_free(auth_xform);
664 	}
665 
666 	if (op)
667 		rte_crypto_op_free(op);
668 
669 	if (obuf)
670 		rte_pktmbuf_free(obuf);
671 
672 	if (ibuf)
673 		rte_pktmbuf_free(ibuf);
674 
675 	return status;
676 }
677 
678 int
679 test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
680 	struct rte_mempool *op_mpool,
681 	struct rte_mempool *sess_mpool,
682 	struct rte_mempool *sess_priv_mpool,
683 	uint8_t dev_id,
684 	int driver_id,
685 	enum blockcipher_test_type test_type)
686 {
687 	int status, overall_status = TEST_SUCCESS;
688 	uint32_t i, test_index = 0;
689 	char test_msg[BLOCKCIPHER_TEST_MSG_LEN + 1];
690 	uint32_t n_test_cases = 0;
691 	uint32_t target_pmd_mask = 0;
692 	const struct blockcipher_test_case *tcs = NULL;
693 
694 	int openssl_pmd = rte_cryptodev_driver_id_get(
695 			RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD));
696 	int ccp_pmd = rte_cryptodev_driver_id_get(
697 			RTE_STR(CRYPTODEV_NAME_CCP_PMD));
698 	int dpaa2_sec_pmd = rte_cryptodev_driver_id_get(
699 			RTE_STR(CRYPTODEV_NAME_DPAA2_SEC_PMD));
700 	int dpaa_sec_pmd = rte_cryptodev_driver_id_get(
701 			RTE_STR(CRYPTODEV_NAME_DPAA_SEC_PMD));
702 	int caam_jr_pmd = rte_cryptodev_driver_id_get(
703 			RTE_STR(CRYPTODEV_NAME_CAAM_JR_PMD));
704 	int scheduler_pmd = rte_cryptodev_driver_id_get(
705 			RTE_STR(CRYPTODEV_NAME_SCHEDULER_PMD));
706 	int armv8_pmd = rte_cryptodev_driver_id_get(
707 			RTE_STR(CRYPTODEV_NAME_ARMV8_PMD));
708 	int aesni_mb_pmd = rte_cryptodev_driver_id_get(
709 			RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD));
710 	int qat_pmd = rte_cryptodev_driver_id_get(
711 			RTE_STR(CRYPTODEV_NAME_QAT_SYM_PMD));
712 	int mrvl_pmd = rte_cryptodev_driver_id_get(
713 			RTE_STR(CRYPTODEV_NAME_MVSAM_PMD));
714 	int virtio_pmd = rte_cryptodev_driver_id_get(
715 			RTE_STR(CRYPTODEV_NAME_VIRTIO_PMD));
716 	int octeontx_pmd = rte_cryptodev_driver_id_get(
717 			RTE_STR(CRYPTODEV_NAME_OCTEONTX_SYM_PMD));
718 	int null_pmd = rte_cryptodev_driver_id_get(
719 				RTE_STR(CRYPTODEV_NAME_NULL_PMD));
720 
721 	switch (test_type) {
722 	case BLKCIPHER_AES_CHAIN_TYPE:
723 		n_test_cases = sizeof(aes_chain_test_cases) /
724 		sizeof(aes_chain_test_cases[0]);
725 		tcs = aes_chain_test_cases;
726 		break;
727 	case BLKCIPHER_AES_CIPHERONLY_TYPE:
728 		n_test_cases = sizeof(aes_cipheronly_test_cases) /
729 		sizeof(aes_cipheronly_test_cases[0]);
730 		tcs = aes_cipheronly_test_cases;
731 		break;
732 	case BLKCIPHER_AES_DOCSIS_TYPE:
733 		n_test_cases = sizeof(aes_docsis_test_cases) /
734 		sizeof(aes_docsis_test_cases[0]);
735 		tcs = aes_docsis_test_cases;
736 		break;
737 	case BLKCIPHER_3DES_CHAIN_TYPE:
738 		n_test_cases = sizeof(triple_des_chain_test_cases) /
739 		sizeof(triple_des_chain_test_cases[0]);
740 		tcs = triple_des_chain_test_cases;
741 		break;
742 	case BLKCIPHER_3DES_CIPHERONLY_TYPE:
743 		n_test_cases = sizeof(triple_des_cipheronly_test_cases) /
744 		sizeof(triple_des_cipheronly_test_cases[0]);
745 		tcs = triple_des_cipheronly_test_cases;
746 		break;
747 	case BLKCIPHER_DES_CIPHERONLY_TYPE:
748 		n_test_cases = sizeof(des_cipheronly_test_cases) /
749 		sizeof(des_cipheronly_test_cases[0]);
750 		tcs = des_cipheronly_test_cases;
751 		break;
752 	case BLKCIPHER_DES_DOCSIS_TYPE:
753 		n_test_cases = sizeof(des_docsis_test_cases) /
754 		sizeof(des_docsis_test_cases[0]);
755 		tcs = des_docsis_test_cases;
756 		break;
757 	case BLKCIPHER_AUTHONLY_TYPE:
758 		n_test_cases = sizeof(hash_test_cases) /
759 		sizeof(hash_test_cases[0]);
760 		tcs = hash_test_cases;
761 		break;
762 	default:
763 		break;
764 	}
765 
766 	if (driver_id == aesni_mb_pmd)
767 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB;
768 	else if (driver_id == qat_pmd)
769 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_QAT;
770 	else if (driver_id == openssl_pmd)
771 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL;
772 	else if (driver_id == armv8_pmd)
773 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8;
774 	else if (driver_id == scheduler_pmd)
775 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_SCHEDULER;
776 	else if (driver_id == dpaa2_sec_pmd)
777 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_DPAA2_SEC;
778 	else if (driver_id == ccp_pmd)
779 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_CCP;
780 	else if (driver_id == dpaa_sec_pmd)
781 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_DPAA_SEC;
782 	else if (driver_id == caam_jr_pmd)
783 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_CAAM_JR;
784 	else if (driver_id == mrvl_pmd)
785 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MVSAM;
786 	else if (driver_id == virtio_pmd)
787 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_VIRTIO;
788 	else if (driver_id == octeontx_pmd)
789 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OCTEONTX;
790 	else if (driver_id == null_pmd)
791 		target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_NULL;
792 	else
793 		TEST_ASSERT(0, "Unrecognized cryptodev type");
794 
795 	for (i = 0; i < n_test_cases; i++) {
796 		const struct blockcipher_test_case *tc = &tcs[i];
797 
798 		if (!(tc->pmd_mask & target_pmd_mask))
799 			continue;
800 
801 		status = test_blockcipher_one_case(tc, mbuf_pool, op_mpool,
802 			sess_mpool, sess_priv_mpool, dev_id, driver_id,
803 			test_msg);
804 
805 		printf("  %u) TestCase %s %s\n", test_index ++,
806 			tc->test_descr, test_msg);
807 
808 		if (status != TEST_SUCCESS) {
809 			if (overall_status == TEST_SUCCESS)
810 				overall_status = status;
811 
812 			if (tc->feature_mask & BLOCKCIPHER_TEST_FEATURE_STOPPER)
813 				break;
814 		}
815 	}
816 
817 	return overall_status;
818 }
819