Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libfido2/fuzz/fuzz_assert.c
39586 views
1
/*
2
* Copyright (c) 2019-2023 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 "wiredata_u2f.h"
17
#include "dummy.h"
18
19
#include "../openbsd-compat/openbsd-compat.h"
20
21
/* Parameter set defining a FIDO2 get assertion operation. */
22
struct param {
23
char pin[MAXSTR];
24
char rp_id[MAXSTR];
25
int ext;
26
int seed;
27
struct blob cdh;
28
struct blob cred;
29
struct blob es256;
30
struct blob rs256;
31
struct blob eddsa;
32
struct blob wire_data;
33
uint8_t cred_count;
34
uint8_t type;
35
uint8_t opt;
36
uint8_t up;
37
uint8_t uv;
38
};
39
40
/*
41
* Collection of HID reports from an authenticator issued with a FIDO2
42
* get assertion using the example parameters above.
43
*/
44
static const uint8_t dummy_wire_data_fido[] = {
45
WIREDATA_CTAP_INIT,
46
WIREDATA_CTAP_CBOR_INFO,
47
WIREDATA_CTAP_CBOR_AUTHKEY,
48
WIREDATA_CTAP_CBOR_PINTOKEN,
49
WIREDATA_CTAP_CBOR_ASSERT,
50
};
51
52
/*
53
* Collection of HID reports from an authenticator issued with a U2F
54
* authentication using the example parameters above.
55
*/
56
static const uint8_t dummy_wire_data_u2f[] = {
57
WIREDATA_CTAP_INIT,
58
WIREDATA_CTAP_U2F_6985,
59
WIREDATA_CTAP_U2F_6985,
60
WIREDATA_CTAP_U2F_6985,
61
WIREDATA_CTAP_U2F_6985,
62
WIREDATA_CTAP_U2F_AUTH,
63
};
64
65
struct param *
66
unpack(const uint8_t *ptr, size_t len)
67
{
68
cbor_item_t *item = NULL, **v;
69
struct cbor_load_result cbor;
70
struct param *p;
71
int ok = -1;
72
73
if ((p = calloc(1, sizeof(*p))) == NULL ||
74
(item = cbor_load(ptr, len, &cbor)) == NULL ||
75
cbor.read != len ||
76
cbor_isa_array(item) == false ||
77
cbor_array_is_definite(item) == false ||
78
cbor_array_size(item) != 15 ||
79
(v = cbor_array_handle(item)) == NULL)
80
goto fail;
81
82
if (unpack_byte(v[0], &p->uv) < 0 ||
83
unpack_byte(v[1], &p->up) < 0 ||
84
unpack_byte(v[2], &p->opt) < 0 ||
85
unpack_byte(v[3], &p->type) < 0 ||
86
unpack_byte(v[4], &p->cred_count) < 0 ||
87
unpack_int(v[5], &p->ext) < 0 ||
88
unpack_int(v[6], &p->seed) < 0 ||
89
unpack_string(v[7], p->rp_id) < 0 ||
90
unpack_string(v[8], p->pin) < 0 ||
91
unpack_blob(v[9], &p->wire_data) < 0 ||
92
unpack_blob(v[10], &p->rs256) < 0 ||
93
unpack_blob(v[11], &p->es256) < 0 ||
94
unpack_blob(v[12], &p->eddsa) < 0 ||
95
unpack_blob(v[13], &p->cred) < 0 ||
96
unpack_blob(v[14], &p->cdh) < 0)
97
goto fail;
98
99
ok = 0;
100
fail:
101
if (ok < 0) {
102
free(p);
103
p = NULL;
104
}
105
106
if (item)
107
cbor_decref(&item);
108
109
return p;
110
}
111
112
size_t
113
pack(uint8_t *ptr, size_t len, const struct param *p)
114
{
115
cbor_item_t *argv[15], *array = NULL;
116
size_t cbor_alloc_len, cbor_len = 0;
117
unsigned char *cbor = NULL;
118
119
memset(argv, 0, sizeof(argv));
120
121
if ((array = cbor_new_definite_array(15)) == NULL ||
122
(argv[0] = pack_byte(p->uv)) == NULL ||
123
(argv[1] = pack_byte(p->up)) == NULL ||
124
(argv[2] = pack_byte(p->opt)) == NULL ||
125
(argv[3] = pack_byte(p->type)) == NULL ||
126
(argv[4] = pack_byte(p->cred_count)) == NULL ||
127
(argv[5] = pack_int(p->ext)) == NULL ||
128
(argv[6] = pack_int(p->seed)) == NULL ||
129
(argv[7] = pack_string(p->rp_id)) == NULL ||
130
(argv[8] = pack_string(p->pin)) == NULL ||
131
(argv[9] = pack_blob(&p->wire_data)) == NULL ||
132
(argv[10] = pack_blob(&p->rs256)) == NULL ||
133
(argv[11] = pack_blob(&p->es256)) == NULL ||
134
(argv[12] = pack_blob(&p->eddsa)) == NULL ||
135
(argv[13] = pack_blob(&p->cred)) == NULL ||
136
(argv[14] = pack_blob(&p->cdh)) == NULL)
137
goto fail;
138
139
for (size_t i = 0; i < 15; i++)
140
if (cbor_array_push(array, argv[i]) == false)
141
goto fail;
142
143
if ((cbor_len = cbor_serialize_alloc(array, &cbor,
144
&cbor_alloc_len)) == 0 || cbor_len > len) {
145
cbor_len = 0;
146
goto fail;
147
}
148
149
memcpy(ptr, cbor, cbor_len);
150
fail:
151
for (size_t i = 0; i < 15; i++)
152
if (argv[i])
153
cbor_decref(&argv[i]);
154
155
if (array)
156
cbor_decref(&array);
157
158
free(cbor);
159
160
return cbor_len;
161
}
162
163
size_t
164
pack_dummy(uint8_t *ptr, size_t len)
165
{
166
struct param dummy;
167
uint8_t blob[MAXCORPUS];
168
size_t blob_len;
169
170
memset(&dummy, 0, sizeof(dummy));
171
172
dummy.type = 1; /* rsa */
173
dummy.ext = FIDO_EXT_HMAC_SECRET;
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.cred.len = sizeof(dummy_cdh); /* XXX */
179
dummy.cdh.len = sizeof(dummy_cdh);
180
dummy.es256.len = sizeof(dummy_es256);
181
dummy.rs256.len = sizeof(dummy_rs256);
182
dummy.eddsa.len = sizeof(dummy_eddsa);
183
dummy.wire_data.len = sizeof(dummy_wire_data_fido);
184
185
memcpy(&dummy.cred.body, &dummy_cdh, dummy.cred.len); /* XXX */
186
memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len);
187
memcpy(&dummy.wire_data.body, &dummy_wire_data_fido,
188
dummy.wire_data.len);
189
memcpy(&dummy.es256.body, &dummy_es256, dummy.es256.len);
190
memcpy(&dummy.rs256.body, &dummy_rs256, dummy.rs256.len);
191
memcpy(&dummy.eddsa.body, &dummy_eddsa, dummy.eddsa.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
get_assert(fido_assert_t *assert, uint8_t opt, const struct blob *cdh,
207
const char *rp_id, int ext, uint8_t up, uint8_t uv, const char *pin,
208
uint8_t cred_count, const struct blob *cred)
209
{
210
fido_dev_t *dev;
211
212
if ((dev = open_dev(opt & 2)) == NULL)
213
return;
214
if (opt & 1)
215
fido_dev_force_u2f(dev);
216
if (ext & FIDO_EXT_HMAC_SECRET)
217
fido_assert_set_extensions(assert, FIDO_EXT_HMAC_SECRET);
218
if (ext & FIDO_EXT_CRED_BLOB)
219
fido_assert_set_extensions(assert, FIDO_EXT_CRED_BLOB);
220
if (ext & FIDO_EXT_LARGEBLOB_KEY)
221
fido_assert_set_extensions(assert, FIDO_EXT_LARGEBLOB_KEY);
222
if (up & 1)
223
fido_assert_set_up(assert, FIDO_OPT_TRUE);
224
else if (opt & 1)
225
fido_assert_set_up(assert, FIDO_OPT_FALSE);
226
if (uv & 1)
227
fido_assert_set_uv(assert, FIDO_OPT_TRUE);
228
229
for (uint8_t i = 0; i < cred_count; i++)
230
fido_assert_allow_cred(assert, cred->body, cred->len);
231
232
fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len);
233
fido_assert_set_rp(assert, rp_id);
234
/* XXX reuse cred as hmac salt */
235
fido_assert_set_hmac_salt(assert, cred->body, cred->len);
236
237
/* repeat memory operations to trigger reallocation paths */
238
fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len);
239
fido_assert_set_rp(assert, rp_id);
240
fido_assert_set_hmac_salt(assert, cred->body, cred->len);
241
242
if (strlen(pin) == 0)
243
pin = NULL;
244
245
fido_dev_get_assert(dev, assert, (opt & 1) ? NULL : pin);
246
247
fido_dev_cancel(dev);
248
fido_dev_close(dev);
249
fido_dev_free(&dev);
250
}
251
252
static void
253
verify_assert(int type, const unsigned char *cdh_ptr, size_t cdh_len,
254
const char *rp_id, const unsigned char *authdata_ptr, size_t authdata_len,
255
const unsigned char *sig_ptr, size_t sig_len, uint8_t up, uint8_t uv,
256
int ext, void *pk)
257
{
258
fido_assert_t *assert = NULL;
259
int r;
260
261
if ((assert = fido_assert_new()) == NULL)
262
return;
263
264
fido_assert_set_clientdata_hash(assert, cdh_ptr, cdh_len);
265
fido_assert_set_rp(assert, rp_id);
266
fido_assert_set_count(assert, 1);
267
268
if (fido_assert_set_authdata(assert, 0, authdata_ptr,
269
authdata_len) != FIDO_OK) {
270
fido_assert_set_authdata_raw(assert, 0, authdata_ptr,
271
authdata_len);
272
}
273
274
if (up & 1)
275
fido_assert_set_up(assert, FIDO_OPT_TRUE);
276
if (uv & 1)
277
fido_assert_set_uv(assert, FIDO_OPT_TRUE);
278
279
fido_assert_set_extensions(assert, ext);
280
fido_assert_set_sig(assert, 0, sig_ptr, sig_len);
281
282
/* repeat memory operations to trigger reallocation paths */
283
if (fido_assert_set_authdata(assert, 0, authdata_ptr,
284
authdata_len) != FIDO_OK) {
285
fido_assert_set_authdata_raw(assert, 0, authdata_ptr,
286
authdata_len);
287
}
288
fido_assert_set_sig(assert, 0, sig_ptr, sig_len);
289
290
r = fido_assert_verify(assert, 0, type, pk);
291
consume(&r, sizeof(r));
292
293
fido_assert_free(&assert);
294
}
295
296
/*
297
* Do a dummy conversion to exercise es256_pk_from_EVP_PKEY().
298
*/
299
static void
300
es256_convert(const es256_pk_t *k)
301
{
302
EVP_PKEY *pkey = NULL;
303
es256_pk_t *pk = NULL;
304
int r;
305
306
if ((pkey = es256_pk_to_EVP_PKEY(k)) == NULL ||
307
(pk = es256_pk_new()) == NULL)
308
goto out;
309
310
r = es256_pk_from_EVP_PKEY(pk, pkey);
311
consume(&r, sizeof(r));
312
out:
313
es256_pk_free(&pk);
314
EVP_PKEY_free(pkey);
315
}
316
317
/*
318
* Do a dummy conversion to exercise es384_pk_from_EVP_PKEY().
319
*/
320
static void
321
es384_convert(const es384_pk_t *k)
322
{
323
EVP_PKEY *pkey = NULL;
324
es384_pk_t *pk = NULL;
325
int r;
326
327
if ((pkey = es384_pk_to_EVP_PKEY(k)) == NULL ||
328
(pk = es384_pk_new()) == NULL)
329
goto out;
330
331
r = es384_pk_from_EVP_PKEY(pk, pkey);
332
consume(&r, sizeof(r));
333
out:
334
es384_pk_free(&pk);
335
EVP_PKEY_free(pkey);
336
}
337
338
/*
339
* Do a dummy conversion to exercise rs256_pk_from_EVP_PKEY().
340
*/
341
static void
342
rs256_convert(const rs256_pk_t *k)
343
{
344
EVP_PKEY *pkey = NULL;
345
rs256_pk_t *pk = NULL;
346
int r;
347
348
if ((pkey = rs256_pk_to_EVP_PKEY(k)) == NULL ||
349
(pk = rs256_pk_new()) == NULL)
350
goto out;
351
352
r = rs256_pk_from_EVP_PKEY(pk, pkey);
353
consume(&r, sizeof(r));
354
out:
355
rs256_pk_free(&pk);
356
EVP_PKEY_free(pkey);
357
}
358
359
/*
360
* Do a dummy conversion to exercise eddsa_pk_from_EVP_PKEY().
361
*/
362
static void
363
eddsa_convert(const eddsa_pk_t *k)
364
{
365
EVP_PKEY *pkey = NULL;
366
eddsa_pk_t *pk = NULL;
367
int r;
368
369
if ((pkey = eddsa_pk_to_EVP_PKEY(k)) == NULL ||
370
(pk = eddsa_pk_new()) == NULL)
371
goto out;
372
373
r = eddsa_pk_from_EVP_PKEY(pk, pkey);
374
consume(&r, sizeof(r));
375
out:
376
if (pk)
377
eddsa_pk_free(&pk);
378
if (pkey)
379
EVP_PKEY_free(pkey);
380
}
381
382
void
383
test(const struct param *p)
384
{
385
fido_assert_t *assert = NULL;
386
es256_pk_t *es256_pk = NULL;
387
es384_pk_t *es384_pk = NULL;
388
rs256_pk_t *rs256_pk = NULL;
389
eddsa_pk_t *eddsa_pk = NULL;
390
uint8_t flags;
391
uint32_t sigcount;
392
int cose_alg = 0;
393
void *pk;
394
395
prng_init((unsigned int)p->seed);
396
fuzz_clock_reset();
397
fido_init(FIDO_DEBUG);
398
fido_set_log_handler(consume_str);
399
400
switch (p->type & 3) {
401
case 0:
402
cose_alg = COSE_ES256;
403
404
if ((es256_pk = es256_pk_new()) == NULL)
405
return;
406
407
es256_pk_from_ptr(es256_pk, p->es256.body, p->es256.len);
408
pk = es256_pk;
409
410
es256_convert(pk);
411
412
break;
413
case 1:
414
cose_alg = COSE_RS256;
415
416
if ((rs256_pk = rs256_pk_new()) == NULL)
417
return;
418
419
rs256_pk_from_ptr(rs256_pk, p->rs256.body, p->rs256.len);
420
pk = rs256_pk;
421
422
rs256_convert(pk);
423
424
break;
425
case 2:
426
cose_alg = COSE_ES384;
427
428
if ((es384_pk = es384_pk_new()) == NULL)
429
return;
430
431
/* XXX reuse p->es256 as es384 */
432
es384_pk_from_ptr(es384_pk, p->es256.body, p->es256.len);
433
pk = es384_pk;
434
435
es384_convert(pk);
436
437
break;
438
default:
439
cose_alg = COSE_EDDSA;
440
441
if ((eddsa_pk = eddsa_pk_new()) == NULL)
442
return;
443
444
eddsa_pk_from_ptr(eddsa_pk, p->eddsa.body, p->eddsa.len);
445
pk = eddsa_pk;
446
447
eddsa_convert(pk);
448
449
break;
450
}
451
452
if ((assert = fido_assert_new()) == NULL)
453
goto out;
454
455
set_wire_data(p->wire_data.body, p->wire_data.len);
456
457
get_assert(assert, p->opt, &p->cdh, p->rp_id, p->ext, p->up, p->uv,
458
p->pin, p->cred_count, &p->cred);
459
460
/* XXX +1 on purpose */
461
for (size_t i = 0; i <= fido_assert_count(assert); i++) {
462
verify_assert(cose_alg,
463
fido_assert_clientdata_hash_ptr(assert),
464
fido_assert_clientdata_hash_len(assert),
465
fido_assert_rp_id(assert),
466
fido_assert_authdata_ptr(assert, i),
467
fido_assert_authdata_len(assert, i),
468
fido_assert_sig_ptr(assert, i),
469
fido_assert_sig_len(assert, i), p->up, p->uv, p->ext, pk);
470
consume(fido_assert_authdata_raw_ptr(assert, i),
471
fido_assert_authdata_raw_len(assert, i));
472
consume(fido_assert_id_ptr(assert, i),
473
fido_assert_id_len(assert, i));
474
consume(fido_assert_user_id_ptr(assert, i),
475
fido_assert_user_id_len(assert, i));
476
consume(fido_assert_hmac_secret_ptr(assert, i),
477
fido_assert_hmac_secret_len(assert, i));
478
consume_str(fido_assert_user_icon(assert, i));
479
consume_str(fido_assert_user_name(assert, i));
480
consume_str(fido_assert_user_display_name(assert, i));
481
consume(fido_assert_blob_ptr(assert, i),
482
fido_assert_blob_len(assert, i));
483
consume(fido_assert_largeblob_key_ptr(assert, i),
484
fido_assert_largeblob_key_len(assert, i));
485
flags = fido_assert_flags(assert, i);
486
consume(&flags, sizeof(flags));
487
sigcount = fido_assert_sigcount(assert, i);
488
consume(&sigcount, sizeof(sigcount));
489
}
490
491
out:
492
es256_pk_free(&es256_pk);
493
es384_pk_free(&es384_pk);
494
rs256_pk_free(&rs256_pk);
495
eddsa_pk_free(&eddsa_pk);
496
497
fido_assert_free(&assert);
498
}
499
500
void
501
mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
502
{
503
if (flags & MUTATE_SEED)
504
p->seed = (int)seed;
505
506
if (flags & MUTATE_PARAM) {
507
mutate_byte(&p->uv);
508
mutate_byte(&p->up);
509
mutate_byte(&p->opt);
510
mutate_byte(&p->type);
511
mutate_byte(&p->cred_count);
512
mutate_int(&p->ext);
513
mutate_blob(&p->rs256);
514
mutate_blob(&p->es256);
515
mutate_blob(&p->eddsa);
516
mutate_blob(&p->cred);
517
mutate_blob(&p->cdh);
518
mutate_string(p->rp_id);
519
mutate_string(p->pin);
520
}
521
522
if (flags & MUTATE_WIREDATA) {
523
if (p->opt & 1) {
524
p->wire_data.len = sizeof(dummy_wire_data_u2f);
525
memcpy(&p->wire_data.body, &dummy_wire_data_u2f,
526
p->wire_data.len);
527
} else {
528
p->wire_data.len = sizeof(dummy_wire_data_fido);
529
memcpy(&p->wire_data.body, &dummy_wire_data_fido,
530
p->wire_data.len);
531
}
532
mutate_blob(&p->wire_data);
533
}
534
}
535
536