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