summaryrefslogtreecommitdiff
path: root/fuzz/fuzz_mgmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'fuzz/fuzz_mgmt.c')
-rw-r--r--fuzz/fuzz_mgmt.c321
1 files changed, 164 insertions, 157 deletions
diff --git a/fuzz/fuzz_mgmt.c b/fuzz/fuzz_mgmt.c
index d46daf6..0b6cf19 100644
--- a/fuzz/fuzz_mgmt.c
+++ b/fuzz/fuzz_mgmt.c
@@ -17,24 +17,15 @@
17 17
18#include "../openbsd-compat/openbsd-compat.h" 18#include "../openbsd-compat/openbsd-compat.h"
19 19
20#define TAG_PIN1 0x01
21#define TAG_PIN2 0x02
22#define TAG_RESET_WIRE_DATA 0x03
23#define TAG_INFO_WIRE_DATA 0x04
24#define TAG_SET_PIN_WIRE_DATA 0x05
25#define TAG_CHANGE_PIN_WIRE_DATA 0x06
26#define TAG_RETRY_WIRE_DATA 0x07
27#define TAG_SEED 0x08
28
29struct param { 20struct param {
30 char pin1[MAXSTR]; 21 char pin1[MAXSTR];
31 char pin2[MAXSTR]; 22 char pin2[MAXSTR];
32 struct blob reset_wire_data; 23 struct blob reset_wire_data;
33 struct blob info_wire_data; 24 struct blob info_wire_data;
34 struct blob set_pin_wire_data; 25 struct blob set_pin_wire_data;
35 struct blob change_pin_wire_data; 26 struct blob change_pin_wire_data;
36 struct blob retry_wire_data; 27 struct blob retry_wire_data;
37 int seed; 28 int seed;
38}; 29};
39 30
40static const uint8_t dummy_reset_wire_data[] = { 31static const uint8_t dummy_reset_wire_data[] = {
@@ -72,56 +63,136 @@ static const uint8_t dummy_retry_wire_data[] = {
72 WIREDATA_CTAP_CBOR_RETRIES, 63 WIREDATA_CTAP_CBOR_RETRIES,
73}; 64};
74 65
75int LLVMFuzzerTestOneInput(const uint8_t *, size_t); 66struct param *
76size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); 67unpack(const uint8_t *ptr, size_t len)
77
78static int
79unpack(const uint8_t *ptr, size_t len, struct param *p) NO_MSAN
80{ 68{
81 uint8_t **pp = (void *)&ptr; 69 cbor_item_t *item = NULL, **v;
82 70 struct cbor_load_result cbor;
83 if (unpack_string(TAG_PIN1, pp, &len, p->pin1) < 0 || 71 struct param *p;
84 unpack_string(TAG_PIN2, pp, &len, p->pin2) < 0 || 72 int ok = -1;
85 unpack_blob(TAG_RESET_WIRE_DATA, pp, &len, &p->reset_wire_data) < 0 || 73
86 unpack_blob(TAG_INFO_WIRE_DATA, pp, &len, &p->info_wire_data) < 0 || 74 if ((p = calloc(1, sizeof(*p))) == NULL ||
87 unpack_blob(TAG_SET_PIN_WIRE_DATA, pp, &len, &p->set_pin_wire_data) < 0 || 75 (item = cbor_load(ptr, len, &cbor)) == NULL ||
88 unpack_blob(TAG_CHANGE_PIN_WIRE_DATA, pp, &len, &p->change_pin_wire_data) < 0 || 76 cbor.read != len ||
89 unpack_blob(TAG_RETRY_WIRE_DATA, pp, &len, &p->retry_wire_data) < 0 || 77 cbor_isa_array(item) == false ||
90 unpack_int(TAG_SEED, pp, &len, &p->seed) < 0) 78 cbor_array_is_definite(item) == false ||
91 return (-1); 79 cbor_array_size(item) != 8 ||
92 80 (v = cbor_array_handle(item)) == NULL)
93 return (0); 81 goto fail;
82
83 if (unpack_int(v[0], &p->seed) < 0 ||
84 unpack_string(v[1], p->pin1) < 0 ||
85 unpack_string(v[2], p->pin2) < 0 ||
86 unpack_blob(v[3], &p->reset_wire_data) < 0 ||
87 unpack_blob(v[4], &p->info_wire_data) < 0 ||
88 unpack_blob(v[5], &p->set_pin_wire_data) < 0 ||
89 unpack_blob(v[6], &p->change_pin_wire_data) < 0 ||
90 unpack_blob(v[7], &p->retry_wire_data) < 0)
91 goto fail;
92
93 ok = 0;
94fail:
95 if (ok < 0) {
96 free(p);
97 p = NULL;
98 }
99
100 if (item)
101 cbor_decref(&item);
102
103 return p;
94} 104}
95 105
96static size_t 106size_t
97pack(uint8_t *ptr, size_t len, const struct param *p) 107pack(uint8_t *ptr, size_t len, const struct param *p)
98{ 108{
99 const size_t max = len; 109 cbor_item_t *argv[8], *array = NULL;
100 110 size_t cbor_alloc_len, cbor_len = 0;
101 if (pack_string(TAG_PIN1, &ptr, &len, p->pin1) < 0 || 111 unsigned char *cbor = NULL;
102 pack_string(TAG_PIN2, &ptr, &len, p->pin2) < 0 || 112
103 pack_blob(TAG_RESET_WIRE_DATA, &ptr, &len, &p->reset_wire_data) < 0 || 113 memset(argv, 0, sizeof(argv));
104 pack_blob(TAG_INFO_WIRE_DATA, &ptr, &len, &p->info_wire_data) < 0 || 114
105 pack_blob(TAG_SET_PIN_WIRE_DATA, &ptr, &len, &p->set_pin_wire_data) < 0 || 115 if ((array = cbor_new_definite_array(8)) == NULL ||
106 pack_blob(TAG_CHANGE_PIN_WIRE_DATA, &ptr, &len, &p->change_pin_wire_data) < 0 || 116 (argv[0] = pack_int(p->seed)) == NULL ||
107 pack_blob(TAG_RETRY_WIRE_DATA, &ptr, &len, &p->retry_wire_data) < 0 || 117 (argv[1] = pack_string(p->pin1)) == NULL ||
108 pack_int(TAG_SEED, &ptr, &len, p->seed) < 0) 118 (argv[2] = pack_string(p->pin2)) == NULL ||
109 return (0); 119 (argv[3] = pack_blob(&p->reset_wire_data)) == NULL ||
110 120 (argv[4] = pack_blob(&p->info_wire_data)) == NULL ||
111 return (max - len); 121 (argv[5] = pack_blob(&p->set_pin_wire_data)) == NULL ||
122 (argv[6] = pack_blob(&p->change_pin_wire_data)) == NULL ||
123 (argv[7] = pack_blob(&p->retry_wire_data)) == NULL)
124 goto fail;
125
126 for (size_t i = 0; i < 8; i++)
127 if (cbor_array_push(array, argv[i]) == false)
128 goto fail;
129
130 if ((cbor_len = cbor_serialize_alloc(array, &cbor,
131 &cbor_alloc_len)) > len) {
132 cbor_len = 0;
133 goto fail;
134 }
135
136 memcpy(ptr, cbor, cbor_len);
137fail:
138 for (size_t i = 0; i < 8; i++)
139 if (argv[i])
140 cbor_decref(&argv[i]);
141
142 if (array)
143 cbor_decref(&array);
144
145 free(cbor);
146
147 return cbor_len;
112} 148}
113 149
114static size_t 150size_t
115input_len(int max) 151pack_dummy(uint8_t *ptr, size_t len)
116{ 152{
117 return (2 * len_string(max) + 5 * len_blob(max) + len_int()); 153 struct param dummy;
154 uint8_t blob[4096];
155 size_t blob_len;
156
157 memset(&dummy, 0, sizeof(dummy));
158
159 strlcpy(dummy.pin1, dummy_pin1, sizeof(dummy.pin1));
160 strlcpy(dummy.pin2, dummy_pin2, sizeof(dummy.pin2));
161
162 dummy.reset_wire_data.len = sizeof(dummy_reset_wire_data);
163 dummy.info_wire_data.len = sizeof(dummy_info_wire_data);
164 dummy.set_pin_wire_data.len = sizeof(dummy_set_pin_wire_data);
165 dummy.change_pin_wire_data.len = sizeof(dummy_change_pin_wire_data);
166 dummy.retry_wire_data.len = sizeof(dummy_retry_wire_data);
167
168 memcpy(&dummy.reset_wire_data.body, &dummy_reset_wire_data,
169 dummy.reset_wire_data.len);
170 memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data,
171 dummy.info_wire_data.len);
172 memcpy(&dummy.set_pin_wire_data.body, &dummy_set_pin_wire_data,
173 dummy.set_pin_wire_data.len);
174 memcpy(&dummy.change_pin_wire_data.body, &dummy_change_pin_wire_data,
175 dummy.change_pin_wire_data.len);
176 memcpy(&dummy.retry_wire_data.body, &dummy_retry_wire_data,
177 dummy.retry_wire_data.len);
178
179 assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
180
181 if (blob_len > len) {
182 memcpy(ptr, blob, len);
183 return len;
184 }
185
186 memcpy(ptr, blob, blob_len);
187
188 return blob_len;
118} 189}
119 190
120static fido_dev_t * 191static fido_dev_t *
121prepare_dev() 192prepare_dev(void)
122{ 193{
123 fido_dev_t *dev; 194 fido_dev_t *dev;
124 fido_dev_io_t io; 195 fido_dev_io_t io;
125 196
126 memset(&io, 0, sizeof(io)); 197 memset(&io, 0, sizeof(io));
127 198
@@ -133,14 +204,14 @@ prepare_dev()
133 if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, 204 if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev,
134 &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { 205 &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) {
135 fido_dev_free(&dev); 206 fido_dev_free(&dev);
136 return (NULL); 207 return NULL;
137 } 208 }
138 209
139 return (dev); 210 return dev;
140} 211}
141 212
142static void 213static void
143dev_reset(struct param *p) 214dev_reset(const struct param *p)
144{ 215{
145 fido_dev_t *dev; 216 fido_dev_t *dev;
146 217
@@ -155,16 +226,12 @@ dev_reset(struct param *p)
155} 226}
156 227
157static void 228static void
158dev_get_cbor_info(struct param *p) 229dev_get_cbor_info(const struct param *p)
159{ 230{
160 fido_dev_t *dev; 231 fido_dev_t *dev;
161 fido_cbor_info_t *ci; 232 fido_cbor_info_t *ci;
162 uint64_t n; 233 uint64_t n;
163 uint8_t proto; 234 uint8_t proto, major, minor, build, flags;
164 uint8_t major;
165 uint8_t minor;
166 uint8_t build;
167 uint8_t flags;
168 235
169 set_wire_data(p->info_wire_data.body, p->info_wire_data.len); 236 set_wire_data(p->info_wire_data.body, p->info_wire_data.len);
170 237
@@ -192,6 +259,7 @@ dev_get_cbor_info(struct param *p)
192 char * const *sa = fido_cbor_info_versions_ptr(ci); 259 char * const *sa = fido_cbor_info_versions_ptr(ci);
193 consume(sa[i], strlen(sa[i])); 260 consume(sa[i], strlen(sa[i]));
194 } 261 }
262
195 for (size_t i = 0; i < fido_cbor_info_extensions_len(ci); i++) { 263 for (size_t i = 0; i < fido_cbor_info_extensions_len(ci); i++) {
196 char * const *sa = fido_cbor_info_extensions_ptr(ci); 264 char * const *sa = fido_cbor_info_extensions_ptr(ci);
197 consume(sa[i], strlen(sa[i])); 265 consume(sa[i], strlen(sa[i]));
@@ -207,6 +275,12 @@ dev_get_cbor_info(struct param *p)
207 n = fido_cbor_info_maxmsgsiz(ci); 275 n = fido_cbor_info_maxmsgsiz(ci);
208 consume(&n, sizeof(n)); 276 consume(&n, sizeof(n));
209 277
278 n = fido_cbor_info_maxcredcntlst(ci);
279 consume(&n, sizeof(n));
280
281 n = fido_cbor_info_maxcredidlen(ci);
282 consume(&n, sizeof(n));
283
210 n = fido_cbor_info_fwversion(ci); 284 n = fido_cbor_info_fwversion(ci);
211 consume(&n, sizeof(n)); 285 consume(&n, sizeof(n));
212 286
@@ -222,7 +296,7 @@ out:
222} 296}
223 297
224static void 298static void
225dev_set_pin(struct param *p) 299dev_set_pin(const struct param *p)
226{ 300{
227 fido_dev_t *dev; 301 fido_dev_t *dev;
228 302
@@ -237,7 +311,7 @@ dev_set_pin(struct param *p)
237} 311}
238 312
239static void 313static void
240dev_change_pin(struct param *p) 314dev_change_pin(const struct param *p)
241{ 315{
242 fido_dev_t *dev; 316 fido_dev_t *dev;
243 317
@@ -252,10 +326,10 @@ dev_change_pin(struct param *p)
252} 326}
253 327
254static void 328static void
255dev_get_retry_count(struct param *p) 329dev_get_retry_count(const struct param *p)
256{ 330{
257 fido_dev_t *dev; 331 fido_dev_t *dev;
258 int n; 332 int n = 0;
259 333
260 set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len); 334 set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);
261 335
@@ -268,103 +342,36 @@ dev_get_retry_count(struct param *p)
268 fido_dev_free(&dev); 342 fido_dev_free(&dev);
269} 343}
270 344
271int 345void
272LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) 346test(const struct param *p)
273{ 347{
274 struct param p; 348 prng_init((unsigned int)p->seed);
275
276 memset(&p, 0, sizeof(p));
277
278 if (size < input_len(GETLEN_MIN) || size > input_len(GETLEN_MAX) ||
279 unpack(data, size, &p) < 0)
280 return (0);
281
282 prng_init((unsigned int)p.seed);
283
284 fido_init(FIDO_DEBUG); 349 fido_init(FIDO_DEBUG);
285 fido_set_log_handler(consume_str); 350 fido_set_log_handler(consume_str);
286 351
287 dev_reset(&p); 352 dev_reset(p);
288 dev_get_cbor_info(&p); 353 dev_get_cbor_info(p);
289 dev_set_pin(&p); 354 dev_set_pin(p);
290 dev_change_pin(&p); 355 dev_change_pin(p);
291 dev_get_retry_count(&p); 356 dev_get_retry_count(p);
292
293 return (0);
294} 357}
295 358
296static size_t 359void
297pack_dummy(uint8_t *ptr, size_t len) 360mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
298{ 361{
299 struct param dummy; 362 if (flags & MUTATE_SEED)
300 uint8_t blob[16384]; 363 p->seed = (int)seed;
301 size_t blob_len;
302
303 memset(&dummy, 0, sizeof(dummy));
304
305 strlcpy(dummy.pin1, dummy_pin1, sizeof(dummy.pin1));
306 strlcpy(dummy.pin2, dummy_pin2, sizeof(dummy.pin2));
307
308 dummy.reset_wire_data.len = sizeof(dummy_reset_wire_data);
309 dummy.info_wire_data.len = sizeof(dummy_info_wire_data);
310 dummy.set_pin_wire_data.len = sizeof(dummy_set_pin_wire_data);
311 dummy.change_pin_wire_data.len = sizeof(dummy_change_pin_wire_data);
312 dummy.retry_wire_data.len = sizeof(dummy_retry_wire_data);
313
314 memcpy(&dummy.reset_wire_data.body, &dummy_reset_wire_data,
315 dummy.reset_wire_data.len);
316 memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data,
317 dummy.info_wire_data.len);
318 memcpy(&dummy.set_pin_wire_data.body, &dummy_set_pin_wire_data,
319 dummy.set_pin_wire_data.len);
320 memcpy(&dummy.change_pin_wire_data.body, &dummy_change_pin_wire_data,
321 dummy.change_pin_wire_data.len);
322 memcpy(&dummy.retry_wire_data.body, &dummy_retry_wire_data,
323 dummy.retry_wire_data.len);
324
325 blob_len = pack(blob, sizeof(blob), &dummy);
326 assert(blob_len != 0);
327 364
328 if (blob_len > len) { 365 if (flags & MUTATE_PARAM) {
329 memcpy(ptr, blob, len); 366 mutate_string(p->pin1);
330 return (len); 367 mutate_string(p->pin2);
331 } 368 }
332 369
333 memcpy(ptr, blob, blob_len); 370 if (flags & MUTATE_WIREDATA) {
334 371 mutate_blob(&p->reset_wire_data);
335 return (blob_len); 372 mutate_blob(&p->info_wire_data);
336} 373 mutate_blob(&p->set_pin_wire_data);
337 374 mutate_blob(&p->change_pin_wire_data);
338size_t 375 mutate_blob(&p->retry_wire_data);
339LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize, 376 }
340 unsigned int seed)
341{
342 struct param p;
343 uint8_t blob[16384];
344 size_t blob_len;
345
346 memset(&p, 0, sizeof(p));
347
348 if (unpack(data, size, &p) < 0)
349 return (pack_dummy(data, maxsize));
350
351 p.seed = (int)seed;
352
353 mutate_string(p.pin1);
354 mutate_string(p.pin2);
355
356 mutate_blob(&p.reset_wire_data);
357 mutate_blob(&p.info_wire_data);
358 mutate_blob(&p.set_pin_wire_data);
359 mutate_blob(&p.change_pin_wire_data);
360 mutate_blob(&p.retry_wire_data);
361
362 blob_len = pack(blob, sizeof(blob), &p);
363
364 if (blob_len == 0 || blob_len > maxsize)
365 return (0);
366
367 memcpy(data, blob, blob_len);
368
369 return (blob_len);
370} 377}