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 <fido.h> 9 #include <string.h> 10 11 #include "../fuzz/wiredata_fido2.h" 12 13 #define FAKE_DEV_HANDLE ((void *)0xdeadbeef) 14 #define REPORT_LEN (64 + 1) 15 16 static uint8_t ctap_nonce[8]; 17 static uint8_t *wiredata_ptr; 18 static size_t wiredata_len; 19 static int initialised; 20 21 static void * 22 dummy_open(const char *path) 23 { 24 (void)path; 25 26 return (FAKE_DEV_HANDLE); 27 } 28 29 static void 30 dummy_close(void *handle) 31 { 32 assert(handle == FAKE_DEV_HANDLE); 33 } 34 35 static int 36 dummy_read(void *handle, unsigned char *ptr, size_t len, int ms) 37 { 38 size_t n; 39 40 (void)ms; 41 42 assert(handle == FAKE_DEV_HANDLE); 43 assert(ptr != NULL); 44 assert(len == REPORT_LEN - 1); 45 46 if (wiredata_ptr == NULL) 47 return (-1); 48 49 if (!initialised) { 50 assert(wiredata_len >= REPORT_LEN - 1); 51 memcpy(&wiredata_ptr[7], &ctap_nonce, sizeof(ctap_nonce)); 52 initialised = 1; 53 } 54 55 if (wiredata_len < len) 56 n = wiredata_len; 57 else 58 n = len; 59 60 memcpy(ptr, wiredata_ptr, n); 61 wiredata_ptr += n; 62 wiredata_len -= n; 63 64 return ((int)n); 65 } 66 67 static int 68 dummy_write(void *handle, const unsigned char *ptr, size_t len) 69 { 70 assert(handle == FAKE_DEV_HANDLE); 71 assert(ptr != NULL); 72 assert(len == REPORT_LEN); 73 74 if (!initialised) 75 memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce)); 76 77 return ((int)len); 78 } 79 80 static uint8_t * 81 wiredata_setup(const uint8_t *data, size_t len) 82 { 83 const uint8_t ctap_init_data[] = { WIREDATA_CTAP_INIT }; 84 85 assert(wiredata_ptr == NULL); 86 assert(SIZE_MAX - len > sizeof(ctap_init_data)); 87 assert((wiredata_ptr = malloc(sizeof(ctap_init_data) + len)) != NULL); 88 89 memcpy(wiredata_ptr, ctap_init_data, sizeof(ctap_init_data)); 90 91 if (len) 92 memcpy(wiredata_ptr + sizeof(ctap_init_data), data, len); 93 94 wiredata_len = sizeof(ctap_init_data) + len; 95 96 return (wiredata_ptr); 97 } 98 99 static void 100 wiredata_clear(uint8_t **wiredata) 101 { 102 free(*wiredata); 103 *wiredata = NULL; 104 wiredata_ptr = NULL; 105 wiredata_len = 0; 106 initialised = 0; 107 } 108 109 /* gh#56 */ 110 static void 111 open_iff_ok(void) 112 { 113 fido_dev_t *dev = NULL; 114 fido_dev_io_t io; 115 116 memset(&io, 0, sizeof(io)); 117 118 io.open = dummy_open; 119 io.close = dummy_close; 120 io.read = dummy_read; 121 io.write = dummy_write; 122 123 assert((dev = fido_dev_new()) != NULL); 124 assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 125 assert(fido_dev_open(dev, "dummy") == FIDO_ERR_RX); 126 assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); 127 128 fido_dev_free(&dev); 129 } 130 131 static void 132 reopen(void) 133 { 134 const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; 135 uint8_t *wiredata; 136 fido_dev_t *dev = NULL; 137 fido_dev_io_t io; 138 139 memset(&io, 0, sizeof(io)); 140 141 io.open = dummy_open; 142 io.close = dummy_close; 143 io.read = dummy_read; 144 io.write = dummy_write; 145 146 wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 147 assert((dev = fido_dev_new()) != NULL); 148 assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 149 assert(fido_dev_open(dev, "dummy") == FIDO_OK); 150 assert(fido_dev_close(dev) == FIDO_OK); 151 wiredata_clear(&wiredata); 152 153 wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 154 assert(fido_dev_open(dev, "dummy") == FIDO_OK); 155 assert(fido_dev_close(dev) == FIDO_OK); 156 wiredata_clear(&wiredata); 157 } 158 159 static void 160 double_open(void) 161 { 162 const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; 163 uint8_t *wiredata; 164 fido_dev_t *dev = NULL; 165 fido_dev_io_t io; 166 167 memset(&io, 0, sizeof(io)); 168 169 io.open = dummy_open; 170 io.close = dummy_close; 171 io.read = dummy_read; 172 io.write = dummy_write; 173 174 wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 175 assert((dev = fido_dev_new()) != NULL); 176 assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 177 assert(fido_dev_open(dev, "dummy") == FIDO_OK); 178 assert(fido_dev_open(dev, "dummy") == FIDO_ERR_INVALID_ARGUMENT); 179 assert(fido_dev_close(dev) == FIDO_OK); 180 wiredata_clear(&wiredata); 181 } 182 183 static void 184 is_fido2(void) 185 { 186 const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; 187 uint8_t *wiredata; 188 fido_dev_t *dev = NULL; 189 fido_dev_io_t io; 190 191 memset(&io, 0, sizeof(io)); 192 193 io.open = dummy_open; 194 io.close = dummy_close; 195 io.read = dummy_read; 196 io.write = dummy_write; 197 198 wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 199 assert((dev = fido_dev_new()) != NULL); 200 assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 201 assert(fido_dev_open(dev, "dummy") == FIDO_OK); 202 assert(fido_dev_is_fido2(dev) == true); 203 assert(fido_dev_supports_pin(dev) == true); 204 fido_dev_force_u2f(dev); 205 assert(fido_dev_is_fido2(dev) == false); 206 assert(fido_dev_supports_pin(dev) == false); 207 assert(fido_dev_close(dev) == FIDO_OK); 208 wiredata_clear(&wiredata); 209 210 wiredata = wiredata_setup(NULL, 0); 211 assert(fido_dev_open(dev, "dummy") == FIDO_OK); 212 assert(fido_dev_is_fido2(dev) == false); 213 assert(fido_dev_supports_pin(dev) == false); 214 fido_dev_force_fido2(dev); 215 assert(fido_dev_is_fido2(dev) == true); 216 assert(fido_dev_supports_pin(dev) == false); 217 assert(fido_dev_close(dev) == FIDO_OK); 218 wiredata_clear(&wiredata); 219 } 220 221 static void 222 has_pin(void) 223 { 224 const uint8_t set_pin_data[] = { 225 WIREDATA_CTAP_CBOR_INFO, 226 WIREDATA_CTAP_CBOR_AUTHKEY, 227 WIREDATA_CTAP_CBOR_STATUS, 228 WIREDATA_CTAP_CBOR_STATUS 229 }; 230 uint8_t *wiredata; 231 fido_dev_t *dev = NULL; 232 fido_dev_io_t io; 233 234 memset(&io, 0, sizeof(io)); 235 236 io.open = dummy_open; 237 io.close = dummy_close; 238 io.read = dummy_read; 239 io.write = dummy_write; 240 241 wiredata = wiredata_setup(set_pin_data, sizeof(set_pin_data)); 242 assert((dev = fido_dev_new()) != NULL); 243 assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 244 assert(fido_dev_open(dev, "dummy") == FIDO_OK); 245 assert(fido_dev_has_pin(dev) == false); 246 assert(fido_dev_set_pin(dev, "top secret", NULL) == FIDO_OK); 247 assert(fido_dev_has_pin(dev) == true); 248 assert(fido_dev_reset(dev) == FIDO_OK); 249 assert(fido_dev_has_pin(dev) == false); 250 assert(fido_dev_close(dev) == FIDO_OK); 251 wiredata_clear(&wiredata); 252 } 253 254 int 255 main(void) 256 { 257 fido_init(0); 258 259 open_iff_ok(); 260 reopen(); 261 double_open(); 262 is_fido2(); 263 has_pin(); 264 265 exit(0); 266 } 267