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