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