Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libfido2/fuzz/fuzz_mgmt.c
39586 views
1
/*
2
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
3
* Use of this source code is governed by a BSD-style
4
* license that can be found in the LICENSE file.
5
* SPDX-License-Identifier: BSD-2-Clause
6
*/
7
8
#include <assert.h>
9
#include <stdint.h>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <string.h>
13
14
#include "mutator_aux.h"
15
#include "wiredata_fido2.h"
16
#include "dummy.h"
17
18
#include "../openbsd-compat/openbsd-compat.h"
19
20
#define MAXRPID 64
21
22
struct param {
23
char pin1[MAXSTR];
24
char pin2[MAXSTR];
25
struct blob reset_wire_data;
26
struct blob info_wire_data;
27
struct blob set_pin_wire_data;
28
struct blob change_pin_wire_data;
29
struct blob retry_wire_data;
30
struct blob config_wire_data;
31
int seed;
32
};
33
34
static const uint8_t dummy_reset_wire_data[] = {
35
WIREDATA_CTAP_INIT,
36
WIREDATA_CTAP_CBOR_INFO,
37
WIREDATA_CTAP_KEEPALIVE,
38
WIREDATA_CTAP_KEEPALIVE,
39
WIREDATA_CTAP_KEEPALIVE,
40
WIREDATA_CTAP_CBOR_STATUS,
41
};
42
43
static const uint8_t dummy_info_wire_data[] = {
44
WIREDATA_CTAP_INIT,
45
WIREDATA_CTAP_CBOR_INFO,
46
WIREDATA_CTAP_CBOR_INFO,
47
};
48
49
static const uint8_t dummy_set_pin_wire_data[] = {
50
WIREDATA_CTAP_INIT,
51
WIREDATA_CTAP_CBOR_INFO,
52
WIREDATA_CTAP_CBOR_AUTHKEY,
53
WIREDATA_CTAP_CBOR_STATUS,
54
};
55
56
static const uint8_t dummy_change_pin_wire_data[] = {
57
WIREDATA_CTAP_INIT,
58
WIREDATA_CTAP_CBOR_INFO,
59
WIREDATA_CTAP_CBOR_AUTHKEY,
60
WIREDATA_CTAP_CBOR_STATUS,
61
};
62
63
static const uint8_t dummy_retry_wire_data[] = {
64
WIREDATA_CTAP_INIT,
65
WIREDATA_CTAP_CBOR_INFO,
66
WIREDATA_CTAP_CBOR_RETRIES,
67
};
68
69
static const uint8_t dummy_config_wire_data[] = {
70
WIREDATA_CTAP_INIT,
71
WIREDATA_CTAP_CBOR_INFO,
72
WIREDATA_CTAP_CBOR_STATUS,
73
};
74
75
struct param *
76
unpack(const uint8_t *ptr, size_t len)
77
{
78
cbor_item_t *item = NULL, **v;
79
struct cbor_load_result cbor;
80
struct param *p;
81
int ok = -1;
82
83
if ((p = calloc(1, sizeof(*p))) == NULL ||
84
(item = cbor_load(ptr, len, &cbor)) == NULL ||
85
cbor.read != len ||
86
cbor_isa_array(item) == false ||
87
cbor_array_is_definite(item) == false ||
88
cbor_array_size(item) != 9 ||
89
(v = cbor_array_handle(item)) == NULL)
90
goto fail;
91
92
if (unpack_int(v[0], &p->seed) < 0 ||
93
unpack_string(v[1], p->pin1) < 0 ||
94
unpack_string(v[2], p->pin2) < 0 ||
95
unpack_blob(v[3], &p->reset_wire_data) < 0 ||
96
unpack_blob(v[4], &p->info_wire_data) < 0 ||
97
unpack_blob(v[5], &p->set_pin_wire_data) < 0 ||
98
unpack_blob(v[6], &p->change_pin_wire_data) < 0 ||
99
unpack_blob(v[7], &p->retry_wire_data) < 0 ||
100
unpack_blob(v[8], &p->config_wire_data) < 0)
101
goto fail;
102
103
ok = 0;
104
fail:
105
if (ok < 0) {
106
free(p);
107
p = NULL;
108
}
109
110
if (item)
111
cbor_decref(&item);
112
113
return p;
114
}
115
116
size_t
117
pack(uint8_t *ptr, size_t len, const struct param *p)
118
{
119
cbor_item_t *argv[9], *array = NULL;
120
size_t cbor_alloc_len, cbor_len = 0;
121
unsigned char *cbor = NULL;
122
123
memset(argv, 0, sizeof(argv));
124
125
if ((array = cbor_new_definite_array(9)) == NULL ||
126
(argv[0] = pack_int(p->seed)) == NULL ||
127
(argv[1] = pack_string(p->pin1)) == NULL ||
128
(argv[2] = pack_string(p->pin2)) == NULL ||
129
(argv[3] = pack_blob(&p->reset_wire_data)) == NULL ||
130
(argv[4] = pack_blob(&p->info_wire_data)) == NULL ||
131
(argv[5] = pack_blob(&p->set_pin_wire_data)) == NULL ||
132
(argv[6] = pack_blob(&p->change_pin_wire_data)) == NULL ||
133
(argv[7] = pack_blob(&p->retry_wire_data)) == NULL ||
134
(argv[8] = pack_blob(&p->config_wire_data)) == NULL)
135
goto fail;
136
137
for (size_t i = 0; i < 9; i++)
138
if (cbor_array_push(array, argv[i]) == false)
139
goto fail;
140
141
if ((cbor_len = cbor_serialize_alloc(array, &cbor,
142
&cbor_alloc_len)) == 0 || cbor_len > len) {
143
cbor_len = 0;
144
goto fail;
145
}
146
147
memcpy(ptr, cbor, cbor_len);
148
fail:
149
for (size_t i = 0; i < 9; i++)
150
if (argv[i])
151
cbor_decref(&argv[i]);
152
153
if (array)
154
cbor_decref(&array);
155
156
free(cbor);
157
158
return cbor_len;
159
}
160
161
size_t
162
pack_dummy(uint8_t *ptr, size_t len)
163
{
164
struct param dummy;
165
uint8_t blob[MAXCORPUS];
166
size_t blob_len;
167
168
memset(&dummy, 0, sizeof(dummy));
169
170
strlcpy(dummy.pin1, dummy_pin1, sizeof(dummy.pin1));
171
strlcpy(dummy.pin2, dummy_pin2, sizeof(dummy.pin2));
172
173
dummy.reset_wire_data.len = sizeof(dummy_reset_wire_data);
174
dummy.info_wire_data.len = sizeof(dummy_info_wire_data);
175
dummy.set_pin_wire_data.len = sizeof(dummy_set_pin_wire_data);
176
dummy.change_pin_wire_data.len = sizeof(dummy_change_pin_wire_data);
177
dummy.retry_wire_data.len = sizeof(dummy_retry_wire_data);
178
dummy.config_wire_data.len = sizeof(dummy_config_wire_data);
179
180
memcpy(&dummy.reset_wire_data.body, &dummy_reset_wire_data,
181
dummy.reset_wire_data.len);
182
memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data,
183
dummy.info_wire_data.len);
184
memcpy(&dummy.set_pin_wire_data.body, &dummy_set_pin_wire_data,
185
dummy.set_pin_wire_data.len);
186
memcpy(&dummy.change_pin_wire_data.body, &dummy_change_pin_wire_data,
187
dummy.change_pin_wire_data.len);
188
memcpy(&dummy.retry_wire_data.body, &dummy_retry_wire_data,
189
dummy.retry_wire_data.len);
190
memcpy(&dummy.config_wire_data.body, &dummy_config_wire_data,
191
dummy.config_wire_data.len);
192
193
assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
194
195
if (blob_len > len) {
196
memcpy(ptr, blob, len);
197
return len;
198
}
199
200
memcpy(ptr, blob, blob_len);
201
202
return blob_len;
203
}
204
205
static void
206
dev_reset(const struct param *p)
207
{
208
fido_dev_t *dev;
209
210
set_wire_data(p->reset_wire_data.body, p->reset_wire_data.len);
211
212
if ((dev = open_dev(0)) == NULL)
213
return;
214
215
fido_dev_reset(dev);
216
fido_dev_close(dev);
217
fido_dev_free(&dev);
218
}
219
220
static void
221
dev_get_cbor_info(const struct param *p)
222
{
223
fido_dev_t *dev;
224
fido_cbor_info_t *ci;
225
uint64_t n;
226
uint8_t proto, major, minor, build, flags;
227
bool v;
228
229
set_wire_data(p->info_wire_data.body, p->info_wire_data.len);
230
231
if ((dev = open_dev(0)) == NULL)
232
return;
233
234
proto = fido_dev_protocol(dev);
235
major = fido_dev_major(dev);
236
minor = fido_dev_minor(dev);
237
build = fido_dev_build(dev);
238
flags = fido_dev_flags(dev);
239
240
consume(&proto, sizeof(proto));
241
consume(&major, sizeof(major));
242
consume(&minor, sizeof(minor));
243
consume(&build, sizeof(build));
244
consume(&flags, sizeof(flags));
245
246
if ((ci = fido_cbor_info_new()) == NULL)
247
goto out;
248
249
fido_dev_get_cbor_info(dev, ci);
250
251
for (size_t i = 0; i < fido_cbor_info_versions_len(ci); i++) {
252
char * const *sa = fido_cbor_info_versions_ptr(ci);
253
consume(sa[i], strlen(sa[i]));
254
}
255
256
for (size_t i = 0; i < fido_cbor_info_extensions_len(ci); i++) {
257
char * const *sa = fido_cbor_info_extensions_ptr(ci);
258
consume(sa[i], strlen(sa[i]));
259
}
260
261
for (size_t i = 0; i < fido_cbor_info_transports_len(ci); i++) {
262
char * const *sa = fido_cbor_info_transports_ptr(ci);
263
consume(sa[i], strlen(sa[i]));
264
}
265
266
for (size_t i = 0; i < fido_cbor_info_options_len(ci); i++) {
267
char * const *sa = fido_cbor_info_options_name_ptr(ci);
268
const bool *va = fido_cbor_info_options_value_ptr(ci);
269
consume(sa[i], strlen(sa[i]));
270
consume(&va[i], sizeof(va[i]));
271
}
272
273
/* +1 on purpose */
274
for (size_t i = 0; i <= fido_cbor_info_algorithm_count(ci); i++) {
275
const char *type = fido_cbor_info_algorithm_type(ci, i);
276
int cose = fido_cbor_info_algorithm_cose(ci, i);
277
consume_str(type);
278
consume(&cose, sizeof(cose));
279
}
280
281
for (size_t i = 0; i < fido_cbor_info_certs_len(ci); i++) {
282
char * const *na = fido_cbor_info_certs_name_ptr(ci);
283
const uint64_t *va = fido_cbor_info_certs_value_ptr(ci);
284
consume(na[i], strlen(na[i]));
285
consume(&va[i], sizeof(va[i]));
286
}
287
288
n = fido_cbor_info_maxmsgsiz(ci);
289
consume(&n, sizeof(n));
290
n = fido_cbor_info_maxcredbloblen(ci);
291
consume(&n, sizeof(n));
292
n = fido_cbor_info_maxcredcntlst(ci);
293
consume(&n, sizeof(n));
294
n = fido_cbor_info_maxcredidlen(ci);
295
consume(&n, sizeof(n));
296
n = fido_cbor_info_maxlargeblob(ci);
297
consume(&n, sizeof(n));
298
n = fido_cbor_info_fwversion(ci);
299
consume(&n, sizeof(n));
300
n = fido_cbor_info_minpinlen(ci);
301
consume(&n, sizeof(n));
302
n = fido_cbor_info_maxrpid_minpinlen(ci);
303
consume(&n, sizeof(n));
304
n = fido_cbor_info_uv_attempts(ci);
305
consume(&n, sizeof(n));
306
n = fido_cbor_info_uv_modality(ci);
307
consume(&n, sizeof(n));
308
n = (uint64_t)fido_cbor_info_rk_remaining(ci);
309
consume(&n, sizeof(n));
310
311
consume(fido_cbor_info_aaguid_ptr(ci), fido_cbor_info_aaguid_len(ci));
312
consume(fido_cbor_info_protocols_ptr(ci),
313
fido_cbor_info_protocols_len(ci));
314
315
v = fido_cbor_info_new_pin_required(ci);
316
consume(&v, sizeof(v));
317
318
out:
319
fido_dev_close(dev);
320
fido_dev_free(&dev);
321
322
fido_cbor_info_free(&ci);
323
}
324
325
static void
326
dev_set_pin(const struct param *p)
327
{
328
fido_dev_t *dev;
329
330
set_wire_data(p->set_pin_wire_data.body, p->set_pin_wire_data.len);
331
332
if ((dev = open_dev(0)) == NULL)
333
return;
334
335
fido_dev_set_pin(dev, p->pin1, NULL);
336
fido_dev_close(dev);
337
fido_dev_free(&dev);
338
}
339
340
static void
341
dev_change_pin(const struct param *p)
342
{
343
fido_dev_t *dev;
344
345
set_wire_data(p->change_pin_wire_data.body, p->change_pin_wire_data.len);
346
347
if ((dev = open_dev(0)) == NULL)
348
return;
349
350
fido_dev_set_pin(dev, p->pin2, p->pin1);
351
fido_dev_close(dev);
352
fido_dev_free(&dev);
353
}
354
355
static void
356
dev_get_retry_count(const struct param *p)
357
{
358
fido_dev_t *dev;
359
int n = 0;
360
361
set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);
362
363
if ((dev = open_dev(0)) == NULL)
364
return;
365
366
fido_dev_get_retry_count(dev, &n);
367
consume(&n, sizeof(n));
368
fido_dev_close(dev);
369
fido_dev_free(&dev);
370
}
371
372
static void
373
dev_get_uv_retry_count(const struct param *p)
374
{
375
fido_dev_t *dev;
376
int n = 0;
377
378
set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);
379
380
if ((dev = open_dev(0)) == NULL)
381
return;
382
383
fido_dev_get_uv_retry_count(dev, &n);
384
consume(&n, sizeof(n));
385
fido_dev_close(dev);
386
fido_dev_free(&dev);
387
}
388
389
static void
390
dev_enable_entattest(const struct param *p)
391
{
392
fido_dev_t *dev;
393
const char *pin;
394
int r;
395
396
set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
397
if ((dev = open_dev(0)) == NULL)
398
return;
399
pin = p->pin1;
400
if (strlen(pin) == 0)
401
pin = NULL;
402
r = fido_dev_enable_entattest(dev, pin);
403
consume_str(fido_strerr(r));
404
fido_dev_close(dev);
405
fido_dev_free(&dev);
406
}
407
408
static void
409
dev_toggle_always_uv(const struct param *p)
410
{
411
fido_dev_t *dev;
412
const char *pin;
413
int r;
414
415
set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
416
if ((dev = open_dev(0)) == NULL)
417
return;
418
pin = p->pin1;
419
if (strlen(pin) == 0)
420
pin = NULL;
421
r = fido_dev_toggle_always_uv(dev, pin);
422
consume_str(fido_strerr(r));
423
fido_dev_close(dev);
424
fido_dev_free(&dev);
425
}
426
427
static void
428
dev_force_pin_change(const struct param *p)
429
{
430
fido_dev_t *dev;
431
const char *pin;
432
int r;
433
434
set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
435
if ((dev = open_dev(0)) == NULL)
436
return;
437
pin = p->pin1;
438
if (strlen(pin) == 0)
439
pin = NULL;
440
r = fido_dev_force_pin_change(dev, pin);
441
consume_str(fido_strerr(r));
442
fido_dev_close(dev);
443
fido_dev_free(&dev);
444
}
445
446
static void
447
dev_set_pin_minlen(const struct param *p)
448
{
449
fido_dev_t *dev;
450
const char *pin;
451
int r;
452
453
set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
454
if ((dev = open_dev(0)) == NULL)
455
return;
456
pin = p->pin1;
457
if (strlen(pin) == 0)
458
pin = NULL;
459
r = fido_dev_set_pin_minlen(dev, strlen(p->pin2), pin);
460
consume_str(fido_strerr(r));
461
fido_dev_close(dev);
462
fido_dev_free(&dev);
463
}
464
465
static void
466
dev_set_pin_minlen_rpid(const struct param *p)
467
{
468
fido_dev_t *dev;
469
const char *rpid[MAXRPID];
470
const char *pin;
471
size_t n;
472
int r;
473
474
set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
475
if ((dev = open_dev(0)) == NULL)
476
return;
477
n = uniform_random(MAXRPID);
478
for (size_t i = 0; i < n; i++)
479
rpid[i] = dummy_rp_id;
480
pin = p->pin1;
481
if (strlen(pin) == 0)
482
pin = NULL;
483
r = fido_dev_set_pin_minlen_rpid(dev, rpid, n, pin);
484
consume_str(fido_strerr(r));
485
fido_dev_close(dev);
486
fido_dev_free(&dev);
487
}
488
489
void
490
test(const struct param *p)
491
{
492
prng_init((unsigned int)p->seed);
493
fuzz_clock_reset();
494
fido_init(FIDO_DEBUG);
495
fido_set_log_handler(consume_str);
496
497
dev_reset(p);
498
dev_get_cbor_info(p);
499
dev_set_pin(p);
500
dev_change_pin(p);
501
dev_get_retry_count(p);
502
dev_get_uv_retry_count(p);
503
dev_enable_entattest(p);
504
dev_toggle_always_uv(p);
505
dev_force_pin_change(p);
506
dev_set_pin_minlen(p);
507
dev_set_pin_minlen_rpid(p);
508
}
509
510
void
511
mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
512
{
513
if (flags & MUTATE_SEED)
514
p->seed = (int)seed;
515
516
if (flags & MUTATE_PARAM) {
517
mutate_string(p->pin1);
518
mutate_string(p->pin2);
519
}
520
521
if (flags & MUTATE_WIREDATA) {
522
mutate_blob(&p->reset_wire_data);
523
mutate_blob(&p->info_wire_data);
524
mutate_blob(&p->set_pin_wire_data);
525
mutate_blob(&p->change_pin_wire_data);
526
mutate_blob(&p->retry_wire_data);
527
}
528
}
529
530