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