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