]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/dpdk/examples/fips_validation/fips_validation.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / dpdk / examples / fips_validation / fips_validation.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
3 */
4
5 #include <stdio.h>
6 #include <string.h>
7
8 #include <rte_string_fns.h>
9 #include <rte_cryptodev.h>
10 #include <rte_malloc.h>
11
12 #include "fips_validation.h"
13
14 #define skip_white_spaces(pos) \
15 ({ \
16 __typeof__(pos) _p = (pos); \
17 for ( ; isspace(*_p); _p++) \
18 ; \
19 _p; \
20 })
21
22 static int
23 get_file_line(void)
24 {
25 FILE *fp = info.fp_rd;
26 char *line = info.one_line_text;
27 int ret;
28 uint32_t loc = 0;
29
30 memset(line, 0, MAX_LINE_CHAR);
31 while ((ret = fgetc(fp)) != EOF) {
32 char c = (char)ret;
33
34 if (loc >= MAX_LINE_CHAR - 1)
35 return -ENOMEM;
36 if (c == '\n')
37 break;
38 line[loc++] = c;
39 }
40
41 if (ret == EOF)
42 return -EOF;
43
44 return 0;
45 }
46
47 int
48 fips_test_fetch_one_block(void)
49 {
50 size_t size;
51 int ret = 0;
52 uint32_t i;
53
54 for (i = 0; i < info.nb_vec_lines; i++) {
55 free(info.vec[i]);
56 info.vec[i] = NULL;
57 }
58
59 i = 0;
60 do {
61 if (i >= MAX_LINE_PER_VECTOR) {
62 ret = -ENOMEM;
63 goto error_exit;
64 }
65
66 ret = get_file_line();
67 size = strlen(info.one_line_text);
68 if (size == 0)
69 break;
70
71 info.vec[i] = calloc(1, size + 5);
72 if (info.vec[i] == NULL)
73 goto error_exit;
74
75 strlcpy(info.vec[i], info.one_line_text, size + 1);
76 i++;
77 } while (ret == 0);
78
79 info.nb_vec_lines = i;
80
81 return ret;
82
83 error_exit:
84 for (i = 0; i < MAX_LINE_PER_VECTOR; i++)
85 if (info.vec[i] != NULL) {
86 free(info.vec[i]);
87 info.vec[i] = NULL;
88 }
89
90 info.nb_vec_lines = 0;
91
92 return -ENOMEM;
93 }
94
95 static int
96 fips_test_parse_header(void)
97 {
98 uint32_t i;
99 char *tmp;
100 int ret;
101 int algo_parsed = 0;
102 time_t t = time(NULL);
103 struct tm *tm_now = localtime(&t);
104
105 ret = fips_test_fetch_one_block();
106 if (ret < 0)
107 return ret;
108
109 for (i = 0; i < info.nb_vec_lines; i++) {
110 if (!algo_parsed) {
111 if (strstr(info.vec[i], "AESVS")) {
112 algo_parsed = 1;
113 info.algo = FIPS_TEST_ALGO_AES;
114 ret = parse_test_aes_init();
115 if (ret < 0)
116 return ret;
117 } else if (strstr(info.vec[i], "GCM")) {
118 algo_parsed = 1;
119 info.algo = FIPS_TEST_ALGO_AES_GCM;
120 ret = parse_test_gcm_init();
121 if (ret < 0)
122 return ret;
123 } else if (strstr(info.vec[i], "CMAC")) {
124 algo_parsed = 1;
125 info.algo = FIPS_TEST_ALGO_AES_CMAC;
126 ret = parse_test_cmac_init();
127 if (ret < 0)
128 return 0;
129 } else if (strstr(info.vec[i], "CCM")) {
130 algo_parsed = 1;
131 info.algo = FIPS_TEST_ALGO_AES_CCM;
132 ret = parse_test_ccm_init();
133 if (ret < 0)
134 return 0;
135 } else if (strstr(info.vec[i], "HMAC")) {
136 algo_parsed = 1;
137 info.algo = FIPS_TEST_ALGO_HMAC;
138 ret = parse_test_hmac_init();
139 if (ret < 0)
140 return ret;
141 } else if (strstr(info.vec[i], "TDES")) {
142 algo_parsed = 1;
143 info.algo = FIPS_TEST_ALGO_TDES;
144 ret = parse_test_tdes_init();
145 if (ret < 0)
146 return 0;
147 } else if (strstr(info.vec[i], "SHA-")) {
148 algo_parsed = 1;
149 info.algo = FIPS_TEST_ALGO_SHA;
150 ret = parse_test_sha_init();
151 if (ret < 0)
152 return ret;
153 }
154 }
155
156 tmp = strstr(info.vec[i], "# Config info for ");
157 if (tmp != NULL) {
158 fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ",
159 info.device_name);
160 continue;
161 }
162
163 tmp = strstr(info.vec[i], "# HMAC information for ");
164 if (tmp != NULL) {
165 fprintf(info.fp_wr, "%s%s\n", "# HMAC information for "
166 "DPDK Cryptodev ",
167 info.device_name);
168 continue;
169 }
170
171 tmp = strstr(info.vec[i], "# Config Info for : ");
172 if (tmp != NULL) {
173
174 fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ",
175 info.device_name);
176 continue;
177 }
178
179 tmp = strstr(info.vec[i], "# information for ");
180 if (tmp != NULL) {
181
182 char tmp_output[128] = {0};
183
184 strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
185
186 fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
187 "information for DPDK Cryptodev ",
188 info.device_name);
189 continue;
190 }
191
192 tmp = strstr(info.vec[i], " test information for ");
193 if (tmp != NULL) {
194 char tmp_output[128] = {0};
195
196 strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
197
198 fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
199 "test information for DPDK Cryptodev ",
200 info.device_name);
201 continue;
202 }
203
204 tmp = strstr(info.vec[i], "\" information for \"");
205 if (tmp != NULL) {
206 char tmp_output[128] = {0};
207
208 strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
209
210 fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
211 "\" information for DPDK Cryptodev ",
212 info.device_name);
213 continue;
214 }
215
216 if (i == info.nb_vec_lines - 1) {
217 /** update the time as current time, write to file */
218 fprintf(info.fp_wr, "%s%s\n", "# Generated on ",
219 asctime(tm_now));
220 continue;
221 }
222
223 /* to this point, no field need to update,
224 * only copy to rsp file
225 */
226 fprintf(info.fp_wr, "%s\n", info.vec[i]);
227 }
228
229 return 0;
230 }
231
232 static int
233 parse_file_type(const char *path)
234 {
235 const char *tmp = path + strlen(path) - 3;
236
237 if (strstr(tmp, REQ_FILE_PERFIX))
238 info.file_type = FIPS_TYPE_REQ;
239 else if (strstr(tmp, RSP_FILE_PERFIX))
240 info.file_type = FIPS_TYPE_RSP;
241 else if (strstr(path, FAX_FILE_PERFIX))
242 info.file_type = FIPS_TYPE_FAX;
243 else
244 return -EINVAL;
245
246 return 0;
247 }
248
249 int
250 fips_test_init(const char *req_file_path, const char *rsp_file_path,
251 const char *device_name)
252 {
253 if (strcmp(req_file_path, rsp_file_path) == 0) {
254 RTE_LOG(ERR, USER1, "File paths cannot be the same\n");
255 return -EINVAL;
256 }
257
258 fips_test_clear();
259
260 info.algo = FIPS_TEST_ALGO_MAX;
261 if (parse_file_type(req_file_path) < 0) {
262 RTE_LOG(ERR, USER1, "File %s type not supported\n",
263 req_file_path);
264 return -EINVAL;
265 }
266
267 info.fp_rd = fopen(req_file_path, "r");
268 if (!info.fp_rd) {
269 RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path);
270 return -EINVAL;
271 }
272
273 info.fp_wr = fopen(rsp_file_path, "w");
274 if (!info.fp_wr) {
275 RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path);
276 return -EINVAL;
277 }
278
279 info.one_line_text = calloc(1, MAX_LINE_CHAR);
280 if (!info.one_line_text) {
281 RTE_LOG(ERR, USER1, "Insufficient memory\n");
282 return -ENOMEM;
283 }
284
285 strlcpy(info.device_name, device_name, sizeof(info.device_name));
286
287 if (fips_test_parse_header() < 0) {
288 RTE_LOG(ERR, USER1, "Failed parsing header\n");
289 return -1;
290 }
291
292 return 0;
293 }
294
295 void
296 fips_test_clear(void)
297 {
298 if (info.fp_rd)
299 fclose(info.fp_rd);
300 if (info.fp_wr)
301 fclose(info.fp_wr);
302 if (info.one_line_text)
303 free(info.one_line_text);
304 if (info.nb_vec_lines) {
305 uint32_t i;
306
307 for (i = 0; i < info.nb_vec_lines; i++)
308 free(info.vec[i]);
309 }
310
311 memset(&info, 0, sizeof(info));
312 }
313
314 int
315 fips_test_parse_one_case(void)
316 {
317 uint32_t i, j = 0;
318 uint32_t is_interim = 0;
319 int ret;
320
321 if (info.interim_callbacks) {
322 for (i = 0; i < info.nb_vec_lines; i++) {
323 for (j = 0; info.interim_callbacks[j].key != NULL; j++)
324 if (strstr(info.vec[i],
325 info.interim_callbacks[j].key)) {
326 is_interim = 1;
327
328 ret = info.interim_callbacks[j].cb(
329 info.interim_callbacks[j].key,
330 info.vec[i],
331 info.interim_callbacks[j].val);
332 if (ret < 0)
333 return ret;
334 }
335 }
336 }
337
338 if (is_interim) {
339 for (i = 0; i < info.nb_vec_lines; i++)
340 fprintf(info.fp_wr, "%s\n", info.vec[i]);
341 fprintf(info.fp_wr, "\n");
342 return 1;
343 }
344
345 for (i = 0; i < info.nb_vec_lines; i++) {
346 for (j = 0; info.callbacks[j].key != NULL; j++)
347 if (strstr(info.vec[i], info.callbacks[j].key)) {
348 ret = info.callbacks[j].cb(
349 info.callbacks[j].key,
350 info.vec[i], info.callbacks[j].val);
351 if (ret < 0)
352 return ret;
353 break;
354 }
355 }
356
357 return 0;
358 }
359
360 void
361 fips_test_write_one_case(void)
362 {
363 uint32_t i;
364
365 for (i = 0; i < info.nb_vec_lines; i++)
366 fprintf(info.fp_wr, "%s\n", info.vec[i]);
367 }
368
369 static int
370 parser_read_uint64_hex(uint64_t *value, const char *p)
371 {
372 char *next;
373 uint64_t val;
374
375 p = skip_white_spaces(p);
376
377 val = strtoul(p, &next, 16);
378 if (p == next)
379 return -EINVAL;
380
381 p = skip_white_spaces(next);
382 if (*p != '\0')
383 return -EINVAL;
384
385 *value = val;
386 return 0;
387 }
388
389 int
390 parser_read_uint8_hex(uint8_t *value, const char *p)
391 {
392 uint64_t val = 0;
393 int ret = parser_read_uint64_hex(&val, p);
394
395 if (ret < 0)
396 return ret;
397
398 if (val > UINT8_MAX)
399 return -ERANGE;
400
401 *value = val;
402 return 0;
403 }
404
405 int
406 parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val)
407 {
408 struct fips_val tmp_val = {0};
409 uint32_t len = val->len;
410 int ret;
411
412 if (len == 0) {
413 if (val->val != NULL) {
414 rte_free(val->val);
415 val->val = NULL;
416 }
417
418 return 0;
419 }
420
421 ret = parse_uint8_hex_str(key, src, &tmp_val);
422 if (ret < 0)
423 return ret;
424
425 if (tmp_val.len == val->len) {
426 val->val = tmp_val.val;
427 return 0;
428 }
429
430 if (tmp_val.len < val->len) {
431 rte_free(tmp_val.val);
432 return -EINVAL;
433 }
434
435 val->val = rte_zmalloc(NULL, val->len, 0);
436 if (!val->val) {
437 rte_free(tmp_val.val);
438 memset(val, 0, sizeof(*val));
439 return -ENOMEM;
440 }
441
442 memcpy(val->val, tmp_val.val, val->len);
443 rte_free(tmp_val.val);
444
445 return 0;
446 }
447
448 int
449 parse_uint8_hex_str(const char *key, char *src, struct fips_val *val)
450 {
451 uint32_t len, j;
452
453 src += strlen(key);
454
455 len = strlen(src) / 2;
456
457 if (val->val) {
458 rte_free(val->val);
459 val->val = NULL;
460 }
461
462 val->val = rte_zmalloc(NULL, len, 0);
463 if (!val->val)
464 return -ENOMEM;
465
466 for (j = 0; j < len; j++) {
467 char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
468
469 if (parser_read_uint8_hex(&val->val[j], byte) < 0) {
470 rte_free(val->val);
471 memset(val, 0, sizeof(*val));
472 return -EINVAL;
473 }
474 }
475
476 val->len = len;
477
478 return 0;
479 }
480
481 int
482 parser_read_uint32_val(const char *key, char *src, struct fips_val *val)
483 {
484 char *data = src + strlen(key);
485 size_t data_len = strlen(data);
486 int ret;
487
488 if (data[data_len - 1] == ']') {
489 char *tmp_data = calloc(1, data_len + 1);
490
491 if (tmp_data == NULL)
492 return -ENOMEM;
493
494 strlcpy(tmp_data, data, data_len);
495
496 ret = parser_read_uint32(&val->len, tmp_data);
497
498 free(tmp_data);
499 } else
500 ret = parser_read_uint32(&val->len, data);
501
502 return ret;
503 }
504
505 int
506 parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val)
507 {
508 int ret;
509
510 ret = parser_read_uint32_val(key, src, val);
511
512 if (ret < 0)
513 return ret;
514
515 val->len /= 8;
516
517 return 0;
518 }
519
520 int
521 writeback_hex_str(const char *key, char *dst, struct fips_val *val)
522 {
523 char *str = dst;
524 uint32_t len;
525
526 str += strlen(key);
527
528 for (len = 0; len < val->len; len++)
529 snprintf(str + len * 2, 255, "%02x", val->val[len]);
530
531 return 0;
532 }
533
534 static int
535 parser_read_uint64(uint64_t *value, const char *p)
536 {
537 char *next;
538 uint64_t val;
539
540 p = skip_white_spaces(p);
541 if (!isdigit(*p))
542 return -EINVAL;
543
544 val = strtoul(p, &next, 10);
545 if (p == next)
546 return -EINVAL;
547
548 p = next;
549 switch (*p) {
550 case 'T':
551 val *= 1024ULL;
552 /* fall through */
553 case 'G':
554 val *= 1024ULL;
555 /* fall through */
556 case 'M':
557 val *= 1024ULL;
558 /* fall through */
559 case 'k':
560 case 'K':
561 val *= 1024ULL;
562 p++;
563 break;
564 }
565
566 p = skip_white_spaces(p);
567 if (*p != '\0')
568 return -EINVAL;
569
570 *value = val;
571 return 0;
572 }
573
574 int
575 parser_read_uint32(uint32_t *value, char *p)
576 {
577 uint64_t val = 0;
578 int ret = parser_read_uint64(&val, p);
579
580 if (ret < 0)
581 return ret;
582
583 if (val > UINT32_MAX)
584 return -EINVAL;
585
586 *value = val;
587 return 0;
588 }
589
590 void
591 parse_write_hex_str(struct fips_val *src)
592 {
593 writeback_hex_str("", info.one_line_text, src);
594
595 fprintf(info.fp_wr, "%s\n", info.one_line_text);
596 }
597
598 int
599 update_info_vec(uint32_t count)
600 {
601 const struct fips_test_callback *cb;
602 uint32_t i, j;
603
604 if (!info.writeback_callbacks)
605 return -1;
606
607 cb = &info.writeback_callbacks[0];
608
609 snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count);
610
611 for (i = 1; i < info.nb_vec_lines; i++) {
612 for (j = 1; info.writeback_callbacks[j].key != NULL; j++) {
613 cb = &info.writeback_callbacks[j];
614 if (strstr(info.vec[i], cb->key)) {
615 cb->cb(cb->key, info.vec[i], cb->val);
616 break;
617 }
618 }
619 }
620
621 return 0;
622 }