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