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