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