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