1 /* 2 * Copyright (c) 2018 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 <sys/types.h> 8 #include <sys/stat.h> 9 #ifdef HAVE_SYS_RANDOM_H 10 #include <sys/random.h> 11 #endif 12 13 #include <fcntl.h> 14 #include <stdint.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #ifdef HAVE_UNISTD_H 18 #include <unistd.h> 19 #endif 20 21 #include "fido.h" 22 23 #if defined(_WIN32) 24 #include <windows.h> 25 26 #include <winternl.h> 27 #include <winerror.h> 28 #include <stdio.h> 29 #include <bcrypt.h> 30 #include <sal.h> 31 32 static int 33 obtain_nonce(uint64_t *nonce) 34 { 35 NTSTATUS status; 36 37 status = BCryptGenRandom(NULL, (unsigned char *)nonce, sizeof(*nonce), 38 BCRYPT_USE_SYSTEM_PREFERRED_RNG); 39 40 if (!NT_SUCCESS(status)) 41 return (-1); 42 43 return (0); 44 } 45 #elif defined(HAVE_ARC4RANDOM_BUF) 46 static int 47 obtain_nonce(uint64_t *nonce) 48 { 49 arc4random_buf(nonce, sizeof(*nonce)); 50 return (0); 51 } 52 #elif defined(HAVE_GETRANDOM) 53 static int 54 obtain_nonce(uint64_t *nonce) 55 { 56 if (getrandom(nonce, sizeof(*nonce), 0) < 0) 57 return (-1); 58 return (0); 59 } 60 #elif defined(HAVE_DEV_URANDOM) 61 static int 62 obtain_nonce(uint64_t *nonce) 63 { 64 int fd = -1; 65 int ok = -1; 66 ssize_t r; 67 68 if ((fd = open(FIDO_RANDOM_DEV, O_RDONLY)) < 0) 69 goto fail; 70 if ((r = read(fd, nonce, sizeof(*nonce))) < 0 || 71 (size_t)r != sizeof(*nonce)) 72 goto fail; 73 74 ok = 0; 75 fail: 76 if (fd != -1) 77 close(fd); 78 79 return (ok); 80 } 81 #else 82 #error "please provide an implementation of obtain_nonce() for your platform" 83 #endif /* _WIN32 */ 84 85 #ifndef TLS 86 #define TLS 87 #endif 88 89 typedef struct dev_manifest_func_node { 90 dev_manifest_func_t manifest_func; 91 struct dev_manifest_func_node *next; 92 } dev_manifest_func_node_t; 93 94 static TLS dev_manifest_func_node_t *manifest_funcs = NULL; 95 96 static void 97 find_manifest_func_node(dev_manifest_func_t f, dev_manifest_func_node_t **curr, 98 dev_manifest_func_node_t **prev) 99 { 100 *prev = NULL; 101 *curr = manifest_funcs; 102 103 while (*curr != NULL && (*curr)->manifest_func != f) { 104 *prev = *curr; 105 *curr = (*curr)->next; 106 } 107 } 108 109 static int 110 fido_dev_open_tx(fido_dev_t *dev, const char *path) 111 { 112 const uint8_t cmd = CTAP_CMD_INIT; 113 114 if (dev->io_handle != NULL) { 115 fido_log_debug("%s: handle=%p", __func__, dev->io_handle); 116 return (FIDO_ERR_INVALID_ARGUMENT); 117 } 118 119 if (dev->io.open == NULL || dev->io.close == NULL) { 120 fido_log_debug("%s: NULL open/close", __func__); 121 return (FIDO_ERR_INVALID_ARGUMENT); 122 } 123 124 if (obtain_nonce(&dev->nonce) < 0) { 125 fido_log_debug("%s: obtain_nonce", __func__); 126 return (FIDO_ERR_INTERNAL); 127 } 128 129 if ((dev->io_handle = dev->io.open(path)) == NULL) { 130 fido_log_debug("%s: dev->io.open", __func__); 131 return (FIDO_ERR_INTERNAL); 132 } 133 134 if (fido_tx(dev, cmd, &dev->nonce, sizeof(dev->nonce)) < 0) { 135 fido_log_debug("%s: fido_tx", __func__); 136 dev->io.close(dev->io_handle); 137 dev->io_handle = NULL; 138 return (FIDO_ERR_TX); 139 } 140 141 return (FIDO_OK); 142 } 143 144 static int 145 fido_dev_open_rx(fido_dev_t *dev, int ms) 146 { 147 fido_cbor_info_t *info = NULL; 148 int reply_len; 149 int r; 150 151 if ((reply_len = fido_rx(dev, CTAP_CMD_INIT, &dev->attr, 152 sizeof(dev->attr), ms)) < 0) { 153 fido_log_debug("%s: fido_rx", __func__); 154 r = FIDO_ERR_RX; 155 goto fail; 156 } 157 158 #ifdef FIDO_FUZZ 159 dev->attr.nonce = dev->nonce; 160 #endif 161 162 if ((size_t)reply_len != sizeof(dev->attr) || 163 dev->attr.nonce != dev->nonce) { 164 fido_log_debug("%s: invalid nonce", __func__); 165 r = FIDO_ERR_RX; 166 goto fail; 167 } 168 169 dev->cid = dev->attr.cid; 170 171 if (fido_dev_is_fido2(dev)) { 172 if ((info = fido_cbor_info_new()) == NULL) { 173 fido_log_debug("%s: fido_cbor_info_new", __func__); 174 r = FIDO_ERR_INTERNAL; 175 goto fail; 176 } 177 if (fido_dev_get_cbor_info_wait(dev, info, ms) != FIDO_OK) { 178 fido_log_debug("%s: falling back to u2f", __func__); 179 fido_dev_force_u2f(dev); 180 } 181 } 182 183 if (fido_dev_is_fido2(dev) && info != NULL) { 184 fido_log_debug("%s: FIDO_MAXMSG=%d, maxmsgsiz=%lu", __func__, 185 FIDO_MAXMSG, (unsigned long)fido_cbor_info_maxmsgsiz(info)); 186 } 187 188 r = FIDO_OK; 189 fail: 190 fido_cbor_info_free(&info); 191 192 if (r != FIDO_OK) { 193 dev->io.close(dev->io_handle); 194 dev->io_handle = NULL; 195 } 196 197 return (r); 198 } 199 200 static int 201 fido_dev_open_wait(fido_dev_t *dev, const char *path, int ms) 202 { 203 int r; 204 205 if ((r = fido_dev_open_tx(dev, path)) != FIDO_OK || 206 (r = fido_dev_open_rx(dev, ms)) != FIDO_OK) 207 return (r); 208 209 return (FIDO_OK); 210 } 211 212 int 213 fido_dev_register_manifest_func(const dev_manifest_func_t f) 214 { 215 dev_manifest_func_node_t *prev, *curr, *n; 216 217 find_manifest_func_node(f, &curr, &prev); 218 if (curr != NULL) 219 return (FIDO_OK); 220 221 if ((n = calloc(1, sizeof(*n))) == NULL) { 222 fido_log_debug("%s: calloc", __func__); 223 return (FIDO_ERR_INTERNAL); 224 } 225 226 n->manifest_func = f; 227 n->next = manifest_funcs; 228 manifest_funcs = n; 229 230 return (FIDO_OK); 231 } 232 233 void 234 fido_dev_unregister_manifest_func(const dev_manifest_func_t f) 235 { 236 dev_manifest_func_node_t *prev, *curr; 237 238 find_manifest_func_node(f, &curr, &prev); 239 if (curr == NULL) 240 return; 241 if (prev != NULL) 242 prev->next = curr->next; 243 else 244 manifest_funcs = curr->next; 245 246 free(curr); 247 } 248 249 int 250 fido_dev_info_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) 251 { 252 dev_manifest_func_node_t *curr = NULL; 253 dev_manifest_func_t m_func; 254 size_t curr_olen; 255 int r; 256 257 *olen = 0; 258 259 if (fido_dev_register_manifest_func(fido_hid_manifest) != FIDO_OK) 260 return (FIDO_ERR_INTERNAL); 261 262 for (curr = manifest_funcs; curr != NULL; curr = curr->next) { 263 curr_olen = 0; 264 m_func = curr->manifest_func; 265 r = m_func(devlist + *olen, ilen - *olen, &curr_olen); 266 if (r != FIDO_OK) 267 return (r); 268 *olen += curr_olen; 269 if (*olen == ilen) 270 break; 271 } 272 273 return (FIDO_OK); 274 } 275 276 int 277 fido_dev_open_with_info(fido_dev_t *dev) 278 { 279 if (dev->path == NULL) 280 return (FIDO_ERR_INVALID_ARGUMENT); 281 282 return (fido_dev_open_wait(dev, dev->path, -1)); 283 } 284 285 int 286 fido_dev_open(fido_dev_t *dev, const char *path) 287 { 288 return (fido_dev_open_wait(dev, path, -1)); 289 } 290 291 int 292 fido_dev_close(fido_dev_t *dev) 293 { 294 if (dev->io_handle == NULL || dev->io.close == NULL) 295 return (FIDO_ERR_INVALID_ARGUMENT); 296 297 dev->io.close(dev->io_handle); 298 dev->io_handle = NULL; 299 300 return (FIDO_OK); 301 } 302 303 int 304 fido_dev_cancel(fido_dev_t *dev) 305 { 306 if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0) < 0) 307 return (FIDO_ERR_TX); 308 309 return (FIDO_OK); 310 } 311 312 int 313 fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io) 314 { 315 if (dev->io_handle != NULL) { 316 fido_log_debug("%s: NULL handle", __func__); 317 return (FIDO_ERR_INVALID_ARGUMENT); 318 } 319 320 if (io == NULL || io->open == NULL || io->close == NULL || 321 io->read == NULL || io->write == NULL) { 322 fido_log_debug("%s: NULL function", __func__); 323 return (FIDO_ERR_INVALID_ARGUMENT); 324 } 325 326 dev->io = *io; 327 328 return (FIDO_OK); 329 } 330 331 void 332 fido_init(int flags) 333 { 334 if (flags & FIDO_DEBUG || getenv("FIDO_DEBUG") != NULL) 335 fido_log_init(); 336 } 337 338 fido_dev_t * 339 fido_dev_new(void) 340 { 341 fido_dev_t *dev; 342 343 if ((dev = calloc(1, sizeof(*dev))) == NULL) 344 return (NULL); 345 346 dev->cid = CTAP_CID_BROADCAST; 347 dev->io = (fido_dev_io_t) { 348 &fido_hid_open, 349 &fido_hid_close, 350 &fido_hid_read, 351 &fido_hid_write, 352 NULL, 353 NULL, 354 }; 355 356 return (dev); 357 } 358 359 fido_dev_t * 360 fido_dev_new_with_info(const fido_dev_info_t *di) 361 { 362 fido_dev_t *dev; 363 364 if ((dev = calloc(1, sizeof(*dev))) == NULL) 365 return (NULL); 366 367 dev->cid = CTAP_CID_BROADCAST; 368 369 if (di->io.open == NULL || di->io.close == NULL || 370 di->io.read == NULL || di->io.write == NULL) { 371 fido_log_debug("%s: NULL function", __func__); 372 fido_dev_free(&dev); 373 return (NULL); 374 } 375 376 dev->io = di->io; 377 if ((dev->path = strdup(di->path)) == NULL) { 378 fido_log_debug("%s: strdup", __func__); 379 fido_dev_free(&dev); 380 return (NULL); 381 } 382 383 return (dev); 384 } 385 386 void 387 fido_dev_free(fido_dev_t **dev_p) 388 { 389 fido_dev_t *dev; 390 391 if (dev_p == NULL || (dev = *dev_p) == NULL) 392 return; 393 394 free(dev->path); 395 free(dev); 396 397 *dev_p = NULL; 398 } 399 400 uint8_t 401 fido_dev_protocol(const fido_dev_t *dev) 402 { 403 return (dev->attr.protocol); 404 } 405 406 uint8_t 407 fido_dev_major(const fido_dev_t *dev) 408 { 409 return (dev->attr.major); 410 } 411 412 uint8_t 413 fido_dev_minor(const fido_dev_t *dev) 414 { 415 return (dev->attr.minor); 416 } 417 418 uint8_t 419 fido_dev_build(const fido_dev_t *dev) 420 { 421 return (dev->attr.build); 422 } 423 424 uint8_t 425 fido_dev_flags(const fido_dev_t *dev) 426 { 427 return (dev->attr.flags); 428 } 429 430 bool 431 fido_dev_is_fido2(const fido_dev_t *dev) 432 { 433 return (dev->attr.flags & FIDO_CAP_CBOR); 434 } 435 436 void 437 fido_dev_force_u2f(fido_dev_t *dev) 438 { 439 dev->attr.flags &= ~FIDO_CAP_CBOR; 440 } 441 442 void 443 fido_dev_force_fido2(fido_dev_t *dev) 444 { 445 dev->attr.flags |= FIDO_CAP_CBOR; 446 } 447