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