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 <openssl/sha.h> 14 15 #include <fcntl.h> 16 #include <stdint.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #ifdef HAVE_UNISTD_H 20 #include <unistd.h> 21 #endif 22 23 #include "fido.h" 24 25 #if defined(_WIN32) 26 #include <windows.h> 27 28 #include <winternl.h> 29 #include <winerror.h> 30 #include <stdio.h> 31 #include <bcrypt.h> 32 #include <sal.h> 33 34 static int 35 obtain_nonce(uint64_t *nonce) 36 { 37 NTSTATUS status; 38 39 status = BCryptGenRandom(NULL, (unsigned char *)nonce, sizeof(*nonce), 40 BCRYPT_USE_SYSTEM_PREFERRED_RNG); 41 42 if (!NT_SUCCESS(status)) 43 return (-1); 44 45 return (0); 46 } 47 #elif defined(HAVE_ARC4RANDOM_BUF) 48 static int 49 obtain_nonce(uint64_t *nonce) 50 { 51 arc4random_buf(nonce, sizeof(*nonce)); 52 return (0); 53 } 54 #elif defined(HAVE_GETRANDOM) 55 static int 56 obtain_nonce(uint64_t *nonce) 57 { 58 if (getrandom(nonce, sizeof(*nonce), 0) < 0) 59 return (-1); 60 return (0); 61 } 62 #elif defined(HAVE_DEV_URANDOM) 63 static int 64 obtain_nonce(uint64_t *nonce) 65 { 66 int fd = -1; 67 int ok = -1; 68 ssize_t r; 69 70 if ((fd = open(FIDO_RANDOM_DEV, O_RDONLY)) < 0) 71 goto fail; 72 if ((r = read(fd, nonce, sizeof(*nonce))) < 0 || 73 (size_t)r != sizeof(*nonce)) 74 goto fail; 75 76 ok = 0; 77 fail: 78 if (fd != -1) 79 close(fd); 80 81 return (ok); 82 } 83 #else 84 #error "please provide an implementation of obtain_nonce() for your platform" 85 #endif /* _WIN32 */ 86 87 #ifndef TLS 88 #define TLS 89 #endif 90 91 typedef struct dev_manifest_func_node { 92 dev_manifest_func_t manifest_func; 93 struct dev_manifest_func_node *next; 94 } dev_manifest_func_node_t; 95 96 static TLS dev_manifest_func_node_t *manifest_funcs = NULL; 97 98 static void 99 find_manifest_func_node(dev_manifest_func_t f, dev_manifest_func_node_t **curr, 100 dev_manifest_func_node_t **prev) 101 { 102 *prev = NULL; 103 *curr = manifest_funcs; 104 105 while (*curr != NULL && (*curr)->manifest_func != f) { 106 *prev = *curr; 107 *curr = (*curr)->next; 108 } 109 } 110 111 #ifdef FIDO_FUZZ 112 static void 113 set_random_report_len(fido_dev_t *dev) 114 { 115 dev->rx_len = CTAP_MIN_REPORT_LEN + 116 uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1); 117 dev->tx_len = CTAP_MIN_REPORT_LEN + 118 uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1); 119 } 120 #endif 121 122 static void 123 fido_dev_set_flags(fido_dev_t *dev, const fido_cbor_info_t *info) 124 { 125 char * const *ptr; 126 const bool *val; 127 size_t len; 128 129 ptr = fido_cbor_info_extensions_ptr(info); 130 len = fido_cbor_info_extensions_len(info); 131 132 for (size_t i = 0; i < len; i++) 133 if (strcmp(ptr[i], "credProtect") == 0) 134 dev->flags |= FIDO_DEV_CRED_PROT; 135 136 ptr = fido_cbor_info_options_name_ptr(info); 137 val = fido_cbor_info_options_value_ptr(info); 138 len = fido_cbor_info_options_len(info); 139 140 for (size_t i = 0; i < len; i++) 141 if (strcmp(ptr[i], "clientPin") == 0) { 142 if (val[i] == true) 143 dev->flags |= FIDO_DEV_PIN_SET; 144 else 145 dev->flags |= FIDO_DEV_PIN_UNSET; 146 } 147 } 148 149 static int 150 fido_dev_open_tx(fido_dev_t *dev, const char *path) 151 { 152 const uint8_t cmd = CTAP_CMD_INIT; 153 int r; 154 155 if (dev->io_handle != NULL) { 156 fido_log_debug("%s: handle=%p", __func__, dev->io_handle); 157 return (FIDO_ERR_INVALID_ARGUMENT); 158 } 159 160 if (dev->io.open == NULL || dev->io.close == NULL) { 161 fido_log_debug("%s: NULL open/close", __func__); 162 return (FIDO_ERR_INVALID_ARGUMENT); 163 } 164 165 if (obtain_nonce(&dev->nonce) < 0) { 166 fido_log_debug("%s: obtain_nonce", __func__); 167 return (FIDO_ERR_INTERNAL); 168 } 169 170 if ((dev->io_handle = dev->io.open(path)) == NULL) { 171 fido_log_debug("%s: dev->io.open", __func__); 172 return (FIDO_ERR_INTERNAL); 173 } 174 175 if (dev->io_own) { 176 dev->rx_len = CTAP_MAX_REPORT_LEN; 177 dev->tx_len = CTAP_MAX_REPORT_LEN; 178 } else { 179 dev->rx_len = fido_hid_report_in_len(dev->io_handle); 180 dev->tx_len = fido_hid_report_out_len(dev->io_handle); 181 } 182 183 #ifdef FIDO_FUZZ 184 set_random_report_len(dev); 185 #endif 186 187 if (dev->rx_len < CTAP_MIN_REPORT_LEN || 188 dev->rx_len > CTAP_MAX_REPORT_LEN) { 189 fido_log_debug("%s: invalid rx_len %zu", __func__, dev->rx_len); 190 r = FIDO_ERR_RX; 191 goto fail; 192 } 193 194 if (dev->tx_len < CTAP_MIN_REPORT_LEN || 195 dev->tx_len > CTAP_MAX_REPORT_LEN) { 196 fido_log_debug("%s: invalid tx_len %zu", __func__, dev->tx_len); 197 r = FIDO_ERR_TX; 198 goto fail; 199 } 200 201 if (fido_tx(dev, cmd, &dev->nonce, sizeof(dev->nonce)) < 0) { 202 fido_log_debug("%s: fido_tx", __func__); 203 r = FIDO_ERR_TX; 204 goto fail; 205 } 206 207 return (FIDO_OK); 208 fail: 209 dev->io.close(dev->io_handle); 210 dev->io_handle = NULL; 211 212 return (r); 213 } 214 215 static int 216 fido_dev_open_rx(fido_dev_t *dev, int ms) 217 { 218 fido_cbor_info_t *info = NULL; 219 int reply_len; 220 int r; 221 222 if ((reply_len = fido_rx(dev, CTAP_CMD_INIT, &dev->attr, 223 sizeof(dev->attr), ms)) < 0) { 224 fido_log_debug("%s: fido_rx", __func__); 225 r = FIDO_ERR_RX; 226 goto fail; 227 } 228 229 #ifdef FIDO_FUZZ 230 dev->attr.nonce = dev->nonce; 231 #endif 232 233 if ((size_t)reply_len != sizeof(dev->attr) || 234 dev->attr.nonce != dev->nonce) { 235 fido_log_debug("%s: invalid nonce", __func__); 236 r = FIDO_ERR_RX; 237 goto fail; 238 } 239 240 dev->flags = 0; 241 dev->cid = dev->attr.cid; 242 243 if (fido_dev_is_fido2(dev)) { 244 if ((info = fido_cbor_info_new()) == NULL) { 245 fido_log_debug("%s: fido_cbor_info_new", __func__); 246 r = FIDO_ERR_INTERNAL; 247 goto fail; 248 } 249 if (fido_dev_get_cbor_info_wait(dev, info, ms) != FIDO_OK) { 250 fido_log_debug("%s: falling back to u2f", __func__); 251 fido_dev_force_u2f(dev); 252 } else { 253 fido_dev_set_flags(dev, info); 254 } 255 } 256 257 if (fido_dev_is_fido2(dev) && info != NULL) { 258 fido_log_debug("%s: FIDO_MAXMSG=%d, maxmsgsiz=%lu", __func__, 259 FIDO_MAXMSG, (unsigned long)fido_cbor_info_maxmsgsiz(info)); 260 } 261 262 r = FIDO_OK; 263 fail: 264 fido_cbor_info_free(&info); 265 266 if (r != FIDO_OK) { 267 dev->io.close(dev->io_handle); 268 dev->io_handle = NULL; 269 } 270 271 return (r); 272 } 273 274 static int 275 fido_dev_open_wait(fido_dev_t *dev, const char *path, int ms) 276 { 277 int r; 278 279 if ((r = fido_dev_open_tx(dev, path)) != FIDO_OK || 280 (r = fido_dev_open_rx(dev, ms)) != FIDO_OK) 281 return (r); 282 283 return (FIDO_OK); 284 } 285 286 int 287 fido_dev_register_manifest_func(const dev_manifest_func_t f) 288 { 289 dev_manifest_func_node_t *prev, *curr, *n; 290 291 find_manifest_func_node(f, &curr, &prev); 292 if (curr != NULL) 293 return (FIDO_OK); 294 295 if ((n = calloc(1, sizeof(*n))) == NULL) { 296 fido_log_debug("%s: calloc", __func__); 297 return (FIDO_ERR_INTERNAL); 298 } 299 300 n->manifest_func = f; 301 n->next = manifest_funcs; 302 manifest_funcs = n; 303 304 return (FIDO_OK); 305 } 306 307 void 308 fido_dev_unregister_manifest_func(const dev_manifest_func_t f) 309 { 310 dev_manifest_func_node_t *prev, *curr; 311 312 find_manifest_func_node(f, &curr, &prev); 313 if (curr == NULL) 314 return; 315 if (prev != NULL) 316 prev->next = curr->next; 317 else 318 manifest_funcs = curr->next; 319 320 free(curr); 321 } 322 323 int 324 fido_dev_info_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) 325 { 326 dev_manifest_func_node_t *curr = NULL; 327 dev_manifest_func_t m_func; 328 size_t curr_olen; 329 int r; 330 331 *olen = 0; 332 333 if (fido_dev_register_manifest_func(fido_hid_manifest) != FIDO_OK) 334 return (FIDO_ERR_INTERNAL); 335 336 for (curr = manifest_funcs; curr != NULL; curr = curr->next) { 337 curr_olen = 0; 338 m_func = curr->manifest_func; 339 r = m_func(devlist + *olen, ilen - *olen, &curr_olen); 340 if (r != FIDO_OK) 341 return (r); 342 *olen += curr_olen; 343 if (*olen == ilen) 344 break; 345 } 346 347 return (FIDO_OK); 348 } 349 350 int 351 fido_dev_open_with_info(fido_dev_t *dev) 352 { 353 if (dev->path == NULL) 354 return (FIDO_ERR_INVALID_ARGUMENT); 355 356 return (fido_dev_open_wait(dev, dev->path, -1)); 357 } 358 359 int 360 fido_dev_open(fido_dev_t *dev, const char *path) 361 { 362 return (fido_dev_open_wait(dev, path, -1)); 363 } 364 365 int 366 fido_dev_close(fido_dev_t *dev) 367 { 368 if (dev->io_handle == NULL || dev->io.close == NULL) 369 return (FIDO_ERR_INVALID_ARGUMENT); 370 371 dev->io.close(dev->io_handle); 372 dev->io_handle = NULL; 373 374 return (FIDO_OK); 375 } 376 377 int 378 fido_dev_cancel(fido_dev_t *dev) 379 { 380 if (fido_dev_is_fido2(dev) == false) 381 return (FIDO_ERR_INVALID_ARGUMENT); 382 383 if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0) < 0) 384 return (FIDO_ERR_TX); 385 386 return (FIDO_OK); 387 } 388 389 int 390 fido_dev_get_touch_begin(fido_dev_t *dev) 391 { 392 fido_blob_t f; 393 cbor_item_t *argv[9]; 394 const char *clientdata = FIDO_DUMMY_CLIENTDATA; 395 const uint8_t user_id = FIDO_DUMMY_USER_ID; 396 unsigned char cdh[SHA256_DIGEST_LENGTH]; 397 fido_rp_t rp; 398 fido_user_t user; 399 int r = FIDO_ERR_INTERNAL; 400 401 memset(&f, 0, sizeof(f)); 402 memset(argv, 0, sizeof(argv)); 403 memset(cdh, 0, sizeof(cdh)); 404 memset(&rp, 0, sizeof(rp)); 405 memset(&user, 0, sizeof(user)); 406 407 if (fido_dev_is_fido2(dev) == false) 408 return (u2f_get_touch_begin(dev)); 409 410 if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) { 411 fido_log_debug("%s: sha256", __func__); 412 return (FIDO_ERR_INTERNAL); 413 } 414 415 if ((rp.id = strdup(FIDO_DUMMY_RP_ID)) == NULL || 416 (user.name = strdup(FIDO_DUMMY_USER_NAME)) == NULL) { 417 fido_log_debug("%s: strdup", __func__); 418 goto fail; 419 } 420 421 if (fido_blob_set(&user.id, &user_id, sizeof(user_id)) < 0) { 422 fido_log_debug("%s: fido_blob_set", __func__); 423 goto fail; 424 } 425 426 if ((argv[0] = cbor_build_bytestring(cdh, sizeof(cdh))) == NULL || 427 (argv[1] = cbor_encode_rp_entity(&rp)) == NULL || 428 (argv[2] = cbor_encode_user_entity(&user)) == NULL || 429 (argv[3] = cbor_encode_pubkey_param(COSE_ES256)) == NULL) { 430 fido_log_debug("%s: cbor encode", __func__); 431 goto fail; 432 } 433 434 if (fido_dev_supports_pin(dev)) { 435 if ((argv[7] = cbor_new_definite_bytestring()) == NULL || 436 (argv[8] = cbor_encode_pin_opt()) == NULL) { 437 fido_log_debug("%s: cbor encode", __func__); 438 goto fail; 439 } 440 } 441 442 if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 || 443 fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) { 444 fido_log_debug("%s: fido_tx", __func__); 445 r = FIDO_ERR_TX; 446 goto fail; 447 } 448 449 r = FIDO_OK; 450 fail: 451 cbor_vector_free(argv, nitems(argv)); 452 free(f.ptr); 453 free(rp.id); 454 free(user.name); 455 free(user.id.ptr); 456 457 return (r); 458 } 459 460 int 461 fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms) 462 { 463 int r; 464 465 *touched = 0; 466 467 if (fido_dev_is_fido2(dev) == false) 468 return (u2f_get_touch_status(dev, touched, ms)); 469 470 switch ((r = fido_rx_cbor_status(dev, ms))) { 471 case FIDO_ERR_PIN_AUTH_INVALID: 472 case FIDO_ERR_PIN_INVALID: 473 case FIDO_ERR_PIN_NOT_SET: 474 case FIDO_ERR_SUCCESS: 475 *touched = 1; 476 break; 477 case FIDO_ERR_RX: 478 /* ignore */ 479 break; 480 default: 481 fido_log_debug("%s: fido_rx_cbor_status", __func__); 482 return (r); 483 } 484 485 return (FIDO_OK); 486 } 487 488 int 489 fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io) 490 { 491 if (dev->io_handle != NULL) { 492 fido_log_debug("%s: non-NULL handle", __func__); 493 return (FIDO_ERR_INVALID_ARGUMENT); 494 } 495 496 if (io == NULL || io->open == NULL || io->close == NULL || 497 io->read == NULL || io->write == NULL) { 498 fido_log_debug("%s: NULL function", __func__); 499 return (FIDO_ERR_INVALID_ARGUMENT); 500 } 501 502 dev->io = *io; 503 dev->io_own = true; 504 505 return (FIDO_OK); 506 } 507 508 int 509 fido_dev_set_transport_functions(fido_dev_t *dev, const fido_dev_transport_t *t) 510 { 511 if (dev->io_handle != NULL) { 512 fido_log_debug("%s: non-NULL handle", __func__); 513 return (FIDO_ERR_INVALID_ARGUMENT); 514 } 515 516 dev->transport = *t; 517 dev->io_own = true; 518 519 return (FIDO_OK); 520 } 521 522 void 523 fido_init(int flags) 524 { 525 if (flags & FIDO_DEBUG || getenv("FIDO_DEBUG") != NULL) 526 fido_log_init(); 527 } 528 529 fido_dev_t * 530 fido_dev_new(void) 531 { 532 fido_dev_t *dev; 533 534 if ((dev = calloc(1, sizeof(*dev))) == NULL) 535 return (NULL); 536 537 dev->cid = CTAP_CID_BROADCAST; 538 dev->io = (fido_dev_io_t) { 539 &fido_hid_open, 540 &fido_hid_close, 541 &fido_hid_read, 542 &fido_hid_write, 543 }; 544 545 return (dev); 546 } 547 548 fido_dev_t * 549 fido_dev_new_with_info(const fido_dev_info_t *di) 550 { 551 fido_dev_t *dev; 552 553 if ((dev = calloc(1, sizeof(*dev))) == NULL) 554 return (NULL); 555 556 dev->cid = CTAP_CID_BROADCAST; 557 558 if (di->io.open == NULL || di->io.close == NULL || 559 di->io.read == NULL || di->io.write == NULL) { 560 fido_log_debug("%s: NULL function", __func__); 561 fido_dev_free(&dev); 562 return (NULL); 563 } 564 565 dev->io = di->io; 566 dev->transport = di->transport; 567 568 if ((dev->path = strdup(di->path)) == NULL) { 569 fido_log_debug("%s: strdup", __func__); 570 fido_dev_free(&dev); 571 return (NULL); 572 } 573 574 return (dev); 575 } 576 577 void 578 fido_dev_free(fido_dev_t **dev_p) 579 { 580 fido_dev_t *dev; 581 582 if (dev_p == NULL || (dev = *dev_p) == NULL) 583 return; 584 585 free(dev->path); 586 free(dev); 587 588 *dev_p = NULL; 589 } 590 591 uint8_t 592 fido_dev_protocol(const fido_dev_t *dev) 593 { 594 return (dev->attr.protocol); 595 } 596 597 uint8_t 598 fido_dev_major(const fido_dev_t *dev) 599 { 600 return (dev->attr.major); 601 } 602 603 uint8_t 604 fido_dev_minor(const fido_dev_t *dev) 605 { 606 return (dev->attr.minor); 607 } 608 609 uint8_t 610 fido_dev_build(const fido_dev_t *dev) 611 { 612 return (dev->attr.build); 613 } 614 615 uint8_t 616 fido_dev_flags(const fido_dev_t *dev) 617 { 618 return (dev->attr.flags); 619 } 620 621 bool 622 fido_dev_is_fido2(const fido_dev_t *dev) 623 { 624 return (dev->attr.flags & FIDO_CAP_CBOR); 625 } 626 627 bool 628 fido_dev_supports_pin(const fido_dev_t *dev) 629 { 630 return (dev->flags & (FIDO_DEV_PIN_SET|FIDO_DEV_PIN_UNSET)); 631 } 632 633 bool 634 fido_dev_has_pin(const fido_dev_t *dev) 635 { 636 return (dev->flags & FIDO_DEV_PIN_SET); 637 } 638 639 bool 640 fido_dev_supports_cred_prot(const fido_dev_t *dev) 641 { 642 return (dev->flags & FIDO_DEV_CRED_PROT); 643 } 644 645 void 646 fido_dev_force_u2f(fido_dev_t *dev) 647 { 648 dev->attr.flags &= (uint8_t)~FIDO_CAP_CBOR; 649 dev->flags = 0; 650 } 651 652 void 653 fido_dev_force_fido2(fido_dev_t *dev) 654 { 655 dev->attr.flags |= FIDO_CAP_CBOR; 656 } 657