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