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