/src/opensc/src/tests/fuzzing/fuzz_piv_tool.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * fuzz_piv_tool.c: Fuzz target for piv-tool |
3 | | * |
4 | | * Copyright (C) 2022 Red Hat, Inc. |
5 | | * |
6 | | * Author: Veronika Hanulikova <vhanulik@redhat.com> |
7 | | * |
8 | | * This library is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public |
10 | | * License as published by the Free Software Foundation; either |
11 | | * version 2.1 of the License, or (at your option) any later version. |
12 | | * |
13 | | * This library is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #ifdef HAVE_CONFIG_H |
23 | | #include "config.h" |
24 | | #endif |
25 | | |
26 | | #include "libopensc/internal.h" |
27 | | #include <stdlib.h> |
28 | | #include <string.h> |
29 | | #include <stdbool.h> |
30 | | #include "fuzzer_reader.h" |
31 | | #include "fuzzer_tool.h" |
32 | | #undef stderr |
33 | 7.54k | #define stderr stdout |
34 | | |
35 | | /* Rename main for calling in fuzz target */ |
36 | | #define main _main |
37 | | /* Connect to virtual reader instead of real card*/ |
38 | 3.19k | #define util_connect_card(ctx, card, id, do_wait) fuzz_util_connect_card(ctx, card) |
39 | | # include "tools/piv-tool.c" |
40 | | #undef main |
41 | | |
42 | | static const uint8_t *reader_data = NULL; |
43 | | static size_t reader_data_size = 0; |
44 | | |
45 | | /* Use instead of util_connect_card() */ |
46 | | int fuzz_util_connect_card(struct sc_context *ctx, struct sc_card **card) |
47 | 18.0k | { |
48 | 18.0k | return fuzz_connect_card(ctx, card, NULL, reader_data, reader_data_size); |
49 | 18.0k | } |
50 | | |
51 | | void initilize_global() |
52 | 3.31k | { |
53 | | /* Global variables need to be reser between runs, |
54 | | fuzz target is called repetitively in one execution */ |
55 | 3.31k | reader_data = NULL; |
56 | 3.31k | reader_data_size = 0; |
57 | 3.31k | ctx = NULL; |
58 | 3.31k | card = NULL; |
59 | 3.31k | bp = NULL; |
60 | 3.31k | opt_reader = NULL; |
61 | 3.31k | opt_apdus = NULL; |
62 | 3.31k | opt_apdu_count = 0; |
63 | | |
64 | 3.31k | optind = 0; |
65 | 3.31k | opterr = 0; /* do not print out error messages */ |
66 | 3.31k | optopt = 0; |
67 | 3.31k | } |
68 | | |
69 | | void test_load(char *op, const uint8_t *data, size_t size) |
70 | 14 | { |
71 | 14 | char *filename = NULL; |
72 | 14 | char *argv[] = {"./fuzz_piv", op, NULL /*ref*/, "-i", NULL /*filename*/, "-A", NULL /*admin*/, NULL}; |
73 | 14 | int argc = 7; |
74 | 14 | char *opt_ref = NULL, *opt_admin = NULL; |
75 | | |
76 | 14 | if (!(opt_ref = extract_word(&data, &size))) |
77 | 5 | return; |
78 | 9 | argv[2] = opt_ref; |
79 | | |
80 | 9 | if (!(opt_admin = extract_word(&data, &size))) { |
81 | 3 | free(opt_ref); |
82 | 3 | return; |
83 | 3 | } |
84 | 6 | argv[6] = opt_admin; |
85 | | |
86 | 6 | if (create_input_file(&filename, &data, &size) != 0) { |
87 | 3 | free(opt_ref); |
88 | 3 | free(opt_admin); |
89 | 3 | remove_file(filename); |
90 | 3 | return; |
91 | 3 | } |
92 | 3 | argv[4] = filename; |
93 | | |
94 | 3 | reader_data = data; |
95 | 3 | reader_data_size = size; |
96 | 3 | _main(argc, argv); |
97 | | |
98 | 3 | free(opt_ref); |
99 | 3 | free(opt_admin); |
100 | 3 | remove_file(filename); |
101 | 3 | } |
102 | | |
103 | | /* Skip argv with option for output file */ |
104 | | int present_outfile(int argc, char *argv[]) |
105 | 3.26k | { |
106 | 3.26k | const struct option _options[] = { |
107 | 3.26k | { "out",1, NULL,'o' }, |
108 | 3.26k | { NULL, 0, NULL, 0 } |
109 | 3.26k | }; |
110 | 3.26k | int c; |
111 | 2.00M | while ((c = getopt_long(argc, argv, "o:", _options, (int *) 0)) != -1) { |
112 | 2.00M | switch (c) { |
113 | 2 | case 'o': |
114 | 2 | return 1; |
115 | 2.00M | default: |
116 | 2.00M | continue; |
117 | 2.00M | } |
118 | 2.00M | } |
119 | 3.26k | optind = 0; |
120 | 3.26k | optopt = 0; |
121 | 3.26k | return 0; |
122 | 3.26k | } |
123 | | |
124 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
125 | 3.32k | { |
126 | 3.32k | uint8_t operation = 0; |
127 | 3.32k | char *filename = NULL; |
128 | 3.32k | char **argv = NULL; |
129 | 3.32k | int argc = 0; |
130 | 3.32k | char auth_path[50] = {0}; |
131 | | |
132 | 3.32k | #ifdef FUZZING_ENABLED |
133 | 3.32k | fclose(stdout); |
134 | 3.32k | #endif |
135 | 3.32k | if (size < 10) |
136 | 6 | return 0; |
137 | | |
138 | 3.31k | initilize_global(); |
139 | 3.31k | operation = data[0]; |
140 | 3.31k | data++; |
141 | 3.31k | size--; |
142 | | |
143 | | /* extract admin argument and set file with admin key */ |
144 | 3.31k | if (create_input_file(&filename, &data, &size) != 0 || size < 3) |
145 | 33 | goto err; |
146 | 3.28k | sprintf(auth_path, "PIV_EXT_AUTH_KEY=%s", filename); |
147 | 3.28k | putenv(auth_path); |
148 | | |
149 | 3.28k | switch (operation) { |
150 | 8 | case 0: |
151 | 8 | test_load("-O", data, size); |
152 | 8 | break; |
153 | 3 | case 1: |
154 | 3 | test_load("-C", data, size); |
155 | 3 | break; |
156 | 3 | case 2: |
157 | 3 | test_load("-Z", data, size); |
158 | 3 | break; |
159 | 3.26k | default: |
160 | 3.26k | if (get_fuzzed_argv("./fuzz_piv", data, size, &argv, &argc, &reader_data, &reader_data_size) != 0) |
161 | 6 | goto err; |
162 | 3.26k | if (present_outfile(argc, argv)) { |
163 | 2 | free_arguments(argc, argv); |
164 | 2 | goto err; |
165 | 2 | } |
166 | 3.26k | _main(argc, argv); |
167 | 3.26k | free_arguments(argc, argv); |
168 | 3.28k | } |
169 | 3.31k | err: |
170 | 3.31k | reader_data = NULL; |
171 | 3.31k | reader_data_size = 0; |
172 | 3.31k | remove_file(filename); |
173 | 3.31k | return 0; |
174 | 3.28k | } |