1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2017 Intel Corporation
3  */
4 
5 #include <rte_common.h>
6 #include <rte_hexdump.h>
7 #include <rte_mbuf.h>
8 #include <rte_malloc.h>
9 #include <rte_memcpy.h>
10 #include <rte_pause.h>
11 
12 #include <rte_crypto.h>
13 #include <rte_cryptodev.h>
14 #include <rte_cryptodev_pmd.h>
15 
16 #include "test.h"
17 #include "test_cryptodev.h"
18 #include "test_cryptodev_blockcipher.h"
19 #include "test_cryptodev_aes_test_vectors.h"
20 #include "test_cryptodev_des_test_vectors.h"
21 #include "test_cryptodev_hash_test_vectors.h"
22 
23 static int
24 verify_algo_support(const struct blockcipher_test_case *t,
25 		const uint8_t dev_id, const uint32_t digest_len)
26 {
27 	int ret = 0;
28 	const struct blockcipher_test_data *tdata = t->test_data;
29 	struct rte_cryptodev_sym_capability_idx cap_idx;
30 	const struct rte_cryptodev_symmetric_capability *capability;
31 
32 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
33 		cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
34 		cap_idx.algo.cipher = tdata->crypto_algo;
35 		capability = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
36 		if (capability == NULL)
37 			return -1;
38 
39 		if (cap_idx.algo.cipher != RTE_CRYPTO_CIPHER_NULL)
40 			ret = rte_cryptodev_sym_capability_check_cipher(capability,
41 							tdata->cipher_key.len,
42 							tdata->iv.len);
43 		if (ret != 0)
44 			return -1;
45 	}
46 
47 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
48 		cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
49 		cap_idx.algo.auth = tdata->auth_algo;
50 		capability = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
51 		if (capability == NULL)
52 			return -1;
53 
54 		if (cap_idx.algo.auth != RTE_CRYPTO_AUTH_NULL)
55 			ret = rte_cryptodev_sym_capability_check_auth(capability,
56 							tdata->auth_key.len,
57 							digest_len,
58 							0);
59 		if (ret != 0)
60 			return -1;
61 	}
62 
63 	return 0;
64 }
65 
66 static int
67 test_blockcipher_one_case(const struct blockcipher_test_case *t,
68 	struct rte_mempool *mbuf_pool,
69 	struct rte_mempool *op_mpool,
70 	struct rte_mempool *sess_mpool,
71 	struct rte_mempool *sess_priv_mpool,
72 	uint8_t dev_id,
73 	char *test_msg)
74 {
75 	struct rte_mbuf *ibuf = NULL;
76 	struct rte_mbuf *obuf = NULL;
77 	struct rte_mbuf *iobuf;
78 	struct rte_crypto_sym_xform *cipher_xform = NULL;
79 	struct rte_crypto_sym_xform *auth_xform = NULL;
80 	struct rte_crypto_sym_xform *init_xform = NULL;
81 	struct rte_crypto_sym_op *sym_op = NULL;
82 	struct rte_crypto_op *op = NULL;
83 	struct rte_cryptodev_info dev_info;
84 	struct rte_cryptodev_sym_session *sess = NULL;
85 
86 	int status = TEST_SUCCESS;
87 	const struct blockcipher_test_data *tdata = t->test_data;
88 	uint8_t cipher_key[tdata->cipher_key.len];
89 	uint8_t auth_key[tdata->auth_key.len];
90 	uint32_t buf_len = tdata->ciphertext.len;
91 	uint32_t digest_len = tdata->digest.len;
92 	char *buf_p = NULL;
93 	uint8_t src_pattern = 0xa5;
94 	uint8_t dst_pattern = 0xb6;
95 	uint8_t tmp_src_buf[MBUF_SIZE];
96 	uint8_t tmp_dst_buf[MBUF_SIZE];
97 
98 	int nb_segs = 1;
99 	uint32_t nb_iterates = 0;
100 
101 	rte_cryptodev_info_get(dev_id, &dev_info);
102 	uint64_t feat_flags = dev_info.feature_flags;
103 
104 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
105 		if (!(feat_flags & RTE_CRYPTODEV_FF_SYM_SESSIONLESS)) {
106 			printf("Device doesn't support sesionless operations "
107 				"Test Skipped.\n");
108 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
109 				"SKIPPED");
110 			return 0;
111 		}
112 	}
113 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
114 		uint64_t oop_flag = RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT;
115 
116 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
117 			if (!(feat_flags & oop_flag)) {
118 				printf("Device doesn't support out-of-place "
119 					"scatter-gather in input mbuf. "
120 					"Test Skipped.\n");
121 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
122 					"SKIPPED");
123 				return 0;
124 			}
125 		} else {
126 			if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
127 				printf("Device doesn't support in-place "
128 					"scatter-gather mbufs. "
129 					"Test Skipped.\n");
130 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
131 					"SKIPPED");
132 				return 0;
133 			}
134 		}
135 
136 		nb_segs = 3;
137 	}
138 
139 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
140 		uint64_t oop_flags = RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
141 			RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
142 			RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
143 			RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT;
144 		if (!(feat_flags & oop_flags)) {
145 			printf("Device doesn't support out-of-place operations."
146 				"Test Skipped.\n");
147 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
148 				"SKIPPED");
149 			return 0;
150 		}
151 	}
152 
153 	if (tdata->cipher_key.len)
154 		memcpy(cipher_key, tdata->cipher_key.data,
155 			tdata->cipher_key.len);
156 	if (tdata->auth_key.len)
157 		memcpy(auth_key, tdata->auth_key.data,
158 			tdata->auth_key.len);
159 
160 	/* Check if PMD is capable of performing that test */
161 	if (verify_algo_support(t, dev_id, digest_len) < 0) {
162 		RTE_LOG(DEBUG, USER1,
163 			"Device does not support this algorithm."
164 			"Test Skipped.\n");
165 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "SKIPPED");
166 		return 0;
167 	}
168 
169 	/* preparing data */
170 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
171 		buf_len += digest_len;
172 
173 	/* for contiguous mbuf, nb_segs is 1 */
174 	ibuf = create_segmented_mbuf(mbuf_pool,
175 			tdata->ciphertext.len, nb_segs, src_pattern);
176 	if (ibuf == NULL) {
177 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
178 			"line %u FAILED: %s",
179 			__LINE__, "Cannot create source mbuf");
180 		status = TEST_FAILED;
181 		goto error_exit;
182 	}
183 
184 	/* only encryption requires plaintext.data input,
185 	 * decryption/(digest gen)/(digest verify) use ciphertext.data
186 	 * to be computed
187 	 */
188 	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
189 		pktmbuf_write(ibuf, 0, tdata->plaintext.len,
190 				tdata->plaintext.data);
191 	else
192 		pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
193 				tdata->ciphertext.data);
194 
195 	buf_p = rte_pktmbuf_append(ibuf, digest_len);
196 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
197 		rte_memcpy(buf_p, tdata->digest.data, digest_len);
198 	else
199 		memset(buf_p, 0, digest_len);
200 
201 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
202 		obuf = rte_pktmbuf_alloc(mbuf_pool);
203 		if (!obuf) {
204 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
205 				"FAILED: %s", __LINE__,
206 				"Allocation of rte_mbuf failed");
207 			status = TEST_FAILED;
208 			goto error_exit;
209 		}
210 		memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
211 
212 		buf_p = rte_pktmbuf_append(obuf, buf_len);
213 		if (!buf_p) {
214 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
215 				"FAILED: %s", __LINE__,
216 				"No room to append mbuf");
217 			status = TEST_FAILED;
218 			goto error_exit;
219 		}
220 		memset(buf_p, 0, buf_len);
221 	}
222 
223 	/* Generate Crypto op data structure */
224 	op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
225 	if (!op) {
226 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
227 			"line %u FAILED: %s",
228 			__LINE__, "Failed to allocate symmetric crypto "
229 			"operation struct");
230 		status = TEST_FAILED;
231 		goto error_exit;
232 	}
233 
234 	sym_op = op->sym;
235 
236 iterate:
237 	if (nb_iterates) {
238 		struct rte_mbuf *tmp_buf = ibuf;
239 
240 		ibuf = obuf;
241 		obuf = tmp_buf;
242 
243 		rte_pktmbuf_reset(ibuf);
244 		rte_pktmbuf_reset(obuf);
245 
246 		rte_pktmbuf_append(ibuf, tdata->ciphertext.len);
247 
248 		/* only encryption requires plaintext.data input,
249 		 * decryption/(digest gen)/(digest verify) use ciphertext.data
250 		 * to be computed
251 		 */
252 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
253 			pktmbuf_write(ibuf, 0, tdata->plaintext.len,
254 					tdata->plaintext.data);
255 		else
256 			pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
257 					tdata->ciphertext.data);
258 
259 		buf_p = rte_pktmbuf_append(ibuf, digest_len);
260 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
261 			rte_memcpy(buf_p, tdata->digest.data, digest_len);
262 		else
263 			memset(buf_p, 0, digest_len);
264 
265 		memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
266 
267 		buf_p = rte_pktmbuf_append(obuf, buf_len);
268 		if (!buf_p) {
269 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
270 				"FAILED: %s", __LINE__,
271 				"No room to append mbuf");
272 			status = TEST_FAILED;
273 			goto error_exit;
274 		}
275 		memset(buf_p, 0, buf_len);
276 	}
277 
278 	sym_op->m_src = ibuf;
279 
280 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
281 		sym_op->m_dst = obuf;
282 		iobuf = obuf;
283 	} else {
284 		sym_op->m_dst = NULL;
285 		iobuf = ibuf;
286 	}
287 
288 	/* sessionless op requires allocate xform using
289 	 * rte_crypto_op_sym_xforms_alloc(), otherwise rte_zmalloc()
290 	 * is used
291 	 */
292 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
293 		uint32_t n_xforms = 0;
294 
295 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
296 			n_xforms++;
297 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
298 			n_xforms++;
299 
300 		if (rte_crypto_op_sym_xforms_alloc(op, n_xforms)
301 			== NULL) {
302 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
303 				"FAILED: %s", __LINE__, "Failed to "
304 				"allocate space for crypto transforms");
305 			status = TEST_FAILED;
306 			goto error_exit;
307 		}
308 	} else {
309 		cipher_xform = rte_zmalloc(NULL,
310 			sizeof(struct rte_crypto_sym_xform), 0);
311 
312 		auth_xform = rte_zmalloc(NULL,
313 			sizeof(struct rte_crypto_sym_xform), 0);
314 
315 		if (!cipher_xform || !auth_xform) {
316 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
317 				"FAILED: %s", __LINE__, "Failed to "
318 				"allocate memory for crypto transforms");
319 			status = TEST_FAILED;
320 			goto error_exit;
321 		}
322 	}
323 
324 	/* preparing xform, for sessioned op, init_xform is initialized
325 	 * here and later as param in rte_cryptodev_sym_session_create() call
326 	 */
327 	if (t->op_mask == BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN) {
328 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
329 			cipher_xform = op->sym->xform;
330 			auth_xform = cipher_xform->next;
331 			auth_xform->next = NULL;
332 		} else {
333 			cipher_xform->next = auth_xform;
334 			auth_xform->next = NULL;
335 			init_xform = cipher_xform;
336 		}
337 	} else if (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC) {
338 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
339 			auth_xform = op->sym->xform;
340 			cipher_xform = auth_xform->next;
341 			cipher_xform->next = NULL;
342 		} else {
343 			auth_xform->next = cipher_xform;
344 			cipher_xform->next = NULL;
345 			init_xform = auth_xform;
346 		}
347 	} else if ((t->op_mask == BLOCKCIPHER_TEST_OP_ENCRYPT) ||
348 			(t->op_mask == BLOCKCIPHER_TEST_OP_DECRYPT)) {
349 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
350 			cipher_xform = op->sym->xform;
351 		else
352 			init_xform = cipher_xform;
353 		cipher_xform->next = NULL;
354 	} else if ((t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_GEN) ||
355 			(t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY)) {
356 		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
357 			auth_xform = op->sym->xform;
358 		else
359 			init_xform = auth_xform;
360 		auth_xform->next = NULL;
361 	} else {
362 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
363 			"line %u FAILED: %s",
364 			__LINE__, "Unrecognized operation");
365 		status = TEST_FAILED;
366 		goto error_exit;
367 	}
368 
369 	/*configure xforms & sym_op cipher and auth data*/
370 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
371 		cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
372 		cipher_xform->cipher.algo = tdata->crypto_algo;
373 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
374 			cipher_xform->cipher.op =
375 				RTE_CRYPTO_CIPHER_OP_ENCRYPT;
376 		else
377 			cipher_xform->cipher.op =
378 				RTE_CRYPTO_CIPHER_OP_DECRYPT;
379 		cipher_xform->cipher.key.data = cipher_key;
380 		cipher_xform->cipher.key.length = tdata->cipher_key.len;
381 		cipher_xform->cipher.iv.offset = IV_OFFSET;
382 
383 		if (tdata->crypto_algo == RTE_CRYPTO_CIPHER_NULL)
384 			cipher_xform->cipher.iv.length = 0;
385 		else
386 			cipher_xform->cipher.iv.length = tdata->iv.len;
387 
388 		sym_op->cipher.data.offset = tdata->cipher_offset;
389 		sym_op->cipher.data.length = tdata->ciphertext.len -
390 				tdata->cipher_offset;
391 		rte_memcpy(rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET),
392 				tdata->iv.data,
393 				tdata->iv.len);
394 	}
395 
396 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
397 		uint32_t digest_offset = tdata->ciphertext.len;
398 
399 		auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
400 		auth_xform->auth.algo = tdata->auth_algo;
401 		auth_xform->auth.key.length = tdata->auth_key.len;
402 		auth_xform->auth.key.data = auth_key;
403 		auth_xform->auth.digest_length = digest_len;
404 
405 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
406 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
407 			sym_op->auth.digest.data = pktmbuf_mtod_offset
408 				(iobuf, digest_offset);
409 			sym_op->auth.digest.phys_addr =
410 				pktmbuf_iova_offset(iobuf,
411 					digest_offset);
412 		} else {
413 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
414 			sym_op->auth.digest.data = pktmbuf_mtod_offset
415 				(sym_op->m_src, digest_offset);
416 			sym_op->auth.digest.phys_addr =
417 				pktmbuf_iova_offset(sym_op->m_src,
418 					digest_offset);
419 		}
420 
421 		sym_op->auth.data.offset = tdata->auth_offset;
422 		sym_op->auth.data.length = tdata->ciphertext.len -
423 				tdata->auth_offset;
424 	}
425 
426 	/**
427 	 * Create session for sessioned op. For mbuf iteration test,
428 	 * skip the session creation for the second iteration.
429 	 */
430 	if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) &&
431 			nb_iterates == 0) {
432 		sess = rte_cryptodev_sym_session_create(sess_mpool);
433 
434 		rte_cryptodev_sym_session_init(dev_id, sess, init_xform,
435 				sess_priv_mpool);
436 		if (!sess) {
437 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
438 				"FAILED: %s", __LINE__,
439 				"Session creation failed");
440 			status = TEST_FAILED;
441 			goto error_exit;
442 		}
443 
444 		/* attach symmetric crypto session to crypto operations */
445 		rte_crypto_op_attach_sym_session(op, sess);
446 	}
447 
448 	debug_hexdump(stdout, "m_src(before):",
449 			sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
450 	rte_memcpy(tmp_src_buf, sym_op->m_src->buf_addr,
451 						sym_op->m_src->buf_len);
452 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
453 		debug_hexdump(stdout, "m_dst(before):",
454 			sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
455 		rte_memcpy(tmp_dst_buf, sym_op->m_dst->buf_addr,
456 						sym_op->m_dst->buf_len);
457 	}
458 
459 	/* Process crypto operation */
460 	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
461 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
462 			"line %u FAILED: %s",
463 			__LINE__, "Error sending packet for encryption");
464 		status = TEST_FAILED;
465 		goto error_exit;
466 	}
467 
468 	op = NULL;
469 
470 	while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
471 		rte_pause();
472 
473 	if (!op) {
474 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
475 			"line %u FAILED: %s",
476 			__LINE__, "Failed to process sym crypto op");
477 		status = TEST_FAILED;
478 		goto error_exit;
479 	}
480 
481 	debug_hexdump(stdout, "m_src(after):",
482 			sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
483 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
484 		debug_hexdump(stdout, "m_dst(after):",
485 			sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
486 
487 	/* Verify results */
488 	if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
489 		if ((t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY) &&
490 			(op->status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED))
491 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
492 				"FAILED: Digest verification failed "
493 				"(0x%X)", __LINE__, op->status);
494 		else
495 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
496 				"FAILED: Operation failed "
497 				"(0x%X)", __LINE__, op->status);
498 		status = TEST_FAILED;
499 		goto error_exit;
500 	}
501 
502 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
503 		uint8_t buffer[2048];
504 		const uint8_t *compare_ref;
505 		uint32_t compare_len;
506 
507 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
508 			compare_ref = tdata->ciphertext.data +
509 					tdata->cipher_offset;
510 			compare_len = tdata->ciphertext.len -
511 					tdata->cipher_offset;
512 		} else {
513 			compare_ref = tdata->plaintext.data +
514 					tdata->cipher_offset;
515 			compare_len = tdata->plaintext.len -
516 					tdata->cipher_offset;
517 		}
518 
519 		if (memcmp(rte_pktmbuf_read(iobuf, tdata->cipher_offset,
520 				compare_len, buffer), compare_ref,
521 				compare_len)) {
522 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
523 				"FAILED: %s", __LINE__,
524 				"Crypto data not as expected");
525 			status = TEST_FAILED;
526 			goto error_exit;
527 		}
528 	}
529 
530 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
531 		uint8_t *auth_res = pktmbuf_mtod_offset(iobuf,
532 					tdata->ciphertext.len);
533 
534 		if (memcmp(auth_res, tdata->digest.data, digest_len)) {
535 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
536 				"FAILED: %s", __LINE__, "Generated "
537 				"digest data not as expected");
538 			status = TEST_FAILED;
539 			goto error_exit;
540 		}
541 	}
542 
543 	/* The only parts that should have changed in the buffer are
544 	 * plaintext/ciphertext and digest.
545 	 * In OOP only the dest buffer should change.
546 	 */
547 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
548 		struct rte_mbuf *mbuf;
549 		uint8_t value;
550 		uint32_t head_unchanged_len, changed_len = 0;
551 		uint32_t i;
552 		uint32_t hdroom_used = 0, tlroom_used = 0;
553 		uint32_t hdroom = 0;
554 
555 		mbuf = sym_op->m_src;
556 		/*
557 		 * Crypto PMDs specify the headroom & tailroom it would use
558 		 * when processing the crypto operation. PMD is free to modify
559 		 * this space, and so the verification check should skip that
560 		 * block.
561 		 */
562 		hdroom_used = dev_info.min_mbuf_headroom_req;
563 		tlroom_used = dev_info.min_mbuf_tailroom_req;
564 
565 		/* Get headroom */
566 		hdroom = rte_pktmbuf_headroom(mbuf);
567 
568 		head_unchanged_len = mbuf->buf_len;
569 
570 		for (i = 0; i < mbuf->buf_len; i++) {
571 
572 			/* Skip headroom used by PMD */
573 			if (i == hdroom - hdroom_used)
574 				i += hdroom_used;
575 
576 			/* Skip tailroom used by PMD */
577 			if (i == (hdroom + mbuf->data_len))
578 				i += tlroom_used;
579 
580 			value = *((uint8_t *)(mbuf->buf_addr)+i);
581 			if (value != tmp_src_buf[i]) {
582 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
583 	"line %u FAILED: OOP src outer mbuf data (0x%x) not as expected (0x%x)",
584 					__LINE__, value, tmp_src_buf[i]);
585 				status = TEST_FAILED;
586 				goto error_exit;
587 			}
588 		}
589 
590 		mbuf = sym_op->m_dst;
591 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
592 			head_unchanged_len = hdroom + sym_op->auth.data.offset;
593 			changed_len = sym_op->auth.data.length;
594 			if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
595 				changed_len += digest_len;
596 		} else {
597 			/* cipher-only */
598 			head_unchanged_len = hdroom +
599 					sym_op->cipher.data.offset;
600 			changed_len = sym_op->cipher.data.length;
601 		}
602 
603 		for (i = 0; i < mbuf->buf_len; i++) {
604 			if (i == head_unchanged_len)
605 				i += changed_len;
606 			value = *((uint8_t *)(mbuf->buf_addr)+i);
607 			if (value != tmp_dst_buf[i]) {
608 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
609 				"line %u FAILED: OOP dst outer mbuf data "
610 				"(0x%x) not as expected (0x%x)",
611 				__LINE__, value, tmp_dst_buf[i]);
612 				status = TEST_FAILED;
613 				goto error_exit;
614 			}
615 		}
616 
617 		if (!nb_iterates) {
618 			nb_iterates++;
619 			goto iterate;
620 		}
621 	} else {
622 		/* In-place operation */
623 		struct rte_mbuf *mbuf;
624 		uint8_t value;
625 		uint32_t head_unchanged_len = 0, changed_len = 0;
626 		uint32_t i;
627 		uint32_t hdroom_used = 0, tlroom_used = 0;
628 		uint32_t hdroom = 0;
629 
630 		/*
631 		 * Crypto PMDs specify the headroom & tailroom it would use
632 		 * when processing the crypto operation. PMD is free to modify
633 		 * this space, and so the verification check should skip that
634 		 * block.
635 		 */
636 		hdroom_used = dev_info.min_mbuf_headroom_req;
637 		tlroom_used = dev_info.min_mbuf_tailroom_req;
638 
639 		mbuf = sym_op->m_src;
640 
641 		/* Get headroom */
642 		hdroom = rte_pktmbuf_headroom(mbuf);
643 
644 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
645 			head_unchanged_len = hdroom +
646 					sym_op->cipher.data.offset;
647 			changed_len = sym_op->cipher.data.length;
648 		} else {
649 			/* auth-only */
650 			head_unchanged_len = hdroom +
651 					sym_op->auth.data.offset +
652 					sym_op->auth.data.length;
653 			changed_len = 0;
654 		}
655 
656 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
657 			changed_len += digest_len;
658 
659 		for (i = 0; i < mbuf->buf_len; i++) {
660 
661 			/* Skip headroom used by PMD */
662 			if (i == hdroom - hdroom_used)
663 				i += hdroom_used;
664 
665 			if (i == head_unchanged_len)
666 				i += changed_len;
667 
668 			/* Skip tailroom used by PMD */
669 			if (i == (hdroom + mbuf->data_len))
670 				i += tlroom_used;
671 
672 			value = *((uint8_t *)(mbuf->buf_addr)+i);
673 			if (value != tmp_src_buf[i]) {
674 				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
675 				"line %u FAILED: outer mbuf data (0x%x) "
676 				"not as expected (0x%x)",
677 				__LINE__, value, tmp_src_buf[i]);
678 				status = TEST_FAILED;
679 				goto error_exit;
680 			}
681 		}
682 	}
683 
684 	snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "PASS");
685 
686 error_exit:
687 	if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
688 		if (sess) {
689 			rte_cryptodev_sym_session_clear(dev_id, sess);
690 			rte_cryptodev_sym_session_free(sess);
691 		}
692 		if (cipher_xform)
693 			rte_free(cipher_xform);
694 		if (auth_xform)
695 			rte_free(auth_xform);
696 	}
697 
698 	if (op)
699 		rte_crypto_op_free(op);
700 
701 	if (obuf)
702 		rte_pktmbuf_free(obuf);
703 
704 	if (ibuf)
705 		rte_pktmbuf_free(ibuf);
706 
707 	return status;
708 }
709 
710 int
711 test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
712 	struct rte_mempool *op_mpool,
713 	struct rte_mempool *sess_mpool,
714 	struct rte_mempool *sess_priv_mpool,
715 	uint8_t dev_id,
716 	enum blockcipher_test_type test_type)
717 {
718 	int status, overall_status = TEST_SUCCESS;
719 	uint32_t i, test_index = 0;
720 	char test_msg[BLOCKCIPHER_TEST_MSG_LEN + 1];
721 	uint32_t n_test_cases = 0;
722 	const struct blockcipher_test_case *tcs = NULL;
723 
724 	switch (test_type) {
725 	case BLKCIPHER_AES_CHAIN_TYPE:
726 		n_test_cases = sizeof(aes_chain_test_cases) /
727 		sizeof(aes_chain_test_cases[0]);
728 		tcs = aes_chain_test_cases;
729 		break;
730 	case BLKCIPHER_AES_CIPHERONLY_TYPE:
731 		n_test_cases = sizeof(aes_cipheronly_test_cases) /
732 		sizeof(aes_cipheronly_test_cases[0]);
733 		tcs = aes_cipheronly_test_cases;
734 		break;
735 	case BLKCIPHER_AES_DOCSIS_TYPE:
736 		n_test_cases = sizeof(aes_docsis_test_cases) /
737 		sizeof(aes_docsis_test_cases[0]);
738 		tcs = aes_docsis_test_cases;
739 		break;
740 	case BLKCIPHER_3DES_CHAIN_TYPE:
741 		n_test_cases = sizeof(triple_des_chain_test_cases) /
742 		sizeof(triple_des_chain_test_cases[0]);
743 		tcs = triple_des_chain_test_cases;
744 		break;
745 	case BLKCIPHER_3DES_CIPHERONLY_TYPE:
746 		n_test_cases = sizeof(triple_des_cipheronly_test_cases) /
747 		sizeof(triple_des_cipheronly_test_cases[0]);
748 		tcs = triple_des_cipheronly_test_cases;
749 		break;
750 	case BLKCIPHER_DES_CIPHERONLY_TYPE:
751 		n_test_cases = sizeof(des_cipheronly_test_cases) /
752 		sizeof(des_cipheronly_test_cases[0]);
753 		tcs = des_cipheronly_test_cases;
754 		break;
755 	case BLKCIPHER_DES_DOCSIS_TYPE:
756 		n_test_cases = sizeof(des_docsis_test_cases) /
757 		sizeof(des_docsis_test_cases[0]);
758 		tcs = des_docsis_test_cases;
759 		break;
760 	case BLKCIPHER_AUTHONLY_TYPE:
761 		n_test_cases = sizeof(hash_test_cases) /
762 		sizeof(hash_test_cases[0]);
763 		tcs = hash_test_cases;
764 		break;
765 	default:
766 		break;
767 	}
768 
769 	for (i = 0; i < n_test_cases; i++) {
770 		const struct blockcipher_test_case *tc = &tcs[i];
771 
772 		status = test_blockcipher_one_case(tc, mbuf_pool, op_mpool,
773 			sess_mpool, sess_priv_mpool, dev_id,
774 			test_msg);
775 
776 		printf("  %u) TestCase %s %s\n", test_index ++,
777 			tc->test_descr, test_msg);
778 
779 		if (status != TEST_SUCCESS) {
780 			if (overall_status == TEST_SUCCESS)
781 				overall_status = status;
782 
783 			if (tc->feature_mask & BLOCKCIPHER_TEST_FEATURE_STOPPER)
784 				break;
785 		}
786 	}
787 
788 	return overall_status;
789 }
790