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