xref: /dpdk/examples/fips_validation/main.c (revision 305921f4508d6a4c399ff99036e379e810455b9b)
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 	if (info.algo == FIPS_TEST_ALGO_AES_CCM)
474 		memcpy(iv + 1, vec.iv.val, vec.iv.len);
475 	else
476 		memcpy(iv, vec.iv.val, vec.iv.len);
477 
478 	sym->m_src = env.mbuf;
479 	sym->aead.data.offset = 0;
480 	sym->aead.aad.data = vec.aead.aad.val;
481 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
482 
483 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
484 		uint8_t *pt;
485 
486 		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
487 			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
488 			return -EPERM;
489 		}
490 
491 		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf,
492 				vec.pt.len + vec.aead.digest.len);
493 
494 		if (!pt) {
495 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
496 					-ENOMEM);
497 			return -ENOMEM;
498 		}
499 
500 		memcpy(pt, vec.pt.val, vec.pt.len);
501 		sym->aead.data.length = vec.pt.len;
502 		sym->aead.digest.data = pt + vec.pt.len;
503 		sym->aead.digest.phys_addr = rte_pktmbuf_mtophys_offset(
504 				env.mbuf, vec.pt.len);
505 	} else {
506 		uint8_t *ct;
507 
508 		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
509 			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
510 			return -EPERM;
511 		}
512 
513 		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
514 
515 		if (!ct) {
516 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
517 					-ENOMEM);
518 			return -ENOMEM;
519 		}
520 
521 		memcpy(ct, vec.ct.val, vec.ct.len);
522 		sym->aead.data.length = vec.ct.len;
523 		sym->aead.digest.data = vec.aead.digest.val;
524 		sym->aead.digest.phys_addr = rte_malloc_virt2iova(
525 				sym->aead.digest.data);
526 	}
527 
528 	rte_crypto_op_attach_sym_session(env.op, env.sess);
529 }
530 
531 static int
532 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
533 {
534 	const struct rte_cryptodev_symmetric_capability *cap;
535 	struct rte_cryptodev_sym_capability_idx cap_idx;
536 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
537 
538 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
539 
540 	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
541 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
542 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
543 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
544 	cipher_xform->key.data = vec.cipher_auth.key.val;
545 	cipher_xform->key.length = vec.cipher_auth.key.len;
546 	cipher_xform->iv.length = vec.iv.len;
547 	cipher_xform->iv.offset = IV_OFF;
548 
549 	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
550 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
551 
552 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
553 	if (!cap) {
554 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
555 				env.dev_id);
556 		return -EINVAL;
557 	}
558 
559 	if (rte_cryptodev_sym_capability_check_cipher(cap,
560 			cipher_xform->key.length,
561 			cipher_xform->iv.length) != 0) {
562 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
563 				info.device_name, cipher_xform->key.length,
564 				cipher_xform->iv.length);
565 		return -EPERM;
566 	}
567 
568 	return 0;
569 }
570 
571 static int
572 prepare_tdes_xform(struct rte_crypto_sym_xform *xform)
573 {
574 	const struct rte_cryptodev_symmetric_capability *cap;
575 	struct rte_cryptodev_sym_capability_idx cap_idx;
576 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
577 
578 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
579 
580 	cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
581 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
582 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
583 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
584 	cipher_xform->key.data = vec.cipher_auth.key.val;
585 	cipher_xform->key.length = vec.cipher_auth.key.len;
586 	cipher_xform->iv.length = vec.iv.len;
587 	cipher_xform->iv.offset = IV_OFF;
588 
589 	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
590 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
591 
592 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
593 	if (!cap) {
594 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
595 				env.dev_id);
596 		return -EINVAL;
597 	}
598 
599 	if (rte_cryptodev_sym_capability_check_cipher(cap,
600 			cipher_xform->key.length,
601 			cipher_xform->iv.length) != 0) {
602 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
603 				info.device_name, cipher_xform->key.length,
604 				cipher_xform->iv.length);
605 		return -EPERM;
606 	}
607 
608 	return 0;
609 }
610 
611 static int
612 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
613 {
614 	const struct rte_cryptodev_symmetric_capability *cap;
615 	struct rte_cryptodev_sym_capability_idx cap_idx;
616 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
617 
618 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
619 
620 	auth_xform->algo = info.interim_info.hmac_data.algo;
621 	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
622 	auth_xform->digest_length = vec.cipher_auth.digest.len;
623 	auth_xform->key.data = vec.cipher_auth.key.val;
624 	auth_xform->key.length = vec.cipher_auth.key.len;
625 
626 	cap_idx.algo.auth = auth_xform->algo;
627 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
628 
629 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
630 	if (!cap) {
631 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
632 				env.dev_id);
633 		return -EINVAL;
634 	}
635 
636 	if (rte_cryptodev_sym_capability_check_auth(cap,
637 			auth_xform->key.length,
638 			auth_xform->digest_length, 0) != 0) {
639 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
640 				info.device_name, auth_xform->key.length,
641 				auth_xform->digest_length);
642 		return -EPERM;
643 	}
644 
645 	return 0;
646 }
647 
648 static int
649 prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
650 {
651 	const struct rte_cryptodev_symmetric_capability *cap;
652 	struct rte_cryptodev_sym_capability_idx cap_idx;
653 	struct rte_crypto_aead_xform *aead_xform = &xform->aead;
654 
655 	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
656 
657 	aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
658 	aead_xform->aad_length = vec.aead.aad.len;
659 	aead_xform->digest_length = vec.aead.digest.len;
660 	aead_xform->iv.offset = IV_OFF;
661 	aead_xform->iv.length = vec.iv.len;
662 	aead_xform->key.data = vec.aead.key.val;
663 	aead_xform->key.length = vec.aead.key.len;
664 	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
665 			RTE_CRYPTO_AEAD_OP_ENCRYPT :
666 			RTE_CRYPTO_AEAD_OP_DECRYPT;
667 
668 	cap_idx.algo.aead = aead_xform->algo;
669 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
670 
671 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
672 	if (!cap) {
673 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
674 				env.dev_id);
675 		return -EINVAL;
676 	}
677 
678 	if (rte_cryptodev_sym_capability_check_aead(cap,
679 			aead_xform->key.length,
680 			aead_xform->digest_length, aead_xform->aad_length,
681 			aead_xform->iv.length) != 0) {
682 		RTE_LOG(ERR, USER1,
683 			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
684 				info.device_name, aead_xform->key.length,
685 				aead_xform->digest_length,
686 				aead_xform->aad_length,
687 				aead_xform->iv.length);
688 		return -EPERM;
689 	}
690 
691 	return 0;
692 }
693 
694 static int
695 prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
696 {
697 	const struct rte_cryptodev_symmetric_capability *cap;
698 	struct rte_cryptodev_sym_capability_idx cap_idx;
699 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
700 
701 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
702 
703 	auth_xform->algo = RTE_CRYPTO_AUTH_AES_CMAC;
704 	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
705 			RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
706 	auth_xform->digest_length = vec.cipher_auth.digest.len;
707 	auth_xform->key.data = vec.cipher_auth.key.val;
708 	auth_xform->key.length = vec.cipher_auth.key.len;
709 
710 	cap_idx.algo.auth = auth_xform->algo;
711 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
712 
713 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
714 	if (!cap) {
715 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
716 				env.dev_id);
717 		return -EINVAL;
718 	}
719 
720 	if (rte_cryptodev_sym_capability_check_auth(cap,
721 			auth_xform->key.length,
722 			auth_xform->digest_length, 0) != 0) {
723 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
724 				info.device_name, auth_xform->key.length,
725 				auth_xform->digest_length);
726 		return -EPERM;
727 	}
728 
729 	return 0;
730 }
731 
732 static int
733 prepare_ccm_xform(struct rte_crypto_sym_xform *xform)
734 {
735 	const struct rte_cryptodev_symmetric_capability *cap;
736 	struct rte_cryptodev_sym_capability_idx cap_idx;
737 	struct rte_crypto_aead_xform *aead_xform = &xform->aead;
738 
739 	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
740 
741 	aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
742 	aead_xform->aad_length = vec.aead.aad.len;
743 	aead_xform->digest_length = vec.aead.digest.len;
744 	aead_xform->iv.offset = IV_OFF;
745 	aead_xform->iv.length = vec.iv.len;
746 	aead_xform->key.data = vec.aead.key.val;
747 	aead_xform->key.length = vec.aead.key.len;
748 	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
749 			RTE_CRYPTO_AEAD_OP_ENCRYPT :
750 			RTE_CRYPTO_AEAD_OP_DECRYPT;
751 
752 	cap_idx.algo.aead = aead_xform->algo;
753 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
754 
755 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
756 	if (!cap) {
757 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
758 				env.dev_id);
759 		return -EINVAL;
760 	}
761 
762 	if (rte_cryptodev_sym_capability_check_aead(cap,
763 			aead_xform->key.length,
764 			aead_xform->digest_length, aead_xform->aad_length,
765 			aead_xform->iv.length) != 0) {
766 		RTE_LOG(ERR, USER1,
767 			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
768 				info.device_name, aead_xform->key.length,
769 				aead_xform->digest_length,
770 				aead_xform->aad_length,
771 				aead_xform->iv.length);
772 		return -EPERM;
773 	}
774 
775 	return 0;
776 }
777 
778 static void
779 get_writeback_data(struct fips_val *val)
780 {
781 	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
782 	val->len = rte_pktmbuf_pkt_len(env.mbuf);
783 }
784 
785 static int
786 fips_run_test(void)
787 {
788 	struct rte_crypto_sym_xform xform = {0};
789 	uint16_t n_deqd;
790 	int ret;
791 
792 	ret = test_ops.prepare_xform(&xform);
793 	if (ret < 0)
794 		return ret;
795 
796 	env.sess = rte_cryptodev_sym_session_create(env.mpool);
797 	if (!env.sess)
798 		return -ENOMEM;
799 
800 	ret = rte_cryptodev_sym_session_init(env.dev_id,
801 			env.sess, &xform, env.mpool);
802 	if (ret < 0) {
803 		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
804 				ret);
805 		return ret;
806 	}
807 
808 	ret = test_ops.prepare_op();
809 	if (ret < 0) {
810 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
811 				ret);
812 		return ret;
813 	}
814 
815 	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
816 		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
817 		return ret;
818 	}
819 
820 	do {
821 		struct rte_crypto_op *deqd_op;
822 
823 		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
824 				1);
825 	} while (n_deqd == 0);
826 
827 	vec.status = env.op->status;
828 
829 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
830 	rte_cryptodev_sym_session_free(env.sess);
831 	env.sess = NULL;
832 
833 	return ret;
834 }
835 
836 static int
837 fips_generic_test(void)
838 {
839 	struct fips_val val;
840 	int ret;
841 
842 	fips_test_write_one_case();
843 
844 	ret = fips_run_test();
845 	if (ret < 0) {
846 		if (ret == -EPERM) {
847 			fprintf(info.fp_wr, "Bypass\n\n");
848 			return 0;
849 		}
850 
851 		return ret;
852 	}
853 
854 	get_writeback_data(&val);
855 
856 	switch (info.file_type) {
857 	case FIPS_TYPE_REQ:
858 	case FIPS_TYPE_RSP:
859 		if (info.parse_writeback == NULL)
860 			return -EPERM;
861 		ret = info.parse_writeback(&val);
862 		if (ret < 0)
863 			return ret;
864 		break;
865 	case FIPS_TYPE_FAX:
866 		if (info.kat_check == NULL)
867 			return -EPERM;
868 		ret = info.kat_check(&val);
869 		if (ret < 0)
870 			return ret;
871 		break;
872 	}
873 
874 	fprintf(info.fp_wr, "\n");
875 
876 	return 0;
877 }
878 
879 static int
880 fips_mct_tdes_test(void)
881 {
882 #define TDES_BLOCK_SIZE		8
883 #define TDES_EXTERN_ITER	400
884 #define TDES_INTERN_ITER	10000
885 	struct fips_val val, val_key;
886 	uint8_t prev_out[TDES_BLOCK_SIZE];
887 	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
888 	uint8_t prev_in[TDES_BLOCK_SIZE];
889 	uint32_t i, j, k;
890 	int ret;
891 
892 	for (i = 0; i < TDES_EXTERN_ITER; i++) {
893 		if (i != 0)
894 			update_info_vec(i);
895 
896 		fips_test_write_one_case();
897 
898 		for (j = 0; j < TDES_INTERN_ITER; j++) {
899 			ret = fips_run_test();
900 			if (ret < 0) {
901 				if (ret == -EPERM) {
902 					fprintf(info.fp_wr, "Bypass\n");
903 					return 0;
904 				}
905 
906 				return ret;
907 			}
908 
909 			get_writeback_data(&val);
910 
911 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
912 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
913 
914 			if (j == 0) {
915 				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
916 
917 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
918 					memcpy(vec.pt.val, vec.iv.val,
919 							TDES_BLOCK_SIZE);
920 					memcpy(vec.iv.val, val.val,
921 							TDES_BLOCK_SIZE);
922 				} else {
923 					memcpy(vec.iv.val, vec.ct.val,
924 							TDES_BLOCK_SIZE);
925 					memcpy(vec.ct.val, val.val,
926 							TDES_BLOCK_SIZE);
927 				}
928 				continue;
929 			}
930 
931 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
932 				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
933 				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
934 			} else {
935 				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
936 				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
937 			}
938 
939 			if (j == TDES_INTERN_ITER - 1)
940 				continue;
941 
942 			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
943 
944 			if (j == TDES_INTERN_ITER - 3)
945 				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
946 		}
947 
948 		info.parse_writeback(&val);
949 		fprintf(info.fp_wr, "\n");
950 
951 		if (i == TDES_EXTERN_ITER - 1)
952 			continue;
953 
954 		/** update key */
955 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
956 
957 		if (info.interim_info.tdes_data.nb_keys == 0) {
958 			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
959 				info.interim_info.tdes_data.nb_keys = 1;
960 			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
961 				info.interim_info.tdes_data.nb_keys = 2;
962 			else
963 				info.interim_info.tdes_data.nb_keys = 3;
964 
965 		}
966 
967 		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
968 
969 			switch (info.interim_info.tdes_data.nb_keys) {
970 			case 3:
971 				val_key.val[k] ^= val.val[k];
972 				val_key.val[k + 8] ^= prev_out[k];
973 				val_key.val[k + 16] ^= prev_prev_out[k];
974 				break;
975 			case 2:
976 				val_key.val[k] ^= val.val[k];
977 				val_key.val[k + 8] ^= prev_out[k];
978 				val_key.val[k + 16] ^= val.val[k];
979 				break;
980 			default: /* case 1 */
981 				val_key.val[k] ^= val.val[k];
982 				val_key.val[k + 8] ^= val.val[k];
983 				val_key.val[k + 16] ^= val.val[k];
984 				break;
985 			}
986 
987 		}
988 
989 		for (k = 0; k < 24; k++)
990 			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
991 					0x1) ?
992 					val_key.val[k] : (val_key.val[k] ^ 0x1);
993 
994 		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
995 			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
996 			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
997 		} else {
998 			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
999 			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1000 		}
1001 	}
1002 
1003 	return 0;
1004 }
1005 
1006 static int
1007 fips_mct_aes_test(void)
1008 {
1009 #define AES_BLOCK_SIZE	16
1010 #define AES_EXTERN_ITER	100
1011 #define AES_INTERN_ITER	1000
1012 	struct fips_val val, val_key;
1013 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1014 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
1015 	uint32_t i, j, k;
1016 	int ret;
1017 
1018 	for (i = 0; i < AES_EXTERN_ITER; i++) {
1019 		if (i != 0)
1020 			update_info_vec(i);
1021 
1022 		fips_test_write_one_case();
1023 
1024 		for (j = 0; j < AES_INTERN_ITER; j++) {
1025 			ret = fips_run_test();
1026 			if (ret < 0) {
1027 				if (ret == -EPERM) {
1028 					fprintf(info.fp_wr, "Bypass\n");
1029 					return 0;
1030 				}
1031 
1032 				return ret;
1033 			}
1034 
1035 			get_writeback_data(&val);
1036 
1037 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1038 				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
1039 
1040 			if (j == 0) {
1041 				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1042 
1043 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1044 					memcpy(vec.pt.val, vec.iv.val,
1045 							AES_BLOCK_SIZE);
1046 					memcpy(vec.iv.val, val.val,
1047 							AES_BLOCK_SIZE);
1048 				} else {
1049 					memcpy(vec.ct.val, vec.iv.val,
1050 							AES_BLOCK_SIZE);
1051 					memcpy(vec.iv.val, prev_in,
1052 							AES_BLOCK_SIZE);
1053 				}
1054 				continue;
1055 			}
1056 
1057 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1058 				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1059 				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
1060 			} else {
1061 				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
1062 				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
1063 			}
1064 
1065 			if (j == AES_INTERN_ITER - 1)
1066 				continue;
1067 
1068 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1069 		}
1070 
1071 		info.parse_writeback(&val);
1072 		fprintf(info.fp_wr, "\n");
1073 
1074 		if (i == AES_EXTERN_ITER - 1)
1075 			continue;
1076 
1077 		/** update key */
1078 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1079 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
1080 			switch (vec.cipher_auth.key.len) {
1081 			case 16:
1082 				val_key.val[k] ^= val.val[k];
1083 				break;
1084 			case 24:
1085 				if (k < 8)
1086 					val_key.val[k] ^= prev_out[k + 8];
1087 				else
1088 					val_key.val[k] ^= val.val[k - 8];
1089 				break;
1090 			case 32:
1091 				if (k < 16)
1092 					val_key.val[k] ^= prev_out[k];
1093 				else
1094 					val_key.val[k] ^= val.val[k - 16];
1095 				break;
1096 			default:
1097 				return -1;
1098 			}
1099 		}
1100 
1101 		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1102 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1103 	}
1104 
1105 	return 0;
1106 }
1107 
1108 static int
1109 init_test_ops(void)
1110 {
1111 	switch (info.algo) {
1112 	case FIPS_TEST_ALGO_AES:
1113 		test_ops.prepare_op = prepare_cipher_op;
1114 		test_ops.prepare_xform  = prepare_aes_xform;
1115 		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
1116 			test_ops.test = fips_mct_aes_test;
1117 		else
1118 			test_ops.test = fips_generic_test;
1119 		break;
1120 	case FIPS_TEST_ALGO_HMAC:
1121 		test_ops.prepare_op = prepare_auth_op;
1122 		test_ops.prepare_xform = prepare_hmac_xform;
1123 		test_ops.test = fips_generic_test;
1124 		break;
1125 	case FIPS_TEST_ALGO_TDES:
1126 		test_ops.prepare_op = prepare_cipher_op;
1127 		test_ops.prepare_xform  = prepare_tdes_xform;
1128 		if (info.interim_info.tdes_data.test_type == TDES_MCT)
1129 			test_ops.test = fips_mct_tdes_test;
1130 		else
1131 			test_ops.test = fips_generic_test;
1132 		break;
1133 	case FIPS_TEST_ALGO_AES_GCM:
1134 		test_ops.prepare_op = prepare_aead_op;
1135 		test_ops.prepare_xform = prepare_gcm_xform;
1136 		test_ops.test = fips_generic_test;
1137 		break;
1138 	case FIPS_TEST_ALGO_AES_CMAC:
1139 		test_ops.prepare_op = prepare_auth_op;
1140 		test_ops.prepare_xform = prepare_cmac_xform;
1141 		test_ops.test = fips_generic_test;
1142 		break;
1143 	case FIPS_TEST_ALGO_AES_CCM:
1144 		test_ops.prepare_op = prepare_aead_op;
1145 		test_ops.prepare_xform = prepare_ccm_xform;
1146 		test_ops.test = fips_generic_test;
1147 		break;
1148 	default:
1149 		return -1;
1150 	}
1151 
1152 	return 0;
1153 }
1154 
1155 static void
1156 print_test_block(void)
1157 {
1158 	uint32_t i;
1159 
1160 	for (i = 0; i < info.nb_vec_lines; i++)
1161 		printf("%s\n", info.vec[i]);
1162 
1163 	printf("\n");
1164 }
1165 
1166 static int
1167 fips_test_one_file(void)
1168 {
1169 	int fetch_ret = 0, ret;
1170 
1171 
1172 	ret = init_test_ops();
1173 	if (ret < 0) {
1174 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
1175 		return ret;
1176 	}
1177 
1178 	while (ret >= 0 && fetch_ret == 0) {
1179 		fetch_ret = fips_test_fetch_one_block();
1180 		if (fetch_ret < 0) {
1181 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
1182 					fetch_ret);
1183 			ret = fetch_ret;
1184 			goto error_one_case;
1185 		}
1186 
1187 		if (info.nb_vec_lines == 0) {
1188 			if (fetch_ret == -EOF)
1189 				break;
1190 
1191 			fprintf(info.fp_wr, "\n");
1192 			continue;
1193 		}
1194 
1195 		ret = fips_test_parse_one_case();
1196 		switch (ret) {
1197 		case 0:
1198 			ret = test_ops.test();
1199 			if (ret == 0)
1200 				break;
1201 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
1202 					ret);
1203 			goto error_one_case;
1204 		case 1:
1205 			break;
1206 		default:
1207 			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
1208 					ret);
1209 			goto error_one_case;
1210 		}
1211 
1212 		continue;
1213 error_one_case:
1214 		print_test_block();
1215 	}
1216 
1217 	fips_test_clear();
1218 
1219 	return ret;
1220 
1221 }
1222