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