xref: /dpdk/examples/fips_validation/main.c (revision 4aaad2995e131856b8520c175b9350c3fcfed7d8)
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 
17 #define REQ_FILE_PATH_KEYWORD	"req-file"
18 #define RSP_FILE_PATH_KEYWORD	"rsp-file"
19 #define FOLDER_KEYWORD		"path-is-folder"
20 #define CRYPTODEV_KEYWORD	"cryptodev"
21 #define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
22 
23 struct fips_test_vector vec;
24 struct fips_test_interim_info info;
25 
26 struct cryptodev_fips_validate_env {
27 	const char *req_path;
28 	const char *rsp_path;
29 	uint32_t is_path_folder;
30 	uint32_t dev_id;
31 	struct rte_mempool *mpool;
32 	struct rte_mempool *op_pool;
33 	struct rte_mbuf *mbuf;
34 	struct rte_crypto_op *op;
35 	struct rte_cryptodev_sym_session *sess;
36 } env;
37 
38 static int
39 cryptodev_fips_validate_app_int(void)
40 {
41 	struct rte_cryptodev_config conf = {rte_socket_id(), 1};
42 	struct rte_cryptodev_qp_conf qp_conf = {128};
43 	int ret;
44 
45 	ret = rte_cryptodev_configure(env.dev_id, &conf);
46 	if (ret < 0)
47 		return ret;
48 
49 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
50 			UINT16_MAX, rte_socket_id());
51 	if (!env.mpool)
52 		return ret;
53 
54 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
55 			rte_socket_id(), env.mpool);
56 	if (ret < 0)
57 		return ret;
58 
59 	ret = -ENOMEM;
60 
61 	env.op_pool = rte_crypto_op_pool_create(
62 			"FIPS_OP_POOL",
63 			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
64 			1, 0,
65 			16,
66 			rte_socket_id());
67 	if (!env.op_pool)
68 		goto error_exit;
69 
70 	env.mbuf = rte_pktmbuf_alloc(env.mpool);
71 	if (!env.mbuf)
72 		goto error_exit;
73 
74 	env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
75 	if (!env.op)
76 		goto error_exit;
77 
78 	return 0;
79 
80 error_exit:
81 	rte_mempool_free(env.mpool);
82 	if (env.op_pool)
83 		rte_mempool_free(env.op_pool);
84 
85 	return ret;
86 }
87 
88 static void
89 cryptodev_fips_validate_app_uninit(void)
90 {
91 	rte_pktmbuf_free(env.mbuf);
92 	rte_crypto_op_free(env.op);
93 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
94 	rte_cryptodev_sym_session_free(env.sess);
95 	rte_mempool_free(env.mpool);
96 	rte_mempool_free(env.op_pool);
97 }
98 
99 static int
100 fips_test_one_file(void);
101 
102 static int
103 parse_cryptodev_arg(char *arg)
104 {
105 	int id = rte_cryptodev_get_dev_id(arg);
106 
107 	if (id < 0) {
108 		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
109 				id, arg);
110 		return id;
111 	}
112 
113 	env.dev_id = (uint32_t)id;
114 
115 	return 0;
116 }
117 
118 static int
119 parse_cryptodev_id_arg(char *arg)
120 {
121 	uint32_t cryptodev_id;
122 
123 	if (parser_read_uint32(&cryptodev_id, arg) < 0) {
124 		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
125 				-EINVAL, arg);
126 		return -1;
127 	}
128 
129 
130 	if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
131 		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
132 				cryptodev_id, arg);
133 		return -1;
134 	}
135 
136 	env.dev_id = (uint32_t)cryptodev_id;
137 
138 	return 0;
139 }
140 
141 static void
142 cryptodev_fips_validate_usage(const char *prgname)
143 {
144 	printf("%s [EAL options] --\n"
145 		"  --%s: REQUEST-FILE-PATH\n"
146 		"  --%s: RESPONSE-FILE-PATH\n"
147 		"  --%s: indicating both paths are folders\n"
148 		"  --%s: CRYPTODEV-NAME\n"
149 		"  --%s: CRYPTODEV-ID-NAME\n",
150 		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
151 		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD);
152 }
153 
154 static int
155 cryptodev_fips_validate_parse_args(int argc, char **argv)
156 {
157 	int opt, ret;
158 	char *prgname = argv[0];
159 	char **argvopt;
160 	int option_index;
161 	struct option lgopts[] = {
162 			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
163 			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
164 			{FOLDER_KEYWORD, no_argument, 0, 0},
165 			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
166 			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
167 			{NULL, 0, 0, 0}
168 	};
169 
170 	argvopt = argv;
171 
172 	while ((opt = getopt_long(argc, argvopt, "s:",
173 				  lgopts, &option_index)) != EOF) {
174 
175 		switch (opt) {
176 		case 0:
177 			if (strcmp(lgopts[option_index].name,
178 					REQ_FILE_PATH_KEYWORD) == 0)
179 				env.req_path = optarg;
180 			else if (strcmp(lgopts[option_index].name,
181 					RSP_FILE_PATH_KEYWORD) == 0)
182 				env.rsp_path = optarg;
183 			else if (strcmp(lgopts[option_index].name,
184 					FOLDER_KEYWORD) == 0)
185 				env.is_path_folder = 1;
186 			else if (strcmp(lgopts[option_index].name,
187 					CRYPTODEV_KEYWORD) == 0) {
188 				ret = parse_cryptodev_arg(optarg);
189 				if (ret < 0) {
190 					cryptodev_fips_validate_usage(prgname);
191 					return -EINVAL;
192 				}
193 			} else if (strcmp(lgopts[option_index].name,
194 					CRYPTODEV_ID_KEYWORD) == 0) {
195 				ret = parse_cryptodev_id_arg(optarg);
196 				if (ret < 0) {
197 					cryptodev_fips_validate_usage(prgname);
198 					return -EINVAL;
199 				}
200 			} else {
201 				cryptodev_fips_validate_usage(prgname);
202 				return -EINVAL;
203 			}
204 			break;
205 		default:
206 			return -1;
207 		}
208 	}
209 
210 	if (env.req_path == NULL || env.rsp_path == NULL ||
211 			env.dev_id == UINT32_MAX) {
212 		cryptodev_fips_validate_usage(prgname);
213 		return -EINVAL;
214 	}
215 
216 	return 0;
217 }
218 
219 int
220 main(int argc, char *argv[])
221 {
222 	int ret;
223 
224 	ret = rte_eal_init(argc, argv);
225 	if (ret < 0) {
226 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
227 		return -1;
228 	}
229 
230 	argc -= ret;
231 	argv += ret;
232 
233 	ret = cryptodev_fips_validate_parse_args(argc, argv);
234 	if (ret < 0)
235 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
236 
237 	ret = cryptodev_fips_validate_app_int();
238 	if (ret < 0) {
239 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
240 		return -1;
241 	}
242 
243 	if (!env.is_path_folder) {
244 		printf("Processing file %s... ", env.req_path);
245 
246 		ret = fips_test_init(env.req_path, env.rsp_path,
247 			rte_cryptodev_name_get(env.dev_id));
248 		if (ret < 0) {
249 			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
250 					ret, env.req_path);
251 			goto exit;
252 		}
253 
254 
255 		ret = fips_test_one_file();
256 		if (ret < 0) {
257 			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
258 					ret, env.req_path);
259 			goto exit;
260 		}
261 
262 		printf("Done\n");
263 
264 	} else {
265 		struct dirent *dir;
266 		DIR *d_req, *d_rsp;
267 		char req_path[1024];
268 		char rsp_path[1024];
269 
270 		d_req = opendir(env.req_path);
271 		if (!d_req) {
272 			RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
273 					-EINVAL, env.req_path);
274 			goto exit;
275 		}
276 
277 		d_rsp = opendir(env.rsp_path);
278 		if (!d_rsp) {
279 			ret = mkdir(env.rsp_path, 0700);
280 			if (ret == 0)
281 				d_rsp = opendir(env.rsp_path);
282 			else {
283 				RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
284 						-EINVAL, env.rsp_path);
285 				goto exit;
286 			}
287 		}
288 		closedir(d_rsp);
289 
290 		while ((dir = readdir(d_req)) != NULL) {
291 			if (strstr(dir->d_name, "req") == NULL)
292 				continue;
293 
294 			snprintf(req_path, 1023, "%s/%s", env.req_path,
295 					dir->d_name);
296 			snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
297 					dir->d_name);
298 			strlcpy(strstr(rsp_path, "req"), "rsp", 4);
299 
300 			printf("Processing file %s... ", req_path);
301 
302 			ret = fips_test_init(req_path, rsp_path,
303 			rte_cryptodev_name_get(env.dev_id));
304 			if (ret < 0) {
305 				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
306 						ret, req_path);
307 				break;
308 			}
309 
310 			ret = fips_test_one_file();
311 			if (ret < 0) {
312 				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
313 						ret, req_path);
314 				break;
315 			}
316 
317 			printf("Done\n");
318 		}
319 
320 		closedir(d_req);
321 	}
322 
323 
324 exit:
325 	fips_test_clear();
326 	cryptodev_fips_validate_app_uninit();
327 
328 	return ret;
329 
330 }
331 
332 #define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
333 #define CRYPTODEV_FIPS_MAX_RETRIES	16
334 
335 typedef int (*fips_test_one_case_t)(void);
336 typedef int (*fips_prepare_op_t)(void);
337 typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
338 
339 struct fips_test_ops {
340 	fips_prepare_xform_t prepare_xform;
341 	fips_prepare_op_t prepare_op;
342 	fips_test_one_case_t test;
343 } test_ops;
344 
345 static int
346 prepare_cipher_op(void)
347 {
348 	struct rte_crypto_sym_op *sym = env.op->sym;
349 	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
350 
351 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
352 	rte_pktmbuf_reset(env.mbuf);
353 
354 	sym->m_src = env.mbuf;
355 	sym->cipher.data.offset = 0;
356 
357 	memcpy(iv, vec.iv.val, vec.iv.len);
358 
359 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
360 		uint8_t *pt;
361 
362 		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
363 			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
364 			return -EPERM;
365 		}
366 
367 		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len);
368 
369 		if (!pt) {
370 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
371 					-ENOMEM);
372 			return -ENOMEM;
373 		}
374 
375 		memcpy(pt, vec.pt.val, vec.pt.len);
376 		sym->cipher.data.length = vec.pt.len;
377 
378 	} else {
379 		uint8_t *ct;
380 
381 		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
382 			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
383 			return -EPERM;
384 		}
385 
386 		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
387 
388 		if (!ct) {
389 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
390 					-ENOMEM);
391 			return -ENOMEM;
392 		}
393 
394 		memcpy(ct, vec.ct.val, vec.ct.len);
395 		sym->cipher.data.length = vec.ct.len;
396 	}
397 
398 	rte_crypto_op_attach_sym_session(env.op, env.sess);
399 
400 	return 0;
401 }
402 
403 static int
404 prepare_auth_op(void)
405 {
406 	struct rte_crypto_sym_op *sym = env.op->sym;
407 
408 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
409 	rte_pktmbuf_reset(env.mbuf);
410 
411 	sym->m_src = env.mbuf;
412 	sym->auth.data.offset = 0;
413 
414 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
415 		uint8_t *pt;
416 
417 		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
418 			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
419 			return -EPERM;
420 		}
421 
422 		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len +
423 				vec.cipher_auth.digest.len);
424 
425 		if (!pt) {
426 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
427 					-ENOMEM);
428 			return -ENOMEM;
429 		}
430 
431 		memcpy(pt, vec.pt.val, vec.pt.len);
432 		sym->auth.data.length = vec.pt.len;
433 		sym->auth.digest.data = pt + vec.pt.len;
434 		sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
435 				env.mbuf, vec.pt.len);
436 
437 	} else {
438 		uint8_t *ct;
439 
440 		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
441 			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
442 			return -EPERM;
443 		}
444 
445 		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf,
446 				vec.ct.len + vec.cipher_auth.digest.len);
447 
448 		if (!ct) {
449 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
450 					-ENOMEM);
451 			return -ENOMEM;
452 		}
453 
454 		memcpy(ct, vec.ct.val, vec.ct.len);
455 		sym->auth.data.length = vec.ct.len;
456 		sym->auth.digest.data = vec.cipher_auth.digest.val;
457 		sym->auth.digest.phys_addr = rte_malloc_virt2iova(
458 				sym->auth.digest.data);
459 	}
460 
461 	rte_crypto_op_attach_sym_session(env.op, env.sess);
462 }
463 
464 static int
465 prepare_aead_op(void)
466 {
467 	struct rte_crypto_sym_op *sym = env.op->sym;
468 	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
469 
470 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
471 	rte_pktmbuf_reset(env.mbuf);
472 
473 	memcpy(iv, vec.iv.val, vec.iv.len);
474 
475 	sym->m_src = env.mbuf;
476 	sym->aead.data.offset = 0;
477 	sym->aead.aad.data = vec.aead.aad.val;
478 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
479 
480 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
481 		uint8_t *pt;
482 
483 		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
484 			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
485 			return -EPERM;
486 		}
487 
488 		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf,
489 				vec.pt.len + vec.aead.digest.len);
490 
491 		if (!pt) {
492 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
493 					-ENOMEM);
494 			return -ENOMEM;
495 		}
496 
497 		memcpy(pt, vec.pt.val, vec.pt.len);
498 		sym->aead.data.length = vec.pt.len;
499 		sym->aead.digest.data = pt + vec.pt.len;
500 		sym->aead.digest.phys_addr = rte_pktmbuf_mtophys_offset(
501 				env.mbuf, vec.pt.len);
502 	} else {
503 		uint8_t *ct;
504 
505 		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
506 			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
507 			return -EPERM;
508 		}
509 
510 		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
511 
512 		if (!ct) {
513 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
514 					-ENOMEM);
515 			return -ENOMEM;
516 		}
517 
518 		memcpy(ct, vec.ct.val, vec.ct.len);
519 		sym->aead.data.length = vec.ct.len;
520 		sym->aead.digest.data = vec.aead.digest.val;
521 		sym->aead.digest.phys_addr = rte_malloc_virt2iova(
522 				sym->aead.digest.data);
523 	}
524 
525 	rte_crypto_op_attach_sym_session(env.op, env.sess);
526 }
527 
528 static int
529 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
530 {
531 	const struct rte_cryptodev_symmetric_capability *cap;
532 	struct rte_cryptodev_sym_capability_idx cap_idx;
533 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
534 
535 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
536 
537 	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
538 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
539 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
540 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
541 	cipher_xform->key.data = vec.cipher_auth.key.val;
542 	cipher_xform->key.length = vec.cipher_auth.key.len;
543 	cipher_xform->iv.length = vec.iv.len;
544 	cipher_xform->iv.offset = IV_OFF;
545 
546 	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
547 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
548 
549 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
550 	if (!cap) {
551 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
552 				env.dev_id);
553 		return -EINVAL;
554 	}
555 
556 	if (rte_cryptodev_sym_capability_check_cipher(cap,
557 			cipher_xform->key.length,
558 			cipher_xform->iv.length) != 0) {
559 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
560 				info.device_name, cipher_xform->key.length,
561 				cipher_xform->iv.length);
562 		return -EPERM;
563 	}
564 
565 	return 0;
566 }
567 
568 static int
569 prepare_tdes_xform(struct rte_crypto_sym_xform *xform)
570 {
571 	const struct rte_cryptodev_symmetric_capability *cap;
572 	struct rte_cryptodev_sym_capability_idx cap_idx;
573 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
574 
575 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
576 
577 	cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
578 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
579 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
580 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
581 	cipher_xform->key.data = vec.cipher_auth.key.val;
582 	cipher_xform->key.length = vec.cipher_auth.key.len;
583 	cipher_xform->iv.length = vec.iv.len;
584 	cipher_xform->iv.offset = IV_OFF;
585 
586 	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
587 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
588 
589 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
590 	if (!cap) {
591 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
592 				env.dev_id);
593 		return -EINVAL;
594 	}
595 
596 	if (rte_cryptodev_sym_capability_check_cipher(cap,
597 			cipher_xform->key.length,
598 			cipher_xform->iv.length) != 0) {
599 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
600 				info.device_name, cipher_xform->key.length,
601 				cipher_xform->iv.length);
602 		return -EPERM;
603 	}
604 
605 	return 0;
606 }
607 
608 static int
609 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
610 {
611 	const struct rte_cryptodev_symmetric_capability *cap;
612 	struct rte_cryptodev_sym_capability_idx cap_idx;
613 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
614 
615 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
616 
617 	auth_xform->algo = info.interim_info.hmac_data.algo;
618 	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
619 	auth_xform->digest_length = vec.cipher_auth.digest.len;
620 	auth_xform->key.data = vec.cipher_auth.key.val;
621 	auth_xform->key.length = vec.cipher_auth.key.len;
622 
623 	cap_idx.algo.auth = auth_xform->algo;
624 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
625 
626 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
627 	if (!cap) {
628 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
629 				env.dev_id);
630 		return -EINVAL;
631 	}
632 
633 	if (rte_cryptodev_sym_capability_check_auth(cap,
634 			auth_xform->key.length,
635 			auth_xform->digest_length, 0) != 0) {
636 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
637 				info.device_name, auth_xform->key.length,
638 				auth_xform->digest_length);
639 		return -EPERM;
640 	}
641 
642 	return 0;
643 }
644 
645 static int
646 prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
647 {
648 	const struct rte_cryptodev_symmetric_capability *cap;
649 	struct rte_cryptodev_sym_capability_idx cap_idx;
650 	struct rte_crypto_aead_xform *aead_xform = &xform->aead;
651 
652 	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
653 
654 	aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
655 	aead_xform->aad_length = vec.aead.aad.len;
656 	aead_xform->digest_length = vec.aead.digest.len;
657 	aead_xform->iv.offset = IV_OFF;
658 	aead_xform->iv.length = vec.iv.len;
659 	aead_xform->key.data = vec.aead.key.val;
660 	aead_xform->key.length = vec.aead.key.len;
661 	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
662 			RTE_CRYPTO_AEAD_OP_ENCRYPT :
663 			RTE_CRYPTO_AEAD_OP_DECRYPT;
664 
665 	cap_idx.algo.aead = aead_xform->algo;
666 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
667 
668 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
669 	if (!cap) {
670 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
671 				env.dev_id);
672 		return -EINVAL;
673 	}
674 
675 	if (rte_cryptodev_sym_capability_check_aead(cap,
676 			aead_xform->key.length,
677 			aead_xform->digest_length, aead_xform->aad_length,
678 			aead_xform->iv.length) != 0) {
679 		RTE_LOG(ERR, USER1,
680 			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
681 				info.device_name, aead_xform->key.length,
682 				aead_xform->digest_length,
683 				aead_xform->aad_length,
684 				aead_xform->iv.length);
685 		return -EPERM;
686 	}
687 
688 	return 0;
689 }
690 
691 static void
692 get_writeback_data(struct fips_val *val)
693 {
694 	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
695 	val->len = rte_pktmbuf_pkt_len(env.mbuf);
696 }
697 
698 static int
699 fips_run_test(void)
700 {
701 	struct rte_crypto_sym_xform xform = {0};
702 	uint16_t n_deqd;
703 	int ret;
704 
705 	ret = test_ops.prepare_xform(&xform);
706 	if (ret < 0)
707 		return ret;
708 
709 	env.sess = rte_cryptodev_sym_session_create(env.mpool);
710 	if (!env.sess)
711 		return -ENOMEM;
712 
713 	ret = rte_cryptodev_sym_session_init(env.dev_id,
714 			env.sess, &xform, env.mpool);
715 	if (ret < 0) {
716 		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
717 				ret);
718 		return ret;
719 	}
720 
721 	ret = test_ops.prepare_op();
722 	if (ret < 0) {
723 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
724 				ret);
725 		return ret;
726 	}
727 
728 	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
729 		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
730 		return ret;
731 	}
732 
733 	do {
734 		struct rte_crypto_op *deqd_op;
735 
736 		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
737 				1);
738 	} while (n_deqd == 0);
739 
740 	vec.status = env.op->status;
741 
742 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
743 	rte_cryptodev_sym_session_free(env.sess);
744 	env.sess = NULL;
745 
746 	return ret;
747 }
748 
749 static int
750 fips_generic_test(void)
751 {
752 	struct fips_val val;
753 	int ret;
754 
755 	fips_test_write_one_case();
756 
757 	ret = fips_run_test();
758 	if (ret < 0) {
759 		if (ret == -EPERM) {
760 			fprintf(info.fp_wr, "Bypass\n\n");
761 			return 0;
762 		}
763 
764 		return ret;
765 	}
766 
767 	get_writeback_data(&val);
768 
769 	switch (info.file_type) {
770 	case FIPS_TYPE_REQ:
771 	case FIPS_TYPE_RSP:
772 		if (info.parse_writeback == NULL)
773 			return -EPERM;
774 		ret = info.parse_writeback(&val);
775 		if (ret < 0)
776 			return ret;
777 		break;
778 	case FIPS_TYPE_FAX:
779 		if (info.kat_check == NULL)
780 			return -EPERM;
781 		ret = info.kat_check(&val);
782 		if (ret < 0)
783 			return ret;
784 		break;
785 	}
786 
787 	fprintf(info.fp_wr, "\n");
788 
789 	return 0;
790 }
791 
792 static int
793 fips_mct_tdes_test(void)
794 {
795 #define TDES_BLOCK_SIZE		8
796 #define TDES_EXTERN_ITER	400
797 #define TDES_INTERN_ITER	10000
798 	struct fips_val val, val_key;
799 	uint8_t prev_out[TDES_BLOCK_SIZE];
800 	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
801 	uint8_t prev_in[TDES_BLOCK_SIZE];
802 	uint32_t i, j, k;
803 	int ret;
804 
805 	for (i = 0; i < TDES_EXTERN_ITER; i++) {
806 		if (i != 0)
807 			update_info_vec(i);
808 
809 		fips_test_write_one_case();
810 
811 		for (j = 0; j < TDES_INTERN_ITER; j++) {
812 			ret = fips_run_test();
813 			if (ret < 0) {
814 				if (ret == -EPERM) {
815 					fprintf(info.fp_wr, "Bypass\n");
816 					return 0;
817 				}
818 
819 				return ret;
820 			}
821 
822 			get_writeback_data(&val);
823 
824 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
825 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
826 
827 			if (j == 0) {
828 				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
829 
830 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
831 					memcpy(vec.pt.val, vec.iv.val,
832 							TDES_BLOCK_SIZE);
833 					memcpy(vec.iv.val, val.val,
834 							TDES_BLOCK_SIZE);
835 				} else {
836 					memcpy(vec.iv.val, vec.ct.val,
837 							TDES_BLOCK_SIZE);
838 					memcpy(vec.ct.val, val.val,
839 							TDES_BLOCK_SIZE);
840 				}
841 				continue;
842 			}
843 
844 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
845 				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
846 				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
847 			} else {
848 				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
849 				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
850 			}
851 
852 			if (j == TDES_INTERN_ITER - 1)
853 				continue;
854 
855 			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
856 
857 			if (j == TDES_INTERN_ITER - 3)
858 				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
859 		}
860 
861 		info.parse_writeback(&val);
862 		fprintf(info.fp_wr, "\n");
863 
864 		if (i == TDES_EXTERN_ITER - 1)
865 			continue;
866 
867 		/** update key */
868 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
869 
870 		if (info.interim_info.tdes_data.nb_keys == 0) {
871 			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
872 				info.interim_info.tdes_data.nb_keys = 1;
873 			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
874 				info.interim_info.tdes_data.nb_keys = 2;
875 			else
876 				info.interim_info.tdes_data.nb_keys = 3;
877 
878 		}
879 
880 		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
881 
882 			switch (info.interim_info.tdes_data.nb_keys) {
883 			case 3:
884 				val_key.val[k] ^= val.val[k];
885 				val_key.val[k + 8] ^= prev_out[k];
886 				val_key.val[k + 16] ^= prev_prev_out[k];
887 				break;
888 			case 2:
889 				val_key.val[k] ^= val.val[k];
890 				val_key.val[k + 8] ^= prev_out[k];
891 				val_key.val[k + 16] ^= val.val[k];
892 				break;
893 			default: /* case 1 */
894 				val_key.val[k] ^= val.val[k];
895 				val_key.val[k + 8] ^= val.val[k];
896 				val_key.val[k + 16] ^= val.val[k];
897 				break;
898 			}
899 
900 		}
901 
902 		for (k = 0; k < 24; k++)
903 			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
904 					0x1) ?
905 					val_key.val[k] : (val_key.val[k] ^ 0x1);
906 
907 		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
908 			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
909 			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
910 		} else {
911 			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
912 			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
913 		}
914 	}
915 
916 	return 0;
917 }
918 
919 static int
920 fips_mct_aes_test(void)
921 {
922 #define AES_BLOCK_SIZE	16
923 #define AES_EXTERN_ITER	100
924 #define AES_INTERN_ITER	1000
925 	struct fips_val val, val_key;
926 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
927 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
928 	uint32_t i, j, k;
929 	int ret;
930 
931 	for (i = 0; i < AES_EXTERN_ITER; i++) {
932 		if (i != 0)
933 			update_info_vec(i);
934 
935 		fips_test_write_one_case();
936 
937 		for (j = 0; j < AES_INTERN_ITER; j++) {
938 			ret = fips_run_test();
939 			if (ret < 0) {
940 				if (ret == -EPERM) {
941 					fprintf(info.fp_wr, "Bypass\n");
942 					return 0;
943 				}
944 
945 				return ret;
946 			}
947 
948 			get_writeback_data(&val);
949 
950 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
951 				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
952 
953 			if (j == 0) {
954 				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
955 
956 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
957 					memcpy(vec.pt.val, vec.iv.val,
958 							AES_BLOCK_SIZE);
959 					memcpy(vec.iv.val, val.val,
960 							AES_BLOCK_SIZE);
961 				} else {
962 					memcpy(vec.ct.val, vec.iv.val,
963 							AES_BLOCK_SIZE);
964 					memcpy(vec.iv.val, prev_in,
965 							AES_BLOCK_SIZE);
966 				}
967 				continue;
968 			}
969 
970 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
971 				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
972 				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
973 			} else {
974 				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
975 				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
976 			}
977 
978 			if (j == AES_INTERN_ITER - 1)
979 				continue;
980 
981 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
982 		}
983 
984 		info.parse_writeback(&val);
985 		fprintf(info.fp_wr, "\n");
986 
987 		if (i == AES_EXTERN_ITER - 1)
988 			continue;
989 
990 		/** update key */
991 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
992 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
993 			switch (vec.cipher_auth.key.len) {
994 			case 16:
995 				val_key.val[k] ^= val.val[k];
996 				break;
997 			case 24:
998 				if (k < 8)
999 					val_key.val[k] ^= prev_out[k + 8];
1000 				else
1001 					val_key.val[k] ^= val.val[k - 8];
1002 				break;
1003 			case 32:
1004 				if (k < 16)
1005 					val_key.val[k] ^= prev_out[k];
1006 				else
1007 					val_key.val[k] ^= val.val[k - 16];
1008 				break;
1009 			default:
1010 				return -1;
1011 			}
1012 		}
1013 
1014 		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1015 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1016 	}
1017 
1018 	return 0;
1019 }
1020 
1021 static int
1022 init_test_ops(void)
1023 {
1024 	switch (info.algo) {
1025 	case FIPS_TEST_ALGO_AES:
1026 		test_ops.prepare_op = prepare_cipher_op;
1027 		test_ops.prepare_xform  = prepare_aes_xform;
1028 		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
1029 			test_ops.test = fips_mct_aes_test;
1030 		else
1031 			test_ops.test = fips_generic_test;
1032 		break;
1033 	case FIPS_TEST_ALGO_HMAC:
1034 		test_ops.prepare_op = prepare_auth_op;
1035 		test_ops.prepare_xform = prepare_hmac_xform;
1036 		test_ops.test = fips_generic_test;
1037 		break;
1038 	case FIPS_TEST_ALGO_TDES:
1039 		test_ops.prepare_op = prepare_cipher_op;
1040 		test_ops.prepare_xform  = prepare_tdes_xform;
1041 		if (info.interim_info.tdes_data.test_type == TDES_MCT)
1042 			test_ops.test = fips_mct_tdes_test;
1043 		else
1044 			test_ops.test = fips_generic_test;
1045 		break;
1046 	case FIPS_TEST_ALGO_AES_GCM:
1047 		test_ops.prepare_op = prepare_aead_op;
1048 		test_ops.prepare_xform = prepare_gcm_xform;
1049 		test_ops.test = fips_generic_test;
1050 		break;
1051 	default:
1052 		return -1;
1053 	}
1054 
1055 	return 0;
1056 }
1057 
1058 static void
1059 print_test_block(void)
1060 {
1061 	uint32_t i;
1062 
1063 	for (i = 0; i < info.nb_vec_lines; i++)
1064 		printf("%s\n", info.vec[i]);
1065 
1066 	printf("\n");
1067 }
1068 
1069 static int
1070 fips_test_one_file(void)
1071 {
1072 	int fetch_ret = 0, ret;
1073 
1074 
1075 	ret = init_test_ops();
1076 	if (ret < 0) {
1077 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
1078 		return ret;
1079 	}
1080 
1081 	while (ret >= 0 && fetch_ret == 0) {
1082 		fetch_ret = fips_test_fetch_one_block();
1083 		if (fetch_ret < 0) {
1084 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
1085 					fetch_ret);
1086 			ret = fetch_ret;
1087 			goto error_one_case;
1088 		}
1089 
1090 		if (info.nb_vec_lines == 0) {
1091 			if (fetch_ret == -EOF)
1092 				break;
1093 
1094 			fprintf(info.fp_wr, "\n");
1095 			continue;
1096 		}
1097 
1098 		ret = fips_test_parse_one_case();
1099 		switch (ret) {
1100 		case 0:
1101 			ret = test_ops.test();
1102 			if (ret == 0)
1103 				break;
1104 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
1105 					ret);
1106 			goto error_one_case;
1107 		case 1:
1108 			break;
1109 		default:
1110 			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
1111 					ret);
1112 			goto error_one_case;
1113 		}
1114 
1115 		continue;
1116 error_one_case:
1117 		print_test_block();
1118 	}
1119 
1120 	fips_test_clear();
1121 
1122 	return ret;
1123 
1124 }
1125