/src/opensc/src/tests/fuzzing/fuzz_pkcs15init.c
Line | Count | Source |
1 | | /* |
2 | | * fuzz_pkcs15init.c: Fuzzer for functions processing pkcs15 init |
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 "fuzzer_reader.h" |
27 | | #include "pkcs15init/pkcs15-lib.c" |
28 | | #include "scconf/scconf.h" |
29 | | #include "pkcs15init/pkcs15-init.h" |
30 | | #include "pkcs15init/profile.c" |
31 | | #include "pkcs15init/profile.h" |
32 | | |
33 | | int fuzz_profile_load(struct sc_profile *profile, const uint8_t *data, size_t size) |
34 | 13.8k | { |
35 | 13.8k | int rv = 0; |
36 | 13.8k | scconf_context *conf = NULL; |
37 | 13.8k | conf = scconf_new(NULL); |
38 | 13.8k | if (!conf) |
39 | 0 | return 0; |
40 | | |
41 | 13.8k | if ((rv = scconf_parse_string(conf, (char *)data)) < 0) { |
42 | 0 | scconf_free(conf); |
43 | 0 | return rv; |
44 | 0 | } |
45 | | |
46 | 13.8k | rv = process_conf(profile, conf); |
47 | 13.8k | scconf_free(conf); |
48 | 13.8k | return rv; |
49 | 13.8k | } |
50 | | |
51 | | void fuzz_pkcs15init_bind(struct sc_card *card, struct sc_profile **result, |
52 | | const uint8_t *data, size_t size) |
53 | 15.1k | { |
54 | 15.1k | struct sc_profile *profile = NULL; |
55 | 15.1k | const char *driver; |
56 | 15.1k | struct sc_pkcs15init_operations * (* func)(void) = NULL; |
57 | 15.1k | int r = 0; |
58 | | |
59 | 15.1k | if (!card || !card->driver || !result) |
60 | 0 | return; |
61 | | |
62 | 15.1k | *result = NULL; |
63 | | |
64 | 15.1k | r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN); |
65 | 15.1k | if (r < 0 && r != SC_ERROR_NOT_SUPPORTED) { |
66 | 49 | return; |
67 | 49 | } |
68 | | |
69 | 15.1k | profile = sc_profile_new(); |
70 | 15.1k | if (!profile) |
71 | 0 | return; |
72 | 15.1k | profile->card = card; |
73 | 15.1k | driver = card->driver->short_name; |
74 | | |
75 | 176k | for (int i = 0; profile_operations[i].name; i++) { |
76 | 176k | if (!strcasecmp(driver, profile_operations[i].name)) { |
77 | 14.2k | func = (struct sc_pkcs15init_operations *(*)(void)) profile_operations[i].func; |
78 | 14.2k | break; |
79 | 14.2k | } |
80 | 176k | } |
81 | 15.1k | if (func) { |
82 | 14.2k | profile->ops = func(); |
83 | 14.2k | } else { |
84 | 932 | sc_profile_free(profile); |
85 | 932 | return; |
86 | 932 | } |
87 | 14.2k | profile->name = strdup("Fuzz profile"); |
88 | | |
89 | 14.2k | r = sc_pkcs15init_read_info(card, profile); |
90 | 14.2k | if (r < 0) { |
91 | 338 | sc_profile_free(profile); |
92 | 338 | return; |
93 | 338 | } |
94 | | |
95 | 13.8k | if (fuzz_profile_load(profile, data, size) < 0) { |
96 | 1.75k | sc_profile_free(profile); |
97 | 1.75k | return; |
98 | 1.75k | } |
99 | | |
100 | 12.1k | if (sc_profile_finish(profile, NULL) < 0) { |
101 | 4.00k | sc_profile_free(profile); |
102 | 4.00k | return; |
103 | 4.00k | } |
104 | 8.11k | *result = profile; |
105 | 8.11k | } |
106 | | |
107 | | int fuzz_get_reader_data(const uint8_t *from, size_t from_size, const uint8_t **to, size_t *to_size) |
108 | 18.3k | { |
109 | 18.3k | size_t i = 0; |
110 | 14.7M | while(i < from_size - 1 && from[i] != '\0') |
111 | 14.7M | i++; |
112 | | |
113 | 18.3k | if (from[i] != '\0') |
114 | 20 | return 0; |
115 | | |
116 | 18.3k | *to_size = from_size - (i + 1); |
117 | 18.3k | *to = from + (i + 1); |
118 | 18.3k | return 1; |
119 | 18.3k | } |
120 | | |
121 | | void do_init_app(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card, |
122 | | unsigned char *so_pin, unsigned char *so_puk) |
123 | 8.11k | { |
124 | 8.11k | struct sc_pkcs15init_initargs init_args; |
125 | 8.11k | sc_pkcs15_auth_info_t info; |
126 | 8.11k | int so_puk_disabled = 0; |
127 | | |
128 | 8.11k | memset(&init_args, 0, sizeof(init_args)); |
129 | 8.11k | memset(&info, 0, sizeof(info)); |
130 | 8.11k | sc_pkcs15init_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &info); |
131 | 8.11k | if ((info.attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED) && |
132 | 214 | (info.attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)) |
133 | 210 | so_puk_disabled = 1; |
134 | | |
135 | 8.11k | sc_pkcs15init_get_pin_info(profile, SC_PKCS15INIT_SO_PUK, &info); |
136 | | |
137 | 8.11k | init_args.so_pin = so_pin; |
138 | 8.11k | init_args.so_pin_len = 8; |
139 | | |
140 | 8.11k | if (!so_puk_disabled) { |
141 | 7.90k | init_args.so_puk = so_puk; |
142 | 7.90k | init_args.so_puk_len = 8; |
143 | 7.90k | } |
144 | | |
145 | 8.11k | sc_pkcs15init_add_app(card, profile, &init_args); |
146 | 8.11k | } |
147 | | |
148 | | void do_store_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card, |
149 | | unsigned char *pin, unsigned char *so_pin) |
150 | 5.66k | { |
151 | 5.66k | struct sc_pkcs15init_pinargs pin_args; |
152 | 5.66k | char pin_id[SC_PKCS15_MAX_ID_SIZE] = "1\0"; |
153 | 5.66k | sc_pkcs15init_set_p15card(profile, p15card); |
154 | | |
155 | 5.66k | memcpy(pin, "1234555678\0", 11); /* Set new pin */ |
156 | 5.66k | memset(&pin_args, 0, sizeof(pin_args)); |
157 | | |
158 | 5.66k | sc_pkcs15_format_id(pin_id, &pin_args.auth_id); |
159 | 5.66k | pin_args.pin = pin; |
160 | 5.66k | pin_args.pin_len = 6; |
161 | 5.66k | pin_args.label = "Basic PIN"; |
162 | | |
163 | 5.66k | pin_args.puk = so_pin; |
164 | 5.66k | pin_args.puk_len = 8; |
165 | | |
166 | 5.66k | sc_pkcs15init_store_pin(p15card, profile, &pin_args); |
167 | 5.66k | } |
168 | | |
169 | | void do_store_data_object(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card, |
170 | | uint8_t *buf, size_t len) |
171 | 5.66k | { |
172 | 5.66k | struct sc_pkcs15init_dataargs args; |
173 | 5.66k | char value[SC_MAX_OBJECT_ID_OCTETS]; |
174 | | |
175 | 5.66k | memcpy(value, buf, SC_MAX_OBJECT_ID_OCTETS); |
176 | 5.66k | value[len < SC_MAX_OBJECT_ID_OCTETS ? len : SC_MAX_OBJECT_ID_OCTETS - 1] = '\0'; |
177 | | |
178 | 5.66k | memset(&args, 0, sizeof(args)); |
179 | 5.66k | sc_init_oid(&args.app_oid); |
180 | 5.66k | args.label = "label"; |
181 | 5.66k | args.app_label = "pkcs15-init"; |
182 | | |
183 | 5.66k | sc_format_oid(&args.app_oid, value); |
184 | | |
185 | 5.66k | args.der_encoded.value = buf; |
186 | 5.66k | args.der_encoded.len = len; |
187 | 5.66k | sc_pkcs15init_store_data_object(p15card, profile, &args, NULL); |
188 | 5.66k | } |
189 | | |
190 | | void do_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card) |
191 | 5.66k | { |
192 | 5.66k | struct sc_pkcs15init_keygen_args keygen_args; |
193 | 5.66k | int algorithms[] = { SC_ALGORITHM_RSA, SC_ALGORITHM_EC }; |
194 | 5.66k | unsigned int keybits[] = { 1024, 0 }; |
195 | | |
196 | 5.66k | memset(&keygen_args, 0, sizeof(keygen_args)); |
197 | 5.66k | sc_pkcs15_format_id("01", &(keygen_args.prkey_args.auth_id)); |
198 | 5.66k | keygen_args.prkey_args.access_flags |= |
199 | 5.66k | SC_PKCS15_PRKEY_ACCESS_SENSITIVE |
200 | 5.66k | | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE |
201 | 5.66k | | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE |
202 | 5.66k | | SC_PKCS15_PRKEY_ACCESS_LOCAL; |
203 | | |
204 | 16.9k | for (int i = 0; i < 2; i++) { |
205 | 11.3k | keygen_args.prkey_args.key.algorithm = algorithms[i]; |
206 | 11.3k | if (algorithms[i] == SC_ALGORITHM_EC) /* strdup called also in parse_alg_spec() */ |
207 | 5.66k | keygen_args.prkey_args.key.u.ec.params.named_curve = strdup("prime256v1"); |
208 | 11.3k | sc_pkcs15init_generate_key(p15card, profile, &keygen_args, keybits[i], NULL); |
209 | | /* clear the keygen prkey by algorithms which includes the pubkey and ec_params */ |
210 | 11.3k | sc_pkcs15_erase_prkey(&keygen_args.prkey_args.key); |
211 | 11.3k | } |
212 | 5.66k | } |
213 | | |
214 | | void do_generate_skey(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card) |
215 | 5.66k | { |
216 | 5.66k | struct sc_pkcs15init_skeyargs skey_args; |
217 | 5.66k | int algorithms[] = { SC_ALGORITHM_DES, SC_ALGORITHM_3DES, SC_ALGORITHM_AES }; |
218 | 5.66k | unsigned int keybits[] = { 64, 192, 128 }; |
219 | | |
220 | | /* init keygen_args*/ |
221 | 5.66k | memset(&skey_args, 0, sizeof(skey_args)); |
222 | 5.66k | skey_args.label = "label"; |
223 | 5.66k | skey_args.usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; |
224 | 5.66k | skey_args.user_consent = 0; |
225 | | |
226 | 22.6k | for (int i = 0; i < 3; i++) { |
227 | 16.9k | skey_args.algorithm = algorithms[i]; |
228 | 16.9k | skey_args.value_len = keybits[i]; |
229 | 16.9k | sc_pkcs15init_generate_secret_key(p15card, profile, &skey_args, NULL); |
230 | 16.9k | } |
231 | 5.66k | } |
232 | | |
233 | | void do_store_secret_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, |
234 | | sc_card_t *card, uint8_t *buf) |
235 | 5.66k | { |
236 | 5.66k | struct sc_pkcs15init_skeyargs args; |
237 | 5.66k | int algorithms[] = { SC_ALGORITHM_AES, SC_ALGORITHM_DES, SC_ALGORITHM_3DES }; |
238 | 5.66k | unsigned int keybits[] = { 128, 64, 192 }; |
239 | | |
240 | 5.66k | memset(&args, 0, sizeof(args)); |
241 | 5.66k | args.access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_SENSITIVE; |
242 | 5.66k | args.usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; |
243 | 5.66k | sc_pkcs15_format_id("02", &(args.auth_id)); |
244 | | |
245 | 22.6k | for (int i = 0; i < 3; i++) { |
246 | 16.9k | size_t keybytes = BYTES4BITS(keybits[i]); |
247 | 16.9k | args.key.data = malloc(keybytes); |
248 | 16.9k | memcpy(args.key.data, buf, keybytes); |
249 | 16.9k | args.key.data_len = keybytes; |
250 | 16.9k | args.algorithm = algorithms[i]; |
251 | 16.9k | args.value_len = keybits[i]; |
252 | | |
253 | 16.9k | sc_pkcs15init_store_secret_key(p15card, profile, &args, NULL); |
254 | 16.9k | if (args.key.data) |
255 | 16.9k | free(args.key.data); |
256 | 16.9k | } |
257 | 5.66k | } |
258 | | |
259 | | void do_erase(struct sc_profile *profile, sc_card_t *card) |
260 | 5.66k | { |
261 | 5.66k | struct sc_pkcs15_card *p15card; |
262 | | |
263 | 5.66k | p15card = sc_pkcs15_card_new(); |
264 | 5.66k | p15card->card = card; |
265 | | |
266 | 5.66k | sc_pkcs15init_erase_card(p15card, profile, NULL); |
267 | 5.66k | sc_pkcs15_card_free(p15card); |
268 | 5.66k | } |
269 | | |
270 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
271 | 18.3k | { |
272 | 18.3k | sc_context_t *ctx = NULL; |
273 | 18.3k | sc_card_t *card = NULL; |
274 | 18.3k | struct sc_pkcs15_card *p15card = NULL; |
275 | 18.3k | struct sc_profile *profile = NULL; |
276 | 18.3k | struct sc_reader *reader = NULL; |
277 | 18.3k | const uint8_t *reader_data = NULL; |
278 | 18.3k | size_t reader_data_size = 0; |
279 | 18.3k | uint8_t *buf = NULL; |
280 | 18.3k | uint16_t len = size < 256 ? size : 256; |
281 | 18.3k | unsigned char *pin = NULL; |
282 | 18.3k | unsigned char *so_pin = NULL; |
283 | 18.3k | unsigned char *puk = NULL; |
284 | 18.3k | unsigned char *so_puk = NULL; |
285 | 18.3k | struct sc_pkcs15_card *tmp_p15_data = NULL; |
286 | | |
287 | 18.3k | #ifdef FUZZING_ENABLED |
288 | 18.3k | fclose(stdout); |
289 | 18.3k | #endif |
290 | | |
291 | 18.3k | if (size == 0) |
292 | 0 | return 0; |
293 | | |
294 | 18.3k | if (!fuzz_get_reader_data(data, size, &reader_data, &reader_data_size)) { |
295 | 20 | return 0; |
296 | 20 | } |
297 | | |
298 | | /* Establish context for fuzz app*/ |
299 | 18.3k | sc_establish_context(&ctx, "fuzz"); |
300 | 18.3k | if (!ctx) |
301 | 0 | return 0; |
302 | | |
303 | 18.3k | if (fuzz_connect_card(ctx, &card, &reader, reader_data, reader_data_size) != SC_SUCCESS) |
304 | 3.15k | goto end; |
305 | | |
306 | | /* Load profile and bind with card */ |
307 | 15.1k | fuzz_pkcs15init_bind(card, &profile, data, size - reader_data_size); |
308 | | |
309 | 15.1k | if(!profile) |
310 | 7.07k | goto end; |
311 | | |
312 | 8.11k | pin = malloc(11); |
313 | 8.11k | so_pin = malloc(9); |
314 | 8.11k | puk = malloc(9); |
315 | 8.11k | so_puk = malloc(9); |
316 | 8.11k | buf = malloc(len * sizeof(char)); |
317 | 8.11k | if (!pin || !so_pin || !puk || !so_puk || !buf) |
318 | 0 | goto end_release; |
319 | | |
320 | 8.11k | memcpy(pin, "123456\0", 7); |
321 | 8.11k | memcpy(so_pin, "12345678\0", 9); |
322 | 8.11k | memcpy(puk, "12345678\0", 9); |
323 | 8.11k | memcpy(so_puk, "12345678\0", 9); |
324 | 8.11k | memcpy(buf, data, len); |
325 | | |
326 | | /* test pkcs15-init functionality*/ |
327 | 8.11k | do_init_app(profile, p15card, card, so_pin, so_puk); |
328 | | |
329 | 8.11k | if (!sc_pkcs15_bind(card, NULL, &p15card)) { /* First and only sc_pkcs15_bind calling, is omitted in next cases*/ |
330 | 5.66k | do_store_pin(profile, p15card, card, pin, so_pin); |
331 | 5.66k | } |
332 | | |
333 | | /* sc_pkcs15_bind failed, no point in testing next cases */ |
334 | 8.11k | if (!p15card) |
335 | 2.45k | goto end_release; |
336 | | |
337 | 5.66k | do_store_data_object(profile, p15card, card, buf, len); |
338 | 5.66k | do_generate_key(profile, p15card, card); |
339 | 5.66k | do_generate_skey(profile, p15card, card); |
340 | 5.66k | do_store_secret_key(profile, p15card, card, buf); |
341 | | |
342 | 5.66k | sc_pkcs15init_finalize_card(card, profile); |
343 | 5.66k | sc_pkcs15init_sanity_check(p15card, profile); |
344 | | |
345 | 5.66k | do_erase(profile, card); |
346 | | |
347 | 8.11k | end_release: |
348 | 8.11k | free(pin); |
349 | 8.11k | free(puk); |
350 | 8.11k | free(so_pin); |
351 | 8.11k | free(so_puk); |
352 | 8.11k | free(buf); |
353 | | |
354 | 18.3k | end: |
355 | 18.3k | if (profile) { |
356 | 8.11k | tmp_p15_data = profile->p15_data; |
357 | 8.11k | sc_pkcs15init_unbind(profile); |
358 | 8.11k | if (tmp_p15_data != p15card) |
359 | 1.19k | sc_pkcs15_unbind(tmp_p15_data); |
360 | 8.11k | } |
361 | 18.3k | if (p15card) { |
362 | 5.66k | sc_pkcs15_unbind(p15card); |
363 | 5.66k | } |
364 | 18.3k | if (card) |
365 | 15.1k | sc_disconnect_card(card); |
366 | 18.3k | sc_release_context(ctx); |
367 | | |
368 | 18.3k | return 0; |
369 | 8.11k | } |