examples: add eal cleanup to examples
[dpdk.git] / examples / fips_validation / main.c
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 #include "fips_dev_self_test.h"
17
18 enum {
19 #define OPT_REQ_FILE_PATH           "req-file"
20         OPT_REQ_FILE_PATH_NUM = 256,
21 #define OPT_RSP_FILE_PATH           "rsp-file"
22         OPT_RSP_FILE_PATH_NUM,
23 #define OPT_MBUF_DATAROOM           "mbuf-dataroom"
24         OPT_MBUF_DATAROOM_NUM,
25 #define OPT_FOLDER                  "path-is-folder"
26         OPT_FOLDER_NUM,
27 #define OPT_CRYPTODEV               "cryptodev"
28         OPT_CRYPTODEV_NUM,
29 #define OPT_CRYPTODEV_ID            "cryptodev-id"
30         OPT_CRYPTODEV_ID_NUM,
31 #define OPT_CRYPTODEV_ST            "self-test"
32         OPT_CRYPTODEV_ST_NUM,
33 #define OPT_CRYPTODEV_BK_ID         "broken-test-id"
34         OPT_CRYPTODEV_BK_ID_NUM,
35 #define OPT_CRYPTODEV_BK_DIR_KEY    "broken-test-dir"
36         OPT_CRYPTODEV_BK_DIR_KEY_NUM,
37 };
38
39 struct fips_test_vector vec;
40 struct fips_test_interim_info info;
41
42 struct cryptodev_fips_validate_env {
43         const char *req_path;
44         const char *rsp_path;
45         uint32_t is_path_folder;
46         uint8_t dev_id;
47         uint8_t dev_support_sgl;
48         uint16_t mbuf_data_room;
49         struct rte_mempool *mpool;
50         struct rte_mempool *sess_mpool;
51         struct rte_mempool *sess_priv_mpool;
52         struct rte_mempool *op_pool;
53         struct rte_mbuf *mbuf;
54         uint8_t *digest;
55         uint16_t digest_len;
56         struct rte_crypto_op *op;
57         struct rte_cryptodev_sym_session *sess;
58         uint16_t self_test;
59         struct fips_dev_broken_test_config *broken_test_config;
60 } env;
61
62 static int
63 cryptodev_fips_validate_app_int(void)
64 {
65         struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
66         struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
67         struct rte_cryptodev_info dev_info;
68         uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
69                         env.dev_id);
70         uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
71         int ret;
72
73         if (env.self_test) {
74                 ret = fips_dev_self_test(env.dev_id, env.broken_test_config);
75                 if (ret < 0) {
76                         struct rte_cryptodev *cryptodev =
77                                         rte_cryptodev_pmd_get_dev(env.dev_id);
78
79                         rte_cryptodev_pmd_destroy(cryptodev);
80
81                         return ret;
82                 }
83         }
84
85         ret = rte_cryptodev_configure(env.dev_id, &conf);
86         if (ret < 0)
87                 return ret;
88
89         rte_cryptodev_info_get(env.dev_id, &dev_info);
90         if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
91                 env.dev_support_sgl = 1;
92         else
93                 env.dev_support_sgl = 0;
94
95         env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
96                         0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
97                         env.mbuf_data_room, rte_socket_id());
98         if (!env.mpool)
99                 return ret;
100
101         ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
102                         rte_socket_id());
103         if (ret < 0)
104                 return ret;
105
106         ret = -ENOMEM;
107
108         env.sess_mpool = rte_cryptodev_sym_session_pool_create(
109                         "FIPS_SESS_MEMPOOL", 16, 0, 0, 0, rte_socket_id());
110         if (!env.sess_mpool)
111                 goto error_exit;
112
113         env.sess_priv_mpool = rte_mempool_create("FIPS_SESS_PRIV_MEMPOOL",
114                         16, sess_sz, 0, 0, NULL, NULL, NULL,
115                         NULL, rte_socket_id(), 0);
116         if (!env.sess_priv_mpool)
117                 goto error_exit;
118
119         env.op_pool = rte_crypto_op_pool_create(
120                         "FIPS_OP_POOL",
121                         RTE_CRYPTO_OP_TYPE_SYMMETRIC,
122                         1, 0,
123                         16,
124                         rte_socket_id());
125         if (!env.op_pool)
126                 goto error_exit;
127
128         env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
129         if (!env.op)
130                 goto error_exit;
131
132         qp_conf.mp_session = env.sess_mpool;
133         qp_conf.mp_session_private = env.sess_priv_mpool;
134
135         ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
136                         rte_socket_id());
137         if (ret < 0)
138                 goto error_exit;
139
140         return 0;
141
142 error_exit:
143
144         rte_mempool_free(env.mpool);
145         if (env.sess_mpool)
146                 rte_mempool_free(env.sess_mpool);
147         if (env.sess_priv_mpool)
148                 rte_mempool_free(env.sess_priv_mpool);
149         if (env.op_pool)
150                 rte_mempool_free(env.op_pool);
151
152         return ret;
153 }
154
155 static void
156 cryptodev_fips_validate_app_uninit(void)
157 {
158         rte_pktmbuf_free(env.mbuf);
159         rte_crypto_op_free(env.op);
160         rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
161         rte_cryptodev_sym_session_free(env.sess);
162         rte_mempool_free(env.mpool);
163         rte_mempool_free(env.sess_mpool);
164         rte_mempool_free(env.sess_priv_mpool);
165         rte_mempool_free(env.op_pool);
166 }
167
168 static int
169 fips_test_one_file(void);
170
171 static int
172 parse_cryptodev_arg(char *arg)
173 {
174         int id = rte_cryptodev_get_dev_id(arg);
175
176         if (id < 0) {
177                 RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
178                                 id, arg);
179                 return id;
180         }
181
182         env.dev_id = (uint8_t)id;
183
184         return 0;
185 }
186
187 static int
188 parse_cryptodev_id_arg(char *arg)
189 {
190         uint32_t cryptodev_id;
191
192         if (parser_read_uint32(&cryptodev_id, arg) < 0) {
193                 RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
194                                 -EINVAL, arg);
195                 return -1;
196         }
197
198
199         if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
200                 RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
201                                 cryptodev_id, arg);
202                 return -1;
203         }
204
205         env.dev_id = (uint8_t)cryptodev_id;
206
207         return 0;
208 }
209
210 static void
211 cryptodev_fips_validate_usage(const char *prgname)
212 {
213         uint32_t def_mbuf_seg_size = DEF_MBUF_SEG_SIZE;
214         printf("%s [EAL options] --\n"
215                 "  --%s: REQUEST-FILE-PATH\n"
216                 "  --%s: RESPONSE-FILE-PATH\n"
217                 "  --%s: indicating both paths are folders\n"
218                 "  --%s: mbuf dataroom size (default %u bytes)\n"
219                 "  --%s: CRYPTODEV-NAME\n"
220                 "  --%s: CRYPTODEV-ID-NAME\n"
221                 "  --%s: self test indicator\n"
222                 "  --%s: self broken test ID\n"
223                 "  --%s: self broken test direction\n",
224                 prgname, OPT_REQ_FILE_PATH, OPT_RSP_FILE_PATH,
225                 OPT_FOLDER, OPT_MBUF_DATAROOM, def_mbuf_seg_size,
226                 OPT_CRYPTODEV, OPT_CRYPTODEV_ID, OPT_CRYPTODEV_ST,
227                 OPT_CRYPTODEV_BK_ID, OPT_CRYPTODEV_BK_DIR_KEY);
228 }
229
230 static int
231 cryptodev_fips_validate_parse_args(int argc, char **argv)
232 {
233         int opt, ret;
234         char *prgname = argv[0];
235         char **argvopt;
236         int option_index;
237         struct option lgopts[] = {
238                 {OPT_REQ_FILE_PATH, required_argument,
239                                 NULL, OPT_REQ_FILE_PATH_NUM},
240                 {OPT_RSP_FILE_PATH, required_argument,
241                                 NULL, OPT_RSP_FILE_PATH_NUM},
242                 {OPT_FOLDER, no_argument,
243                                 NULL, OPT_FOLDER_NUM},
244                 {OPT_MBUF_DATAROOM, required_argument,
245                                 NULL, OPT_MBUF_DATAROOM_NUM},
246                 {OPT_CRYPTODEV, required_argument,
247                                 NULL, OPT_CRYPTODEV_NUM},
248                 {OPT_CRYPTODEV_ID, required_argument,
249                                 NULL, OPT_CRYPTODEV_ID_NUM},
250                 {OPT_CRYPTODEV_ST, no_argument,
251                                 NULL, OPT_CRYPTODEV_ST_NUM},
252                 {OPT_CRYPTODEV_BK_ID, required_argument,
253                                 NULL, OPT_CRYPTODEV_BK_ID_NUM},
254                 {OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
255                                 NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
256                 {NULL, 0, 0, 0}
257         };
258
259         argvopt = argv;
260
261         env.mbuf_data_room = DEF_MBUF_SEG_SIZE;
262         if (rte_cryptodev_count())
263                 env.dev_id = 0;
264         else {
265                 cryptodev_fips_validate_usage(prgname);
266                 return -EINVAL;
267         }
268
269         while ((opt = getopt_long(argc, argvopt, "s:",
270                                   lgopts, &option_index)) != EOF) {
271
272                 switch (opt) {
273                 case OPT_REQ_FILE_PATH_NUM:
274                         env.req_path = optarg;
275                         break;
276
277                 case OPT_RSP_FILE_PATH_NUM:
278                         env.rsp_path = optarg;
279                         break;
280
281                 case OPT_FOLDER_NUM:
282                         env.is_path_folder = 1;
283                         break;
284
285                 case OPT_CRYPTODEV_NUM:
286                         ret = parse_cryptodev_arg(optarg);
287                         if (ret < 0) {
288                                 cryptodev_fips_validate_usage(prgname);
289                                 return -EINVAL;
290                         }
291                         break;
292
293                 case OPT_CRYPTODEV_ID_NUM:
294                         ret = parse_cryptodev_id_arg(optarg);
295                         if (ret < 0) {
296                                 cryptodev_fips_validate_usage(prgname);
297                                 return -EINVAL;
298                         }
299                         break;
300
301                 case OPT_CRYPTODEV_ST_NUM:
302                         env.self_test = 1;
303                         break;
304
305                 case OPT_CRYPTODEV_BK_ID_NUM:
306                         if (!env.broken_test_config) {
307                                 env.broken_test_config = rte_malloc(
308                                         NULL,
309                                         sizeof(*env.broken_test_config),
310                                         0);
311                                 if (!env.broken_test_config)
312                                         return -ENOMEM;
313
314                                 env.broken_test_config->expect_fail_dir =
315                                         self_test_dir_enc_auth_gen;
316                         }
317
318                         if (parser_read_uint32(
319                                 &env.broken_test_config->expect_fail_test_idx,
320                                         optarg) < 0) {
321                                 rte_free(env.broken_test_config);
322                                 cryptodev_fips_validate_usage(prgname);
323                                 return -EINVAL;
324                         }
325                         break;
326
327                 case OPT_CRYPTODEV_BK_DIR_KEY_NUM:
328                         if (!env.broken_test_config) {
329                                 env.broken_test_config = rte_malloc(
330                                         NULL,
331                                         sizeof(*env.broken_test_config),
332                                         0);
333                                 if (!env.broken_test_config)
334                                         return -ENOMEM;
335
336                                 env.broken_test_config->expect_fail_test_idx =
337                                         0;
338                         }
339
340                         if (strcmp(optarg, "enc") == 0)
341                                 env.broken_test_config->expect_fail_dir =
342                                         self_test_dir_enc_auth_gen;
343                         else if (strcmp(optarg, "dec")
344                                         == 0)
345                                 env.broken_test_config->expect_fail_dir =
346                                         self_test_dir_dec_auth_verify;
347                         else {
348                                 rte_free(env.broken_test_config);
349                                 cryptodev_fips_validate_usage(prgname);
350                                 return -EINVAL;
351                         }
352                         break;
353
354
355                 case OPT_MBUF_DATAROOM_NUM:
356                         if (parser_read_uint16(&env.mbuf_data_room,
357                                         optarg) < 0) {
358                                 cryptodev_fips_validate_usage(prgname);
359                                 return -EINVAL;
360                         }
361
362                         if (env.mbuf_data_room == 0) {
363                                 cryptodev_fips_validate_usage(prgname);
364                                 return -EINVAL;
365                         }
366                         break;
367
368                 default:
369                         cryptodev_fips_validate_usage(prgname);
370                         return -EINVAL;
371                 }
372         }
373
374         if ((env.req_path == NULL && env.rsp_path != NULL) ||
375                         (env.req_path != NULL && env.rsp_path == NULL)) {
376                 RTE_LOG(ERR, USER1, "Missing req path or rsp path\n");
377                 cryptodev_fips_validate_usage(prgname);
378                 return -EINVAL;
379         }
380
381         if (env.req_path == NULL && env.self_test == 0) {
382                 RTE_LOG(ERR, USER1, "--self-test must be set if req path is missing\n");
383                 cryptodev_fips_validate_usage(prgname);
384                 return -EINVAL;
385         }
386
387         return 0;
388 }
389
390 int
391 main(int argc, char *argv[])
392 {
393         int ret;
394
395         ret = rte_eal_init(argc, argv);
396         if (ret < 0) {
397                 RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
398                 return -1;
399         }
400
401         argc -= ret;
402         argv += ret;
403
404         ret = cryptodev_fips_validate_parse_args(argc, argv);
405         if (ret < 0)
406                 rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
407
408         ret = cryptodev_fips_validate_app_int();
409         if (ret < 0) {
410                 RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
411                 return -1;
412         }
413
414         if (env.req_path == NULL || env.rsp_path == NULL) {
415                 printf("No request, exit.\n");
416                 goto exit;
417         }
418
419         if (!env.is_path_folder) {
420                 printf("Processing file %s... ", env.req_path);
421
422                 ret = fips_test_init(env.req_path, env.rsp_path,
423                         rte_cryptodev_name_get(env.dev_id));
424                 if (ret < 0) {
425                         RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
426                                         ret, env.req_path);
427                         goto exit;
428                 }
429
430
431                 ret = fips_test_one_file();
432                 if (ret < 0) {
433                         RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
434                                         ret, env.req_path);
435                         goto exit;
436                 }
437
438                 printf("Done\n");
439
440         } else {
441                 struct dirent *dir;
442                 DIR *d_req, *d_rsp;
443                 char req_path[1024];
444                 char rsp_path[1024];
445
446                 d_req = opendir(env.req_path);
447                 if (!d_req) {
448                         RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
449                                         -EINVAL, env.req_path);
450                         goto exit;
451                 }
452
453                 d_rsp = opendir(env.rsp_path);
454                 if (!d_rsp) {
455                         ret = mkdir(env.rsp_path, 0700);
456                         if (ret == 0)
457                                 d_rsp = opendir(env.rsp_path);
458                         else {
459                                 RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
460                                                 -EINVAL, env.rsp_path);
461                                 goto exit;
462                         }
463                 }
464                 closedir(d_rsp);
465
466                 while ((dir = readdir(d_req)) != NULL) {
467                         if (strstr(dir->d_name, "req") == NULL)
468                                 continue;
469
470                         snprintf(req_path, 1023, "%s/%s", env.req_path,
471                                         dir->d_name);
472                         snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
473                                         dir->d_name);
474                         strlcpy(strstr(rsp_path, "req"), "rsp", 4);
475
476                         printf("Processing file %s... ", req_path);
477
478                         ret = fips_test_init(req_path, rsp_path,
479                         rte_cryptodev_name_get(env.dev_id));
480                         if (ret < 0) {
481                                 RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
482                                                 ret, req_path);
483                                 break;
484                         }
485
486                         ret = fips_test_one_file();
487                         if (ret < 0) {
488                                 RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
489                                                 ret, req_path);
490                                 break;
491                         }
492
493                         printf("Done\n");
494                 }
495
496                 closedir(d_req);
497         }
498
499
500 exit:
501         fips_test_clear();
502         cryptodev_fips_validate_app_uninit();
503
504         /* clean up the EAL */
505         rte_eal_cleanup();
506
507         return ret;
508
509 }
510
511 #define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
512 #define CRYPTODEV_FIPS_MAX_RETRIES      16
513
514 struct fips_test_ops test_ops;
515
516 static int
517 prepare_data_mbufs(struct fips_val *val)
518 {
519         struct rte_mbuf *m, *head = 0;
520         uint8_t *src = val->val;
521         uint32_t total_len = val->len;
522         uint16_t nb_seg;
523         int ret = 0;
524
525         if (env.mbuf)
526                 rte_pktmbuf_free(env.mbuf);
527
528         if (total_len > RTE_MBUF_MAX_NB_SEGS) {
529                 RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
530                 return -EPERM;
531         }
532
533         nb_seg = total_len / env.mbuf_data_room;
534         if (total_len % env.mbuf_data_room)
535                 nb_seg++;
536
537         m = rte_pktmbuf_alloc(env.mpool);
538         if (!m) {
539                 RTE_LOG(ERR, USER1, "Error %i: Not enough mbuf\n",
540                                 -ENOMEM);
541                 return -ENOMEM;
542         }
543         head = m;
544
545         while (nb_seg) {
546                 uint16_t len = RTE_MIN(total_len, env.mbuf_data_room);
547                 uint8_t *dst = (uint8_t *)rte_pktmbuf_append(m, len);
548
549                 if (!dst) {
550                         RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
551                                         -ENOMEM);
552                         ret = -ENOMEM;
553                         goto error_exit;
554                 }
555
556                 memcpy(dst, src, len);
557
558                 if (head != m) {
559                         ret = rte_pktmbuf_chain(head, m);
560                         if (ret) {
561                                 rte_pktmbuf_free(m);
562                                 RTE_LOG(ERR, USER1, "Error %i: SGL build\n",
563                                                 ret);
564                                 goto error_exit;
565                         }
566                 }
567                 total_len -= len;
568
569                 if (total_len) {
570                         if (!env.dev_support_sgl) {
571                                 RTE_LOG(ERR, USER1, "SGL not supported\n");
572                                 ret = -EPERM;
573                                 goto error_exit;
574                         }
575
576                         m = rte_pktmbuf_alloc(env.mpool);
577                         if (!m) {
578                                 RTE_LOG(ERR, USER1, "Error %i: No memory\n",
579                                                 -ENOMEM);
580                                 goto error_exit;
581                         }
582                 } else
583                         break;
584
585                 src += len;
586                 nb_seg--;
587         }
588
589         if (total_len) {
590                 RTE_LOG(ERR, USER1, "Error %i: Failed to store all data\n",
591                                 -ENOMEM);
592                 goto error_exit;
593         }
594
595         env.mbuf = head;
596
597         return 0;
598
599 error_exit:
600         if (head)
601                 rte_pktmbuf_free(head);
602         return ret;
603 }
604
605 static int
606 prepare_cipher_op(void)
607 {
608         struct rte_crypto_sym_op *sym = env.op->sym;
609         uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
610         int ret;
611
612         __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
613
614         memcpy(iv, vec.iv.val, vec.iv.len);
615
616         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
617                 ret = prepare_data_mbufs(&vec.pt);
618                 if (ret < 0)
619                         return ret;
620
621                 sym->cipher.data.length = vec.pt.len;
622         } else {
623                 ret = prepare_data_mbufs(&vec.ct);
624                 if (ret < 0)
625                         return ret;
626
627                 sym->cipher.data.length = vec.ct.len;
628         }
629
630         rte_crypto_op_attach_sym_session(env.op, env.sess);
631
632         sym->m_src = env.mbuf;
633         sym->cipher.data.offset = 0;
634
635         return 0;
636 }
637
638 int
639 prepare_auth_op(void)
640 {
641         struct rte_crypto_sym_op *sym = env.op->sym;
642         int ret;
643
644         __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
645
646         if (vec.iv.len) {
647                 uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *,
648                                 IV_OFF);
649                 memset(iv, 0, vec.iv.len);
650                 if (vec.iv.val)
651                         memcpy(iv, vec.iv.val, vec.iv.len);
652         }
653
654         ret = prepare_data_mbufs(&vec.pt);
655         if (ret < 0)
656                 return ret;
657
658         if (env.digest)
659                 rte_free(env.digest);
660
661         env.digest = rte_zmalloc(NULL, vec.cipher_auth.digest.len,
662                         RTE_CACHE_LINE_SIZE);
663         if (!env.digest) {
664                 RTE_LOG(ERR, USER1, "Not enough memory\n");
665                 return -ENOMEM;
666         }
667         env.digest_len = vec.cipher_auth.digest.len;
668
669         sym->m_src = env.mbuf;
670         sym->auth.data.offset = 0;
671         sym->auth.data.length = vec.pt.len;
672         sym->auth.digest.data = env.digest;
673         sym->auth.digest.phys_addr = rte_malloc_virt2iova(env.digest);
674
675         if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
676                 memcpy(env.digest, vec.cipher_auth.digest.val,
677                                 vec.cipher_auth.digest.len);
678
679         rte_crypto_op_attach_sym_session(env.op, env.sess);
680
681         return 0;
682 }
683
684 int
685 prepare_aead_op(void)
686 {
687         struct rte_crypto_sym_op *sym = env.op->sym;
688         uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
689         int ret;
690
691         __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
692
693         if (info.algo == FIPS_TEST_ALGO_AES_CCM)
694                 iv++;
695
696         if (vec.iv.val)
697                 memcpy(iv, vec.iv.val, vec.iv.len);
698         else
699                 /* if REQ file has iv length but not data, default as all 0 */
700                 memset(iv, 0, vec.iv.len);
701
702         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
703                 ret = prepare_data_mbufs(&vec.pt);
704                 if (ret < 0)
705                         return ret;
706
707                 if (env.digest)
708                         rte_free(env.digest);
709                 env.digest = rte_zmalloc(NULL, vec.aead.digest.len,
710                                 RTE_CACHE_LINE_SIZE);
711                 if (!env.digest) {
712                         RTE_LOG(ERR, USER1, "Not enough memory\n");
713                         return -ENOMEM;
714                 }
715                 env.digest_len = vec.cipher_auth.digest.len;
716
717                 sym->aead.data.length = vec.pt.len;
718                 sym->aead.digest.data = env.digest;
719                 sym->aead.digest.phys_addr = rte_malloc_virt2iova(env.digest);
720         } else {
721                 ret = prepare_data_mbufs(&vec.ct);
722                 if (ret < 0)
723                         return ret;
724
725                 sym->aead.data.length = vec.ct.len;
726                 sym->aead.digest.data = vec.aead.digest.val;
727                 sym->aead.digest.phys_addr = rte_malloc_virt2iova(
728                                 sym->aead.digest.data);
729         }
730
731         sym->m_src = env.mbuf;
732         sym->aead.data.offset = 0;
733         sym->aead.aad.data = vec.aead.aad.val;
734         sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
735
736         rte_crypto_op_attach_sym_session(env.op, env.sess);
737
738         return 0;
739 }
740
741 static int
742 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
743 {
744         const struct rte_cryptodev_symmetric_capability *cap;
745         struct rte_cryptodev_sym_capability_idx cap_idx;
746         struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
747
748         xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
749
750         if (info.interim_info.aes_data.cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC)
751                 cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
752         else
753                 cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_ECB;
754
755         cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
756                         RTE_CRYPTO_CIPHER_OP_ENCRYPT :
757                         RTE_CRYPTO_CIPHER_OP_DECRYPT;
758         cipher_xform->key.data = vec.cipher_auth.key.val;
759         cipher_xform->key.length = vec.cipher_auth.key.len;
760         if (cipher_xform->algo == RTE_CRYPTO_CIPHER_AES_CBC) {
761                 cipher_xform->iv.length = vec.iv.len;
762                 cipher_xform->iv.offset = IV_OFF;
763         } else {
764                 cipher_xform->iv.length = 0;
765                 cipher_xform->iv.offset = 0;
766         }
767         cap_idx.algo.cipher = cipher_xform->algo;
768         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
769
770         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
771         if (!cap) {
772                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
773                                 env.dev_id);
774                 return -EINVAL;
775         }
776
777         if (rte_cryptodev_sym_capability_check_cipher(cap,
778                         cipher_xform->key.length,
779                         cipher_xform->iv.length) != 0) {
780                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
781                                 info.device_name, cipher_xform->key.length,
782                                 cipher_xform->iv.length);
783                 return -EPERM;
784         }
785
786         return 0;
787 }
788
789 static int
790 prepare_tdes_xform(struct rte_crypto_sym_xform *xform)
791 {
792         const struct rte_cryptodev_symmetric_capability *cap;
793         struct rte_cryptodev_sym_capability_idx cap_idx;
794         struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
795
796         xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
797
798         if (info.interim_info.tdes_data.test_mode == TDES_MODE_CBC)
799                 cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
800         else
801                 cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_ECB;
802         cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
803                         RTE_CRYPTO_CIPHER_OP_ENCRYPT :
804                         RTE_CRYPTO_CIPHER_OP_DECRYPT;
805         cipher_xform->key.data = vec.cipher_auth.key.val;
806         cipher_xform->key.length = vec.cipher_auth.key.len;
807
808         if (cipher_xform->algo == RTE_CRYPTO_CIPHER_3DES_CBC) {
809                 cipher_xform->iv.length = vec.iv.len;
810                 cipher_xform->iv.offset = IV_OFF;
811         } else {
812                 cipher_xform->iv.length = 0;
813                 cipher_xform->iv.offset = 0;
814         }
815         cap_idx.algo.cipher = cipher_xform->algo;
816         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
817
818         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
819         if (!cap) {
820                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
821                                 env.dev_id);
822                 return -EINVAL;
823         }
824
825         if (rte_cryptodev_sym_capability_check_cipher(cap,
826                         cipher_xform->key.length,
827                         cipher_xform->iv.length) != 0) {
828                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
829                                 info.device_name, cipher_xform->key.length,
830                                 cipher_xform->iv.length);
831                 return -EPERM;
832         }
833
834         return 0;
835 }
836
837 static int
838 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
839 {
840         const struct rte_cryptodev_symmetric_capability *cap;
841         struct rte_cryptodev_sym_capability_idx cap_idx;
842         struct rte_crypto_auth_xform *auth_xform = &xform->auth;
843
844         xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
845
846         auth_xform->algo = info.interim_info.hmac_data.algo;
847         auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
848         auth_xform->digest_length = vec.cipher_auth.digest.len;
849         auth_xform->key.data = vec.cipher_auth.key.val;
850         auth_xform->key.length = vec.cipher_auth.key.len;
851
852         cap_idx.algo.auth = auth_xform->algo;
853         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
854
855         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
856         if (!cap) {
857                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
858                                 env.dev_id);
859                 return -EINVAL;
860         }
861
862         if (rte_cryptodev_sym_capability_check_auth(cap,
863                         auth_xform->key.length,
864                         auth_xform->digest_length, 0) != 0) {
865                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
866                                 info.device_name, auth_xform->key.length,
867                                 auth_xform->digest_length);
868                 return -EPERM;
869         }
870
871         return 0;
872 }
873
874 int
875 prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
876 {
877         const struct rte_cryptodev_symmetric_capability *cap;
878         struct rte_cryptodev_sym_capability_idx cap_idx;
879         struct rte_crypto_aead_xform *aead_xform = &xform->aead;
880
881         xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
882
883         aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
884         aead_xform->aad_length = vec.aead.aad.len;
885         aead_xform->digest_length = vec.aead.digest.len;
886         aead_xform->iv.offset = IV_OFF;
887         aead_xform->iv.length = vec.iv.len;
888         aead_xform->key.data = vec.aead.key.val;
889         aead_xform->key.length = vec.aead.key.len;
890         aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
891                         RTE_CRYPTO_AEAD_OP_ENCRYPT :
892                         RTE_CRYPTO_AEAD_OP_DECRYPT;
893
894         cap_idx.algo.aead = aead_xform->algo;
895         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
896
897         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
898         if (!cap) {
899                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
900                                 env.dev_id);
901                 return -EINVAL;
902         }
903
904         if (rte_cryptodev_sym_capability_check_aead(cap,
905                         aead_xform->key.length,
906                         aead_xform->digest_length, aead_xform->aad_length,
907                         aead_xform->iv.length) != 0) {
908                 RTE_LOG(ERR, USER1,
909                         "PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
910                                 info.device_name, aead_xform->key.length,
911                                 aead_xform->digest_length,
912                                 aead_xform->aad_length,
913                                 aead_xform->iv.length);
914                 return -EPERM;
915         }
916
917         return 0;
918 }
919
920 int
921 prepare_gmac_xform(struct rte_crypto_sym_xform *xform)
922 {
923         const struct rte_cryptodev_symmetric_capability *cap;
924         struct rte_cryptodev_sym_capability_idx cap_idx;
925         struct rte_crypto_auth_xform *auth_xform = &xform->auth;
926
927         xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
928
929         auth_xform->algo = RTE_CRYPTO_AUTH_AES_GMAC;
930         auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
931                         RTE_CRYPTO_AUTH_OP_GENERATE :
932                         RTE_CRYPTO_AUTH_OP_VERIFY;
933         auth_xform->iv.offset = IV_OFF;
934         auth_xform->iv.length = vec.iv.len;
935         auth_xform->digest_length = vec.aead.digest.len;
936         auth_xform->key.data = vec.aead.key.val;
937         auth_xform->key.length = vec.aead.key.len;
938
939         cap_idx.algo.auth = auth_xform->algo;
940         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
941
942         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
943         if (!cap) {
944                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
945                                 env.dev_id);
946                 return -EINVAL;
947         }
948
949         if (rte_cryptodev_sym_capability_check_auth(cap,
950                         auth_xform->key.length,
951                         auth_xform->digest_length,
952                         auth_xform->iv.length) != 0) {
953
954                 RTE_LOG(ERR, USER1,
955                         "PMD %s key length %u Digest length %u IV length %u\n",
956                                 info.device_name, auth_xform->key.length,
957                                 auth_xform->digest_length,
958                                 auth_xform->iv.length);
959                 return -EPERM;
960         }
961
962         return 0;
963 }
964
965 static int
966 prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
967 {
968         const struct rte_cryptodev_symmetric_capability *cap;
969         struct rte_cryptodev_sym_capability_idx cap_idx;
970         struct rte_crypto_auth_xform *auth_xform = &xform->auth;
971
972         xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
973
974         auth_xform->algo = RTE_CRYPTO_AUTH_AES_CMAC;
975         auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
976                         RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
977         auth_xform->digest_length = vec.cipher_auth.digest.len;
978         auth_xform->key.data = vec.cipher_auth.key.val;
979         auth_xform->key.length = vec.cipher_auth.key.len;
980
981         cap_idx.algo.auth = auth_xform->algo;
982         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
983
984         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
985         if (!cap) {
986                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
987                                 env.dev_id);
988                 return -EINVAL;
989         }
990
991         if (rte_cryptodev_sym_capability_check_auth(cap,
992                         auth_xform->key.length,
993                         auth_xform->digest_length, 0) != 0) {
994                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
995                                 info.device_name, auth_xform->key.length,
996                                 auth_xform->digest_length);
997                 return -EPERM;
998         }
999
1000         return 0;
1001 }
1002
1003 static int
1004 prepare_ccm_xform(struct rte_crypto_sym_xform *xform)
1005 {
1006         const struct rte_cryptodev_symmetric_capability *cap;
1007         struct rte_cryptodev_sym_capability_idx cap_idx;
1008         struct rte_crypto_aead_xform *aead_xform = &xform->aead;
1009
1010         xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
1011
1012         aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
1013         aead_xform->aad_length = vec.aead.aad.len;
1014         aead_xform->digest_length = vec.aead.digest.len;
1015         aead_xform->iv.offset = IV_OFF;
1016         aead_xform->iv.length = vec.iv.len;
1017         aead_xform->key.data = vec.aead.key.val;
1018         aead_xform->key.length = vec.aead.key.len;
1019         aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
1020                         RTE_CRYPTO_AEAD_OP_ENCRYPT :
1021                         RTE_CRYPTO_AEAD_OP_DECRYPT;
1022
1023         cap_idx.algo.aead = aead_xform->algo;
1024         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
1025
1026         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1027         if (!cap) {
1028                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1029                                 env.dev_id);
1030                 return -EINVAL;
1031         }
1032
1033         if (rte_cryptodev_sym_capability_check_aead(cap,
1034                         aead_xform->key.length,
1035                         aead_xform->digest_length, aead_xform->aad_length,
1036                         aead_xform->iv.length) != 0) {
1037                 RTE_LOG(ERR, USER1,
1038                         "PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
1039                                 info.device_name, aead_xform->key.length,
1040                                 aead_xform->digest_length,
1041                                 aead_xform->aad_length,
1042                                 aead_xform->iv.length);
1043                 return -EPERM;
1044         }
1045
1046         return 0;
1047 }
1048
1049 static int
1050 prepare_sha_xform(struct rte_crypto_sym_xform *xform)
1051 {
1052         const struct rte_cryptodev_symmetric_capability *cap;
1053         struct rte_cryptodev_sym_capability_idx cap_idx;
1054         struct rte_crypto_auth_xform *auth_xform = &xform->auth;
1055
1056         xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
1057
1058         auth_xform->algo = info.interim_info.sha_data.algo;
1059         auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
1060         auth_xform->digest_length = vec.cipher_auth.digest.len;
1061
1062         cap_idx.algo.auth = auth_xform->algo;
1063         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
1064
1065         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1066         if (!cap) {
1067                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1068                                 env.dev_id);
1069                 return -EINVAL;
1070         }
1071
1072         if (rte_cryptodev_sym_capability_check_auth(cap,
1073                         auth_xform->key.length,
1074                         auth_xform->digest_length, 0) != 0) {
1075                 RTE_LOG(ERR, USER1, "PMD %s key length %u digest length %u\n",
1076                                 info.device_name, auth_xform->key.length,
1077                                 auth_xform->digest_length);
1078                 return -EPERM;
1079         }
1080
1081         return 0;
1082 }
1083
1084 static int
1085 prepare_xts_xform(struct rte_crypto_sym_xform *xform)
1086 {
1087         const struct rte_cryptodev_symmetric_capability *cap;
1088         struct rte_cryptodev_sym_capability_idx cap_idx;
1089         struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
1090
1091         xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1092
1093         cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_XTS;
1094         cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
1095                         RTE_CRYPTO_CIPHER_OP_ENCRYPT :
1096                         RTE_CRYPTO_CIPHER_OP_DECRYPT;
1097         cipher_xform->key.data = vec.cipher_auth.key.val;
1098         cipher_xform->key.length = vec.cipher_auth.key.len;
1099         cipher_xform->iv.length = vec.iv.len;
1100         cipher_xform->iv.offset = IV_OFF;
1101
1102         cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_XTS;
1103         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1104
1105         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1106         if (!cap) {
1107                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1108                                 env.dev_id);
1109                 return -EINVAL;
1110         }
1111
1112         if (rte_cryptodev_sym_capability_check_cipher(cap,
1113                         cipher_xform->key.length,
1114                         cipher_xform->iv.length) != 0) {
1115                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
1116                                 info.device_name, cipher_xform->key.length,
1117                                 cipher_xform->iv.length);
1118                 return -EPERM;
1119         }
1120
1121         return 0;
1122 }
1123
1124 static int
1125 get_writeback_data(struct fips_val *val)
1126 {
1127         struct rte_mbuf *m = env.mbuf;
1128         uint16_t data_len = rte_pktmbuf_pkt_len(m);
1129         uint16_t total_len = data_len + env.digest_len;
1130         uint8_t *src, *dst, *wb_data;
1131
1132         /* in case val is reused for MCT test, try to free the buffer first */
1133         if (val->val) {
1134                 free(val->val);
1135                 val->val = NULL;
1136         }
1137
1138         wb_data = dst = calloc(1, total_len);
1139         if (!dst) {
1140                 RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
1141                 return -ENOMEM;
1142         }
1143
1144         while (m && data_len) {
1145                 uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
1146
1147                 src = rte_pktmbuf_mtod(m, uint8_t *);
1148                 memcpy(dst, src, seg_len);
1149                 m = m->next;
1150                 data_len -= seg_len;
1151                 dst += seg_len;
1152         }
1153
1154         if (data_len) {
1155                 RTE_LOG(ERR, USER1, "Error -1: write back data\n");
1156                 free(wb_data);
1157                 return -1;
1158         }
1159
1160         if (env.digest)
1161                 memcpy(dst, env.digest, env.digest_len);
1162
1163         val->val = wb_data;
1164         val->len = total_len;
1165
1166         return 0;
1167 }
1168
1169 static int
1170 fips_run_test(void)
1171 {
1172         struct rte_crypto_sym_xform xform = {0};
1173         uint16_t n_deqd;
1174         int ret;
1175
1176         ret = test_ops.prepare_xform(&xform);
1177         if (ret < 0)
1178                 return ret;
1179
1180         env.sess = rte_cryptodev_sym_session_create(env.sess_mpool);
1181         if (!env.sess)
1182                 return -ENOMEM;
1183
1184         ret = rte_cryptodev_sym_session_init(env.dev_id,
1185                         env.sess, &xform, env.sess_priv_mpool);
1186         if (ret < 0) {
1187                 RTE_LOG(ERR, USER1, "Error %i: Init session\n",
1188                                 ret);
1189                 goto exit;
1190         }
1191
1192         ret = test_ops.prepare_op();
1193         if (ret < 0) {
1194                 RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
1195                                 ret);
1196                 goto exit;
1197         }
1198
1199         if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
1200                 RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
1201                 ret = -1;
1202                 goto exit;
1203         }
1204
1205         do {
1206                 struct rte_crypto_op *deqd_op;
1207
1208                 n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
1209                                 1);
1210         } while (n_deqd == 0);
1211
1212         vec.status = env.op->status;
1213
1214 exit:
1215         rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
1216         rte_cryptodev_sym_session_free(env.sess);
1217         env.sess = NULL;
1218
1219         return ret;
1220 }
1221
1222 static int
1223 fips_generic_test(void)
1224 {
1225         struct fips_val val = {NULL, 0};
1226         int ret;
1227
1228         fips_test_write_one_case();
1229
1230         ret = fips_run_test();
1231         if (ret < 0) {
1232                 if (ret == -EPERM || ret == -ENOTSUP) {
1233                         fprintf(info.fp_wr, "Bypass\n\n");
1234                         return 0;
1235                 }
1236
1237                 return ret;
1238         }
1239
1240         ret = get_writeback_data(&val);
1241         if (ret < 0)
1242                 return ret;
1243
1244         switch (info.file_type) {
1245         case FIPS_TYPE_REQ:
1246         case FIPS_TYPE_RSP:
1247                 if (info.parse_writeback == NULL)
1248                         return -EPERM;
1249                 ret = info.parse_writeback(&val);
1250                 if (ret < 0)
1251                         return ret;
1252                 break;
1253         case FIPS_TYPE_FAX:
1254                 if (info.kat_check == NULL)
1255                         return -EPERM;
1256                 ret = info.kat_check(&val);
1257                 if (ret < 0)
1258                         return ret;
1259                 break;
1260         }
1261
1262         fprintf(info.fp_wr, "\n");
1263         free(val.val);
1264
1265         return 0;
1266 }
1267
1268 static int
1269 fips_mct_tdes_test(void)
1270 {
1271 #define TDES_BLOCK_SIZE         8
1272 #define TDES_EXTERN_ITER        400
1273 #define TDES_INTERN_ITER        10000
1274         struct fips_val val = {NULL, 0}, val_key;
1275         uint8_t prev_out[TDES_BLOCK_SIZE] = {0};
1276         uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0};
1277         uint8_t prev_in[TDES_BLOCK_SIZE] = {0};
1278         uint32_t i, j, k;
1279         int ret;
1280         int test_mode = info.interim_info.tdes_data.test_mode;
1281
1282         for (i = 0; i < TDES_EXTERN_ITER; i++) {
1283                 if ((i == 0) && (info.version == 21.4f)) {
1284                         if (!(strstr(info.vec[0], "COUNT")))
1285                                 fprintf(info.fp_wr, "%s%u\n", "COUNT = ", 0);
1286                 }
1287
1288                 if (i != 0)
1289                         update_info_vec(i);
1290
1291                 fips_test_write_one_case();
1292
1293                 for (j = 0; j < TDES_INTERN_ITER; j++) {
1294                         ret = fips_run_test();
1295                         if (ret < 0) {
1296                                 if (ret == -EPERM) {
1297                                         fprintf(info.fp_wr, "Bypass\n");
1298                                         return 0;
1299                                 }
1300                                 return ret;
1301                         }
1302
1303                         ret = get_writeback_data(&val);
1304                         if (ret < 0)
1305                                 return ret;
1306
1307                         if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1308                                 memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
1309
1310                         if (j == 0) {
1311                                 memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
1312
1313                                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1314                                         if (test_mode == TDES_MODE_ECB) {
1315                                                 memcpy(vec.pt.val, val.val,
1316                                                            TDES_BLOCK_SIZE);
1317                                         } else {
1318                                                 memcpy(vec.pt.val, vec.iv.val,
1319                                                            TDES_BLOCK_SIZE);
1320                                                 memcpy(vec.iv.val, val.val,
1321                                                            TDES_BLOCK_SIZE);
1322                                         }
1323
1324                                 } else {
1325                                         if (test_mode == TDES_MODE_ECB) {
1326                                                 memcpy(vec.ct.val, val.val,
1327                                                            TDES_BLOCK_SIZE);
1328                                         } else {
1329                                                 memcpy(vec.iv.val, vec.ct.val,
1330                                                            TDES_BLOCK_SIZE);
1331                                                 memcpy(vec.ct.val, val.val,
1332                                                            TDES_BLOCK_SIZE);
1333                                         }
1334                                 }
1335                                 continue;
1336                         }
1337
1338                         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1339                                 if (test_mode == TDES_MODE_ECB) {
1340                                         memcpy(vec.pt.val, val.val,
1341                                                    TDES_BLOCK_SIZE);
1342                                 } else {
1343                                         memcpy(vec.iv.val, val.val,
1344                                                    TDES_BLOCK_SIZE);
1345                                         memcpy(vec.pt.val, prev_out,
1346                                                    TDES_BLOCK_SIZE);
1347                                 }
1348                         } else {
1349                                 if (test_mode == TDES_MODE_ECB) {
1350                                         memcpy(vec.ct.val, val.val,
1351                                                    TDES_BLOCK_SIZE);
1352                                 } else {
1353                                         memcpy(vec.iv.val, vec.ct.val,
1354                                                    TDES_BLOCK_SIZE);
1355                                         memcpy(vec.ct.val, val.val,
1356                                                    TDES_BLOCK_SIZE);
1357                                 }
1358                         }
1359
1360                         if (j == TDES_INTERN_ITER - 1)
1361                                 continue;
1362
1363                         memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
1364
1365                         if (j == TDES_INTERN_ITER - 3)
1366                                 memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
1367                 }
1368
1369                 info.parse_writeback(&val);
1370                 fprintf(info.fp_wr, "\n");
1371
1372                 if (i == TDES_EXTERN_ITER - 1)
1373                         continue;
1374
1375                 /** update key */
1376                 memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1377
1378                 if (info.interim_info.tdes_data.nb_keys == 0) {
1379                         if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
1380                                 info.interim_info.tdes_data.nb_keys = 1;
1381                         else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
1382                                 info.interim_info.tdes_data.nb_keys = 2;
1383                         else
1384                                 info.interim_info.tdes_data.nb_keys = 3;
1385
1386                 }
1387
1388                 for (k = 0; k < TDES_BLOCK_SIZE; k++) {
1389
1390                         switch (info.interim_info.tdes_data.nb_keys) {
1391                         case 3:
1392                                 val_key.val[k] ^= val.val[k];
1393                                 val_key.val[k + 8] ^= prev_out[k];
1394                                 val_key.val[k + 16] ^= prev_prev_out[k];
1395                                 break;
1396                         case 2:
1397                                 val_key.val[k] ^= val.val[k];
1398                                 val_key.val[k + 8] ^= prev_out[k];
1399                                 val_key.val[k + 16] ^= val.val[k];
1400                                 break;
1401                         default: /* case 1 */
1402                                 val_key.val[k] ^= val.val[k];
1403                                 val_key.val[k + 8] ^= val.val[k];
1404                                 val_key.val[k + 16] ^= val.val[k];
1405                                 break;
1406                         }
1407
1408                 }
1409
1410                 for (k = 0; k < 24; k++)
1411                         val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
1412                                         0x1) ?
1413                                         val_key.val[k] : (val_key.val[k] ^ 0x1);
1414
1415                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1416                         if (test_mode == TDES_MODE_ECB) {
1417                                 memcpy(vec.pt.val, val.val, TDES_BLOCK_SIZE);
1418                         } else {
1419                                 memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
1420                                 memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
1421                         }
1422                 } else {
1423                         if (test_mode == TDES_MODE_ECB) {
1424                                 memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1425                         } else {
1426                                 memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
1427                                 memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1428                         }
1429                 }
1430         }
1431
1432         if (val.val)
1433                 free(val.val);
1434
1435         return 0;
1436 }
1437
1438 static int
1439 fips_mct_aes_ecb_test(void)
1440 {
1441 #define AES_BLOCK_SIZE  16
1442 #define AES_EXTERN_ITER 100
1443 #define AES_INTERN_ITER 1000
1444         struct fips_val val = {NULL, 0}, val_key;
1445         uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1446         uint32_t i, j, k;
1447         int ret;
1448
1449         for (i = 0; i < AES_EXTERN_ITER; i++) {
1450                 if (i != 0)
1451                         update_info_vec(i);
1452
1453                 fips_test_write_one_case();
1454
1455                 for (j = 0; j < AES_INTERN_ITER; j++) {
1456                         ret = fips_run_test();
1457                         if (ret < 0) {
1458                                 if (ret == -EPERM) {
1459                                         fprintf(info.fp_wr, "Bypass\n");
1460                                         return 0;
1461                                 }
1462
1463                                 return ret;
1464                         }
1465
1466                         ret = get_writeback_data(&val);
1467                         if (ret < 0)
1468                                 return ret;
1469
1470                         if (info.op == FIPS_TEST_ENC_AUTH_GEN)
1471                                 memcpy(vec.pt.val, val.val, AES_BLOCK_SIZE);
1472                         else
1473                                 memcpy(vec.ct.val, val.val, AES_BLOCK_SIZE);
1474
1475                         if (j == AES_INTERN_ITER - 1)
1476                                 continue;
1477
1478                         memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1479                 }
1480
1481                 info.parse_writeback(&val);
1482                 fprintf(info.fp_wr, "\n");
1483
1484                 if (i == AES_EXTERN_ITER - 1)
1485                         continue;
1486
1487                 /** update key */
1488                 memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1489                 for (k = 0; k < vec.cipher_auth.key.len; k++) {
1490                         switch (vec.cipher_auth.key.len) {
1491                         case 16:
1492                                 val_key.val[k] ^= val.val[k];
1493                                 break;
1494                         case 24:
1495                                 if (k < 8)
1496                                         val_key.val[k] ^= prev_out[k + 8];
1497                                 else
1498                                         val_key.val[k] ^= val.val[k - 8];
1499                                 break;
1500                         case 32:
1501                                 if (k < 16)
1502                                         val_key.val[k] ^= prev_out[k];
1503                                 else
1504                                         val_key.val[k] ^= val.val[k - 16];
1505                                 break;
1506                         default:
1507                                 return -1;
1508                         }
1509                 }
1510         }
1511
1512         if (val.val)
1513                 free(val.val);
1514
1515         return 0;
1516 }
1517 static int
1518 fips_mct_aes_test(void)
1519 {
1520 #define AES_BLOCK_SIZE  16
1521 #define AES_EXTERN_ITER 100
1522 #define AES_INTERN_ITER 1000
1523         struct fips_val val = {NULL, 0}, val_key;
1524         uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1525         uint8_t prev_in[AES_BLOCK_SIZE] = {0};
1526         uint32_t i, j, k;
1527         int ret;
1528
1529         if (info.interim_info.aes_data.cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB)
1530                 return fips_mct_aes_ecb_test();
1531
1532         for (i = 0; i < AES_EXTERN_ITER; i++) {
1533                 if (i != 0)
1534                         update_info_vec(i);
1535
1536                 fips_test_write_one_case();
1537
1538                 for (j = 0; j < AES_INTERN_ITER; j++) {
1539                         ret = fips_run_test();
1540                         if (ret < 0) {
1541                                 if (ret == -EPERM) {
1542                                         fprintf(info.fp_wr, "Bypass\n");
1543                                         return 0;
1544                                 }
1545
1546                                 return ret;
1547                         }
1548
1549                         ret = get_writeback_data(&val);
1550                         if (ret < 0)
1551                                 return ret;
1552
1553                         if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1554                                 memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
1555
1556                         if (j == 0) {
1557                                 memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1558
1559                                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1560                                         memcpy(vec.pt.val, vec.iv.val,
1561                                                         AES_BLOCK_SIZE);
1562                                         memcpy(vec.iv.val, val.val,
1563                                                         AES_BLOCK_SIZE);
1564                                 } else {
1565                                         memcpy(vec.ct.val, vec.iv.val,
1566                                                         AES_BLOCK_SIZE);
1567                                         memcpy(vec.iv.val, prev_in,
1568                                                         AES_BLOCK_SIZE);
1569                                 }
1570                                 continue;
1571                         }
1572
1573                         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1574                                 memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1575                                 memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
1576                         } else {
1577                                 memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
1578                                 memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
1579                         }
1580
1581                         if (j == AES_INTERN_ITER - 1)
1582                                 continue;
1583
1584                         memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1585                 }
1586
1587                 info.parse_writeback(&val);
1588                 fprintf(info.fp_wr, "\n");
1589
1590                 if (i == AES_EXTERN_ITER - 1)
1591                         continue;
1592
1593                 /** update key */
1594                 memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1595                 for (k = 0; k < vec.cipher_auth.key.len; k++) {
1596                         switch (vec.cipher_auth.key.len) {
1597                         case 16:
1598                                 val_key.val[k] ^= val.val[k];
1599                                 break;
1600                         case 24:
1601                                 if (k < 8)
1602                                         val_key.val[k] ^= prev_out[k + 8];
1603                                 else
1604                                         val_key.val[k] ^= val.val[k - 8];
1605                                 break;
1606                         case 32:
1607                                 if (k < 16)
1608                                         val_key.val[k] ^= prev_out[k];
1609                                 else
1610                                         val_key.val[k] ^= val.val[k - 16];
1611                                 break;
1612                         default:
1613                                 return -1;
1614                         }
1615                 }
1616
1617                 if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1618                         memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1619         }
1620
1621         if (val.val)
1622                 free(val.val);
1623
1624         return 0;
1625 }
1626
1627 static int
1628 fips_mct_sha_test(void)
1629 {
1630 #define SHA_EXTERN_ITER 100
1631 #define SHA_INTERN_ITER 1000
1632 #define SHA_MD_BLOCK    3
1633         struct fips_val val = {NULL, 0}, md[SHA_MD_BLOCK];
1634         char temp[MAX_DIGEST_SIZE*2];
1635         int ret;
1636         uint32_t i, j;
1637
1638         val.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0);
1639         for (i = 0; i < SHA_MD_BLOCK; i++)
1640                 md[i].val = rte_malloc(NULL, (MAX_DIGEST_SIZE*2), 0);
1641
1642         rte_free(vec.pt.val);
1643         vec.pt.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0);
1644
1645         fips_test_write_one_case();
1646         fprintf(info.fp_wr, "\n");
1647
1648         for (j = 0; j < SHA_EXTERN_ITER; j++) {
1649
1650                 memcpy(md[0].val, vec.cipher_auth.digest.val,
1651                         vec.cipher_auth.digest.len);
1652                 md[0].len = vec.cipher_auth.digest.len;
1653                 memcpy(md[1].val, vec.cipher_auth.digest.val,
1654                         vec.cipher_auth.digest.len);
1655                 md[1].len = vec.cipher_auth.digest.len;
1656                 memcpy(md[2].val, vec.cipher_auth.digest.val,
1657                         vec.cipher_auth.digest.len);
1658                 md[2].len = vec.cipher_auth.digest.len;
1659
1660                 for (i = 0; i < (SHA_INTERN_ITER); i++) {
1661
1662                         memcpy(vec.pt.val, md[0].val,
1663                                 (size_t)md[0].len);
1664                         memcpy((vec.pt.val + md[0].len), md[1].val,
1665                                 (size_t)md[1].len);
1666                         memcpy((vec.pt.val + md[0].len + md[1].len),
1667                                 md[2].val,
1668                                 (size_t)md[2].len);
1669                         vec.pt.len = md[0].len + md[1].len + md[2].len;
1670
1671                         ret = fips_run_test();
1672                         if (ret < 0) {
1673                                 if (ret == -EPERM || ret == -ENOTSUP) {
1674                                         fprintf(info.fp_wr, "Bypass\n\n");
1675                                         return 0;
1676                                 }
1677                                 return ret;
1678                         }
1679
1680                         ret = get_writeback_data(&val);
1681                         if (ret < 0)
1682                                 return ret;
1683
1684                         memcpy(md[0].val, md[1].val, md[1].len);
1685                         md[0].len = md[1].len;
1686                         memcpy(md[1].val, md[2].val, md[2].len);
1687                         md[1].len = md[2].len;
1688
1689                         memcpy(md[2].val, (val.val + vec.pt.len),
1690                                 vec.cipher_auth.digest.len);
1691                         md[2].len = vec.cipher_auth.digest.len;
1692                 }
1693
1694                 memcpy(vec.cipher_auth.digest.val, md[2].val, md[2].len);
1695                 vec.cipher_auth.digest.len = md[2].len;
1696
1697                 fprintf(info.fp_wr, "COUNT = %u\n", j);
1698
1699                 writeback_hex_str("", temp, &vec.cipher_auth.digest);
1700
1701                 fprintf(info.fp_wr, "MD = %s\n\n", temp);
1702         }
1703
1704         for (i = 0; i < (SHA_MD_BLOCK); i++)
1705                 rte_free(md[i].val);
1706
1707         rte_free(vec.pt.val);
1708
1709         if (val.val)
1710                 free(val.val);
1711
1712         return 0;
1713 }
1714
1715
1716 static int
1717 init_test_ops(void)
1718 {
1719         switch (info.algo) {
1720         case FIPS_TEST_ALGO_AES:
1721                 test_ops.prepare_op = prepare_cipher_op;
1722                 test_ops.prepare_xform  = prepare_aes_xform;
1723                 if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
1724                         test_ops.test = fips_mct_aes_test;
1725                 else
1726                         test_ops.test = fips_generic_test;
1727                 break;
1728         case FIPS_TEST_ALGO_HMAC:
1729                 test_ops.prepare_op = prepare_auth_op;
1730                 test_ops.prepare_xform = prepare_hmac_xform;
1731                 test_ops.test = fips_generic_test;
1732                 break;
1733         case FIPS_TEST_ALGO_TDES:
1734                 test_ops.prepare_op = prepare_cipher_op;
1735                 test_ops.prepare_xform  = prepare_tdes_xform;
1736                 if (info.interim_info.tdes_data.test_type == TDES_MCT)
1737                         test_ops.test = fips_mct_tdes_test;
1738                 else
1739                         test_ops.test = fips_generic_test;
1740                 break;
1741         case FIPS_TEST_ALGO_AES_GCM:
1742                 test_ops.prepare_op = prepare_aead_op;
1743                 test_ops.prepare_xform = prepare_gcm_xform;
1744                 test_ops.test = fips_generic_test;
1745                 break;
1746         case FIPS_TEST_ALGO_AES_CMAC:
1747                 test_ops.prepare_op = prepare_auth_op;
1748                 test_ops.prepare_xform = prepare_cmac_xform;
1749                 test_ops.test = fips_generic_test;
1750                 break;
1751         case FIPS_TEST_ALGO_AES_CCM:
1752                 test_ops.prepare_op = prepare_aead_op;
1753                 test_ops.prepare_xform = prepare_ccm_xform;
1754                 test_ops.test = fips_generic_test;
1755                 break;
1756         case FIPS_TEST_ALGO_SHA:
1757                 test_ops.prepare_op = prepare_auth_op;
1758                 test_ops.prepare_xform = prepare_sha_xform;
1759                 if (info.interim_info.sha_data.test_type == SHA_MCT)
1760                         test_ops.test = fips_mct_sha_test;
1761                 else
1762                         test_ops.test = fips_generic_test;
1763                 break;
1764         case FIPS_TEST_ALGO_AES_XTS:
1765                 test_ops.prepare_op = prepare_cipher_op;
1766                 test_ops.prepare_xform = prepare_xts_xform;
1767                 test_ops.test = fips_generic_test;
1768                 break;
1769         default:
1770                 if (strstr(info.file_name, "TECB") ||
1771                                 strstr(info.file_name, "TCBC")) {
1772                         info.algo = FIPS_TEST_ALGO_TDES;
1773                         test_ops.prepare_op = prepare_cipher_op;
1774                         test_ops.prepare_xform  = prepare_tdes_xform;
1775                         if (info.interim_info.tdes_data.test_type == TDES_MCT)
1776                                 test_ops.test = fips_mct_tdes_test;
1777                         else
1778                                 test_ops.test = fips_generic_test;
1779                         break;
1780                 }
1781                 return -1;
1782         }
1783
1784         return 0;
1785 }
1786
1787 static void
1788 print_test_block(void)
1789 {
1790         uint32_t i;
1791
1792         for (i = 0; i < info.nb_vec_lines; i++)
1793                 printf("%s\n", info.vec[i]);
1794
1795         printf("\n");
1796 }
1797
1798 static int
1799 fips_test_one_file(void)
1800 {
1801         int fetch_ret = 0, ret;
1802
1803         ret = init_test_ops();
1804         if (ret < 0) {
1805                 RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
1806                 return ret;
1807         }
1808
1809         while (ret >= 0 && fetch_ret == 0) {
1810                 fetch_ret = fips_test_fetch_one_block();
1811                 if (fetch_ret < 0) {
1812                         RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
1813                                         fetch_ret);
1814                         ret = fetch_ret;
1815                         goto error_one_case;
1816                 }
1817
1818                 if (info.nb_vec_lines == 0) {
1819                         if (fetch_ret == -EOF)
1820                                 break;
1821
1822                         fprintf(info.fp_wr, "\n");
1823                         continue;
1824                 }
1825
1826                 ret = fips_test_parse_one_case();
1827                 switch (ret) {
1828                 case 0:
1829                         ret = test_ops.test();
1830                         if (ret == 0)
1831                                 break;
1832                         RTE_LOG(ERR, USER1, "Error %i: test block\n",
1833                                         ret);
1834                         goto error_one_case;
1835                 case 1:
1836                         break;
1837                 default:
1838                         RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
1839                                         ret);
1840                         goto error_one_case;
1841                 }
1842
1843                 continue;
1844 error_one_case:
1845                 print_test_block();
1846         }
1847
1848         fips_test_clear();
1849
1850         if (env.digest)
1851                 rte_free(env.digest);
1852         if (env.mbuf)
1853                 rte_pktmbuf_free(env.mbuf);
1854
1855         return ret;
1856 }