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