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