xref: /dpdk/examples/fips_validation/main.c (revision f4eac3a09c51a1a2dab1f2fd3a10fe0619286a0d)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4 
5 #include <sys/stat.h>
6 #include <getopt.h>
7 #include <dirent.h>
8 
9 #include <rte_cryptodev.h>
10 #include <rte_malloc.h>
11 #include <rte_mempool.h>
12 #include <rte_mbuf.h>
13 #include <rte_string_fns.h>
14 
15 #include "fips_validation.h"
16 #include "fips_dev_self_test.h"
17 
18 enum {
19 #define OPT_REQ_FILE_PATH           "req-file"
20 	OPT_REQ_FILE_PATH_NUM = 256,
21 #define OPT_RSP_FILE_PATH           "rsp-file"
22 	OPT_RSP_FILE_PATH_NUM,
23 #define OPT_MBUF_DATAROOM           "mbuf-dataroom"
24 	OPT_MBUF_DATAROOM_NUM,
25 #define OPT_FOLDER                  "path-is-folder"
26 	OPT_FOLDER_NUM,
27 #define OPT_CRYPTODEV               "cryptodev"
28 	OPT_CRYPTODEV_NUM,
29 #define OPT_CRYPTODEV_ID            "cryptodev-id"
30 	OPT_CRYPTODEV_ID_NUM,
31 #define OPT_CRYPTODEV_ST            "self-test"
32 	OPT_CRYPTODEV_ST_NUM,
33 #define OPT_CRYPTODEV_BK_ID         "broken-test-id"
34 	OPT_CRYPTODEV_BK_ID_NUM,
35 #define OPT_CRYPTODEV_BK_DIR_KEY    "broken-test-dir"
36 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
37 };
38 
39 struct fips_test_vector vec;
40 struct fips_test_interim_info info;
41 
42 struct cryptodev_fips_validate_env {
43 	const char *req_path;
44 	const char *rsp_path;
45 	uint32_t is_path_folder;
46 	uint8_t dev_id;
47 	uint8_t dev_support_sgl;
48 	uint16_t mbuf_data_room;
49 	struct rte_mempool *mpool;
50 	struct rte_mempool *sess_mpool;
51 	struct rte_mempool *sess_priv_mpool;
52 	struct rte_mempool *op_pool;
53 	struct rte_mbuf *mbuf;
54 	uint8_t *digest;
55 	uint16_t digest_len;
56 	struct rte_crypto_op *op;
57 	struct rte_cryptodev_sym_session *sess;
58 	uint16_t self_test;
59 	struct fips_dev_broken_test_config *broken_test_config;
60 } env;
61 
62 static int
63 cryptodev_fips_validate_app_int(void)
64 {
65 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
66 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
67 	struct rte_cryptodev_info dev_info;
68 	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
69 			env.dev_id);
70 	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
71 	int ret;
72 
73 	if (env.self_test) {
74 		ret = fips_dev_self_test(env.dev_id, env.broken_test_config);
75 		if (ret < 0) {
76 			rte_cryptodev_close(env.dev_id);
77 
78 			return ret;
79 		}
80 	}
81 
82 	ret = rte_cryptodev_configure(env.dev_id, &conf);
83 	if (ret < 0)
84 		return ret;
85 
86 	rte_cryptodev_info_get(env.dev_id, &dev_info);
87 	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
88 		env.dev_support_sgl = 1;
89 	else
90 		env.dev_support_sgl = 0;
91 
92 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
93 			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
94 			env.mbuf_data_room, rte_socket_id());
95 	if (!env.mpool)
96 		return ret;
97 
98 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
99 			rte_socket_id());
100 	if (ret < 0)
101 		return ret;
102 
103 	ret = -ENOMEM;
104 
105 	env.sess_mpool = rte_cryptodev_sym_session_pool_create(
106 			"FIPS_SESS_MEMPOOL", 16, 0, 0, 0, rte_socket_id());
107 	if (!env.sess_mpool)
108 		goto error_exit;
109 
110 	env.sess_priv_mpool = rte_mempool_create("FIPS_SESS_PRIV_MEMPOOL",
111 			16, sess_sz, 0, 0, NULL, NULL, NULL,
112 			NULL, rte_socket_id(), 0);
113 	if (!env.sess_priv_mpool)
114 		goto error_exit;
115 
116 	env.op_pool = rte_crypto_op_pool_create(
117 			"FIPS_OP_POOL",
118 			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
119 			1, 0,
120 			16,
121 			rte_socket_id());
122 	if (!env.op_pool)
123 		goto error_exit;
124 
125 	env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
126 	if (!env.op)
127 		goto error_exit;
128 
129 	qp_conf.mp_session = env.sess_mpool;
130 	qp_conf.mp_session_private = env.sess_priv_mpool;
131 
132 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
133 			rte_socket_id());
134 	if (ret < 0)
135 		goto error_exit;
136 
137 	ret = rte_cryptodev_start(env.dev_id);
138 	if (ret < 0)
139 		goto error_exit;
140 
141 	return 0;
142 
143 error_exit:
144 
145 	rte_mempool_free(env.mpool);
146 	rte_mempool_free(env.sess_mpool);
147 	rte_mempool_free(env.sess_priv_mpool);
148 	rte_mempool_free(env.op_pool);
149 
150 	return ret;
151 }
152 
153 static void
154 cryptodev_fips_validate_app_uninit(void)
155 {
156 	rte_pktmbuf_free(env.mbuf);
157 	rte_crypto_op_free(env.op);
158 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
159 	rte_cryptodev_sym_session_free(env.sess);
160 	rte_mempool_free(env.mpool);
161 	rte_mempool_free(env.sess_mpool);
162 	rte_mempool_free(env.sess_priv_mpool);
163 	rte_mempool_free(env.op_pool);
164 }
165 
166 static int
167 fips_test_one_file(void);
168 
169 static int
170 parse_cryptodev_arg(char *arg)
171 {
172 	int id = rte_cryptodev_get_dev_id(arg);
173 
174 	if (id < 0) {
175 		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
176 				id, arg);
177 		return id;
178 	}
179 
180 	env.dev_id = (uint8_t)id;
181 
182 	return 0;
183 }
184 
185 static int
186 parse_cryptodev_id_arg(char *arg)
187 {
188 	uint32_t cryptodev_id;
189 
190 	if (parser_read_uint32(&cryptodev_id, arg) < 0) {
191 		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
192 				-EINVAL, arg);
193 		return -1;
194 	}
195 
196 
197 	if (!rte_cryptodev_is_valid_dev(cryptodev_id)) {
198 		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
199 				cryptodev_id, arg);
200 		return -1;
201 	}
202 
203 	env.dev_id = (uint8_t)cryptodev_id;
204 
205 	return 0;
206 }
207 
208 static void
209 cryptodev_fips_validate_usage(const char *prgname)
210 {
211 	uint32_t def_mbuf_seg_size = DEF_MBUF_SEG_SIZE;
212 	printf("%s [EAL options] --\n"
213 		"  --%s: REQUEST-FILE-PATH\n"
214 		"  --%s: RESPONSE-FILE-PATH\n"
215 		"  --%s: indicating both paths are folders\n"
216 		"  --%s: mbuf dataroom size (default %u bytes)\n"
217 		"  --%s: CRYPTODEV-NAME\n"
218 		"  --%s: CRYPTODEV-ID-NAME\n"
219 		"  --%s: self test indicator\n"
220 		"  --%s: self broken test ID\n"
221 		"  --%s: self broken test direction\n",
222 		prgname, OPT_REQ_FILE_PATH, OPT_RSP_FILE_PATH,
223 		OPT_FOLDER, OPT_MBUF_DATAROOM, def_mbuf_seg_size,
224 		OPT_CRYPTODEV, OPT_CRYPTODEV_ID, OPT_CRYPTODEV_ST,
225 		OPT_CRYPTODEV_BK_ID, OPT_CRYPTODEV_BK_DIR_KEY);
226 }
227 
228 static int
229 cryptodev_fips_validate_parse_args(int argc, char **argv)
230 {
231 	int opt, ret;
232 	char *prgname = argv[0];
233 	char **argvopt;
234 	int option_index;
235 	struct option lgopts[] = {
236 		{OPT_REQ_FILE_PATH, required_argument,
237 				NULL, OPT_REQ_FILE_PATH_NUM},
238 		{OPT_RSP_FILE_PATH, required_argument,
239 				NULL, OPT_RSP_FILE_PATH_NUM},
240 		{OPT_FOLDER, no_argument,
241 				NULL, OPT_FOLDER_NUM},
242 		{OPT_MBUF_DATAROOM, required_argument,
243 				NULL, OPT_MBUF_DATAROOM_NUM},
244 		{OPT_CRYPTODEV, required_argument,
245 				NULL, OPT_CRYPTODEV_NUM},
246 		{OPT_CRYPTODEV_ID, required_argument,
247 				NULL, OPT_CRYPTODEV_ID_NUM},
248 		{OPT_CRYPTODEV_ST, no_argument,
249 				NULL, OPT_CRYPTODEV_ST_NUM},
250 		{OPT_CRYPTODEV_BK_ID, required_argument,
251 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
252 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
253 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
254 		{NULL, 0, 0, 0}
255 	};
256 
257 	argvopt = argv;
258 
259 	env.mbuf_data_room = DEF_MBUF_SEG_SIZE;
260 	if (rte_cryptodev_count())
261 		env.dev_id = 0;
262 	else {
263 		cryptodev_fips_validate_usage(prgname);
264 		return -EINVAL;
265 	}
266 
267 	while ((opt = getopt_long(argc, argvopt, "s:",
268 				  lgopts, &option_index)) != EOF) {
269 
270 		switch (opt) {
271 		case OPT_REQ_FILE_PATH_NUM:
272 			env.req_path = optarg;
273 			break;
274 
275 		case OPT_RSP_FILE_PATH_NUM:
276 			env.rsp_path = optarg;
277 			break;
278 
279 		case OPT_FOLDER_NUM:
280 			env.is_path_folder = 1;
281 			break;
282 
283 		case OPT_CRYPTODEV_NUM:
284 			ret = parse_cryptodev_arg(optarg);
285 			if (ret < 0) {
286 				cryptodev_fips_validate_usage(prgname);
287 				return -EINVAL;
288 			}
289 			break;
290 
291 		case OPT_CRYPTODEV_ID_NUM:
292 			ret = parse_cryptodev_id_arg(optarg);
293 			if (ret < 0) {
294 				cryptodev_fips_validate_usage(prgname);
295 				return -EINVAL;
296 			}
297 			break;
298 
299 		case OPT_CRYPTODEV_ST_NUM:
300 			env.self_test = 1;
301 			break;
302 
303 		case OPT_CRYPTODEV_BK_ID_NUM:
304 			if (!env.broken_test_config) {
305 				env.broken_test_config = rte_malloc(
306 					NULL,
307 					sizeof(*env.broken_test_config),
308 					0);
309 				if (!env.broken_test_config)
310 					return -ENOMEM;
311 
312 				env.broken_test_config->expect_fail_dir =
313 					self_test_dir_enc_auth_gen;
314 			}
315 
316 			if (parser_read_uint32(
317 				&env.broken_test_config->expect_fail_test_idx,
318 					optarg) < 0) {
319 				rte_free(env.broken_test_config);
320 				cryptodev_fips_validate_usage(prgname);
321 				return -EINVAL;
322 			}
323 			break;
324 
325 		case OPT_CRYPTODEV_BK_DIR_KEY_NUM:
326 			if (!env.broken_test_config) {
327 				env.broken_test_config = rte_malloc(
328 					NULL,
329 					sizeof(*env.broken_test_config),
330 					0);
331 				if (!env.broken_test_config)
332 					return -ENOMEM;
333 
334 				env.broken_test_config->expect_fail_test_idx =
335 					0;
336 			}
337 
338 			if (strcmp(optarg, "enc") == 0)
339 				env.broken_test_config->expect_fail_dir =
340 					self_test_dir_enc_auth_gen;
341 			else if (strcmp(optarg, "dec")
342 					== 0)
343 				env.broken_test_config->expect_fail_dir =
344 					self_test_dir_dec_auth_verify;
345 			else {
346 				rte_free(env.broken_test_config);
347 				cryptodev_fips_validate_usage(prgname);
348 				return -EINVAL;
349 			}
350 			break;
351 
352 
353 		case OPT_MBUF_DATAROOM_NUM:
354 			if (parser_read_uint16(&env.mbuf_data_room,
355 					optarg) < 0) {
356 				cryptodev_fips_validate_usage(prgname);
357 				return -EINVAL;
358 			}
359 
360 			if (env.mbuf_data_room == 0) {
361 				cryptodev_fips_validate_usage(prgname);
362 				return -EINVAL;
363 			}
364 			break;
365 
366 		default:
367 			cryptodev_fips_validate_usage(prgname);
368 			return -EINVAL;
369 		}
370 	}
371 
372 	if ((env.req_path == NULL && env.rsp_path != NULL) ||
373 			(env.req_path != NULL && env.rsp_path == NULL)) {
374 		RTE_LOG(ERR, USER1, "Missing req path or rsp path\n");
375 		cryptodev_fips_validate_usage(prgname);
376 		return -EINVAL;
377 	}
378 
379 	if (env.req_path == NULL && env.self_test == 0) {
380 		RTE_LOG(ERR, USER1, "--self-test must be set if req path is missing\n");
381 		cryptodev_fips_validate_usage(prgname);
382 		return -EINVAL;
383 	}
384 
385 	return 0;
386 }
387 
388 int
389 main(int argc, char *argv[])
390 {
391 	int ret;
392 
393 	ret = rte_eal_init(argc, argv);
394 	if (ret < 0) {
395 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
396 		return -1;
397 	}
398 
399 	argc -= ret;
400 	argv += ret;
401 
402 	ret = cryptodev_fips_validate_parse_args(argc, argv);
403 	if (ret < 0)
404 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
405 
406 	ret = cryptodev_fips_validate_app_int();
407 	if (ret < 0) {
408 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
409 		return -1;
410 	}
411 
412 	if (env.req_path == NULL || env.rsp_path == NULL) {
413 		printf("No request, exit.\n");
414 		goto exit;
415 	}
416 
417 	if (!env.is_path_folder) {
418 		printf("Processing file %s... ", env.req_path);
419 
420 		ret = fips_test_init(env.req_path, env.rsp_path,
421 			rte_cryptodev_name_get(env.dev_id));
422 		if (ret < 0) {
423 			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
424 					ret, env.req_path);
425 			goto exit;
426 		}
427 
428 
429 		ret = fips_test_one_file();
430 		if (ret < 0) {
431 			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
432 					ret, env.req_path);
433 			goto exit;
434 		}
435 
436 		printf("Done\n");
437 
438 	} else {
439 		struct dirent *dir;
440 		DIR *d_req, *d_rsp;
441 		char req_path[1024];
442 		char rsp_path[1024];
443 
444 		d_req = opendir(env.req_path);
445 		if (!d_req) {
446 			RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
447 					-EINVAL, env.req_path);
448 			goto exit;
449 		}
450 
451 		d_rsp = opendir(env.rsp_path);
452 		if (!d_rsp) {
453 			ret = mkdir(env.rsp_path, 0700);
454 			if (ret == 0)
455 				d_rsp = opendir(env.rsp_path);
456 			else {
457 				RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
458 						-EINVAL, env.rsp_path);
459 				goto exit;
460 			}
461 		}
462 		closedir(d_rsp);
463 
464 		while ((dir = readdir(d_req)) != NULL) {
465 			if (strstr(dir->d_name, "req") == NULL)
466 				continue;
467 
468 			snprintf(req_path, 1023, "%s/%s", env.req_path,
469 					dir->d_name);
470 			snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
471 					dir->d_name);
472 			strlcpy(strstr(rsp_path, "req"), "rsp", 4);
473 
474 			printf("Processing file %s... ", req_path);
475 
476 			ret = fips_test_init(req_path, rsp_path,
477 			rte_cryptodev_name_get(env.dev_id));
478 			if (ret < 0) {
479 				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
480 						ret, req_path);
481 				break;
482 			}
483 
484 			ret = fips_test_one_file();
485 			if (ret < 0) {
486 				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
487 						ret, req_path);
488 				break;
489 			}
490 
491 			printf("Done\n");
492 		}
493 
494 		closedir(d_req);
495 	}
496 
497 
498 exit:
499 	fips_test_clear();
500 	cryptodev_fips_validate_app_uninit();
501 
502 	/* clean up the EAL */
503 	rte_eal_cleanup();
504 
505 	return ret;
506 
507 }
508 
509 #define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
510 #define CRYPTODEV_FIPS_MAX_RETRIES	16
511 
512 struct fips_test_ops test_ops;
513 
514 static int
515 prepare_data_mbufs(struct fips_val *val)
516 {
517 	struct rte_mbuf *m, *head = 0;
518 	uint8_t *src = val->val;
519 	uint32_t total_len = val->len;
520 	uint16_t nb_seg;
521 	int ret = 0;
522 
523 	rte_pktmbuf_free(env.mbuf);
524 
525 	if (total_len > RTE_MBUF_MAX_NB_SEGS) {
526 		RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
527 		return -EPERM;
528 	}
529 
530 	nb_seg = total_len / env.mbuf_data_room;
531 	if (total_len % env.mbuf_data_room)
532 		nb_seg++;
533 
534 	m = rte_pktmbuf_alloc(env.mpool);
535 	if (!m) {
536 		RTE_LOG(ERR, USER1, "Error %i: Not enough mbuf\n",
537 				-ENOMEM);
538 		return -ENOMEM;
539 	}
540 	head = m;
541 
542 	while (nb_seg) {
543 		uint16_t len = RTE_MIN(total_len, env.mbuf_data_room);
544 		uint8_t *dst = (uint8_t *)rte_pktmbuf_append(m, len);
545 
546 		if (!dst) {
547 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
548 					-ENOMEM);
549 			ret = -ENOMEM;
550 			goto error_exit;
551 		}
552 
553 		memcpy(dst, src, len);
554 
555 		if (head != m) {
556 			ret = rte_pktmbuf_chain(head, m);
557 			if (ret) {
558 				rte_pktmbuf_free(m);
559 				RTE_LOG(ERR, USER1, "Error %i: SGL build\n",
560 						ret);
561 				goto error_exit;
562 			}
563 		}
564 		total_len -= len;
565 
566 		if (total_len) {
567 			if (!env.dev_support_sgl) {
568 				RTE_LOG(ERR, USER1, "SGL not supported\n");
569 				ret = -EPERM;
570 				goto error_exit;
571 			}
572 
573 			m = rte_pktmbuf_alloc(env.mpool);
574 			if (!m) {
575 				RTE_LOG(ERR, USER1, "Error %i: No memory\n",
576 						-ENOMEM);
577 				goto error_exit;
578 			}
579 		} else
580 			break;
581 
582 		src += len;
583 		nb_seg--;
584 	}
585 
586 	if (total_len) {
587 		RTE_LOG(ERR, USER1, "Error %i: Failed to store all data\n",
588 				-ENOMEM);
589 		goto error_exit;
590 	}
591 
592 	env.mbuf = head;
593 
594 	return 0;
595 
596 error_exit:
597 	rte_pktmbuf_free(head);
598 	return ret;
599 }
600 
601 static int
602 prepare_cipher_op(void)
603 {
604 	struct rte_crypto_sym_op *sym = env.op->sym;
605 	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
606 	int ret;
607 
608 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
609 
610 	memcpy(iv, vec.iv.val, vec.iv.len);
611 
612 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
613 		ret = prepare_data_mbufs(&vec.pt);
614 		if (ret < 0)
615 			return ret;
616 
617 		sym->cipher.data.length = vec.pt.len;
618 	} else {
619 		ret = prepare_data_mbufs(&vec.ct);
620 		if (ret < 0)
621 			return ret;
622 
623 		sym->cipher.data.length = vec.ct.len;
624 	}
625 
626 	rte_crypto_op_attach_sym_session(env.op, env.sess);
627 
628 	sym->m_src = env.mbuf;
629 	sym->cipher.data.offset = 0;
630 
631 	return 0;
632 }
633 
634 int
635 prepare_auth_op(void)
636 {
637 	struct rte_crypto_sym_op *sym = env.op->sym;
638 	int ret;
639 
640 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
641 
642 	if (vec.iv.len) {
643 		uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *,
644 				IV_OFF);
645 		memset(iv, 0, vec.iv.len);
646 		if (vec.iv.val)
647 			memcpy(iv, vec.iv.val, vec.iv.len);
648 	}
649 
650 	ret = prepare_data_mbufs(&vec.pt);
651 	if (ret < 0)
652 		return ret;
653 
654 	rte_free(env.digest);
655 
656 	env.digest = rte_zmalloc(NULL, vec.cipher_auth.digest.len,
657 			RTE_CACHE_LINE_SIZE);
658 	if (!env.digest) {
659 		RTE_LOG(ERR, USER1, "Not enough memory\n");
660 		return -ENOMEM;
661 	}
662 	env.digest_len = vec.cipher_auth.digest.len;
663 
664 	sym->m_src = env.mbuf;
665 	sym->auth.data.offset = 0;
666 	sym->auth.data.length = vec.pt.len;
667 	sym->auth.digest.data = env.digest;
668 	sym->auth.digest.phys_addr = rte_malloc_virt2iova(env.digest);
669 
670 	if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
671 		memcpy(env.digest, vec.cipher_auth.digest.val,
672 				vec.cipher_auth.digest.len);
673 
674 	rte_crypto_op_attach_sym_session(env.op, env.sess);
675 
676 	return 0;
677 }
678 
679 int
680 prepare_aead_op(void)
681 {
682 	struct rte_crypto_sym_op *sym = env.op->sym;
683 	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
684 	int ret;
685 
686 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
687 
688 	if (info.algo == FIPS_TEST_ALGO_AES_CCM)
689 		iv++;
690 
691 	if (vec.iv.val)
692 		memcpy(iv, vec.iv.val, vec.iv.len);
693 	else
694 		/* if REQ file has iv length but not data, default as all 0 */
695 		memset(iv, 0, vec.iv.len);
696 
697 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
698 		ret = prepare_data_mbufs(&vec.pt);
699 		if (ret < 0)
700 			return ret;
701 
702 		rte_free(env.digest);
703 		env.digest = rte_zmalloc(NULL, vec.aead.digest.len,
704 				RTE_CACHE_LINE_SIZE);
705 		if (!env.digest) {
706 			RTE_LOG(ERR, USER1, "Not enough memory\n");
707 			return -ENOMEM;
708 		}
709 		env.digest_len = vec.cipher_auth.digest.len;
710 
711 		sym->aead.data.length = vec.pt.len;
712 		sym->aead.digest.data = env.digest;
713 		sym->aead.digest.phys_addr = rte_malloc_virt2iova(env.digest);
714 	} else {
715 		ret = prepare_data_mbufs(&vec.ct);
716 		if (ret < 0)
717 			return ret;
718 
719 		sym->aead.data.length = vec.ct.len;
720 		sym->aead.digest.data = vec.aead.digest.val;
721 		sym->aead.digest.phys_addr = rte_malloc_virt2iova(
722 				sym->aead.digest.data);
723 	}
724 
725 	sym->m_src = env.mbuf;
726 	sym->aead.data.offset = 0;
727 	sym->aead.aad.data = vec.aead.aad.val;
728 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
729 
730 	rte_crypto_op_attach_sym_session(env.op, env.sess);
731 
732 	return 0;
733 }
734 
735 static int
736 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
737 {
738 	const struct rte_cryptodev_symmetric_capability *cap;
739 	struct rte_cryptodev_sym_capability_idx cap_idx;
740 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
741 
742 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
743 
744 	if (info.interim_info.aes_data.cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC)
745 		cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
746 	else
747 		cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_ECB;
748 
749 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
750 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
751 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
752 	cipher_xform->key.data = vec.cipher_auth.key.val;
753 	cipher_xform->key.length = vec.cipher_auth.key.len;
754 	if (cipher_xform->algo == RTE_CRYPTO_CIPHER_AES_CBC) {
755 		cipher_xform->iv.length = vec.iv.len;
756 		cipher_xform->iv.offset = IV_OFF;
757 	} else {
758 		cipher_xform->iv.length = 0;
759 		cipher_xform->iv.offset = 0;
760 	}
761 	cap_idx.algo.cipher = cipher_xform->algo;
762 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
763 
764 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
765 	if (!cap) {
766 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
767 				env.dev_id);
768 		return -EINVAL;
769 	}
770 
771 	if (rte_cryptodev_sym_capability_check_cipher(cap,
772 			cipher_xform->key.length,
773 			cipher_xform->iv.length) != 0) {
774 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
775 				info.device_name, cipher_xform->key.length,
776 				cipher_xform->iv.length);
777 		return -EPERM;
778 	}
779 
780 	return 0;
781 }
782 
783 static int
784 prepare_tdes_xform(struct rte_crypto_sym_xform *xform)
785 {
786 	const struct rte_cryptodev_symmetric_capability *cap;
787 	struct rte_cryptodev_sym_capability_idx cap_idx;
788 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
789 
790 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
791 
792 	if (info.interim_info.tdes_data.test_mode == TDES_MODE_CBC)
793 		cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
794 	else
795 		cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_ECB;
796 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
797 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
798 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
799 	cipher_xform->key.data = vec.cipher_auth.key.val;
800 	cipher_xform->key.length = vec.cipher_auth.key.len;
801 
802 	if (cipher_xform->algo == RTE_CRYPTO_CIPHER_3DES_CBC) {
803 		cipher_xform->iv.length = vec.iv.len;
804 		cipher_xform->iv.offset = IV_OFF;
805 	} else {
806 		cipher_xform->iv.length = 0;
807 		cipher_xform->iv.offset = 0;
808 	}
809 	cap_idx.algo.cipher = cipher_xform->algo;
810 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
811 
812 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
813 	if (!cap) {
814 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
815 				env.dev_id);
816 		return -EINVAL;
817 	}
818 
819 	if (rte_cryptodev_sym_capability_check_cipher(cap,
820 			cipher_xform->key.length,
821 			cipher_xform->iv.length) != 0) {
822 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
823 				info.device_name, cipher_xform->key.length,
824 				cipher_xform->iv.length);
825 		return -EPERM;
826 	}
827 
828 	return 0;
829 }
830 
831 static int
832 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
833 {
834 	const struct rte_cryptodev_symmetric_capability *cap;
835 	struct rte_cryptodev_sym_capability_idx cap_idx;
836 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
837 
838 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
839 
840 	auth_xform->algo = info.interim_info.hmac_data.algo;
841 	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
842 	auth_xform->digest_length = vec.cipher_auth.digest.len;
843 	auth_xform->key.data = vec.cipher_auth.key.val;
844 	auth_xform->key.length = vec.cipher_auth.key.len;
845 
846 	cap_idx.algo.auth = auth_xform->algo;
847 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
848 
849 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
850 	if (!cap) {
851 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
852 				env.dev_id);
853 		return -EINVAL;
854 	}
855 
856 	if (rte_cryptodev_sym_capability_check_auth(cap,
857 			auth_xform->key.length,
858 			auth_xform->digest_length, 0) != 0) {
859 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
860 				info.device_name, auth_xform->key.length,
861 				auth_xform->digest_length);
862 		return -EPERM;
863 	}
864 
865 	return 0;
866 }
867 
868 int
869 prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
870 {
871 	const struct rte_cryptodev_symmetric_capability *cap;
872 	struct rte_cryptodev_sym_capability_idx cap_idx;
873 	struct rte_crypto_aead_xform *aead_xform = &xform->aead;
874 
875 	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
876 
877 	aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
878 	aead_xform->aad_length = vec.aead.aad.len;
879 	aead_xform->digest_length = vec.aead.digest.len;
880 	aead_xform->iv.offset = IV_OFF;
881 	aead_xform->iv.length = vec.iv.len;
882 	aead_xform->key.data = vec.aead.key.val;
883 	aead_xform->key.length = vec.aead.key.len;
884 	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
885 			RTE_CRYPTO_AEAD_OP_ENCRYPT :
886 			RTE_CRYPTO_AEAD_OP_DECRYPT;
887 
888 	cap_idx.algo.aead = aead_xform->algo;
889 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
890 
891 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
892 	if (!cap) {
893 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
894 				env.dev_id);
895 		return -EINVAL;
896 	}
897 
898 	if (rte_cryptodev_sym_capability_check_aead(cap,
899 			aead_xform->key.length,
900 			aead_xform->digest_length, aead_xform->aad_length,
901 			aead_xform->iv.length) != 0) {
902 		RTE_LOG(ERR, USER1,
903 			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
904 				info.device_name, aead_xform->key.length,
905 				aead_xform->digest_length,
906 				aead_xform->aad_length,
907 				aead_xform->iv.length);
908 		return -EPERM;
909 	}
910 
911 	return 0;
912 }
913 
914 int
915 prepare_gmac_xform(struct rte_crypto_sym_xform *xform)
916 {
917 	const struct rte_cryptodev_symmetric_capability *cap;
918 	struct rte_cryptodev_sym_capability_idx cap_idx;
919 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
920 
921 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
922 
923 	auth_xform->algo = RTE_CRYPTO_AUTH_AES_GMAC;
924 	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
925 			RTE_CRYPTO_AUTH_OP_GENERATE :
926 			RTE_CRYPTO_AUTH_OP_VERIFY;
927 	auth_xform->iv.offset = IV_OFF;
928 	auth_xform->iv.length = vec.iv.len;
929 	auth_xform->digest_length = vec.aead.digest.len;
930 	auth_xform->key.data = vec.aead.key.val;
931 	auth_xform->key.length = vec.aead.key.len;
932 
933 	cap_idx.algo.auth = auth_xform->algo;
934 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
935 
936 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
937 	if (!cap) {
938 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
939 				env.dev_id);
940 		return -EINVAL;
941 	}
942 
943 	if (rte_cryptodev_sym_capability_check_auth(cap,
944 			auth_xform->key.length,
945 			auth_xform->digest_length,
946 			auth_xform->iv.length) != 0) {
947 
948 		RTE_LOG(ERR, USER1,
949 			"PMD %s key length %u Digest length %u IV length %u\n",
950 				info.device_name, auth_xform->key.length,
951 				auth_xform->digest_length,
952 				auth_xform->iv.length);
953 		return -EPERM;
954 	}
955 
956 	return 0;
957 }
958 
959 static int
960 prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
961 {
962 	const struct rte_cryptodev_symmetric_capability *cap;
963 	struct rte_cryptodev_sym_capability_idx cap_idx;
964 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
965 
966 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
967 
968 	auth_xform->algo = RTE_CRYPTO_AUTH_AES_CMAC;
969 	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
970 			RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
971 	auth_xform->digest_length = vec.cipher_auth.digest.len;
972 	auth_xform->key.data = vec.cipher_auth.key.val;
973 	auth_xform->key.length = vec.cipher_auth.key.len;
974 
975 	cap_idx.algo.auth = auth_xform->algo;
976 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
977 
978 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
979 	if (!cap) {
980 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
981 				env.dev_id);
982 		return -EINVAL;
983 	}
984 
985 	if (rte_cryptodev_sym_capability_check_auth(cap,
986 			auth_xform->key.length,
987 			auth_xform->digest_length, 0) != 0) {
988 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
989 				info.device_name, auth_xform->key.length,
990 				auth_xform->digest_length);
991 		return -EPERM;
992 	}
993 
994 	return 0;
995 }
996 
997 static int
998 prepare_ccm_xform(struct rte_crypto_sym_xform *xform)
999 {
1000 	const struct rte_cryptodev_symmetric_capability *cap;
1001 	struct rte_cryptodev_sym_capability_idx cap_idx;
1002 	struct rte_crypto_aead_xform *aead_xform = &xform->aead;
1003 
1004 	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
1005 
1006 	aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
1007 	aead_xform->aad_length = vec.aead.aad.len;
1008 	aead_xform->digest_length = vec.aead.digest.len;
1009 	aead_xform->iv.offset = IV_OFF;
1010 	aead_xform->iv.length = vec.iv.len;
1011 	aead_xform->key.data = vec.aead.key.val;
1012 	aead_xform->key.length = vec.aead.key.len;
1013 	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
1014 			RTE_CRYPTO_AEAD_OP_ENCRYPT :
1015 			RTE_CRYPTO_AEAD_OP_DECRYPT;
1016 
1017 	cap_idx.algo.aead = aead_xform->algo;
1018 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
1019 
1020 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1021 	if (!cap) {
1022 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1023 				env.dev_id);
1024 		return -EINVAL;
1025 	}
1026 
1027 	if (rte_cryptodev_sym_capability_check_aead(cap,
1028 			aead_xform->key.length,
1029 			aead_xform->digest_length, aead_xform->aad_length,
1030 			aead_xform->iv.length) != 0) {
1031 		RTE_LOG(ERR, USER1,
1032 			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
1033 				info.device_name, aead_xform->key.length,
1034 				aead_xform->digest_length,
1035 				aead_xform->aad_length,
1036 				aead_xform->iv.length);
1037 		return -EPERM;
1038 	}
1039 
1040 	return 0;
1041 }
1042 
1043 static int
1044 prepare_sha_xform(struct rte_crypto_sym_xform *xform)
1045 {
1046 	const struct rte_cryptodev_symmetric_capability *cap;
1047 	struct rte_cryptodev_sym_capability_idx cap_idx;
1048 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
1049 
1050 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
1051 
1052 	auth_xform->algo = info.interim_info.sha_data.algo;
1053 	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
1054 	auth_xform->digest_length = vec.cipher_auth.digest.len;
1055 
1056 	cap_idx.algo.auth = auth_xform->algo;
1057 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
1058 
1059 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1060 	if (!cap) {
1061 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1062 				env.dev_id);
1063 		return -EINVAL;
1064 	}
1065 
1066 	if (rte_cryptodev_sym_capability_check_auth(cap,
1067 			auth_xform->key.length,
1068 			auth_xform->digest_length, 0) != 0) {
1069 		RTE_LOG(ERR, USER1, "PMD %s key length %u digest length %u\n",
1070 				info.device_name, auth_xform->key.length,
1071 				auth_xform->digest_length);
1072 		return -EPERM;
1073 	}
1074 
1075 	return 0;
1076 }
1077 
1078 static int
1079 prepare_xts_xform(struct rte_crypto_sym_xform *xform)
1080 {
1081 	const struct rte_cryptodev_symmetric_capability *cap;
1082 	struct rte_cryptodev_sym_capability_idx cap_idx;
1083 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
1084 
1085 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1086 
1087 	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_XTS;
1088 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
1089 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
1090 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
1091 	cipher_xform->key.data = vec.cipher_auth.key.val;
1092 	cipher_xform->key.length = vec.cipher_auth.key.len;
1093 	cipher_xform->iv.length = vec.iv.len;
1094 	cipher_xform->iv.offset = IV_OFF;
1095 
1096 	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_XTS;
1097 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1098 
1099 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1100 	if (!cap) {
1101 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1102 				env.dev_id);
1103 		return -EINVAL;
1104 	}
1105 
1106 	if (rte_cryptodev_sym_capability_check_cipher(cap,
1107 			cipher_xform->key.length,
1108 			cipher_xform->iv.length) != 0) {
1109 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
1110 				info.device_name, cipher_xform->key.length,
1111 				cipher_xform->iv.length);
1112 		return -EPERM;
1113 	}
1114 
1115 	return 0;
1116 }
1117 
1118 static int
1119 get_writeback_data(struct fips_val *val)
1120 {
1121 	struct rte_mbuf *m = env.mbuf;
1122 	uint16_t data_len = rte_pktmbuf_pkt_len(m);
1123 	uint16_t total_len = data_len + env.digest_len;
1124 	uint8_t *src, *dst, *wb_data;
1125 
1126 	/* in case val is reused for MCT test, try to free the buffer first */
1127 	if (val->val) {
1128 		free(val->val);
1129 		val->val = NULL;
1130 	}
1131 
1132 	wb_data = dst = calloc(1, total_len);
1133 	if (!dst) {
1134 		RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
1135 		return -ENOMEM;
1136 	}
1137 
1138 	while (m && data_len) {
1139 		uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
1140 
1141 		src = rte_pktmbuf_mtod(m, uint8_t *);
1142 		memcpy(dst, src, seg_len);
1143 		m = m->next;
1144 		data_len -= seg_len;
1145 		dst += seg_len;
1146 	}
1147 
1148 	if (data_len) {
1149 		RTE_LOG(ERR, USER1, "Error -1: write back data\n");
1150 		free(wb_data);
1151 		return -1;
1152 	}
1153 
1154 	if (env.digest)
1155 		memcpy(dst, env.digest, env.digest_len);
1156 
1157 	val->val = wb_data;
1158 	val->len = total_len;
1159 
1160 	return 0;
1161 }
1162 
1163 static int
1164 fips_run_test(void)
1165 {
1166 	struct rte_crypto_sym_xform xform = {0};
1167 	uint16_t n_deqd;
1168 	int ret;
1169 
1170 	ret = test_ops.prepare_xform(&xform);
1171 	if (ret < 0)
1172 		return ret;
1173 
1174 	env.sess = rte_cryptodev_sym_session_create(env.sess_mpool);
1175 	if (!env.sess)
1176 		return -ENOMEM;
1177 
1178 	ret = rte_cryptodev_sym_session_init(env.dev_id,
1179 			env.sess, &xform, env.sess_priv_mpool);
1180 	if (ret < 0) {
1181 		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
1182 				ret);
1183 		goto exit;
1184 	}
1185 
1186 	ret = test_ops.prepare_op();
1187 	if (ret < 0) {
1188 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
1189 				ret);
1190 		goto exit;
1191 	}
1192 
1193 	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
1194 		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
1195 		ret = -1;
1196 		goto exit;
1197 	}
1198 
1199 	do {
1200 		struct rte_crypto_op *deqd_op;
1201 
1202 		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
1203 				1);
1204 	} while (n_deqd == 0);
1205 
1206 	vec.status = env.op->status;
1207 
1208 exit:
1209 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
1210 	rte_cryptodev_sym_session_free(env.sess);
1211 	env.sess = NULL;
1212 
1213 	return ret;
1214 }
1215 
1216 static int
1217 fips_generic_test(void)
1218 {
1219 	struct fips_val val = {NULL, 0};
1220 	int ret;
1221 
1222 	fips_test_write_one_case();
1223 
1224 	ret = fips_run_test();
1225 	if (ret < 0) {
1226 		if (ret == -EPERM || ret == -ENOTSUP) {
1227 			fprintf(info.fp_wr, "Bypass\n\n");
1228 			return 0;
1229 		}
1230 
1231 		return ret;
1232 	}
1233 
1234 	ret = get_writeback_data(&val);
1235 	if (ret < 0)
1236 		return ret;
1237 
1238 	switch (info.file_type) {
1239 	case FIPS_TYPE_REQ:
1240 	case FIPS_TYPE_RSP:
1241 		if (info.parse_writeback == NULL)
1242 			return -EPERM;
1243 		ret = info.parse_writeback(&val);
1244 		if (ret < 0)
1245 			return ret;
1246 		break;
1247 	case FIPS_TYPE_FAX:
1248 		if (info.kat_check == NULL)
1249 			return -EPERM;
1250 		ret = info.kat_check(&val);
1251 		if (ret < 0)
1252 			return ret;
1253 		break;
1254 	}
1255 
1256 	fprintf(info.fp_wr, "\n");
1257 	free(val.val);
1258 
1259 	return 0;
1260 }
1261 
1262 static int
1263 fips_mct_tdes_test(void)
1264 {
1265 #define TDES_BLOCK_SIZE		8
1266 #define TDES_EXTERN_ITER	400
1267 #define TDES_INTERN_ITER	10000
1268 	struct fips_val val = {NULL, 0}, val_key;
1269 	uint8_t prev_out[TDES_BLOCK_SIZE] = {0};
1270 	uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0};
1271 	uint8_t prev_in[TDES_BLOCK_SIZE] = {0};
1272 	uint32_t i, j, k;
1273 	int ret;
1274 	int test_mode = info.interim_info.tdes_data.test_mode;
1275 
1276 	for (i = 0; i < TDES_EXTERN_ITER; i++) {
1277 		if ((i == 0) && (info.version == 21.4f)) {
1278 			if (!(strstr(info.vec[0], "COUNT")))
1279 				fprintf(info.fp_wr, "%s%u\n", "COUNT = ", 0);
1280 		}
1281 
1282 		if (i != 0)
1283 			update_info_vec(i);
1284 
1285 		fips_test_write_one_case();
1286 
1287 		for (j = 0; j < TDES_INTERN_ITER; j++) {
1288 			ret = fips_run_test();
1289 			if (ret < 0) {
1290 				if (ret == -EPERM) {
1291 					fprintf(info.fp_wr, "Bypass\n");
1292 					return 0;
1293 				}
1294 				return ret;
1295 			}
1296 
1297 			ret = get_writeback_data(&val);
1298 			if (ret < 0)
1299 				return ret;
1300 
1301 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1302 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
1303 
1304 			if (j == 0) {
1305 				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
1306 
1307 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1308 					if (test_mode == TDES_MODE_ECB) {
1309 						memcpy(vec.pt.val, val.val,
1310 							   TDES_BLOCK_SIZE);
1311 					} else {
1312 						memcpy(vec.pt.val, vec.iv.val,
1313 							   TDES_BLOCK_SIZE);
1314 						memcpy(vec.iv.val, val.val,
1315 							   TDES_BLOCK_SIZE);
1316 					}
1317 
1318 				} else {
1319 					if (test_mode == TDES_MODE_ECB) {
1320 						memcpy(vec.ct.val, val.val,
1321 							   TDES_BLOCK_SIZE);
1322 					} else {
1323 						memcpy(vec.iv.val, vec.ct.val,
1324 							   TDES_BLOCK_SIZE);
1325 						memcpy(vec.ct.val, val.val,
1326 							   TDES_BLOCK_SIZE);
1327 					}
1328 				}
1329 				continue;
1330 			}
1331 
1332 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1333 				if (test_mode == TDES_MODE_ECB) {
1334 					memcpy(vec.pt.val, val.val,
1335 						   TDES_BLOCK_SIZE);
1336 				} else {
1337 					memcpy(vec.iv.val, val.val,
1338 						   TDES_BLOCK_SIZE);
1339 					memcpy(vec.pt.val, prev_out,
1340 						   TDES_BLOCK_SIZE);
1341 				}
1342 			} else {
1343 				if (test_mode == TDES_MODE_ECB) {
1344 					memcpy(vec.ct.val, val.val,
1345 						   TDES_BLOCK_SIZE);
1346 				} else {
1347 					memcpy(vec.iv.val, vec.ct.val,
1348 						   TDES_BLOCK_SIZE);
1349 					memcpy(vec.ct.val, val.val,
1350 						   TDES_BLOCK_SIZE);
1351 				}
1352 			}
1353 
1354 			if (j == TDES_INTERN_ITER - 1)
1355 				continue;
1356 
1357 			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
1358 
1359 			if (j == TDES_INTERN_ITER - 3)
1360 				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
1361 		}
1362 
1363 		info.parse_writeback(&val);
1364 		fprintf(info.fp_wr, "\n");
1365 
1366 		if (i == TDES_EXTERN_ITER - 1)
1367 			continue;
1368 
1369 		/** update key */
1370 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1371 
1372 		if (info.interim_info.tdes_data.nb_keys == 0) {
1373 			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
1374 				info.interim_info.tdes_data.nb_keys = 1;
1375 			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
1376 				info.interim_info.tdes_data.nb_keys = 2;
1377 			else
1378 				info.interim_info.tdes_data.nb_keys = 3;
1379 
1380 		}
1381 
1382 		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
1383 
1384 			switch (info.interim_info.tdes_data.nb_keys) {
1385 			case 3:
1386 				val_key.val[k] ^= val.val[k];
1387 				val_key.val[k + 8] ^= prev_out[k];
1388 				val_key.val[k + 16] ^= prev_prev_out[k];
1389 				break;
1390 			case 2:
1391 				val_key.val[k] ^= val.val[k];
1392 				val_key.val[k + 8] ^= prev_out[k];
1393 				val_key.val[k + 16] ^= val.val[k];
1394 				break;
1395 			default: /* case 1 */
1396 				val_key.val[k] ^= val.val[k];
1397 				val_key.val[k + 8] ^= val.val[k];
1398 				val_key.val[k + 16] ^= val.val[k];
1399 				break;
1400 			}
1401 
1402 		}
1403 
1404 		for (k = 0; k < 24; k++)
1405 			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
1406 					0x1) ?
1407 					val_key.val[k] : (val_key.val[k] ^ 0x1);
1408 
1409 		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1410 			if (test_mode == TDES_MODE_ECB) {
1411 				memcpy(vec.pt.val, val.val, TDES_BLOCK_SIZE);
1412 			} else {
1413 				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
1414 				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
1415 			}
1416 		} else {
1417 			if (test_mode == TDES_MODE_ECB) {
1418 				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1419 			} else {
1420 				memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
1421 				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1422 			}
1423 		}
1424 	}
1425 
1426 	free(val.val);
1427 
1428 	return 0;
1429 }
1430 
1431 static int
1432 fips_mct_aes_ecb_test(void)
1433 {
1434 #define AES_BLOCK_SIZE	16
1435 #define AES_EXTERN_ITER	100
1436 #define AES_INTERN_ITER	1000
1437 	struct fips_val val = {NULL, 0}, val_key;
1438 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1439 	uint32_t i, j, k;
1440 	int ret;
1441 
1442 	for (i = 0; i < AES_EXTERN_ITER; i++) {
1443 		if (i != 0)
1444 			update_info_vec(i);
1445 
1446 		fips_test_write_one_case();
1447 
1448 		for (j = 0; j < AES_INTERN_ITER; j++) {
1449 			ret = fips_run_test();
1450 			if (ret < 0) {
1451 				if (ret == -EPERM) {
1452 					fprintf(info.fp_wr, "Bypass\n");
1453 					return 0;
1454 				}
1455 
1456 				return ret;
1457 			}
1458 
1459 			ret = get_writeback_data(&val);
1460 			if (ret < 0)
1461 				return ret;
1462 
1463 			if (info.op == FIPS_TEST_ENC_AUTH_GEN)
1464 				memcpy(vec.pt.val, val.val, AES_BLOCK_SIZE);
1465 			else
1466 				memcpy(vec.ct.val, val.val, AES_BLOCK_SIZE);
1467 
1468 			if (j == AES_INTERN_ITER - 1)
1469 				continue;
1470 
1471 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1472 		}
1473 
1474 		info.parse_writeback(&val);
1475 		fprintf(info.fp_wr, "\n");
1476 
1477 		if (i == AES_EXTERN_ITER - 1)
1478 			continue;
1479 
1480 		/** update key */
1481 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1482 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
1483 			switch (vec.cipher_auth.key.len) {
1484 			case 16:
1485 				val_key.val[k] ^= val.val[k];
1486 				break;
1487 			case 24:
1488 				if (k < 8)
1489 					val_key.val[k] ^= prev_out[k + 8];
1490 				else
1491 					val_key.val[k] ^= val.val[k - 8];
1492 				break;
1493 			case 32:
1494 				if (k < 16)
1495 					val_key.val[k] ^= prev_out[k];
1496 				else
1497 					val_key.val[k] ^= val.val[k - 16];
1498 				break;
1499 			default:
1500 				return -1;
1501 			}
1502 		}
1503 	}
1504 
1505 	free(val.val);
1506 
1507 	return 0;
1508 }
1509 static int
1510 fips_mct_aes_test(void)
1511 {
1512 #define AES_BLOCK_SIZE	16
1513 #define AES_EXTERN_ITER	100
1514 #define AES_INTERN_ITER	1000
1515 	struct fips_val val = {NULL, 0}, val_key;
1516 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1517 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
1518 	uint32_t i, j, k;
1519 	int ret;
1520 
1521 	if (info.interim_info.aes_data.cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB)
1522 		return fips_mct_aes_ecb_test();
1523 
1524 	for (i = 0; i < AES_EXTERN_ITER; i++) {
1525 		if (i != 0)
1526 			update_info_vec(i);
1527 
1528 		fips_test_write_one_case();
1529 
1530 		for (j = 0; j < AES_INTERN_ITER; j++) {
1531 			ret = fips_run_test();
1532 			if (ret < 0) {
1533 				if (ret == -EPERM) {
1534 					fprintf(info.fp_wr, "Bypass\n");
1535 					return 0;
1536 				}
1537 
1538 				return ret;
1539 			}
1540 
1541 			ret = get_writeback_data(&val);
1542 			if (ret < 0)
1543 				return ret;
1544 
1545 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1546 				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
1547 
1548 			if (j == 0) {
1549 				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1550 
1551 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1552 					memcpy(vec.pt.val, vec.iv.val,
1553 							AES_BLOCK_SIZE);
1554 					memcpy(vec.iv.val, val.val,
1555 							AES_BLOCK_SIZE);
1556 				} else {
1557 					memcpy(vec.ct.val, vec.iv.val,
1558 							AES_BLOCK_SIZE);
1559 					memcpy(vec.iv.val, prev_in,
1560 							AES_BLOCK_SIZE);
1561 				}
1562 				continue;
1563 			}
1564 
1565 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1566 				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1567 				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
1568 			} else {
1569 				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
1570 				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
1571 			}
1572 
1573 			if (j == AES_INTERN_ITER - 1)
1574 				continue;
1575 
1576 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1577 		}
1578 
1579 		info.parse_writeback(&val);
1580 		fprintf(info.fp_wr, "\n");
1581 
1582 		if (i == AES_EXTERN_ITER - 1)
1583 			continue;
1584 
1585 		/** update key */
1586 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1587 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
1588 			switch (vec.cipher_auth.key.len) {
1589 			case 16:
1590 				val_key.val[k] ^= val.val[k];
1591 				break;
1592 			case 24:
1593 				if (k < 8)
1594 					val_key.val[k] ^= prev_out[k + 8];
1595 				else
1596 					val_key.val[k] ^= val.val[k - 8];
1597 				break;
1598 			case 32:
1599 				if (k < 16)
1600 					val_key.val[k] ^= prev_out[k];
1601 				else
1602 					val_key.val[k] ^= val.val[k - 16];
1603 				break;
1604 			default:
1605 				return -1;
1606 			}
1607 		}
1608 
1609 		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1610 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1611 	}
1612 
1613 	free(val.val);
1614 
1615 	return 0;
1616 }
1617 
1618 static int
1619 fips_mct_sha_test(void)
1620 {
1621 #define SHA_EXTERN_ITER	100
1622 #define SHA_INTERN_ITER	1000
1623 #define SHA_MD_BLOCK	3
1624 	struct fips_val val = {NULL, 0}, md[SHA_MD_BLOCK];
1625 	char temp[MAX_DIGEST_SIZE*2];
1626 	int ret;
1627 	uint32_t i, j;
1628 
1629 	for (i = 0; i < SHA_MD_BLOCK; i++)
1630 		md[i].val = rte_malloc(NULL, (MAX_DIGEST_SIZE*2), 0);
1631 
1632 	rte_free(vec.pt.val);
1633 	vec.pt.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0);
1634 
1635 	fips_test_write_one_case();
1636 	fprintf(info.fp_wr, "\n");
1637 
1638 	for (j = 0; j < SHA_EXTERN_ITER; j++) {
1639 
1640 		memcpy(md[0].val, vec.cipher_auth.digest.val,
1641 			vec.cipher_auth.digest.len);
1642 		md[0].len = vec.cipher_auth.digest.len;
1643 		memcpy(md[1].val, vec.cipher_auth.digest.val,
1644 			vec.cipher_auth.digest.len);
1645 		md[1].len = vec.cipher_auth.digest.len;
1646 		memcpy(md[2].val, vec.cipher_auth.digest.val,
1647 			vec.cipher_auth.digest.len);
1648 		md[2].len = vec.cipher_auth.digest.len;
1649 
1650 		for (i = 0; i < (SHA_INTERN_ITER); i++) {
1651 
1652 			memcpy(vec.pt.val, md[0].val,
1653 				(size_t)md[0].len);
1654 			memcpy((vec.pt.val + md[0].len), md[1].val,
1655 				(size_t)md[1].len);
1656 			memcpy((vec.pt.val + md[0].len + md[1].len),
1657 				md[2].val,
1658 				(size_t)md[2].len);
1659 			vec.pt.len = md[0].len + md[1].len + md[2].len;
1660 
1661 			ret = fips_run_test();
1662 			if (ret < 0) {
1663 				if (ret == -EPERM || ret == -ENOTSUP) {
1664 					fprintf(info.fp_wr, "Bypass\n\n");
1665 					return 0;
1666 				}
1667 				return ret;
1668 			}
1669 
1670 			ret = get_writeback_data(&val);
1671 			if (ret < 0)
1672 				return ret;
1673 
1674 			memcpy(md[0].val, md[1].val, md[1].len);
1675 			md[0].len = md[1].len;
1676 			memcpy(md[1].val, md[2].val, md[2].len);
1677 			md[1].len = md[2].len;
1678 
1679 			memcpy(md[2].val, (val.val + vec.pt.len),
1680 				vec.cipher_auth.digest.len);
1681 			md[2].len = vec.cipher_auth.digest.len;
1682 		}
1683 
1684 		memcpy(vec.cipher_auth.digest.val, md[2].val, md[2].len);
1685 		vec.cipher_auth.digest.len = md[2].len;
1686 
1687 		fprintf(info.fp_wr, "COUNT = %u\n", j);
1688 
1689 		writeback_hex_str("", temp, &vec.cipher_auth.digest);
1690 
1691 		fprintf(info.fp_wr, "MD = %s\n\n", temp);
1692 	}
1693 
1694 	for (i = 0; i < (SHA_MD_BLOCK); i++)
1695 		rte_free(md[i].val);
1696 
1697 	rte_free(vec.pt.val);
1698 
1699 	free(val.val);
1700 
1701 	return 0;
1702 }
1703 
1704 
1705 static int
1706 init_test_ops(void)
1707 {
1708 	switch (info.algo) {
1709 	case FIPS_TEST_ALGO_AES:
1710 		test_ops.prepare_op = prepare_cipher_op;
1711 		test_ops.prepare_xform  = prepare_aes_xform;
1712 		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
1713 			test_ops.test = fips_mct_aes_test;
1714 		else
1715 			test_ops.test = fips_generic_test;
1716 		break;
1717 	case FIPS_TEST_ALGO_HMAC:
1718 		test_ops.prepare_op = prepare_auth_op;
1719 		test_ops.prepare_xform = prepare_hmac_xform;
1720 		test_ops.test = fips_generic_test;
1721 		break;
1722 	case FIPS_TEST_ALGO_TDES:
1723 		test_ops.prepare_op = prepare_cipher_op;
1724 		test_ops.prepare_xform  = prepare_tdes_xform;
1725 		if (info.interim_info.tdes_data.test_type == TDES_MCT)
1726 			test_ops.test = fips_mct_tdes_test;
1727 		else
1728 			test_ops.test = fips_generic_test;
1729 		break;
1730 	case FIPS_TEST_ALGO_AES_GCM:
1731 		test_ops.prepare_op = prepare_aead_op;
1732 		test_ops.prepare_xform = prepare_gcm_xform;
1733 		test_ops.test = fips_generic_test;
1734 		break;
1735 	case FIPS_TEST_ALGO_AES_CMAC:
1736 		test_ops.prepare_op = prepare_auth_op;
1737 		test_ops.prepare_xform = prepare_cmac_xform;
1738 		test_ops.test = fips_generic_test;
1739 		break;
1740 	case FIPS_TEST_ALGO_AES_CCM:
1741 		test_ops.prepare_op = prepare_aead_op;
1742 		test_ops.prepare_xform = prepare_ccm_xform;
1743 		test_ops.test = fips_generic_test;
1744 		break;
1745 	case FIPS_TEST_ALGO_SHA:
1746 		test_ops.prepare_op = prepare_auth_op;
1747 		test_ops.prepare_xform = prepare_sha_xform;
1748 		if (info.interim_info.sha_data.test_type == SHA_MCT)
1749 			test_ops.test = fips_mct_sha_test;
1750 		else
1751 			test_ops.test = fips_generic_test;
1752 		break;
1753 	case FIPS_TEST_ALGO_AES_XTS:
1754 		test_ops.prepare_op = prepare_cipher_op;
1755 		test_ops.prepare_xform = prepare_xts_xform;
1756 		test_ops.test = fips_generic_test;
1757 		break;
1758 	default:
1759 		if (strstr(info.file_name, "TECB") ||
1760 				strstr(info.file_name, "TCBC")) {
1761 			info.algo = FIPS_TEST_ALGO_TDES;
1762 			test_ops.prepare_op = prepare_cipher_op;
1763 			test_ops.prepare_xform	= prepare_tdes_xform;
1764 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
1765 				test_ops.test = fips_mct_tdes_test;
1766 			else
1767 				test_ops.test = fips_generic_test;
1768 			break;
1769 		}
1770 		return -1;
1771 	}
1772 
1773 	return 0;
1774 }
1775 
1776 static void
1777 print_test_block(void)
1778 {
1779 	uint32_t i;
1780 
1781 	for (i = 0; i < info.nb_vec_lines; i++)
1782 		printf("%s\n", info.vec[i]);
1783 
1784 	printf("\n");
1785 }
1786 
1787 static int
1788 fips_test_one_file(void)
1789 {
1790 	int fetch_ret = 0, ret;
1791 
1792 	ret = init_test_ops();
1793 	if (ret < 0) {
1794 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
1795 		return ret;
1796 	}
1797 
1798 	while (ret >= 0 && fetch_ret == 0) {
1799 		fetch_ret = fips_test_fetch_one_block();
1800 		if (fetch_ret < 0) {
1801 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
1802 					fetch_ret);
1803 			ret = fetch_ret;
1804 			goto error_one_case;
1805 		}
1806 
1807 		if (info.nb_vec_lines == 0) {
1808 			if (fetch_ret == -EOF)
1809 				break;
1810 
1811 			fprintf(info.fp_wr, "\n");
1812 			continue;
1813 		}
1814 
1815 		ret = fips_test_parse_one_case();
1816 		switch (ret) {
1817 		case 0:
1818 			ret = test_ops.test();
1819 			if (ret == 0)
1820 				break;
1821 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
1822 					ret);
1823 			goto error_one_case;
1824 		case 1:
1825 			break;
1826 		default:
1827 			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
1828 					ret);
1829 			goto error_one_case;
1830 		}
1831 
1832 		continue;
1833 error_one_case:
1834 		print_test_block();
1835 	}
1836 
1837 	fips_test_clear();
1838 
1839 	if (env.digest) {
1840 		rte_free(env.digest);
1841 		env.digest = NULL;
1842 	}
1843 	rte_pktmbuf_free(env.mbuf);
1844 
1845 	return ret;
1846 }
1847