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