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