xref: /dpdk/examples/fips_validation/main.c (revision bc8e32473cc3978d763a1387eaa8244bcf75e77d)
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 struct fips_test_ops test_ops;
494 
495 static int
496 prepare_data_mbufs(struct fips_val *val)
497 {
498 	struct rte_mbuf *m, *head = 0;
499 	uint8_t *src = val->val;
500 	uint32_t total_len = val->len;
501 	uint16_t nb_seg;
502 	int ret = 0;
503 
504 	if (env.mbuf)
505 		rte_pktmbuf_free(env.mbuf);
506 
507 	if (total_len > RTE_MBUF_MAX_NB_SEGS) {
508 		RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
509 		return -EPERM;
510 	}
511 
512 	nb_seg = total_len / env.mbuf_data_room;
513 	if (total_len % env.mbuf_data_room)
514 		nb_seg++;
515 
516 	m = rte_pktmbuf_alloc(env.mpool);
517 	if (!m) {
518 		RTE_LOG(ERR, USER1, "Error %i: Not enough mbuf\n",
519 				-ENOMEM);
520 		return -ENOMEM;
521 	}
522 	head = m;
523 
524 	while (nb_seg) {
525 		uint16_t len = RTE_MIN(total_len, env.mbuf_data_room);
526 		uint8_t *dst = (uint8_t *)rte_pktmbuf_append(m, len);
527 
528 		if (!dst) {
529 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
530 					-ENOMEM);
531 			ret = -ENOMEM;
532 			goto error_exit;
533 		}
534 
535 		memcpy(dst, src, len);
536 
537 		if (head != m) {
538 			ret = rte_pktmbuf_chain(head, m);
539 			if (ret) {
540 				rte_pktmbuf_free(m);
541 				RTE_LOG(ERR, USER1, "Error %i: SGL build\n",
542 						ret);
543 				goto error_exit;
544 			}
545 		}
546 		total_len -= len;
547 
548 		if (total_len) {
549 			if (!env.dev_support_sgl) {
550 				RTE_LOG(ERR, USER1, "SGL not supported\n");
551 				ret = -EPERM;
552 				goto error_exit;
553 			}
554 
555 			m = rte_pktmbuf_alloc(env.mpool);
556 			if (!m) {
557 				RTE_LOG(ERR, USER1, "Error %i: No memory\n",
558 						-ENOMEM);
559 				goto error_exit;
560 			}
561 		} else
562 			break;
563 
564 		src += len;
565 		nb_seg--;
566 	}
567 
568 	if (total_len) {
569 		RTE_LOG(ERR, USER1, "Error %i: Failed to store all data\n",
570 				-ENOMEM);
571 		goto error_exit;
572 	}
573 
574 	env.mbuf = head;
575 
576 	return 0;
577 
578 error_exit:
579 	if (head)
580 		rte_pktmbuf_free(head);
581 	return ret;
582 }
583 
584 static int
585 prepare_cipher_op(void)
586 {
587 	struct rte_crypto_sym_op *sym = env.op->sym;
588 	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
589 	int ret;
590 
591 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
592 
593 	memcpy(iv, vec.iv.val, vec.iv.len);
594 
595 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
596 		ret = prepare_data_mbufs(&vec.pt);
597 		if (ret < 0)
598 			return ret;
599 
600 		sym->cipher.data.length = vec.pt.len;
601 	} else {
602 		ret = prepare_data_mbufs(&vec.ct);
603 		if (ret < 0)
604 			return ret;
605 
606 		sym->cipher.data.length = vec.ct.len;
607 	}
608 
609 	rte_crypto_op_attach_sym_session(env.op, env.sess);
610 
611 	sym->m_src = env.mbuf;
612 	sym->cipher.data.offset = 0;
613 
614 	return 0;
615 }
616 
617 int
618 prepare_auth_op(void)
619 {
620 	struct rte_crypto_sym_op *sym = env.op->sym;
621 	int ret;
622 
623 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
624 
625 	if (vec.iv.len) {
626 		uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *,
627 				IV_OFF);
628 		memset(iv, 0, vec.iv.len);
629 		if (vec.iv.val)
630 			memcpy(iv, vec.iv.val, vec.iv.len);
631 	}
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 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 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 int
900 prepare_gmac_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_GMAC;
909 	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
910 			RTE_CRYPTO_AUTH_OP_GENERATE :
911 			RTE_CRYPTO_AUTH_OP_VERIFY;
912 	auth_xform->iv.offset = IV_OFF;
913 	auth_xform->iv.length = vec.iv.len;
914 	auth_xform->digest_length = vec.aead.digest.len;
915 	auth_xform->key.data = vec.aead.key.val;
916 	auth_xform->key.length = vec.aead.key.len;
917 
918 	cap_idx.algo.auth = auth_xform->algo;
919 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
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_auth(cap,
929 			auth_xform->key.length,
930 			auth_xform->digest_length,
931 			auth_xform->iv.length) != 0) {
932 
933 		RTE_LOG(ERR, USER1,
934 			"PMD %s key length %u Digest length %u IV length %u\n",
935 				info.device_name, auth_xform->key.length,
936 				auth_xform->digest_length,
937 				auth_xform->iv.length);
938 		return -EPERM;
939 	}
940 
941 	return 0;
942 }
943 
944 static int
945 prepare_cmac_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_CMAC;
954 	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
955 			RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
956 	auth_xform->digest_length = vec.cipher_auth.digest.len;
957 	auth_xform->key.data = vec.cipher_auth.key.val;
958 	auth_xform->key.length = vec.cipher_auth.key.len;
959 
960 	cap_idx.algo.auth = auth_xform->algo;
961 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
962 
963 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
964 	if (!cap) {
965 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
966 				env.dev_id);
967 		return -EINVAL;
968 	}
969 
970 	if (rte_cryptodev_sym_capability_check_auth(cap,
971 			auth_xform->key.length,
972 			auth_xform->digest_length, 0) != 0) {
973 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
974 				info.device_name, auth_xform->key.length,
975 				auth_xform->digest_length);
976 		return -EPERM;
977 	}
978 
979 	return 0;
980 }
981 
982 static int
983 prepare_ccm_xform(struct rte_crypto_sym_xform *xform)
984 {
985 	const struct rte_cryptodev_symmetric_capability *cap;
986 	struct rte_cryptodev_sym_capability_idx cap_idx;
987 	struct rte_crypto_aead_xform *aead_xform = &xform->aead;
988 
989 	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
990 
991 	aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
992 	aead_xform->aad_length = vec.aead.aad.len;
993 	aead_xform->digest_length = vec.aead.digest.len;
994 	aead_xform->iv.offset = IV_OFF;
995 	aead_xform->iv.length = vec.iv.len;
996 	aead_xform->key.data = vec.aead.key.val;
997 	aead_xform->key.length = vec.aead.key.len;
998 	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
999 			RTE_CRYPTO_AEAD_OP_ENCRYPT :
1000 			RTE_CRYPTO_AEAD_OP_DECRYPT;
1001 
1002 	cap_idx.algo.aead = aead_xform->algo;
1003 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
1004 
1005 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1006 	if (!cap) {
1007 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1008 				env.dev_id);
1009 		return -EINVAL;
1010 	}
1011 
1012 	if (rte_cryptodev_sym_capability_check_aead(cap,
1013 			aead_xform->key.length,
1014 			aead_xform->digest_length, aead_xform->aad_length,
1015 			aead_xform->iv.length) != 0) {
1016 		RTE_LOG(ERR, USER1,
1017 			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
1018 				info.device_name, aead_xform->key.length,
1019 				aead_xform->digest_length,
1020 				aead_xform->aad_length,
1021 				aead_xform->iv.length);
1022 		return -EPERM;
1023 	}
1024 
1025 	return 0;
1026 }
1027 
1028 static int
1029 prepare_sha_xform(struct rte_crypto_sym_xform *xform)
1030 {
1031 	const struct rte_cryptodev_symmetric_capability *cap;
1032 	struct rte_cryptodev_sym_capability_idx cap_idx;
1033 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
1034 
1035 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
1036 
1037 	auth_xform->algo = info.interim_info.sha_data.algo;
1038 	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
1039 	auth_xform->digest_length = vec.cipher_auth.digest.len;
1040 
1041 	cap_idx.algo.auth = auth_xform->algo;
1042 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
1043 
1044 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1045 	if (!cap) {
1046 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1047 				env.dev_id);
1048 		return -EINVAL;
1049 	}
1050 
1051 	if (rte_cryptodev_sym_capability_check_auth(cap,
1052 			auth_xform->key.length,
1053 			auth_xform->digest_length, 0) != 0) {
1054 		RTE_LOG(ERR, USER1, "PMD %s key length %u digest length %u\n",
1055 				info.device_name, auth_xform->key.length,
1056 				auth_xform->digest_length);
1057 		return -EPERM;
1058 	}
1059 
1060 	return 0;
1061 }
1062 
1063 static int
1064 prepare_xts_xform(struct rte_crypto_sym_xform *xform)
1065 {
1066 	const struct rte_cryptodev_symmetric_capability *cap;
1067 	struct rte_cryptodev_sym_capability_idx cap_idx;
1068 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
1069 
1070 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1071 
1072 	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_XTS;
1073 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
1074 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
1075 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
1076 	cipher_xform->key.data = vec.cipher_auth.key.val;
1077 	cipher_xform->key.length = vec.cipher_auth.key.len;
1078 	cipher_xform->iv.length = vec.iv.len;
1079 	cipher_xform->iv.offset = IV_OFF;
1080 
1081 	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_XTS;
1082 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1083 
1084 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1085 	if (!cap) {
1086 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1087 				env.dev_id);
1088 		return -EINVAL;
1089 	}
1090 
1091 	if (rte_cryptodev_sym_capability_check_cipher(cap,
1092 			cipher_xform->key.length,
1093 			cipher_xform->iv.length) != 0) {
1094 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
1095 				info.device_name, cipher_xform->key.length,
1096 				cipher_xform->iv.length);
1097 		return -EPERM;
1098 	}
1099 
1100 	return 0;
1101 }
1102 
1103 static int
1104 get_writeback_data(struct fips_val *val)
1105 {
1106 	struct rte_mbuf *m = env.mbuf;
1107 	uint16_t data_len = rte_pktmbuf_pkt_len(m);
1108 	uint16_t total_len = data_len + env.digest_len;
1109 	uint8_t *src, *dst, *wb_data;
1110 
1111 	/* in case val is reused for MCT test, try to free the buffer first */
1112 	if (val->val) {
1113 		free(val->val);
1114 		val->val = NULL;
1115 	}
1116 
1117 	wb_data = dst = calloc(1, total_len);
1118 	if (!dst) {
1119 		RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
1120 		return -ENOMEM;
1121 	}
1122 
1123 	while (m && data_len) {
1124 		uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
1125 
1126 		src = rte_pktmbuf_mtod(m, uint8_t *);
1127 		memcpy(dst, src, seg_len);
1128 		m = m->next;
1129 		data_len -= seg_len;
1130 		dst += seg_len;
1131 	}
1132 
1133 	if (data_len) {
1134 		RTE_LOG(ERR, USER1, "Error -1: write back data\n");
1135 		free(wb_data);
1136 		return -1;
1137 	}
1138 
1139 	if (env.digest)
1140 		memcpy(dst, env.digest, env.digest_len);
1141 
1142 	val->val = wb_data;
1143 	val->len = total_len;
1144 
1145 	return 0;
1146 }
1147 
1148 static int
1149 fips_run_test(void)
1150 {
1151 	struct rte_crypto_sym_xform xform = {0};
1152 	uint16_t n_deqd;
1153 	int ret;
1154 
1155 	ret = test_ops.prepare_xform(&xform);
1156 	if (ret < 0)
1157 		return ret;
1158 
1159 	env.sess = rte_cryptodev_sym_session_create(env.sess_mpool);
1160 	if (!env.sess)
1161 		return -ENOMEM;
1162 
1163 	ret = rte_cryptodev_sym_session_init(env.dev_id,
1164 			env.sess, &xform, env.sess_priv_mpool);
1165 	if (ret < 0) {
1166 		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
1167 				ret);
1168 		goto exit;
1169 	}
1170 
1171 	ret = test_ops.prepare_op();
1172 	if (ret < 0) {
1173 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
1174 				ret);
1175 		goto exit;
1176 	}
1177 
1178 	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
1179 		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
1180 		ret = -1;
1181 		goto exit;
1182 	}
1183 
1184 	do {
1185 		struct rte_crypto_op *deqd_op;
1186 
1187 		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
1188 				1);
1189 	} while (n_deqd == 0);
1190 
1191 	vec.status = env.op->status;
1192 
1193 exit:
1194 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
1195 	rte_cryptodev_sym_session_free(env.sess);
1196 	env.sess = NULL;
1197 
1198 	return ret;
1199 }
1200 
1201 static int
1202 fips_generic_test(void)
1203 {
1204 	struct fips_val val = {NULL, 0};
1205 	int ret;
1206 
1207 	fips_test_write_one_case();
1208 
1209 	ret = fips_run_test();
1210 	if (ret < 0) {
1211 		if (ret == -EPERM || ret == -ENOTSUP) {
1212 			fprintf(info.fp_wr, "Bypass\n\n");
1213 			return 0;
1214 		}
1215 
1216 		return ret;
1217 	}
1218 
1219 	ret = get_writeback_data(&val);
1220 	if (ret < 0)
1221 		return ret;
1222 
1223 	switch (info.file_type) {
1224 	case FIPS_TYPE_REQ:
1225 	case FIPS_TYPE_RSP:
1226 		if (info.parse_writeback == NULL)
1227 			return -EPERM;
1228 		ret = info.parse_writeback(&val);
1229 		if (ret < 0)
1230 			return ret;
1231 		break;
1232 	case FIPS_TYPE_FAX:
1233 		if (info.kat_check == NULL)
1234 			return -EPERM;
1235 		ret = info.kat_check(&val);
1236 		if (ret < 0)
1237 			return ret;
1238 		break;
1239 	}
1240 
1241 	fprintf(info.fp_wr, "\n");
1242 	free(val.val);
1243 
1244 	return 0;
1245 }
1246 
1247 static int
1248 fips_mct_tdes_test(void)
1249 {
1250 #define TDES_BLOCK_SIZE		8
1251 #define TDES_EXTERN_ITER	400
1252 #define TDES_INTERN_ITER	10000
1253 	struct fips_val val = {NULL, 0}, val_key;
1254 	uint8_t prev_out[TDES_BLOCK_SIZE] = {0};
1255 	uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0};
1256 	uint8_t prev_in[TDES_BLOCK_SIZE] = {0};
1257 	uint32_t i, j, k;
1258 	int ret;
1259 	int test_mode = info.interim_info.tdes_data.test_mode;
1260 
1261 	for (i = 0; i < TDES_EXTERN_ITER; i++) {
1262 		if ((i == 0) && (info.version == 21.4f)) {
1263 			if (!(strstr(info.vec[0], "COUNT")))
1264 				fprintf(info.fp_wr, "%s%u\n", "COUNT = ", 0);
1265 		}
1266 
1267 		if (i != 0)
1268 			update_info_vec(i);
1269 
1270 		fips_test_write_one_case();
1271 
1272 		for (j = 0; j < TDES_INTERN_ITER; j++) {
1273 			ret = fips_run_test();
1274 			if (ret < 0) {
1275 				if (ret == -EPERM) {
1276 					fprintf(info.fp_wr, "Bypass\n");
1277 					return 0;
1278 				}
1279 				return ret;
1280 			}
1281 
1282 			ret = get_writeback_data(&val);
1283 			if (ret < 0)
1284 				return ret;
1285 
1286 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1287 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
1288 
1289 			if (j == 0) {
1290 				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
1291 
1292 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1293 					if (test_mode == TDES_MODE_ECB) {
1294 						memcpy(vec.pt.val, val.val,
1295 							   TDES_BLOCK_SIZE);
1296 					} else {
1297 						memcpy(vec.pt.val, vec.iv.val,
1298 							   TDES_BLOCK_SIZE);
1299 						memcpy(vec.iv.val, val.val,
1300 							   TDES_BLOCK_SIZE);
1301 					}
1302 
1303 				} else {
1304 					if (test_mode == TDES_MODE_ECB) {
1305 						memcpy(vec.ct.val, val.val,
1306 							   TDES_BLOCK_SIZE);
1307 					} else {
1308 						memcpy(vec.iv.val, vec.ct.val,
1309 							   TDES_BLOCK_SIZE);
1310 						memcpy(vec.ct.val, val.val,
1311 							   TDES_BLOCK_SIZE);
1312 					}
1313 				}
1314 				continue;
1315 			}
1316 
1317 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1318 				if (test_mode == TDES_MODE_ECB) {
1319 					memcpy(vec.pt.val, val.val,
1320 						   TDES_BLOCK_SIZE);
1321 				} else {
1322 					memcpy(vec.iv.val, val.val,
1323 						   TDES_BLOCK_SIZE);
1324 					memcpy(vec.pt.val, prev_out,
1325 						   TDES_BLOCK_SIZE);
1326 				}
1327 			} else {
1328 				if (test_mode == TDES_MODE_ECB) {
1329 					memcpy(vec.ct.val, val.val,
1330 						   TDES_BLOCK_SIZE);
1331 				} else {
1332 					memcpy(vec.iv.val, vec.ct.val,
1333 						   TDES_BLOCK_SIZE);
1334 					memcpy(vec.ct.val, val.val,
1335 						   TDES_BLOCK_SIZE);
1336 				}
1337 			}
1338 
1339 			if (j == TDES_INTERN_ITER - 1)
1340 				continue;
1341 
1342 			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
1343 
1344 			if (j == TDES_INTERN_ITER - 3)
1345 				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
1346 		}
1347 
1348 		info.parse_writeback(&val);
1349 		fprintf(info.fp_wr, "\n");
1350 
1351 		if (i == TDES_EXTERN_ITER - 1)
1352 			continue;
1353 
1354 		/** update key */
1355 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1356 
1357 		if (info.interim_info.tdes_data.nb_keys == 0) {
1358 			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
1359 				info.interim_info.tdes_data.nb_keys = 1;
1360 			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
1361 				info.interim_info.tdes_data.nb_keys = 2;
1362 			else
1363 				info.interim_info.tdes_data.nb_keys = 3;
1364 
1365 		}
1366 
1367 		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
1368 
1369 			switch (info.interim_info.tdes_data.nb_keys) {
1370 			case 3:
1371 				val_key.val[k] ^= val.val[k];
1372 				val_key.val[k + 8] ^= prev_out[k];
1373 				val_key.val[k + 16] ^= prev_prev_out[k];
1374 				break;
1375 			case 2:
1376 				val_key.val[k] ^= val.val[k];
1377 				val_key.val[k + 8] ^= prev_out[k];
1378 				val_key.val[k + 16] ^= val.val[k];
1379 				break;
1380 			default: /* case 1 */
1381 				val_key.val[k] ^= val.val[k];
1382 				val_key.val[k + 8] ^= val.val[k];
1383 				val_key.val[k + 16] ^= val.val[k];
1384 				break;
1385 			}
1386 
1387 		}
1388 
1389 		for (k = 0; k < 24; k++)
1390 			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
1391 					0x1) ?
1392 					val_key.val[k] : (val_key.val[k] ^ 0x1);
1393 
1394 		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1395 			if (test_mode == TDES_MODE_ECB) {
1396 				memcpy(vec.pt.val, val.val, TDES_BLOCK_SIZE);
1397 			} else {
1398 				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
1399 				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
1400 			}
1401 		} else {
1402 			if (test_mode == TDES_MODE_ECB) {
1403 				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1404 			} else {
1405 				memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
1406 				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1407 			}
1408 		}
1409 	}
1410 
1411 	if (val.val)
1412 		free(val.val);
1413 
1414 	return 0;
1415 }
1416 
1417 static int
1418 fips_mct_aes_ecb_test(void)
1419 {
1420 #define AES_BLOCK_SIZE	16
1421 #define AES_EXTERN_ITER	100
1422 #define AES_INTERN_ITER	1000
1423 	struct fips_val val = {NULL, 0}, val_key;
1424 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1425 	uint32_t i, j, k;
1426 	int ret;
1427 
1428 	for (i = 0; i < AES_EXTERN_ITER; i++) {
1429 		if (i != 0)
1430 			update_info_vec(i);
1431 
1432 		fips_test_write_one_case();
1433 
1434 		for (j = 0; j < AES_INTERN_ITER; j++) {
1435 			ret = fips_run_test();
1436 			if (ret < 0) {
1437 				if (ret == -EPERM) {
1438 					fprintf(info.fp_wr, "Bypass\n");
1439 					return 0;
1440 				}
1441 
1442 				return ret;
1443 			}
1444 
1445 			ret = get_writeback_data(&val);
1446 			if (ret < 0)
1447 				return ret;
1448 
1449 			if (info.op == FIPS_TEST_ENC_AUTH_GEN)
1450 				memcpy(vec.pt.val, val.val, AES_BLOCK_SIZE);
1451 			else
1452 				memcpy(vec.ct.val, val.val, AES_BLOCK_SIZE);
1453 
1454 			if (j == AES_INTERN_ITER - 1)
1455 				continue;
1456 
1457 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1458 		}
1459 
1460 		info.parse_writeback(&val);
1461 		fprintf(info.fp_wr, "\n");
1462 
1463 		if (i == AES_EXTERN_ITER - 1)
1464 			continue;
1465 
1466 		/** update key */
1467 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1468 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
1469 			switch (vec.cipher_auth.key.len) {
1470 			case 16:
1471 				val_key.val[k] ^= val.val[k];
1472 				break;
1473 			case 24:
1474 				if (k < 8)
1475 					val_key.val[k] ^= prev_out[k + 8];
1476 				else
1477 					val_key.val[k] ^= val.val[k - 8];
1478 				break;
1479 			case 32:
1480 				if (k < 16)
1481 					val_key.val[k] ^= prev_out[k];
1482 				else
1483 					val_key.val[k] ^= val.val[k - 16];
1484 				break;
1485 			default:
1486 				return -1;
1487 			}
1488 		}
1489 	}
1490 
1491 	if (val.val)
1492 		free(val.val);
1493 
1494 	return 0;
1495 }
1496 static int
1497 fips_mct_aes_test(void)
1498 {
1499 #define AES_BLOCK_SIZE	16
1500 #define AES_EXTERN_ITER	100
1501 #define AES_INTERN_ITER	1000
1502 	struct fips_val val = {NULL, 0}, val_key;
1503 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1504 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
1505 	uint32_t i, j, k;
1506 	int ret;
1507 
1508 	if (info.interim_info.aes_data.cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB)
1509 		return fips_mct_aes_ecb_test();
1510 
1511 	for (i = 0; i < AES_EXTERN_ITER; i++) {
1512 		if (i != 0)
1513 			update_info_vec(i);
1514 
1515 		fips_test_write_one_case();
1516 
1517 		for (j = 0; j < AES_INTERN_ITER; j++) {
1518 			ret = fips_run_test();
1519 			if (ret < 0) {
1520 				if (ret == -EPERM) {
1521 					fprintf(info.fp_wr, "Bypass\n");
1522 					return 0;
1523 				}
1524 
1525 				return ret;
1526 			}
1527 
1528 			ret = get_writeback_data(&val);
1529 			if (ret < 0)
1530 				return ret;
1531 
1532 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1533 				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
1534 
1535 			if (j == 0) {
1536 				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1537 
1538 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1539 					memcpy(vec.pt.val, vec.iv.val,
1540 							AES_BLOCK_SIZE);
1541 					memcpy(vec.iv.val, val.val,
1542 							AES_BLOCK_SIZE);
1543 				} else {
1544 					memcpy(vec.ct.val, vec.iv.val,
1545 							AES_BLOCK_SIZE);
1546 					memcpy(vec.iv.val, prev_in,
1547 							AES_BLOCK_SIZE);
1548 				}
1549 				continue;
1550 			}
1551 
1552 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1553 				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1554 				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
1555 			} else {
1556 				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
1557 				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
1558 			}
1559 
1560 			if (j == AES_INTERN_ITER - 1)
1561 				continue;
1562 
1563 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1564 		}
1565 
1566 		info.parse_writeback(&val);
1567 		fprintf(info.fp_wr, "\n");
1568 
1569 		if (i == AES_EXTERN_ITER - 1)
1570 			continue;
1571 
1572 		/** update key */
1573 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1574 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
1575 			switch (vec.cipher_auth.key.len) {
1576 			case 16:
1577 				val_key.val[k] ^= val.val[k];
1578 				break;
1579 			case 24:
1580 				if (k < 8)
1581 					val_key.val[k] ^= prev_out[k + 8];
1582 				else
1583 					val_key.val[k] ^= val.val[k - 8];
1584 				break;
1585 			case 32:
1586 				if (k < 16)
1587 					val_key.val[k] ^= prev_out[k];
1588 				else
1589 					val_key.val[k] ^= val.val[k - 16];
1590 				break;
1591 			default:
1592 				return -1;
1593 			}
1594 		}
1595 
1596 		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1597 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1598 	}
1599 
1600 	if (val.val)
1601 		free(val.val);
1602 
1603 	return 0;
1604 }
1605 
1606 static int
1607 fips_mct_sha_test(void)
1608 {
1609 #define SHA_EXTERN_ITER	100
1610 #define SHA_INTERN_ITER	1000
1611 #define SHA_MD_BLOCK	3
1612 	struct fips_val val = {NULL, 0}, md[SHA_MD_BLOCK];
1613 	char temp[MAX_DIGEST_SIZE*2];
1614 	int ret;
1615 	uint32_t i, j;
1616 
1617 	val.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0);
1618 	for (i = 0; i < SHA_MD_BLOCK; i++)
1619 		md[i].val = rte_malloc(NULL, (MAX_DIGEST_SIZE*2), 0);
1620 
1621 	rte_free(vec.pt.val);
1622 	vec.pt.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0);
1623 
1624 	fips_test_write_one_case();
1625 	fprintf(info.fp_wr, "\n");
1626 
1627 	for (j = 0; j < SHA_EXTERN_ITER; j++) {
1628 
1629 		memcpy(md[0].val, vec.cipher_auth.digest.val,
1630 			vec.cipher_auth.digest.len);
1631 		md[0].len = vec.cipher_auth.digest.len;
1632 		memcpy(md[1].val, vec.cipher_auth.digest.val,
1633 			vec.cipher_auth.digest.len);
1634 		md[1].len = vec.cipher_auth.digest.len;
1635 		memcpy(md[2].val, vec.cipher_auth.digest.val,
1636 			vec.cipher_auth.digest.len);
1637 		md[2].len = vec.cipher_auth.digest.len;
1638 
1639 		for (i = 0; i < (SHA_INTERN_ITER); i++) {
1640 
1641 			memcpy(vec.pt.val, md[0].val,
1642 				(size_t)md[0].len);
1643 			memcpy((vec.pt.val + md[0].len), md[1].val,
1644 				(size_t)md[1].len);
1645 			memcpy((vec.pt.val + md[0].len + md[1].len),
1646 				md[2].val,
1647 				(size_t)md[2].len);
1648 			vec.pt.len = md[0].len + md[1].len + md[2].len;
1649 
1650 			ret = fips_run_test();
1651 			if (ret < 0) {
1652 				if (ret == -EPERM || ret == -ENOTSUP) {
1653 					fprintf(info.fp_wr, "Bypass\n\n");
1654 					return 0;
1655 				}
1656 				return ret;
1657 			}
1658 
1659 			ret = get_writeback_data(&val);
1660 			if (ret < 0)
1661 				return ret;
1662 
1663 			memcpy(md[0].val, md[1].val, md[1].len);
1664 			md[0].len = md[1].len;
1665 			memcpy(md[1].val, md[2].val, md[2].len);
1666 			md[1].len = md[2].len;
1667 
1668 			memcpy(md[2].val, (val.val + vec.pt.len),
1669 				vec.cipher_auth.digest.len);
1670 			md[2].len = vec.cipher_auth.digest.len;
1671 		}
1672 
1673 		memcpy(vec.cipher_auth.digest.val, md[2].val, md[2].len);
1674 		vec.cipher_auth.digest.len = md[2].len;
1675 
1676 		fprintf(info.fp_wr, "COUNT = %u\n", j);
1677 
1678 		writeback_hex_str("", temp, &vec.cipher_auth.digest);
1679 
1680 		fprintf(info.fp_wr, "MD = %s\n\n", temp);
1681 	}
1682 
1683 	for (i = 0; i < (SHA_MD_BLOCK); i++)
1684 		rte_free(md[i].val);
1685 
1686 	rte_free(vec.pt.val);
1687 
1688 	if (val.val)
1689 		free(val.val);
1690 
1691 	return 0;
1692 }
1693 
1694 
1695 static int
1696 init_test_ops(void)
1697 {
1698 	switch (info.algo) {
1699 	case FIPS_TEST_ALGO_AES:
1700 		test_ops.prepare_op = prepare_cipher_op;
1701 		test_ops.prepare_xform  = prepare_aes_xform;
1702 		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
1703 			test_ops.test = fips_mct_aes_test;
1704 		else
1705 			test_ops.test = fips_generic_test;
1706 		break;
1707 	case FIPS_TEST_ALGO_HMAC:
1708 		test_ops.prepare_op = prepare_auth_op;
1709 		test_ops.prepare_xform = prepare_hmac_xform;
1710 		test_ops.test = fips_generic_test;
1711 		break;
1712 	case FIPS_TEST_ALGO_TDES:
1713 		test_ops.prepare_op = prepare_cipher_op;
1714 		test_ops.prepare_xform  = prepare_tdes_xform;
1715 		if (info.interim_info.tdes_data.test_type == TDES_MCT)
1716 			test_ops.test = fips_mct_tdes_test;
1717 		else
1718 			test_ops.test = fips_generic_test;
1719 		break;
1720 	case FIPS_TEST_ALGO_AES_GCM:
1721 		test_ops.prepare_op = prepare_aead_op;
1722 		test_ops.prepare_xform = prepare_gcm_xform;
1723 		test_ops.test = fips_generic_test;
1724 		break;
1725 	case FIPS_TEST_ALGO_AES_CMAC:
1726 		test_ops.prepare_op = prepare_auth_op;
1727 		test_ops.prepare_xform = prepare_cmac_xform;
1728 		test_ops.test = fips_generic_test;
1729 		break;
1730 	case FIPS_TEST_ALGO_AES_CCM:
1731 		test_ops.prepare_op = prepare_aead_op;
1732 		test_ops.prepare_xform = prepare_ccm_xform;
1733 		test_ops.test = fips_generic_test;
1734 		break;
1735 	case FIPS_TEST_ALGO_SHA:
1736 		test_ops.prepare_op = prepare_auth_op;
1737 		test_ops.prepare_xform = prepare_sha_xform;
1738 		if (info.interim_info.sha_data.test_type == SHA_MCT)
1739 			test_ops.test = fips_mct_sha_test;
1740 		else
1741 			test_ops.test = fips_generic_test;
1742 		break;
1743 	case FIPS_TEST_ALGO_AES_XTS:
1744 		test_ops.prepare_op = prepare_cipher_op;
1745 		test_ops.prepare_xform = prepare_xts_xform;
1746 		test_ops.test = fips_generic_test;
1747 		break;
1748 	default:
1749 		if (strstr(info.file_name, "TECB") ||
1750 				strstr(info.file_name, "TCBC")) {
1751 			info.algo = FIPS_TEST_ALGO_TDES;
1752 			test_ops.prepare_op = prepare_cipher_op;
1753 			test_ops.prepare_xform	= prepare_tdes_xform;
1754 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
1755 				test_ops.test = fips_mct_tdes_test;
1756 			else
1757 				test_ops.test = fips_generic_test;
1758 			break;
1759 		}
1760 		return -1;
1761 	}
1762 
1763 	return 0;
1764 }
1765 
1766 static void
1767 print_test_block(void)
1768 {
1769 	uint32_t i;
1770 
1771 	for (i = 0; i < info.nb_vec_lines; i++)
1772 		printf("%s\n", info.vec[i]);
1773 
1774 	printf("\n");
1775 }
1776 
1777 static int
1778 fips_test_one_file(void)
1779 {
1780 	int fetch_ret = 0, ret;
1781 
1782 	ret = init_test_ops();
1783 	if (ret < 0) {
1784 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
1785 		return ret;
1786 	}
1787 
1788 	while (ret >= 0 && fetch_ret == 0) {
1789 		fetch_ret = fips_test_fetch_one_block();
1790 		if (fetch_ret < 0) {
1791 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
1792 					fetch_ret);
1793 			ret = fetch_ret;
1794 			goto error_one_case;
1795 		}
1796 
1797 		if (info.nb_vec_lines == 0) {
1798 			if (fetch_ret == -EOF)
1799 				break;
1800 
1801 			fprintf(info.fp_wr, "\n");
1802 			continue;
1803 		}
1804 
1805 		ret = fips_test_parse_one_case();
1806 		switch (ret) {
1807 		case 0:
1808 			ret = test_ops.test();
1809 			if (ret == 0)
1810 				break;
1811 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
1812 					ret);
1813 			goto error_one_case;
1814 		case 1:
1815 			break;
1816 		default:
1817 			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
1818 					ret);
1819 			goto error_one_case;
1820 		}
1821 
1822 		continue;
1823 error_one_case:
1824 		print_test_block();
1825 	}
1826 
1827 	fips_test_clear();
1828 
1829 	if (env.digest)
1830 		rte_free(env.digest);
1831 	if (env.mbuf)
1832 		rte_pktmbuf_free(env.mbuf);
1833 
1834 	return ret;
1835 }
1836