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