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