]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libfido2/fuzz/fuzz_largeblob.c
sqlite3: Vendor import of sqlite3 3.44.0
[FreeBSD/FreeBSD.git] / contrib / libfido2 / fuzz / fuzz_largeblob.c
1 /*
2  * Copyright (c) 2020 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 /* Parameter set defining a FIDO2 "large blob" operation. */
21 struct param {
22         char pin[MAXSTR];
23         int seed;
24         struct blob key;
25         struct blob get_wiredata;
26         struct blob set_wiredata;
27 };
28
29 /*
30  * Collection of HID reports from an authenticator issued with a FIDO2
31  * 'authenticatorLargeBlobs' 'get' command.
32  */
33 static const uint8_t dummy_get_wiredata[] = {
34         WIREDATA_CTAP_INIT,
35         WIREDATA_CTAP_CBOR_INFO,
36         WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY
37 };
38
39 /*
40  * Collection of HID reports from an authenticator issued with a FIDO2
41  * 'authenticatorLargeBlobs' 'set' command.
42  */
43 static const uint8_t dummy_set_wiredata[] = {
44         WIREDATA_CTAP_INIT,
45         WIREDATA_CTAP_CBOR_INFO,
46         WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY,
47         WIREDATA_CTAP_CBOR_AUTHKEY,
48         WIREDATA_CTAP_CBOR_PINTOKEN,
49         WIREDATA_CTAP_CBOR_STATUS
50 };
51
52 /*
53  * XXX this needs to match the encrypted blob embedded in
54  * WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY.
55  */
56 static const uint8_t dummy_key[] = {
57         0xa9, 0x1b, 0xc4, 0xdd, 0xfc, 0x9a, 0x93, 0x79,
58         0x75, 0xba, 0xf7, 0x7f, 0x4d, 0x57, 0xfc, 0xa6,
59         0xe1, 0xf8, 0x06, 0x43, 0x23, 0x99, 0x51, 0x32,
60         0xce, 0x6e, 0x19, 0x84, 0x50, 0x13, 0x2d, 0x7b
61 };
62
63 struct param *
64 unpack(const uint8_t *ptr, size_t len)
65 {
66         cbor_item_t *item = NULL, **v;
67         struct cbor_load_result cbor;
68         struct param *p;
69         int ok = -1;
70
71         if ((p = calloc(1, sizeof(*p))) == NULL ||
72             (item = cbor_load(ptr, len, &cbor)) == NULL ||
73             cbor.read != len ||
74             cbor_isa_array(item) == false ||
75             cbor_array_is_definite(item) == false ||
76             cbor_array_size(item) != 5 ||
77             (v = cbor_array_handle(item)) == NULL)
78                 goto fail;
79
80         if (unpack_int(v[0], &p->seed) < 0 ||
81             unpack_string(v[1], p->pin) < 0 ||
82             unpack_blob(v[2], &p->key) < 0 ||
83             unpack_blob(v[3], &p->get_wiredata) < 0 ||
84             unpack_blob(v[4], &p->set_wiredata) < 0)
85                 goto fail;
86
87         ok = 0;
88 fail:
89         if (ok < 0) {
90                 free(p);
91                 p = NULL;
92         }
93
94         if (item)
95                 cbor_decref(&item);
96
97         return p;
98 }
99
100 size_t
101 pack(uint8_t *ptr, size_t len, const struct param *p)
102 {
103         cbor_item_t *argv[5], *array = NULL;
104         size_t cbor_alloc_len, cbor_len = 0;
105         unsigned char *cbor = NULL;
106
107         memset(argv, 0, sizeof(argv));
108
109         if ((array = cbor_new_definite_array(5)) == NULL ||
110             (argv[0] = pack_int(p->seed)) == NULL ||
111             (argv[1] = pack_string(p->pin)) == NULL ||
112             (argv[2] = pack_blob(&p->key)) == NULL ||
113             (argv[3] = pack_blob(&p->get_wiredata)) == NULL ||
114             (argv[4] = pack_blob(&p->set_wiredata)) == NULL)
115                 goto fail;
116
117         for (size_t i = 0; i < 5; i++)
118                 if (cbor_array_push(array, argv[i]) == false)
119                         goto fail;
120
121         if ((cbor_len = cbor_serialize_alloc(array, &cbor,
122             &cbor_alloc_len)) == 0 || cbor_len > len) {
123                 cbor_len = 0;
124                 goto fail;
125         }
126
127         memcpy(ptr, cbor, cbor_len);
128 fail:
129         for (size_t i = 0; i < 5; i++)
130                 if (argv[i])
131                         cbor_decref(&argv[i]);
132
133         if (array)
134                 cbor_decref(&array);
135
136         free(cbor);
137
138         return cbor_len;
139 }
140
141 size_t
142 pack_dummy(uint8_t *ptr, size_t len)
143 {
144         struct param dummy;
145         uint8_t blob[MAXCORPUS];
146         size_t blob_len;
147
148         memset(&dummy, 0, sizeof(dummy));
149
150         strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
151
152         dummy.get_wiredata.len = sizeof(dummy_get_wiredata);
153         dummy.set_wiredata.len = sizeof(dummy_set_wiredata);
154         dummy.key.len = sizeof(dummy_key);
155
156         memcpy(&dummy.get_wiredata.body, &dummy_get_wiredata,
157             dummy.get_wiredata.len);
158         memcpy(&dummy.set_wiredata.body, &dummy_set_wiredata,
159             dummy.set_wiredata.len);
160         memcpy(&dummy.key.body, &dummy_key, dummy.key.len);
161
162         assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
163
164         if (blob_len > len) {
165                 memcpy(ptr, blob, len);
166                 return len;
167         }
168
169         memcpy(ptr, blob, blob_len);
170
171         return blob_len;
172 }
173
174 static fido_dev_t *
175 prepare_dev(void)
176 {
177         fido_dev_t *dev;
178
179         if ((dev = open_dev(0)) == NULL)
180                 return NULL;
181
182         return dev;
183 }
184
185 static void
186 get_blob(const struct param *p, int array)
187 {
188         fido_dev_t *dev;
189         u_char *ptr = NULL;
190         size_t len = 0;
191
192         set_wire_data(p->get_wiredata.body, p->get_wiredata.len);
193
194         if ((dev = prepare_dev()) == NULL)
195                 return;
196
197         if (array)
198                 fido_dev_largeblob_get_array(dev, &ptr, &len);
199         else
200                 fido_dev_largeblob_get(dev, p->key.body, p->key.len, &ptr, &len);
201         consume(ptr, len);
202         free(ptr);
203
204         fido_dev_close(dev);
205         fido_dev_free(&dev);
206 }
207
208
209 static void
210 set_blob(const struct param *p, int op)
211 {
212         fido_dev_t *dev;
213         const char *pin;
214
215         set_wire_data(p->set_wiredata.body, p->set_wiredata.len);
216
217         if ((dev = prepare_dev()) == NULL)
218                 return;
219         pin = p->pin;
220         if (strlen(pin) == 0)
221                 pin = NULL;
222
223         switch (op) {
224         case 0:
225                 fido_dev_largeblob_remove(dev, p->key.body, p->key.len, pin);
226                 break;
227         case 1:
228                 /* XXX reuse p->get_wiredata as the blob to be set */
229                 fido_dev_largeblob_set(dev, p->key.body, p->key.len,
230                     p->get_wiredata.body, p->get_wiredata.len, pin);
231                 break;
232         case 2:
233                 /* XXX reuse p->get_wiredata as the body of the cbor array */
234                 fido_dev_largeblob_set_array(dev, p->get_wiredata.body,
235                     p->get_wiredata.len, pin);
236         }
237
238         fido_dev_close(dev);
239         fido_dev_free(&dev);
240 }
241
242 void
243 test(const struct param *p)
244 {
245         prng_init((unsigned int)p->seed);
246         fuzz_clock_reset();
247         fido_init(FIDO_DEBUG);
248         fido_set_log_handler(consume_str);
249
250         get_blob(p, 0);
251         get_blob(p, 1);
252         set_blob(p, 0);
253         set_blob(p, 1);
254         set_blob(p, 2);
255 }
256
257 void
258 mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
259 {
260         if (flags & MUTATE_SEED)
261                 p->seed = (int)seed;
262
263         if (flags & MUTATE_PARAM) {
264                 mutate_blob(&p->key);
265                 mutate_string(p->pin);
266         }
267
268         if (flags & MUTATE_WIREDATA) {
269                 mutate_blob(&p->get_wiredata);
270                 mutate_blob(&p->set_wiredata);
271         }
272 }