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