xref: /dpdk/app/test/test_cryptodev_blockcipher.c (revision e11bdd37745229bf26b557305c07d118c3dbaad7)
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 0;
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 0;
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 0;
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 0;
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 0;
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 			goto error_exit;
439 		}
440 		if (!sess || status < 0) {
441 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
442 				"FAILED: %s", __LINE__,
443 				"Session creation failed");
444 			status = TEST_FAILED;
445 			goto error_exit;
446 		}
447 
448 		/* attach symmetric crypto session to crypto operations */
449 		rte_crypto_op_attach_sym_session(op, sess);
450 	}
451 
452 	debug_hexdump(stdout, "m_src(before):",
453 			sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
454 	rte_memcpy(tmp_src_buf, sym_op->m_src->buf_addr,
455 						sym_op->m_src->buf_len);
456 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
457 		debug_hexdump(stdout, "m_dst(before):",
458 			sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
459 		rte_memcpy(tmp_dst_buf, sym_op->m_dst->buf_addr,
460 						sym_op->m_dst->buf_len);
461 	}
462 
463 	/* Process crypto operation */
464 	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
465 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
466 			"line %u FAILED: %s",
467 			__LINE__, "Error sending packet for encryption");
468 		status = TEST_FAILED;
469 		goto error_exit;
470 	}
471 
472 	op = NULL;
473 
474 	while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
475 		rte_pause();
476 
477 	if (!op) {
478 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
479 			"line %u FAILED: %s",
480 			__LINE__, "Failed to process sym crypto op");
481 		status = TEST_FAILED;
482 		goto error_exit;
483 	}
484 
485 	debug_hexdump(stdout, "m_src(after):",
486 			sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
487 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
488 		debug_hexdump(stdout, "m_dst(after):",
489 			sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
490 
491 	/* Verify results */
492 	if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
493 		if ((t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY) &&
494 			(op->status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED))
495 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
496 				"FAILED: Digest verification failed "
497 				"(0x%X)", __LINE__, op->status);
498 		else
499 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
500 				"FAILED: Operation failed "
501 				"(0x%X)", __LINE__, op->status);
502 		status = TEST_FAILED;
503 		goto error_exit;
504 	}
505 
506 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
507 		uint8_t buffer[2048];
508 		const uint8_t *compare_ref;
509 		uint32_t compare_len;
510 
511 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
512 			compare_ref = tdata->ciphertext.data +
513 					tdata->cipher_offset;
514 			compare_len = tdata->ciphertext.len -
515 					tdata->cipher_offset;
516 		} else {
517 			compare_ref = tdata->plaintext.data +
518 					tdata->cipher_offset;
519 			compare_len = tdata->plaintext.len -
520 					tdata->cipher_offset;
521 		}
522 
523 		if (memcmp(rte_pktmbuf_read(iobuf, tdata->cipher_offset,
524 				compare_len, buffer), compare_ref,
525 				compare_len)) {
526 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
527 				"FAILED: %s", __LINE__,
528 				"Crypto data not as expected");
529 			status = TEST_FAILED;
530 			goto error_exit;
531 		}
532 	}
533 
534 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
535 		uint8_t *auth_res = pktmbuf_mtod_offset(iobuf,
536 					tdata->ciphertext.len);
537 
538 		if (memcmp(auth_res, tdata->digest.data, digest_len)) {
539 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
540 				"FAILED: %s", __LINE__, "Generated "
541 				"digest data not as expected");
542 			status = TEST_FAILED;
543 			goto error_exit;
544 		}
545 	}
546 
547 	/* The only parts that should have changed in the buffer are
548 	 * plaintext/ciphertext and digest.
549 	 * In OOP only the dest buffer should change.
550 	 */
551 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
552 		struct rte_mbuf *mbuf;
553 		uint8_t value;
554 		uint32_t head_unchanged_len, changed_len = 0;
555 		uint32_t i;
556 		uint32_t hdroom_used = 0, tlroom_used = 0;
557 		uint32_t hdroom = 0;
558 
559 		mbuf = sym_op->m_src;
560 		/*
561 		 * Crypto PMDs specify the headroom & tailroom it would use
562 		 * when processing the crypto operation. PMD is free to modify
563 		 * this space, and so the verification check should skip that
564 		 * block.
565 		 */
566 		hdroom_used = dev_info.min_mbuf_headroom_req;
567 		tlroom_used = dev_info.min_mbuf_tailroom_req;
568 
569 		/* Get headroom */
570 		hdroom = rte_pktmbuf_headroom(mbuf);
571 
572 		head_unchanged_len = mbuf->buf_len;
573 
574 		for (i = 0; i < mbuf->buf_len; i++) {
575 
576 			/* Skip headroom used by PMD */
577 			if (i == hdroom - hdroom_used)
578 				i += hdroom_used;
579 
580 			/* Skip tailroom used by PMD */
581 			if (i == (hdroom + mbuf->data_len))
582 				i += tlroom_used;
583 
584 			value = *((uint8_t *)(mbuf->buf_addr)+i);
585 			if (value != tmp_src_buf[i]) {
586 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
587 	"line %u FAILED: OOP src outer mbuf data (0x%x) not as expected (0x%x)",
588 					__LINE__, value, tmp_src_buf[i]);
589 				status = TEST_FAILED;
590 				goto error_exit;
591 			}
592 		}
593 
594 		mbuf = sym_op->m_dst;
595 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
596 			head_unchanged_len = hdroom + sym_op->auth.data.offset;
597 			changed_len = sym_op->auth.data.length;
598 			if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
599 				changed_len += digest_len;
600 		} else {
601 			/* cipher-only */
602 			head_unchanged_len = hdroom +
603 					sym_op->cipher.data.offset;
604 			changed_len = sym_op->cipher.data.length;
605 		}
606 
607 		for (i = 0; i < mbuf->buf_len; i++) {
608 			if (i == head_unchanged_len)
609 				i += changed_len;
610 			value = *((uint8_t *)(mbuf->buf_addr)+i);
611 			if (value != tmp_dst_buf[i]) {
612 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
613 				"line %u FAILED: OOP dst outer mbuf data "
614 				"(0x%x) not as expected (0x%x)",
615 				__LINE__, value, tmp_dst_buf[i]);
616 				status = TEST_FAILED;
617 				goto error_exit;
618 			}
619 		}
620 
621 		if (!nb_iterates) {
622 			nb_iterates++;
623 			goto iterate;
624 		}
625 	} else {
626 		/* In-place operation */
627 		struct rte_mbuf *mbuf;
628 		uint8_t value;
629 		uint32_t head_unchanged_len = 0, changed_len = 0;
630 		uint32_t i;
631 		uint32_t hdroom_used = 0, tlroom_used = 0;
632 		uint32_t hdroom = 0;
633 
634 		/*
635 		 * Crypto PMDs specify the headroom & tailroom it would use
636 		 * when processing the crypto operation. PMD is free to modify
637 		 * this space, and so the verification check should skip that
638 		 * block.
639 		 */
640 		hdroom_used = dev_info.min_mbuf_headroom_req;
641 		tlroom_used = dev_info.min_mbuf_tailroom_req;
642 
643 		mbuf = sym_op->m_src;
644 
645 		/* Get headroom */
646 		hdroom = rte_pktmbuf_headroom(mbuf);
647 
648 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
649 			head_unchanged_len = hdroom +
650 					sym_op->cipher.data.offset;
651 			changed_len = sym_op->cipher.data.length;
652 		} else {
653 			/* auth-only */
654 			head_unchanged_len = hdroom +
655 					sym_op->auth.data.offset +
656 					sym_op->auth.data.length;
657 			changed_len = 0;
658 		}
659 
660 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
661 			changed_len += digest_len;
662 
663 		for (i = 0; i < mbuf->buf_len; i++) {
664 
665 			/* Skip headroom used by PMD */
666 			if (i == hdroom - hdroom_used)
667 				i += hdroom_used;
668 
669 			if (i == head_unchanged_len)
670 				i += changed_len;
671 
672 			/* Skip tailroom used by PMD */
673 			if (i == (hdroom + mbuf->data_len))
674 				i += tlroom_used;
675 
676 			value = *((uint8_t *)(mbuf->buf_addr)+i);
677 			if (value != tmp_src_buf[i]) {
678 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
679 				"line %u FAILED: outer mbuf data (0x%x) "
680 				"not as expected (0x%x)",
681 				__LINE__, value, tmp_src_buf[i]);
682 				status = TEST_FAILED;
683 				goto error_exit;
684 			}
685 		}
686 	}
687 
688 	snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "PASS");
689 
690 error_exit:
691 	if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
692 		if (sess) {
693 			rte_cryptodev_sym_session_clear(dev_id, sess);
694 			rte_cryptodev_sym_session_free(sess);
695 		}
696 		if (cipher_xform)
697 			rte_free(cipher_xform);
698 		if (auth_xform)
699 			rte_free(auth_xform);
700 	}
701 
702 	if (op)
703 		rte_crypto_op_free(op);
704 
705 	if (obuf)
706 		rte_pktmbuf_free(obuf);
707 
708 	if (ibuf)
709 		rte_pktmbuf_free(ibuf);
710 
711 	return status;
712 }
713 
714 int
715 test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
716 	struct rte_mempool *op_mpool,
717 	struct rte_mempool *sess_mpool,
718 	struct rte_mempool *sess_priv_mpool,
719 	uint8_t dev_id,
720 	enum blockcipher_test_type test_type)
721 {
722 	int status, overall_status = TEST_SUCCESS;
723 	uint32_t i, test_index = 0;
724 	char test_msg[BLOCKCIPHER_TEST_MSG_LEN + 1];
725 	uint32_t n_test_cases = 0;
726 	const struct blockcipher_test_case *tcs = NULL;
727 
728 	switch (test_type) {
729 	case BLKCIPHER_AES_CHAIN_TYPE:
730 		n_test_cases = sizeof(aes_chain_test_cases) /
731 		sizeof(aes_chain_test_cases[0]);
732 		tcs = aes_chain_test_cases;
733 		break;
734 	case BLKCIPHER_AES_CIPHERONLY_TYPE:
735 		n_test_cases = sizeof(aes_cipheronly_test_cases) /
736 		sizeof(aes_cipheronly_test_cases[0]);
737 		tcs = aes_cipheronly_test_cases;
738 		break;
739 	case BLKCIPHER_AES_DOCSIS_TYPE:
740 		n_test_cases = sizeof(aes_docsis_test_cases) /
741 		sizeof(aes_docsis_test_cases[0]);
742 		tcs = aes_docsis_test_cases;
743 		break;
744 	case BLKCIPHER_3DES_CHAIN_TYPE:
745 		n_test_cases = sizeof(triple_des_chain_test_cases) /
746 		sizeof(triple_des_chain_test_cases[0]);
747 		tcs = triple_des_chain_test_cases;
748 		break;
749 	case BLKCIPHER_3DES_CIPHERONLY_TYPE:
750 		n_test_cases = sizeof(triple_des_cipheronly_test_cases) /
751 		sizeof(triple_des_cipheronly_test_cases[0]);
752 		tcs = triple_des_cipheronly_test_cases;
753 		break;
754 	case BLKCIPHER_DES_CIPHERONLY_TYPE:
755 		n_test_cases = sizeof(des_cipheronly_test_cases) /
756 		sizeof(des_cipheronly_test_cases[0]);
757 		tcs = des_cipheronly_test_cases;
758 		break;
759 	case BLKCIPHER_DES_DOCSIS_TYPE:
760 		n_test_cases = sizeof(des_docsis_test_cases) /
761 		sizeof(des_docsis_test_cases[0]);
762 		tcs = des_docsis_test_cases;
763 		break;
764 	case BLKCIPHER_AUTHONLY_TYPE:
765 		n_test_cases = sizeof(hash_test_cases) /
766 		sizeof(hash_test_cases[0]);
767 		tcs = hash_test_cases;
768 		break;
769 	default:
770 		break;
771 	}
772 
773 	for (i = 0; i < n_test_cases; i++) {
774 		const struct blockcipher_test_case *tc = &tcs[i];
775 
776 		status = test_blockcipher_one_case(tc, mbuf_pool, op_mpool,
777 			sess_mpool, sess_priv_mpool, dev_id,
778 			test_msg);
779 
780 		printf("  %u) TestCase %s %s\n", test_index ++,
781 			tc->test_descr, test_msg);
782 
783 		if (status != TEST_SUCCESS) {
784 			if (overall_status == TEST_SUCCESS)
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