New upstream version 17.11-rc3
[deb_dpdk.git] / app / test-crypto-perf / cperf_test_vector_parsing.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of Intel Corporation nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 #ifdef RTE_EXEC_ENV_BSDAPP
33         #define _WITH_GETLINE
34 #endif
35 #include <stdio.h>
36
37 #include <rte_malloc.h>
38
39 #include "cperf_options.h"
40 #include "cperf_test_vectors.h"
41 #include "cperf_test_vector_parsing.h"
42
43 int
44 free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts)
45 {
46         if (vector == NULL || opts == NULL)
47                 return -1;
48
49         rte_free(vector->cipher_iv.data);
50         rte_free(vector->auth_iv.data);
51         rte_free(vector->aad.data);
52         rte_free(vector->digest.data);
53
54         if (opts->test_file != NULL) {
55                 rte_free(vector->plaintext.data);
56                 rte_free(vector->cipher_key.data);
57                 rte_free(vector->auth_key.data);
58                 rte_free(vector->ciphertext.data);
59         }
60
61         rte_free(vector);
62
63         return 0;
64 }
65
66 void
67 show_test_vector(struct cperf_test_vector *test_vector)
68 {
69         const uint8_t wrap = 32;
70         uint32_t i;
71
72         if (test_vector == NULL)
73                 return;
74
75         if (test_vector->plaintext.data) {
76                 printf("\nplaintext =\n");
77                 for (i = 0; i < test_vector->plaintext.length; ++i) {
78                         if ((i % wrap == 0) && (i != 0))
79                                 printf("\n");
80                         if (i == test_vector->plaintext.length - 1)
81                                 printf("0x%02x",
82                                         test_vector->plaintext.data[i]);
83                         else
84                                 printf("0x%02x, ",
85                                         test_vector->plaintext.data[i]);
86                 }
87                 printf("\n");
88         }
89
90         if (test_vector->cipher_key.data) {
91                 printf("\ncipher_key =\n");
92                 for (i = 0; i < test_vector->cipher_key.length; ++i) {
93                         if ((i % wrap == 0) && (i != 0))
94                                 printf("\n");
95                         if (i == (uint32_t)(test_vector->cipher_key.length - 1))
96                                 printf("0x%02x",
97                                         test_vector->cipher_key.data[i]);
98                         else
99                                 printf("0x%02x, ",
100                                         test_vector->cipher_key.data[i]);
101                 }
102                 printf("\n");
103         }
104
105         if (test_vector->auth_key.data) {
106                 printf("\nauth_key =\n");
107                 for (i = 0; i < test_vector->auth_key.length; ++i) {
108                         if ((i % wrap == 0) && (i != 0))
109                                 printf("\n");
110                         if (i == (uint32_t)(test_vector->auth_key.length - 1))
111                                 printf("0x%02x", test_vector->auth_key.data[i]);
112                         else
113                                 printf("0x%02x, ",
114                                         test_vector->auth_key.data[i]);
115                 }
116                 printf("\n");
117         }
118
119         if (test_vector->aead_key.data) {
120                 printf("\naead_key =\n");
121                 for (i = 0; i < test_vector->aead_key.length; ++i) {
122                         if ((i % wrap == 0) && (i != 0))
123                                 printf("\n");
124                         if (i == (uint32_t)(test_vector->aead_key.length - 1))
125                                 printf("0x%02x", test_vector->aead_key.data[i]);
126                         else
127                                 printf("0x%02x, ",
128                                         test_vector->aead_key.data[i]);
129                 }
130                 printf("\n");
131         }
132
133         if (test_vector->cipher_iv.data) {
134                 printf("\ncipher_iv =\n");
135                 for (i = 0; i < test_vector->cipher_iv.length; ++i) {
136                         if ((i % wrap == 0) && (i != 0))
137                                 printf("\n");
138                         if (i == (uint32_t)(test_vector->cipher_iv.length - 1))
139                                 printf("0x%02x", test_vector->cipher_iv.data[i]);
140                         else
141                                 printf("0x%02x, ", test_vector->cipher_iv.data[i]);
142                 }
143                 printf("\n");
144         }
145
146         if (test_vector->auth_iv.data) {
147                 printf("\nauth_iv =\n");
148                 for (i = 0; i < test_vector->auth_iv.length; ++i) {
149                         if ((i % wrap == 0) && (i != 0))
150                                 printf("\n");
151                         if (i == (uint32_t)(test_vector->auth_iv.length - 1))
152                                 printf("0x%02x", test_vector->auth_iv.data[i]);
153                         else
154                                 printf("0x%02x, ", test_vector->auth_iv.data[i]);
155                 }
156                 printf("\n");
157         }
158
159         if (test_vector->aead_iv.data) {
160                 printf("\naead_iv =\n");
161                 for (i = 0; i < test_vector->aead_iv.length; ++i) {
162                         if ((i % wrap == 0) && (i != 0))
163                                 printf("\n");
164                         if (i == (uint32_t)(test_vector->aead_iv.length - 1))
165                                 printf("0x%02x", test_vector->aead_iv.data[i]);
166                         else
167                                 printf("0x%02x, ", test_vector->aead_iv.data[i]);
168                 }
169                 printf("\n");
170         }
171
172         if (test_vector->ciphertext.data) {
173                 printf("\nciphertext =\n");
174                 for (i = 0; i < test_vector->ciphertext.length; ++i) {
175                         if ((i % wrap == 0) && (i != 0))
176                                 printf("\n");
177                         if (i == test_vector->ciphertext.length - 1)
178                                 printf("0x%02x",
179                                         test_vector->ciphertext.data[i]);
180                         else
181                                 printf("0x%02x, ",
182                                         test_vector->ciphertext.data[i]);
183                 }
184                 printf("\n");
185         }
186
187         if (test_vector->aad.data) {
188                 printf("\naad =\n");
189                 for (i = 0; i < test_vector->aad.length; ++i) {
190                         if ((i % wrap == 0) && (i != 0))
191                                 printf("\n");
192                         if (i == (uint32_t)(test_vector->aad.length - 1))
193                                 printf("0x%02x", test_vector->aad.data[i]);
194                         else
195                                 printf("0x%02x, ", test_vector->aad.data[i]);
196                 }
197                 printf("\n");
198         }
199
200         if (test_vector->digest.data) {
201                 printf("\ndigest =\n");
202                 for (i = 0; i < test_vector->digest.length; ++i) {
203                         if ((i % wrap == 0) && (i != 0))
204                                 printf("\n");
205                         if (i == (uint32_t)(test_vector->digest.length - 1))
206                                 printf("0x%02x", test_vector->digest.data[i]);
207                         else
208                                 printf("0x%02x, ", test_vector->digest.data[i]);
209                 }
210                 printf("\n");
211         }
212 }
213
214 /* trim leading and trailing spaces */
215 static char *
216 trim_space(char *str)
217 {
218         char *start, *end;
219
220         for (start = str; *start; start++) {
221                 if (!isspace((unsigned char) start[0]))
222                         break;
223         }
224
225         for (end = start + strlen(start); end > start + 1; end--) {
226                 if (!isspace((unsigned char) end[-1]))
227                         break;
228         }
229
230         *end = 0;
231
232         /* Shift from "start" to the beginning of the string */
233         if (start > str)
234                 memmove(str, start, (end - start) + 1);
235
236         return str;
237 }
238
239 /* tokenization test values separated by a comma */
240 static int
241 parse_values(char *tokens, uint8_t **data, uint32_t *data_length)
242 {
243         uint32_t n_tokens;
244         uint32_t data_size = 32;
245
246         uint8_t *values, *values_resized;
247         char *tok, *error = NULL;
248
249         tok = strtok(tokens, CPERF_VALUE_DELIMITER);
250         if (tok == NULL)
251                 return -1;
252
253         values = (uint8_t *) rte_zmalloc(NULL, sizeof(uint8_t) * data_size, 0);
254         if (values == NULL)
255                 return -1;
256
257         n_tokens = 0;
258         while (tok != NULL) {
259                 values_resized = NULL;
260
261                 if (n_tokens >= data_size) {
262                         data_size *= 2;
263
264                         values_resized = (uint8_t *) rte_realloc(values,
265                                 sizeof(uint8_t) * data_size, 0);
266                         if (values_resized == NULL) {
267                                 rte_free(values);
268                                 return -1;
269                         }
270                         values = values_resized;
271                 }
272
273                 values[n_tokens] = (uint8_t) strtoul(tok, &error, 0);
274                 if ((error == NULL) || (*error != '\0')) {
275                         printf("Failed with convert '%s'\n", tok);
276                         rte_free(values);
277                         return -1;
278                 }
279
280                 tok = strtok(NULL, CPERF_VALUE_DELIMITER);
281                 if (tok == NULL)
282                         break;
283
284                 n_tokens++;
285         }
286
287         values_resized = (uint8_t *) rte_realloc(values,
288                 sizeof(uint8_t) * (n_tokens + 1), 0);
289
290         if (values_resized == NULL) {
291                 rte_free(values);
292                 return -1;
293         }
294
295         *data = values_resized;
296         *data_length = n_tokens + 1;
297
298         return 0;
299 }
300
301 /* checks the type of key and assigns data */
302 static int
303 parse_entry(char *entry, struct cperf_test_vector *vector,
304         struct cperf_options *opts, uint8_t tc_found)
305 {
306         int status;
307         uint32_t data_length;
308
309         uint8_t *data = NULL;
310         char *token, *key_token;
311
312         if (entry == NULL) {
313                 printf("Expected entry value\n");
314                 return -1;
315         }
316
317         /* get key */
318         token = strtok(entry, CPERF_ENTRY_DELIMITER);
319         key_token = token;
320         /* get values for key */
321         token = strtok(NULL, CPERF_ENTRY_DELIMITER);
322
323         if (key_token == NULL || token == NULL) {
324                 printf("Expected 'key = values' but was '%.40s'..\n", entry);
325                 return -1;
326         }
327
328         status = parse_values(token, &data, &data_length);
329         if (status)
330                 return -1;
331
332         /* compare keys */
333         if (strstr(key_token, "plaintext")) {
334                 rte_free(vector->plaintext.data);
335                 vector->plaintext.data = data;
336                 if (tc_found)
337                         vector->plaintext.length = data_length;
338                 else {
339                         if (opts->max_buffer_size > data_length) {
340                                 printf("Global plaintext shorter than "
341                                         "buffer_sz\n");
342                                 return -1;
343                         }
344                         vector->plaintext.length = opts->max_buffer_size;
345                 }
346
347         } else if (strstr(key_token, "cipher_key")) {
348                 rte_free(vector->cipher_key.data);
349                 vector->cipher_key.data = data;
350                 if (tc_found)
351                         vector->cipher_key.length = data_length;
352                 else {
353                         if (opts->cipher_key_sz > data_length) {
354                                 printf("Global cipher_key shorter than "
355                                         "cipher_key_sz\n");
356                                 return -1;
357                         }
358                         vector->cipher_key.length = opts->cipher_key_sz;
359                 }
360
361         } else if (strstr(key_token, "auth_key")) {
362                 rte_free(vector->auth_key.data);
363                 vector->auth_key.data = data;
364                 if (tc_found)
365                         vector->auth_key.length = data_length;
366                 else {
367                         if (opts->auth_key_sz > data_length) {
368                                 printf("Global auth_key shorter than "
369                                         "auth_key_sz\n");
370                                 return -1;
371                         }
372                         vector->auth_key.length = opts->auth_key_sz;
373                 }
374
375         } else if (strstr(key_token, "aead_key")) {
376                 rte_free(vector->aead_key.data);
377                 vector->aead_key.data = data;
378                 if (tc_found)
379                         vector->aead_key.length = data_length;
380                 else {
381                         if (opts->aead_key_sz > data_length) {
382                                 printf("Global aead_key shorter than "
383                                         "aead_key_sz\n");
384                                 return -1;
385                         }
386                         vector->aead_key.length = opts->aead_key_sz;
387                 }
388
389         } else if (strstr(key_token, "cipher_iv")) {
390                 rte_free(vector->cipher_iv.data);
391                 vector->cipher_iv.data = data;
392                 if (tc_found)
393                         vector->cipher_iv.length = data_length;
394                 else {
395                         if (opts->cipher_iv_sz > data_length) {
396                                 printf("Global cipher iv shorter than "
397                                         "cipher_iv_sz\n");
398                                 return -1;
399                         }
400                         vector->cipher_iv.length = opts->cipher_iv_sz;
401                 }
402
403         } else if (strstr(key_token, "auth_iv")) {
404                 rte_free(vector->auth_iv.data);
405                 vector->auth_iv.data = data;
406                 if (tc_found)
407                         vector->auth_iv.length = data_length;
408                 else {
409                         if (opts->auth_iv_sz > data_length) {
410                                 printf("Global auth iv shorter than "
411                                         "auth_iv_sz\n");
412                                 return -1;
413                         }
414                         vector->auth_iv.length = opts->auth_iv_sz;
415                 }
416
417         } else if (strstr(key_token, "aead_iv")) {
418                 rte_free(vector->aead_iv.data);
419                 vector->aead_iv.data = data;
420                 if (tc_found)
421                         vector->aead_iv.length = data_length;
422                 else {
423                         if (opts->aead_iv_sz > data_length) {
424                                 printf("Global aead iv shorter than "
425                                         "aead_iv_sz\n");
426                                 return -1;
427                         }
428                         vector->aead_iv.length = opts->aead_iv_sz;
429                 }
430
431         } else if (strstr(key_token, "ciphertext")) {
432                 rte_free(vector->ciphertext.data);
433                 vector->ciphertext.data = data;
434                 if (tc_found)
435                         vector->ciphertext.length = data_length;
436                 else {
437                         if (opts->max_buffer_size > data_length) {
438                                 printf("Global ciphertext shorter than "
439                                         "buffer_sz\n");
440                                 return -1;
441                         }
442                         vector->ciphertext.length = opts->max_buffer_size;
443                 }
444
445         } else if (strstr(key_token, "aad")) {
446                 rte_free(vector->aad.data);
447                 vector->aad.data = data;
448                 vector->aad.phys_addr = rte_malloc_virt2iova(vector->aad.data);
449                 if (tc_found)
450                         vector->aad.length = data_length;
451                 else {
452                         if (opts->aead_aad_sz > data_length) {
453                                 printf("Global aad shorter than "
454                                         "aead_aad_sz\n");
455                                 return -1;
456                         }
457                         vector->aad.length = opts->aead_aad_sz;
458                 }
459
460         } else if (strstr(key_token, "digest")) {
461                 rte_free(vector->digest.data);
462                 vector->digest.data = data;
463                 vector->digest.phys_addr = rte_malloc_virt2iova(
464                         vector->digest.data);
465                 if (tc_found)
466                         vector->digest.length = data_length;
467                 else {
468                         if (opts->digest_sz > data_length) {
469                                 printf("Global digest shorter than "
470                                         "digest_sz\n");
471                                 return -1;
472                         }
473                         vector->digest.length = opts->digest_sz;
474                 }
475         } else {
476                 printf("Not valid key: '%s'\n", trim_space(key_token));
477                 return -1;
478         }
479
480         return 0;
481 }
482
483 /* searches in the file for test keys and values */
484 static int
485 parse_file(struct cperf_test_vector *vector, struct cperf_options *opts)
486 {
487         uint8_t tc_found = 0;
488         uint8_t tc_data_start = 0;
489         ssize_t read;
490         size_t len = 0;
491         int status = 0;
492
493         FILE *fp;
494         char *line = NULL;
495         char *entry = NULL;
496
497         fp = fopen(opts->test_file, "r");
498         if (fp == NULL) {
499                 printf("File %s does not exists\n", opts->test_file);
500                 return -1;
501         }
502
503         while ((read = getline(&line, &len, fp)) != -1) {
504
505                 /* ignore comments and new lines */
506                 if (line[0] == '#' || line[0] == '/' || line[0] == '\n'
507                         || line[0] == '\r' || line[0] == ' ')
508                         continue;
509
510                 trim_space(line);
511
512                 /* next test case is started */
513                 if (line[0] == '[' && line[strlen(line) - 1] == ']' && tc_found)
514                         break;
515                 /* test case section started, end of global data */
516                 else if (line[0] == '[' && line[strlen(line) - 1] == ']')
517                         tc_data_start = 1;
518
519                 /* test name unspecified, end after global data */
520                 if (tc_data_start && opts->test_name == NULL)
521                         break;
522                 /* searching for a suitable test */
523                 else if (tc_data_start && tc_found == 0) {
524                         if (!strcmp(line, opts->test_name)) {
525                                 tc_found = 1;
526                                 continue;
527                         } else
528                                 continue;
529                 }
530
531                 /* buffer for multiline */
532                 entry = (char *) rte_realloc(entry,
533                                         sizeof(char) * strlen(line) + 1, 0);
534                 if (entry == NULL)
535                         return -1;
536
537                 memset(entry, 0, strlen(line) + 1);
538                 strncpy(entry, line, strlen(line));
539
540                 /* check if entry ends with , or = */
541                 if (entry[strlen(entry) - 1] == ','
542                         || entry[strlen(entry) - 1] == '=') {
543                         while ((read = getline(&line, &len, fp)) != -1) {
544                                 trim_space(line);
545
546                                 /* extend entry about length of new line */
547                                 char *entry_extended = (char *) rte_realloc(
548                                         entry, sizeof(char)
549                                                 * (strlen(line) + strlen(entry))
550                                                 + 1, 0);
551
552                                 if (entry_extended == NULL)
553                                         goto err;
554                                 entry = entry_extended;
555
556                                 strncat(entry, line, strlen(line));
557
558                                 if (entry[strlen(entry) - 1] != ',')
559                                         break;
560                         }
561                 }
562                 status = parse_entry(entry, vector, opts, tc_found);
563                 if (status) {
564                         printf("An error occurred while parsing!\n");
565                         goto err;
566                 }
567         }
568
569         if (tc_found == 0 && opts->test_name != NULL) {
570                 printf("Not found '%s' case in test file\n", opts->test_name);
571                 goto err;
572         }
573
574         fclose(fp);
575         free(line);
576         rte_free(entry);
577
578         return 0;
579
580 err:
581         if (fp)
582                 fclose(fp);
583         if (line)
584                 free(line);
585         if (entry)
586                 rte_free(entry);
587
588         return -1;
589 }
590
591 struct cperf_test_vector*
592 cperf_test_vector_get_from_file(struct cperf_options *opts)
593 {
594         int status;
595         struct cperf_test_vector *test_vector = NULL;
596
597         if (opts == NULL || opts->test_file == NULL)
598                 return test_vector;
599
600         test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL,
601                 sizeof(struct cperf_test_vector), 0);
602         if (test_vector == NULL)
603                 return test_vector;
604
605         /* filling the vector with data from a file */
606         status = parse_file(test_vector, opts);
607         if (status) {
608                 free_test_vector(test_vector, opts);
609                 return NULL;
610         }
611
612         /* other values not included in the file */
613         test_vector->data.cipher_offset = 0;
614         test_vector->data.cipher_length = opts->max_buffer_size;
615
616         test_vector->data.auth_offset = 0;
617         test_vector->data.auth_length = opts->max_buffer_size;
618
619         return test_vector;
620 }