xref: /dpdk/app/test/test_cryptodev_blockcipher.c (revision 4acc862b18a2f1691d1561f7b75542f6a056d41f)
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 
15 #include "test.h"
16 #include "test_cryptodev.h"
17 #include "test_cryptodev_blockcipher.h"
18 #include "test_cryptodev_aes_test_vectors.h"
19 #include "test_cryptodev_des_test_vectors.h"
20 #include "test_cryptodev_hash_test_vectors.h"
21 #include "test_cryptodev_sm4_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 				!(t->test_data->wrapped_key))
41 			ret = rte_cryptodev_sym_capability_check_cipher(capability,
42 							tdata->cipher_key.len,
43 							tdata->iv.len);
44 		if (ret != 0)
45 			return -1;
46 	}
47 
48 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
49 		cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
50 		cap_idx.algo.auth = tdata->auth_algo;
51 		capability = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
52 		if (capability == NULL)
53 			return -1;
54 
55 		if (cap_idx.algo.auth != RTE_CRYPTO_AUTH_NULL)
56 			ret = rte_cryptodev_sym_capability_check_auth(capability,
57 							tdata->auth_key.len,
58 							digest_len,
59 							0);
60 		if (ret != 0)
61 			return -1;
62 	}
63 
64 	return 0;
65 }
66 
67 static int
68 test_blockcipher_one_case(const struct blockcipher_test_case *t,
69 	struct rte_mempool *mbuf_pool,
70 	struct rte_mempool *op_mpool,
71 	struct rte_mempool *sess_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 	void *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 	uint32_t pad_len;
98 
99 	int nb_segs_in = 1;
100 	int nb_segs_out = 1;
101 	uint64_t sgl_type = t->sgl_flag;
102 	uint32_t nb_iterates = 0;
103 
104 	rte_cryptodev_info_get(dev_id, &dev_info);
105 	uint64_t feat_flags = dev_info.feature_flags;
106 
107 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
108 		if (!(feat_flags & RTE_CRYPTODEV_FF_SYM_SESSIONLESS)) {
109 			printf("Device doesn't support sessionless operations "
110 				"Test Skipped.\n");
111 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
112 				"SKIPPED");
113 			return TEST_SKIPPED;
114 		}
115 	}
116 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_DIGEST_ENCRYPTED) {
117 		if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
118 			printf("Device doesn't support encrypted digest "
119 				"Test Skipped.\n");
120 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
121 				"SKIPPED");
122 			return TEST_SKIPPED;
123 		}
124 	}
125 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
126 		if (sgl_type == 0) {
127 			if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
128 				sgl_type = RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT;
129 			else
130 				sgl_type = RTE_CRYPTODEV_FF_IN_PLACE_SGL;
131 		}
132 
133 		if (!(feat_flags & sgl_type)) {
134 			printf("Device doesn't support scatter-gather type."
135 				" Test Skipped.\n");
136 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
137 				"SKIPPED");
138 			return TEST_SKIPPED;
139 		}
140 
141 		if (sgl_type == RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT ||
142 				sgl_type == RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT ||
143 				sgl_type == RTE_CRYPTODEV_FF_IN_PLACE_SGL)
144 			nb_segs_in = t->sgl_segs == 0 ? 3 : t->sgl_segs;
145 
146 		if (sgl_type == RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT ||
147 				sgl_type == RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT)
148 			nb_segs_out = t->sgl_segs == 0 ? 3 : t->sgl_segs;
149 	}
150 
151 	if (!!(feat_flags & RTE_CRYPTODEV_FF_CIPHER_WRAPPED_KEY) ^
152 		tdata->wrapped_key) {
153 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
154 			"SKIPPED");
155 		return TEST_SKIPPED;
156 	}
157 
158 	if (global_api_test_type == CRYPTODEV_RAW_API_TEST &&
159 		!(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP)) {
160 		printf("Device doesn't support raw data-path APIs. "
161 			"Test Skipped.\n");
162 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "SKIPPED");
163 		return TEST_SKIPPED;
164 	}
165 
166 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
167 		uint64_t oop_flags = RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
168 			RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
169 			RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
170 			RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT;
171 		if (!(feat_flags & oop_flags)) {
172 			printf("Device doesn't support out-of-place operations."
173 				"Test Skipped.\n");
174 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
175 				"SKIPPED");
176 			return TEST_SKIPPED;
177 		}
178 		if (global_api_test_type == CRYPTODEV_RAW_API_TEST) {
179 			printf("Raw Data Path APIs do not support OOP, "
180 				"Test Skipped.\n");
181 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "SKIPPED");
182 			status = TEST_SKIPPED;
183 			goto error_exit;
184 		}
185 	}
186 
187 	if (tdata->cipher_key.len)
188 		memcpy(cipher_key, tdata->cipher_key.data,
189 			tdata->cipher_key.len);
190 	if (tdata->auth_key.len)
191 		memcpy(auth_key, tdata->auth_key.data,
192 			tdata->auth_key.len);
193 
194 	/* Check if PMD is capable of performing that test */
195 	if (verify_algo_support(t, dev_id, digest_len) < 0) {
196 		RTE_LOG(DEBUG, USER1,
197 			"Device does not support this algorithm."
198 			"Test Skipped.\n");
199 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "SKIPPED");
200 		return TEST_SKIPPED;
201 	}
202 
203 	/* preparing data */
204 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
205 		buf_len += digest_len;
206 
207 	pad_len = RTE_ALIGN(buf_len, 16) - buf_len;
208 	if (t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED)
209 		buf_len += pad_len;
210 
211 	/* for contiguous mbuf, nb_segs is 1 */
212 	ibuf = create_segmented_mbuf(mbuf_pool,
213 			tdata->ciphertext.len, nb_segs_in, src_pattern);
214 	if (ibuf == NULL) {
215 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
216 			"line %u FAILED: %s",
217 			__LINE__, "Cannot create source mbuf");
218 		status = TEST_FAILED;
219 		goto error_exit;
220 	}
221 
222 	/* only encryption requires plaintext.data input,
223 	 * decryption/(digest gen)/(digest verify) use ciphertext.data
224 	 * to be computed
225 	 */
226 	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
227 		pktmbuf_write(ibuf, 0, tdata->plaintext.len,
228 				tdata->plaintext.data);
229 	else
230 		pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
231 				tdata->ciphertext.data);
232 
233 	buf_p = rte_pktmbuf_append(ibuf, digest_len);
234 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
235 		if (t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED)
236 			rte_memcpy(buf_p,
237 				tdata->ciphertext.data + tdata->ciphertext.len,
238 				 digest_len);
239 		else
240 			rte_memcpy(buf_p, tdata->digest.data, digest_len);
241 	else
242 		memset(buf_p, 0, digest_len);
243 	if (t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED) {
244 		buf_p = rte_pktmbuf_append(ibuf, pad_len);
245 		if (!buf_p) {
246 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
247 				"FAILED: %s", __LINE__,
248 				"No room to append mbuf");
249 			status = TEST_FAILED;
250 			goto error_exit;
251 		}
252 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY) {
253 			const uint8_t *temp_p = tdata->ciphertext.data +
254 					tdata->ciphertext.len +
255 					digest_len;
256 			rte_memcpy(buf_p, temp_p, pad_len);
257 		} else
258 			memset(buf_p, 0xa5, pad_len);
259 	}
260 
261 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
262 		obuf = create_segmented_mbuf(mbuf_pool,
263 			tdata->ciphertext.len, nb_segs_out, dst_pattern);
264 		if (!obuf) {
265 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
266 				"FAILED: %s", __LINE__,
267 				"Allocation of rte_mbuf failed");
268 			status = TEST_FAILED;
269 			goto error_exit;
270 		}
271 		memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
272 
273 		if (t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED)
274 			buf_p = rte_pktmbuf_append(obuf, buf_len + pad_len);
275 		else
276 			buf_p = rte_pktmbuf_append(obuf, buf_len);
277 		if (!buf_p) {
278 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
279 				"FAILED: %s", __LINE__,
280 				"No room to append mbuf");
281 			status = TEST_FAILED;
282 			goto error_exit;
283 		}
284 		memset(buf_p, 0, buf_len);
285 	}
286 
287 	/* Generate Crypto op data structure */
288 	op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
289 	if (!op) {
290 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
291 			"line %u FAILED: %s",
292 			__LINE__, "Failed to allocate symmetric crypto "
293 			"operation struct");
294 		status = TEST_FAILED;
295 		goto error_exit;
296 	}
297 
298 	sym_op = op->sym;
299 
300 iterate:
301 	if (nb_iterates) {
302 		struct rte_mbuf *tmp_buf = ibuf;
303 
304 		ibuf = obuf;
305 		obuf = tmp_buf;
306 
307 		rte_pktmbuf_reset(ibuf);
308 		rte_pktmbuf_reset(obuf);
309 
310 		rte_pktmbuf_append(ibuf, tdata->ciphertext.len);
311 
312 		/* only encryption requires plaintext.data input,
313 		 * decryption/(digest gen)/(digest verify) use ciphertext.data
314 		 * to be computed
315 		 */
316 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
317 			pktmbuf_write(ibuf, 0, tdata->plaintext.len,
318 					tdata->plaintext.data);
319 		else
320 			pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
321 					tdata->ciphertext.data);
322 
323 		buf_p = rte_pktmbuf_append(ibuf, digest_len);
324 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
325 			rte_memcpy(buf_p, tdata->digest.data, digest_len);
326 		else
327 			memset(buf_p, 0, digest_len);
328 
329 		memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
330 
331 		buf_p = rte_pktmbuf_append(obuf, buf_len);
332 		if (!buf_p) {
333 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
334 				"FAILED: %s", __LINE__,
335 				"No room to append mbuf");
336 			status = TEST_FAILED;
337 			goto error_exit;
338 		}
339 		memset(buf_p, 0, buf_len);
340 	}
341 
342 	sym_op->m_src = ibuf;
343 
344 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
345 		sym_op->m_dst = obuf;
346 		iobuf = obuf;
347 	} else {
348 		sym_op->m_dst = NULL;
349 		iobuf = ibuf;
350 	}
351 
352 	/* sessionless op requires allocate xform using
353 	 * rte_crypto_op_sym_xforms_alloc(), otherwise rte_zmalloc()
354 	 * is used
355 	 */
356 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
357 		uint32_t n_xforms = 0;
358 
359 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
360 			n_xforms++;
361 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
362 			n_xforms++;
363 
364 		if (rte_crypto_op_sym_xforms_alloc(op, n_xforms)
365 			== NULL) {
366 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
367 				"FAILED: %s", __LINE__, "Failed to "
368 				"allocate space for crypto transforms");
369 			status = TEST_FAILED;
370 			goto error_exit;
371 		}
372 	} else {
373 		cipher_xform = rte_zmalloc(NULL,
374 			sizeof(struct rte_crypto_sym_xform), 0);
375 
376 		auth_xform = rte_zmalloc(NULL,
377 			sizeof(struct rte_crypto_sym_xform), 0);
378 
379 		if (!cipher_xform || !auth_xform) {
380 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
381 				"FAILED: %s", __LINE__, "Failed to "
382 				"allocate memory for crypto transforms");
383 			status = TEST_FAILED;
384 			goto error_exit;
385 		}
386 	}
387 
388 	/* preparing xform, for sessioned op, init_xform is initialized
389 	 * here and later as param in rte_cryptodev_sym_session_create() call
390 	 */
391 	if (t->op_mask == BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN) {
392 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
393 			cipher_xform = op->sym->xform;
394 			auth_xform = cipher_xform->next;
395 			auth_xform->next = NULL;
396 		} else {
397 			cipher_xform->next = auth_xform;
398 			auth_xform->next = NULL;
399 			init_xform = cipher_xform;
400 		}
401 	} else if (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC) {
402 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
403 			auth_xform = op->sym->xform;
404 			cipher_xform = auth_xform->next;
405 			cipher_xform->next = NULL;
406 		} else {
407 			auth_xform->next = cipher_xform;
408 			cipher_xform->next = NULL;
409 			init_xform = auth_xform;
410 		}
411 	} else if (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_GEN_ENC) {
412 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
413 			auth_xform = op->sym->xform;
414 			cipher_xform = auth_xform->next;
415 			cipher_xform->next = NULL;
416 		} else {
417 			auth_xform->next = cipher_xform;
418 			cipher_xform->next = NULL;
419 			init_xform = auth_xform;
420 		}
421 	} else if (t->op_mask == BLOCKCIPHER_TEST_OP_DEC_AUTH_VERIFY) {
422 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
423 			cipher_xform = op->sym->xform;
424 			auth_xform = cipher_xform->next;
425 			auth_xform->next = NULL;
426 		} else {
427 			cipher_xform->next = auth_xform;
428 			auth_xform->next = NULL;
429 			init_xform = cipher_xform;
430 		}
431 	} else if ((t->op_mask == BLOCKCIPHER_TEST_OP_ENCRYPT) ||
432 			(t->op_mask == BLOCKCIPHER_TEST_OP_DECRYPT)) {
433 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
434 			cipher_xform = op->sym->xform;
435 		else
436 			init_xform = cipher_xform;
437 		cipher_xform->next = NULL;
438 	} else if ((t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_GEN) ||
439 			(t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY)) {
440 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
441 			auth_xform = op->sym->xform;
442 		else
443 			init_xform = auth_xform;
444 		auth_xform->next = NULL;
445 	} else {
446 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
447 			"line %u FAILED: %s",
448 			__LINE__, "Unrecognized operation");
449 		status = TEST_FAILED;
450 		goto error_exit;
451 	}
452 
453 	/*configure xforms & sym_op cipher and auth data*/
454 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
455 		cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
456 		cipher_xform->cipher.algo = tdata->crypto_algo;
457 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
458 			cipher_xform->cipher.op =
459 				RTE_CRYPTO_CIPHER_OP_ENCRYPT;
460 		else
461 			cipher_xform->cipher.op =
462 				RTE_CRYPTO_CIPHER_OP_DECRYPT;
463 		cipher_xform->cipher.key.data = cipher_key;
464 		cipher_xform->cipher.key.length = tdata->cipher_key.len;
465 		cipher_xform->cipher.iv.offset = IV_OFFSET;
466 		cipher_xform->cipher.dataunit_len = tdata->xts_dataunit_len;
467 
468 		if (tdata->crypto_algo == RTE_CRYPTO_CIPHER_NULL)
469 			cipher_xform->cipher.iv.length = 0;
470 		else
471 			cipher_xform->cipher.iv.length = tdata->iv.len;
472 
473 		sym_op->cipher.data.offset = tdata->cipher_offset;
474 		sym_op->cipher.data.length = tdata->ciphertext.len -
475 				tdata->cipher_offset;
476 		if (t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED) {
477 			sym_op->cipher.data.length += tdata->digest.len;
478 			sym_op->cipher.data.length += pad_len;
479 		}
480 		rte_memcpy(rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET),
481 				tdata->iv.data,
482 				tdata->iv.len);
483 	}
484 
485 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
486 		uint32_t digest_offset = tdata->ciphertext.len;
487 
488 		auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
489 		auth_xform->auth.algo = tdata->auth_algo;
490 		auth_xform->auth.key.length = tdata->auth_key.len;
491 		auth_xform->auth.key.data = auth_key;
492 		auth_xform->auth.digest_length = digest_len;
493 
494 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
495 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
496 			sym_op->auth.digest.data = pktmbuf_mtod_offset
497 				(iobuf, digest_offset);
498 			sym_op->auth.digest.phys_addr =
499 				pktmbuf_iova_offset(iobuf,
500 					digest_offset);
501 		} else {
502 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
503 			sym_op->auth.digest.data = pktmbuf_mtod_offset
504 				(sym_op->m_src, digest_offset);
505 			sym_op->auth.digest.phys_addr =
506 				pktmbuf_iova_offset(sym_op->m_src,
507 					digest_offset);
508 		}
509 
510 		sym_op->auth.data.offset = tdata->auth_offset;
511 		sym_op->auth.data.length = tdata->ciphertext.len -
512 				tdata->auth_offset;
513 	}
514 
515 	/**
516 	 * Create session for sessioned op. For mbuf iteration test,
517 	 * skip the session creation for the second iteration.
518 	 */
519 	if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) &&
520 			nb_iterates == 0) {
521 		sess = rte_cryptodev_sym_session_create(dev_id, init_xform,
522 				sess_mpool);
523 		if (sess == NULL) {
524 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "UNSUPPORTED");
525 			status = TEST_SKIPPED;
526 			goto error_exit;
527 		}
528 		if (!sess || status < 0) {
529 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
530 				"FAILED: %s", __LINE__,
531 				"Session creation failed");
532 			status = TEST_FAILED;
533 			goto error_exit;
534 		}
535 
536 		/* attach symmetric crypto session to crypto operations */
537 		rte_crypto_op_attach_sym_session(op, sess);
538 	}
539 
540 	debug_hexdump(stdout, "m_src(before):",
541 			sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
542 	rte_memcpy(tmp_src_buf, sym_op->m_src->buf_addr,
543 						sym_op->m_src->buf_len);
544 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
545 		debug_hexdump(stdout, "m_dst(before):",
546 			sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
547 		rte_memcpy(tmp_dst_buf, sym_op->m_dst->buf_addr,
548 						sym_op->m_dst->buf_len);
549 	}
550 
551 	/* Process crypto operation */
552 	if (global_api_test_type == CRYPTODEV_RAW_API_TEST) {
553 		uint8_t is_cipher = 0, is_auth = 0;
554 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
555 			is_cipher = 1;
556 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
557 			is_auth = 1;
558 
559 		status = process_sym_raw_dp_op(dev_id, 0, op, is_cipher, is_auth,
560 					       0, tdata->iv.len);
561 		if (status != TEST_SUCCESS) {
562 			if (status == TEST_SKIPPED)
563 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "SKIPPED");
564 			else
565 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "FAILED");
566 
567 			goto error_exit;
568 		}
569 	} else {
570 		if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
571 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
572 				"line %u FAILED: %s",
573 				__LINE__, "Error sending packet for encryption");
574 			status = TEST_FAILED;
575 			goto error_exit;
576 		}
577 
578 		op = NULL;
579 
580 		while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
581 			rte_pause();
582 
583 		if (!op) {
584 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
585 				"line %u FAILED: %s",
586 				__LINE__, "Failed to process sym crypto op");
587 			status = TEST_FAILED;
588 			goto error_exit;
589 		}
590 	}
591 
592 	debug_hexdump(stdout, "m_src(after):",
593 			sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
594 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
595 		debug_hexdump(stdout, "m_dst(after):",
596 			sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
597 
598 	/* Verify results */
599 	if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
600 		if ((t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY) &&
601 			(op->status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED))
602 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
603 				"FAILED: Digest verification failed "
604 				"(0x%X)", __LINE__, op->status);
605 		else
606 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
607 				"FAILED: Operation failed "
608 				"(0x%X)", __LINE__, op->status);
609 		status = TEST_FAILED;
610 		goto error_exit;
611 	}
612 
613 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
614 		uint8_t buffer[2048];
615 		const uint8_t *compare_ref;
616 		uint32_t compare_len;
617 
618 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
619 			compare_ref = tdata->ciphertext.data +
620 					tdata->cipher_offset;
621 			compare_len = tdata->ciphertext.len -
622 					tdata->cipher_offset;
623 			if (t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED)
624 				compare_len += tdata->digest.len;
625 		} else {
626 			compare_ref = tdata->plaintext.data +
627 					tdata->cipher_offset;
628 			compare_len = tdata->plaintext.len -
629 					tdata->cipher_offset;
630 		}
631 
632 		if (memcmp(rte_pktmbuf_read(iobuf, tdata->cipher_offset,
633 				compare_len, buffer), compare_ref,
634 				compare_len)) {
635 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
636 				"FAILED: %s", __LINE__,
637 				"Crypto data not as expected");
638 			status = TEST_FAILED;
639 			goto error_exit;
640 		}
641 	}
642 
643 	/* Check digest data only in enc-then-auth_gen case.
644 	 * In auth_gen-then-enc case, cipher text contains both encrypted
645 	 * plain text and encrypted digest value. If cipher text is correct,
646 	 * it implies digest is also generated properly.
647 	 */
648 	if (!(t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED))
649 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
650 			uint8_t *auth_res = pktmbuf_mtod_offset(iobuf,
651 						tdata->ciphertext.len);
652 
653 			if (memcmp(auth_res, tdata->digest.data, digest_len)) {
654 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
655 					"FAILED: %s", __LINE__, "Generated "
656 					"digest data not as expected");
657 				status = TEST_FAILED;
658 				goto error_exit;
659 			}
660 		}
661 
662 	/* The only parts that should have changed in the buffer are
663 	 * plaintext/ciphertext and digest.
664 	 * In OOP only the dest buffer should change.
665 	 */
666 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
667 		struct rte_mbuf *mbuf;
668 		uint8_t value;
669 		uint32_t head_unchanged_len, changed_len = 0;
670 		uint32_t i;
671 		uint32_t hdroom_used = 0, tlroom_used = 0;
672 		uint32_t hdroom = 0;
673 
674 		mbuf = sym_op->m_src;
675 		/*
676 		 * Crypto PMDs specify the headroom & tailroom it would use
677 		 * when processing the crypto operation. PMD is free to modify
678 		 * this space, and so the verification check should skip that
679 		 * block.
680 		 */
681 		hdroom_used = dev_info.min_mbuf_headroom_req;
682 		tlroom_used = dev_info.min_mbuf_tailroom_req;
683 
684 		/* Get headroom */
685 		hdroom = rte_pktmbuf_headroom(mbuf);
686 
687 		head_unchanged_len = mbuf->buf_len;
688 
689 		for (i = 0; i < mbuf->buf_len; i++) {
690 
691 			/* Skip headroom used by PMD */
692 			if (i == hdroom - hdroom_used)
693 				i += hdroom_used;
694 
695 			/* Skip tailroom used by PMD */
696 			if (i == (hdroom + mbuf->data_len))
697 				i += tlroom_used;
698 
699 			value = *((uint8_t *)(mbuf->buf_addr)+i);
700 			if (value != tmp_src_buf[i]) {
701 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
702 	"line %u FAILED: OOP src outer mbuf data (0x%x) not as expected (0x%x)",
703 					__LINE__, value, tmp_src_buf[i]);
704 				status = TEST_FAILED;
705 				goto error_exit;
706 			}
707 		}
708 
709 		mbuf = sym_op->m_dst;
710 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
711 			head_unchanged_len = hdroom + sym_op->auth.data.offset;
712 			changed_len = sym_op->auth.data.length;
713 			if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
714 				changed_len += digest_len;
715 		} else {
716 			/* cipher-only */
717 			head_unchanged_len = hdroom +
718 					sym_op->cipher.data.offset;
719 			changed_len = sym_op->cipher.data.length;
720 		}
721 
722 		if (t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED)
723 			changed_len = sym_op->cipher.data.length +
724 				digest_len + pad_len;
725 
726 		for (i = 0; i < mbuf->buf_len; i++) {
727 			if (i == head_unchanged_len)
728 				i += changed_len;
729 			value = *((uint8_t *)(mbuf->buf_addr)+i);
730 			if (value != tmp_dst_buf[i]) {
731 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
732 				"line %u FAILED: OOP dst outer mbuf data "
733 				"(0x%x) not as expected (0x%x)",
734 				__LINE__, value, tmp_dst_buf[i]);
735 				status = TEST_FAILED;
736 				goto error_exit;
737 			}
738 		}
739 
740 		if (!nb_iterates) {
741 			nb_iterates++;
742 			goto iterate;
743 		}
744 	} else {
745 		/* In-place operation */
746 		struct rte_mbuf *mbuf;
747 		uint8_t value;
748 		uint32_t head_unchanged_len = 0, changed_len = 0;
749 		uint32_t i;
750 		uint32_t hdroom_used = 0, tlroom_used = 0;
751 		uint32_t hdroom = 0;
752 
753 		/*
754 		 * Crypto PMDs specify the headroom & tailroom it would use
755 		 * when processing the crypto operation. PMD is free to modify
756 		 * this space, and so the verification check should skip that
757 		 * block.
758 		 */
759 		hdroom_used = dev_info.min_mbuf_headroom_req;
760 		tlroom_used = dev_info.min_mbuf_tailroom_req;
761 
762 		mbuf = sym_op->m_src;
763 
764 		/* Get headroom */
765 		hdroom = rte_pktmbuf_headroom(mbuf);
766 
767 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
768 			head_unchanged_len = hdroom +
769 					sym_op->cipher.data.offset;
770 			changed_len = sym_op->cipher.data.length;
771 		} else {
772 			/* auth-only */
773 			head_unchanged_len = hdroom +
774 					sym_op->auth.data.offset +
775 					sym_op->auth.data.length;
776 			changed_len = 0;
777 		}
778 
779 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
780 			changed_len += digest_len;
781 
782 		if (t->op_mask & BLOCKCIPHER_TEST_OP_DIGEST_ENCRYPTED)
783 			changed_len = sym_op->cipher.data.length;
784 
785 		for (i = 0; i < mbuf->buf_len; i++) {
786 
787 			/* Skip headroom used by PMD */
788 			if (i == hdroom - hdroom_used)
789 				i += hdroom_used;
790 
791 			if (i == head_unchanged_len)
792 				i += changed_len;
793 
794 			/* Skip tailroom used by PMD */
795 			if (i == (hdroom + mbuf->data_len))
796 				i += tlroom_used;
797 
798 			value = *((uint8_t *)(mbuf->buf_addr)+i);
799 			if (value != tmp_src_buf[i]) {
800 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
801 				"line %u FAILED: outer mbuf data (0x%x) "
802 				"not as expected (0x%x)",
803 				__LINE__, value, tmp_src_buf[i]);
804 				status = TEST_FAILED;
805 				goto error_exit;
806 			}
807 		}
808 	}
809 
810 	snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "PASS");
811 
812 error_exit:
813 	if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
814 		if (sess)
815 			rte_cryptodev_sym_session_free(dev_id, sess);
816 		rte_free(cipher_xform);
817 		rte_free(auth_xform);
818 	}
819 
820 	rte_crypto_op_free(op);
821 
822 	rte_pktmbuf_free(obuf);
823 
824 	rte_pktmbuf_free(ibuf);
825 
826 	return status;
827 }
828 
829 static int
830 blockcipher_test_case_run(const void *data)
831 {
832 	const struct blockcipher_test_case *tc_data = data;
833 	int status;
834 	char test_msg[BLOCKCIPHER_TEST_MSG_LEN + 1];
835 
836 	status = test_blockcipher_one_case(tc_data,
837 			p_testsuite_params->mbuf_pool,
838 			p_testsuite_params->op_mpool,
839 			p_testsuite_params->session_mpool,
840 			p_testsuite_params->valid_devs[0],
841 			test_msg);
842 	return status;
843 }
844 
845 static int
846 aes_chain_setup(void)
847 {
848 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
849 	struct rte_cryptodev_info dev_info;
850 	uint64_t feat_flags;
851 	const enum rte_crypto_cipher_algorithm ciphers[] = {
852 		RTE_CRYPTO_CIPHER_NULL,
853 		RTE_CRYPTO_CIPHER_AES_CTR,
854 		RTE_CRYPTO_CIPHER_AES_CBC
855 	};
856 	const enum rte_crypto_auth_algorithm auths[] = {
857 		RTE_CRYPTO_AUTH_NULL,
858 		RTE_CRYPTO_AUTH_SHA1_HMAC,
859 		RTE_CRYPTO_AUTH_AES_XCBC_MAC,
860 		RTE_CRYPTO_AUTH_SHA256_HMAC,
861 		RTE_CRYPTO_AUTH_SHA512_HMAC,
862 		RTE_CRYPTO_AUTH_SHA224_HMAC,
863 		RTE_CRYPTO_AUTH_SHA384_HMAC
864 	};
865 
866 	rte_cryptodev_info_get(dev_id, &dev_info);
867 	feat_flags = dev_info.feature_flags;
868 
869 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
870 			((global_api_test_type == CRYPTODEV_RAW_API_TEST) &&
871 			!(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) {
872 		RTE_LOG(INFO, USER1, "Feature flag requirements for AES Chain "
873 				"testsuite not met\n");
874 		return TEST_SKIPPED;
875 	}
876 
877 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0
878 			&& check_auth_capabilities_supported(auths,
879 			RTE_DIM(auths)) != 0) {
880 		RTE_LOG(INFO, USER1, "Capability requirements for AES Chain "
881 				"testsuite not met\n");
882 		return TEST_SKIPPED;
883 	}
884 
885 	return 0;
886 }
887 
888 static int
889 aes_cipheronly_setup(void)
890 {
891 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
892 	struct rte_cryptodev_info dev_info;
893 	uint64_t feat_flags;
894 	const enum rte_crypto_cipher_algorithm ciphers[] = {
895 		RTE_CRYPTO_CIPHER_NULL,
896 		RTE_CRYPTO_CIPHER_AES_CTR,
897 		RTE_CRYPTO_CIPHER_AES_CBC,
898 		RTE_CRYPTO_CIPHER_AES_ECB,
899 		RTE_CRYPTO_CIPHER_AES_XTS
900 	};
901 	const enum rte_crypto_auth_algorithm auths[] = {
902 		RTE_CRYPTO_AUTH_NULL,
903 		RTE_CRYPTO_AUTH_SHA1_HMAC,
904 		RTE_CRYPTO_AUTH_AES_XCBC_MAC
905 	};
906 
907 	rte_cryptodev_info_get(dev_id, &dev_info);
908 	feat_flags = dev_info.feature_flags;
909 
910 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
911 			((global_api_test_type == CRYPTODEV_RAW_API_TEST) &&
912 			!(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) {
913 		RTE_LOG(INFO, USER1, "Feature flag requirements for AES Cipheronly "
914 				"testsuite not met\n");
915 		return TEST_SKIPPED;
916 	}
917 
918 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0
919 			&& check_auth_capabilities_supported(auths,
920 			RTE_DIM(auths)) != 0) {
921 		RTE_LOG(INFO, USER1, "Capability requirements for AES Cipheronly "
922 				"testsuite not met\n");
923 		return TEST_SKIPPED;
924 	}
925 
926 	return 0;
927 }
928 
929 static int
930 aes_docsis_setup(void)
931 {
932 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
933 	struct rte_cryptodev_info dev_info;
934 	uint64_t feat_flags;
935 	const enum rte_crypto_cipher_algorithm ciphers[] = {
936 		RTE_CRYPTO_CIPHER_AES_DOCSISBPI
937 	};
938 
939 	rte_cryptodev_info_get(dev_id, &dev_info);
940 	feat_flags = dev_info.feature_flags;
941 
942 	/* Data-path service does not support DOCSIS yet */
943 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
944 			(global_api_test_type == CRYPTODEV_RAW_API_TEST)) {
945 		RTE_LOG(INFO, USER1, "Feature flag requirements for AES Docsis "
946 				"testsuite not met\n");
947 		return TEST_SKIPPED;
948 	}
949 
950 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0) {
951 		RTE_LOG(INFO, USER1, "Capability requirements for AES Docsis "
952 				"testsuite not met\n");
953 		return TEST_SKIPPED;
954 	}
955 
956 	return 0;
957 }
958 
959 static int
960 triple_des_chain_setup(void)
961 {
962 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
963 	struct rte_cryptodev_info dev_info;
964 	uint64_t feat_flags;
965 	const enum rte_crypto_cipher_algorithm ciphers[] = {
966 		RTE_CRYPTO_CIPHER_3DES_CTR,
967 		RTE_CRYPTO_CIPHER_3DES_CBC
968 	};
969 	const enum rte_crypto_auth_algorithm auths[] = {
970 		RTE_CRYPTO_AUTH_SHA1_HMAC,
971 		RTE_CRYPTO_AUTH_SHA1
972 	};
973 
974 	rte_cryptodev_info_get(dev_id, &dev_info);
975 	feat_flags = dev_info.feature_flags;
976 
977 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
978 			((global_api_test_type == CRYPTODEV_RAW_API_TEST) &&
979 			!(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) {
980 		RTE_LOG(INFO, USER1, "Feature flag requirements for 3DES Chain "
981 				"testsuite not met\n");
982 		return TEST_SKIPPED;
983 	}
984 
985 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0
986 			&& check_auth_capabilities_supported(auths,
987 			RTE_DIM(auths)) != 0) {
988 		RTE_LOG(INFO, USER1, "Capability requirements for 3DES Chain "
989 				"testsuite not met\n");
990 		return TEST_SKIPPED;
991 	}
992 
993 	return 0;
994 }
995 
996 static int
997 triple_des_cipheronly_setup(void)
998 {
999 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
1000 	struct rte_cryptodev_info dev_info;
1001 	uint64_t feat_flags;
1002 	const enum rte_crypto_cipher_algorithm ciphers[] = {
1003 		RTE_CRYPTO_CIPHER_3DES_CTR,
1004 		RTE_CRYPTO_CIPHER_3DES_CBC
1005 	};
1006 
1007 	rte_cryptodev_info_get(dev_id, &dev_info);
1008 	feat_flags = dev_info.feature_flags;
1009 
1010 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
1011 			((global_api_test_type == CRYPTODEV_RAW_API_TEST) &&
1012 			!(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) {
1013 		RTE_LOG(INFO, USER1, "Feature flag requirements for 3DES "
1014 				"Cipheronly testsuite not met\n");
1015 		return TEST_SKIPPED;
1016 	}
1017 
1018 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0) {
1019 		RTE_LOG(INFO, USER1, "Capability requirements for 3DES "
1020 				"Cipheronly testsuite not met\n");
1021 		return TEST_SKIPPED;
1022 	}
1023 
1024 	return 0;
1025 }
1026 
1027 static int
1028 des_cipheronly_setup(void)
1029 {
1030 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
1031 	struct rte_cryptodev_info dev_info;
1032 	uint64_t feat_flags;
1033 	const enum rte_crypto_cipher_algorithm ciphers[] = {
1034 		RTE_CRYPTO_CIPHER_DES_CBC
1035 	};
1036 
1037 	rte_cryptodev_info_get(dev_id, &dev_info);
1038 	feat_flags = dev_info.feature_flags;
1039 
1040 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
1041 			((global_api_test_type == CRYPTODEV_RAW_API_TEST) &&
1042 			!(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) {
1043 		RTE_LOG(INFO, USER1, "Feature flag requirements for DES "
1044 				"Cipheronly testsuite not met\n");
1045 		return TEST_SKIPPED;
1046 	}
1047 
1048 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0) {
1049 		RTE_LOG(INFO, USER1, "Capability requirements for DES "
1050 				"Cipheronly testsuite not met\n");
1051 		return TEST_SKIPPED;
1052 	}
1053 
1054 	return 0;
1055 }
1056 
1057 static int
1058 des_docsis_setup(void)
1059 {
1060 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
1061 	struct rte_cryptodev_info dev_info;
1062 	uint64_t feat_flags;
1063 	const enum rte_crypto_cipher_algorithm ciphers[] = {
1064 		RTE_CRYPTO_CIPHER_DES_DOCSISBPI
1065 	};
1066 
1067 	rte_cryptodev_info_get(dev_id, &dev_info);
1068 	feat_flags = dev_info.feature_flags;
1069 
1070 	/* Data-path service does not support DOCSIS yet */
1071 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
1072 			(global_api_test_type == CRYPTODEV_RAW_API_TEST)) {
1073 		RTE_LOG(INFO, USER1, "Feature flag requirements for DES Docsis "
1074 				"testsuite not met\n");
1075 		return TEST_SKIPPED;
1076 	}
1077 
1078 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0) {
1079 		RTE_LOG(INFO, USER1, "Capability requirements for DES Docsis "
1080 				"testsuite not met\n");
1081 		return TEST_SKIPPED;
1082 	}
1083 
1084 	return 0;
1085 }
1086 
1087 static int
1088 authonly_setup(void)
1089 {
1090 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
1091 	struct rte_cryptodev_info dev_info;
1092 	uint64_t feat_flags;
1093 	const enum rte_crypto_auth_algorithm auths[] = {
1094 		RTE_CRYPTO_AUTH_MD5,
1095 		RTE_CRYPTO_AUTH_MD5_HMAC,
1096 		RTE_CRYPTO_AUTH_SHA1,
1097 		RTE_CRYPTO_AUTH_SHA1_HMAC,
1098 		RTE_CRYPTO_AUTH_SHA224,
1099 		RTE_CRYPTO_AUTH_SHA224_HMAC,
1100 		RTE_CRYPTO_AUTH_SHA256,
1101 		RTE_CRYPTO_AUTH_SHA256_HMAC,
1102 		RTE_CRYPTO_AUTH_SHA384,
1103 		RTE_CRYPTO_AUTH_SHA384_HMAC,
1104 		RTE_CRYPTO_AUTH_SHA512,
1105 		RTE_CRYPTO_AUTH_SHA512_HMAC,
1106 		RTE_CRYPTO_AUTH_AES_CMAC,
1107 		RTE_CRYPTO_AUTH_NULL,
1108 		RTE_CRYPTO_AUTH_AES_XCBC_MAC
1109 	};
1110 
1111 	rte_cryptodev_info_get(dev_id, &dev_info);
1112 	feat_flags = dev_info.feature_flags;
1113 
1114 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
1115 			((global_api_test_type == CRYPTODEV_RAW_API_TEST) &&
1116 			!(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) {
1117 		RTE_LOG(INFO, USER1, "Feature flag requirements for Auth Only "
1118 				"testsuite not met\n");
1119 		return TEST_SKIPPED;
1120 	}
1121 
1122 	if (check_auth_capabilities_supported(auths, RTE_DIM(auths)) != 0) {
1123 		RTE_LOG(INFO, USER1, "Capability requirements for Auth Only "
1124 				"testsuite not met\n");
1125 		return TEST_SKIPPED;
1126 	}
1127 
1128 	return 0;
1129 }
1130 
1131 static int
1132 sm4_chain_setup(void)
1133 {
1134 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
1135 	struct rte_cryptodev_info dev_info;
1136 	uint64_t feat_flags;
1137 	const enum rte_crypto_cipher_algorithm ciphers[] = {
1138 		RTE_CRYPTO_CIPHER_SM4_CTR,
1139 		RTE_CRYPTO_CIPHER_SM4_CBC,
1140 		RTE_CRYPTO_CIPHER_SM4_OFB,
1141 		RTE_CRYPTO_CIPHER_SM4_CFB
1142 	};
1143 	const enum rte_crypto_auth_algorithm auths[] = {
1144 		RTE_CRYPTO_AUTH_SM3,
1145 		RTE_CRYPTO_AUTH_SM3_HMAC,
1146 	};
1147 
1148 	rte_cryptodev_info_get(dev_id, &dev_info);
1149 	feat_flags = dev_info.feature_flags;
1150 
1151 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
1152 	    (global_api_test_type == CRYPTODEV_RAW_API_TEST &&
1153 	    !(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) {
1154 		RTE_LOG(INFO, USER1, "Feature flag for SM4 Chain testsuite not met\n");
1155 		return TEST_SKIPPED;
1156 	}
1157 
1158 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0 &&
1159 	    check_auth_capabilities_supported(auths, RTE_DIM(auths)) != 0) {
1160 		RTE_LOG(INFO, USER1, "Capability for SM4 Chain testsuite not met\n");
1161 		return TEST_SKIPPED;
1162 	}
1163 
1164 	return 0;
1165 }
1166 
1167 static int
1168 sm4_cipheronly_setup(void)
1169 {
1170 	uint8_t dev_id = p_testsuite_params->valid_devs[0];
1171 	struct rte_cryptodev_info dev_info;
1172 	uint64_t feat_flags;
1173 	const enum rte_crypto_cipher_algorithm ciphers[] = {
1174 		RTE_CRYPTO_CIPHER_SM4_CBC,
1175 		RTE_CRYPTO_CIPHER_SM4_ECB,
1176 		RTE_CRYPTO_CIPHER_SM4_CTR,
1177 		RTE_CRYPTO_CIPHER_SM4_OFB,
1178 		RTE_CRYPTO_CIPHER_SM4_CFB,
1179 		RTE_CRYPTO_CIPHER_SM4_XTS
1180 	};
1181 
1182 	rte_cryptodev_info_get(dev_id, &dev_info);
1183 	feat_flags = dev_info.feature_flags;
1184 
1185 	if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ||
1186 	    (global_api_test_type == CRYPTODEV_RAW_API_TEST &&
1187 	    !(feat_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) {
1188 		RTE_LOG(INFO, USER1, "Feature flag for SM4 Cipheronly not met\n");
1189 		return TEST_SKIPPED;
1190 	}
1191 
1192 	if (check_cipher_capabilities_supported(ciphers, RTE_DIM(ciphers)) != 0) {
1193 		RTE_LOG(INFO, USER1, "Capability for SM4 Cipheronly not met\n");
1194 		return TEST_SKIPPED;
1195 	}
1196 
1197 	return 0;
1198 }
1199 
1200 struct unit_test_suite *
1201 build_blockcipher_test_suite(enum blockcipher_test_type test_type)
1202 {
1203 	int i, n_test_cases = 0;
1204 	struct unit_test_suite *ts;
1205 	const char *ts_name = NULL;
1206 	const struct blockcipher_test_case *blk_tcs;
1207 	struct unit_test_case *tc;
1208 	int (*ts_setup)(void) = NULL;
1209 
1210 	switch (test_type) {
1211 	case BLKCIPHER_AES_CHAIN_TYPE:
1212 		n_test_cases = RTE_DIM(aes_chain_test_cases);
1213 		blk_tcs = aes_chain_test_cases;
1214 		ts_name = "AES Chain";
1215 		ts_setup = aes_chain_setup;
1216 		break;
1217 	case BLKCIPHER_AES_CIPHERONLY_TYPE:
1218 		n_test_cases = RTE_DIM(aes_cipheronly_test_cases);
1219 		blk_tcs = aes_cipheronly_test_cases;
1220 		ts_name = "AES Cipher Only";
1221 		ts_setup = aes_cipheronly_setup;
1222 		break;
1223 	case BLKCIPHER_AES_DOCSIS_TYPE:
1224 		n_test_cases = RTE_DIM(aes_docsis_test_cases);
1225 		blk_tcs = aes_docsis_test_cases;
1226 		ts_name = "AES Docsis";
1227 		ts_setup = aes_docsis_setup;
1228 		break;
1229 	case BLKCIPHER_3DES_CHAIN_TYPE:
1230 		n_test_cases = RTE_DIM(triple_des_chain_test_cases);
1231 		blk_tcs = triple_des_chain_test_cases;
1232 		ts_name = "3DES Chain";
1233 		ts_setup = triple_des_chain_setup;
1234 		break;
1235 	case BLKCIPHER_3DES_CIPHERONLY_TYPE:
1236 		n_test_cases = RTE_DIM(triple_des_cipheronly_test_cases);
1237 		blk_tcs = triple_des_cipheronly_test_cases;
1238 		ts_name = "3DES Cipher Only";
1239 		ts_setup = triple_des_cipheronly_setup;
1240 		break;
1241 	case BLKCIPHER_DES_CIPHERONLY_TYPE:
1242 		n_test_cases = RTE_DIM(des_cipheronly_test_cases);
1243 		blk_tcs = des_cipheronly_test_cases;
1244 		ts_name = "DES Cipher Only";
1245 		ts_setup = des_cipheronly_setup;
1246 		break;
1247 	case BLKCIPHER_DES_DOCSIS_TYPE:
1248 		n_test_cases = RTE_DIM(des_docsis_test_cases);
1249 		blk_tcs = des_docsis_test_cases;
1250 		ts_name = "DES Docsis";
1251 		ts_setup = des_docsis_setup;
1252 		break;
1253 	case BLKCIPHER_SM4_CHAIN_TYPE:
1254 		n_test_cases = RTE_DIM(sm4_chain_test_cases);
1255 		blk_tcs = sm4_chain_test_cases;
1256 		ts_name = "SM4 Chain";
1257 		ts_setup = sm4_chain_setup;
1258 		break;
1259 	case BLKCIPHER_SM4_CIPHERONLY_TYPE:
1260 		n_test_cases = RTE_DIM(sm4_cipheronly_test_cases);
1261 		blk_tcs = sm4_cipheronly_test_cases;
1262 		ts_name = "SM4 Cipher Only";
1263 		ts_setup = sm4_cipheronly_setup;
1264 		break;
1265 	case BLKCIPHER_AUTHONLY_TYPE:
1266 		n_test_cases = RTE_DIM(hash_test_cases);
1267 		blk_tcs = hash_test_cases;
1268 		ts_name = "Auth Only";
1269 		ts_setup = authonly_setup;
1270 		break;
1271 	default:
1272 		return NULL;
1273 	}
1274 
1275 	ts = calloc(1, sizeof(struct unit_test_suite) +
1276 			(sizeof(struct unit_test_case) * (n_test_cases + 1)));
1277 	ts->suite_name = ts_name;
1278 	ts->setup = ts_setup;
1279 
1280 	for (i = 0; i < n_test_cases; i++) {
1281 		tc = &ts->unit_test_cases[i];
1282 		tc->name = blk_tcs[i].test_descr;
1283 		tc->enabled = 1;
1284 		tc->setup = ut_setup;
1285 		tc->teardown = ut_teardown;
1286 		tc->testcase = NULL;
1287 		tc->testcase_with_data = blockcipher_test_case_run;
1288 		tc->data = &blk_tcs[i];
1289 	}
1290 	tc = &ts->unit_test_cases[i];
1291 	tc->name = NULL;
1292 	tc->enabled = 0;
1293 	tc->setup = NULL;
1294 	tc->teardown = NULL;
1295 	tc->testcase = NULL;
1296 	tc->testcase_with_data = NULL;
1297 	tc->data = NULL;
1298 
1299 	return ts;
1300 }
1301 
1302 void
1303 free_blockcipher_test_suite(struct unit_test_suite *ts)
1304 {
1305 	free(ts);
1306 }
1307