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