1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 8 #include <rte_string_fns.h> 9 #include <rte_cryptodev.h> 10 #include <rte_malloc.h> 11 12 #include "fips_validation.h" 13 14 #define skip_white_spaces(pos) \ 15 ({ \ 16 __typeof__(pos) _p = (pos); \ 17 for ( ; isspace(*_p); _p++) \ 18 ; \ 19 _p; \ 20 }) 21 22 static int 23 get_file_line(void) 24 { 25 FILE *fp = info.fp_rd; 26 char *line = info.one_line_text; 27 int ret; 28 uint32_t loc = 0; 29 30 memset(line, 0, MAX_LINE_CHAR); 31 while ((ret = fgetc(fp)) != EOF) { 32 char c = (char)ret; 33 34 if (loc >= MAX_LINE_CHAR - 1) 35 return -ENOMEM; 36 if (c == '\n') 37 break; 38 line[loc++] = c; 39 } 40 41 if (ret == EOF) 42 return -EOF; 43 44 return 0; 45 } 46 47 int 48 fips_test_fetch_one_block(void) 49 { 50 size_t size; 51 int ret = 0; 52 uint32_t i; 53 54 for (i = 0; i < info.nb_vec_lines; i++) { 55 free(info.vec[i]); 56 info.vec[i] = NULL; 57 } 58 59 i = 0; 60 do { 61 if (i >= MAX_LINE_PER_VECTOR) { 62 ret = -ENOMEM; 63 goto error_exit; 64 } 65 66 ret = get_file_line(); 67 size = strlen(info.one_line_text); 68 if (size == 0) 69 break; 70 71 info.vec[i] = calloc(1, size + 5); 72 if (info.vec[i] == NULL) 73 goto error_exit; 74 75 strlcpy(info.vec[i], info.one_line_text, size + 1); 76 i++; 77 } while (ret == 0); 78 79 info.nb_vec_lines = i; 80 81 return ret; 82 83 error_exit: 84 for (i = 0; i < MAX_LINE_PER_VECTOR; i++) 85 if (info.vec[i] != NULL) { 86 free(info.vec[i]); 87 info.vec[i] = NULL; 88 } 89 90 info.nb_vec_lines = 0; 91 92 return -ENOMEM; 93 } 94 95 static int 96 fips_test_parse_header(void) 97 { 98 uint32_t i; 99 char *tmp; 100 int ret; 101 int algo_parsed = 0; 102 time_t t = time(NULL); 103 struct tm *tm_now = localtime(&t); 104 105 ret = fips_test_fetch_one_block(); 106 if (ret < 0) 107 return ret; 108 109 for (i = 0; i < info.nb_vec_lines; i++) { 110 if (!algo_parsed) { 111 if (strstr(info.vec[i], "AESVS")) { 112 algo_parsed = 1; 113 info.algo = FIPS_TEST_ALGO_AES; 114 ret = parse_test_aes_init(); 115 if (ret < 0) 116 return ret; 117 } else if (strstr(info.vec[i], "GCM")) { 118 algo_parsed = 1; 119 info.algo = FIPS_TEST_ALGO_AES_GCM; 120 ret = parse_test_gcm_init(); 121 if (ret < 0) 122 return ret; 123 } else if (strstr(info.vec[i], "CMAC")) { 124 algo_parsed = 1; 125 info.algo = FIPS_TEST_ALGO_AES_CMAC; 126 ret = parse_test_cmac_init(); 127 if (ret < 0) 128 return 0; 129 } else if (strstr(info.vec[i], "CCM")) { 130 algo_parsed = 1; 131 info.algo = FIPS_TEST_ALGO_AES_CCM; 132 ret = parse_test_ccm_init(); 133 if (ret < 0) 134 return 0; 135 } else if (strstr(info.vec[i], "HMAC")) { 136 algo_parsed = 1; 137 info.algo = FIPS_TEST_ALGO_HMAC; 138 ret = parse_test_hmac_init(); 139 if (ret < 0) 140 return ret; 141 } else if (strstr(info.vec[i], "TDES")) { 142 algo_parsed = 1; 143 info.algo = FIPS_TEST_ALGO_TDES; 144 ret = parse_test_tdes_init(); 145 if (ret < 0) 146 return 0; 147 } else if (strstr(info.vec[i], "PERMUTATION")) { 148 algo_parsed = 1; 149 info.algo = FIPS_TEST_ALGO_TDES; 150 ret = parse_test_tdes_init(); 151 if (ret < 0) 152 return 0; 153 } else if (strstr(info.vec[i], "VARIABLE")) { 154 algo_parsed = 1; 155 info.algo = FIPS_TEST_ALGO_TDES; 156 ret = parse_test_tdes_init(); 157 if (ret < 0) 158 return 0; 159 } else if (strstr(info.vec[i], "SUBSTITUTION")) { 160 algo_parsed = 1; 161 info.algo = FIPS_TEST_ALGO_TDES; 162 ret = parse_test_tdes_init(); 163 if (ret < 0) 164 return 0; 165 } else if (strstr(info.vec[i], "SHA-")) { 166 algo_parsed = 1; 167 info.algo = FIPS_TEST_ALGO_SHA; 168 ret = parse_test_sha_init(); 169 if (ret < 0) 170 return ret; 171 } else if (strstr(info.vec[i], "XTS")) { 172 algo_parsed = 1; 173 info.algo = FIPS_TEST_ALGO_AES_XTS; 174 ret = parse_test_xts_init(); 175 if (ret < 0) 176 return ret; 177 } 178 } 179 180 tmp = strstr(info.vec[i], "# Config info for "); 181 if (tmp != NULL) { 182 fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ", 183 info.device_name); 184 continue; 185 } 186 187 tmp = strstr(info.vec[i], "# HMAC information for "); 188 if (tmp != NULL) { 189 fprintf(info.fp_wr, "%s%s\n", "# HMAC information for " 190 "DPDK Cryptodev ", 191 info.device_name); 192 continue; 193 } 194 195 tmp = strstr(info.vec[i], "# Config Info for : "); 196 if (tmp != NULL) { 197 198 fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ", 199 info.device_name); 200 continue; 201 } 202 203 tmp = strstr(info.vec[i], "# information for "); 204 if (tmp != NULL) { 205 206 char tmp_output[128] = {0}; 207 208 strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1); 209 210 fprintf(info.fp_wr, "%s%s%s\n", tmp_output, 211 "information for DPDK Cryptodev ", 212 info.device_name); 213 continue; 214 } 215 216 tmp = strstr(info.vec[i], " test information for "); 217 if (tmp != NULL) { 218 char tmp_output[128] = {0}; 219 220 strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1); 221 222 fprintf(info.fp_wr, "%s%s%s\n", tmp_output, 223 "test information for DPDK Cryptodev ", 224 info.device_name); 225 continue; 226 } 227 228 tmp = strstr(info.vec[i], "\" information for \""); 229 if (tmp != NULL) { 230 char tmp_output[128] = {0}; 231 232 strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1); 233 234 fprintf(info.fp_wr, "%s%s%s\n", tmp_output, 235 "\" information for DPDK Cryptodev ", 236 info.device_name); 237 continue; 238 } 239 240 if (i == info.nb_vec_lines - 1) { 241 /** update the time as current time, write to file */ 242 fprintf(info.fp_wr, "%s%s\n", "# Generated on ", 243 asctime(tm_now)); 244 continue; 245 } 246 247 /* to this point, no field need to update, 248 * only copy to rsp file 249 */ 250 fprintf(info.fp_wr, "%s\n", info.vec[i]); 251 } 252 253 return 0; 254 } 255 256 static int 257 parse_file_type(const char *path) 258 { 259 const char *tmp = path + strlen(path) - 3; 260 261 if (strstr(tmp, REQ_FILE_PERFIX)) 262 info.file_type = FIPS_TYPE_REQ; 263 else if (strstr(tmp, RSP_FILE_PERFIX)) 264 info.file_type = FIPS_TYPE_RSP; 265 else if (strstr(path, FAX_FILE_PERFIX)) 266 info.file_type = FIPS_TYPE_FAX; 267 else 268 return -EINVAL; 269 270 return 0; 271 } 272 273 int 274 fips_test_init(const char *req_file_path, const char *rsp_file_path, 275 const char *device_name) 276 { 277 if (strcmp(req_file_path, rsp_file_path) == 0) { 278 RTE_LOG(ERR, USER1, "File paths cannot be the same\n"); 279 return -EINVAL; 280 } 281 282 fips_test_clear(); 283 284 strcpy(info.file_name, req_file_path); 285 info.algo = FIPS_TEST_ALGO_MAX; 286 if (parse_file_type(req_file_path) < 0) { 287 RTE_LOG(ERR, USER1, "File %s type not supported\n", 288 req_file_path); 289 return -EINVAL; 290 } 291 292 info.fp_rd = fopen(req_file_path, "r"); 293 if (!info.fp_rd) { 294 RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path); 295 return -EINVAL; 296 } 297 298 info.fp_wr = fopen(rsp_file_path, "w"); 299 if (!info.fp_wr) { 300 RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path); 301 return -EINVAL; 302 } 303 304 info.one_line_text = calloc(1, MAX_LINE_CHAR); 305 if (!info.one_line_text) { 306 RTE_LOG(ERR, USER1, "Insufficient memory\n"); 307 return -ENOMEM; 308 } 309 310 strlcpy(info.device_name, device_name, sizeof(info.device_name)); 311 312 if (fips_test_parse_header() < 0) { 313 RTE_LOG(ERR, USER1, "Failed parsing header\n"); 314 return -1; 315 } 316 317 return 0; 318 } 319 320 void 321 fips_test_clear(void) 322 { 323 if (info.fp_rd) 324 fclose(info.fp_rd); 325 if (info.fp_wr) 326 fclose(info.fp_wr); 327 if (info.one_line_text) 328 free(info.one_line_text); 329 if (info.nb_vec_lines) { 330 uint32_t i; 331 332 for (i = 0; i < info.nb_vec_lines; i++) 333 free(info.vec[i]); 334 } 335 336 memset(&info, 0, sizeof(info)); 337 } 338 339 int 340 fips_test_parse_one_case(void) 341 { 342 uint32_t i, j = 0; 343 uint32_t is_interim = 0; 344 int ret; 345 346 if (info.interim_callbacks) { 347 for (i = 0; i < info.nb_vec_lines; i++) { 348 for (j = 0; info.interim_callbacks[j].key != NULL; j++) 349 if (strstr(info.vec[i], 350 info.interim_callbacks[j].key)) { 351 is_interim = 1; 352 353 ret = info.interim_callbacks[j].cb( 354 info.interim_callbacks[j].key, 355 info.vec[i], 356 info.interim_callbacks[j].val); 357 if (ret < 0) 358 return ret; 359 } 360 } 361 } 362 363 if (is_interim) { 364 for (i = 0; i < info.nb_vec_lines; i++) 365 fprintf(info.fp_wr, "%s\n", info.vec[i]); 366 fprintf(info.fp_wr, "\n"); 367 return 1; 368 } 369 370 for (i = 0; i < info.nb_vec_lines; i++) { 371 for (j = 0; info.callbacks[j].key != NULL; j++) 372 if (strstr(info.vec[i], info.callbacks[j].key)) { 373 ret = info.callbacks[j].cb( 374 info.callbacks[j].key, 375 info.vec[i], info.callbacks[j].val); 376 if (ret < 0) 377 return ret; 378 break; 379 } 380 } 381 382 return 0; 383 } 384 385 void 386 fips_test_write_one_case(void) 387 { 388 uint32_t i; 389 390 for (i = 0; i < info.nb_vec_lines; i++) 391 fprintf(info.fp_wr, "%s\n", info.vec[i]); 392 } 393 394 static int 395 parser_read_uint64_hex(uint64_t *value, const char *p) 396 { 397 char *next; 398 uint64_t val; 399 400 p = skip_white_spaces(p); 401 402 val = strtoul(p, &next, 16); 403 if (p == next) 404 return -EINVAL; 405 406 p = skip_white_spaces(next); 407 if (*p != '\0') 408 return -EINVAL; 409 410 *value = val; 411 return 0; 412 } 413 414 int 415 parser_read_uint8_hex(uint8_t *value, const char *p) 416 { 417 uint64_t val = 0; 418 int ret = parser_read_uint64_hex(&val, p); 419 420 if (ret < 0) 421 return ret; 422 423 if (val > UINT8_MAX) 424 return -ERANGE; 425 426 *value = val; 427 return 0; 428 } 429 430 int 431 parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val) 432 { 433 struct fips_val tmp_val = {0}; 434 uint32_t len = val->len; 435 int ret; 436 437 if (len == 0) { 438 if (val->val != NULL) { 439 rte_free(val->val); 440 val->val = NULL; 441 } 442 443 return 0; 444 } 445 446 ret = parse_uint8_hex_str(key, src, &tmp_val); 447 if (ret < 0) 448 return ret; 449 450 if (tmp_val.len == val->len) { 451 val->val = tmp_val.val; 452 return 0; 453 } 454 455 if (tmp_val.len < val->len) { 456 rte_free(tmp_val.val); 457 return -EINVAL; 458 } 459 460 val->val = rte_zmalloc(NULL, val->len, 0); 461 if (!val->val) { 462 rte_free(tmp_val.val); 463 memset(val, 0, sizeof(*val)); 464 return -ENOMEM; 465 } 466 467 memcpy(val->val, tmp_val.val, val->len); 468 rte_free(tmp_val.val); 469 470 return 0; 471 } 472 473 int 474 parse_uint8_hex_str(const char *key, char *src, struct fips_val *val) 475 { 476 uint32_t len, j; 477 478 src += strlen(key); 479 480 len = strlen(src) / 2; 481 482 if (val->val) { 483 rte_free(val->val); 484 val->val = NULL; 485 } 486 487 val->val = rte_zmalloc(NULL, len, 0); 488 if (!val->val) 489 return -ENOMEM; 490 491 for (j = 0; j < len; j++) { 492 char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'}; 493 494 if (parser_read_uint8_hex(&val->val[j], byte) < 0) { 495 rte_free(val->val); 496 memset(val, 0, sizeof(*val)); 497 return -EINVAL; 498 } 499 } 500 501 val->len = len; 502 503 return 0; 504 } 505 506 int 507 parser_read_uint32_val(const char *key, char *src, struct fips_val *val) 508 { 509 char *data = src + strlen(key); 510 size_t data_len = strlen(data); 511 int ret; 512 513 if (data[data_len - 1] == ']') { 514 char *tmp_data = calloc(1, data_len + 1); 515 516 if (tmp_data == NULL) 517 return -ENOMEM; 518 519 strlcpy(tmp_data, data, data_len); 520 521 ret = parser_read_uint32(&val->len, tmp_data); 522 523 free(tmp_data); 524 } else 525 ret = parser_read_uint32(&val->len, data); 526 527 return ret; 528 } 529 530 int 531 parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val) 532 { 533 int ret; 534 535 ret = parser_read_uint32_val(key, src, val); 536 537 if (ret < 0) 538 return ret; 539 540 val->len /= 8; 541 542 return 0; 543 } 544 545 int 546 writeback_hex_str(const char *key, char *dst, struct fips_val *val) 547 { 548 char *str = dst; 549 uint32_t len; 550 551 str += strlen(key); 552 553 for (len = 0; len < val->len; len++) 554 snprintf(str + len * 2, 255, "%02x", val->val[len]); 555 556 return 0; 557 } 558 559 static int 560 parser_read_uint64(uint64_t *value, const char *p) 561 { 562 char *next; 563 uint64_t val; 564 565 p = skip_white_spaces(p); 566 if (!isdigit(*p)) 567 return -EINVAL; 568 569 val = strtoul(p, &next, 10); 570 if (p == next) 571 return -EINVAL; 572 573 p = next; 574 switch (*p) { 575 case 'T': 576 val *= 1024ULL; 577 /* fall through */ 578 case 'G': 579 val *= 1024ULL; 580 /* fall through */ 581 case 'M': 582 val *= 1024ULL; 583 /* fall through */ 584 case 'k': 585 case 'K': 586 val *= 1024ULL; 587 p++; 588 break; 589 } 590 591 p = skip_white_spaces(p); 592 if (*p != '\0') 593 return -EINVAL; 594 595 *value = val; 596 return 0; 597 } 598 599 int 600 parser_read_uint32(uint32_t *value, char *p) 601 { 602 uint64_t val = 0; 603 int ret = parser_read_uint64(&val, p); 604 605 if (ret < 0) 606 return ret; 607 608 if (val > UINT32_MAX) 609 return -EINVAL; 610 611 *value = val; 612 return 0; 613 } 614 615 void 616 parse_write_hex_str(struct fips_val *src) 617 { 618 writeback_hex_str("", info.one_line_text, src); 619 620 fprintf(info.fp_wr, "%s\n", info.one_line_text); 621 } 622 623 int 624 update_info_vec(uint32_t count) 625 { 626 const struct fips_test_callback *cb; 627 uint32_t i, j; 628 629 if (!info.writeback_callbacks) 630 return -1; 631 632 cb = &info.writeback_callbacks[0]; 633 634 snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count); 635 636 for (i = 1; i < info.nb_vec_lines; i++) { 637 for (j = 1; info.writeback_callbacks[j].key != NULL; j++) { 638 cb = &info.writeback_callbacks[j]; 639 if (strstr(info.vec[i], cb->key)) { 640 cb->cb(cb->key, info.vec[i], cb->val); 641 break; 642 } 643 } 644 } 645 646 return 0; 647 } 648