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