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