xref: /dpdk/examples/fips_validation/main.c (revision f64adb6714e07daf2a1d4fe3ee3172f3f4a80c07)
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_hmac_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_auth_xform *auth_xform = &xform->auth;
510 
511 	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
512 
513 	auth_xform->algo = info.interim_info.hmac_data.algo;
514 	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
515 	auth_xform->digest_length = vec.cipher_auth.digest.len;
516 	auth_xform->key.data = vec.cipher_auth.key.val;
517 	auth_xform->key.length = vec.cipher_auth.key.len;
518 
519 	cap_idx.algo.auth = auth_xform->algo;
520 	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
521 
522 	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
523 	if (!cap) {
524 		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
525 				env.dev_id);
526 		return -EINVAL;
527 	}
528 
529 	if (rte_cryptodev_sym_capability_check_auth(cap,
530 			auth_xform->key.length,
531 			auth_xform->digest_length, 0) != 0) {
532 		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
533 				info.device_name, auth_xform->key.length,
534 				auth_xform->digest_length);
535 		return -EPERM;
536 	}
537 
538 	return 0;
539 }
540 
541 static void
542 get_writeback_data(struct fips_val *val)
543 {
544 	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
545 	val->len = rte_pktmbuf_pkt_len(env.mbuf);
546 }
547 
548 static int
549 fips_run_test(void)
550 {
551 	struct rte_crypto_sym_xform xform = {0};
552 	uint16_t n_deqd;
553 	int ret;
554 
555 	ret = test_ops.prepare_xform(&xform);
556 	if (ret < 0)
557 		return ret;
558 
559 	env.sess = rte_cryptodev_sym_session_create(env.mpool);
560 	if (!env.sess)
561 		return -ENOMEM;
562 
563 	ret = rte_cryptodev_sym_session_init(env.dev_id,
564 			env.sess, &xform, env.mpool);
565 	if (ret < 0) {
566 		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
567 				ret);
568 		return ret;
569 	}
570 
571 	ret = test_ops.prepare_op();
572 	if (ret < 0) {
573 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
574 				ret);
575 		return ret;
576 	}
577 
578 	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
579 		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
580 		return ret;
581 	}
582 
583 	do {
584 		struct rte_crypto_op *deqd_op;
585 
586 		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
587 				1);
588 	} while (n_deqd == 0);
589 
590 	vec.status = env.op->status;
591 
592 	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
593 	rte_cryptodev_sym_session_free(env.sess);
594 	env.sess = NULL;
595 
596 	return ret;
597 }
598 
599 static int
600 fips_generic_test(void)
601 {
602 	struct fips_val val;
603 	int ret;
604 
605 	fips_test_write_one_case();
606 
607 	ret = fips_run_test();
608 	if (ret < 0) {
609 		if (ret == -EPERM) {
610 			fprintf(info.fp_wr, "Bypass\n\n");
611 			return 0;
612 		}
613 
614 		return ret;
615 	}
616 
617 	get_writeback_data(&val);
618 
619 	switch (info.file_type) {
620 	case FIPS_TYPE_REQ:
621 	case FIPS_TYPE_RSP:
622 		if (info.parse_writeback == NULL)
623 			return -EPERM;
624 		ret = info.parse_writeback(&val);
625 		if (ret < 0)
626 			return ret;
627 		break;
628 	case FIPS_TYPE_FAX:
629 		if (info.kat_check == NULL)
630 			return -EPERM;
631 		ret = info.kat_check(&val);
632 		if (ret < 0)
633 			return ret;
634 		break;
635 	}
636 
637 	fprintf(info.fp_wr, "\n");
638 
639 	return 0;
640 }
641 
642 static int
643 fips_mct_aes_test(void)
644 {
645 #define AES_BLOCK_SIZE	16
646 #define AES_EXTERN_ITER	100
647 #define AES_INTERN_ITER	1000
648 	struct fips_val val, val_key;
649 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
650 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
651 	uint32_t i, j, k;
652 	int ret;
653 
654 	for (i = 0; i < AES_EXTERN_ITER; i++) {
655 		if (i != 0)
656 			update_info_vec(i);
657 
658 		fips_test_write_one_case();
659 
660 		for (j = 0; j < AES_INTERN_ITER; j++) {
661 			ret = fips_run_test();
662 			if (ret < 0) {
663 				if (ret == -EPERM) {
664 					fprintf(info.fp_wr, "Bypass\n");
665 					return 0;
666 				}
667 
668 				return ret;
669 			}
670 
671 			get_writeback_data(&val);
672 
673 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
674 				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
675 
676 			if (j == 0) {
677 				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
678 
679 				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
680 					memcpy(vec.pt.val, vec.iv.val,
681 							AES_BLOCK_SIZE);
682 					memcpy(vec.iv.val, val.val,
683 							AES_BLOCK_SIZE);
684 				} else {
685 					memcpy(vec.ct.val, vec.iv.val,
686 							AES_BLOCK_SIZE);
687 					memcpy(vec.iv.val, prev_in,
688 							AES_BLOCK_SIZE);
689 				}
690 				continue;
691 			}
692 
693 			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
694 				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
695 				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
696 			} else {
697 				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
698 				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
699 			}
700 
701 			if (j == AES_INTERN_ITER - 1)
702 				continue;
703 
704 			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
705 		}
706 
707 		info.parse_writeback(&val);
708 		fprintf(info.fp_wr, "\n");
709 
710 		if (i == AES_EXTERN_ITER - 1)
711 			continue;
712 
713 		/** update key */
714 		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
715 		for (k = 0; k < vec.cipher_auth.key.len; k++) {
716 			switch (vec.cipher_auth.key.len) {
717 			case 16:
718 				val_key.val[k] ^= val.val[k];
719 				break;
720 			case 24:
721 				if (k < 8)
722 					val_key.val[k] ^= prev_out[k + 8];
723 				else
724 					val_key.val[k] ^= val.val[k - 8];
725 				break;
726 			case 32:
727 				if (k < 16)
728 					val_key.val[k] ^= prev_out[k];
729 				else
730 					val_key.val[k] ^= val.val[k - 16];
731 				break;
732 			default:
733 				return -1;
734 			}
735 		}
736 
737 		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
738 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
739 	}
740 
741 	return 0;
742 }
743 
744 static int
745 init_test_ops(void)
746 {
747 	switch (info.algo) {
748 	case FIPS_TEST_ALGO_AES:
749 		test_ops.prepare_op = prepare_cipher_op;
750 		test_ops.prepare_xform  = prepare_aes_xform;
751 		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
752 			test_ops.test = fips_mct_aes_test;
753 		else
754 			test_ops.test = fips_generic_test;
755 		break;
756 	case FIPS_TEST_ALGO_HMAC:
757 		test_ops.prepare_op = prepare_auth_op;
758 		test_ops.prepare_xform = prepare_hmac_xform;
759 		test_ops.test = fips_generic_test;
760 		break;
761 
762 	default:
763 		return -1;
764 	}
765 
766 	return 0;
767 }
768 
769 static void
770 print_test_block(void)
771 {
772 	uint32_t i;
773 
774 	for (i = 0; i < info.nb_vec_lines; i++)
775 		printf("%s\n", info.vec[i]);
776 
777 	printf("\n");
778 }
779 
780 static int
781 fips_test_one_file(void)
782 {
783 	int fetch_ret = 0, ret;
784 
785 
786 	ret = init_test_ops();
787 	if (ret < 0) {
788 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
789 		return ret;
790 	}
791 
792 	while (ret >= 0 && fetch_ret == 0) {
793 		fetch_ret = fips_test_fetch_one_block();
794 		if (fetch_ret < 0) {
795 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
796 					fetch_ret);
797 			ret = fetch_ret;
798 			goto error_one_case;
799 		}
800 
801 		if (info.nb_vec_lines == 0) {
802 			if (fetch_ret == -EOF)
803 				break;
804 
805 			fprintf(info.fp_wr, "\n");
806 			continue;
807 		}
808 
809 		ret = fips_test_parse_one_case();
810 		switch (ret) {
811 		case 0:
812 			ret = test_ops.test();
813 			if (ret == 0)
814 				break;
815 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
816 					ret);
817 			goto error_one_case;
818 		case 1:
819 			break;
820 		default:
821 			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
822 					ret);
823 			goto error_one_case;
824 		}
825 
826 		continue;
827 error_one_case:
828 		print_test_block();
829 	}
830 
831 	fips_test_clear();
832 
833 	return ret;
834 
835 }
836