1 /*
2 * Copyright (c) 2019 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 */
6
7 #include <assert.h>
8 #include <cbor.h>
9 #include <errno.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "mutator_aux.h"
17
18 #define HID_DEV_HANDLE 0x68696421
19 #define NFC_DEV_HANDLE 0x6e666321
20
21 int fido_nfc_rx(fido_dev_t *, uint8_t, unsigned char *, size_t, int);
22 int fido_nfc_tx(fido_dev_t *, uint8_t, const unsigned char *, size_t);
23 size_t LLVMFuzzerMutate(uint8_t *, size_t, size_t);
24
25 static const uint8_t *wire_data_ptr = NULL;
26 static size_t wire_data_len = 0;
27
28 void
consume(const void * body,size_t len)29 consume(const void *body, size_t len)
30 {
31 const volatile uint8_t *ptr = body;
32 volatile uint8_t x = 0;
33
34 #ifdef WITH_MSAN
35 __msan_check_mem_is_initialized(body, len);
36 #endif
37
38 while (len--)
39 x ^= *ptr++;
40 }
41
42 void
consume_str(const char * str)43 consume_str(const char *str)
44 {
45 if (str != NULL)
46 consume(str, strlen(str) + 1);
47 }
48
49 int
unpack_int(cbor_item_t * item,int * v)50 unpack_int(cbor_item_t *item, int *v)
51 {
52 if (cbor_is_int(item) == false ||
53 cbor_int_get_width(item) != CBOR_INT_64)
54 return -1;
55
56 if (cbor_isa_uint(item))
57 *v = (int)cbor_get_uint64(item);
58 else
59 *v = (int)(-cbor_get_uint64(item) - 1);
60
61 return 0;
62 }
63
64 int
unpack_string(cbor_item_t * item,char * v)65 unpack_string(cbor_item_t *item, char *v)
66 {
67 size_t len;
68
69 if (cbor_isa_bytestring(item) == false ||
70 (len = cbor_bytestring_length(item)) >= MAXSTR)
71 return -1;
72
73 memcpy(v, cbor_bytestring_handle(item), len);
74 v[len] = '\0';
75
76 return 0;
77 }
78
79 int
unpack_byte(cbor_item_t * item,uint8_t * v)80 unpack_byte(cbor_item_t *item, uint8_t *v)
81 {
82 if (cbor_isa_uint(item) == false ||
83 cbor_int_get_width(item) != CBOR_INT_8)
84 return -1;
85
86 *v = cbor_get_uint8(item);
87
88 return 0;
89 }
90
91 int
unpack_blob(cbor_item_t * item,struct blob * v)92 unpack_blob(cbor_item_t *item, struct blob *v)
93 {
94 if (cbor_isa_bytestring(item) == false ||
95 (v->len = cbor_bytestring_length(item)) > sizeof(v->body))
96 return -1;
97
98 memcpy(v->body, cbor_bytestring_handle(item), v->len);
99
100 return 0;
101 }
102
103 cbor_item_t *
pack_int(int v)104 pack_int(int v) NO_MSAN
105 {
106 if (v < 0)
107 return cbor_build_negint64((uint64_t)(-(int64_t)v - 1));
108 else
109 return cbor_build_uint64((uint64_t)v);
110 }
111
112 cbor_item_t *
pack_string(const char * v)113 pack_string(const char *v) NO_MSAN
114 {
115 if (strlen(v) >= MAXSTR)
116 return NULL;
117
118 return cbor_build_bytestring((const unsigned char *)v, strlen(v));
119 }
120
121 cbor_item_t *
pack_byte(uint8_t v)122 pack_byte(uint8_t v) NO_MSAN
123 {
124 return cbor_build_uint8(v);
125 }
126
127 cbor_item_t *
pack_blob(const struct blob * v)128 pack_blob(const struct blob *v) NO_MSAN
129 {
130 return cbor_build_bytestring(v->body, v->len);
131 }
132
133 void
mutate_byte(uint8_t * b)134 mutate_byte(uint8_t *b)
135 {
136 LLVMFuzzerMutate(b, sizeof(*b), sizeof(*b));
137 }
138
139 void
mutate_int(int * i)140 mutate_int(int *i)
141 {
142 LLVMFuzzerMutate((uint8_t *)i, sizeof(*i), sizeof(*i));
143 }
144
145 void
mutate_blob(struct blob * blob)146 mutate_blob(struct blob *blob)
147 {
148 blob->len = LLVMFuzzerMutate((uint8_t *)blob->body, blob->len,
149 sizeof(blob->body));
150 }
151
152 void
mutate_string(char * s)153 mutate_string(char *s)
154 {
155 size_t n;
156
157 n = LLVMFuzzerMutate((uint8_t *)s, strlen(s), MAXSTR - 1);
158 s[n] = '\0';
159 }
160
161 /* XXX should fail, but doesn't */
162 static int
buf_read(unsigned char * ptr,size_t len,int ms)163 buf_read(unsigned char *ptr, size_t len, int ms)
164 {
165 size_t n;
166
167 (void)ms;
168
169 if (wire_data_len < len)
170 n = wire_data_len;
171 else
172 n = len;
173
174 memcpy(ptr, wire_data_ptr, n);
175
176 wire_data_ptr += n;
177 wire_data_len -= n;
178
179 return (int)n;
180 }
181
182 static int
buf_write(const unsigned char * ptr,size_t len)183 buf_write(const unsigned char *ptr, size_t len)
184 {
185 consume(ptr, len);
186
187 if (uniform_random(400) < 1) {
188 errno = EIO;
189 return -1;
190 }
191
192 return (int)len;
193 }
194
195 static void *
hid_open(const char * path)196 hid_open(const char *path)
197 {
198 (void)path;
199
200 return (void *)HID_DEV_HANDLE;
201 }
202
203 static void
hid_close(void * handle)204 hid_close(void *handle)
205 {
206 assert(handle == (void *)HID_DEV_HANDLE);
207 }
208
209 static int
hid_read(void * handle,unsigned char * ptr,size_t len,int ms)210 hid_read(void *handle, unsigned char *ptr, size_t len, int ms)
211 {
212 assert(handle == (void *)HID_DEV_HANDLE);
213 assert(len >= CTAP_MIN_REPORT_LEN && len <= CTAP_MAX_REPORT_LEN);
214
215 return buf_read(ptr, len, ms);
216 }
217
218 static int
hid_write(void * handle,const unsigned char * ptr,size_t len)219 hid_write(void *handle, const unsigned char *ptr, size_t len)
220 {
221 assert(handle == (void *)HID_DEV_HANDLE);
222 assert(len >= CTAP_MIN_REPORT_LEN + 1 &&
223 len <= CTAP_MAX_REPORT_LEN + 1);
224
225 return buf_write(ptr, len);
226 }
227
228 static void *
nfc_open(const char * path)229 nfc_open(const char *path)
230 {
231 (void)path;
232
233 return (void *)NFC_DEV_HANDLE;
234 }
235
236 static void
nfc_close(void * handle)237 nfc_close(void *handle)
238 {
239 assert(handle == (void *)NFC_DEV_HANDLE);
240 }
241
242 static int
nfc_read(void * handle,unsigned char * ptr,size_t len,int ms)243 nfc_read(void *handle, unsigned char *ptr, size_t len, int ms)
244 {
245 assert(handle == (void *)NFC_DEV_HANDLE);
246 assert(len > 0 && len <= 256 + 2);
247
248 return buf_read(ptr, len, ms);
249 }
250
251 static int
nfc_write(void * handle,const unsigned char * ptr,size_t len)252 nfc_write(void *handle, const unsigned char *ptr, size_t len)
253 {
254 assert(handle == (void *)NFC_DEV_HANDLE);
255 assert(len > 0 && len <= 256 + 2);
256
257 return buf_write(ptr, len);
258 }
259
260 ssize_t
fd_read(int fd,void * ptr,size_t len)261 fd_read(int fd, void *ptr, size_t len)
262 {
263 assert(fd != -1);
264
265 return buf_read(ptr, len, -1);
266 }
267
268 ssize_t
fd_write(int fd,const void * ptr,size_t len)269 fd_write(int fd, const void *ptr, size_t len)
270 {
271 assert(fd != -1);
272
273 return buf_write(ptr, len);
274 }
275
276 fido_dev_t *
open_dev(int nfc)277 open_dev(int nfc)
278 {
279 fido_dev_t *dev;
280 fido_dev_io_t io;
281 fido_dev_transport_t t;
282
283 memset(&io, 0, sizeof(io));
284 memset(&t, 0, sizeof(t));
285
286 if ((dev = fido_dev_new()) == NULL)
287 return NULL;
288
289 if (nfc) {
290 io.open = nfc_open;
291 io.close = nfc_close;
292 io.read = nfc_read;
293 io.write = nfc_write;
294 } else {
295 io.open = hid_open;
296 io.close = hid_close;
297 io.read = hid_read;
298 io.write = hid_write;
299 }
300
301 if (fido_dev_set_io_functions(dev, &io) != FIDO_OK)
302 goto fail;
303
304 if (nfc) {
305 t.rx = fido_nfc_rx;
306 t.tx = fido_nfc_tx;
307 if (fido_dev_set_transport_functions(dev, &t) != FIDO_OK)
308 goto fail;
309 }
310
311 if (fido_dev_open(dev, "nodev") != FIDO_OK)
312 goto fail;
313
314 return dev;
315 fail:
316 fido_dev_free(&dev);
317
318 return NULL;
319 }
320
321 void
set_wire_data(const uint8_t * ptr,size_t len)322 set_wire_data(const uint8_t *ptr, size_t len)
323 {
324 wire_data_ptr = ptr;
325 wire_data_len = len;
326 }
327