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