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