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