New upstream version 18.08
[deb_dpdk.git] / app / test-crypto-perf / cperf_test_vector_parsing.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016-2017 Intel Corporation
3  */
4 #ifdef RTE_EXEC_ENV_BSDAPP
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
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
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 *
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
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
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
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*
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 }