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