xref: /dpdk/examples/fips_validation/main.c (revision ac026f4668d031220b3203913005c0ded0a38e1d)
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 int
692 prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
693 {
694 	const struct rte_cryptodev_symmetric_capability *cap;
695 	struct rte_cryptodev_sym_capability_idx cap_idx;
696 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
697 
698 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
699 
700 	auth_xform->algo = RTE_CRYPTO_AUTH_AES_CMAC;
701 	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
702 			RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
703 	auth_xform->digest_length = vec.cipher_auth.digest.len;
704 	auth_xform->key.data = vec.cipher_auth.key.val;
705 	auth_xform->key.length = vec.cipher_auth.key.len;
706 
707 	cap_idx.algo.auth = auth_xform->algo;
708 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
709 
710 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
711 	if (!cap) {
712 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
713 				env.dev_id);
714 		return -EINVAL;
715 	}
716 
717 	if (rte_cryptodev_sym_capability_check_auth(cap,
718 			auth_xform->key.length,
719 			auth_xform->digest_length, 0) != 0) {
720 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
721 				info.device_name, auth_xform->key.length,
722 				auth_xform->digest_length);
723 		return -EPERM;
724 	}
725 
726 	return 0;
727 }
728 
729 static void
730 get_writeback_data(struct fips_val *val)
731 {
732 	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
733 	val->len = rte_pktmbuf_pkt_len(env.mbuf);
734 }
735 
736 static int
737 fips_run_test(void)
738 {
739 	struct rte_crypto_sym_xform xform = {0};
740 	uint16_t n_deqd;
741 	int ret;
742 
743 	ret = test_ops.prepare_xform(&xform);
744 	if (ret < 0)
745 		return ret;
746 
747 	env.sess = rte_cryptodev_sym_session_create(env.mpool);
748 	if (!env.sess)
749 		return -ENOMEM;
750 
751 	ret = rte_cryptodev_sym_session_init(env.dev_id,
752 			env.sess, &xform, env.mpool);
753 	if (ret < 0) {
754 		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
755 				ret);
756 		return ret;
757 	}
758 
759 	ret = test_ops.prepare_op();
760 	if (ret < 0) {
761 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
762 				ret);
763 		return ret;
764 	}
765 
766 	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
767 		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
768 		return ret;
769 	}
770 
771 	do {
772 		struct rte_crypto_op *deqd_op;
773 
774 		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
775 				1);
776 	} while (n_deqd == 0);
777 
778 	vec.status = env.op->status;
779 
780 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
781 	rte_cryptodev_sym_session_free(env.sess);
782 	env.sess = NULL;
783 
784 	return ret;
785 }
786 
787 static int
788 fips_generic_test(void)
789 {
790 	struct fips_val val;
791 	int ret;
792 
793 	fips_test_write_one_case();
794 
795 	ret = fips_run_test();
796 	if (ret < 0) {
797 		if (ret == -EPERM) {
798 			fprintf(info.fp_wr, "Bypass\n\n");
799 			return 0;
800 		}
801 
802 		return ret;
803 	}
804 
805 	get_writeback_data(&val);
806 
807 	switch (info.file_type) {
808 	case FIPS_TYPE_REQ:
809 	case FIPS_TYPE_RSP:
810 		if (info.parse_writeback == NULL)
811 			return -EPERM;
812 		ret = info.parse_writeback(&val);
813 		if (ret < 0)
814 			return ret;
815 		break;
816 	case FIPS_TYPE_FAX:
817 		if (info.kat_check == NULL)
818 			return -EPERM;
819 		ret = info.kat_check(&val);
820 		if (ret < 0)
821 			return ret;
822 		break;
823 	}
824 
825 	fprintf(info.fp_wr, "\n");
826 
827 	return 0;
828 }
829 
830 static int
831 fips_mct_tdes_test(void)
832 {
833 #define TDES_BLOCK_SIZE		8
834 #define TDES_EXTERN_ITER	400
835 #define TDES_INTERN_ITER	10000
836 	struct fips_val val, val_key;
837 	uint8_t prev_out[TDES_BLOCK_SIZE];
838 	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
839 	uint8_t prev_in[TDES_BLOCK_SIZE];
840 	uint32_t i, j, k;
841 	int ret;
842 
843 	for (i = 0; i < TDES_EXTERN_ITER; i++) {
844 		if (i != 0)
845 			update_info_vec(i);
846 
847 		fips_test_write_one_case();
848 
849 		for (j = 0; j < TDES_INTERN_ITER; j++) {
850 			ret = fips_run_test();
851 			if (ret < 0) {
852 				if (ret == -EPERM) {
853 					fprintf(info.fp_wr, "Bypass\n");
854 					return 0;
855 				}
856 
857 				return ret;
858 			}
859 
860 			get_writeback_data(&val);
861 
862 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
863 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
864 
865 			if (j == 0) {
866 				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
867 
868 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
869 					memcpy(vec.pt.val, vec.iv.val,
870 							TDES_BLOCK_SIZE);
871 					memcpy(vec.iv.val, val.val,
872 							TDES_BLOCK_SIZE);
873 				} else {
874 					memcpy(vec.iv.val, vec.ct.val,
875 							TDES_BLOCK_SIZE);
876 					memcpy(vec.ct.val, val.val,
877 							TDES_BLOCK_SIZE);
878 				}
879 				continue;
880 			}
881 
882 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
883 				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
884 				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
885 			} else {
886 				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
887 				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
888 			}
889 
890 			if (j == TDES_INTERN_ITER - 1)
891 				continue;
892 
893 			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
894 
895 			if (j == TDES_INTERN_ITER - 3)
896 				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
897 		}
898 
899 		info.parse_writeback(&val);
900 		fprintf(info.fp_wr, "\n");
901 
902 		if (i == TDES_EXTERN_ITER - 1)
903 			continue;
904 
905 		/** update key */
906 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
907 
908 		if (info.interim_info.tdes_data.nb_keys == 0) {
909 			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
910 				info.interim_info.tdes_data.nb_keys = 1;
911 			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
912 				info.interim_info.tdes_data.nb_keys = 2;
913 			else
914 				info.interim_info.tdes_data.nb_keys = 3;
915 
916 		}
917 
918 		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
919 
920 			switch (info.interim_info.tdes_data.nb_keys) {
921 			case 3:
922 				val_key.val[k] ^= val.val[k];
923 				val_key.val[k + 8] ^= prev_out[k];
924 				val_key.val[k + 16] ^= prev_prev_out[k];
925 				break;
926 			case 2:
927 				val_key.val[k] ^= val.val[k];
928 				val_key.val[k + 8] ^= prev_out[k];
929 				val_key.val[k + 16] ^= val.val[k];
930 				break;
931 			default: /* case 1 */
932 				val_key.val[k] ^= val.val[k];
933 				val_key.val[k + 8] ^= val.val[k];
934 				val_key.val[k + 16] ^= val.val[k];
935 				break;
936 			}
937 
938 		}
939 
940 		for (k = 0; k < 24; k++)
941 			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
942 					0x1) ?
943 					val_key.val[k] : (val_key.val[k] ^ 0x1);
944 
945 		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
946 			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
947 			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
948 		} else {
949 			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
950 			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
951 		}
952 	}
953 
954 	return 0;
955 }
956 
957 static int
958 fips_mct_aes_test(void)
959 {
960 #define AES_BLOCK_SIZE	16
961 #define AES_EXTERN_ITER	100
962 #define AES_INTERN_ITER	1000
963 	struct fips_val val, val_key;
964 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
965 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
966 	uint32_t i, j, k;
967 	int ret;
968 
969 	for (i = 0; i < AES_EXTERN_ITER; i++) {
970 		if (i != 0)
971 			update_info_vec(i);
972 
973 		fips_test_write_one_case();
974 
975 		for (j = 0; j < AES_INTERN_ITER; j++) {
976 			ret = fips_run_test();
977 			if (ret < 0) {
978 				if (ret == -EPERM) {
979 					fprintf(info.fp_wr, "Bypass\n");
980 					return 0;
981 				}
982 
983 				return ret;
984 			}
985 
986 			get_writeback_data(&val);
987 
988 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
989 				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
990 
991 			if (j == 0) {
992 				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
993 
994 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
995 					memcpy(vec.pt.val, vec.iv.val,
996 							AES_BLOCK_SIZE);
997 					memcpy(vec.iv.val, val.val,
998 							AES_BLOCK_SIZE);
999 				} else {
1000 					memcpy(vec.ct.val, vec.iv.val,
1001 							AES_BLOCK_SIZE);
1002 					memcpy(vec.iv.val, prev_in,
1003 							AES_BLOCK_SIZE);
1004 				}
1005 				continue;
1006 			}
1007 
1008 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1009 				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1010 				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
1011 			} else {
1012 				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
1013 				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
1014 			}
1015 
1016 			if (j == AES_INTERN_ITER - 1)
1017 				continue;
1018 
1019 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1020 		}
1021 
1022 		info.parse_writeback(&val);
1023 		fprintf(info.fp_wr, "\n");
1024 
1025 		if (i == AES_EXTERN_ITER - 1)
1026 			continue;
1027 
1028 		/** update key */
1029 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1030 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
1031 			switch (vec.cipher_auth.key.len) {
1032 			case 16:
1033 				val_key.val[k] ^= val.val[k];
1034 				break;
1035 			case 24:
1036 				if (k < 8)
1037 					val_key.val[k] ^= prev_out[k + 8];
1038 				else
1039 					val_key.val[k] ^= val.val[k - 8];
1040 				break;
1041 			case 32:
1042 				if (k < 16)
1043 					val_key.val[k] ^= prev_out[k];
1044 				else
1045 					val_key.val[k] ^= val.val[k - 16];
1046 				break;
1047 			default:
1048 				return -1;
1049 			}
1050 		}
1051 
1052 		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1053 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1054 	}
1055 
1056 	return 0;
1057 }
1058 
1059 static int
1060 init_test_ops(void)
1061 {
1062 	switch (info.algo) {
1063 	case FIPS_TEST_ALGO_AES:
1064 		test_ops.prepare_op = prepare_cipher_op;
1065 		test_ops.prepare_xform  = prepare_aes_xform;
1066 		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
1067 			test_ops.test = fips_mct_aes_test;
1068 		else
1069 			test_ops.test = fips_generic_test;
1070 		break;
1071 	case FIPS_TEST_ALGO_HMAC:
1072 		test_ops.prepare_op = prepare_auth_op;
1073 		test_ops.prepare_xform = prepare_hmac_xform;
1074 		test_ops.test = fips_generic_test;
1075 		break;
1076 	case FIPS_TEST_ALGO_TDES:
1077 		test_ops.prepare_op = prepare_cipher_op;
1078 		test_ops.prepare_xform  = prepare_tdes_xform;
1079 		if (info.interim_info.tdes_data.test_type == TDES_MCT)
1080 			test_ops.test = fips_mct_tdes_test;
1081 		else
1082 			test_ops.test = fips_generic_test;
1083 		break;
1084 	case FIPS_TEST_ALGO_AES_GCM:
1085 		test_ops.prepare_op = prepare_aead_op;
1086 		test_ops.prepare_xform = prepare_gcm_xform;
1087 		test_ops.test = fips_generic_test;
1088 		break;
1089 	case FIPS_TEST_ALGO_AES_CMAC:
1090 		test_ops.prepare_op = prepare_auth_op;
1091 		test_ops.prepare_xform = prepare_cmac_xform;
1092 		test_ops.test = fips_generic_test;
1093 		break;
1094 	default:
1095 		return -1;
1096 	}
1097 
1098 	return 0;
1099 }
1100 
1101 static void
1102 print_test_block(void)
1103 {
1104 	uint32_t i;
1105 
1106 	for (i = 0; i < info.nb_vec_lines; i++)
1107 		printf("%s\n", info.vec[i]);
1108 
1109 	printf("\n");
1110 }
1111 
1112 static int
1113 fips_test_one_file(void)
1114 {
1115 	int fetch_ret = 0, ret;
1116 
1117 
1118 	ret = init_test_ops();
1119 	if (ret < 0) {
1120 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
1121 		return ret;
1122 	}
1123 
1124 	while (ret >= 0 && fetch_ret == 0) {
1125 		fetch_ret = fips_test_fetch_one_block();
1126 		if (fetch_ret < 0) {
1127 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
1128 					fetch_ret);
1129 			ret = fetch_ret;
1130 			goto error_one_case;
1131 		}
1132 
1133 		if (info.nb_vec_lines == 0) {
1134 			if (fetch_ret == -EOF)
1135 				break;
1136 
1137 			fprintf(info.fp_wr, "\n");
1138 			continue;
1139 		}
1140 
1141 		ret = fips_test_parse_one_case();
1142 		switch (ret) {
1143 		case 0:
1144 			ret = test_ops.test();
1145 			if (ret == 0)
1146 				break;
1147 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
1148 					ret);
1149 			goto error_one_case;
1150 		case 1:
1151 			break;
1152 		default:
1153 			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
1154 					ret);
1155 			goto error_one_case;
1156 		}
1157 
1158 		continue;
1159 error_one_case:
1160 		print_test_block();
1161 	}
1162 
1163 	fips_test_clear();
1164 
1165 	return ret;
1166 
1167 }
1168