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