xref: /dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c (revision b79e4c00af0e7cfb8601ab0208659d226b82bd10)
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 }
566