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