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
free_test_vector(struct cperf_test_vector * vector,struct cperf_options * opts)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
show_test_vector(struct cperf_test_vector * test_vector)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 *
trim_space(char * str)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
parse_values(char * tokens,uint8_t ** data,uint32_t * data_length)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
parse_entry(char * entry,struct cperf_test_vector * vector,struct cperf_options * opts,uint8_t tc_found)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
parse_file(struct cperf_test_vector * vector,struct cperf_options * opts)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*
cperf_test_vector_get_from_file(struct cperf_options * opts)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