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