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