examples/fips_validation: support GCM parsing
[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
17 #define REQ_FILE_PATH_KEYWORD   "req-file"
18 #define RSP_FILE_PATH_KEYWORD   "rsp-file"
19 #define FOLDER_KEYWORD          "path-is-folder"
20 #define CRYPTODEV_KEYWORD       "cryptodev"
21 #define CRYPTODEV_ID_KEYWORD    "cryptodev-id"
22
23 struct fips_test_vector vec;
24 struct fips_test_interim_info info;
25
26 struct cryptodev_fips_validate_env {
27         const char *req_path;
28         const char *rsp_path;
29         uint32_t is_path_folder;
30         uint32_t dev_id;
31         struct rte_mempool *mpool;
32         struct rte_mempool *op_pool;
33         struct rte_mbuf *mbuf;
34         struct rte_crypto_op *op;
35         struct rte_cryptodev_sym_session *sess;
36 } env;
37
38 static int
39 cryptodev_fips_validate_app_int(void)
40 {
41         struct rte_cryptodev_config conf = {rte_socket_id(), 1};
42         struct rte_cryptodev_qp_conf qp_conf = {128};
43         int ret;
44
45         ret = rte_cryptodev_configure(env.dev_id, &conf);
46         if (ret < 0)
47                 return ret;
48
49         env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
50                         UINT16_MAX, rte_socket_id());
51         if (!env.mpool)
52                 return ret;
53
54         ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
55                         rte_socket_id(), env.mpool);
56         if (ret < 0)
57                 return ret;
58
59         ret = -ENOMEM;
60
61         env.op_pool = rte_crypto_op_pool_create(
62                         "FIPS_OP_POOL",
63                         RTE_CRYPTO_OP_TYPE_SYMMETRIC,
64                         1, 0,
65                         16,
66                         rte_socket_id());
67         if (!env.op_pool)
68                 goto error_exit;
69
70         env.mbuf = rte_pktmbuf_alloc(env.mpool);
71         if (!env.mbuf)
72                 goto error_exit;
73
74         env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
75         if (!env.op)
76                 goto error_exit;
77
78         return 0;
79
80 error_exit:
81         rte_mempool_free(env.mpool);
82         if (env.op_pool)
83                 rte_mempool_free(env.op_pool);
84
85         return ret;
86 }
87
88 static void
89 cryptodev_fips_validate_app_uninit(void)
90 {
91         rte_pktmbuf_free(env.mbuf);
92         rte_crypto_op_free(env.op);
93         rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
94         rte_cryptodev_sym_session_free(env.sess);
95         rte_mempool_free(env.mpool);
96         rte_mempool_free(env.op_pool);
97 }
98
99 static int
100 fips_test_one_file(void);
101
102 static int
103 parse_cryptodev_arg(char *arg)
104 {
105         int id = rte_cryptodev_get_dev_id(arg);
106
107         if (id < 0) {
108                 RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
109                                 id, arg);
110                 return id;
111         }
112
113         env.dev_id = (uint32_t)id;
114
115         return 0;
116 }
117
118 static int
119 parse_cryptodev_id_arg(char *arg)
120 {
121         uint32_t cryptodev_id;
122
123         if (parser_read_uint32(&cryptodev_id, arg) < 0) {
124                 RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
125                                 -EINVAL, arg);
126                 return -1;
127         }
128
129
130         if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
131                 RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
132                                 cryptodev_id, arg);
133                 return -1;
134         }
135
136         env.dev_id = (uint32_t)cryptodev_id;
137
138         return 0;
139 }
140
141 static void
142 cryptodev_fips_validate_usage(const char *prgname)
143 {
144         printf("%s [EAL options] --\n"
145                 "  --%s: REQUEST-FILE-PATH\n"
146                 "  --%s: RESPONSE-FILE-PATH\n"
147                 "  --%s: indicating both paths are folders\n"
148                 "  --%s: CRYPTODEV-NAME\n"
149                 "  --%s: CRYPTODEV-ID-NAME\n",
150                 prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
151                 FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD);
152 }
153
154 static int
155 cryptodev_fips_validate_parse_args(int argc, char **argv)
156 {
157         int opt, ret;
158         char *prgname = argv[0];
159         char **argvopt;
160         int option_index;
161         struct option lgopts[] = {
162                         {REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
163                         {RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
164                         {FOLDER_KEYWORD, no_argument, 0, 0},
165                         {CRYPTODEV_KEYWORD, required_argument, 0, 0},
166                         {CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
167                         {NULL, 0, 0, 0}
168         };
169
170         argvopt = argv;
171
172         while ((opt = getopt_long(argc, argvopt, "s:",
173                                   lgopts, &option_index)) != EOF) {
174
175                 switch (opt) {
176                 case 0:
177                         if (strcmp(lgopts[option_index].name,
178                                         REQ_FILE_PATH_KEYWORD) == 0)
179                                 env.req_path = optarg;
180                         else if (strcmp(lgopts[option_index].name,
181                                         RSP_FILE_PATH_KEYWORD) == 0)
182                                 env.rsp_path = optarg;
183                         else if (strcmp(lgopts[option_index].name,
184                                         FOLDER_KEYWORD) == 0)
185                                 env.is_path_folder = 1;
186                         else if (strcmp(lgopts[option_index].name,
187                                         CRYPTODEV_KEYWORD) == 0) {
188                                 ret = parse_cryptodev_arg(optarg);
189                                 if (ret < 0) {
190                                         cryptodev_fips_validate_usage(prgname);
191                                         return -EINVAL;
192                                 }
193                         } else if (strcmp(lgopts[option_index].name,
194                                         CRYPTODEV_ID_KEYWORD) == 0) {
195                                 ret = parse_cryptodev_id_arg(optarg);
196                                 if (ret < 0) {
197                                         cryptodev_fips_validate_usage(prgname);
198                                         return -EINVAL;
199                                 }
200                         } else {
201                                 cryptodev_fips_validate_usage(prgname);
202                                 return -EINVAL;
203                         }
204                         break;
205                 default:
206                         return -1;
207                 }
208         }
209
210         if (env.req_path == NULL || env.rsp_path == NULL ||
211                         env.dev_id == UINT32_MAX) {
212                 cryptodev_fips_validate_usage(prgname);
213                 return -EINVAL;
214         }
215
216         return 0;
217 }
218
219 int
220 main(int argc, char *argv[])
221 {
222         int ret;
223
224         ret = rte_eal_init(argc, argv);
225         if (ret < 0) {
226                 RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
227                 return -1;
228         }
229
230         argc -= ret;
231         argv += ret;
232
233         ret = cryptodev_fips_validate_parse_args(argc, argv);
234         if (ret < 0)
235                 rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
236
237         ret = cryptodev_fips_validate_app_int();
238         if (ret < 0) {
239                 RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
240                 return -1;
241         }
242
243         if (!env.is_path_folder) {
244                 printf("Processing file %s... ", env.req_path);
245
246                 ret = fips_test_init(env.req_path, env.rsp_path,
247                         rte_cryptodev_name_get(env.dev_id));
248                 if (ret < 0) {
249                         RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
250                                         ret, env.req_path);
251                         goto exit;
252                 }
253
254
255                 ret = fips_test_one_file();
256                 if (ret < 0) {
257                         RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
258                                         ret, env.req_path);
259                         goto exit;
260                 }
261
262                 printf("Done\n");
263
264         } else {
265                 struct dirent *dir;
266                 DIR *d_req, *d_rsp;
267                 char req_path[1024];
268                 char rsp_path[1024];
269
270                 d_req = opendir(env.req_path);
271                 if (!d_req) {
272                         RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
273                                         -EINVAL, env.req_path);
274                         goto exit;
275                 }
276
277                 d_rsp = opendir(env.rsp_path);
278                 if (!d_rsp) {
279                         ret = mkdir(env.rsp_path, 0700);
280                         if (ret == 0)
281                                 d_rsp = opendir(env.rsp_path);
282                         else {
283                                 RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
284                                                 -EINVAL, env.rsp_path);
285                                 goto exit;
286                         }
287                 }
288                 closedir(d_rsp);
289
290                 while ((dir = readdir(d_req)) != NULL) {
291                         if (strstr(dir->d_name, "req") == NULL)
292                                 continue;
293
294                         snprintf(req_path, 1023, "%s/%s", env.req_path,
295                                         dir->d_name);
296                         snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
297                                         dir->d_name);
298                         strlcpy(strstr(rsp_path, "req"), "rsp", 4);
299
300                         printf("Processing file %s... ", req_path);
301
302                         ret = fips_test_init(req_path, rsp_path,
303                         rte_cryptodev_name_get(env.dev_id));
304                         if (ret < 0) {
305                                 RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
306                                                 ret, req_path);
307                                 break;
308                         }
309
310                         ret = fips_test_one_file();
311                         if (ret < 0) {
312                                 RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
313                                                 ret, req_path);
314                                 break;
315                         }
316
317                         printf("Done\n");
318                 }
319
320                 closedir(d_req);
321         }
322
323
324 exit:
325         fips_test_clear();
326         cryptodev_fips_validate_app_uninit();
327
328         return ret;
329
330 }
331
332 #define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
333 #define CRYPTODEV_FIPS_MAX_RETRIES      16
334
335 typedef int (*fips_test_one_case_t)(void);
336 typedef int (*fips_prepare_op_t)(void);
337 typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
338
339 struct fips_test_ops {
340         fips_prepare_xform_t prepare_xform;
341         fips_prepare_op_t prepare_op;
342         fips_test_one_case_t test;
343 } test_ops;
344
345 static int
346 prepare_cipher_op(void)
347 {
348         struct rte_crypto_sym_op *sym = env.op->sym;
349         uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
350
351         __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
352         rte_pktmbuf_reset(env.mbuf);
353
354         sym->m_src = env.mbuf;
355         sym->cipher.data.offset = 0;
356
357         memcpy(iv, vec.iv.val, vec.iv.len);
358
359         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
360                 uint8_t *pt;
361
362                 if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
363                         RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
364                         return -EPERM;
365                 }
366
367                 pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len);
368
369                 if (!pt) {
370                         RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
371                                         -ENOMEM);
372                         return -ENOMEM;
373                 }
374
375                 memcpy(pt, vec.pt.val, vec.pt.len);
376                 sym->cipher.data.length = vec.pt.len;
377
378         } else {
379                 uint8_t *ct;
380
381                 if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
382                         RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
383                         return -EPERM;
384                 }
385
386                 ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
387
388                 if (!ct) {
389                         RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
390                                         -ENOMEM);
391                         return -ENOMEM;
392                 }
393
394                 memcpy(ct, vec.ct.val, vec.ct.len);
395                 sym->cipher.data.length = vec.ct.len;
396         }
397
398         rte_crypto_op_attach_sym_session(env.op, env.sess);
399
400         return 0;
401 }
402
403 static int
404 prepare_auth_op(void)
405 {
406         struct rte_crypto_sym_op *sym = env.op->sym;
407
408         __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
409         rte_pktmbuf_reset(env.mbuf);
410
411         sym->m_src = env.mbuf;
412         sym->auth.data.offset = 0;
413
414         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
415                 uint8_t *pt;
416
417                 if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
418                         RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
419                         return -EPERM;
420                 }
421
422                 pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len +
423                                 vec.cipher_auth.digest.len);
424
425                 if (!pt) {
426                         RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
427                                         -ENOMEM);
428                         return -ENOMEM;
429                 }
430
431                 memcpy(pt, vec.pt.val, vec.pt.len);
432                 sym->auth.data.length = vec.pt.len;
433                 sym->auth.digest.data = pt + vec.pt.len;
434                 sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
435                                 env.mbuf, vec.pt.len);
436
437         } else {
438                 uint8_t *ct;
439
440                 if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
441                         RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
442                         return -EPERM;
443                 }
444
445                 ct = (uint8_t *)rte_pktmbuf_append(env.mbuf,
446                                 vec.ct.len + vec.cipher_auth.digest.len);
447
448                 if (!ct) {
449                         RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
450                                         -ENOMEM);
451                         return -ENOMEM;
452                 }
453
454                 memcpy(ct, vec.ct.val, vec.ct.len);
455                 sym->auth.data.length = vec.ct.len;
456                 sym->auth.digest.data = vec.cipher_auth.digest.val;
457                 sym->auth.digest.phys_addr = rte_malloc_virt2iova(
458                                 sym->auth.digest.data);
459         }
460
461         rte_crypto_op_attach_sym_session(env.op, env.sess);
462 }
463
464 static int
465 prepare_aead_op(void)
466 {
467         struct rte_crypto_sym_op *sym = env.op->sym;
468         uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
469
470         __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
471         rte_pktmbuf_reset(env.mbuf);
472
473         memcpy(iv, vec.iv.val, vec.iv.len);
474
475         sym->m_src = env.mbuf;
476         sym->aead.data.offset = 0;
477         sym->aead.aad.data = vec.aead.aad.val;
478         sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
479
480         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
481                 uint8_t *pt;
482
483                 if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
484                         RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
485                         return -EPERM;
486                 }
487
488                 pt = (uint8_t *)rte_pktmbuf_append(env.mbuf,
489                                 vec.pt.len + vec.aead.digest.len);
490
491                 if (!pt) {
492                         RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
493                                         -ENOMEM);
494                         return -ENOMEM;
495                 }
496
497                 memcpy(pt, vec.pt.val, vec.pt.len);
498                 sym->aead.data.length = vec.pt.len;
499                 sym->aead.digest.data = pt + vec.pt.len;
500                 sym->aead.digest.phys_addr = rte_pktmbuf_mtophys_offset(
501                                 env.mbuf, vec.pt.len);
502         } else {
503                 uint8_t *ct;
504
505                 if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
506                         RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
507                         return -EPERM;
508                 }
509
510                 ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
511
512                 if (!ct) {
513                         RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
514                                         -ENOMEM);
515                         return -ENOMEM;
516                 }
517
518                 memcpy(ct, vec.ct.val, vec.ct.len);
519                 sym->aead.data.length = vec.ct.len;
520                 sym->aead.digest.data = vec.aead.digest.val;
521                 sym->aead.digest.phys_addr = rte_malloc_virt2iova(
522                                 sym->aead.digest.data);
523         }
524
525         rte_crypto_op_attach_sym_session(env.op, env.sess);
526 }
527
528 static int
529 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
530 {
531         const struct rte_cryptodev_symmetric_capability *cap;
532         struct rte_cryptodev_sym_capability_idx cap_idx;
533         struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
534
535         xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
536
537         cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
538         cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
539                         RTE_CRYPTO_CIPHER_OP_ENCRYPT :
540                         RTE_CRYPTO_CIPHER_OP_DECRYPT;
541         cipher_xform->key.data = vec.cipher_auth.key.val;
542         cipher_xform->key.length = vec.cipher_auth.key.len;
543         cipher_xform->iv.length = vec.iv.len;
544         cipher_xform->iv.offset = IV_OFF;
545
546         cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
547         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
548
549         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
550         if (!cap) {
551                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
552                                 env.dev_id);
553                 return -EINVAL;
554         }
555
556         if (rte_cryptodev_sym_capability_check_cipher(cap,
557                         cipher_xform->key.length,
558                         cipher_xform->iv.length) != 0) {
559                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
560                                 info.device_name, cipher_xform->key.length,
561                                 cipher_xform->iv.length);
562                 return -EPERM;
563         }
564
565         return 0;
566 }
567
568 static int
569 prepare_tdes_xform(struct rte_crypto_sym_xform *xform)
570 {
571         const struct rte_cryptodev_symmetric_capability *cap;
572         struct rte_cryptodev_sym_capability_idx cap_idx;
573         struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
574
575         xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
576
577         cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
578         cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
579                         RTE_CRYPTO_CIPHER_OP_ENCRYPT :
580                         RTE_CRYPTO_CIPHER_OP_DECRYPT;
581         cipher_xform->key.data = vec.cipher_auth.key.val;
582         cipher_xform->key.length = vec.cipher_auth.key.len;
583         cipher_xform->iv.length = vec.iv.len;
584         cipher_xform->iv.offset = IV_OFF;
585
586         cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
587         cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
588
589         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
590         if (!cap) {
591                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
592                                 env.dev_id);
593                 return -EINVAL;
594         }
595
596         if (rte_cryptodev_sym_capability_check_cipher(cap,
597                         cipher_xform->key.length,
598                         cipher_xform->iv.length) != 0) {
599                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
600                                 info.device_name, cipher_xform->key.length,
601                                 cipher_xform->iv.length);
602                 return -EPERM;
603         }
604
605         return 0;
606 }
607
608 static int
609 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
610 {
611         const struct rte_cryptodev_symmetric_capability *cap;
612         struct rte_cryptodev_sym_capability_idx cap_idx;
613         struct rte_crypto_auth_xform *auth_xform = &xform->auth;
614
615         xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
616
617         auth_xform->algo = info.interim_info.hmac_data.algo;
618         auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
619         auth_xform->digest_length = vec.cipher_auth.digest.len;
620         auth_xform->key.data = vec.cipher_auth.key.val;
621         auth_xform->key.length = vec.cipher_auth.key.len;
622
623         cap_idx.algo.auth = auth_xform->algo;
624         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
625
626         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
627         if (!cap) {
628                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
629                                 env.dev_id);
630                 return -EINVAL;
631         }
632
633         if (rte_cryptodev_sym_capability_check_auth(cap,
634                         auth_xform->key.length,
635                         auth_xform->digest_length, 0) != 0) {
636                 RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
637                                 info.device_name, auth_xform->key.length,
638                                 auth_xform->digest_length);
639                 return -EPERM;
640         }
641
642         return 0;
643 }
644
645 static int
646 prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
647 {
648         const struct rte_cryptodev_symmetric_capability *cap;
649         struct rte_cryptodev_sym_capability_idx cap_idx;
650         struct rte_crypto_aead_xform *aead_xform = &xform->aead;
651
652         xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
653
654         aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
655         aead_xform->aad_length = vec.aead.aad.len;
656         aead_xform->digest_length = vec.aead.digest.len;
657         aead_xform->iv.offset = IV_OFF;
658         aead_xform->iv.length = vec.iv.len;
659         aead_xform->key.data = vec.aead.key.val;
660         aead_xform->key.length = vec.aead.key.len;
661         aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
662                         RTE_CRYPTO_AEAD_OP_ENCRYPT :
663                         RTE_CRYPTO_AEAD_OP_DECRYPT;
664
665         cap_idx.algo.aead = aead_xform->algo;
666         cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
667
668         cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
669         if (!cap) {
670                 RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
671                                 env.dev_id);
672                 return -EINVAL;
673         }
674
675         if (rte_cryptodev_sym_capability_check_aead(cap,
676                         aead_xform->key.length,
677                         aead_xform->digest_length, aead_xform->aad_length,
678                         aead_xform->iv.length) != 0) {
679                 RTE_LOG(ERR, USER1,
680                         "PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
681                                 info.device_name, aead_xform->key.length,
682                                 aead_xform->digest_length,
683                                 aead_xform->aad_length,
684                                 aead_xform->iv.length);
685                 return -EPERM;
686         }
687
688         return 0;
689 }
690
691 static void
692 get_writeback_data(struct fips_val *val)
693 {
694         val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
695         val->len = rte_pktmbuf_pkt_len(env.mbuf);
696 }
697
698 static int
699 fips_run_test(void)
700 {
701         struct rte_crypto_sym_xform xform = {0};
702         uint16_t n_deqd;
703         int ret;
704
705         ret = test_ops.prepare_xform(&xform);
706         if (ret < 0)
707                 return ret;
708
709         env.sess = rte_cryptodev_sym_session_create(env.mpool);
710         if (!env.sess)
711                 return -ENOMEM;
712
713         ret = rte_cryptodev_sym_session_init(env.dev_id,
714                         env.sess, &xform, env.mpool);
715         if (ret < 0) {
716                 RTE_LOG(ERR, USER1, "Error %i: Init session\n",
717                                 ret);
718                 return ret;
719         }
720
721         ret = test_ops.prepare_op();
722         if (ret < 0) {
723                 RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
724                                 ret);
725                 return ret;
726         }
727
728         if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
729                 RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
730                 return ret;
731         }
732
733         do {
734                 struct rte_crypto_op *deqd_op;
735
736                 n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
737                                 1);
738         } while (n_deqd == 0);
739
740         vec.status = env.op->status;
741
742         rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
743         rte_cryptodev_sym_session_free(env.sess);
744         env.sess = NULL;
745
746         return ret;
747 }
748
749 static int
750 fips_generic_test(void)
751 {
752         struct fips_val val;
753         int ret;
754
755         fips_test_write_one_case();
756
757         ret = fips_run_test();
758         if (ret < 0) {
759                 if (ret == -EPERM) {
760                         fprintf(info.fp_wr, "Bypass\n\n");
761                         return 0;
762                 }
763
764                 return ret;
765         }
766
767         get_writeback_data(&val);
768
769         switch (info.file_type) {
770         case FIPS_TYPE_REQ:
771         case FIPS_TYPE_RSP:
772                 if (info.parse_writeback == NULL)
773                         return -EPERM;
774                 ret = info.parse_writeback(&val);
775                 if (ret < 0)
776                         return ret;
777                 break;
778         case FIPS_TYPE_FAX:
779                 if (info.kat_check == NULL)
780                         return -EPERM;
781                 ret = info.kat_check(&val);
782                 if (ret < 0)
783                         return ret;
784                 break;
785         }
786
787         fprintf(info.fp_wr, "\n");
788
789         return 0;
790 }
791
792 static int
793 fips_mct_tdes_test(void)
794 {
795 #define TDES_BLOCK_SIZE         8
796 #define TDES_EXTERN_ITER        400
797 #define TDES_INTERN_ITER        10000
798         struct fips_val val, val_key;
799         uint8_t prev_out[TDES_BLOCK_SIZE];
800         uint8_t prev_prev_out[TDES_BLOCK_SIZE];
801         uint8_t prev_in[TDES_BLOCK_SIZE];
802         uint32_t i, j, k;
803         int ret;
804
805         for (i = 0; i < TDES_EXTERN_ITER; i++) {
806                 if (i != 0)
807                         update_info_vec(i);
808
809                 fips_test_write_one_case();
810
811                 for (j = 0; j < TDES_INTERN_ITER; j++) {
812                         ret = fips_run_test();
813                         if (ret < 0) {
814                                 if (ret == -EPERM) {
815                                         fprintf(info.fp_wr, "Bypass\n");
816                                         return 0;
817                                 }
818
819                                 return ret;
820                         }
821
822                         get_writeback_data(&val);
823
824                         if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
825                                 memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
826
827                         if (j == 0) {
828                                 memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
829
830                                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
831                                         memcpy(vec.pt.val, vec.iv.val,
832                                                         TDES_BLOCK_SIZE);
833                                         memcpy(vec.iv.val, val.val,
834                                                         TDES_BLOCK_SIZE);
835                                 } else {
836                                         memcpy(vec.iv.val, vec.ct.val,
837                                                         TDES_BLOCK_SIZE);
838                                         memcpy(vec.ct.val, val.val,
839                                                         TDES_BLOCK_SIZE);
840                                 }
841                                 continue;
842                         }
843
844                         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
845                                 memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
846                                 memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
847                         } else {
848                                 memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
849                                 memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
850                         }
851
852                         if (j == TDES_INTERN_ITER - 1)
853                                 continue;
854
855                         memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
856
857                         if (j == TDES_INTERN_ITER - 3)
858                                 memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
859                 }
860
861                 info.parse_writeback(&val);
862                 fprintf(info.fp_wr, "\n");
863
864                 if (i == TDES_EXTERN_ITER - 1)
865                         continue;
866
867                 /** update key */
868                 memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
869
870                 if (info.interim_info.tdes_data.nb_keys == 0) {
871                         if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
872                                 info.interim_info.tdes_data.nb_keys = 1;
873                         else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
874                                 info.interim_info.tdes_data.nb_keys = 2;
875                         else
876                                 info.interim_info.tdes_data.nb_keys = 3;
877
878                 }
879
880                 for (k = 0; k < TDES_BLOCK_SIZE; k++) {
881
882                         switch (info.interim_info.tdes_data.nb_keys) {
883                         case 3:
884                                 val_key.val[k] ^= val.val[k];
885                                 val_key.val[k + 8] ^= prev_out[k];
886                                 val_key.val[k + 16] ^= prev_prev_out[k];
887                                 break;
888                         case 2:
889                                 val_key.val[k] ^= val.val[k];
890                                 val_key.val[k + 8] ^= prev_out[k];
891                                 val_key.val[k + 16] ^= val.val[k];
892                                 break;
893                         default: /* case 1 */
894                                 val_key.val[k] ^= val.val[k];
895                                 val_key.val[k + 8] ^= val.val[k];
896                                 val_key.val[k + 16] ^= val.val[k];
897                                 break;
898                         }
899
900                 }
901
902                 for (k = 0; k < 24; k++)
903                         val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
904                                         0x1) ?
905                                         val_key.val[k] : (val_key.val[k] ^ 0x1);
906
907                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
908                         memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
909                         memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
910                 } else {
911                         memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
912                         memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
913                 }
914         }
915
916         return 0;
917 }
918
919 static int
920 fips_mct_aes_test(void)
921 {
922 #define AES_BLOCK_SIZE  16
923 #define AES_EXTERN_ITER 100
924 #define AES_INTERN_ITER 1000
925         struct fips_val val, val_key;
926         uint8_t prev_out[AES_BLOCK_SIZE] = {0};
927         uint8_t prev_in[AES_BLOCK_SIZE] = {0};
928         uint32_t i, j, k;
929         int ret;
930
931         for (i = 0; i < AES_EXTERN_ITER; i++) {
932                 if (i != 0)
933                         update_info_vec(i);
934
935                 fips_test_write_one_case();
936
937                 for (j = 0; j < AES_INTERN_ITER; j++) {
938                         ret = fips_run_test();
939                         if (ret < 0) {
940                                 if (ret == -EPERM) {
941                                         fprintf(info.fp_wr, "Bypass\n");
942                                         return 0;
943                                 }
944
945                                 return ret;
946                         }
947
948                         get_writeback_data(&val);
949
950                         if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
951                                 memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
952
953                         if (j == 0) {
954                                 memcpy(prev_out, val.val, AES_BLOCK_SIZE);
955
956                                 if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
957                                         memcpy(vec.pt.val, vec.iv.val,
958                                                         AES_BLOCK_SIZE);
959                                         memcpy(vec.iv.val, val.val,
960                                                         AES_BLOCK_SIZE);
961                                 } else {
962                                         memcpy(vec.ct.val, vec.iv.val,
963                                                         AES_BLOCK_SIZE);
964                                         memcpy(vec.iv.val, prev_in,
965                                                         AES_BLOCK_SIZE);
966                                 }
967                                 continue;
968                         }
969
970                         if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
971                                 memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
972                                 memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
973                         } else {
974                                 memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
975                                 memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
976                         }
977
978                         if (j == AES_INTERN_ITER - 1)
979                                 continue;
980
981                         memcpy(prev_out, val.val, AES_BLOCK_SIZE);
982                 }
983
984                 info.parse_writeback(&val);
985                 fprintf(info.fp_wr, "\n");
986
987                 if (i == AES_EXTERN_ITER - 1)
988                         continue;
989
990                 /** update key */
991                 memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
992                 for (k = 0; k < vec.cipher_auth.key.len; k++) {
993                         switch (vec.cipher_auth.key.len) {
994                         case 16:
995                                 val_key.val[k] ^= val.val[k];
996                                 break;
997                         case 24:
998                                 if (k < 8)
999                                         val_key.val[k] ^= prev_out[k + 8];
1000                                 else
1001                                         val_key.val[k] ^= val.val[k - 8];
1002                                 break;
1003                         case 32:
1004                                 if (k < 16)
1005                                         val_key.val[k] ^= prev_out[k];
1006                                 else
1007                                         val_key.val[k] ^= val.val[k - 16];
1008                                 break;
1009                         default:
1010                                 return -1;
1011                         }
1012                 }
1013
1014                 if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
1015                         memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
1016         }
1017
1018         return 0;
1019 }
1020
1021 static int
1022 init_test_ops(void)
1023 {
1024         switch (info.algo) {
1025         case FIPS_TEST_ALGO_AES:
1026                 test_ops.prepare_op = prepare_cipher_op;
1027                 test_ops.prepare_xform  = prepare_aes_xform;
1028                 if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
1029                         test_ops.test = fips_mct_aes_test;
1030                 else
1031                         test_ops.test = fips_generic_test;
1032                 break;
1033         case FIPS_TEST_ALGO_HMAC:
1034                 test_ops.prepare_op = prepare_auth_op;
1035                 test_ops.prepare_xform = prepare_hmac_xform;
1036                 test_ops.test = fips_generic_test;
1037                 break;
1038         case FIPS_TEST_ALGO_TDES:
1039                 test_ops.prepare_op = prepare_cipher_op;
1040                 test_ops.prepare_xform  = prepare_tdes_xform;
1041                 if (info.interim_info.tdes_data.test_type == TDES_MCT)
1042                         test_ops.test = fips_mct_tdes_test;
1043                 else
1044                         test_ops.test = fips_generic_test;
1045                 break;
1046         case FIPS_TEST_ALGO_AES_GCM:
1047                 test_ops.prepare_op = prepare_aead_op;
1048                 test_ops.prepare_xform = prepare_gcm_xform;
1049                 test_ops.test = fips_generic_test;
1050                 break;
1051         default:
1052                 return -1;
1053         }
1054
1055         return 0;
1056 }
1057
1058 static void
1059 print_test_block(void)
1060 {
1061         uint32_t i;
1062
1063         for (i = 0; i < info.nb_vec_lines; i++)
1064                 printf("%s\n", info.vec[i]);
1065
1066         printf("\n");
1067 }
1068
1069 static int
1070 fips_test_one_file(void)
1071 {
1072         int fetch_ret = 0, ret;
1073
1074
1075         ret = init_test_ops();
1076         if (ret < 0) {
1077                 RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
1078                 return ret;
1079         }
1080
1081         while (ret >= 0 && fetch_ret == 0) {
1082                 fetch_ret = fips_test_fetch_one_block();
1083                 if (fetch_ret < 0) {
1084                         RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
1085                                         fetch_ret);
1086                         ret = fetch_ret;
1087                         goto error_one_case;
1088                 }
1089
1090                 if (info.nb_vec_lines == 0) {
1091                         if (fetch_ret == -EOF)
1092                                 break;
1093
1094                         fprintf(info.fp_wr, "\n");
1095                         continue;
1096                 }
1097
1098                 ret = fips_test_parse_one_case();
1099                 switch (ret) {
1100                 case 0:
1101                         ret = test_ops.test();
1102                         if (ret == 0)
1103                                 break;
1104                         RTE_LOG(ERR, USER1, "Error %i: test block\n",
1105                                         ret);
1106                         goto error_one_case;
1107                 case 1:
1108                         break;
1109                 default:
1110                         RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
1111                                         ret);
1112                         goto error_one_case;
1113                 }
1114
1115                 continue;
1116 error_one_case:
1117                 print_test_block();
1118         }
1119
1120         fips_test_clear();
1121
1122         return ret;
1123
1124 }