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