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