app/crypto-perf: fix FreeBSD build
[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         /* get key */
241         token = strtok(entry, CPERF_ENTRY_DELIMITER);
242         key_token = token;
243
244         /* get values for key */
245         token = strtok(NULL, CPERF_ENTRY_DELIMITER);
246         if (token == NULL) {
247                 printf("Expected 'key = values' but was '%.40s'..\n",
248                         key_token);
249                 return -1;
250         }
251
252         status = parse_values(token, &data, &data_length);
253         if (status)
254                 return -1;
255
256         /* compare keys */
257         if (strstr(key_token, "plaintext")) {
258                 rte_free(vector->plaintext.data);
259                 vector->plaintext.data = data;
260                 if (tc_found)
261                         vector->plaintext.length = data_length;
262                 else {
263                         if (opts->buffer_sz > data_length) {
264                                 printf("Global plaintext shorter than "
265                                         "buffer_sz\n");
266                                 return -1;
267                         }
268                         vector->plaintext.length = opts->buffer_sz;
269                 }
270
271         } else if (strstr(key_token, "cipher_key")) {
272                 rte_free(vector->cipher_key.data);
273                 vector->cipher_key.data = data;
274                 if (tc_found)
275                         vector->cipher_key.length = data_length;
276                 else {
277                         if (opts->cipher_key_sz > data_length) {
278                                 printf("Global cipher_key shorter than "
279                                         "cipher_key_sz\n");
280                                 return -1;
281                         }
282                         vector->cipher_key.length = opts->cipher_key_sz;
283                 }
284
285         } else if (strstr(key_token, "auth_key")) {
286                 rte_free(vector->auth_key.data);
287                 vector->auth_key.data = data;
288                 if (tc_found)
289                         vector->auth_key.length = data_length;
290                 else {
291                         if (opts->auth_key_sz > data_length) {
292                                 printf("Global auth_key shorter than "
293                                         "auth_key_sz\n");
294                                 return -1;
295                         }
296                         vector->auth_key.length = opts->auth_key_sz;
297                 }
298
299         } else if (strstr(key_token, "iv")) {
300                 rte_free(vector->iv.data);
301                 vector->iv.data = data;
302                 vector->iv.phys_addr = rte_malloc_virt2phy(vector->iv.data);
303                 if (tc_found)
304                         vector->iv.length = data_length;
305                 else {
306                         if (opts->cipher_iv_sz > data_length) {
307                                 printf("Global iv shorter than "
308                                         "cipher_iv_sz\n");
309                                 return -1;
310                         }
311                         vector->iv.length = opts->cipher_iv_sz;
312                 }
313
314         } else if (strstr(key_token, "ciphertext")) {
315                 rte_free(vector->ciphertext.data);
316                 vector->ciphertext.data = data;
317                 if (tc_found)
318                         vector->ciphertext.length = data_length;
319                 else {
320                         if (opts->buffer_sz > data_length) {
321                                 printf("Global ciphertext shorter than "
322                                         "buffer_sz\n");
323                                 return -1;
324                         }
325                         vector->ciphertext.length = opts->buffer_sz;
326                 }
327
328         } else if (strstr(key_token, "aad")) {
329                 rte_free(vector->aad.data);
330                 vector->aad.data = data;
331                 vector->aad.phys_addr = rte_malloc_virt2phy(vector->aad.data);
332                 if (tc_found)
333                         vector->aad.length = data_length;
334                 else {
335                         if (opts->auth_aad_sz > data_length) {
336                                 printf("Global aad shorter than "
337                                         "auth_aad_sz\n");
338                                 return -1;
339                         }
340                         vector->aad.length = opts->auth_aad_sz;
341                 }
342
343         } else if (strstr(key_token, "digest")) {
344                 rte_free(vector->digest.data);
345                 vector->digest.data = data;
346                 vector->digest.phys_addr = rte_malloc_virt2phy(
347                         vector->digest.data);
348                 if (tc_found)
349                         vector->digest.length = data_length;
350                 else {
351                         if (opts->auth_digest_sz > data_length) {
352                                 printf("Global digest shorter than "
353                                         "auth_digest_sz\n");
354                                 return -1;
355                         }
356                         vector->digest.length = opts->auth_digest_sz;
357                 }
358         } else {
359                 printf("Not valid key: '%s'\n", trim_space(key_token));
360                 return -1;
361         }
362
363         return 0;
364 }
365
366 /* searches in the file for test keys and values */
367 static int
368 parse_file(struct cperf_test_vector *vector, struct cperf_options *opts)
369 {
370         uint8_t tc_found = 0;
371         uint8_t tc_data_start = 0;
372         ssize_t read;
373         size_t len = 0;
374         int status = 0;
375
376         FILE *fp;
377         char *line = NULL;
378         char *entry = NULL;
379
380         fp = fopen(opts->test_file, "r");
381         if (fp == NULL) {
382                 printf("File %s does not exists\n", opts->test_file);
383                 return -1;
384         }
385
386         while ((read = getline(&line, &len, fp)) != -1) {
387
388                 /* ignore comments and new lines */
389                 if (line[0] == '#' || line[0] == '/' || line[0] == '\n'
390                         || line[0] == '\r' || line[0] == ' ')
391                         continue;
392
393                 trim_space(line);
394
395                 /* next test case is started */
396                 if (line[0] == '[' && line[strlen(line) - 1] == ']' && tc_found)
397                         break;
398                 /* test case section started, end of global data */
399                 else if (line[0] == '[' && line[strlen(line) - 1] == ']')
400                         tc_data_start = 1;
401
402                 /* test name unspecified, end after global data */
403                 if (tc_data_start && opts->test_name == NULL)
404                         break;
405                 /* searching for a suitable test */
406                 else if (tc_data_start && tc_found == 0) {
407                         if (!strcmp(line, opts->test_name)) {
408                                 tc_found = 1;
409                                 continue;
410                         } else
411                                 continue;
412                 }
413
414                 /* buffer for multiline */
415                 entry = (char *) rte_realloc(entry,
416                                         sizeof(char) * strlen(line) + 1, 0);
417                 if (entry == NULL)
418                         return -1;
419
420                 memset(entry, 0, strlen(line) + 1);
421                 strncpy(entry, line, strlen(line));
422
423                 /* check if entry ends with , or = */
424                 if (entry[strlen(entry) - 1] == ','
425                         || entry[strlen(entry) - 1] == '=') {
426                         while ((read = getline(&line, &len, fp)) != -1) {
427                                 trim_space(line);
428
429                                 /* extend entry about length of new line */
430                                 char *entry_extended = (char *) rte_realloc(
431                                         entry, sizeof(char)
432                                                 * (strlen(line) + strlen(entry))
433                                                 + 1, 0);
434
435                                 if (entry_extended == NULL)
436                                         goto err;
437                                 entry = entry_extended;
438
439                                 strncat(entry, line, strlen(line));
440
441                                 if (entry[strlen(entry) - 1] != ',')
442                                         break;
443                         }
444                 }
445                 status = parse_entry(entry, vector, opts, tc_found);
446                 if (status) {
447                         printf("An error occurred while parsing!\n");
448                         goto err;
449                 }
450         }
451
452         if (tc_found == 0 && opts->test_name != NULL) {
453                 printf("Not found '%s' case in test file\n", opts->test_name);
454                 goto err;
455         }
456
457         fclose(fp);
458         free(line);
459         rte_free(entry);
460
461         return 0;
462
463 err:
464         if (fp)
465                 fclose(fp);
466         if (line)
467                 free(line);
468         if (entry)
469                 rte_free(entry);
470
471         return -1;
472 }
473
474 struct cperf_test_vector*
475 cperf_test_vector_get_from_file(struct cperf_options *opts)
476 {
477         int status;
478         struct cperf_test_vector *test_vector = NULL;
479
480         if (opts == NULL || opts->test_file == NULL)
481                 return test_vector;
482
483         test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL,
484                 sizeof(struct cperf_test_vector), 0);
485         if (test_vector == NULL)
486                 return test_vector;
487
488         /* filling the vector with data from a file */
489         status = parse_file(test_vector, opts);
490         if (status) {
491                 free_test_vector(test_vector, opts);
492                 return NULL;
493         }
494
495         /* other values not included in the file */
496         test_vector->data.cipher_offset = 0;
497         test_vector->data.cipher_length = opts->buffer_sz;
498
499         test_vector->data.auth_offset = 0;
500         test_vector->data.auth_length = opts->buffer_sz;
501
502         return test_vector;
503 }