xref: /dpdk/examples/fips_validation/main.c (revision 527cbf3d5ee380f49db828957de4ba75f71e4311)
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_aes_xform(struct rte_crypto_sym_xform *xform)
466 {
467 	const struct rte_cryptodev_symmetric_capability *cap;
468 	struct rte_cryptodev_sym_capability_idx cap_idx;
469 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
470 
471 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
472 
473 	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
474 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
475 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
476 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
477 	cipher_xform->key.data = vec.cipher_auth.key.val;
478 	cipher_xform->key.length = vec.cipher_auth.key.len;
479 	cipher_xform->iv.length = vec.iv.len;
480 	cipher_xform->iv.offset = IV_OFF;
481 
482 	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
483 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
484 
485 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
486 	if (!cap) {
487 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
488 				env.dev_id);
489 		return -EINVAL;
490 	}
491 
492 	if (rte_cryptodev_sym_capability_check_cipher(cap,
493 			cipher_xform->key.length,
494 			cipher_xform->iv.length) != 0) {
495 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
496 				info.device_name, cipher_xform->key.length,
497 				cipher_xform->iv.length);
498 		return -EPERM;
499 	}
500 
501 	return 0;
502 }
503 
504 static int
505 prepare_tdes_xform(struct rte_crypto_sym_xform *xform)
506 {
507 	const struct rte_cryptodev_symmetric_capability *cap;
508 	struct rte_cryptodev_sym_capability_idx cap_idx;
509 	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
510 
511 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
512 
513 	cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
514 	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
515 			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
516 			RTE_CRYPTO_CIPHER_OP_DECRYPT;
517 	cipher_xform->key.data = vec.cipher_auth.key.val;
518 	cipher_xform->key.length = vec.cipher_auth.key.len;
519 	cipher_xform->iv.length = vec.iv.len;
520 	cipher_xform->iv.offset = IV_OFF;
521 
522 	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
523 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
524 
525 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
526 	if (!cap) {
527 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
528 				env.dev_id);
529 		return -EINVAL;
530 	}
531 
532 	if (rte_cryptodev_sym_capability_check_cipher(cap,
533 			cipher_xform->key.length,
534 			cipher_xform->iv.length) != 0) {
535 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
536 				info.device_name, cipher_xform->key.length,
537 				cipher_xform->iv.length);
538 		return -EPERM;
539 	}
540 
541 	return 0;
542 }
543 
544 static int
545 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
546 {
547 	const struct rte_cryptodev_symmetric_capability *cap;
548 	struct rte_cryptodev_sym_capability_idx cap_idx;
549 	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
550 
551 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
552 
553 	auth_xform->algo = info.interim_info.hmac_data.algo;
554 	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
555 	auth_xform->digest_length = vec.cipher_auth.digest.len;
556 	auth_xform->key.data = vec.cipher_auth.key.val;
557 	auth_xform->key.length = vec.cipher_auth.key.len;
558 
559 	cap_idx.algo.auth = auth_xform->algo;
560 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
561 
562 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
563 	if (!cap) {
564 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
565 				env.dev_id);
566 		return -EINVAL;
567 	}
568 
569 	if (rte_cryptodev_sym_capability_check_auth(cap,
570 			auth_xform->key.length,
571 			auth_xform->digest_length, 0) != 0) {
572 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
573 				info.device_name, auth_xform->key.length,
574 				auth_xform->digest_length);
575 		return -EPERM;
576 	}
577 
578 	return 0;
579 }
580 
581 static void
582 get_writeback_data(struct fips_val *val)
583 {
584 	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
585 	val->len = rte_pktmbuf_pkt_len(env.mbuf);
586 }
587 
588 static int
589 fips_run_test(void)
590 {
591 	struct rte_crypto_sym_xform xform = {0};
592 	uint16_t n_deqd;
593 	int ret;
594 
595 	ret = test_ops.prepare_xform(&xform);
596 	if (ret < 0)
597 		return ret;
598 
599 	env.sess = rte_cryptodev_sym_session_create(env.mpool);
600 	if (!env.sess)
601 		return -ENOMEM;
602 
603 	ret = rte_cryptodev_sym_session_init(env.dev_id,
604 			env.sess, &xform, env.mpool);
605 	if (ret < 0) {
606 		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
607 				ret);
608 		return ret;
609 	}
610 
611 	ret = test_ops.prepare_op();
612 	if (ret < 0) {
613 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
614 				ret);
615 		return ret;
616 	}
617 
618 	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
619 		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
620 		return ret;
621 	}
622 
623 	do {
624 		struct rte_crypto_op *deqd_op;
625 
626 		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
627 				1);
628 	} while (n_deqd == 0);
629 
630 	vec.status = env.op->status;
631 
632 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
633 	rte_cryptodev_sym_session_free(env.sess);
634 	env.sess = NULL;
635 
636 	return ret;
637 }
638 
639 static int
640 fips_generic_test(void)
641 {
642 	struct fips_val val;
643 	int ret;
644 
645 	fips_test_write_one_case();
646 
647 	ret = fips_run_test();
648 	if (ret < 0) {
649 		if (ret == -EPERM) {
650 			fprintf(info.fp_wr, "Bypass\n\n");
651 			return 0;
652 		}
653 
654 		return ret;
655 	}
656 
657 	get_writeback_data(&val);
658 
659 	switch (info.file_type) {
660 	case FIPS_TYPE_REQ:
661 	case FIPS_TYPE_RSP:
662 		if (info.parse_writeback == NULL)
663 			return -EPERM;
664 		ret = info.parse_writeback(&val);
665 		if (ret < 0)
666 			return ret;
667 		break;
668 	case FIPS_TYPE_FAX:
669 		if (info.kat_check == NULL)
670 			return -EPERM;
671 		ret = info.kat_check(&val);
672 		if (ret < 0)
673 			return ret;
674 		break;
675 	}
676 
677 	fprintf(info.fp_wr, "\n");
678 
679 	return 0;
680 }
681 
682 static int
683 fips_mct_tdes_test(void)
684 {
685 #define TDES_BLOCK_SIZE		8
686 #define TDES_EXTERN_ITER	400
687 #define TDES_INTERN_ITER	10000
688 	struct fips_val val, val_key;
689 	uint8_t prev_out[TDES_BLOCK_SIZE];
690 	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
691 	uint8_t prev_in[TDES_BLOCK_SIZE];
692 	uint32_t i, j, k;
693 	int ret;
694 
695 	for (i = 0; i < TDES_EXTERN_ITER; i++) {
696 		if (i != 0)
697 			update_info_vec(i);
698 
699 		fips_test_write_one_case();
700 
701 		for (j = 0; j < TDES_INTERN_ITER; j++) {
702 			ret = fips_run_test();
703 			if (ret < 0) {
704 				if (ret == -EPERM) {
705 					fprintf(info.fp_wr, "Bypass\n");
706 					return 0;
707 				}
708 
709 				return ret;
710 			}
711 
712 			get_writeback_data(&val);
713 
714 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
715 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
716 
717 			if (j == 0) {
718 				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
719 
720 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
721 					memcpy(vec.pt.val, vec.iv.val,
722 							TDES_BLOCK_SIZE);
723 					memcpy(vec.iv.val, val.val,
724 							TDES_BLOCK_SIZE);
725 				} else {
726 					memcpy(vec.iv.val, vec.ct.val,
727 							TDES_BLOCK_SIZE);
728 					memcpy(vec.ct.val, val.val,
729 							TDES_BLOCK_SIZE);
730 				}
731 				continue;
732 			}
733 
734 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
735 				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
736 				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
737 			} else {
738 				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
739 				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
740 			}
741 
742 			if (j == TDES_INTERN_ITER - 1)
743 				continue;
744 
745 			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
746 
747 			if (j == TDES_INTERN_ITER - 3)
748 				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
749 		}
750 
751 		info.parse_writeback(&val);
752 		fprintf(info.fp_wr, "\n");
753 
754 		if (i == TDES_EXTERN_ITER - 1)
755 			continue;
756 
757 		/** update key */
758 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
759 
760 		if (info.interim_info.tdes_data.nb_keys == 0) {
761 			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
762 				info.interim_info.tdes_data.nb_keys = 1;
763 			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
764 				info.interim_info.tdes_data.nb_keys = 2;
765 			else
766 				info.interim_info.tdes_data.nb_keys = 3;
767 
768 		}
769 
770 		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
771 
772 			switch (info.interim_info.tdes_data.nb_keys) {
773 			case 3:
774 				val_key.val[k] ^= val.val[k];
775 				val_key.val[k + 8] ^= prev_out[k];
776 				val_key.val[k + 16] ^= prev_prev_out[k];
777 				break;
778 			case 2:
779 				val_key.val[k] ^= val.val[k];
780 				val_key.val[k + 8] ^= prev_out[k];
781 				val_key.val[k + 16] ^= val.val[k];
782 				break;
783 			default: /* case 1 */
784 				val_key.val[k] ^= val.val[k];
785 				val_key.val[k + 8] ^= val.val[k];
786 				val_key.val[k + 16] ^= val.val[k];
787 				break;
788 			}
789 
790 		}
791 
792 		for (k = 0; k < 24; k++)
793 			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
794 					0x1) ?
795 					val_key.val[k] : (val_key.val[k] ^ 0x1);
796 
797 		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
798 			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
799 			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
800 		} else {
801 			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
802 			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
803 		}
804 	}
805 
806 	return 0;
807 }
808 
809 static int
810 fips_mct_aes_test(void)
811 {
812 #define AES_BLOCK_SIZE	16
813 #define AES_EXTERN_ITER	100
814 #define AES_INTERN_ITER	1000
815 	struct fips_val val, val_key;
816 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
817 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
818 	uint32_t i, j, k;
819 	int ret;
820 
821 	for (i = 0; i < AES_EXTERN_ITER; i++) {
822 		if (i != 0)
823 			update_info_vec(i);
824 
825 		fips_test_write_one_case();
826 
827 		for (j = 0; j < AES_INTERN_ITER; j++) {
828 			ret = fips_run_test();
829 			if (ret < 0) {
830 				if (ret == -EPERM) {
831 					fprintf(info.fp_wr, "Bypass\n");
832 					return 0;
833 				}
834 
835 				return ret;
836 			}
837 
838 			get_writeback_data(&val);
839 
840 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
841 				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
842 
843 			if (j == 0) {
844 				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
845 
846 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
847 					memcpy(vec.pt.val, vec.iv.val,
848 							AES_BLOCK_SIZE);
849 					memcpy(vec.iv.val, val.val,
850 							AES_BLOCK_SIZE);
851 				} else {
852 					memcpy(vec.ct.val, vec.iv.val,
853 							AES_BLOCK_SIZE);
854 					memcpy(vec.iv.val, prev_in,
855 							AES_BLOCK_SIZE);
856 				}
857 				continue;
858 			}
859 
860 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
861 				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
862 				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
863 			} else {
864 				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
865 				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
866 			}
867 
868 			if (j == AES_INTERN_ITER - 1)
869 				continue;
870 
871 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
872 		}
873 
874 		info.parse_writeback(&val);
875 		fprintf(info.fp_wr, "\n");
876 
877 		if (i == AES_EXTERN_ITER - 1)
878 			continue;
879 
880 		/** update key */
881 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
882 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
883 			switch (vec.cipher_auth.key.len) {
884 			case 16:
885 				val_key.val[k] ^= val.val[k];
886 				break;
887 			case 24:
888 				if (k < 8)
889 					val_key.val[k] ^= prev_out[k + 8];
890 				else
891 					val_key.val[k] ^= val.val[k - 8];
892 				break;
893 			case 32:
894 				if (k < 16)
895 					val_key.val[k] ^= prev_out[k];
896 				else
897 					val_key.val[k] ^= val.val[k - 16];
898 				break;
899 			default:
900 				return -1;
901 			}
902 		}
903 
904 		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
905 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
906 	}
907 
908 	return 0;
909 }
910 
911 static int
912 init_test_ops(void)
913 {
914 	switch (info.algo) {
915 	case FIPS_TEST_ALGO_AES:
916 		test_ops.prepare_op = prepare_cipher_op;
917 		test_ops.prepare_xform  = prepare_aes_xform;
918 		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
919 			test_ops.test = fips_mct_aes_test;
920 		else
921 			test_ops.test = fips_generic_test;
922 		break;
923 	case FIPS_TEST_ALGO_HMAC:
924 		test_ops.prepare_op = prepare_auth_op;
925 		test_ops.prepare_xform = prepare_hmac_xform;
926 		test_ops.test = fips_generic_test;
927 		break;
928 	case FIPS_TEST_ALGO_TDES:
929 		test_ops.prepare_op = prepare_cipher_op;
930 		test_ops.prepare_xform  = prepare_tdes_xform;
931 		if (info.interim_info.tdes_data.test_type == TDES_MCT)
932 			test_ops.test = fips_mct_tdes_test;
933 		else
934 			test_ops.test = fips_generic_test;
935 		break;
936 
937 	default:
938 		return -1;
939 	}
940 
941 	return 0;
942 }
943 
944 static void
945 print_test_block(void)
946 {
947 	uint32_t i;
948 
949 	for (i = 0; i < info.nb_vec_lines; i++)
950 		printf("%s\n", info.vec[i]);
951 
952 	printf("\n");
953 }
954 
955 static int
956 fips_test_one_file(void)
957 {
958 	int fetch_ret = 0, ret;
959 
960 
961 	ret = init_test_ops();
962 	if (ret < 0) {
963 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
964 		return ret;
965 	}
966 
967 	while (ret >= 0 && fetch_ret == 0) {
968 		fetch_ret = fips_test_fetch_one_block();
969 		if (fetch_ret < 0) {
970 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
971 					fetch_ret);
972 			ret = fetch_ret;
973 			goto error_one_case;
974 		}
975 
976 		if (info.nb_vec_lines == 0) {
977 			if (fetch_ret == -EOF)
978 				break;
979 
980 			fprintf(info.fp_wr, "\n");
981 			continue;
982 		}
983 
984 		ret = fips_test_parse_one_case();
985 		switch (ret) {
986 		case 0:
987 			ret = test_ops.test();
988 			if (ret == 0)
989 				break;
990 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
991 					ret);
992 			goto error_one_case;
993 		case 1:
994 			break;
995 		default:
996 			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
997 					ret);
998 			goto error_one_case;
999 		}
1000 
1001 		continue;
1002 error_one_case:
1003 		print_test_block();
1004 	}
1005 
1006 	fips_test_clear();
1007 
1008 	return ret;
1009 
1010 }
1011