xref: /dpdk/app/test/test_cryptodev_crosscheck.c (revision 2c0519b2cfb1f2976cefc69e2035f35512a72f34)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2023 Marvell.
3  */
4 #include <rte_cryptodev.h>
5 #include <rte_malloc.h>
6 
7 #include "test.h"
8 #include "test_cryptodev.h"
9 
10 #define MAX_NB_SESSIONS 1
11 #define MAX_TEST_STRING_LEN 256
12 
13 /*
14  * The test suite will iterate through the capabilities of each probed cryptodev to identify the
15  * common ones. Once the common capabilities are determined, the test suite will generate potential
16  * valid inputs and crosscheck (compare) the output results from all cryptodevs.
17  */
18 static struct rte_cryptodev_symmetric_capability *common_symm_capas;
19 static uint16_t nb_common_sym_caps;
20 
21 /* Policies of capabilities selection */
22 enum capability_select_type {
23 	CAPABILITY_TYPE_MIN,
24 	CAPABILITY_TYPE_MAX,
25 	CAPABILITY_TYPE_LAST,
26 };
27 
28 static const char * const capability_select_strings[] = {
29 	[CAPABILITY_TYPE_MIN] = "MIN",
30 	[CAPABILITY_TYPE_MAX] = "MAX",
31 };
32 
33 /* Length of input text to be encrypted */
34 static size_t input_length[] = { 64, 256, 512 };
35 
36 /* Calculate number of test cases(combinations) per algorithm */
37 #define NB_TEST_CASES_PER_ALGO (CAPABILITY_TYPE_LAST * RTE_DIM(input_length))
38 
39 enum crypto_op_type {
40 	OP_ENCRYPT,
41 	OP_DECRYPT,
42 };
43 
44 struct crosscheck_test_profile {
45 	char name[MAX_TEST_STRING_LEN];
46 	size_t input_buf_len;
47 	enum rte_crypto_sym_xform_type xform_type;
48 	int algo;
49 	uint16_t block_size;
50 	uint16_t key_size;
51 	uint16_t iv_size;
52 	uint16_t digest_size;
53 	uint16_t aad_size;
54 	uint32_t dataunit_set;
55 };
56 
57 struct meta_test_suite {
58 	char suite_name[MAX_TEST_STRING_LEN];
59 	struct crosscheck_test_profile profile[NB_TEST_CASES_PER_ALGO];
60 };
61 
62 struct memory_segment {
63 	uint8_t *mem;
64 	uint16_t len;
65 };
66 
67 struct crosscheck_testsuite_params {
68 	struct rte_mempool *mbuf_pool;
69 	struct rte_mempool *op_mpool;
70 	struct rte_mempool *session_mpool;
71 	struct rte_cryptodev_config conf;
72 	struct rte_cryptodev_qp_conf qp_conf;
73 
74 	uint8_t valid_devs[RTE_CRYPTO_MAX_DEVS];
75 	uint8_t valid_dev_count;
76 
77 	struct memory_segment key;
78 	struct memory_segment digest;
79 	struct memory_segment aad;
80 	struct memory_segment iv;
81 
82 	struct memory_segment expected_digest;
83 	struct memory_segment expected_aad;
84 };
85 
86 static struct crosscheck_testsuite_params testsuite_params;
87 
88 static const char*
algo_name_get(const struct rte_cryptodev_symmetric_capability * capa)89 algo_name_get(const struct rte_cryptodev_symmetric_capability *capa)
90 {
91 	switch (capa->xform_type) {
92 	case RTE_CRYPTO_SYM_XFORM_AUTH:
93 		return rte_cryptodev_get_auth_algo_string(capa->auth.algo);
94 	case RTE_CRYPTO_SYM_XFORM_CIPHER:
95 		return rte_cryptodev_get_cipher_algo_string(capa->cipher.algo);
96 	case RTE_CRYPTO_SYM_XFORM_AEAD:
97 		return rte_cryptodev_get_aead_algo_string(capa->aead.algo);
98 	default:
99 		return NULL;
100 	}
101 }
102 
103 static void
incrementing_generate(uint8_t * dst,uint8_t start,uint16_t size)104 incrementing_generate(uint8_t *dst, uint8_t start, uint16_t size)
105 {
106 	int i;
107 
108 	for (i = 0; i < size; i++)
109 		dst[i] = start + i;
110 }
111 
112 static void
pattern_fill(uint8_t * input,const char * pattern,uint16_t size)113 pattern_fill(uint8_t *input, const char *pattern, uint16_t size)
114 {
115 	size_t pattern_len = strlen(pattern);
116 	size_t filled_len = 0, to_fill;
117 
118 	while (filled_len < size) {
119 		to_fill = RTE_MIN(pattern_len, size - filled_len);
120 		rte_memcpy(input, pattern, to_fill);
121 		filled_len += to_fill;
122 		input += to_fill;
123 	}
124 }
125 
126 static struct crosscheck_test_profile
profile_create(const struct rte_cryptodev_symmetric_capability * capa,enum capability_select_type capability_type,size_t input_len)127 profile_create(const struct rte_cryptodev_symmetric_capability *capa,
128 	       enum capability_select_type capability_type, size_t input_len)
129 {
130 	struct crosscheck_test_profile profile;
131 
132 	memset(&profile, 0, sizeof(profile));
133 	profile.xform_type = capa->xform_type;
134 
135 	switch (capa->xform_type) {
136 	case RTE_CRYPTO_SYM_XFORM_AUTH:
137 		profile.block_size = capa->auth.block_size;
138 		profile.algo = capa->auth.algo;
139 
140 		switch (capability_type) {
141 		case CAPABILITY_TYPE_MIN:
142 			profile.key_size = capa->auth.key_size.min;
143 			profile.iv_size = capa->auth.iv_size.min;
144 			profile.digest_size = capa->auth.digest_size.min;
145 			profile.aad_size = capa->auth.aad_size.min;
146 			break;
147 		case CAPABILITY_TYPE_MAX:
148 			profile.key_size = capa->auth.key_size.max;
149 			profile.iv_size = capa->auth.iv_size.max;
150 			profile.digest_size = capa->auth.digest_size.max;
151 			profile.aad_size = capa->auth.aad_size.max;
152 			break;
153 		default:
154 			rte_panic("Wrong capability profile type: %i\n", capability_type);
155 			break;
156 		}
157 		break;
158 	case RTE_CRYPTO_SYM_XFORM_CIPHER:
159 		profile.block_size = capa->cipher.block_size;
160 		profile.algo = capa->cipher.algo;
161 		profile.dataunit_set = capa->cipher.dataunit_set;
162 
163 		switch (capability_type) {
164 		case CAPABILITY_TYPE_MIN:
165 			profile.key_size = capa->cipher.key_size.min;
166 			profile.iv_size = capa->cipher.iv_size.min;
167 			break;
168 		case CAPABILITY_TYPE_MAX:
169 			profile.key_size = capa->cipher.key_size.max;
170 			profile.iv_size = capa->cipher.iv_size.max;
171 			break;
172 		default:
173 			rte_panic("Wrong capability profile type: %i\n", capability_type);
174 			break;
175 		}
176 		break;
177 	case RTE_CRYPTO_SYM_XFORM_AEAD:
178 		profile.block_size = capa->aead.block_size;
179 		profile.algo = capa->aead.algo;
180 
181 		switch (capability_type) {
182 		case CAPABILITY_TYPE_MIN:
183 			profile.key_size = capa->aead.key_size.min;
184 			profile.iv_size = capa->aead.iv_size.min;
185 			profile.digest_size = capa->aead.digest_size.min;
186 			profile.aad_size = capa->aead.aad_size.min;
187 			break;
188 		case CAPABILITY_TYPE_MAX:
189 			profile.key_size = capa->aead.key_size.max;
190 			profile.iv_size = capa->aead.iv_size.max;
191 			profile.digest_size = capa->aead.digest_size.max;
192 			profile.aad_size = capa->aead.aad_size.max;
193 			break;
194 		default:
195 			rte_panic("Wrong capability profile type: %i\n", capability_type);
196 			break;
197 		}
198 		break;
199 	default:
200 		rte_panic("Wrong xform profile type: %i\n", capa->xform_type);
201 		break;
202 	}
203 
204 	profile.input_buf_len = RTE_ALIGN_CEIL(input_len, profile.block_size);
205 
206 	snprintf(profile.name, MAX_TEST_STRING_LEN,
207 			"'%s' - capabilities: '%s', input len: '%zu'",
208 			algo_name_get(capa), capability_select_strings[capability_type],
209 			input_len);
210 
211 	return profile;
212 }
213 
214 static inline int
common_range_set(struct rte_crypto_param_range * dst,const struct rte_crypto_param_range * src)215 common_range_set(struct rte_crypto_param_range *dst, const struct rte_crypto_param_range *src)
216 {
217 	/* Check if ranges overlaps */
218 	if ((dst->min > src->max) && (dst->max < src->min))
219 		return -1;
220 	dst->min = RTE_MAX(dst->min, src->min);
221 	dst->max = RTE_MIN(dst->max, src->max);
222 
223 	return 0;
224 }
225 
226 static uint16_t
nb_sym_capabilities_get(const struct rte_cryptodev_capabilities * cap)227 nb_sym_capabilities_get(const struct rte_cryptodev_capabilities *cap)
228 {
229 	uint16_t nb_caps = 0;
230 
231 	for (; cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED; cap++) {
232 		if (cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC)
233 			nb_caps += 1;
234 	}
235 
236 	return nb_caps;
237 }
238 
239 static struct rte_cryptodev_sym_capability_idx
sym_capability_to_idx(const struct rte_cryptodev_symmetric_capability * cap)240 sym_capability_to_idx(const struct rte_cryptodev_symmetric_capability *cap)
241 {
242 	struct rte_cryptodev_sym_capability_idx cap_idx;
243 
244 	cap_idx.type = cap->xform_type;
245 	switch (cap_idx.type) {
246 	case RTE_CRYPTO_SYM_XFORM_CIPHER:
247 		cap_idx.algo.auth = cap->auth.algo;
248 		break;
249 	case RTE_CRYPTO_SYM_XFORM_AUTH:
250 		cap_idx.algo.cipher = cap->cipher.algo;
251 		break;
252 	case RTE_CRYPTO_SYM_XFORM_AEAD:
253 		cap_idx.algo.aead = cap->aead.algo;
254 		break;
255 	default:
256 		rte_panic("Wrong capability profile type: %i\n", cap_idx.type);
257 		break;
258 	}
259 
260 	return cap_idx;
261 }
262 
263 /* Set the biggest common range for all capability fields */
264 static int
common_capability_set(struct rte_cryptodev_symmetric_capability * dst,const struct rte_cryptodev_symmetric_capability * src)265 common_capability_set(struct rte_cryptodev_symmetric_capability *dst,
266 		       const struct rte_cryptodev_symmetric_capability *src)
267 {
268 	switch (src->xform_type) {
269 	case RTE_CRYPTO_SYM_XFORM_AUTH:
270 		if (dst->auth.algo != src->auth.algo)
271 			return -ENOENT;
272 		if (dst->auth.block_size != src->auth.block_size)
273 			return -ENOENT;
274 		if (common_range_set(&dst->auth.key_size, &src->auth.key_size))
275 			return -ENOENT;
276 		if (common_range_set(&dst->auth.digest_size, &src->auth.digest_size))
277 			return -ENOENT;
278 		if (common_range_set(&dst->auth.aad_size, &src->auth.aad_size))
279 			return -ENOENT;
280 		if (common_range_set(&dst->auth.iv_size, &src->auth.iv_size))
281 			return -ENOENT;
282 		break;
283 	case RTE_CRYPTO_SYM_XFORM_CIPHER:
284 		if (dst->cipher.algo != src->cipher.algo)
285 			return -ENOENT;
286 		if (dst->cipher.block_size != src->cipher.block_size)
287 			return -ENOENT;
288 		if (common_range_set(&dst->cipher.key_size, &src->cipher.key_size))
289 			return -ENOENT;
290 		if (common_range_set(&dst->cipher.iv_size, &src->cipher.iv_size))
291 			return -ENOENT;
292 		if (dst->cipher.dataunit_set != src->cipher.dataunit_set)
293 			return -ENOENT;
294 		break;
295 	case RTE_CRYPTO_SYM_XFORM_AEAD:
296 		if (dst->aead.algo != src->aead.algo)
297 			return -ENOENT;
298 		if (dst->aead.block_size != src->aead.block_size)
299 			return -ENOENT;
300 		if (common_range_set(&dst->aead.key_size, &src->aead.key_size))
301 			return -ENOENT;
302 		if (common_range_set(&dst->aead.digest_size, &src->aead.digest_size))
303 			return -ENOENT;
304 		if (common_range_set(&dst->aead.aad_size, &src->aead.aad_size))
305 			return -ENOENT;
306 		if (common_range_set(&dst->aead.iv_size, &src->aead.iv_size))
307 			return -ENOENT;
308 		break;
309 	default:
310 		RTE_LOG(ERR, USER1, "Unsupported xform_type!\n");
311 		return -ENOENT;
312 	}
313 
314 	return 0;
315 }
316 
317 static int
capabilities_inspect(void)318 capabilities_inspect(void)
319 {
320 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
321 	const struct rte_cryptodev_symmetric_capability *next_dev_cap;
322 	struct rte_cryptodev_symmetric_capability common_cap;
323 	struct rte_cryptodev_sym_capability_idx cap_idx;
324 	const struct rte_cryptodev_capabilities *cap;
325 	struct rte_cryptodev_info dev_info;
326 	uint16_t nb_caps, cap_i = 0;
327 	uint8_t cdev_id, i;
328 
329 	/* Get list of capabilities of first device */
330 	cdev_id = ts_params->valid_devs[0];
331 	rte_cryptodev_info_get(cdev_id, &dev_info);
332 	cap = dev_info.capabilities;
333 	nb_caps = nb_sym_capabilities_get(cap);
334 	common_symm_capas = rte_calloc(NULL, nb_caps,
335 				       sizeof(struct rte_cryptodev_symmetric_capability), 0);
336 	if (common_symm_capas == NULL)
337 		return -ENOMEM;
338 
339 	for (; cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED; cap++) {
340 		/* Skip non symmetric capabilities */
341 		if (cap->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC)
342 			continue;
343 		/* AES_CCM requires special handling due to api requirements, skip now */
344 		if (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AEAD &&
345 				cap->sym.aead.algo == RTE_CRYPTO_AEAD_AES_CCM)
346 			continue;
347 
348 		cap_idx = sym_capability_to_idx(&cap->sym);
349 		common_cap = cap->sym;
350 		for (i = 1; i < ts_params->valid_dev_count; i++) {
351 			cdev_id = ts_params->valid_devs[i];
352 			next_dev_cap = rte_cryptodev_sym_capability_get(cdev_id, &cap_idx);
353 			/* Capability not supported by one of devs, skip */
354 			if (next_dev_cap == NULL)
355 				goto skip;
356 			/* Check if capabilities have a common range of values */
357 			if (common_capability_set(&common_cap, next_dev_cap) != 0)
358 				goto skip;
359 		}
360 
361 		/* If capability reach this point - it's support by all cryptodevs */
362 		common_symm_capas[cap_i++] = common_cap;
363 skip:;
364 	}
365 	nb_common_sym_caps = cap_i;
366 
367 	return 0;
368 }
369 
370 static int
crosscheck_init(void)371 crosscheck_init(void)
372 {
373 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
374 	const struct rte_cryptodev_symmetric_capability *cap;
375 	const uint32_t nb_queue_pairs = 1;
376 	struct rte_cryptodev_info info;
377 	uint32_t session_priv_size = 0;
378 	uint32_t nb_devs, dev_id;
379 	uint8_t i;
380 
381 	memset(ts_params, 0, sizeof(*ts_params));
382 
383 	/* Create list of valid crypto devs */
384 	nb_devs = rte_cryptodev_count();
385 	for (dev_id = 0; dev_id < nb_devs; dev_id++) {
386 		rte_cryptodev_info_get(dev_id, &info);
387 
388 		if (info.sym.max_nb_sessions != 0 && info.sym.max_nb_sessions < MAX_NB_SESSIONS)
389 			continue;
390 		if (info.max_nb_queue_pairs < nb_queue_pairs)
391 			continue;
392 		ts_params->valid_devs[ts_params->valid_dev_count++] = dev_id;
393 		/* Obtaining configuration parameters, that will satisfy all cryptodevs */
394 		session_priv_size = RTE_MAX(session_priv_size,
395 					    rte_cryptodev_sym_get_private_session_size(dev_id));
396 	}
397 
398 	if (ts_params->valid_dev_count < 2) {
399 		RTE_LOG(WARNING, USER1, "Min number of cryptodevs for test is 2, found (%d)\n",
400 			ts_params->valid_dev_count);
401 		return TEST_SKIPPED;
402 	}
403 
404 	/* Create pools for mbufs, crypto operations and sessions */
405 	ts_params->mbuf_pool = rte_pktmbuf_pool_create("CRYPTO_MBUFPOOL", NUM_MBUFS,
406 			MBUF_CACHE_SIZE, 0, MBUF_SIZE, rte_socket_id());
407 	if (ts_params->mbuf_pool == NULL) {
408 		RTE_LOG(ERR, USER1, "Can't create CRYPTO_MBUFPOOL\n");
409 		return TEST_FAILED;
410 	}
411 
412 	ts_params->op_mpool = rte_crypto_op_pool_create("MBUF_CRYPTO_SYM_OP_POOL",
413 			RTE_CRYPTO_OP_TYPE_SYMMETRIC, NUM_MBUFS, MBUF_CACHE_SIZE,
414 			DEFAULT_NUM_XFORMS * sizeof(struct rte_crypto_sym_xform) +
415 			MAXIMUM_IV_LENGTH, rte_socket_id());
416 
417 	if (ts_params->op_mpool == NULL) {
418 		RTE_LOG(ERR, USER1, "Can't create CRYPTO_OP_POOL\n");
419 		return TEST_FAILED;
420 	}
421 
422 	ts_params->session_mpool = rte_cryptodev_sym_session_pool_create("test_sess_mp",
423 			MAX_NB_SESSIONS, session_priv_size, 0, 0, SOCKET_ID_ANY);
424 	TEST_ASSERT_NOT_NULL(ts_params->session_mpool, "session mempool allocation failed");
425 
426 	/* Setup queue pair conf params */
427 	ts_params->conf.nb_queue_pairs = nb_queue_pairs;
428 	ts_params->conf.socket_id = SOCKET_ID_ANY;
429 	ts_params->conf.ff_disable = RTE_CRYPTODEV_FF_SECURITY;
430 	ts_params->qp_conf.nb_descriptors = MAX_NUM_OPS_INFLIGHT;
431 	ts_params->qp_conf.mp_session = ts_params->session_mpool;
432 
433 	if (capabilities_inspect() != 0)
434 		return TEST_FAILED;
435 
436 	/* Allocate memory based on max supported capabilities */
437 	for (i = 0; i < nb_common_sym_caps; i++) {
438 		cap = &common_symm_capas[i];
439 		switch (cap->xform_type) {
440 		case RTE_CRYPTO_SYM_XFORM_AUTH:
441 			ts_params->key.len = RTE_MAX(ts_params->key.len, cap->auth.key_size.max);
442 			ts_params->digest.len = RTE_MAX(ts_params->digest.len,
443 							cap->auth.digest_size.max);
444 			ts_params->aad.len = RTE_MAX(ts_params->aad.len, cap->auth.aad_size.max);
445 			ts_params->iv.len = RTE_MAX(ts_params->iv.len, cap->auth.iv_size.max);
446 			break;
447 		case RTE_CRYPTO_SYM_XFORM_CIPHER:
448 			ts_params->key.len = RTE_MAX(ts_params->key.len, cap->cipher.key_size.max);
449 			ts_params->iv.len = RTE_MAX(ts_params->iv.len, cap->cipher.iv_size.max);
450 			break;
451 		case RTE_CRYPTO_SYM_XFORM_AEAD:
452 			ts_params->key.len = RTE_MAX(ts_params->key.len, cap->aead.key_size.max);
453 			ts_params->digest.len = RTE_MAX(ts_params->digest.len,
454 							cap->aead.digest_size.max);
455 			ts_params->aad.len = RTE_MAX(ts_params->aad.len, cap->aead.aad_size.max);
456 			ts_params->iv.len = RTE_MAX(ts_params->iv.len, cap->aead.iv_size.max);
457 			break;
458 		default:
459 			rte_panic("Wrong capability profile type: %i\n", cap->xform_type);
460 			break;
461 		}
462 	}
463 
464 	if (ts_params->key.len) {
465 		ts_params->key.mem = rte_zmalloc(NULL, ts_params->key.len, 0);
466 		TEST_ASSERT_NOT_NULL(ts_params->key.mem, "Key mem allocation failed\n");
467 		pattern_fill(ts_params->key.mem, "*Secret key*", ts_params->key.len);
468 	}
469 	if (ts_params->digest.len) {
470 		ts_params->digest.mem = rte_zmalloc(NULL, ts_params->digest.len, 16);
471 		TEST_ASSERT_NOT_NULL(ts_params->digest.mem, "digest mem allocation failed\n");
472 		ts_params->expected_digest.len = ts_params->digest.len;
473 		ts_params->expected_digest.mem = rte_zmalloc(NULL, ts_params->digest.len, 0);
474 		TEST_ASSERT_NOT_NULL(ts_params->expected_digest.mem,
475 				     "Expected digest allocation failed\n");
476 	}
477 	if (ts_params->aad.len) {
478 		ts_params->aad.mem = rte_zmalloc(NULL, ts_params->aad.len, 16);
479 		TEST_ASSERT_NOT_NULL(ts_params->aad.mem, "aad mem allocation failed\n");
480 		ts_params->expected_aad.len = ts_params->aad.len;
481 		ts_params->expected_aad.mem = rte_zmalloc(NULL, ts_params->expected_aad.len, 0);
482 		TEST_ASSERT_NOT_NULL(ts_params->expected_aad.mem,
483 				     "Expected aad allocation failed\n");
484 	}
485 	if (ts_params->iv.len) {
486 		ts_params->iv.mem = rte_zmalloc(NULL, ts_params->iv.len, 0);
487 		TEST_ASSERT_NOT_NULL(ts_params->iv.mem, "iv mem allocation failed\n");
488 		pattern_fill(ts_params->iv.mem, "IV", ts_params->iv.len);
489 	}
490 
491 	return TEST_SUCCESS;
492 }
493 
494 static void
crosscheck_fini(void)495 crosscheck_fini(void)
496 {
497 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
498 
499 	rte_mempool_free(ts_params->mbuf_pool);
500 	rte_mempool_free(ts_params->op_mpool);
501 	rte_mempool_free(ts_params->session_mpool);
502 	rte_free(ts_params->key.mem);
503 	rte_free(ts_params->digest.mem);
504 	rte_free(ts_params->aad.mem);
505 	rte_free(ts_params->iv.mem);
506 }
507 
508 static int
dev_configure_and_start(uint64_t ff_disable)509 dev_configure_and_start(uint64_t ff_disable)
510 {
511 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
512 	uint8_t i, dev_id;
513 	uint16_t qp_id;
514 
515 	/* Reconfigure device to default parameters */
516 	ts_params->conf.ff_disable = ff_disable;
517 
518 	/* Configure cryptodevs */
519 	for (i = 0; i < ts_params->valid_dev_count; i++) {
520 		dev_id = ts_params->valid_devs[i];
521 		TEST_ASSERT_SUCCESS(rte_cryptodev_configure(dev_id, &ts_params->conf),
522 				    "Failed to configure cryptodev %u with %u qps",
523 				    dev_id, ts_params->conf.nb_queue_pairs);
524 
525 		for (qp_id = 0; qp_id < ts_params->conf.nb_queue_pairs; qp_id++) {
526 			TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
527 				dev_id, qp_id, &ts_params->qp_conf,
528 				rte_cryptodev_socket_id(dev_id)),
529 				"Failed to setup queue pair %u on cryptodev %u",
530 				qp_id, dev_id);
531 		}
532 		rte_cryptodev_stats_reset(dev_id);
533 
534 		/* Start the device */
535 		TEST_ASSERT_SUCCESS(rte_cryptodev_start(dev_id), "Failed to start cryptodev %u",
536 				    dev_id);
537 	}
538 
539 	return TEST_SUCCESS;
540 }
541 
542 static int
crosscheck_suite_setup(void)543 crosscheck_suite_setup(void)
544 {
545 	dev_configure_and_start(RTE_CRYPTODEV_FF_SECURITY);
546 
547 	return 0;
548 }
549 
550 static void
crosscheck_suite_teardown(void)551 crosscheck_suite_teardown(void)
552 {
553 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
554 	uint8_t i, dev_id;
555 
556 	for (i = 0; i < ts_params->valid_dev_count; i++) {
557 		dev_id = ts_params->valid_devs[i];
558 		rte_cryptodev_stop(dev_id);
559 	}
560 }
561 
562 static struct rte_crypto_op *
crypto_request_process(uint8_t dev_id,struct rte_crypto_op * op)563 crypto_request_process(uint8_t dev_id, struct rte_crypto_op *op)
564 {
565 	struct rte_crypto_op *res = NULL;
566 
567 	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
568 		RTE_LOG(ERR, USER1, "Error sending packet for encryption\n");
569 		return NULL;
570 	}
571 
572 	while (rte_cryptodev_dequeue_burst(dev_id, 0, &res, 1) == 0)
573 		rte_pause();
574 
575 	if (res->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
576 		RTE_LOG(ERR, USER1, "Operation status %d\n", res->status);
577 		return NULL;
578 	}
579 
580 	if (res != op) {
581 		RTE_LOG(ERR, USER1, "Unexpected operation received!\n");
582 		rte_crypto_op_free(res);
583 		return NULL;
584 	}
585 
586 	return res;
587 }
588 
589 static struct rte_cryptodev_sym_session*
session_create(const struct crosscheck_test_profile * profile,uint8_t dev_id,enum crypto_op_type op_type)590 session_create(const struct crosscheck_test_profile *profile, uint8_t dev_id,
591 	       enum crypto_op_type op_type)
592 {
593 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
594 	struct rte_cryptodev_sym_session *session;
595 	struct rte_crypto_sym_xform xform;
596 
597 	memset(&xform, 0, sizeof(xform));
598 
599 	switch (profile->xform_type) {
600 	case RTE_CRYPTO_SYM_XFORM_AUTH:
601 		xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
602 		xform.next = NULL;
603 		xform.auth.algo = profile->algo;
604 		xform.auth.op = op_type == OP_ENCRYPT ? RTE_CRYPTO_AUTH_OP_GENERATE :
605 			RTE_CRYPTO_AUTH_OP_VERIFY;
606 		xform.auth.digest_length = profile->digest_size;
607 		xform.auth.key.length = profile->key_size;
608 		xform.auth.key.data = ts_params->key.mem;
609 		xform.auth.iv.length = profile->iv_size;
610 		xform.auth.iv.offset = IV_OFFSET;
611 		break;
612 	case RTE_CRYPTO_SYM_XFORM_CIPHER:
613 		xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
614 		xform.next = NULL;
615 		xform.cipher.algo = profile->algo;
616 		xform.cipher.op = op_type == OP_ENCRYPT ? RTE_CRYPTO_CIPHER_OP_ENCRYPT :
617 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
618 		xform.cipher.key.length = profile->key_size;
619 		xform.cipher.key.data = ts_params->key.mem;
620 		xform.cipher.iv.length = profile->iv_size;
621 		xform.cipher.iv.offset = IV_OFFSET;
622 		break;
623 	case RTE_CRYPTO_SYM_XFORM_AEAD:
624 		xform.type = RTE_CRYPTO_SYM_XFORM_AEAD;
625 		xform.next = NULL;
626 		xform.aead.algo = profile->algo;
627 		xform.aead.op = op_type == OP_ENCRYPT ? RTE_CRYPTO_AEAD_OP_ENCRYPT :
628 			RTE_CRYPTO_AEAD_OP_DECRYPT;
629 		xform.aead.digest_length = profile->digest_size;
630 		xform.aead.key.length = profile->key_size;
631 		xform.aead.key.data = ts_params->key.mem;
632 		xform.aead.iv.length = profile->iv_size;
633 		xform.aead.iv.offset = IV_OFFSET;
634 		xform.aead.aad_length = profile->aad_size;
635 		break;
636 	default:
637 		return NULL;
638 	}
639 
640 	session = rte_cryptodev_sym_session_create(dev_id, &xform, testsuite_params.session_mpool);
641 
642 	return session;
643 }
644 
645 static struct rte_mbuf*
mbuf_create(const uint8_t * input_buf,uint16_t input_len)646 mbuf_create(const uint8_t *input_buf, uint16_t input_len)
647 {
648 	struct rte_mbuf *pkt;
649 	uint8_t *pkt_data;
650 
651 	pkt = rte_pktmbuf_alloc(testsuite_params.mbuf_pool);
652 	if (pkt == NULL) {
653 		RTE_LOG(ERR, USER1,  "Failed to allocate input buffer in mempool");
654 		return NULL;
655 	}
656 
657 	/* zeroing tailroom */
658 	memset(rte_pktmbuf_mtod(pkt, uint8_t *), 0, rte_pktmbuf_tailroom(pkt));
659 
660 	pkt_data = (uint8_t *)rte_pktmbuf_append(pkt, input_len);
661 	if (pkt_data == NULL) {
662 		RTE_LOG(ERR, USER1, "no room to append data, len: %d", input_len);
663 		goto error;
664 	}
665 	rte_memcpy(pkt_data, input_buf, input_len);
666 
667 	return pkt;
668 error:
669 	rte_pktmbuf_free(pkt);
670 	return NULL;
671 }
672 
673 static struct rte_crypto_op*
operation_create(const struct crosscheck_test_profile * profile,struct rte_mbuf * ibuf,enum crypto_op_type op_type)674 operation_create(const struct crosscheck_test_profile *profile,
675 		 struct rte_mbuf *ibuf, enum crypto_op_type op_type)
676 {
677 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
678 	uint8_t *digest_data = NULL, *aad_data = NULL, *iv_ptr = NULL;
679 	uint16_t aad_size, digest_size, plaintext_len;
680 	struct rte_crypto_sym_op *sym_op;
681 	struct rte_crypto_op *op;
682 
683 	op = rte_crypto_op_alloc(ts_params->op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
684 	if (op == NULL) {
685 		RTE_LOG(ERR, USER1, "Failed to allocate symmetric crypto operation struct");
686 		return NULL;
687 	}
688 
689 	plaintext_len = profile->input_buf_len;
690 	aad_size = profile->aad_size;
691 	digest_size = profile->digest_size;
692 
693 	if (aad_size) {
694 		aad_data = ts_params->aad.mem;
695 		if (op_type == OP_ENCRYPT)
696 			pattern_fill(aad_data, "This is an aad.", aad_size);
697 	}
698 
699 	if (digest_size) {
700 		digest_data = ts_params->digest.mem;
701 		if (op_type == OP_ENCRYPT)
702 			memset(digest_data, 0, sizeof(digest_size));
703 	}
704 
705 	sym_op = op->sym;
706 	memset(sym_op, 0, sizeof(*sym_op));
707 
708 	iv_ptr = rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET);
709 	rte_memcpy(iv_ptr, ts_params->iv.mem, profile->iv_size);
710 
711 	switch (profile->xform_type) {
712 	case RTE_CRYPTO_SYM_XFORM_AUTH:
713 		sym_op->auth.digest.data = digest_data;
714 		sym_op->auth.digest.phys_addr = rte_malloc_virt2iova(sym_op->auth.digest.data);
715 		sym_op->auth.data.length = plaintext_len;
716 		break;
717 	case RTE_CRYPTO_SYM_XFORM_CIPHER:
718 		sym_op->cipher.data.length = plaintext_len;
719 		break;
720 	case RTE_CRYPTO_SYM_XFORM_AEAD:
721 		sym_op->aead.aad.data = aad_data;
722 		sym_op->aead.aad.phys_addr = rte_malloc_virt2iova(sym_op->aead.aad.data);
723 		sym_op->aead.digest.data = digest_data;
724 		sym_op->aead.digest.phys_addr = rte_malloc_virt2iova(sym_op->aead.digest.data);
725 		sym_op->aead.data.offset = 0;
726 		sym_op->aead.data.length = plaintext_len;
727 		break;
728 	default:
729 		goto error;
730 	}
731 
732 	sym_op->m_src = ibuf;
733 
734 	return op;
735 
736 error:
737 	rte_crypto_op_free(op);
738 	return NULL;
739 }
740 
741 static void
mbuf_to_buf_copy(const struct rte_mbuf * m,uint8_t * res_buf,uint16_t * len)742 mbuf_to_buf_copy(const struct rte_mbuf *m, uint8_t *res_buf, uint16_t *len)
743 {
744 	const uint8_t *out;
745 
746 	*len = m->pkt_len;
747 	out = rte_pktmbuf_read(m, 0, *len, res_buf);
748 	/* Single segment buffer */
749 	if (out != res_buf)
750 		memcpy(res_buf, out, *len);
751 }
752 
753 static int
single_dev_process(const struct crosscheck_test_profile * profile,uint16_t dev_id,enum crypto_op_type op_type,const uint8_t * input_buf,uint16_t input_len,uint8_t * output_buf,uint16_t * output_len)754 single_dev_process(const struct crosscheck_test_profile *profile, uint16_t dev_id, enum
755 		   crypto_op_type op_type, const uint8_t *input_buf, uint16_t input_len,
756 		   uint8_t *output_buf, uint16_t *output_len)
757 {
758 	struct rte_cryptodev_sym_session *session = NULL;
759 	struct rte_mbuf *ibuf = NULL, *obuf = NULL;
760 	struct rte_crypto_op *op = NULL;
761 	int ret = -1;
762 
763 	session = session_create(profile, dev_id, op_type);
764 	if (session == NULL)
765 		goto error;
766 
767 	ibuf = mbuf_create(input_buf, input_len);
768 	if (ibuf == NULL)
769 		goto error;
770 
771 	op = operation_create(profile, ibuf, op_type);
772 	if (op == NULL)
773 		goto error;
774 
775 	debug_hexdump(stdout, "Input:", rte_pktmbuf_mtod(ibuf, uint8_t*), ibuf->pkt_len);
776 
777 	rte_crypto_op_attach_sym_session(op, session);
778 
779 	struct rte_crypto_op *res = crypto_request_process(dev_id, op);
780 	if (res == NULL)
781 		goto error;
782 
783 	obuf = op->sym->m_src;
784 	if (obuf == NULL) {
785 		RTE_LOG(ERR, USER1, "Invalid packet received\n");
786 		goto error;
787 	}
788 	mbuf_to_buf_copy(obuf, output_buf, output_len);
789 
790 	ret = 0;
791 
792 error:
793 	if (session != NULL) {
794 		int sret;
795 		sret = rte_cryptodev_sym_session_free(dev_id, session);
796 		RTE_VERIFY(sret == 0);
797 	}
798 	rte_pktmbuf_free(ibuf);
799 	rte_crypto_op_free(op);
800 	return ret;
801 }
802 
803 static int
buffers_compare(const uint8_t * expected,uint16_t expected_len,const uint8_t * received,uint16_t received_len)804 buffers_compare(const uint8_t *expected, uint16_t expected_len,
805 		const uint8_t *received, uint16_t received_len)
806 {
807 	TEST_ASSERT_EQUAL(expected_len, received_len, "Length mismatch %d != %d !\n",
808 			  expected_len, received_len);
809 
810 	if (memcmp(expected, received, expected_len)) {
811 		rte_hexdump(rte_log_get_stream(), "expected", expected, expected_len);
812 		rte_hexdump(rte_log_get_stream(), "received", received, expected_len);
813 		return TEST_FAILED;
814 	}
815 
816 	return TEST_SUCCESS;
817 }
818 
819 static int
crosscheck_all_devices(const struct crosscheck_test_profile * profile,enum crypto_op_type op_type,const uint8_t * input_text,uint16_t input_len,uint8_t * output_text,uint16_t * output_len)820 crosscheck_all_devices(const struct crosscheck_test_profile *profile, enum crypto_op_type op_type,
821 		       const uint8_t *input_text, uint16_t input_len, uint8_t *output_text,
822 		       uint16_t *output_len)
823 {
824 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
825 	uint16_t len = 0, expected_len = 0;
826 	uint8_t expected_text[MBUF_SIZE];
827 	uint8_t i, dev_id;
828 	int status;
829 
830 
831 	for (i = 0; i < ts_params->valid_dev_count; i++) {
832 		dev_id = ts_params->valid_devs[i];
833 		status = single_dev_process(profile, dev_id, op_type, input_text, input_len,
834 					    output_text, &len);
835 		TEST_ASSERT_SUCCESS(status, "Error occurred during processing");
836 
837 		if (i == 0) {
838 			/* First device, copy data for future comparisons */
839 			memcpy(expected_text, output_text, len);
840 			memcpy(ts_params->expected_digest.mem, ts_params->digest.mem,
841 			       profile->digest_size);
842 			memcpy(ts_params->expected_aad.mem, ts_params->aad.mem, profile->aad_size);
843 			expected_len = len;
844 		} else {
845 			/* Compare output against expected(first) output */
846 			TEST_ASSERT_SUCCESS(buffers_compare(expected_text, expected_len,
847 					output_text, len),
848 					"Text mismatch occurred on dev %i\n", dev_id);
849 			TEST_ASSERT_SUCCESS(buffers_compare(ts_params->expected_digest.mem,
850 					profile->digest_size, ts_params->digest.mem,
851 					profile->digest_size),
852 					"Digest mismatch occurred on dev %i\n", dev_id);
853 			TEST_ASSERT_SUCCESS(buffers_compare(ts_params->expected_aad.mem,
854 					profile->aad_size, ts_params->aad.mem, profile->aad_size),
855 					"AAD mismatch occurred on dev %i\n", dev_id);
856 		}
857 
858 		RTE_LOG(DEBUG, USER1, "DEV ID: %u finished processing\n", dev_id);
859 		debug_hexdump(stdout, "Output: ", output_text, len);
860 		if (profile->digest_size)
861 			debug_hexdump(stdout, "Digest: ", ts_params->digest.mem,
862 				      profile->digest_size);
863 	}
864 
865 	*output_len = len;
866 
867 	return TEST_SUCCESS;
868 }
869 
870 static int
check_negative_all_devices(const struct crosscheck_test_profile * profile,enum crypto_op_type op_type,const uint8_t * input_text,uint16_t input_len)871 check_negative_all_devices(const struct crosscheck_test_profile *profile,
872 			   enum crypto_op_type op_type, const uint8_t *input_text,
873 			   uint16_t input_len)
874 {
875 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
876 
877 	uint8_t output_text[MBUF_SIZE];
878 	uint8_t i, dev_id;
879 	uint16_t len;
880 	int status;
881 
882 	for (i = 0; i < ts_params->valid_dev_count; i++) {
883 		dev_id = ts_params->valid_devs[i];
884 		status = single_dev_process(profile, dev_id, op_type, input_text, input_len,
885 					    output_text, &len);
886 		TEST_ASSERT_FAIL(status, "Error occurred during processing negative case");
887 
888 	}
889 
890 	return TEST_SUCCESS;
891 }
892 
893 static int
crosscheck_with_profile_run(const struct crosscheck_test_profile * profile)894 crosscheck_with_profile_run(const struct crosscheck_test_profile *profile)
895 {
896 	struct crosscheck_testsuite_params *ts_params = &testsuite_params;
897 	uint8_t input_text[profile->input_buf_len];
898 	uint16_t output_len, encrypted_len;
899 	uint8_t encrypted_text[MBUF_SIZE];
900 	uint8_t output_text[MBUF_SIZE];
901 	int status;
902 
903 	memset(ts_params->digest.mem, 0, ts_params->digest.len);
904 	memset(ts_params->aad.mem, 0, ts_params->aad.len);
905 
906 	/* Encrypt Stage */
907 	RTE_LOG(DEBUG, USER1, "Executing encrypt stage\n");
908 	/* Fill input with incrementing pattern */
909 	incrementing_generate(input_text, 'a', profile->input_buf_len);
910 	status = crosscheck_all_devices(profile, OP_ENCRYPT, input_text, profile->input_buf_len,
911 					output_text, &output_len);
912 	TEST_ASSERT_SUCCESS(status, "Error occurred during encryption");
913 
914 	/* Decrypt Stage */
915 	RTE_LOG(DEBUG, USER1, "Executing decrypt stage\n");
916 	/* Set up encrypted data as input */
917 	encrypted_len = output_len;
918 	memcpy(encrypted_text, output_text, output_len);
919 	status = crosscheck_all_devices(profile, OP_DECRYPT, encrypted_text, encrypted_len,
920 					output_text, &output_len);
921 	TEST_ASSERT_SUCCESS(status, "Error occurred during decryption");
922 
923 	/* Negative Stage */
924 	RTE_LOG(DEBUG, USER1, "Executing negative stage\n");
925 	if (profile->digest_size) {
926 		/* Corrupting one byte of digest */
927 		ts_params->digest.mem[profile->digest_size - 1] += 1;
928 		status = check_negative_all_devices(profile, OP_DECRYPT, encrypted_text,
929 						    encrypted_len);
930 		TEST_ASSERT_SUCCESS(status, "Error occurred during decryption");
931 	}
932 
933 
934 	return TEST_SUCCESS;
935 }
936 
937 static int
test_crosscheck_unit(const void * ptr)938 test_crosscheck_unit(const void *ptr)
939 {
940 	const struct crosscheck_test_profile *profile = ptr;
941 
942 	if (profile->xform_type == RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED)
943 		return TEST_SKIPPED;
944 
945 	return crosscheck_with_profile_run(profile);
946 }
947 
948 static struct unit_test_suite*
sym_unit_test_suite_create(const struct rte_cryptodev_symmetric_capability * capa)949 sym_unit_test_suite_create(const struct rte_cryptodev_symmetric_capability *capa)
950 {
951 	size_t uts_size, total_size, input_sz;
952 	struct meta_test_suite *meta_ts;
953 	const char *suite_prefix = NULL;
954 	const char *algo_name = NULL;
955 	struct unit_test_suite *uts;
956 	uint64_t test_case_idx = 0;
957 	struct unit_test_case *utc;
958 	int cap_type;
959 	char *mem;
960 
961 	const char * const suite_prefix_strings[] = {
962 		[RTE_CRYPTO_SYM_XFORM_AUTH] = "Algo AUTH ",
963 		[RTE_CRYPTO_SYM_XFORM_CIPHER] = "Algo CIPHER ",
964 		[RTE_CRYPTO_SYM_XFORM_AEAD] = "Algo AEAD ",
965 	};
966 
967 	suite_prefix = suite_prefix_strings[capa->xform_type];
968 	algo_name = algo_name_get(capa);
969 
970 	/* Calculate size for test suite with all test cases +1 NULL case */
971 	uts_size = sizeof(struct unit_test_suite) +
972 		(NB_TEST_CASES_PER_ALGO + 1) * sizeof(struct unit_test_case);
973 
974 	/* Also allocate memory for suite meta data */
975 	total_size = uts_size + sizeof(struct meta_test_suite);
976 	mem = rte_zmalloc(NULL, total_size, 0);
977 	if (mem == NULL)
978 		return NULL;
979 	uts = (struct unit_test_suite *) mem;
980 	meta_ts = (struct meta_test_suite *) (mem + uts_size);
981 
982 	/* Initialize test suite */
983 	snprintf(meta_ts->suite_name, MAX_TEST_STRING_LEN, "%s '%s'", suite_prefix, algo_name);
984 	uts->suite_name = meta_ts->suite_name;
985 
986 	/* Initialize test cases */
987 	for (cap_type = 0; cap_type < CAPABILITY_TYPE_LAST; cap_type++) {
988 		for (input_sz = 0; input_sz < RTE_DIM(input_length); input_sz++) {
989 			meta_ts->profile[test_case_idx] = profile_create(
990 					capa, cap_type, input_length[input_sz]);
991 			utc = &uts->unit_test_cases[test_case_idx];
992 			utc->name = meta_ts->profile[test_case_idx].name;
993 			utc->data = (const void *) &meta_ts->profile[test_case_idx];
994 			utc->testcase_with_data = test_crosscheck_unit;
995 			utc->enabled = true;
996 
997 			test_case_idx += 1;
998 			RTE_VERIFY(test_case_idx <= NB_TEST_CASES_PER_ALGO);
999 		}
1000 	}
1001 
1002 	return uts;
1003 }
1004 
1005 static int
test_crosscheck(void)1006 test_crosscheck(void)
1007 {
1008 	struct unit_test_suite **test_suites = NULL;
1009 	int ret, i;
1010 
1011 	static struct unit_test_suite ts = {
1012 		.suite_name = "Crosscheck Unit Test Suite",
1013 		.setup = crosscheck_suite_setup,
1014 		.teardown = crosscheck_suite_teardown,
1015 		.unit_test_cases = {TEST_CASES_END()}
1016 	};
1017 
1018 	ret = crosscheck_init();
1019 	if (ret)
1020 		goto exit;
1021 
1022 	if (nb_common_sym_caps == 0) {
1023 		RTE_LOG(WARNING, USER1, "Cryptodevs don't have common capabilities\n");
1024 		ret = TEST_SKIPPED;
1025 		goto exit;
1026 	}
1027 
1028 	/* + 1 for NULL-end suite */
1029 	test_suites = rte_calloc(NULL, nb_common_sym_caps + 1, sizeof(struct unit_test_suite *), 0);
1030 	TEST_ASSERT_NOT_NULL(test_suites, "test_suites allocation failed");
1031 
1032 	/* Create test suite for each supported algorithm */
1033 	ts.unit_test_suites = test_suites;
1034 	for (i = 0; i < nb_common_sym_caps; i++)
1035 		ts.unit_test_suites[i] = sym_unit_test_suite_create(&common_symm_capas[i]);
1036 
1037 	ret = unit_test_suite_runner(&ts);
1038 
1039 	for (i = 0; i < nb_common_sym_caps; i++)
1040 		rte_free(ts.unit_test_suites[i]);
1041 
1042 	rte_free(test_suites);
1043 
1044 exit:
1045 	crosscheck_fini();
1046 
1047 	return ret;
1048 }
1049 
1050 REGISTER_TEST_COMMAND(cryptodev_crosscheck, test_crosscheck);
1051