/src/opensc/src/tests/fuzzing/fuzz_pkcs11.c
Line | Count | Source |
1 | | /* |
2 | | * fuzz_pkcs11.c: Fuzz target for PKCS #11 API |
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 "pkcs11/pkcs11.h" |
27 | | #include "pkcs11/pkcs11-opensc.h" |
28 | | #include "pkcs11/sc-pkcs11.h" |
29 | | #include "fuzzer_reader.h" |
30 | | #include "fuzzer_tool.h" |
31 | | |
32 | | #define SIG_LEN 512 |
33 | | |
34 | | /* If disabled, card is connected only via C_Initialize */ |
35 | | #define FUZZING 1 |
36 | | |
37 | | extern CK_FUNCTION_LIST_3_0 pkcs11_function_list_3_0; |
38 | | static CK_FUNCTION_LIST_3_0_PTR p11 = NULL; |
39 | | |
40 | | /* Values used for key template*/ |
41 | | static CK_BBOOL _true = TRUE; |
42 | | static CK_BBOOL _false = FALSE; |
43 | | |
44 | | /* Global parameters for key template */ |
45 | | CK_ULONG key_type = 0; |
46 | | unsigned char ecparams[256]; |
47 | | unsigned char *opt_object_label[256]; |
48 | | CK_BYTE opt_object_id[100]; |
49 | | CK_MECHANISM_TYPE opt_allowed_mechanisms[20]; |
50 | | |
51 | | #if FUZZING |
52 | | static int fuzz_card_connect(const uint8_t *data, size_t size, sc_pkcs11_slot_t **slot_out) |
53 | 15.4k | { |
54 | | /* Works in the same manner as card_detect() for only one slot and card with virtual reader */ |
55 | 15.4k | struct sc_pkcs11_card *p11card = NULL; |
56 | 15.4k | struct sc_reader *reader = NULL; |
57 | 15.4k | struct sc_app_info *app_generic = NULL; |
58 | 15.4k | sc_pkcs11_slot_t *slot = NULL; |
59 | 15.4k | int rv = CKR_OK, free_p11card = 0; |
60 | | |
61 | | /* Erase possible virtual slots*/ |
62 | 15.4k | list_clear(&virtual_slots); |
63 | | |
64 | | /* Erase possible readers from context */ |
65 | 15.4k | while (list_size(&context->readers)) { |
66 | 0 | sc_reader_t *rdr = (sc_reader_t *) list_get_at(&context->readers, 0); |
67 | 0 | _sc_delete_reader(context, rdr); |
68 | 0 | } |
69 | 15.4k | if (context->reader_driver->ops->finish != NULL) |
70 | 15.4k | context->reader_driver->ops->finish(context); |
71 | | |
72 | | /* Create virtual reader */ |
73 | 15.4k | context->reader_driver = sc_get_fuzz_driver(); |
74 | 15.4k | fuzz_add_reader(context, data, size); |
75 | 15.4k | reader = sc_ctx_get_reader(context, 0); |
76 | | |
77 | | /* Add slot for reader */ |
78 | 15.4k | if (create_slot(reader) != CKR_OK) { |
79 | 0 | goto fail; |
80 | 0 | } |
81 | | |
82 | | /* Locate a slot related to the reader */ |
83 | 15.4k | for (size_t i = 0; i < list_size(&virtual_slots); i++) { |
84 | 15.4k | slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); |
85 | 15.4k | if (slot->reader == reader) { |
86 | 15.4k | p11card = slot->p11card; |
87 | 15.4k | break; |
88 | 15.4k | } |
89 | 15.4k | } |
90 | | |
91 | | /* Create p11card */ |
92 | 15.4k | p11card = (struct sc_pkcs11_card *)calloc(1, sizeof(struct sc_pkcs11_card)); |
93 | 15.4k | p11card->reader = reader; |
94 | 15.4k | free_p11card = 1; |
95 | | |
96 | | /* Connect card to reader */ |
97 | 15.4k | if ((rv = sc_connect_card(reader, &p11card->card)) != SC_SUCCESS) { |
98 | 3.00k | goto fail; |
99 | 3.00k | } |
100 | 12.4k | init_slot_info(&slot->slot_info, reader); |
101 | | |
102 | | /* Instead of detecting framework*/ |
103 | 12.4k | p11card->framework = &framework_pkcs15; |
104 | | |
105 | | /* Bind 'generic' application or (emulated?) card without applications */ |
106 | 12.4k | app_generic = sc_pkcs15_get_application_by_type(p11card->card, "generic"); |
107 | 12.4k | if (app_generic || !p11card->card->app_count) { |
108 | 11.0k | scconf_block *conf_block = NULL; |
109 | | |
110 | 11.0k | conf_block = sc_match_atr_block(p11card->card->ctx, NULL, &p11card->reader->atr); |
111 | 11.0k | if (!conf_block) /* check default block */ |
112 | 11.0k | conf_block = sc_get_conf_block(context, "framework", "pkcs15", 1); |
113 | | |
114 | 11.0k | rv = p11card->framework->bind(p11card, app_generic); |
115 | 11.0k | if (rv != CKR_TOKEN_NOT_RECOGNIZED && rv != CKR_OK) |
116 | 1.06k | goto fail; |
117 | | |
118 | 9.94k | rv = p11card->framework->create_tokens(p11card, app_generic); |
119 | 9.94k | if (rv != CKR_OK) |
120 | 0 | goto fail; |
121 | 9.94k | free_p11card = 0; |
122 | 9.94k | } |
123 | | |
124 | | /* Bind rest of application*/ |
125 | 15.0k | for (int j = 0; j < p11card->card->app_count; j++) { |
126 | 3.71k | struct sc_app_info *app_info = p11card->card->app[j]; |
127 | | |
128 | 3.71k | if (app_generic && app_generic == p11card->card->app[j]) |
129 | 0 | continue; |
130 | | |
131 | 3.71k | if (p11card->framework->bind(p11card, app_info) != CKR_OK) { |
132 | 3.09k | continue; |
133 | 3.09k | } |
134 | 626 | rv = p11card->framework->create_tokens(p11card, app_info); |
135 | 626 | if (rv != CKR_OK) { |
136 | 0 | goto fail; |
137 | 0 | } |
138 | 626 | free_p11card = 0; |
139 | 626 | } |
140 | 11.3k | if (slot_out) |
141 | 254 | *slot_out = slot; |
142 | 15.4k | fail: |
143 | 15.4k | if (free_p11card) { |
144 | 5.21k | sc_pkcs11_card_free(p11card); |
145 | 5.21k | } |
146 | 15.4k | return rv; |
147 | 11.3k | } |
148 | | #endif |
149 | | |
150 | | static int fuzz_pkcs11_initialize(const uint8_t *data, size_t size, sc_pkcs11_slot_t **slot_out, CK_SESSION_HANDLE *session) |
151 | 15.4k | { |
152 | 15.4k | p11 = &pkcs11_function_list_3_0; |
153 | | |
154 | 15.4k | context = NULL; |
155 | 15.4k | memset(&sc_pkcs11_conf, 0, sizeof(struct sc_pkcs11_config)); |
156 | | |
157 | 15.4k | p11->C_Initialize(NULL); |
158 | | |
159 | 15.4k | #if FUZZING |
160 | | /* fuzz target can connect to real card via C_Initialize */ |
161 | 15.4k | if (fuzz_card_connect(data, size, slot_out) != CKR_OK) { |
162 | 4.06k | p11->C_Finalize(NULL); |
163 | 4.06k | return CKR_GENERAL_ERROR; |
164 | 4.06k | } |
165 | 11.3k | #endif |
166 | | |
167 | 11.3k | if (p11->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, session) != CKR_OK) { |
168 | 1.14k | p11->C_Finalize(NULL); |
169 | 1.14k | return CKR_GENERAL_ERROR; |
170 | 1.14k | } |
171 | 10.2k | return CKR_OK; |
172 | 11.3k | } |
173 | | |
174 | | static int set_mechanism(const uint8_t **data, size_t *size, CK_MECHANISM *mech) |
175 | 1.75k | { |
176 | 1.75k | if (*size < sizeof(unsigned long int)) |
177 | 0 | return 1; |
178 | | |
179 | 1.75k | memset(mech, 0, sizeof(*mech)); |
180 | 1.75k | (*mech).mechanism = *((unsigned long int *)*data); |
181 | 1.75k | *data += sizeof(unsigned long int); |
182 | 1.75k | *size -= sizeof(unsigned long int); |
183 | 1.75k | return 0; |
184 | 1.75k | } |
185 | | |
186 | | static void test_change_pin(const unsigned char *data, size_t size) |
187 | 1.02k | { |
188 | 1.02k | CK_SESSION_HANDLE session; |
189 | 1.02k | CK_TOKEN_INFO info; |
190 | 1.02k | char *pin = NULL; |
191 | 1.02k | char *new_pin = NULL; |
192 | 1.02k | int login_type = data[0]; |
193 | 1.02k | data++; size--; |
194 | | |
195 | 1.02k | if (!(pin = extract_word(&data, &size))) |
196 | 2 | goto end; |
197 | 1.02k | if (!(new_pin = extract_word(&data, &size))) |
198 | 1 | goto end; |
199 | | |
200 | 1.02k | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
201 | 153 | goto end; |
202 | 870 | p11->C_GetTokenInfo(0, &info); |
203 | 870 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, pin == NULL ? 0 : strlen(pin)); |
204 | 870 | p11->C_SetPIN(session, |
205 | 870 | (CK_UTF8CHAR *) pin, pin == NULL ? 0 : strlen(pin), |
206 | 870 | (CK_UTF8CHAR *) new_pin, new_pin == NULL ? 0 : strlen(new_pin)); |
207 | | |
208 | 870 | p11->C_CloseSession(session); |
209 | 870 | p11->C_Finalize(NULL); |
210 | 1.02k | end: |
211 | 1.02k | free(new_pin); |
212 | 1.02k | free(pin); |
213 | 1.02k | } |
214 | | |
215 | | static void test_init_pin(const unsigned char *data, size_t size) |
216 | 450 | { |
217 | 450 | CK_SESSION_HANDLE session; |
218 | 450 | CK_TOKEN_INFO info; |
219 | 450 | char *pin = NULL; |
220 | 450 | char *so_pin = NULL; |
221 | 450 | int login_type = data[0]; |
222 | 450 | data++; size--; |
223 | | |
224 | 450 | if (!(pin = extract_word(&data, &size))) |
225 | 1 | goto end; |
226 | 449 | if (!(so_pin = extract_word(&data, &size))) |
227 | 2 | goto end; |
228 | | |
229 | 447 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
230 | 108 | goto end; |
231 | 339 | p11->C_GetTokenInfo(0, &info); |
232 | 339 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) so_pin, so_pin == NULL ? 0 : strlen(so_pin)); |
233 | 339 | p11->C_InitPIN(session, (CK_UTF8CHAR *) pin, pin == NULL ? 0 : strlen(pin)); |
234 | | |
235 | 339 | p11->C_CloseSession(session); |
236 | 339 | p11->C_Finalize(NULL); |
237 | 450 | end: |
238 | 450 | free(pin); |
239 | 450 | free(so_pin); |
240 | 450 | } |
241 | | |
242 | | static void test_init_token(const unsigned char *data, size_t size) |
243 | 375 | { |
244 | 375 | CK_SESSION_HANDLE session; |
245 | 375 | char *pin = NULL; |
246 | 375 | unsigned char *label = NULL; |
247 | 375 | size_t label_len = 0; |
248 | 375 | unsigned char token_label[33]; |
249 | 375 | sc_pkcs11_slot_t *slot = NULL; |
250 | | /* token label must be padded with blank characters, and which must not be null-terminated*/ |
251 | 375 | memset(token_label, ' ', sizeof(token_label)); |
252 | | |
253 | 375 | if (!(pin = extract_word(&data, &size))) |
254 | 1 | goto end; |
255 | 374 | if (!(label = (unsigned char *) extract_word(&data, &size))) |
256 | 1 | goto end; |
257 | 373 | label_len = strlen((char *) label); |
258 | 373 | memcpy(token_label, label, label_len < 33 ? label_len : 32); |
259 | | |
260 | 373 | if (fuzz_pkcs11_initialize(data, size, &slot, &session) != CKR_OK) |
261 | 120 | goto end; |
262 | 253 | p11->C_InitToken(slot->id, (CK_UTF8CHAR *) pin, pin == NULL ? 0 : strlen(pin), token_label); |
263 | | |
264 | 253 | p11->C_CloseSession(session); |
265 | 253 | p11->C_Finalize(NULL); |
266 | 375 | end: |
267 | 375 | free(pin); |
268 | 375 | free(label); |
269 | 375 | } |
270 | | |
271 | | static void test_random(const unsigned char *data, size_t size) |
272 | 11.5k | { |
273 | 11.5k | CK_SESSION_HANDLE session; |
274 | 11.5k | size_t random_len = data[0]; |
275 | 11.5k | CK_BYTE buf[256]; |
276 | 11.5k | data++; size--; |
277 | | |
278 | 11.5k | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
279 | 4.55k | return; |
280 | | |
281 | 6.97k | p11->C_GenerateRandom(session, buf, random_len); |
282 | | |
283 | 6.97k | p11->C_CloseSession(session); |
284 | 6.97k | p11->C_Finalize(NULL); |
285 | 6.97k | } |
286 | | |
287 | | static void test_digest_update(const uint8_t *data, size_t size) |
288 | 238 | { |
289 | 238 | CK_SESSION_HANDLE session; |
290 | 238 | const uint8_t *dig_data = NULL; |
291 | 238 | size_t dig_size = 0; |
292 | 238 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
293 | 238 | unsigned char buffer[64] = {0}; |
294 | 238 | CK_ULONG hash_len = sizeof(buffer); |
295 | 238 | int to_process = 0, rv = 0; |
296 | | |
297 | 238 | if (set_mechanism(&data, &size, &mech)) |
298 | 0 | return; |
299 | | |
300 | | /* Copy data for hashing*/ |
301 | 238 | dig_data = data; |
302 | 238 | if ((dig_size = get_buffer(&dig_data, size, &data, &size, 6000)) == 0) |
303 | 2 | return; |
304 | | |
305 | 236 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
306 | 10 | return; |
307 | | |
308 | 226 | if (p11->C_DigestInit(session, &mech) != CKR_OK) |
309 | 217 | goto end; |
310 | | |
311 | 122 | while (dig_size > 0) { |
312 | 113 | to_process = dig_size > sizeof(buffer) ? sizeof(buffer) : dig_size; |
313 | 113 | dig_size -= to_process; |
314 | 113 | memcpy(buffer, dig_data, to_process); |
315 | 113 | dig_data += to_process; |
316 | | |
317 | 113 | rv = p11->C_DigestUpdate(session, buffer, to_process); |
318 | 113 | if (rv != CKR_OK) |
319 | 0 | goto end; |
320 | 113 | } |
321 | 9 | hash_len = sizeof(buffer); |
322 | 9 | p11->C_DigestFinal(session, buffer, &hash_len); |
323 | | |
324 | 226 | end: |
325 | 226 | p11->C_CloseSession(session); |
326 | 226 | p11->C_Finalize(NULL); |
327 | 226 | } |
328 | | |
329 | | void test_digest(const uint8_t *data, size_t size) |
330 | 81 | { |
331 | 81 | CK_SESSION_HANDLE session; |
332 | 81 | const uint8_t *ptr = NULL; |
333 | 81 | unsigned char *dig_data = NULL; |
334 | 81 | size_t dig_size = 0; |
335 | 81 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
336 | 81 | unsigned char buffer[64] = {0}; |
337 | 81 | CK_ULONG hash_len = sizeof(buffer); |
338 | | |
339 | 81 | if (set_mechanism(&data, &size, &mech)) |
340 | 0 | return; |
341 | | |
342 | | /* Copy data for hashing*/ |
343 | 81 | ptr = data; |
344 | 81 | if ((dig_size = get_buffer(&ptr, size, &data, &size, 6000)) == 0) |
345 | 2 | return; |
346 | 79 | if (!(dig_data = malloc(dig_size))) |
347 | 0 | return; |
348 | 79 | memcpy(dig_data, ptr, dig_size); |
349 | | |
350 | 79 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
351 | 20 | goto end; |
352 | | |
353 | 59 | if (p11->C_DigestInit(session, &mech) == CKR_OK) |
354 | 1 | p11->C_Digest(session, dig_data, dig_size, buffer, &hash_len); |
355 | | |
356 | 59 | p11->C_CloseSession(session); |
357 | 59 | p11->C_Finalize(NULL); |
358 | 79 | end: |
359 | 79 | free(dig_data); |
360 | 79 | } |
361 | | |
362 | | static int fuzz_find_object(CK_SESSION_HANDLE sess, CK_OBJECT_CLASS cls, |
363 | | CK_OBJECT_HANDLE_PTR ret, const unsigned char *id, size_t id_len) |
364 | 995 | { |
365 | | /* taken from tools/pkcs11-tool.c */ |
366 | 995 | CK_ATTRIBUTE attrs[2]; |
367 | 995 | unsigned int nattrs = 0; |
368 | 995 | CK_ULONG count = 0; |
369 | | |
370 | 995 | attrs[0].type = CKA_CLASS; |
371 | 995 | attrs[0].pValue = &cls; |
372 | 995 | attrs[0].ulValueLen = sizeof(cls); |
373 | 995 | nattrs++; |
374 | 995 | if (id) { |
375 | 171 | attrs[nattrs].type = CKA_ID; |
376 | 171 | attrs[nattrs].pValue = (void *) id; |
377 | 171 | attrs[nattrs].ulValueLen = id_len; |
378 | 171 | nattrs++; |
379 | 171 | } |
380 | | |
381 | 995 | if (p11->C_FindObjectsInit(sess, attrs, nattrs) != CKR_OK) |
382 | 0 | return -1; |
383 | | |
384 | 995 | if (p11->C_FindObjects(sess, ret, 1, &count) != CKR_OK) |
385 | 0 | return -1; |
386 | | |
387 | 995 | if (count == 0) |
388 | 366 | *ret = CK_INVALID_HANDLE; |
389 | 995 | p11->C_FindObjectsFinal(sess); |
390 | 995 | return count; |
391 | 995 | } |
392 | | |
393 | | static void test_sign(const uint8_t *data, size_t size) |
394 | 353 | { |
395 | 353 | CK_SESSION_HANDLE session; |
396 | 353 | uint8_t login_type = CKU_USER; |
397 | 353 | char *pin = NULL; |
398 | 353 | const unsigned char *opt_id; |
399 | 353 | size_t opt_id_len = 0; |
400 | 353 | const uint8_t *sign_data = NULL; |
401 | 353 | size_t sign_data_size = 0; |
402 | 353 | CK_OBJECT_HANDLE key = CK_INVALID_HANDLE; |
403 | 353 | unsigned char in_buffer[1025], sig_buffer[512]; |
404 | 353 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
405 | 353 | CK_ULONG sig_len = sizeof(sig_buffer); |
406 | 353 | size_t to_process = 0; |
407 | 353 | CK_TOKEN_INFO info; |
408 | | |
409 | | /* Process options*/ |
410 | 353 | if (set_mechanism(&data, &size, &mech) || size < 3) |
411 | 2 | return; |
412 | 351 | login_type = data[0]; |
413 | 351 | data++; size--; |
414 | 351 | if (!(pin = extract_word(&data, &size))) |
415 | 3 | return; |
416 | 348 | opt_id = data; |
417 | 348 | opt_id_len = get_buffer(&opt_id, size, &data, &size, 256); |
418 | | |
419 | | /* Prepare buffer for signing */ |
420 | 348 | sign_data = data; |
421 | 348 | if ((sign_data_size = get_buffer(&sign_data, size, &data, &size, 6000)) == 0) |
422 | 2 | goto end; |
423 | | |
424 | | /* Initialize */ |
425 | 346 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
426 | 18 | goto end; |
427 | 328 | p11->C_GetTokenInfo(0, &info); |
428 | 328 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
429 | 328 | fuzz_find_object(session, CKO_PRIVATE_KEY, &key, opt_id_len ? opt_id : NULL, opt_id_len); |
430 | | |
431 | 328 | if (p11->C_SignInit(session, &mech, key) != CKR_OK) |
432 | 73 | goto fin; |
433 | 255 | p11->C_Login(session, CKU_CONTEXT_SPECIFIC, (CK_UTF8CHAR *) pin, strlen(pin)); |
434 | | |
435 | 255 | if (sign_data_size <= sizeof(in_buffer)) { |
436 | 241 | memcpy(in_buffer, sign_data, sign_data_size); |
437 | 241 | p11->C_Sign(session, in_buffer, sign_data_size, sig_buffer, &sig_len); |
438 | 241 | } else { |
439 | 46 | while (sign_data_size > 0) { |
440 | 32 | to_process = sign_data_size < sizeof(in_buffer) ? sign_data_size : sizeof(in_buffer); |
441 | 32 | sign_data_size -= to_process; |
442 | 32 | memcpy(in_buffer, sign_data, to_process); |
443 | 32 | sign_data += to_process; |
444 | | |
445 | 32 | if (p11->C_SignUpdate(session, in_buffer, to_process) != CKR_OK) |
446 | 0 | goto fin; |
447 | 32 | } |
448 | | |
449 | 14 | sig_len = sizeof(sig_buffer); |
450 | 14 | p11->C_SignFinal(session, sig_buffer, &sig_len); |
451 | 14 | } |
452 | | |
453 | 328 | fin: |
454 | 328 | p11->C_CloseSession(session); |
455 | 328 | p11->C_Finalize(NULL); |
456 | 348 | end: |
457 | 348 | free(pin); |
458 | 348 | } |
459 | | |
460 | | static void test_verify(const uint8_t *data, size_t size) |
461 | 150 | { |
462 | 150 | CK_SESSION_HANDLE session; |
463 | 150 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
464 | 150 | uint8_t login_type = CKU_USER; |
465 | 150 | char *pin = NULL; |
466 | 150 | const unsigned char *opt_id = NULL; |
467 | 150 | size_t opt_id_len = 0; |
468 | 150 | const uint8_t *verify_data = NULL, *sig_data = NULL; |
469 | 150 | size_t verify_data_size = 0; |
470 | 150 | CK_OBJECT_HANDLE key = CK_INVALID_HANDLE; |
471 | 150 | unsigned char in_buffer[1025], sig_buffer[512]; |
472 | 150 | CK_ULONG sig_len = sizeof(sig_buffer); |
473 | 150 | size_t to_process = 0; |
474 | | |
475 | | /* Process options*/ |
476 | 150 | if (set_mechanism(&data, &size, &mech) || size < 3) |
477 | 2 | return; |
478 | 148 | login_type = data[0]; |
479 | 148 | data++; size--; |
480 | 148 | if (!(pin = extract_word(&data, &size))) |
481 | 1 | return; |
482 | 147 | opt_id = data; |
483 | 147 | opt_id_len = get_buffer(&opt_id, size, &data, &size, 256); |
484 | | |
485 | | /* Prepare buffer with data */ |
486 | 147 | verify_data = data; |
487 | 147 | if ((verify_data_size = get_buffer(&verify_data, size, &data, &size, 6000)) == 0) |
488 | 6 | goto end; |
489 | | /* Get buffer with signature */ |
490 | 141 | sig_data = data; |
491 | 141 | if ((sig_len = get_buffer(&sig_data, size, &data, &size, 512)) == 0) |
492 | 3 | goto end; |
493 | 138 | memcpy(sig_buffer, sig_data, sig_len); |
494 | | |
495 | | /* Initialize */ |
496 | 138 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
497 | 16 | goto end; |
498 | | |
499 | 122 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
500 | | |
501 | 122 | if (!fuzz_find_object(session, CKO_PUBLIC_KEY, &key, opt_id_len ? opt_id : NULL, opt_id_len) |
502 | 56 | && !fuzz_find_object(session, CKO_CERTIFICATE, &key, opt_id_len ? opt_id : NULL, opt_id_len)) |
503 | 56 | goto fin; |
504 | | |
505 | 66 | if (p11->C_VerifyInit(session, &mech, key) != CKR_OK) |
506 | 16 | goto fin; |
507 | | |
508 | 50 | if (verify_data_size <= sizeof(in_buffer)) { |
509 | 50 | memcpy(in_buffer, verify_data, verify_data_size); |
510 | 50 | p11->C_Verify(session, in_buffer, verify_data_size, sig_buffer, sig_len); |
511 | 50 | } else { |
512 | 0 | while (verify_data_size > 0) { |
513 | 0 | to_process = verify_data_size < sizeof(in_buffer) ? verify_data_size : sizeof(in_buffer); |
514 | 0 | verify_data_size -= to_process; |
515 | 0 | memcpy(in_buffer, verify_data, to_process); |
516 | 0 | verify_data += to_process; |
517 | |
|
518 | 0 | if (p11->C_VerifyUpdate(session, in_buffer, to_process) != CKR_OK) |
519 | 0 | goto fin; |
520 | 0 | } |
521 | | |
522 | 0 | p11->C_VerifyFinal(session, sig_buffer, sig_len); |
523 | 0 | } |
524 | 122 | fin: |
525 | 122 | p11->C_CloseSession(session); |
526 | 122 | p11->C_Finalize(NULL); |
527 | 147 | end: |
528 | 147 | free(pin); |
529 | 147 | } |
530 | | |
531 | | static void test_decrypt(const uint8_t *data, size_t size) |
532 | 402 | { |
533 | 402 | CK_SESSION_HANDLE session; |
534 | 402 | uint8_t login_type = CKU_USER; |
535 | 402 | char *pin = NULL; |
536 | 402 | const unsigned char *opt_id; |
537 | 402 | size_t opt_id_len = 0; |
538 | 402 | const uint8_t *dec_data = NULL; |
539 | 402 | size_t dec_data_size = 0; |
540 | 402 | CK_OBJECT_HANDLE key = CK_INVALID_HANDLE; |
541 | 402 | unsigned char in_buffer[1024], out_buffer[1024]; |
542 | 402 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
543 | 402 | size_t out_len = 0; |
544 | | |
545 | | /* Process options*/ |
546 | 402 | if (set_mechanism(&data, &size, &mech) || size < 3) |
547 | 2 | return; |
548 | 400 | login_type = data[0]; |
549 | 400 | data++; size--; |
550 | 400 | if (!(pin = extract_word(&data, &size))) |
551 | 2 | return; |
552 | 398 | opt_id = data; |
553 | 398 | opt_id_len = get_buffer(&opt_id, size, &data, &size, 256); |
554 | | |
555 | | /* Prepare buffer for signing */ |
556 | 398 | dec_data = data; |
557 | 398 | if ((dec_data_size = get_buffer(&dec_data, size, &data, &size, 1024)) == 0) |
558 | 3 | goto end; |
559 | | |
560 | | /* Initialize */ |
561 | 395 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
562 | 28 | goto end; |
563 | | |
564 | 367 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
565 | 367 | if (!fuzz_find_object(session, CKO_PRIVATE_KEY, &key, opt_id_len ? opt_id : NULL, opt_id_len) |
566 | 82 | && !fuzz_find_object(session, CKO_SECRET_KEY, &key, opt_id_len ? opt_id : NULL, opt_id_len)) |
567 | 82 | goto fin; |
568 | | |
569 | 285 | if (p11->C_DecryptInit(session, &mech, key) != CKR_OK) |
570 | 100 | goto fin; |
571 | | |
572 | 185 | p11->C_Login(session, CKU_CONTEXT_SPECIFIC, (CK_UTF8CHAR *) pin, strlen(pin)); |
573 | 185 | out_len = sizeof(out_buffer); |
574 | | |
575 | 185 | memcpy(in_buffer, dec_data, dec_data_size); |
576 | 185 | p11->C_Decrypt(session, in_buffer, dec_data_size, out_buffer, &out_len); |
577 | 367 | fin: |
578 | 367 | p11->C_CloseSession(session); |
579 | 367 | p11->C_Finalize(NULL); |
580 | 398 | end: |
581 | 398 | free(pin); |
582 | 398 | } |
583 | | |
584 | | static void test_wrap(const uint8_t *data, size_t size) |
585 | 29 | { |
586 | 29 | CK_SESSION_HANDLE session; |
587 | 29 | uint8_t login_type = CKU_USER; |
588 | 29 | char *pin = NULL; |
589 | 29 | CK_BYTE pWrappedKey[4096]; |
590 | 29 | CK_ULONG pulWrappedKeyLen = sizeof(pWrappedKey); |
591 | 29 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
592 | 29 | CK_OBJECT_HANDLE hWrappingKey; |
593 | 29 | CK_OBJECT_HANDLE hkey; |
594 | 29 | const unsigned char *hkey_id; |
595 | 29 | const unsigned char *opt_id; |
596 | 29 | size_t opt_id_len = 0, hkey_id_len = 0; |
597 | | |
598 | | /* Set options */ |
599 | 29 | if (set_mechanism(&data, &size, &mech) || size < 3) |
600 | 2 | return; |
601 | 27 | login_type = data[0]; |
602 | 27 | data++; size--; |
603 | 27 | if (!(pin = extract_word(&data, &size))) |
604 | 2 | return; |
605 | 25 | opt_id = data; |
606 | 25 | opt_id_len = get_buffer(&opt_id, size, &data, &size, 256); |
607 | 25 | hkey_id = data; |
608 | 25 | hkey_id_len = get_buffer(&hkey_id, size, &data, &size, 256); |
609 | | |
610 | | /* Initialize */ |
611 | 25 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
612 | 11 | goto end; |
613 | | |
614 | 14 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
615 | 14 | if (!fuzz_find_object(session, CKO_SECRET_KEY, &hkey, hkey_id_len ? hkey_id : NULL, hkey_id_len)) |
616 | 14 | goto fin; |
617 | 0 | if (!fuzz_find_object(session, CKO_PUBLIC_KEY, &hWrappingKey, opt_id_len ? opt_id : NULL, opt_id_len)) |
618 | 0 | if (!fuzz_find_object(session, CKO_SECRET_KEY, &hWrappingKey, opt_id_len ? opt_id : NULL, opt_id_len)) |
619 | 0 | goto fin; |
620 | 0 | p11->C_WrapKey(session, &mech, hWrappingKey, hkey, pWrappedKey, &pulWrappedKeyLen); |
621 | |
|
622 | 14 | fin: |
623 | 14 | p11->C_CloseSession(session); |
624 | 14 | p11->C_Finalize(NULL); |
625 | 25 | end: |
626 | 25 | free(pin); |
627 | 25 | } |
628 | | |
629 | 6.42k | #define FILL_ATTR(attr, typ, val, len) do { \ |
630 | 6.42k | (attr).type=(typ); \ |
631 | 6.42k | (attr).pValue=(val); \ |
632 | 6.42k | (attr).ulValueLen=len; \ |
633 | 6.42k | } while(0) |
634 | | |
635 | | void fill_bool_attr(CK_ATTRIBUTE **keyTemplate, int *n_attr, int type, int value) |
636 | 4.21k | { |
637 | 4.21k | if (value) { |
638 | 2.85k | FILL_ATTR((*keyTemplate)[*n_attr], type, &_true, sizeof(_true)); |
639 | 2.85k | } |
640 | 1.35k | else { |
641 | 1.35k | FILL_ATTR((*keyTemplate)[*n_attr], type, &_false, sizeof(_false)); |
642 | 1.35k | } |
643 | | |
644 | 4.21k | ++(*n_attr); |
645 | 4.21k | } |
646 | | |
647 | | int fill_key_template(CK_ATTRIBUTE **keyTemplate, int *n_attr, const uint8_t **data, size_t *size, CK_OBJECT_CLASS *class, int token) |
648 | 1.15k | { |
649 | 1.15k | const unsigned char *ptr = NULL; |
650 | 1.15k | size_t ecparams_size = 0; |
651 | 1.15k | size_t opt_object_label_size = 0; |
652 | 1.15k | size_t opt_object_id_len = 0; |
653 | 1.15k | size_t opt_allowed_mechanisms_len = 0; |
654 | 1.15k | int bool_types[] = {CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_VERIFY, CKA_SENSITIVE, |
655 | 1.15k | CKA_SIGN, CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, |
656 | 1.15k | CKA_DERIVE, CKA_PRIVATE, CKA_ALWAYS_AUTHENTICATE, CKA_EXTRACTABLE}; |
657 | | |
658 | 1.15k | if (!(*keyTemplate = malloc(20 * sizeof(CK_ATTRIBUTE)))) |
659 | 0 | return 1; |
660 | 1.15k | memset(*keyTemplate, 0, 20 * sizeof(CK_ATTRIBUTE)); |
661 | 1.15k | FILL_ATTR((*keyTemplate)[0], CKA_CLASS, class, sizeof(CKA_CLASS)); |
662 | 1.15k | *n_attr = 1; |
663 | 1.15k | fill_bool_attr(keyTemplate, n_attr, CKA_TOKEN, token); |
664 | | |
665 | 15.9k | for (int i = 0; i < 13; i++) { |
666 | | /* ... | present -> 0/1 | value | ...*/ |
667 | 14.8k | if (*size < 3) |
668 | 28 | return 1; |
669 | 14.7k | if ((*data)[0] % 2) { |
670 | 2.64k | fill_bool_attr(keyTemplate, n_attr, bool_types[i], (*data)[1] % 2); |
671 | 2.64k | (*data)++; (*size)--; |
672 | 2.64k | } |
673 | 14.7k | (*data)++; (*size)--; |
674 | 14.7k | } |
675 | | |
676 | 1.13k | if (*size > 2 && (*data)[0] % 2 && *n_attr < 20){ |
677 | | /* ... | present -> 0/1 | value | ...*/ |
678 | 163 | key_type = (CK_ULONG) (*data)[1]; |
679 | 163 | FILL_ATTR((*keyTemplate)[*n_attr], CKA_KEY_TYPE, &key_type, sizeof(key_type)); |
680 | 163 | ++(*n_attr); |
681 | 163 | (*data) += 2; |
682 | 163 | (*size) -= 2; |
683 | 163 | } |
684 | | |
685 | 1.13k | if (*size > 3 && (*data)[0] % 2 && *n_attr < 20){ |
686 | | /* ... | present -> 0/1 | len | len | data | ... */ |
687 | 108 | (*data)++; (*size)--; |
688 | 108 | ptr = *data; |
689 | 108 | if ((ecparams_size = get_buffer(&ptr, *size, data, size, 256)) == 0) |
690 | 6 | return 1; |
691 | 102 | memcpy(ecparams, ptr, ecparams_size); |
692 | 102 | FILL_ATTR((*keyTemplate)[*n_attr], CKA_EC_PARAMS, ecparams, ecparams_size); |
693 | 102 | ++(*n_attr); |
694 | 102 | } |
695 | | |
696 | 1.12k | if (*size > 3 && (*data)[0] % 2 && *n_attr < 20){ |
697 | | /* ... | present -> 0/1 | len | len | data | ... */ |
698 | 86 | (*data)++; (*size)--; |
699 | 86 | ptr = *data; |
700 | 86 | if ((opt_object_label_size = get_buffer(&ptr, *size, data, size, 128)) == 0) |
701 | 2 | return 1; |
702 | 84 | memcpy(opt_object_label, ptr, opt_object_label_size); |
703 | 84 | FILL_ATTR((*keyTemplate)[*n_attr], CKA_LABEL, opt_object_label, opt_object_label_size); |
704 | 84 | ++(*n_attr); |
705 | 84 | } |
706 | | |
707 | 1.12k | if (*size > 3 && (*data)[0] % 2 && *n_attr < 20){ |
708 | | /* ... | present -> 0/1 | len | len | data | ... */ |
709 | 68 | (*data)++; (*size)--; |
710 | 68 | ptr = *data; |
711 | 68 | if ((opt_object_id_len = get_buffer(&ptr, *size, data, size, 100)) == 0) |
712 | 5 | return 1; |
713 | 63 | memcpy(opt_object_id, ptr, opt_object_id_len); |
714 | 63 | FILL_ATTR((*keyTemplate)[*n_attr], CKA_ID, opt_object_id, opt_object_id_len); |
715 | 63 | ++(*n_attr); |
716 | 63 | } |
717 | 1.11k | if (*size > 4 && (*data)[0] % 2 && *n_attr < 20){ |
718 | | /* ... | present -> 0/1 | len | mech1 | mech2 | ... | mechn | ... */ |
719 | 54 | opt_allowed_mechanisms_len = (*data)[1] > 20 ? 20 : (*data)[1]; |
720 | 54 | (*data) += 2; |
721 | 54 | (*size) -= 2; |
722 | 566 | for (size_t i = 0; i < opt_allowed_mechanisms_len; i++) { |
723 | 524 | if (*size <= sizeof(unsigned int)) |
724 | 12 | return 1; |
725 | 512 | opt_allowed_mechanisms[i] = *((unsigned int *)data); |
726 | 512 | (*data) += sizeof(unsigned int); |
727 | 512 | (*size) -= sizeof(unsigned int); |
728 | 512 | } |
729 | 42 | FILL_ATTR((*keyTemplate)[*n_attr], CKA_ALLOWED_MECHANISMS, opt_allowed_mechanisms, opt_allowed_mechanisms_len); |
730 | 42 | ++(*n_attr); |
731 | 42 | } |
732 | 1.10k | if (*size == 0) |
733 | 0 | return 1; |
734 | 1.10k | return 0; |
735 | 1.10k | } |
736 | | |
737 | | static void test_unwrap(const uint8_t *data, size_t size) |
738 | 24 | { |
739 | 24 | CK_SESSION_HANDLE session; |
740 | 24 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
741 | 24 | uint8_t login_type = CKU_USER; |
742 | 24 | char *pin = NULL; |
743 | 24 | const unsigned char *opt_id, *wrapped_key; |
744 | 24 | size_t opt_id_len; |
745 | 24 | CK_OBJECT_HANDLE hUnwrappingKey; |
746 | 24 | CK_ULONG wrapped_key_length; |
747 | 24 | CK_BYTE_PTR pWrappedKey; |
748 | 24 | unsigned char in_buffer[1024]; |
749 | 24 | CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY; |
750 | 24 | CK_ATTRIBUTE *keyTemplate = NULL; |
751 | 24 | int n_attr = 2; |
752 | 24 | CK_OBJECT_HANDLE hSecretKey; |
753 | | |
754 | | /* Set options */ |
755 | 24 | if (set_mechanism(&data, &size, &mech) || size < 3) |
756 | 1 | goto end; |
757 | 23 | login_type = data[0]; |
758 | 23 | data++; size--; |
759 | 23 | if (!(pin = extract_word(&data, &size))) |
760 | 3 | goto end; |
761 | 20 | opt_id = data; |
762 | 20 | opt_id_len = get_buffer(&opt_id, size, &data, &size, 256); |
763 | 20 | wrapped_key = data; |
764 | 20 | if ((wrapped_key_length = get_buffer(&wrapped_key, size, &data, &size, 1024)) == 0) |
765 | 2 | goto end; |
766 | 18 | memcpy(in_buffer, wrapped_key, wrapped_key_length); |
767 | 18 | pWrappedKey = in_buffer; |
768 | | |
769 | 18 | if (fill_key_template((CK_ATTRIBUTE **) &keyTemplate, &n_attr, &data, &size, &secret_key_class, true)) |
770 | 6 | goto end; |
771 | | |
772 | | /* Initialize */ |
773 | 12 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
774 | 6 | goto end; |
775 | | |
776 | 6 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
777 | | /* Find keys*/ |
778 | 6 | if (!fuzz_find_object(session, CKO_PRIVATE_KEY, &hUnwrappingKey, opt_id_len ? opt_id : NULL, opt_id_len)) |
779 | 4 | if (!fuzz_find_object(session, CKO_SECRET_KEY, &hUnwrappingKey, opt_id_len ? opt_id : NULL, opt_id_len)) |
780 | 4 | goto fin; |
781 | 2 | p11->C_UnwrapKey(session, &mech, hUnwrappingKey, pWrappedKey, wrapped_key_length, keyTemplate, n_attr, &hSecretKey); |
782 | | |
783 | 6 | fin: |
784 | 6 | p11->C_CloseSession(session); |
785 | 6 | p11->C_Finalize(NULL); |
786 | 24 | end: |
787 | 24 | free(pin); |
788 | 24 | free(keyTemplate); |
789 | 24 | } |
790 | | |
791 | | static void test_derive(const uint8_t *data, size_t size) |
792 | 30 | { |
793 | 30 | CK_SESSION_HANDLE session; |
794 | 30 | CK_OBJECT_HANDLE key; |
795 | 30 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
796 | 30 | uint8_t login_type = CKU_USER; |
797 | 30 | char *pin = NULL; |
798 | 30 | const unsigned char *opt_id = NULL; |
799 | 30 | size_t opt_id_len; |
800 | 30 | CK_OBJECT_HANDLE newkey = 0; |
801 | 30 | CK_OBJECT_CLASS newkey_class = CKO_SECRET_KEY; |
802 | 30 | CK_ATTRIBUTE *keyTemplate = NULL; |
803 | 30 | int n_attrs = 2; |
804 | | |
805 | | /* Set options */ |
806 | 30 | if (set_mechanism(&data, &size, &mech) || size < 3) |
807 | 1 | goto end; |
808 | 29 | login_type = data[0]; |
809 | 29 | data++; size--; |
810 | 29 | if (!(pin = extract_word(&data, &size))) |
811 | 1 | goto end; |
812 | 28 | opt_id = data; |
813 | 28 | opt_id_len = get_buffer(&opt_id, size, &data, &size, 256); |
814 | 28 | if (fill_key_template((CK_ATTRIBUTE **) &keyTemplate, &n_attrs, &data, &size, &newkey_class, false)) |
815 | 1 | goto end; |
816 | | |
817 | | /* Initialize */ |
818 | 27 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
819 | 11 | goto end; |
820 | | |
821 | 16 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
822 | 16 | if (fuzz_find_object(session, CKO_PRIVATE_KEY, &key, opt_id_len ? opt_id : NULL, opt_id_len)) |
823 | 4 | p11->C_DeriveKey(session, &mech, key, keyTemplate, n_attrs, &newkey); |
824 | | |
825 | 16 | p11->C_CloseSession(session); |
826 | 16 | p11->C_Finalize(NULL); |
827 | 30 | end: |
828 | 30 | free(pin); |
829 | 30 | free(keyTemplate); |
830 | 30 | } |
831 | | |
832 | | static void test_genkeypair(const uint8_t *data, size_t size) |
833 | 452 | { |
834 | 452 | CK_SESSION_HANDLE session; |
835 | 452 | CK_OBJECT_HANDLE hPublicKey; |
836 | 452 | CK_OBJECT_HANDLE hPrivateKey; |
837 | 452 | CK_MECHANISM mech = {0, NULL_PTR, 0}; |
838 | 452 | uint8_t login_type = CKU_USER; |
839 | 452 | char *pin = NULL; |
840 | 452 | CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; |
841 | 452 | CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY; |
842 | 452 | int n_pubkey_attr = 2; |
843 | 452 | int n_privkey_attr = 2; |
844 | 452 | CK_ATTRIBUTE *publicKeyTemplate = NULL; |
845 | 452 | CK_ATTRIBUTE *privateKeyTemplate = NULL; |
846 | | |
847 | | /* Process options*/ |
848 | 452 | if (set_mechanism(&data, &size, &mech) || size < 3) |
849 | 1 | goto end; |
850 | 451 | login_type = data[0]; |
851 | 451 | data++; size--; |
852 | 451 | if (!(pin = extract_word(&data, &size))) |
853 | 3 | goto end; |
854 | | |
855 | 448 | if (fill_key_template(&publicKeyTemplate, &n_pubkey_attr, &data, &size, &pubkey_class, true) != 0 |
856 | 446 | || fill_key_template(&privateKeyTemplate, &n_privkey_attr, &data, &size, &privkey_class, true) != 0) |
857 | 10 | goto end; |
858 | | |
859 | | /* Initialize */ |
860 | 438 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
861 | 70 | goto end; |
862 | | |
863 | 368 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
864 | 368 | p11->C_GenerateKeyPair(session, &mech, publicKeyTemplate, n_pubkey_attr, |
865 | 368 | privateKeyTemplate, n_privkey_attr, |
866 | 368 | &hPublicKey, &hPrivateKey); |
867 | 368 | p11->C_CloseSession(session); |
868 | 368 | p11->C_Finalize(NULL); |
869 | | |
870 | 452 | end: |
871 | 452 | free(pin); |
872 | 452 | free(privateKeyTemplate); |
873 | 452 | free(publicKeyTemplate); |
874 | 452 | } |
875 | | |
876 | | static void test_store_data(const uint8_t *data, size_t size) |
877 | 112 | { |
878 | 112 | CK_SESSION_HANDLE session; |
879 | 112 | CK_OBJECT_HANDLE data_obj; |
880 | 112 | CK_OBJECT_CLASS class = CKO_DATA; |
881 | 112 | uint8_t login_type = CKU_USER; |
882 | 112 | unsigned char contents[5001]; |
883 | 112 | int contents_len = 0; |
884 | 112 | const uint8_t *ptr = NULL; |
885 | 112 | CK_ATTRIBUTE *data_templ = NULL; |
886 | 112 | int n_data_attr = 0; |
887 | 112 | char *pin = NULL; |
888 | 112 | unsigned char app_id[256]; |
889 | 112 | int app_id_len = 0; |
890 | | |
891 | | /* Create data template */ |
892 | 112 | if (!(data_templ = malloc(20 * sizeof(CK_ATTRIBUTE)))) |
893 | 0 | return; |
894 | 112 | memset(data_templ, 0, 20 * sizeof(CK_ATTRIBUTE)); |
895 | | |
896 | | /* Get PIN */ |
897 | 112 | if (!(pin = extract_word(&data, &size))) |
898 | 1 | goto end; |
899 | | |
900 | | /* Extract content from fuzzing input*/ |
901 | 111 | memset(contents, 0, sizeof(contents)); |
902 | 111 | ptr = data; |
903 | 111 | if ((contents_len = get_buffer(&ptr, size, &data, &size, 5000)) == 0) |
904 | 4 | goto end; |
905 | 107 | memcpy(contents, ptr, contents_len); |
906 | 107 | contents[contents_len] = '\0'; |
907 | | |
908 | | /* Fill attributes to data template */ |
909 | 107 | if (size < 4) |
910 | 3 | goto end; |
911 | 104 | FILL_ATTR(data_templ[n_data_attr], CKA_CLASS, &class, sizeof(class)); |
912 | 104 | n_data_attr++; |
913 | 104 | FILL_ATTR(data_templ[n_data_attr], CKA_VALUE, &contents, contents_len); |
914 | 104 | n_data_attr++; |
915 | 104 | fill_bool_attr(&data_templ, &n_data_attr, CKA_TOKEN, *data % 2); |
916 | 104 | data++; size--; |
917 | 104 | fill_bool_attr(&data_templ, &n_data_attr, CKA_PRIVATE, *data % 2); |
918 | 104 | data++; size--; |
919 | | |
920 | | /* Get application id*/ |
921 | 104 | if (data[0] % 2){ |
922 | 51 | data++; size--; |
923 | 51 | ptr = data; |
924 | 51 | if ((app_id_len = get_buffer(&ptr, size, &data, &size, 256)) == 0) |
925 | 2 | goto end; |
926 | 49 | memcpy(app_id, ptr, app_id_len); |
927 | 49 | FILL_ATTR(data_templ[n_data_attr], CKA_OBJECT_ID, app_id, app_id_len); |
928 | 49 | n_data_attr++; |
929 | 49 | } |
930 | | |
931 | | /* Initialize */ |
932 | 102 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
933 | 7 | goto end; |
934 | | |
935 | 95 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
936 | 95 | p11->C_CreateObject(session, data_templ, n_data_attr, &data_obj); |
937 | 95 | p11->C_CloseSession(session); |
938 | 95 | p11->C_Finalize(NULL); |
939 | 112 | end: |
940 | 112 | free(data_templ); |
941 | 112 | free(pin); |
942 | 112 | } |
943 | | |
944 | | static void test_store_cert(const uint8_t *data, size_t size) |
945 | 116 | { |
946 | 116 | CK_SESSION_HANDLE session; |
947 | 116 | CK_OBJECT_CLASS class = CKO_CERTIFICATE; |
948 | 116 | uint8_t login_type = CKU_USER; |
949 | 116 | unsigned char contents[5000]; |
950 | 116 | int contents_len = 0; |
951 | 116 | const uint8_t *ptr = NULL; |
952 | 116 | CK_ATTRIBUTE *cert_templ = NULL; |
953 | 116 | int n_cert_attr = 0; |
954 | 116 | char *pin = NULL; |
955 | 116 | CK_OBJECT_HANDLE cert_obj; |
956 | 116 | CK_CERTIFICATE_TYPE cert_type = CKC_X_509; |
957 | | |
958 | | /* Create certificate template */ |
959 | 116 | if (!(cert_templ = malloc(20 * sizeof(CK_ATTRIBUTE)))) |
960 | 0 | return; |
961 | 116 | memset(cert_templ, 0, 20 * sizeof(CK_ATTRIBUTE)); |
962 | | |
963 | | /* Get PIN */ |
964 | 116 | if (!(pin = extract_word(&data, &size))) |
965 | 1 | goto end; |
966 | | |
967 | | /* Extract content from fuzzing input */ |
968 | 115 | memset(contents, 0, sizeof(contents)); |
969 | 115 | ptr = data; |
970 | 115 | if ((contents_len = get_buffer(&ptr, size, &data, &size, 5000)) == 0) |
971 | 7 | goto end; |
972 | 108 | memcpy(contents, ptr, contents_len); |
973 | 108 | contents[contents_len] = '\0'; |
974 | | |
975 | | /* Fill attributes to certificate template */ |
976 | 108 | if (size < 4) |
977 | 6 | goto end; |
978 | 102 | FILL_ATTR(cert_templ[n_cert_attr], CKA_CLASS, &class, sizeof(class)); |
979 | 102 | n_cert_attr++; |
980 | 102 | FILL_ATTR(cert_templ[n_cert_attr], CKA_VALUE, contents, contents_len); |
981 | 102 | n_cert_attr++; |
982 | 102 | FILL_ATTR(cert_templ[n_cert_attr], CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)); |
983 | 102 | n_cert_attr++; |
984 | 102 | fill_bool_attr(&cert_templ, &n_cert_attr, CKA_TOKEN, *data % 2); |
985 | 102 | data++; size--; |
986 | 102 | fill_bool_attr(&cert_templ, &n_cert_attr, CKA_PRIVATE, *data % 2); |
987 | 102 | data++; size--; |
988 | | |
989 | | /* Initialize */ |
990 | 102 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
991 | 41 | goto end; |
992 | | |
993 | 61 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
994 | 61 | p11->C_CreateObject(session, cert_templ, n_cert_attr, &cert_obj); |
995 | 61 | p11->C_CloseSession(session); |
996 | 61 | p11->C_Finalize(NULL); |
997 | 116 | end: |
998 | 116 | free(pin); |
999 | 116 | free(cert_templ); |
1000 | 116 | } |
1001 | | |
1002 | | static void test_store_key(const uint8_t *data, size_t size) |
1003 | 221 | { |
1004 | 221 | CK_SESSION_HANDLE session; |
1005 | 221 | CK_OBJECT_CLASS class = CKO_SECRET_KEY; |
1006 | 221 | uint8_t login_type = CKU_USER; |
1007 | 221 | unsigned char contents[5000]; |
1008 | 221 | int contents_len = 0; |
1009 | 221 | const uint8_t *ptr = NULL; |
1010 | 221 | CK_ATTRIBUTE *key_template = NULL; |
1011 | 221 | int n_key_attr = 0; |
1012 | 221 | char *pin = NULL; |
1013 | 221 | CK_OBJECT_HANDLE key_obj; |
1014 | | |
1015 | 221 | memset(contents, 0, sizeof(contents)); |
1016 | 221 | if (size < 3) |
1017 | 0 | return; |
1018 | 221 | class = *data; |
1019 | 221 | data++; size--; |
1020 | | |
1021 | | /* Get PIN */ |
1022 | 221 | if (!(pin = extract_word(&data, &size))) |
1023 | 2 | goto end; |
1024 | | |
1025 | 219 | if (fill_key_template(&key_template, &n_key_attr, &data, &size, &class, true) != 0) |
1026 | 36 | goto end; |
1027 | | |
1028 | 183 | if (size < 3) |
1029 | 13 | goto end; |
1030 | 170 | if (data[0] && n_key_attr < 20) { |
1031 | 51 | data++; size--; |
1032 | 51 | ptr = data; |
1033 | 51 | if ((contents_len = get_buffer(&ptr, size, &data, &size, 5000)) == 0) |
1034 | 17 | goto end; |
1035 | 34 | memcpy(contents, ptr, contents_len); |
1036 | 34 | FILL_ATTR(key_template[n_key_attr], CKA_VALUE, contents, contents_len); |
1037 | 34 | n_key_attr++; |
1038 | 34 | } |
1039 | | |
1040 | | /* Initialize */ |
1041 | 153 | if (fuzz_pkcs11_initialize(data, size, NULL, &session) != CKR_OK) |
1042 | 47 | goto end; |
1043 | | |
1044 | 106 | p11->C_Login(session, login_type, (CK_UTF8CHAR *) pin, strlen(pin)); |
1045 | 106 | p11->C_CreateObject(session, key_template, n_key_attr, &key_obj); |
1046 | 106 | p11->C_CloseSession(session); |
1047 | 106 | p11->C_Finalize(NULL); |
1048 | 221 | end: |
1049 | 221 | free(pin); |
1050 | 221 | free(key_template); |
1051 | 221 | } |
1052 | | |
1053 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
1054 | 15.5k | { |
1055 | 15.5k | uint8_t operation = 0; |
1056 | 15.5k | void (*func_ptr[])(const uint8_t*, size_t) = { |
1057 | 15.5k | test_change_pin, |
1058 | 15.5k | test_init_pin, |
1059 | 15.5k | test_init_token, |
1060 | 15.5k | test_random, |
1061 | 15.5k | test_digest_update, |
1062 | 15.5k | test_digest, |
1063 | 15.5k | test_sign, |
1064 | 15.5k | test_verify, |
1065 | 15.5k | test_decrypt, |
1066 | 15.5k | test_wrap, |
1067 | 15.5k | test_unwrap, |
1068 | 15.5k | test_derive, |
1069 | 15.5k | test_genkeypair, |
1070 | 15.5k | test_store_data, |
1071 | 15.5k | test_store_cert, |
1072 | 15.5k | test_store_key |
1073 | 15.5k | }; |
1074 | | |
1075 | 15.5k | if (size < 10) |
1076 | 6 | return 0; |
1077 | | |
1078 | 15.5k | operation = *data % 16; |
1079 | 15.5k | data++; |
1080 | 15.5k | size--; |
1081 | | |
1082 | 15.5k | func_ptr[operation](data, size); |
1083 | | |
1084 | 15.5k | return 0; |
1085 | 15.5k | } |