1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016-2017 Intel Corporation 3 */ 4 #ifdef RTE_EXEC_ENV_BSDAPP 5 #define _WITH_GETLINE 6 #endif 7 #include <stdio.h> 8 9 #include <rte_malloc.h> 10 11 #include "cperf_options.h" 12 #include "cperf_test_vectors.h" 13 #include "cperf_test_vector_parsing.h" 14 15 int 16 free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts) 17 { 18 if (vector == NULL || opts == NULL) 19 return -1; 20 21 rte_free(vector->cipher_iv.data); 22 rte_free(vector->auth_iv.data); 23 rte_free(vector->aad.data); 24 rte_free(vector->digest.data); 25 26 if (opts->test_file != NULL) { 27 rte_free(vector->plaintext.data); 28 rte_free(vector->cipher_key.data); 29 rte_free(vector->auth_key.data); 30 rte_free(vector->ciphertext.data); 31 } 32 33 rte_free(vector); 34 35 return 0; 36 } 37 38 void 39 show_test_vector(struct cperf_test_vector *test_vector) 40 { 41 const uint8_t wrap = 32; 42 uint32_t i; 43 44 if (test_vector == NULL) 45 return; 46 47 if (test_vector->plaintext.data) { 48 printf("\nplaintext =\n"); 49 for (i = 0; i < test_vector->plaintext.length; ++i) { 50 if ((i % wrap == 0) && (i != 0)) 51 printf("\n"); 52 if (i == test_vector->plaintext.length - 1) 53 printf("0x%02x", 54 test_vector->plaintext.data[i]); 55 else 56 printf("0x%02x, ", 57 test_vector->plaintext.data[i]); 58 } 59 printf("\n"); 60 } 61 62 if (test_vector->cipher_key.data) { 63 printf("\ncipher_key =\n"); 64 for (i = 0; i < test_vector->cipher_key.length; ++i) { 65 if ((i % wrap == 0) && (i != 0)) 66 printf("\n"); 67 if (i == (uint32_t)(test_vector->cipher_key.length - 1)) 68 printf("0x%02x", 69 test_vector->cipher_key.data[i]); 70 else 71 printf("0x%02x, ", 72 test_vector->cipher_key.data[i]); 73 } 74 printf("\n"); 75 } 76 77 if (test_vector->auth_key.data) { 78 printf("\nauth_key =\n"); 79 for (i = 0; i < test_vector->auth_key.length; ++i) { 80 if ((i % wrap == 0) && (i != 0)) 81 printf("\n"); 82 if (i == (uint32_t)(test_vector->auth_key.length - 1)) 83 printf("0x%02x", test_vector->auth_key.data[i]); 84 else 85 printf("0x%02x, ", 86 test_vector->auth_key.data[i]); 87 } 88 printf("\n"); 89 } 90 91 if (test_vector->aead_key.data) { 92 printf("\naead_key =\n"); 93 for (i = 0; i < test_vector->aead_key.length; ++i) { 94 if ((i % wrap == 0) && (i != 0)) 95 printf("\n"); 96 if (i == (uint32_t)(test_vector->aead_key.length - 1)) 97 printf("0x%02x", test_vector->aead_key.data[i]); 98 else 99 printf("0x%02x, ", 100 test_vector->aead_key.data[i]); 101 } 102 printf("\n"); 103 } 104 105 if (test_vector->cipher_iv.data) { 106 printf("\ncipher_iv =\n"); 107 for (i = 0; i < test_vector->cipher_iv.length; ++i) { 108 if ((i % wrap == 0) && (i != 0)) 109 printf("\n"); 110 if (i == (uint32_t)(test_vector->cipher_iv.length - 1)) 111 printf("0x%02x", test_vector->cipher_iv.data[i]); 112 else 113 printf("0x%02x, ", test_vector->cipher_iv.data[i]); 114 } 115 printf("\n"); 116 } 117 118 if (test_vector->auth_iv.data) { 119 printf("\nauth_iv =\n"); 120 for (i = 0; i < test_vector->auth_iv.length; ++i) { 121 if ((i % wrap == 0) && (i != 0)) 122 printf("\n"); 123 if (i == (uint32_t)(test_vector->auth_iv.length - 1)) 124 printf("0x%02x", test_vector->auth_iv.data[i]); 125 else 126 printf("0x%02x, ", test_vector->auth_iv.data[i]); 127 } 128 printf("\n"); 129 } 130 131 if (test_vector->aead_iv.data) { 132 printf("\naead_iv =\n"); 133 for (i = 0; i < test_vector->aead_iv.length; ++i) { 134 if ((i % wrap == 0) && (i != 0)) 135 printf("\n"); 136 if (i == (uint32_t)(test_vector->aead_iv.length - 1)) 137 printf("0x%02x", test_vector->aead_iv.data[i]); 138 else 139 printf("0x%02x, ", test_vector->aead_iv.data[i]); 140 } 141 printf("\n"); 142 } 143 144 if (test_vector->ciphertext.data) { 145 printf("\nciphertext =\n"); 146 for (i = 0; i < test_vector->ciphertext.length; ++i) { 147 if ((i % wrap == 0) && (i != 0)) 148 printf("\n"); 149 if (i == test_vector->ciphertext.length - 1) 150 printf("0x%02x", 151 test_vector->ciphertext.data[i]); 152 else 153 printf("0x%02x, ", 154 test_vector->ciphertext.data[i]); 155 } 156 printf("\n"); 157 } 158 159 if (test_vector->aad.data) { 160 printf("\naad =\n"); 161 for (i = 0; i < test_vector->aad.length; ++i) { 162 if ((i % wrap == 0) && (i != 0)) 163 printf("\n"); 164 if (i == (uint32_t)(test_vector->aad.length - 1)) 165 printf("0x%02x", test_vector->aad.data[i]); 166 else 167 printf("0x%02x, ", test_vector->aad.data[i]); 168 } 169 printf("\n"); 170 } 171 172 if (test_vector->digest.data) { 173 printf("\ndigest =\n"); 174 for (i = 0; i < test_vector->digest.length; ++i) { 175 if ((i % wrap == 0) && (i != 0)) 176 printf("\n"); 177 if (i == (uint32_t)(test_vector->digest.length - 1)) 178 printf("0x%02x", test_vector->digest.data[i]); 179 else 180 printf("0x%02x, ", test_vector->digest.data[i]); 181 } 182 printf("\n"); 183 } 184 } 185 186 /* trim leading and trailing spaces */ 187 static char * 188 trim_space(char *str) 189 { 190 char *start, *end; 191 192 for (start = str; *start; start++) { 193 if (!isspace((unsigned char) start[0])) 194 break; 195 } 196 197 for (end = start + strlen(start); end > start + 1; end--) { 198 if (!isspace((unsigned char) end[-1])) 199 break; 200 } 201 202 *end = 0; 203 204 /* Shift from "start" to the beginning of the string */ 205 if (start > str) 206 memmove(str, start, (end - start) + 1); 207 208 return str; 209 } 210 211 /* tokenization test values separated by a comma */ 212 static int 213 parse_values(char *tokens, uint8_t **data, uint32_t *data_length) 214 { 215 uint32_t n_tokens; 216 uint32_t data_size = 32; 217 218 uint8_t *values, *values_resized; 219 char *tok, *error = NULL; 220 221 tok = strtok(tokens, CPERF_VALUE_DELIMITER); 222 if (tok == NULL) 223 return -1; 224 225 values = (uint8_t *) rte_zmalloc(NULL, sizeof(uint8_t) * data_size, 0); 226 if (values == NULL) 227 return -1; 228 229 n_tokens = 0; 230 while (tok != NULL) { 231 values_resized = NULL; 232 233 if (n_tokens >= data_size) { 234 data_size *= 2; 235 236 values_resized = (uint8_t *) rte_realloc(values, 237 sizeof(uint8_t) * data_size, 0); 238 if (values_resized == NULL) { 239 rte_free(values); 240 return -1; 241 } 242 values = values_resized; 243 } 244 245 values[n_tokens] = (uint8_t) strtoul(tok, &error, 0); 246 if ((error == NULL) || (*error != '\0')) { 247 printf("Failed with convert '%s'\n", tok); 248 rte_free(values); 249 return -1; 250 } 251 252 tok = strtok(NULL, CPERF_VALUE_DELIMITER); 253 if (tok == NULL) 254 break; 255 256 n_tokens++; 257 } 258 259 values_resized = (uint8_t *) rte_realloc(values, 260 sizeof(uint8_t) * (n_tokens + 1), 0); 261 262 if (values_resized == NULL) { 263 rte_free(values); 264 return -1; 265 } 266 267 *data = values_resized; 268 *data_length = n_tokens + 1; 269 270 return 0; 271 } 272 273 /* checks the type of key and assigns data */ 274 static int 275 parse_entry(char *entry, struct cperf_test_vector *vector, 276 struct cperf_options *opts, uint8_t tc_found) 277 { 278 int status; 279 uint32_t data_length; 280 281 uint8_t *data = NULL; 282 char *token, *key_token; 283 284 if (entry == NULL) { 285 printf("Expected entry value\n"); 286 return -1; 287 } 288 289 /* get key */ 290 token = strtok(entry, CPERF_ENTRY_DELIMITER); 291 key_token = token; 292 /* get values for key */ 293 token = strtok(NULL, CPERF_ENTRY_DELIMITER); 294 295 if (key_token == NULL || token == NULL) { 296 printf("Expected 'key = values' but was '%.40s'..\n", entry); 297 return -1; 298 } 299 300 status = parse_values(token, &data, &data_length); 301 if (status) 302 return -1; 303 304 /* compare keys */ 305 if (strstr(key_token, "plaintext")) { 306 rte_free(vector->plaintext.data); 307 vector->plaintext.data = data; 308 if (tc_found) 309 vector->plaintext.length = data_length; 310 else { 311 if (opts->max_buffer_size > data_length) { 312 printf("Global plaintext shorter than " 313 "buffer_sz\n"); 314 return -1; 315 } 316 vector->plaintext.length = opts->max_buffer_size; 317 } 318 319 } else if (strstr(key_token, "cipher_key")) { 320 rte_free(vector->cipher_key.data); 321 vector->cipher_key.data = data; 322 if (tc_found) 323 vector->cipher_key.length = data_length; 324 else { 325 if (opts->cipher_key_sz > data_length) { 326 printf("Global cipher_key shorter than " 327 "cipher_key_sz\n"); 328 return -1; 329 } 330 vector->cipher_key.length = opts->cipher_key_sz; 331 } 332 333 } else if (strstr(key_token, "auth_key")) { 334 rte_free(vector->auth_key.data); 335 vector->auth_key.data = data; 336 if (tc_found) 337 vector->auth_key.length = data_length; 338 else { 339 if (opts->auth_key_sz > data_length) { 340 printf("Global auth_key shorter than " 341 "auth_key_sz\n"); 342 return -1; 343 } 344 vector->auth_key.length = opts->auth_key_sz; 345 } 346 347 } else if (strstr(key_token, "aead_key")) { 348 rte_free(vector->aead_key.data); 349 vector->aead_key.data = data; 350 if (tc_found) 351 vector->aead_key.length = data_length; 352 else { 353 if (opts->aead_key_sz > data_length) { 354 printf("Global aead_key shorter than " 355 "aead_key_sz\n"); 356 return -1; 357 } 358 vector->aead_key.length = opts->aead_key_sz; 359 } 360 361 } else if (strstr(key_token, "cipher_iv")) { 362 rte_free(vector->cipher_iv.data); 363 vector->cipher_iv.data = data; 364 if (tc_found) 365 vector->cipher_iv.length = data_length; 366 else { 367 if (opts->cipher_iv_sz > data_length) { 368 printf("Global cipher iv shorter than " 369 "cipher_iv_sz\n"); 370 return -1; 371 } 372 vector->cipher_iv.length = opts->cipher_iv_sz; 373 } 374 375 } else if (strstr(key_token, "auth_iv")) { 376 rte_free(vector->auth_iv.data); 377 vector->auth_iv.data = data; 378 if (tc_found) 379 vector->auth_iv.length = data_length; 380 else { 381 if (opts->auth_iv_sz > data_length) { 382 printf("Global auth iv shorter than " 383 "auth_iv_sz\n"); 384 return -1; 385 } 386 vector->auth_iv.length = opts->auth_iv_sz; 387 } 388 389 } else if (strstr(key_token, "aead_iv")) { 390 rte_free(vector->aead_iv.data); 391 vector->aead_iv.data = data; 392 if (tc_found) 393 vector->aead_iv.length = data_length; 394 else { 395 if (opts->aead_iv_sz > data_length) { 396 printf("Global aead iv shorter than " 397 "aead_iv_sz\n"); 398 return -1; 399 } 400 vector->aead_iv.length = opts->aead_iv_sz; 401 } 402 403 } else if (strstr(key_token, "ciphertext")) { 404 rte_free(vector->ciphertext.data); 405 vector->ciphertext.data = data; 406 if (tc_found) 407 vector->ciphertext.length = data_length; 408 else { 409 if (opts->max_buffer_size > data_length) { 410 printf("Global ciphertext shorter than " 411 "buffer_sz\n"); 412 return -1; 413 } 414 vector->ciphertext.length = opts->max_buffer_size; 415 } 416 417 } else if (strstr(key_token, "aad")) { 418 rte_free(vector->aad.data); 419 vector->aad.data = data; 420 vector->aad.phys_addr = rte_malloc_virt2iova(vector->aad.data); 421 if (tc_found) 422 vector->aad.length = data_length; 423 else { 424 if (opts->aead_aad_sz > data_length) { 425 printf("Global aad shorter than " 426 "aead_aad_sz\n"); 427 return -1; 428 } 429 vector->aad.length = opts->aead_aad_sz; 430 } 431 432 } else if (strstr(key_token, "digest")) { 433 rte_free(vector->digest.data); 434 vector->digest.data = data; 435 vector->digest.phys_addr = rte_malloc_virt2iova( 436 vector->digest.data); 437 if (tc_found) 438 vector->digest.length = data_length; 439 else { 440 if (opts->digest_sz > data_length) { 441 printf("Global digest shorter than " 442 "digest_sz\n"); 443 return -1; 444 } 445 vector->digest.length = opts->digest_sz; 446 } 447 } else { 448 printf("Not valid key: '%s'\n", trim_space(key_token)); 449 return -1; 450 } 451 452 return 0; 453 } 454 455 /* searches in the file for test keys and values */ 456 static int 457 parse_file(struct cperf_test_vector *vector, struct cperf_options *opts) 458 { 459 uint8_t tc_found = 0; 460 uint8_t tc_data_start = 0; 461 ssize_t read; 462 size_t len = 0; 463 int status = 0; 464 465 FILE *fp; 466 char *line = NULL; 467 char *entry = NULL; 468 469 fp = fopen(opts->test_file, "r"); 470 if (fp == NULL) { 471 printf("File %s does not exists\n", opts->test_file); 472 return -1; 473 } 474 475 while ((read = getline(&line, &len, fp)) != -1) { 476 477 /* ignore comments and new lines */ 478 if (line[0] == '#' || line[0] == '/' || line[0] == '\n' 479 || line[0] == '\r' || line[0] == ' ') 480 continue; 481 482 trim_space(line); 483 484 /* next test case is started */ 485 if (line[0] == '[' && line[strlen(line) - 1] == ']' && tc_found) 486 break; 487 /* test case section started, end of global data */ 488 else if (line[0] == '[' && line[strlen(line) - 1] == ']') 489 tc_data_start = 1; 490 491 /* test name unspecified, end after global data */ 492 if (tc_data_start && opts->test_name == NULL) 493 break; 494 /* searching for a suitable test */ 495 else if (tc_data_start && tc_found == 0) { 496 if (!strcmp(line, opts->test_name)) { 497 tc_found = 1; 498 continue; 499 } else 500 continue; 501 } 502 503 /* buffer for multiline */ 504 entry = (char *) rte_realloc(entry, 505 sizeof(char) * strlen(line) + 1, 0); 506 if (entry == NULL) 507 return -1; 508 509 strcpy(entry, line); 510 511 /* check if entry ends with , or = */ 512 if (entry[strlen(entry) - 1] == ',' 513 || entry[strlen(entry) - 1] == '=') { 514 while ((read = getline(&line, &len, fp)) != -1) { 515 trim_space(line); 516 517 /* extend entry about length of new line */ 518 char *entry_extended = (char *) rte_realloc( 519 entry, sizeof(char) 520 * (strlen(line) + strlen(entry)) 521 + 1, 0); 522 523 if (entry_extended == NULL) 524 goto err; 525 entry = entry_extended; 526 /* entry has been allocated accordingly */ 527 strcpy(&entry[strlen(entry)], line); 528 529 if (entry[strlen(entry) - 1] != ',') 530 break; 531 } 532 } 533 status = parse_entry(entry, vector, opts, tc_found); 534 if (status) { 535 printf("An error occurred while parsing!\n"); 536 goto err; 537 } 538 } 539 540 if (tc_found == 0 && opts->test_name != NULL) { 541 printf("Not found '%s' case in test file\n", opts->test_name); 542 goto err; 543 } 544 545 fclose(fp); 546 free(line); 547 rte_free(entry); 548 549 return 0; 550 551 err: 552 if (fp) 553 fclose(fp); 554 if (line) 555 free(line); 556 if (entry) 557 rte_free(entry); 558 559 return -1; 560 } 561 562 struct cperf_test_vector* 563 cperf_test_vector_get_from_file(struct cperf_options *opts) 564 { 565 int status; 566 struct cperf_test_vector *test_vector = NULL; 567 568 if (opts == NULL || opts->test_file == NULL) 569 return test_vector; 570 571 test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL, 572 sizeof(struct cperf_test_vector), 0); 573 if (test_vector == NULL) 574 return test_vector; 575 576 /* filling the vector with data from a file */ 577 status = parse_file(test_vector, opts); 578 if (status) { 579 free_test_vector(test_vector, opts); 580 return NULL; 581 } 582 583 /* other values not included in the file */ 584 test_vector->data.cipher_offset = 0; 585 test_vector->data.cipher_length = opts->max_buffer_size; 586 587 test_vector->data.auth_offset = 0; 588 test_vector->data.auth_length = opts->max_buffer_size; 589 590 return test_vector; 591 } 592