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