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