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