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