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->cipher_iv.data) { 120 printf("\ncipher_iv =\n"); 121 for (i = 0; i < test_vector->cipher_iv.length; ++i) { 122 if ((i % wrap == 0) && (i != 0)) 123 printf("\n"); 124 if (i == (uint32_t)(test_vector->cipher_iv.length - 1)) 125 printf("0x%02x", test_vector->cipher_iv.data[i]); 126 else 127 printf("0x%02x, ", test_vector->cipher_iv.data[i]); 128 } 129 printf("\n"); 130 } 131 132 if (test_vector->auth_iv.data) { 133 printf("\nauth_iv =\n"); 134 for (i = 0; i < test_vector->auth_iv.length; ++i) { 135 if ((i % wrap == 0) && (i != 0)) 136 printf("\n"); 137 if (i == (uint32_t)(test_vector->auth_iv.length - 1)) 138 printf("0x%02x", test_vector->auth_iv.data[i]); 139 else 140 printf("0x%02x, ", test_vector->auth_iv.data[i]); 141 } 142 printf("\n"); 143 } 144 145 if (test_vector->ciphertext.data) { 146 printf("\nciphertext =\n"); 147 for (i = 0; i < test_vector->ciphertext.length; ++i) { 148 if ((i % wrap == 0) && (i != 0)) 149 printf("\n"); 150 if (i == test_vector->ciphertext.length - 1) 151 printf("0x%02x", 152 test_vector->ciphertext.data[i]); 153 else 154 printf("0x%02x, ", 155 test_vector->ciphertext.data[i]); 156 } 157 printf("\n"); 158 } 159 160 if (test_vector->aad.data) { 161 printf("\naad =\n"); 162 for (i = 0; i < test_vector->aad.length; ++i) { 163 if ((i % wrap == 0) && (i != 0)) 164 printf("\n"); 165 if (i == (uint32_t)(test_vector->aad.length - 1)) 166 printf("0x%02x", test_vector->aad.data[i]); 167 else 168 printf("0x%02x, ", test_vector->aad.data[i]); 169 } 170 printf("\n"); 171 } 172 173 if (test_vector->digest.data) { 174 printf("\ndigest =\n"); 175 for (i = 0; i < test_vector->digest.length; ++i) { 176 if ((i % wrap == 0) && (i != 0)) 177 printf("\n"); 178 if (i == (uint32_t)(test_vector->digest.length - 1)) 179 printf("0x%02x", test_vector->digest.data[i]); 180 else 181 printf("0x%02x, ", test_vector->digest.data[i]); 182 } 183 printf("\n"); 184 } 185 } 186 187 /* trim leading and trailing spaces */ 188 static char * 189 trim_space(char *str) 190 { 191 char *start, *end; 192 193 for (start = str; *start; start++) { 194 if (!isspace((unsigned char) start[0])) 195 break; 196 } 197 198 for (end = start + strlen(start); end > start + 1; end--) { 199 if (!isspace((unsigned char) end[-1])) 200 break; 201 } 202 203 *end = 0; 204 205 /* Shift from "start" to the beginning of the string */ 206 if (start > str) 207 memmove(str, start, (end - start) + 1); 208 209 return str; 210 } 211 212 /* tokenization test values separated by a comma */ 213 static int 214 parse_values(char *tokens, uint8_t **data, uint32_t *data_length) 215 { 216 uint32_t n_tokens; 217 uint32_t data_size = 32; 218 219 uint8_t *values, *values_resized; 220 char *tok, *error = NULL; 221 222 tok = strtok(tokens, CPERF_VALUE_DELIMITER); 223 if (tok == NULL) 224 return -1; 225 226 values = (uint8_t *) rte_zmalloc(NULL, sizeof(uint8_t) * data_size, 0); 227 if (values == NULL) 228 return -1; 229 230 n_tokens = 0; 231 while (tok != NULL) { 232 values_resized = NULL; 233 234 if (n_tokens >= data_size) { 235 data_size *= 2; 236 237 values_resized = (uint8_t *) rte_realloc(values, 238 sizeof(uint8_t) * data_size, 0); 239 if (values_resized == NULL) { 240 rte_free(values); 241 return -1; 242 } 243 values = values_resized; 244 } 245 246 values[n_tokens] = (uint8_t) strtoul(tok, &error, 0); 247 if ((error == NULL) || (*error != '\0')) { 248 printf("Failed with convert '%s'\n", tok); 249 rte_free(values); 250 return -1; 251 } 252 253 tok = strtok(NULL, CPERF_VALUE_DELIMITER); 254 if (tok == NULL) 255 break; 256 257 n_tokens++; 258 } 259 260 values_resized = (uint8_t *) rte_realloc(values, 261 sizeof(uint8_t) * (n_tokens + 1), 0); 262 263 if (values_resized == NULL) { 264 rte_free(values); 265 return -1; 266 } 267 268 *data = values_resized; 269 *data_length = n_tokens + 1; 270 271 return 0; 272 } 273 274 /* checks the type of key and assigns data */ 275 static int 276 parse_entry(char *entry, struct cperf_test_vector *vector, 277 struct cperf_options *opts, uint8_t tc_found) 278 { 279 int status; 280 uint32_t data_length; 281 282 uint8_t *data = NULL; 283 char *token, *key_token; 284 285 if (entry == NULL) { 286 printf("Expected entry value\n"); 287 return -1; 288 } 289 290 /* get key */ 291 token = strtok(entry, CPERF_ENTRY_DELIMITER); 292 key_token = token; 293 /* get values for key */ 294 token = strtok(NULL, CPERF_ENTRY_DELIMITER); 295 296 if (key_token == NULL || token == NULL) { 297 printf("Expected 'key = values' but was '%.40s'..\n", entry); 298 return -1; 299 } 300 301 status = parse_values(token, &data, &data_length); 302 if (status) 303 return -1; 304 305 /* compare keys */ 306 if (strstr(key_token, "plaintext")) { 307 rte_free(vector->plaintext.data); 308 vector->plaintext.data = data; 309 if (tc_found) 310 vector->plaintext.length = data_length; 311 else { 312 if (opts->max_buffer_size > data_length) { 313 printf("Global plaintext shorter than " 314 "buffer_sz\n"); 315 return -1; 316 } 317 vector->plaintext.length = opts->max_buffer_size; 318 } 319 320 } else if (strstr(key_token, "cipher_key")) { 321 rte_free(vector->cipher_key.data); 322 vector->cipher_key.data = data; 323 if (tc_found) 324 vector->cipher_key.length = data_length; 325 else { 326 if (opts->cipher_key_sz > data_length) { 327 printf("Global cipher_key shorter than " 328 "cipher_key_sz\n"); 329 return -1; 330 } 331 vector->cipher_key.length = opts->cipher_key_sz; 332 } 333 334 } else if (strstr(key_token, "auth_key")) { 335 rte_free(vector->auth_key.data); 336 vector->auth_key.data = data; 337 if (tc_found) 338 vector->auth_key.length = data_length; 339 else { 340 if (opts->auth_key_sz > data_length) { 341 printf("Global auth_key shorter than " 342 "auth_key_sz\n"); 343 return -1; 344 } 345 vector->auth_key.length = opts->auth_key_sz; 346 } 347 348 } else if (strstr(key_token, "cipher_iv")) { 349 rte_free(vector->cipher_iv.data); 350 vector->cipher_iv.data = data; 351 if (tc_found) 352 vector->cipher_iv.length = data_length; 353 else { 354 if (opts->cipher_iv_sz > data_length) { 355 printf("Global cipher iv shorter than " 356 "cipher_iv_sz\n"); 357 return -1; 358 } 359 vector->cipher_iv.length = opts->cipher_iv_sz; 360 } 361 362 } else if (strstr(key_token, "auth_iv")) { 363 rte_free(vector->auth_iv.data); 364 vector->auth_iv.data = data; 365 if (tc_found) 366 vector->auth_iv.length = data_length; 367 else { 368 if (opts->auth_iv_sz > data_length) { 369 printf("Global auth iv shorter than " 370 "auth_iv_sz\n"); 371 return -1; 372 } 373 vector->auth_iv.length = opts->auth_iv_sz; 374 } 375 376 } else if (strstr(key_token, "ciphertext")) { 377 rte_free(vector->ciphertext.data); 378 vector->ciphertext.data = data; 379 if (tc_found) 380 vector->ciphertext.length = data_length; 381 else { 382 if (opts->max_buffer_size > data_length) { 383 printf("Global ciphertext shorter than " 384 "buffer_sz\n"); 385 return -1; 386 } 387 vector->ciphertext.length = opts->max_buffer_size; 388 } 389 390 } else if (strstr(key_token, "aad")) { 391 rte_free(vector->aad.data); 392 vector->aad.data = data; 393 vector->aad.phys_addr = rte_malloc_virt2phy(vector->aad.data); 394 if (tc_found) 395 vector->aad.length = data_length; 396 else { 397 if (opts->aead_aad_sz > data_length) { 398 printf("Global aad shorter than " 399 "aead_aad_sz\n"); 400 return -1; 401 } 402 vector->aad.length = opts->aead_aad_sz; 403 } 404 405 } else if (strstr(key_token, "digest")) { 406 rte_free(vector->digest.data); 407 vector->digest.data = data; 408 vector->digest.phys_addr = rte_malloc_virt2phy( 409 vector->digest.data); 410 if (tc_found) 411 vector->digest.length = data_length; 412 else { 413 if (opts->digest_sz > data_length) { 414 printf("Global digest shorter than " 415 "digest_sz\n"); 416 return -1; 417 } 418 vector->digest.length = opts->digest_sz; 419 } 420 } else { 421 printf("Not valid key: '%s'\n", trim_space(key_token)); 422 return -1; 423 } 424 425 return 0; 426 } 427 428 /* searches in the file for test keys and values */ 429 static int 430 parse_file(struct cperf_test_vector *vector, struct cperf_options *opts) 431 { 432 uint8_t tc_found = 0; 433 uint8_t tc_data_start = 0; 434 ssize_t read; 435 size_t len = 0; 436 int status = 0; 437 438 FILE *fp; 439 char *line = NULL; 440 char *entry = NULL; 441 442 fp = fopen(opts->test_file, "r"); 443 if (fp == NULL) { 444 printf("File %s does not exists\n", opts->test_file); 445 return -1; 446 } 447 448 while ((read = getline(&line, &len, fp)) != -1) { 449 450 /* ignore comments and new lines */ 451 if (line[0] == '#' || line[0] == '/' || line[0] == '\n' 452 || line[0] == '\r' || line[0] == ' ') 453 continue; 454 455 trim_space(line); 456 457 /* next test case is started */ 458 if (line[0] == '[' && line[strlen(line) - 1] == ']' && tc_found) 459 break; 460 /* test case section started, end of global data */ 461 else if (line[0] == '[' && line[strlen(line) - 1] == ']') 462 tc_data_start = 1; 463 464 /* test name unspecified, end after global data */ 465 if (tc_data_start && opts->test_name == NULL) 466 break; 467 /* searching for a suitable test */ 468 else if (tc_data_start && tc_found == 0) { 469 if (!strcmp(line, opts->test_name)) { 470 tc_found = 1; 471 continue; 472 } else 473 continue; 474 } 475 476 /* buffer for multiline */ 477 entry = (char *) rte_realloc(entry, 478 sizeof(char) * strlen(line) + 1, 0); 479 if (entry == NULL) 480 return -1; 481 482 memset(entry, 0, strlen(line) + 1); 483 strncpy(entry, line, strlen(line)); 484 485 /* check if entry ends with , or = */ 486 if (entry[strlen(entry) - 1] == ',' 487 || entry[strlen(entry) - 1] == '=') { 488 while ((read = getline(&line, &len, fp)) != -1) { 489 trim_space(line); 490 491 /* extend entry about length of new line */ 492 char *entry_extended = (char *) rte_realloc( 493 entry, sizeof(char) 494 * (strlen(line) + strlen(entry)) 495 + 1, 0); 496 497 if (entry_extended == NULL) 498 goto err; 499 entry = entry_extended; 500 501 strncat(entry, line, strlen(line)); 502 503 if (entry[strlen(entry) - 1] != ',') 504 break; 505 } 506 } 507 status = parse_entry(entry, vector, opts, tc_found); 508 if (status) { 509 printf("An error occurred while parsing!\n"); 510 goto err; 511 } 512 } 513 514 if (tc_found == 0 && opts->test_name != NULL) { 515 printf("Not found '%s' case in test file\n", opts->test_name); 516 goto err; 517 } 518 519 fclose(fp); 520 free(line); 521 rte_free(entry); 522 523 return 0; 524 525 err: 526 if (fp) 527 fclose(fp); 528 if (line) 529 free(line); 530 if (entry) 531 rte_free(entry); 532 533 return -1; 534 } 535 536 struct cperf_test_vector* 537 cperf_test_vector_get_from_file(struct cperf_options *opts) 538 { 539 int status; 540 struct cperf_test_vector *test_vector = NULL; 541 542 if (opts == NULL || opts->test_file == NULL) 543 return test_vector; 544 545 test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL, 546 sizeof(struct cperf_test_vector), 0); 547 if (test_vector == NULL) 548 return test_vector; 549 550 /* filling the vector with data from a file */ 551 status = parse_file(test_vector, opts); 552 if (status) { 553 free_test_vector(test_vector, opts); 554 return NULL; 555 } 556 557 /* other values not included in the file */ 558 test_vector->data.cipher_offset = 0; 559 test_vector->data.cipher_length = opts->max_buffer_size; 560 561 test_vector->data.auth_offset = 0; 562 test_vector->data.auth_length = opts->max_buffer_size; 563 564 return test_vector; 565 } 566