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