4d778af11f624f2718c4cd22ba45711e21c71121
[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 typedef int (*fips_test_one_case_t)(void);
494 typedef int (*fips_prepare_op_t)(void);
495 typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
496
497 struct fips_test_ops {
498         fips_prepare_xform_t prepare_xform;
499         fips_prepare_op_t prepare_op;
500         fips_test_one_case_t test;
501 } test_ops;
502
503 static int
504 prepare_data_mbufs(struct fips_val *val)
505 {
506         struct rte_mbuf *m, *head = 0;
507         uint8_t *src = val->val;
508         uint32_t total_len = val->len;
509         uint16_t nb_seg;
510         int ret = 0;
511
512         if (env.mbuf)
513                 rte_pktmbuf_free(env.mbuf);
514
515         if (total_len > RTE_MBUF_MAX_NB_SEGS) {
516                 RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
517                 return -EPERM;
518         }
519
520         nb_seg = total_len / env.mbuf_data_room;
521         if (total_len % env.mbuf_data_room)
522                 nb_seg++;
523
524         m = rte_pktmbuf_alloc(env.mpool);
525         if (!m) {
526                 RTE_LOG(ERR, USER1, "Error %i: Not enough mbuf\n",
527                                 -ENOMEM);
528                 return -ENOMEM;
529         }
530         head = m;
531
532         while (nb_seg) {
533                 uint16_t len = RTE_MIN(total_len, env.mbuf_data_room);
534                 uint8_t *dst = (uint8_t *)rte_pktmbuf_append(m, len);
535
536                 if (!dst) {
537                         RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
538                                         -ENOMEM);
539                         ret = -ENOMEM;
540                         goto error_exit;
541                 }
542
543                 memcpy(dst, src, len);
544
545                 if (head != m) {
546                         ret = rte_pktmbuf_chain(head, m);
547                         if (ret) {
548                                 rte_pktmbuf_free(m);
549                                 RTE_LOG(ERR, USER1, "Error %i: SGL build\n",
550                                                 ret);
551                                 goto error_exit;
552                         }
553                 }
554                 total_len -= len;
555
556                 if (total_len) {
557                         if (!env.dev_support_sgl) {
558                                 RTE_LOG(ERR, USER1, "SGL not supported\n");
559                                 ret = -EPERM;
560                                 goto error_exit;
561                         }
562
563                         m = rte_pktmbuf_alloc(env.mpool);
564                         if (!m) {
565                                 RTE_LOG(ERR, USER1, "Error %i: No memory\n",
566                                                 -ENOMEM);
567                                 goto error_exit;
568                         }
569                 } else
570                         break;
571
572                 src += len;
573                 nb_seg--;
574         }
575
576         if (total_len) {
577                 RTE_LOG(ERR, USER1, "Error %i: Failed to store all data\n",
578                                 -ENOMEM);
579                 goto error_exit;
580         }
581
582         env.mbuf = head;
583
584         return 0;
585
586 error_exit:
587         if (head)
588                 rte_pktmbuf_free(head);
589         return ret;
590 }
591
592 static int
593 prepare_cipher_op(void)
594 {
595         struct rte_crypto_sym_op *sym = env.op->sym;
596         uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
597         int ret;
598
599         __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
600
601         memcpy(iv, vec.iv.val, vec.iv.len);
602
603         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
604                 ret = prepare_data_mbufs(&vec.pt);
605                 if (ret < 0)
606                         return ret;
607
608                 sym->cipher.data.length = vec.pt.len;
609         } else {
610                 ret = prepare_data_mbufs(&vec.ct);
611                 if (ret < 0)
612                         return ret;
613
614                 sym->cipher.data.length = vec.ct.len;
615         }
616
617         rte_crypto_op_attach_sym_session(env.op, env.sess);
618
619         sym->m_src = env.mbuf;
620         sym->cipher.data.offset = 0;
621
622         return 0;
623 }
624
625 static int
626 prepare_auth_op(void)
627 {
628         struct rte_crypto_sym_op *sym = env.op->sym;
629         int ret;
630
631         __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
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 static 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 static 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 static int
900 prepare_cmac_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_CMAC;
909         auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
910                         RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
911         auth_xform->digest_length = vec.cipher_auth.digest.len;
912         auth_xform->key.data = vec.cipher_auth.key.val;
913         auth_xform->key.length = vec.cipher_auth.key.len;
914
915         cap_idx.algo.auth = auth_xform->algo;
916         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
917
918         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
919         if (!cap) {
920                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
921                                 env.dev_id);
922                 return -EINVAL;
923         }
924
925         if (rte_cryptodev_sym_capability_check_auth(cap,
926                         auth_xform->key.length,
927                         auth_xform->digest_length, 0) != 0) {
928                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
929                                 info.device_name, auth_xform->key.length,
930                                 auth_xform->digest_length);
931                 return -EPERM;
932         }
933
934         return 0;
935 }
936
937 static int
938 prepare_ccm_xform(struct rte_crypto_sym_xform *xform)
939 {
940         const struct rte_cryptodev_symmetric_capability *cap;
941         struct rte_cryptodev_sym_capability_idx cap_idx;
942         struct rte_crypto_aead_xform *aead_xform = &xform->aead;
943
944         xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
945
946         aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
947         aead_xform->aad_length = vec.aead.aad.len;
948         aead_xform->digest_length = vec.aead.digest.len;
949         aead_xform->iv.offset = IV_OFF;
950         aead_xform->iv.length = vec.iv.len;
951         aead_xform->key.data = vec.aead.key.val;
952         aead_xform->key.length = vec.aead.key.len;
953         aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
954                         RTE_CRYPTO_AEAD_OP_ENCRYPT :
955                         RTE_CRYPTO_AEAD_OP_DECRYPT;
956
957         cap_idx.algo.aead = aead_xform->algo;
958         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
959
960         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
961         if (!cap) {
962                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
963                                 env.dev_id);
964                 return -EINVAL;
965         }
966
967         if (rte_cryptodev_sym_capability_check_aead(cap,
968                         aead_xform->key.length,
969                         aead_xform->digest_length, aead_xform->aad_length,
970                         aead_xform->iv.length) != 0) {
971                 RTE_LOG(ERR, USER1,
972                         "PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
973                                 info.device_name, aead_xform->key.length,
974                                 aead_xform->digest_length,
975                                 aead_xform->aad_length,
976                                 aead_xform->iv.length);
977                 return -EPERM;
978         }
979
980         return 0;
981 }
982
983 static int
984 prepare_sha_xform(struct rte_crypto_sym_xform *xform)
985 {
986         const struct rte_cryptodev_symmetric_capability *cap;
987         struct rte_cryptodev_sym_capability_idx cap_idx;
988         struct rte_crypto_auth_xform *auth_xform = &xform->auth;
989
990         xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
991
992         auth_xform->algo = info.interim_info.sha_data.algo;
993         auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
994         auth_xform->digest_length = vec.cipher_auth.digest.len;
995
996         cap_idx.algo.auth = auth_xform->algo;
997         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
998
999         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1000         if (!cap) {
1001                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1002                                 env.dev_id);
1003                 return -EINVAL;
1004         }
1005
1006         if (rte_cryptodev_sym_capability_check_auth(cap,
1007                         auth_xform->key.length,
1008                         auth_xform->digest_length, 0) != 0) {
1009                 RTE_LOG(ERR, USER1, "PMD %s key length %u digest length %u\n",
1010                                 info.device_name, auth_xform->key.length,
1011                                 auth_xform->digest_length);
1012                 return -EPERM;
1013         }
1014
1015         return 0;
1016 }
1017
1018 static int
1019 prepare_xts_xform(struct rte_crypto_sym_xform *xform)
1020 {
1021         const struct rte_cryptodev_symmetric_capability *cap;
1022         struct rte_cryptodev_sym_capability_idx cap_idx;
1023         struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
1024
1025         xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1026
1027         cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_XTS;
1028         cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
1029                         RTE_CRYPTO_CIPHER_OP_ENCRYPT :
1030                         RTE_CRYPTO_CIPHER_OP_DECRYPT;
1031         cipher_xform->key.data = vec.cipher_auth.key.val;
1032         cipher_xform->key.length = vec.cipher_auth.key.len;
1033         cipher_xform->iv.length = vec.iv.len;
1034         cipher_xform->iv.offset = IV_OFF;
1035
1036         cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_XTS;
1037         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1038
1039         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
1040         if (!cap) {
1041                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
1042                                 env.dev_id);
1043                 return -EINVAL;
1044         }
1045
1046         if (rte_cryptodev_sym_capability_check_cipher(cap,
1047                         cipher_xform->key.length,
1048                         cipher_xform->iv.length) != 0) {
1049                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
1050                                 info.device_name, cipher_xform->key.length,
1051                                 cipher_xform->iv.length);
1052                 return -EPERM;
1053         }
1054
1055         return 0;
1056 }
1057
1058 static int
1059 get_writeback_data(struct fips_val *val)
1060 {
1061         struct rte_mbuf *m = env.mbuf;
1062         uint16_t data_len = rte_pktmbuf_pkt_len(m);
1063         uint16_t total_len = data_len + env.digest_len;
1064         uint8_t *src, *dst, *wb_data;
1065
1066         /* in case val is reused for MCT test, try to free the buffer first */
1067         if (val->val) {
1068                 free(val->val);
1069                 val->val = NULL;
1070         }
1071
1072         wb_data = dst = calloc(1, total_len);
1073         if (!dst) {
1074                 RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
1075                 return -ENOMEM;
1076         }
1077
1078         while (m && data_len) {
1079                 uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
1080
1081                 src = rte_pktmbuf_mtod(m, uint8_t *);
1082                 memcpy(dst, src, seg_len);
1083                 m = m->next;
1084                 data_len -= seg_len;
1085                 dst += seg_len;
1086         }
1087
1088         if (data_len) {
1089                 RTE_LOG(ERR, USER1, "Error -1: write back data\n");
1090                 return -1;
1091         }
1092
1093         if (env.digest)
1094                 memcpy(dst, env.digest, env.digest_len);
1095
1096         val->val = wb_data;
1097         val->len = total_len;
1098
1099         return 0;
1100 }
1101
1102 static int
1103 fips_run_test(void)
1104 {
1105         struct rte_crypto_sym_xform xform = {0};
1106         uint16_t n_deqd;
1107         int ret;
1108
1109         ret = test_ops.prepare_xform(&xform);
1110         if (ret < 0)
1111                 return ret;
1112
1113         env.sess = rte_cryptodev_sym_session_create(env.sess_mpool);
1114         if (!env.sess)
1115                 return -ENOMEM;
1116
1117         ret = rte_cryptodev_sym_session_init(env.dev_id,
1118                         env.sess, &xform, env.sess_priv_mpool);
1119         if (ret < 0) {
1120                 RTE_LOG(ERR, USER1, "Error %i: Init session\n",
1121                                 ret);
1122                 goto exit;
1123         }
1124
1125         ret = test_ops.prepare_op();
1126         if (ret < 0) {
1127                 RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
1128                                 ret);
1129                 goto exit;
1130         }
1131
1132         if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
1133                 RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
1134                 ret = -1;
1135                 goto exit;
1136         }
1137
1138         do {
1139                 struct rte_crypto_op *deqd_op;
1140
1141                 n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
1142                                 1);
1143         } while (n_deqd == 0);
1144
1145         vec.status = env.op->status;
1146
1147 exit:
1148         rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
1149         rte_cryptodev_sym_session_free(env.sess);
1150         env.sess = NULL;
1151
1152         return ret;
1153 }
1154
1155 static int
1156 fips_generic_test(void)
1157 {
1158         struct fips_val val = {NULL, 0};
1159         int ret;
1160
1161         fips_test_write_one_case();
1162
1163         ret = fips_run_test();
1164         if (ret < 0) {
1165                 if (ret == -EPERM || ret == -ENOTSUP) {
1166                         fprintf(info.fp_wr, "Bypass\n\n");
1167                         return 0;
1168                 }
1169
1170                 return ret;
1171         }
1172
1173         ret = get_writeback_data(&val);
1174         if (ret < 0)
1175                 return ret;
1176
1177         switch (info.file_type) {
1178         case FIPS_TYPE_REQ:
1179         case FIPS_TYPE_RSP:
1180                 if (info.parse_writeback == NULL)
1181                         return -EPERM;
1182                 ret = info.parse_writeback(&val);
1183                 if (ret < 0)
1184                         return ret;
1185                 break;
1186         case FIPS_TYPE_FAX:
1187                 if (info.kat_check == NULL)
1188                         return -EPERM;
1189                 ret = info.kat_check(&val);
1190                 if (ret < 0)
1191                         return ret;
1192                 break;
1193         }
1194
1195         fprintf(info.fp_wr, "\n");
1196         free(val.val);
1197
1198         return 0;
1199 }
1200
1201 static int
1202 fips_mct_tdes_test(void)
1203 {
1204 #define TDES_BLOCK_SIZE         8
1205 #define TDES_EXTERN_ITER        400
1206 #define TDES_INTERN_ITER        10000
1207         struct fips_val val = {NULL, 0}, val_key;
1208         uint8_t prev_out[TDES_BLOCK_SIZE] = {0};
1209         uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0};
1210         uint8_t prev_in[TDES_BLOCK_SIZE] = {0};
1211         uint32_t i, j, k;
1212         int ret;
1213         int test_mode = info.interim_info.tdes_data.test_mode;
1214
1215         for (i = 0; i < TDES_EXTERN_ITER; i++) {
1216                 if ((i == 0) && (info.version == 21.4f)) {
1217                         if (!(strstr(info.vec[0], "COUNT")))
1218                                 fprintf(info.fp_wr, "%s%u\n", "COUNT = ", 0);
1219                 }
1220
1221                 if (i != 0)
1222                         update_info_vec(i);
1223
1224                 fips_test_write_one_case();
1225
1226                 for (j = 0; j < TDES_INTERN_ITER; j++) {
1227                         ret = fips_run_test();
1228                         if (ret < 0) {
1229                                 if (ret == -EPERM) {
1230                                         fprintf(info.fp_wr, "Bypass\n");
1231                                         return 0;
1232                                 }
1233                                 return ret;
1234                         }
1235
1236                         ret = get_writeback_data(&val);
1237                         if (ret < 0)
1238                                 return ret;
1239
1240                         if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1241                                 memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
1242
1243                         if (j == 0) {
1244                                 memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
1245
1246                                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1247                                         if (test_mode == TDES_MODE_ECB) {
1248                                                 memcpy(vec.pt.val, val.val,
1249                                                            TDES_BLOCK_SIZE);
1250                                         } else {
1251                                                 memcpy(vec.pt.val, vec.iv.val,
1252                                                            TDES_BLOCK_SIZE);
1253                                                 memcpy(vec.iv.val, val.val,
1254                                                            TDES_BLOCK_SIZE);
1255                                         }
1256
1257                                 } else {
1258                                         if (test_mode == TDES_MODE_ECB) {
1259                                                 memcpy(vec.ct.val, val.val,
1260                                                            TDES_BLOCK_SIZE);
1261                                         } else {
1262                                                 memcpy(vec.iv.val, vec.ct.val,
1263                                                            TDES_BLOCK_SIZE);
1264                                                 memcpy(vec.ct.val, val.val,
1265                                                            TDES_BLOCK_SIZE);
1266                                         }
1267                                 }
1268                                 continue;
1269                         }
1270
1271                         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1272                                 if (test_mode == TDES_MODE_ECB) {
1273                                         memcpy(vec.pt.val, val.val,
1274                                                    TDES_BLOCK_SIZE);
1275                                 } else {
1276                                         memcpy(vec.iv.val, val.val,
1277                                                    TDES_BLOCK_SIZE);
1278                                         memcpy(vec.pt.val, prev_out,
1279                                                    TDES_BLOCK_SIZE);
1280                                 }
1281                         } else {
1282                                 if (test_mode == TDES_MODE_ECB) {
1283                                         memcpy(vec.ct.val, val.val,
1284                                                    TDES_BLOCK_SIZE);
1285                                 } else {
1286                                         memcpy(vec.iv.val, vec.ct.val,
1287                                                    TDES_BLOCK_SIZE);
1288                                         memcpy(vec.ct.val, val.val,
1289                                                    TDES_BLOCK_SIZE);
1290                                 }
1291                         }
1292
1293                         if (j == TDES_INTERN_ITER - 1)
1294                                 continue;
1295
1296                         memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
1297
1298                         if (j == TDES_INTERN_ITER - 3)
1299                                 memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
1300                 }
1301
1302                 info.parse_writeback(&val);
1303                 fprintf(info.fp_wr, "\n");
1304
1305                 if (i == TDES_EXTERN_ITER - 1)
1306                         continue;
1307
1308                 /** update key */
1309                 memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1310
1311                 if (info.interim_info.tdes_data.nb_keys == 0) {
1312                         if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
1313                                 info.interim_info.tdes_data.nb_keys = 1;
1314                         else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
1315                                 info.interim_info.tdes_data.nb_keys = 2;
1316                         else
1317                                 info.interim_info.tdes_data.nb_keys = 3;
1318
1319                 }
1320
1321                 for (k = 0; k < TDES_BLOCK_SIZE; k++) {
1322
1323                         switch (info.interim_info.tdes_data.nb_keys) {
1324                         case 3:
1325                                 val_key.val[k] ^= val.val[k];
1326                                 val_key.val[k + 8] ^= prev_out[k];
1327                                 val_key.val[k + 16] ^= prev_prev_out[k];
1328                                 break;
1329                         case 2:
1330                                 val_key.val[k] ^= val.val[k];
1331                                 val_key.val[k + 8] ^= prev_out[k];
1332                                 val_key.val[k + 16] ^= val.val[k];
1333                                 break;
1334                         default: /* case 1 */
1335                                 val_key.val[k] ^= val.val[k];
1336                                 val_key.val[k + 8] ^= val.val[k];
1337                                 val_key.val[k + 16] ^= val.val[k];
1338                                 break;
1339                         }
1340
1341                 }
1342
1343                 for (k = 0; k < 24; k++)
1344                         val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
1345                                         0x1) ?
1346                                         val_key.val[k] : (val_key.val[k] ^ 0x1);
1347
1348                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1349                         if (test_mode == TDES_MODE_ECB) {
1350                                 memcpy(vec.pt.val, val.val, TDES_BLOCK_SIZE);
1351                         } else {
1352                                 memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
1353                                 memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
1354                         }
1355                 } else {
1356                         if (test_mode == TDES_MODE_ECB) {
1357                                 memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1358                         } else {
1359                                 memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
1360                                 memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
1361                         }
1362                 }
1363         }
1364
1365         if (val.val)
1366                 free(val.val);
1367
1368         return 0;
1369 }
1370
1371 static int
1372 fips_mct_aes_ecb_test(void)
1373 {
1374 #define AES_BLOCK_SIZE  16
1375 #define AES_EXTERN_ITER 100
1376 #define AES_INTERN_ITER 1000
1377         struct fips_val val = {NULL, 0}, val_key;
1378         uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1379         uint32_t i, j, k;
1380         int ret;
1381
1382         for (i = 0; i < AES_EXTERN_ITER; i++) {
1383                 if (i != 0)
1384                         update_info_vec(i);
1385
1386                 fips_test_write_one_case();
1387
1388                 for (j = 0; j < AES_INTERN_ITER; j++) {
1389                         ret = fips_run_test();
1390                         if (ret < 0) {
1391                                 if (ret == -EPERM) {
1392                                         fprintf(info.fp_wr, "Bypass\n");
1393                                         return 0;
1394                                 }
1395
1396                                 return ret;
1397                         }
1398
1399                         ret = get_writeback_data(&val);
1400                         if (ret < 0)
1401                                 return ret;
1402
1403                         if (info.op == FIPS_TEST_ENC_AUTH_GEN)
1404                                 memcpy(vec.pt.val, val.val, AES_BLOCK_SIZE);
1405                         else
1406                                 memcpy(vec.ct.val, val.val, AES_BLOCK_SIZE);
1407
1408                         if (j == AES_INTERN_ITER - 1)
1409                                 continue;
1410
1411                         memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1412                 }
1413
1414                 info.parse_writeback(&val);
1415                 fprintf(info.fp_wr, "\n");
1416
1417                 if (i == AES_EXTERN_ITER - 1)
1418                         continue;
1419
1420                 /** update key */
1421                 memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1422                 for (k = 0; k < vec.cipher_auth.key.len; k++) {
1423                         switch (vec.cipher_auth.key.len) {
1424                         case 16:
1425                                 val_key.val[k] ^= val.val[k];
1426                                 break;
1427                         case 24:
1428                                 if (k < 8)
1429                                         val_key.val[k] ^= prev_out[k + 8];
1430                                 else
1431                                         val_key.val[k] ^= val.val[k - 8];
1432                                 break;
1433                         case 32:
1434                                 if (k < 16)
1435                                         val_key.val[k] ^= prev_out[k];
1436                                 else
1437                                         val_key.val[k] ^= val.val[k - 16];
1438                                 break;
1439                         default:
1440                                 return -1;
1441                         }
1442                 }
1443         }
1444
1445         if (val.val)
1446                 free(val.val);
1447
1448         return 0;
1449 }
1450 static int
1451 fips_mct_aes_test(void)
1452 {
1453 #define AES_BLOCK_SIZE  16
1454 #define AES_EXTERN_ITER 100
1455 #define AES_INTERN_ITER 1000
1456         struct fips_val val = {NULL, 0}, val_key;
1457         uint8_t prev_out[AES_BLOCK_SIZE] = {0};
1458         uint8_t prev_in[AES_BLOCK_SIZE] = {0};
1459         uint32_t i, j, k;
1460         int ret;
1461
1462         if (info.interim_info.aes_data.cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB)
1463                 return fips_mct_aes_ecb_test();
1464
1465         for (i = 0; i < AES_EXTERN_ITER; i++) {
1466                 if (i != 0)
1467                         update_info_vec(i);
1468
1469                 fips_test_write_one_case();
1470
1471                 for (j = 0; j < AES_INTERN_ITER; j++) {
1472                         ret = fips_run_test();
1473                         if (ret < 0) {
1474                                 if (ret == -EPERM) {
1475                                         fprintf(info.fp_wr, "Bypass\n");
1476                                         return 0;
1477                                 }
1478
1479                                 return ret;
1480                         }
1481
1482                         get_writeback_data(&val);
1483
1484                         if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1485                                 memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
1486
1487                         if (j == 0) {
1488                                 memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1489
1490                                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1491                                         memcpy(vec.pt.val, vec.iv.val,
1492                                                         AES_BLOCK_SIZE);
1493                                         memcpy(vec.iv.val, val.val,
1494                                                         AES_BLOCK_SIZE);
1495                                 } else {
1496                                         memcpy(vec.ct.val, vec.iv.val,
1497                                                         AES_BLOCK_SIZE);
1498                                         memcpy(vec.iv.val, prev_in,
1499                                                         AES_BLOCK_SIZE);
1500                                 }
1501                                 continue;
1502                         }
1503
1504                         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
1505                                 memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1506                                 memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
1507                         } else {
1508                                 memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
1509                                 memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
1510                         }
1511
1512                         if (j == AES_INTERN_ITER - 1)
1513                                 continue;
1514
1515                         memcpy(prev_out, val.val, AES_BLOCK_SIZE);
1516                 }
1517
1518                 info.parse_writeback(&val);
1519                 fprintf(info.fp_wr, "\n");
1520
1521                 if (i == AES_EXTERN_ITER - 1)
1522                         continue;
1523
1524                 /** update key */
1525                 memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
1526                 for (k = 0; k < vec.cipher_auth.key.len; k++) {
1527                         switch (vec.cipher_auth.key.len) {
1528                         case 16:
1529                                 val_key.val[k] ^= val.val[k];
1530                                 break;
1531                         case 24:
1532                                 if (k < 8)
1533                                         val_key.val[k] ^= prev_out[k + 8];
1534                                 else
1535                                         val_key.val[k] ^= val.val[k - 8];
1536                                 break;
1537                         case 32:
1538                                 if (k < 16)
1539                                         val_key.val[k] ^= prev_out[k];
1540                                 else
1541                                         val_key.val[k] ^= val.val[k - 16];
1542                                 break;
1543                         default:
1544                                 return -1;
1545                         }
1546                 }
1547
1548                 if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1549                         memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1550         }
1551
1552         if (val.val)
1553                 free(val.val);
1554
1555         return 0;
1556 }
1557
1558 static int
1559 fips_mct_sha_test(void)
1560 {
1561 #define SHA_EXTERN_ITER 100
1562 #define SHA_INTERN_ITER 1000
1563 #define SHA_MD_BLOCK    3
1564         struct fips_val val = {NULL, 0}, md[SHA_MD_BLOCK];
1565         char temp[MAX_DIGEST_SIZE*2];
1566         int ret;
1567         uint32_t i, j;
1568
1569         val.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0);
1570         for (i = 0; i < SHA_MD_BLOCK; i++)
1571                 md[i].val = rte_malloc(NULL, (MAX_DIGEST_SIZE*2), 0);
1572
1573         rte_free(vec.pt.val);
1574         vec.pt.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0);
1575
1576         fips_test_write_one_case();
1577         fprintf(info.fp_wr, "\n");
1578
1579         for (j = 0; j < SHA_EXTERN_ITER; j++) {
1580
1581                 memcpy(md[0].val, vec.cipher_auth.digest.val,
1582                         vec.cipher_auth.digest.len);
1583                 md[0].len = vec.cipher_auth.digest.len;
1584                 memcpy(md[1].val, vec.cipher_auth.digest.val,
1585                         vec.cipher_auth.digest.len);
1586                 md[1].len = vec.cipher_auth.digest.len;
1587                 memcpy(md[2].val, vec.cipher_auth.digest.val,
1588                         vec.cipher_auth.digest.len);
1589                 md[2].len = vec.cipher_auth.digest.len;
1590
1591                 for (i = 0; i < (SHA_INTERN_ITER); i++) {
1592
1593                         memcpy(vec.pt.val, md[0].val,
1594                                 (size_t)md[0].len);
1595                         memcpy((vec.pt.val + md[0].len), md[1].val,
1596                                 (size_t)md[1].len);
1597                         memcpy((vec.pt.val + md[0].len + md[1].len),
1598                                 md[2].val,
1599                                 (size_t)md[2].len);
1600                         vec.pt.len = md[0].len + md[1].len + md[2].len;
1601
1602                         ret = fips_run_test();
1603                         if (ret < 0) {
1604                                 if (ret == -EPERM || ret == -ENOTSUP) {
1605                                         fprintf(info.fp_wr, "Bypass\n\n");
1606                                         return 0;
1607                                 }
1608                                 return ret;
1609                         }
1610
1611                         get_writeback_data(&val);
1612
1613                         memcpy(md[0].val, md[1].val, md[1].len);
1614                         md[0].len = md[1].len;
1615                         memcpy(md[1].val, md[2].val, md[2].len);
1616                         md[1].len = md[2].len;
1617
1618                         memcpy(md[2].val, (val.val + vec.pt.len),
1619                                 vec.cipher_auth.digest.len);
1620                         md[2].len = vec.cipher_auth.digest.len;
1621                 }
1622
1623                 memcpy(vec.cipher_auth.digest.val, md[2].val, md[2].len);
1624                 vec.cipher_auth.digest.len = md[2].len;
1625
1626                 fprintf(info.fp_wr, "COUNT = %u\n", j);
1627
1628                 writeback_hex_str("", temp, &vec.cipher_auth.digest);
1629
1630                 fprintf(info.fp_wr, "MD = %s\n\n", temp);
1631         }
1632
1633         for (i = 0; i < (SHA_MD_BLOCK); i++)
1634                 rte_free(md[i].val);
1635
1636         rte_free(vec.pt.val);
1637
1638         if (val.val)
1639                 free(val.val);
1640
1641         return 0;
1642 }
1643
1644
1645 static int
1646 init_test_ops(void)
1647 {
1648         switch (info.algo) {
1649         case FIPS_TEST_ALGO_AES:
1650                 test_ops.prepare_op = prepare_cipher_op;
1651                 test_ops.prepare_xform  = prepare_aes_xform;
1652                 if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
1653                         test_ops.test = fips_mct_aes_test;
1654                 else
1655                         test_ops.test = fips_generic_test;
1656                 break;
1657         case FIPS_TEST_ALGO_HMAC:
1658                 test_ops.prepare_op = prepare_auth_op;
1659                 test_ops.prepare_xform = prepare_hmac_xform;
1660                 test_ops.test = fips_generic_test;
1661                 break;
1662         case FIPS_TEST_ALGO_TDES:
1663                 test_ops.prepare_op = prepare_cipher_op;
1664                 test_ops.prepare_xform  = prepare_tdes_xform;
1665                 if (info.interim_info.tdes_data.test_type == TDES_MCT)
1666                         test_ops.test = fips_mct_tdes_test;
1667                 else
1668                         test_ops.test = fips_generic_test;
1669                 break;
1670         case FIPS_TEST_ALGO_AES_GCM:
1671                 test_ops.prepare_op = prepare_aead_op;
1672                 test_ops.prepare_xform = prepare_gcm_xform;
1673                 test_ops.test = fips_generic_test;
1674                 break;
1675         case FIPS_TEST_ALGO_AES_CMAC:
1676                 test_ops.prepare_op = prepare_auth_op;
1677                 test_ops.prepare_xform = prepare_cmac_xform;
1678                 test_ops.test = fips_generic_test;
1679                 break;
1680         case FIPS_TEST_ALGO_AES_CCM:
1681                 test_ops.prepare_op = prepare_aead_op;
1682                 test_ops.prepare_xform = prepare_ccm_xform;
1683                 test_ops.test = fips_generic_test;
1684                 break;
1685         case FIPS_TEST_ALGO_SHA:
1686                 test_ops.prepare_op = prepare_auth_op;
1687                 test_ops.prepare_xform = prepare_sha_xform;
1688                 if (info.interim_info.sha_data.test_type == SHA_MCT)
1689                         test_ops.test = fips_mct_sha_test;
1690                 else
1691                         test_ops.test = fips_generic_test;
1692                 break;
1693         case FIPS_TEST_ALGO_AES_XTS:
1694                 test_ops.prepare_op = prepare_cipher_op;
1695                 test_ops.prepare_xform = prepare_xts_xform;
1696                 test_ops.test = fips_generic_test;
1697                 break;
1698         default:
1699                 if (strstr(info.file_name, "TECB") ||
1700                                 strstr(info.file_name, "TCBC")) {
1701                         info.algo = FIPS_TEST_ALGO_TDES;
1702                         test_ops.prepare_op = prepare_cipher_op;
1703                         test_ops.prepare_xform  = prepare_tdes_xform;
1704                         if (info.interim_info.tdes_data.test_type == TDES_MCT)
1705                                 test_ops.test = fips_mct_tdes_test;
1706                         else
1707                                 test_ops.test = fips_generic_test;
1708                         break;
1709                 }
1710                 return -1;
1711         }
1712
1713         return 0;
1714 }
1715
1716 static void
1717 print_test_block(void)
1718 {
1719         uint32_t i;
1720
1721         for (i = 0; i < info.nb_vec_lines; i++)
1722                 printf("%s\n", info.vec[i]);
1723
1724         printf("\n");
1725 }
1726
1727 static int
1728 fips_test_one_file(void)
1729 {
1730         int fetch_ret = 0, ret;
1731
1732         ret = init_test_ops();
1733         if (ret < 0) {
1734                 RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
1735                 return ret;
1736         }
1737
1738         while (ret >= 0 && fetch_ret == 0) {
1739                 fetch_ret = fips_test_fetch_one_block();
1740                 if (fetch_ret < 0) {
1741                         RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
1742                                         fetch_ret);
1743                         ret = fetch_ret;
1744                         goto error_one_case;
1745                 }
1746
1747                 if (info.nb_vec_lines == 0) {
1748                         if (fetch_ret == -EOF)
1749                                 break;
1750
1751                         fprintf(info.fp_wr, "\n");
1752                         continue;
1753                 }
1754
1755                 ret = fips_test_parse_one_case();
1756                 switch (ret) {
1757                 case 0:
1758                         ret = test_ops.test();
1759                         if (ret == 0)
1760                                 break;
1761                         RTE_LOG(ERR, USER1, "Error %i: test block\n",
1762                                         ret);
1763                         goto error_one_case;
1764                 case 1:
1765                         break;
1766                 default:
1767                         RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
1768                                         ret);
1769                         goto error_one_case;
1770                 }
1771
1772                 continue;
1773 error_one_case:
1774                 print_test_block();
1775         }
1776
1777         fips_test_clear();
1778
1779         if (env.digest)
1780                 rte_free(env.digest);
1781         if (env.mbuf)
1782                 rte_pktmbuf_free(env.mbuf);
1783
1784         return ret;
1785 }