summaryrefslogtreecommitdiff
path: root/fuzz/fuzz_credman.c
diff options
context:
space:
mode:
Diffstat (limited to 'fuzz/fuzz_credman.c')
-rw-r--r--fuzz/fuzz_credman.c314
1 files changed, 163 insertions, 151 deletions
diff --git a/fuzz/fuzz_credman.c b/fuzz/fuzz_credman.c
index 323d0a9..db0dfb8 100644
--- a/fuzz/fuzz_credman.c
+++ b/fuzz/fuzz_credman.c
@@ -19,25 +19,16 @@
19 19
20#include "../openbsd-compat/openbsd-compat.h" 20#include "../openbsd-compat/openbsd-compat.h"
21 21
22#define TAG_META_WIRE_DATA 0x01
23#define TAG_RP_WIRE_DATA 0x02
24#define TAG_RK_WIRE_DATA 0x03
25#define TAG_DEL_WIRE_DATA 0x04
26#define TAG_CRED_ID 0x05
27#define TAG_PIN 0x06
28#define TAG_RP_ID 0x07
29#define TAG_SEED 0x08
30
31/* Parameter set defining a FIDO2 credential management operation. */ 22/* Parameter set defining a FIDO2 credential management operation. */
32struct param { 23struct param {
33 char pin[MAXSTR]; 24 char pin[MAXSTR];
34 char rp_id[MAXSTR]; 25 char rp_id[MAXSTR];
35 int seed; 26 int seed;
36 struct blob cred_id; 27 struct blob cred_id;
37 struct blob del_wire_data; 28 struct blob del_wire_data;
38 struct blob meta_wire_data; 29 struct blob meta_wire_data;
39 struct blob rk_wire_data; 30 struct blob rk_wire_data;
40 struct blob rp_wire_data; 31 struct blob rp_wire_data;
41}; 32};
42 33
43/* 34/*
@@ -88,56 +79,136 @@ static const uint8_t dummy_del_wire_data[] = {
88 WIREDATA_CTAP_CBOR_STATUS, 79 WIREDATA_CTAP_CBOR_STATUS,
89}; 80};
90 81
91int LLVMFuzzerTestOneInput(const uint8_t *, size_t); 82struct param *
92size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); 83unpack(const uint8_t *ptr, size_t len)
93
94static int
95unpack(const uint8_t *ptr, size_t len, struct param *p) NO_MSAN
96{ 84{
97 uint8_t **pp = (void *)&ptr; 85 cbor_item_t *item = NULL, **v;
98 86 struct cbor_load_result cbor;
99 if (unpack_string(TAG_PIN, pp, &len, p->pin) < 0 || 87 struct param *p;
100 unpack_string(TAG_RP_ID, pp, &len, p->rp_id) < 0 || 88 int ok = -1;
101 unpack_blob(TAG_CRED_ID, pp, &len, &p->cred_id) < 0 || 89
102 unpack_blob(TAG_META_WIRE_DATA, pp, &len, &p->meta_wire_data) < 0 || 90 if ((p = calloc(1, sizeof(*p))) == NULL ||
103 unpack_blob(TAG_RP_WIRE_DATA, pp, &len, &p->rp_wire_data) < 0 || 91 (item = cbor_load(ptr, len, &cbor)) == NULL ||
104 unpack_blob(TAG_RK_WIRE_DATA, pp, &len, &p->rk_wire_data) < 0 || 92 cbor.read != len ||
105 unpack_blob(TAG_DEL_WIRE_DATA, pp, &len, &p->del_wire_data) < 0 || 93 cbor_isa_array(item) == false ||
106 unpack_int(TAG_SEED, pp, &len, &p->seed) < 0) 94 cbor_array_is_definite(item) == false ||
107 return (-1); 95 cbor_array_size(item) != 8 ||
108 96 (v = cbor_array_handle(item)) == NULL)
109 return (0); 97 goto fail;
98
99 if (unpack_int(v[0], &p->seed) < 0 ||
100 unpack_string(v[1], p->pin) < 0 ||
101 unpack_string(v[2], p->rp_id) < 0 ||
102 unpack_blob(v[3], &p->cred_id) < 0 ||
103 unpack_blob(v[4], &p->meta_wire_data) < 0 ||
104 unpack_blob(v[5], &p->rp_wire_data) < 0 ||
105 unpack_blob(v[6], &p->rk_wire_data) < 0 ||
106 unpack_blob(v[7], &p->del_wire_data) < 0)
107 goto fail;
108
109 ok = 0;
110fail:
111 if (ok < 0) {
112 free(p);
113 p = NULL;
114 }
115
116 if (item)
117 cbor_decref(&item);
118
119 return p;
110} 120}
111 121
112static size_t 122size_t
113pack(uint8_t *ptr, size_t len, const struct param *p) 123pack(uint8_t *ptr, size_t len, const struct param *p)
114{ 124{
115 const size_t max = len; 125 cbor_item_t *argv[8], *array = NULL;
116 126 size_t cbor_alloc_len, cbor_len = 0;
117 if (pack_string(TAG_PIN, &ptr, &len, p->pin) < 0 || 127 unsigned char *cbor = NULL;
118 pack_string(TAG_RP_ID, &ptr, &len, p->rp_id) < 0 || 128
119 pack_blob(TAG_CRED_ID, &ptr, &len, &p->cred_id) < 0 || 129 memset(argv, 0, sizeof(argv));
120 pack_blob(TAG_META_WIRE_DATA, &ptr, &len, &p->meta_wire_data) < 0 || 130
121 pack_blob(TAG_RP_WIRE_DATA, &ptr, &len, &p->rp_wire_data) < 0 || 131 if ((array = cbor_new_definite_array(8)) == NULL ||
122 pack_blob(TAG_RK_WIRE_DATA, &ptr, &len, &p->rk_wire_data) < 0 || 132 (argv[0] = pack_int(p->seed)) == NULL ||
123 pack_blob(TAG_DEL_WIRE_DATA, &ptr, &len, &p->del_wire_data) < 0 || 133 (argv[1] = pack_string(p->pin)) == NULL ||
124 pack_int(TAG_SEED, &ptr, &len, p->seed) < 0) 134 (argv[2] = pack_string(p->rp_id)) == NULL ||
125 return (0); 135 (argv[3] = pack_blob(&p->cred_id)) == NULL ||
126 136 (argv[4] = pack_blob(&p->meta_wire_data)) == NULL ||
127 return (max - len); 137 (argv[5] = pack_blob(&p->rp_wire_data)) == NULL ||
138 (argv[6] = pack_blob(&p->rk_wire_data)) == NULL ||
139 (argv[7] = pack_blob(&p->del_wire_data)) == NULL)
140 goto fail;
141
142 for (size_t i = 0; i < 8; i++)
143 if (cbor_array_push(array, argv[i]) == false)
144 goto fail;
145
146 if ((cbor_len = cbor_serialize_alloc(array, &cbor,
147 &cbor_alloc_len)) > len) {
148 cbor_len = 0;
149 goto fail;
150 }
151
152 memcpy(ptr, cbor, cbor_len);
153fail:
154 for (size_t i = 0; i < 8; i++)
155 if (argv[i])
156 cbor_decref(&argv[i]);
157
158 if (array)
159 cbor_decref(&array);
160
161 free(cbor);
162
163 return cbor_len;
128} 164}
129 165
130static size_t 166size_t
131input_len(int max) 167pack_dummy(uint8_t *ptr, size_t len)
132{ 168{
133 return (2 * len_string(max) + 5 * len_blob(max) + len_int()); 169 struct param dummy;
170 uint8_t blob[4096];
171 size_t blob_len;
172
173 memset(&dummy, 0, sizeof(dummy));
174
175 strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
176 strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
177
178 dummy.meta_wire_data.len = sizeof(dummy_meta_wire_data);
179 dummy.rp_wire_data.len = sizeof(dummy_rp_wire_data);
180 dummy.rk_wire_data.len = sizeof(dummy_rk_wire_data);
181 dummy.del_wire_data.len = sizeof(dummy_del_wire_data);
182 dummy.cred_id.len = sizeof(dummy_cred_id);
183
184 memcpy(&dummy.meta_wire_data.body, &dummy_meta_wire_data,
185 dummy.meta_wire_data.len);
186 memcpy(&dummy.rp_wire_data.body, &dummy_rp_wire_data,
187 dummy.rp_wire_data.len);
188 memcpy(&dummy.rk_wire_data.body, &dummy_rk_wire_data,
189 dummy.rk_wire_data.len);
190 memcpy(&dummy.del_wire_data.body, &dummy_del_wire_data,
191 dummy.del_wire_data.len);
192 memcpy(&dummy.cred_id.body, &dummy_cred_id, dummy.cred_id.len);
193
194 assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
195
196 if (blob_len > len) {
197 memcpy(ptr, blob, len);
198 return len;
199 }
200
201 memcpy(ptr, blob, blob_len);
202
203 return blob_len;
134} 204}
135 205
136static fido_dev_t * 206static fido_dev_t *
137prepare_dev() 207prepare_dev(void)
138{ 208{
139 fido_dev_t *dev; 209 fido_dev_t *dev;
140 fido_dev_io_t io; 210 fido_dev_io_t io;
211 bool x;
141 212
142 memset(&io, 0, sizeof(io)); 213 memset(&io, 0, sizeof(io));
143 214
@@ -149,14 +220,19 @@ prepare_dev()
149 if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, 220 if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev,
150 &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { 221 &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) {
151 fido_dev_free(&dev); 222 fido_dev_free(&dev);
152 return (NULL); 223 return NULL;
153 } 224 }
154 225
155 return (dev); 226 x = fido_dev_is_fido2(dev);
227 consume(&x, sizeof(x));
228 x = fido_dev_supports_cred_prot(dev);
229 consume(&x, sizeof(x));
230
231 return dev;
156} 232}
157 233
158static void 234static void
159get_metadata(struct param *p) 235get_metadata(const struct param *p)
160{ 236{
161 fido_dev_t *dev; 237 fido_dev_t *dev;
162 fido_credman_metadata_t *metadata; 238 fido_credman_metadata_t *metadata;
@@ -187,7 +263,7 @@ get_metadata(struct param *p)
187} 263}
188 264
189static void 265static void
190get_rp_list(struct param *p) 266get_rp_list(const struct param *p)
191{ 267{
192 fido_dev_t *dev; 268 fido_dev_t *dev;
193 fido_credman_rp_t *rp; 269 fido_credman_rp_t *rp;
@@ -221,12 +297,12 @@ get_rp_list(struct param *p)
221} 297}
222 298
223static void 299static void
224get_rk_list(struct param *p) 300get_rk_list(const struct param *p)
225{ 301{
226 fido_dev_t *dev; 302 fido_dev_t *dev;
227 fido_credman_rk_t *rk; 303 fido_credman_rk_t *rk;
228 const fido_cred_t *cred; 304 const fido_cred_t *cred;
229 int type; 305 int val;
230 306
231 set_wire_data(p->rk_wire_data.body, p->rk_wire_data.len); 307 set_wire_data(p->rk_wire_data.body, p->rk_wire_data.len);
232 308
@@ -247,8 +323,8 @@ get_rk_list(struct param *p)
247 assert(i >= fido_credman_rk_count(rk)); 323 assert(i >= fido_credman_rk_count(rk));
248 continue; 324 continue;
249 } 325 }
250 type = fido_cred_type(cred); 326 val = fido_cred_type(cred);
251 consume(&type, sizeof(type)); 327 consume(&val, sizeof(val));
252 consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred)); 328 consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));
253 consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred)); 329 consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred));
254 consume(fido_cred_user_id_ptr(cred), 330 consume(fido_cred_user_id_ptr(cred),
@@ -257,6 +333,8 @@ get_rk_list(struct param *p)
257 xstrlen(fido_cred_user_name(cred))); 333 xstrlen(fido_cred_user_name(cred)));
258 consume(fido_cred_display_name(cred), 334 consume(fido_cred_display_name(cred),
259 xstrlen(fido_cred_display_name(cred))); 335 xstrlen(fido_cred_display_name(cred)));
336 val = fido_cred_prot(cred);
337 consume(&val, sizeof(val));
260 } 338 }
261 339
262 fido_credman_rk_free(&rk); 340 fido_credman_rk_free(&rk);
@@ -265,7 +343,7 @@ get_rk_list(struct param *p)
265} 343}
266 344
267static void 345static void
268del_rk(struct param *p) 346del_rk(const struct param *p)
269{ 347{
270 fido_dev_t *dev; 348 fido_dev_t *dev;
271 349
@@ -279,101 +357,35 @@ del_rk(struct param *p)
279 fido_dev_free(&dev); 357 fido_dev_free(&dev);
280} 358}
281 359
282int 360void
283LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) 361test(const struct param *p)
284{ 362{
285 struct param p; 363 prng_init((unsigned int)p->seed);
286
287 memset(&p, 0, sizeof(p));
288
289 if (size < input_len(GETLEN_MIN) || size > input_len(GETLEN_MAX) ||
290 unpack(data, size, &p) < 0)
291 return (0);
292
293 prng_init((unsigned int)p.seed);
294
295 fido_init(FIDO_DEBUG); 364 fido_init(FIDO_DEBUG);
296 fido_set_log_handler(consume_str); 365 fido_set_log_handler(consume_str);
297 366
298 get_metadata(&p); 367 get_metadata(p);
299 get_rp_list(&p); 368 get_rp_list(p);
300 get_rk_list(&p); 369 get_rk_list(p);
301 del_rk(&p); 370 del_rk(p);
302
303 return (0);
304} 371}
305 372
306static size_t 373void
307pack_dummy(uint8_t *ptr, size_t len) 374mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
308{ 375{
309 struct param dummy; 376 if (flags & MUTATE_SEED)
310 uint8_t blob[32768]; 377 p->seed = (int)seed;
311 size_t blob_len;
312
313 memset(&dummy, 0, sizeof(dummy));
314
315 strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
316 strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
317 378
318 dummy.meta_wire_data.len = sizeof(dummy_meta_wire_data); 379 if (flags & MUTATE_PARAM) {
319 dummy.rp_wire_data.len = sizeof(dummy_rp_wire_data); 380 mutate_blob(&p->cred_id);
320 dummy.rk_wire_data.len = sizeof(dummy_rk_wire_data); 381 mutate_string(p->pin);
321 dummy.del_wire_data.len = sizeof(dummy_del_wire_data); 382 mutate_string(p->rp_id);
322 dummy.cred_id.len = sizeof(dummy_cred_id);
323
324 memcpy(&dummy.meta_wire_data.body, &dummy_meta_wire_data,
325 dummy.meta_wire_data.len);
326 memcpy(&dummy.rp_wire_data.body, &dummy_rp_wire_data,
327 dummy.rp_wire_data.len);
328 memcpy(&dummy.rk_wire_data.body, &dummy_rk_wire_data,
329 dummy.rk_wire_data.len);
330 memcpy(&dummy.del_wire_data.body, &dummy_del_wire_data,
331 dummy.del_wire_data.len);
332 memcpy(&dummy.cred_id.body, &dummy_cred_id, dummy.cred_id.len);
333
334 blob_len = pack(blob, sizeof(blob), &dummy);
335 assert(blob_len != 0);
336
337 if (blob_len > len) {
338 memcpy(ptr, blob, len);
339 return (len);
340 } 383 }
341 384
342 memcpy(ptr, blob, blob_len); 385 if (flags & MUTATE_WIREDATA) {
343 386 mutate_blob(&p->meta_wire_data);
344 return (blob_len); 387 mutate_blob(&p->rp_wire_data);
345} 388 mutate_blob(&p->rk_wire_data);
346 389 mutate_blob(&p->del_wire_data);
347size_t 390 }
348LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize,
349 unsigned int seed) NO_MSAN
350{
351 struct param p;
352 uint8_t blob[16384];
353 size_t blob_len;
354
355 memset(&p, 0, sizeof(p));
356
357 if (unpack(data, size, &p) < 0)
358 return (pack_dummy(data, maxsize));
359
360 p.seed = (int)seed;
361
362 mutate_blob(&p.cred_id);
363 mutate_blob(&p.meta_wire_data);
364 mutate_blob(&p.rp_wire_data);
365 mutate_blob(&p.rk_wire_data);
366 mutate_blob(&p.del_wire_data);
367
368 mutate_string(p.pin);
369 mutate_string(p.rp_id);
370
371 blob_len = pack(blob, sizeof(blob), &p);
372
373 if (blob_len == 0 || blob_len > maxsize)
374 return (0);
375
376 memcpy(data, blob, blob_len);
377
378 return (blob_len);
379} 391}