xref: /dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c (revision 1a4998dc4d9446c58e1813bb05b92b572edb381e)
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_virt2phy(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_virt2phy(
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 }
621