xref: /freebsd/contrib/libfido2/fuzz/mutator_aux.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
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 
42 void
43 consume_str(const char *str)
44 {
45 	if (str != NULL)
46 		consume(str, strlen(str) + 1);
47 }
48 
49 int
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
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
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
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 *
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 *
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 *
122 pack_byte(uint8_t v) NO_MSAN
123 {
124 	return cbor_build_uint8(v);
125 }
126 
127 cbor_item_t *
128 pack_blob(const struct blob *v) NO_MSAN
129 {
130 	return cbor_build_bytestring(v->body, v->len);
131 }
132 
133 void
134 mutate_byte(uint8_t *b)
135 {
136 	LLVMFuzzerMutate(b, sizeof(*b), sizeof(*b));
137 }
138 
139 void
140 mutate_int(int *i)
141 {
142 	LLVMFuzzerMutate((uint8_t *)i, sizeof(*i), sizeof(*i));
143 }
144 
145 void
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
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
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
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 *
196 hid_open(const char *path)
197 {
198 	(void)path;
199 
200 	return (void *)HID_DEV_HANDLE;
201 }
202 
203 static void
204 hid_close(void *handle)
205 {
206 	assert(handle == (void *)HID_DEV_HANDLE);
207 }
208 
209 static int
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
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 *
229 nfc_open(const char *path)
230 {
231 	(void)path;
232 
233 	return (void *)NFC_DEV_HANDLE;
234 }
235 
236 static void
237 nfc_close(void *handle)
238 {
239 	assert(handle == (void *)NFC_DEV_HANDLE);
240 }
241 
242 static int
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
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
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
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 *
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
322 set_wire_data(const uint8_t *ptr, size_t len)
323 {
324 	wire_data_ptr = ptr;
325 	wire_data_len = len;
326 }
327