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