1 /* $OpenBSD: sk-usbhid.c,v 1.45 2022/09/14 00:14:37 djm Exp $ */ 2 /* 3 * Copyright (c) 2019 Markus Friedl 4 * Copyright (c) 2020 Pedro Martelletto 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <stdint.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <stdio.h> 23 #include <stddef.h> 24 #include <stdarg.h> 25 #include <time.h> 26 27 #ifdef WITH_OPENSSL 28 #include <openssl/opensslv.h> 29 #include <openssl/crypto.h> 30 #include <openssl/bn.h> 31 #include <openssl/ec.h> 32 #include <openssl/ecdsa.h> 33 #include <openssl/evp.h> 34 #endif /* WITH_OPENSSL */ 35 36 #include <fido.h> 37 #include <fido/credman.h> 38 39 #ifndef SK_STANDALONE 40 # include "log.h" 41 # include "xmalloc.h" 42 # include "misc.h" 43 /* 44 * If building as part of OpenSSH, then rename exported functions. 45 * This must be done before including sk-api.h. 46 */ 47 # define sk_api_version ssh_sk_api_version 48 # define sk_enroll ssh_sk_enroll 49 # define sk_sign ssh_sk_sign 50 # define sk_load_resident_keys ssh_sk_load_resident_keys 51 #endif /* !SK_STANDALONE */ 52 53 #include "sk-api.h" 54 55 /* #define SK_DEBUG 1 */ 56 57 #ifdef SK_DEBUG 58 #define SSH_FIDO_INIT_ARG FIDO_DEBUG 59 #else 60 #define SSH_FIDO_INIT_ARG 0 61 #endif 62 63 #define MAX_FIDO_DEVICES 8 64 #define FIDO_POLL_MS 50 65 #define SELECT_MS 15000 66 #define POLL_SLEEP_NS 200000000 67 68 /* Compatibility with OpenSSH 1.0.x */ 69 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) 70 #define ECDSA_SIG_get0(sig, pr, ps) \ 71 do { \ 72 (*pr) = sig->r; \ 73 (*ps) = sig->s; \ 74 } while (0) 75 #endif 76 #ifndef FIDO_ERR_OPERATION_DENIED 77 #define FIDO_ERR_OPERATION_DENIED 0x27 78 #endif 79 80 struct sk_usbhid { 81 fido_dev_t *dev; 82 char *path; 83 }; 84 85 /* Return the version of the middleware API */ 86 uint32_t sk_api_version(void); 87 88 /* Enroll a U2F key (private key generation) */ 89 int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, 90 const char *application, uint8_t flags, const char *pin, 91 struct sk_option **options, struct sk_enroll_response **enroll_response); 92 93 /* Sign a challenge */ 94 int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len, 95 const char *application, const uint8_t *key_handle, size_t key_handle_len, 96 uint8_t flags, const char *pin, struct sk_option **options, 97 struct sk_sign_response **sign_response); 98 99 /* Load resident keys */ 100 int sk_load_resident_keys(const char *pin, struct sk_option **options, 101 struct sk_resident_key ***rks, size_t *nrks); 102 103 static void skdebug(const char *func, const char *fmt, ...) 104 __attribute__((__format__ (printf, 2, 3))); 105 106 static void 107 skdebug(const char *func, const char *fmt, ...) 108 { 109 #if !defined(SK_STANDALONE) 110 char *msg; 111 va_list ap; 112 113 va_start(ap, fmt); 114 xvasprintf(&msg, fmt, ap); 115 va_end(ap); 116 debug("%s: %s", func, msg); 117 free(msg); 118 #elif defined(SK_DEBUG) 119 va_list ap; 120 121 va_start(ap, fmt); 122 fprintf(stderr, "%s: ", func); 123 vfprintf(stderr, fmt, ap); 124 fputc('\n', stderr); 125 va_end(ap); 126 #else 127 (void)func; /* XXX */ 128 (void)fmt; /* XXX */ 129 #endif 130 } 131 132 uint32_t 133 sk_api_version(void) 134 { 135 return SSH_SK_VERSION_MAJOR; 136 } 137 138 static struct sk_usbhid * 139 sk_open(const char *path) 140 { 141 struct sk_usbhid *sk; 142 int r; 143 144 if (path == NULL) { 145 skdebug(__func__, "path == NULL"); 146 return NULL; 147 } 148 if ((sk = calloc(1, sizeof(*sk))) == NULL) { 149 skdebug(__func__, "calloc sk failed"); 150 return NULL; 151 } 152 if ((sk->path = strdup(path)) == NULL) { 153 skdebug(__func__, "strdup path failed"); 154 free(sk); 155 return NULL; 156 } 157 if ((sk->dev = fido_dev_new()) == NULL) { 158 skdebug(__func__, "fido_dev_new failed"); 159 free(sk->path); 160 free(sk); 161 return NULL; 162 } 163 if ((r = fido_dev_open(sk->dev, sk->path)) != FIDO_OK) { 164 skdebug(__func__, "fido_dev_open %s failed: %s", sk->path, 165 fido_strerr(r)); 166 fido_dev_free(&sk->dev); 167 free(sk->path); 168 free(sk); 169 return NULL; 170 } 171 return sk; 172 } 173 174 static void 175 sk_close(struct sk_usbhid *sk) 176 { 177 if (sk == NULL) 178 return; 179 fido_dev_cancel(sk->dev); /* cancel any pending operation */ 180 fido_dev_close(sk->dev); 181 fido_dev_free(&sk->dev); 182 free(sk->path); 183 free(sk); 184 } 185 186 static struct sk_usbhid ** 187 sk_openv(const fido_dev_info_t *devlist, size_t ndevs, size_t *nopen) 188 { 189 const fido_dev_info_t *di; 190 struct sk_usbhid **skv; 191 size_t i; 192 193 *nopen = 0; 194 if ((skv = calloc(ndevs, sizeof(*skv))) == NULL) { 195 skdebug(__func__, "calloc skv failed"); 196 return NULL; 197 } 198 for (i = 0; i < ndevs; i++) { 199 if ((di = fido_dev_info_ptr(devlist, i)) == NULL) 200 skdebug(__func__, "fido_dev_info_ptr failed"); 201 else if ((skv[*nopen] = sk_open(fido_dev_info_path(di))) == NULL) 202 skdebug(__func__, "sk_open failed"); 203 else 204 (*nopen)++; 205 } 206 if (*nopen == 0) { 207 for (i = 0; i < ndevs; i++) 208 sk_close(skv[i]); 209 free(skv); 210 skv = NULL; 211 } 212 213 return skv; 214 } 215 216 static void 217 sk_closev(struct sk_usbhid **skv, size_t nsk) 218 { 219 size_t i; 220 221 for (i = 0; i < nsk; i++) 222 sk_close(skv[i]); 223 free(skv); 224 } 225 226 static int 227 sk_touch_begin(struct sk_usbhid **skv, size_t nsk) 228 { 229 size_t i, ok = 0; 230 int r; 231 232 for (i = 0; i < nsk; i++) 233 if ((r = fido_dev_get_touch_begin(skv[i]->dev)) != FIDO_OK) 234 skdebug(__func__, "fido_dev_get_touch_begin %s failed:" 235 " %s", skv[i]->path, fido_strerr(r)); 236 else 237 ok++; 238 239 return ok ? 0 : -1; 240 } 241 242 static int 243 sk_touch_poll(struct sk_usbhid **skv, size_t nsk, int *touch, size_t *idx) 244 { 245 struct timespec ts_pause; 246 size_t npoll, i; 247 int r; 248 249 ts_pause.tv_sec = 0; 250 ts_pause.tv_nsec = POLL_SLEEP_NS; 251 nanosleep(&ts_pause, NULL); 252 npoll = nsk; 253 for (i = 0; i < nsk; i++) { 254 if (skv[i] == NULL) 255 continue; /* device discarded */ 256 skdebug(__func__, "polling %s", skv[i]->path); 257 if ((r = fido_dev_get_touch_status(skv[i]->dev, touch, 258 FIDO_POLL_MS)) != FIDO_OK) { 259 skdebug(__func__, "fido_dev_get_touch_status %s: %s", 260 skv[i]->path, fido_strerr(r)); 261 sk_close(skv[i]); /* discard device */ 262 skv[i] = NULL; 263 if (--npoll == 0) { 264 skdebug(__func__, "no device left to poll"); 265 return -1; 266 } 267 } else if (*touch) { 268 *idx = i; 269 return 0; 270 } 271 } 272 *touch = 0; 273 return 0; 274 } 275 276 /* Check if the specified key handle exists on a given sk. */ 277 static int 278 sk_try(const struct sk_usbhid *sk, const char *application, 279 const uint8_t *key_handle, size_t key_handle_len) 280 { 281 fido_assert_t *assert = NULL; 282 int r = FIDO_ERR_INTERNAL; 283 uint8_t message[32]; 284 285 memset(message, '\0', sizeof(message)); 286 if ((assert = fido_assert_new()) == NULL) { 287 skdebug(__func__, "fido_assert_new failed"); 288 goto out; 289 } 290 /* generate an invalid signature on FIDO2 tokens */ 291 if ((r = fido_assert_set_clientdata(assert, message, 292 sizeof(message))) != FIDO_OK) { 293 skdebug(__func__, "fido_assert_set_clientdata: %s", 294 fido_strerr(r)); 295 goto out; 296 } 297 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { 298 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); 299 goto out; 300 } 301 if ((r = fido_assert_allow_cred(assert, key_handle, 302 key_handle_len)) != FIDO_OK) { 303 skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r)); 304 goto out; 305 } 306 if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) { 307 skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); 308 goto out; 309 } 310 r = fido_dev_get_assert(sk->dev, assert, NULL); 311 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); 312 if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { 313 /* U2F tokens may return this */ 314 r = FIDO_OK; 315 } 316 out: 317 fido_assert_free(&assert); 318 319 return r != FIDO_OK ? -1 : 0; 320 } 321 322 static int 323 check_sk_options(fido_dev_t *dev, const char *opt, int *ret) 324 { 325 fido_cbor_info_t *info; 326 char * const *name; 327 const bool *value; 328 size_t len, i; 329 int r; 330 331 *ret = -1; 332 333 if (!fido_dev_is_fido2(dev)) { 334 skdebug(__func__, "device is not fido2"); 335 return 0; 336 } 337 if ((info = fido_cbor_info_new()) == NULL) { 338 skdebug(__func__, "fido_cbor_info_new failed"); 339 return -1; 340 } 341 if ((r = fido_dev_get_cbor_info(dev, info)) != FIDO_OK) { 342 skdebug(__func__, "fido_dev_get_cbor_info: %s", fido_strerr(r)); 343 fido_cbor_info_free(&info); 344 return -1; 345 } 346 name = fido_cbor_info_options_name_ptr(info); 347 value = fido_cbor_info_options_value_ptr(info); 348 len = fido_cbor_info_options_len(info); 349 for (i = 0; i < len; i++) { 350 if (!strcmp(name[i], opt)) { 351 *ret = value[i]; 352 break; 353 } 354 } 355 fido_cbor_info_free(&info); 356 if (*ret == -1) 357 skdebug(__func__, "option %s is unknown", opt); 358 else 359 skdebug(__func__, "option %s is %s", opt, *ret ? "on" : "off"); 360 361 return 0; 362 } 363 364 static struct sk_usbhid * 365 sk_select_by_cred(const fido_dev_info_t *devlist, size_t ndevs, 366 const char *application, const uint8_t *key_handle, size_t key_handle_len) 367 { 368 struct sk_usbhid **skv, *sk; 369 size_t skvcnt, i; 370 int internal_uv; 371 372 if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) { 373 skdebug(__func__, "sk_openv failed"); 374 return NULL; 375 } 376 if (skvcnt == 1 && check_sk_options(skv[0]->dev, "uv", 377 &internal_uv) == 0 && internal_uv != -1) { 378 sk = skv[0]; 379 skv[0] = NULL; 380 goto out; 381 } 382 sk = NULL; 383 for (i = 0; i < skvcnt; i++) { 384 if (sk_try(skv[i], application, key_handle, 385 key_handle_len) == 0) { 386 sk = skv[i]; 387 skv[i] = NULL; 388 skdebug(__func__, "found key in %s", sk->path); 389 break; 390 } 391 } 392 out: 393 sk_closev(skv, skvcnt); 394 return sk; 395 } 396 397 static struct sk_usbhid * 398 sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs) 399 { 400 struct sk_usbhid **skv, *sk; 401 struct timeval tv_start, tv_now, tv_delta; 402 size_t skvcnt, idx; 403 int touch, ms_remain; 404 405 if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) { 406 skdebug(__func__, "sk_openv failed"); 407 return NULL; 408 } 409 sk = NULL; 410 if (skvcnt < 2) { 411 if (skvcnt == 1) { 412 /* single candidate */ 413 sk = skv[0]; 414 skv[0] = NULL; 415 } 416 goto out; 417 } 418 if (sk_touch_begin(skv, skvcnt) == -1) { 419 skdebug(__func__, "sk_touch_begin failed"); 420 goto out; 421 } 422 monotime_tv(&tv_start); 423 do { 424 if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) { 425 skdebug(__func__, "sk_touch_poll failed"); 426 goto out; 427 } 428 if (touch) { 429 sk = skv[idx]; 430 skv[idx] = NULL; 431 goto out; 432 } 433 monotime_tv(&tv_now); 434 timersub(&tv_now, &tv_start, &tv_delta); 435 ms_remain = SELECT_MS - tv_delta.tv_sec * 1000 - 436 tv_delta.tv_usec / 1000; 437 } while (ms_remain >= FIDO_POLL_MS); 438 skdebug(__func__, "timeout"); 439 out: 440 sk_closev(skv, skvcnt); 441 return sk; 442 } 443 444 static struct sk_usbhid * 445 sk_probe(const char *application, const uint8_t *key_handle, 446 size_t key_handle_len, int probe_resident) 447 { 448 struct sk_usbhid *sk; 449 fido_dev_info_t *devlist; 450 size_t ndevs; 451 int r; 452 453 if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) { 454 skdebug(__func__, "fido_dev_info_new failed"); 455 return NULL; 456 } 457 if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES, 458 &ndevs)) != FIDO_OK) { 459 skdebug(__func__, "fido_dev_info_manifest failed: %s", 460 fido_strerr(r)); 461 fido_dev_info_free(&devlist, MAX_FIDO_DEVICES); 462 return NULL; 463 } 464 skdebug(__func__, "%zu device(s) detected", ndevs); 465 if (ndevs == 0) { 466 sk = NULL; 467 } else if (application != NULL && key_handle != NULL) { 468 skdebug(__func__, "selecting sk by cred"); 469 sk = sk_select_by_cred(devlist, ndevs, application, key_handle, 470 key_handle_len); 471 } else { 472 skdebug(__func__, "selecting sk by touch"); 473 sk = sk_select_by_touch(devlist, ndevs); 474 } 475 fido_dev_info_free(&devlist, MAX_FIDO_DEVICES); 476 return sk; 477 } 478 479 #ifdef WITH_OPENSSL 480 /* 481 * The key returned via fido_cred_pubkey_ptr() is in affine coordinates, 482 * but the API expects a SEC1 octet string. 483 */ 484 static int 485 pack_public_key_ecdsa(const fido_cred_t *cred, 486 struct sk_enroll_response *response) 487 { 488 const uint8_t *ptr; 489 BIGNUM *x = NULL, *y = NULL; 490 EC_POINT *q = NULL; 491 EC_GROUP *g = NULL; 492 int ret = -1; 493 494 response->public_key = NULL; 495 response->public_key_len = 0; 496 497 if ((x = BN_new()) == NULL || 498 (y = BN_new()) == NULL || 499 (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL || 500 (q = EC_POINT_new(g)) == NULL) { 501 skdebug(__func__, "libcrypto setup failed"); 502 goto out; 503 } 504 if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { 505 skdebug(__func__, "fido_cred_pubkey_ptr failed"); 506 goto out; 507 } 508 if (fido_cred_pubkey_len(cred) != 64) { 509 skdebug(__func__, "bad fido_cred_pubkey_len %zu", 510 fido_cred_pubkey_len(cred)); 511 goto out; 512 } 513 514 if (BN_bin2bn(ptr, 32, x) == NULL || 515 BN_bin2bn(ptr + 32, 32, y) == NULL) { 516 skdebug(__func__, "BN_bin2bn failed"); 517 goto out; 518 } 519 if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) { 520 skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed"); 521 goto out; 522 } 523 response->public_key_len = EC_POINT_point2oct(g, q, 524 POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); 525 if (response->public_key_len == 0 || response->public_key_len > 2048) { 526 skdebug(__func__, "bad pubkey length %zu", 527 response->public_key_len); 528 goto out; 529 } 530 if ((response->public_key = malloc(response->public_key_len)) == NULL) { 531 skdebug(__func__, "malloc pubkey failed"); 532 goto out; 533 } 534 if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, 535 response->public_key, response->public_key_len, NULL) == 0) { 536 skdebug(__func__, "EC_POINT_point2oct failed"); 537 goto out; 538 } 539 /* success */ 540 ret = 0; 541 out: 542 if (ret != 0 && response->public_key != NULL) { 543 memset(response->public_key, 0, response->public_key_len); 544 free(response->public_key); 545 response->public_key = NULL; 546 } 547 EC_POINT_free(q); 548 EC_GROUP_free(g); 549 BN_clear_free(x); 550 BN_clear_free(y); 551 return ret; 552 } 553 #endif /* WITH_OPENSSL */ 554 555 static int 556 pack_public_key_ed25519(const fido_cred_t *cred, 557 struct sk_enroll_response *response) 558 { 559 const uint8_t *ptr; 560 size_t len; 561 int ret = -1; 562 563 response->public_key = NULL; 564 response->public_key_len = 0; 565 566 if ((len = fido_cred_pubkey_len(cred)) != 32) { 567 skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len); 568 goto out; 569 } 570 if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { 571 skdebug(__func__, "fido_cred_pubkey_ptr failed"); 572 goto out; 573 } 574 response->public_key_len = len; 575 if ((response->public_key = malloc(response->public_key_len)) == NULL) { 576 skdebug(__func__, "malloc pubkey failed"); 577 goto out; 578 } 579 memcpy(response->public_key, ptr, len); 580 ret = 0; 581 out: 582 if (ret != 0) 583 free(response->public_key); 584 return ret; 585 } 586 587 static int 588 pack_public_key(uint32_t alg, const fido_cred_t *cred, 589 struct sk_enroll_response *response) 590 { 591 switch(alg) { 592 #ifdef WITH_OPENSSL 593 case SSH_SK_ECDSA: 594 return pack_public_key_ecdsa(cred, response); 595 #endif /* WITH_OPENSSL */ 596 case SSH_SK_ED25519: 597 return pack_public_key_ed25519(cred, response); 598 default: 599 return -1; 600 } 601 } 602 603 static int 604 fidoerr_to_skerr(int fidoerr) 605 { 606 switch (fidoerr) { 607 case FIDO_ERR_UNSUPPORTED_OPTION: 608 case FIDO_ERR_UNSUPPORTED_ALGORITHM: 609 return SSH_SK_ERR_UNSUPPORTED; 610 case FIDO_ERR_PIN_REQUIRED: 611 case FIDO_ERR_PIN_INVALID: 612 case FIDO_ERR_OPERATION_DENIED: 613 return SSH_SK_ERR_PIN_REQUIRED; 614 default: 615 return -1; 616 } 617 } 618 619 static int 620 check_enroll_options(struct sk_option **options, char **devicep, 621 uint8_t *user_id, size_t user_id_len) 622 { 623 size_t i; 624 625 if (options == NULL) 626 return 0; 627 for (i = 0; options[i] != NULL; i++) { 628 if (strcmp(options[i]->name, "device") == 0) { 629 if ((*devicep = strdup(options[i]->value)) == NULL) { 630 skdebug(__func__, "strdup device failed"); 631 return -1; 632 } 633 skdebug(__func__, "requested device %s", *devicep); 634 } else if (strcmp(options[i]->name, "user") == 0) { 635 if (strlcpy(user_id, options[i]->value, user_id_len) >= 636 user_id_len) { 637 skdebug(__func__, "user too long"); 638 return -1; 639 } 640 skdebug(__func__, "requested user %s", 641 (char *)user_id); 642 } else { 643 skdebug(__func__, "requested unsupported option %s", 644 options[i]->name); 645 if (options[i]->required) { 646 skdebug(__func__, "unknown required option"); 647 return -1; 648 } 649 } 650 } 651 return 0; 652 } 653 654 static int 655 key_lookup(fido_dev_t *dev, const char *application, const uint8_t *user_id, 656 size_t user_id_len, const char *pin) 657 { 658 fido_assert_t *assert = NULL; 659 uint8_t message[32]; 660 int r = FIDO_ERR_INTERNAL; 661 int sk_supports_uv, uv; 662 size_t i; 663 664 memset(message, '\0', sizeof(message)); 665 if ((assert = fido_assert_new()) == NULL) { 666 skdebug(__func__, "fido_assert_new failed"); 667 goto out; 668 } 669 /* generate an invalid signature on FIDO2 tokens */ 670 if ((r = fido_assert_set_clientdata(assert, message, 671 sizeof(message))) != FIDO_OK) { 672 skdebug(__func__, "fido_assert_set_clientdata: %s", 673 fido_strerr(r)); 674 goto out; 675 } 676 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { 677 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); 678 goto out; 679 } 680 if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) { 681 skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); 682 goto out; 683 } 684 uv = FIDO_OPT_OMIT; 685 if (pin == NULL && check_sk_options(dev, "uv", &sk_supports_uv) == 0 && 686 sk_supports_uv != -1) 687 uv = FIDO_OPT_TRUE; 688 if ((r = fido_assert_set_uv(assert, uv)) != FIDO_OK) { 689 skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); 690 goto out; 691 } 692 if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) { 693 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); 694 goto out; 695 } 696 r = FIDO_ERR_NO_CREDENTIALS; 697 skdebug(__func__, "%zu signatures returned", fido_assert_count(assert)); 698 for (i = 0; i < fido_assert_count(assert); i++) { 699 if (fido_assert_user_id_len(assert, i) == user_id_len && 700 memcmp(fido_assert_user_id_ptr(assert, i), user_id, 701 user_id_len) == 0) { 702 skdebug(__func__, "credential exists"); 703 r = FIDO_OK; 704 goto out; 705 } 706 } 707 out: 708 fido_assert_free(&assert); 709 710 return r; 711 } 712 713 int 714 sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, 715 const char *application, uint8_t flags, const char *pin, 716 struct sk_option **options, struct sk_enroll_response **enroll_response) 717 { 718 fido_cred_t *cred = NULL; 719 const uint8_t *ptr; 720 uint8_t user_id[32]; 721 struct sk_usbhid *sk = NULL; 722 struct sk_enroll_response *response = NULL; 723 size_t len; 724 int credprot; 725 int cose_alg; 726 int ret = SSH_SK_ERR_GENERAL; 727 int r; 728 char *device = NULL; 729 730 fido_init(SSH_FIDO_INIT_ARG); 731 732 if (enroll_response == NULL) { 733 skdebug(__func__, "enroll_response == NULL"); 734 goto out; 735 } 736 *enroll_response = NULL; 737 memset(user_id, 0, sizeof(user_id)); 738 if (check_enroll_options(options, &device, user_id, 739 sizeof(user_id)) != 0) 740 goto out; /* error already logged */ 741 742 switch(alg) { 743 #ifdef WITH_OPENSSL 744 case SSH_SK_ECDSA: 745 cose_alg = COSE_ES256; 746 break; 747 #endif /* WITH_OPENSSL */ 748 case SSH_SK_ED25519: 749 cose_alg = COSE_EDDSA; 750 break; 751 default: 752 skdebug(__func__, "unsupported key type %d", alg); 753 goto out; 754 } 755 if (device != NULL) 756 sk = sk_open(device); 757 else 758 sk = sk_probe(NULL, NULL, 0, 0); 759 if (sk == NULL) { 760 ret = SSH_SK_ERR_DEVICE_NOT_FOUND; 761 skdebug(__func__, "failed to find sk"); 762 goto out; 763 } 764 skdebug(__func__, "using device %s", sk->path); 765 if ((flags & SSH_SK_RESIDENT_KEY) != 0 && 766 (flags & SSH_SK_FORCE_OPERATION) == 0 && 767 (r = key_lookup(sk->dev, application, user_id, sizeof(user_id), 768 pin)) != FIDO_ERR_NO_CREDENTIALS) { 769 if (r != FIDO_OK) { 770 ret = fidoerr_to_skerr(r); 771 skdebug(__func__, "key_lookup failed"); 772 } else { 773 ret = SSH_SK_ERR_CREDENTIAL_EXISTS; 774 skdebug(__func__, "key exists"); 775 } 776 goto out; 777 } 778 if ((cred = fido_cred_new()) == NULL) { 779 skdebug(__func__, "fido_cred_new failed"); 780 goto out; 781 } 782 if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) { 783 skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r)); 784 goto out; 785 } 786 if ((r = fido_cred_set_clientdata(cred, 787 challenge, challenge_len)) != FIDO_OK) { 788 skdebug(__func__, "fido_cred_set_clientdata: %s", 789 fido_strerr(r)); 790 goto out; 791 } 792 if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ? 793 FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) { 794 skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r)); 795 goto out; 796 } 797 if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id), 798 "openssh", "openssh", NULL)) != FIDO_OK) { 799 skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r)); 800 goto out; 801 } 802 if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) { 803 skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r)); 804 goto out; 805 } 806 if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) { 807 if (!fido_dev_supports_cred_prot(sk->dev)) { 808 skdebug(__func__, "%s does not support credprot, " 809 "refusing to create unprotected " 810 "resident/verify-required key", sk->path); 811 ret = SSH_SK_ERR_UNSUPPORTED; 812 goto out; 813 } 814 if ((flags & SSH_SK_USER_VERIFICATION_REQD)) 815 credprot = FIDO_CRED_PROT_UV_REQUIRED; 816 else 817 credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID; 818 819 if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) { 820 skdebug(__func__, "fido_cred_set_prot: %s", 821 fido_strerr(r)); 822 ret = fidoerr_to_skerr(r); 823 goto out; 824 } 825 } 826 if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) { 827 skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r)); 828 ret = fidoerr_to_skerr(r); 829 goto out; 830 } 831 if (fido_cred_x5c_ptr(cred) != NULL) { 832 if ((r = fido_cred_verify(cred)) != FIDO_OK) { 833 skdebug(__func__, "fido_cred_verify: %s", 834 fido_strerr(r)); 835 goto out; 836 } 837 } else { 838 skdebug(__func__, "self-attested credential"); 839 if ((r = fido_cred_verify_self(cred)) != FIDO_OK) { 840 skdebug(__func__, "fido_cred_verify_self: %s", 841 fido_strerr(r)); 842 goto out; 843 } 844 } 845 if ((response = calloc(1, sizeof(*response))) == NULL) { 846 skdebug(__func__, "calloc response failed"); 847 goto out; 848 } 849 response->flags = flags; 850 if (pack_public_key(alg, cred, response) != 0) { 851 skdebug(__func__, "pack_public_key failed"); 852 goto out; 853 } 854 if ((ptr = fido_cred_id_ptr(cred)) != NULL) { 855 len = fido_cred_id_len(cred); 856 if ((response->key_handle = calloc(1, len)) == NULL) { 857 skdebug(__func__, "calloc key handle failed"); 858 goto out; 859 } 860 memcpy(response->key_handle, ptr, len); 861 response->key_handle_len = len; 862 } 863 if ((ptr = fido_cred_sig_ptr(cred)) != NULL) { 864 len = fido_cred_sig_len(cred); 865 if ((response->signature = calloc(1, len)) == NULL) { 866 skdebug(__func__, "calloc signature failed"); 867 goto out; 868 } 869 memcpy(response->signature, ptr, len); 870 response->signature_len = len; 871 } 872 if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) { 873 len = fido_cred_x5c_len(cred); 874 skdebug(__func__, "attestation cert len=%zu", len); 875 if ((response->attestation_cert = calloc(1, len)) == NULL) { 876 skdebug(__func__, "calloc attestation cert failed"); 877 goto out; 878 } 879 memcpy(response->attestation_cert, ptr, len); 880 response->attestation_cert_len = len; 881 } 882 if ((ptr = fido_cred_authdata_ptr(cred)) != NULL) { 883 len = fido_cred_authdata_len(cred); 884 skdebug(__func__, "authdata len=%zu", len); 885 if ((response->authdata = calloc(1, len)) == NULL) { 886 skdebug(__func__, "calloc authdata failed"); 887 goto out; 888 } 889 memcpy(response->authdata, ptr, len); 890 response->authdata_len = len; 891 } 892 *enroll_response = response; 893 response = NULL; 894 ret = 0; 895 out: 896 free(device); 897 if (response != NULL) { 898 free(response->public_key); 899 free(response->key_handle); 900 free(response->signature); 901 free(response->attestation_cert); 902 free(response->authdata); 903 free(response); 904 } 905 sk_close(sk); 906 fido_cred_free(&cred); 907 return ret; 908 } 909 910 #ifdef WITH_OPENSSL 911 static int 912 pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response) 913 { 914 ECDSA_SIG *sig = NULL; 915 const BIGNUM *sig_r, *sig_s; 916 const unsigned char *cp; 917 size_t sig_len; 918 int ret = -1; 919 920 cp = fido_assert_sig_ptr(assert, 0); 921 sig_len = fido_assert_sig_len(assert, 0); 922 if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) { 923 skdebug(__func__, "d2i_ECDSA_SIG failed"); 924 goto out; 925 } 926 ECDSA_SIG_get0(sig, &sig_r, &sig_s); 927 response->sig_r_len = BN_num_bytes(sig_r); 928 response->sig_s_len = BN_num_bytes(sig_s); 929 if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL || 930 (response->sig_s = calloc(1, response->sig_s_len)) == NULL) { 931 skdebug(__func__, "calloc signature failed"); 932 goto out; 933 } 934 BN_bn2bin(sig_r, response->sig_r); 935 BN_bn2bin(sig_s, response->sig_s); 936 ret = 0; 937 out: 938 ECDSA_SIG_free(sig); 939 if (ret != 0) { 940 free(response->sig_r); 941 free(response->sig_s); 942 response->sig_r = NULL; 943 response->sig_s = NULL; 944 } 945 return ret; 946 } 947 #endif /* WITH_OPENSSL */ 948 949 static int 950 pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response) 951 { 952 const unsigned char *ptr; 953 size_t len; 954 int ret = -1; 955 956 ptr = fido_assert_sig_ptr(assert, 0); 957 len = fido_assert_sig_len(assert, 0); 958 if (len != 64) { 959 skdebug(__func__, "bad length %zu", len); 960 goto out; 961 } 962 response->sig_r_len = len; 963 if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) { 964 skdebug(__func__, "calloc signature failed"); 965 goto out; 966 } 967 memcpy(response->sig_r, ptr, len); 968 ret = 0; 969 out: 970 if (ret != 0) { 971 free(response->sig_r); 972 response->sig_r = NULL; 973 } 974 return ret; 975 } 976 977 static int 978 pack_sig(uint32_t alg, fido_assert_t *assert, 979 struct sk_sign_response *response) 980 { 981 switch(alg) { 982 #ifdef WITH_OPENSSL 983 case SSH_SK_ECDSA: 984 return pack_sig_ecdsa(assert, response); 985 #endif /* WITH_OPENSSL */ 986 case SSH_SK_ED25519: 987 return pack_sig_ed25519(assert, response); 988 default: 989 return -1; 990 } 991 } 992 993 /* Checks sk_options for sk_sign() and sk_load_resident_keys() */ 994 static int 995 check_sign_load_resident_options(struct sk_option **options, char **devicep) 996 { 997 size_t i; 998 999 if (options == NULL) 1000 return 0; 1001 for (i = 0; options[i] != NULL; i++) { 1002 if (strcmp(options[i]->name, "device") == 0) { 1003 if ((*devicep = strdup(options[i]->value)) == NULL) { 1004 skdebug(__func__, "strdup device failed"); 1005 return -1; 1006 } 1007 skdebug(__func__, "requested device %s", *devicep); 1008 } else { 1009 skdebug(__func__, "requested unsupported option %s", 1010 options[i]->name); 1011 if (options[i]->required) { 1012 skdebug(__func__, "unknown required option"); 1013 return -1; 1014 } 1015 } 1016 } 1017 return 0; 1018 } 1019 1020 int 1021 sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, 1022 const char *application, 1023 const uint8_t *key_handle, size_t key_handle_len, 1024 uint8_t flags, const char *pin, struct sk_option **options, 1025 struct sk_sign_response **sign_response) 1026 { 1027 fido_assert_t *assert = NULL; 1028 char *device = NULL; 1029 struct sk_usbhid *sk = NULL; 1030 struct sk_sign_response *response = NULL; 1031 int ret = SSH_SK_ERR_GENERAL, internal_uv; 1032 int r; 1033 1034 fido_init(SSH_FIDO_INIT_ARG); 1035 1036 if (sign_response == NULL) { 1037 skdebug(__func__, "sign_response == NULL"); 1038 goto out; 1039 } 1040 *sign_response = NULL; 1041 if (check_sign_load_resident_options(options, &device) != 0) 1042 goto out; /* error already logged */ 1043 if (device != NULL) 1044 sk = sk_open(device); 1045 else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD)) 1046 sk = sk_probe(NULL, NULL, 0, 0); 1047 else 1048 sk = sk_probe(application, key_handle, key_handle_len, 0); 1049 if (sk == NULL) { 1050 ret = SSH_SK_ERR_DEVICE_NOT_FOUND; 1051 skdebug(__func__, "failed to find sk"); 1052 goto out; 1053 } 1054 if ((assert = fido_assert_new()) == NULL) { 1055 skdebug(__func__, "fido_assert_new failed"); 1056 goto out; 1057 } 1058 if ((r = fido_assert_set_clientdata(assert, 1059 data, datalen)) != FIDO_OK) { 1060 skdebug(__func__, "fido_assert_set_clientdata: %s", 1061 fido_strerr(r)); 1062 goto out; 1063 } 1064 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { 1065 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); 1066 goto out; 1067 } 1068 if ((r = fido_assert_allow_cred(assert, key_handle, 1069 key_handle_len)) != FIDO_OK) { 1070 skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r)); 1071 goto out; 1072 } 1073 if ((r = fido_assert_set_up(assert, 1074 (flags & SSH_SK_USER_PRESENCE_REQD) ? 1075 FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) { 1076 skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); 1077 goto out; 1078 } 1079 if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD)) { 1080 if (check_sk_options(sk->dev, "uv", &internal_uv) < 0 || 1081 internal_uv != 1) { 1082 skdebug(__func__, "check_sk_options uv"); 1083 ret = SSH_SK_ERR_PIN_REQUIRED; 1084 goto out; 1085 } 1086 if ((r = fido_assert_set_uv(assert, 1087 FIDO_OPT_TRUE)) != FIDO_OK) { 1088 skdebug(__func__, "fido_assert_set_uv: %s", 1089 fido_strerr(r)); 1090 ret = fidoerr_to_skerr(r); 1091 goto out; 1092 } 1093 } 1094 if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) { 1095 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); 1096 ret = fidoerr_to_skerr(r); 1097 goto out; 1098 } 1099 if ((response = calloc(1, sizeof(*response))) == NULL) { 1100 skdebug(__func__, "calloc response failed"); 1101 goto out; 1102 } 1103 response->flags = fido_assert_flags(assert, 0); 1104 response->counter = fido_assert_sigcount(assert, 0); 1105 if (pack_sig(alg, assert, response) != 0) { 1106 skdebug(__func__, "pack_sig failed"); 1107 goto out; 1108 } 1109 *sign_response = response; 1110 response = NULL; 1111 ret = 0; 1112 out: 1113 free(device); 1114 if (response != NULL) { 1115 free(response->sig_r); 1116 free(response->sig_s); 1117 free(response); 1118 } 1119 sk_close(sk); 1120 fido_assert_free(&assert); 1121 return ret; 1122 } 1123 1124 static int 1125 read_rks(struct sk_usbhid *sk, const char *pin, 1126 struct sk_resident_key ***rksp, size_t *nrksp) 1127 { 1128 int ret = SSH_SK_ERR_GENERAL, r = -1, internal_uv; 1129 fido_credman_metadata_t *metadata = NULL; 1130 fido_credman_rp_t *rp = NULL; 1131 fido_credman_rk_t *rk = NULL; 1132 size_t i, j, nrp, nrk, user_id_len; 1133 const fido_cred_t *cred; 1134 const char *rp_id, *rp_name, *user_name; 1135 struct sk_resident_key *srk = NULL, **tmp; 1136 const u_char *user_id; 1137 1138 if (pin == NULL) { 1139 skdebug(__func__, "no PIN specified"); 1140 ret = SSH_SK_ERR_PIN_REQUIRED; 1141 goto out; 1142 } 1143 if ((metadata = fido_credman_metadata_new()) == NULL) { 1144 skdebug(__func__, "alloc failed"); 1145 goto out; 1146 } 1147 if (check_sk_options(sk->dev, "uv", &internal_uv) != 0) { 1148 skdebug(__func__, "check_sk_options failed"); 1149 goto out; 1150 } 1151 1152 if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) { 1153 if (r == FIDO_ERR_INVALID_COMMAND) { 1154 skdebug(__func__, "device %s does not support " 1155 "resident keys", sk->path); 1156 ret = 0; 1157 goto out; 1158 } 1159 skdebug(__func__, "get metadata for %s failed: %s", 1160 sk->path, fido_strerr(r)); 1161 ret = fidoerr_to_skerr(r); 1162 goto out; 1163 } 1164 skdebug(__func__, "existing %llu, remaining %llu", 1165 (unsigned long long)fido_credman_rk_existing(metadata), 1166 (unsigned long long)fido_credman_rk_remaining(metadata)); 1167 if ((rp = fido_credman_rp_new()) == NULL) { 1168 skdebug(__func__, "alloc rp failed"); 1169 goto out; 1170 } 1171 if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) { 1172 skdebug(__func__, "get RPs for %s failed: %s", 1173 sk->path, fido_strerr(r)); 1174 goto out; 1175 } 1176 nrp = fido_credman_rp_count(rp); 1177 skdebug(__func__, "Device %s has resident keys for %zu RPs", 1178 sk->path, nrp); 1179 1180 /* Iterate over RP IDs that have resident keys */ 1181 for (i = 0; i < nrp; i++) { 1182 rp_id = fido_credman_rp_id(rp, i); 1183 rp_name = fido_credman_rp_name(rp, i); 1184 skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu", 1185 i, rp_name == NULL ? "(none)" : rp_name, 1186 rp_id == NULL ? "(none)" : rp_id, 1187 fido_credman_rp_id_hash_len(rp, i)); 1188 1189 /* Skip non-SSH RP IDs */ 1190 if (rp_id == NULL || 1191 strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0) 1192 continue; 1193 1194 fido_credman_rk_free(&rk); 1195 if ((rk = fido_credman_rk_new()) == NULL) { 1196 skdebug(__func__, "alloc rk failed"); 1197 goto out; 1198 } 1199 if ((r = fido_credman_get_dev_rk(sk->dev, 1200 fido_credman_rp_id(rp, i), rk, pin)) != 0) { 1201 skdebug(__func__, "get RKs for %s slot %zu failed: %s", 1202 sk->path, i, fido_strerr(r)); 1203 goto out; 1204 } 1205 nrk = fido_credman_rk_count(rk); 1206 skdebug(__func__, "RP \"%s\" has %zu resident keys", 1207 fido_credman_rp_id(rp, i), nrk); 1208 1209 /* Iterate over resident keys for this RP ID */ 1210 for (j = 0; j < nrk; j++) { 1211 if ((cred = fido_credman_rk(rk, j)) == NULL) { 1212 skdebug(__func__, "no RK in slot %zu", j); 1213 continue; 1214 } 1215 if ((user_name = fido_cred_user_name(cred)) == NULL) 1216 user_name = ""; 1217 user_id = fido_cred_user_id_ptr(cred); 1218 user_id_len = fido_cred_user_id_len(cred); 1219 skdebug(__func__, "Device %s RP \"%s\" user \"%s\" " 1220 "uidlen %zu slot %zu: type %d flags 0x%02x " 1221 "prot 0x%02x", sk->path, rp_id, user_name, 1222 user_id_len, j, fido_cred_type(cred), 1223 fido_cred_flags(cred), fido_cred_prot(cred)); 1224 1225 /* build response entry */ 1226 if ((srk = calloc(1, sizeof(*srk))) == NULL || 1227 (srk->key.key_handle = calloc(1, 1228 fido_cred_id_len(cred))) == NULL || 1229 (srk->application = strdup(rp_id)) == NULL || 1230 (user_id_len > 0 && 1231 (srk->user_id = calloc(1, user_id_len)) == NULL)) { 1232 skdebug(__func__, "alloc sk_resident_key"); 1233 goto out; 1234 } 1235 1236 srk->key.key_handle_len = fido_cred_id_len(cred); 1237 memcpy(srk->key.key_handle, fido_cred_id_ptr(cred), 1238 srk->key.key_handle_len); 1239 srk->user_id_len = user_id_len; 1240 if (srk->user_id_len != 0) 1241 memcpy(srk->user_id, user_id, srk->user_id_len); 1242 1243 switch (fido_cred_type(cred)) { 1244 case COSE_ES256: 1245 srk->alg = SSH_SK_ECDSA; 1246 break; 1247 case COSE_EDDSA: 1248 srk->alg = SSH_SK_ED25519; 1249 break; 1250 default: 1251 skdebug(__func__, "unsupported key type %d", 1252 fido_cred_type(cred)); 1253 goto out; /* XXX free rk and continue */ 1254 } 1255 1256 if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED 1257 && internal_uv == -1) 1258 srk->flags |= SSH_SK_USER_VERIFICATION_REQD; 1259 1260 if ((r = pack_public_key(srk->alg, cred, 1261 &srk->key)) != 0) { 1262 skdebug(__func__, "pack public key failed"); 1263 goto out; 1264 } 1265 /* append */ 1266 if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1, 1267 sizeof(**rksp))) == NULL) { 1268 skdebug(__func__, "alloc rksp"); 1269 goto out; 1270 } 1271 *rksp = tmp; 1272 (*rksp)[(*nrksp)++] = srk; 1273 srk = NULL; 1274 } 1275 } 1276 /* Success */ 1277 ret = 0; 1278 out: 1279 if (srk != NULL) { 1280 free(srk->application); 1281 freezero(srk->key.public_key, srk->key.public_key_len); 1282 freezero(srk->key.key_handle, srk->key.key_handle_len); 1283 freezero(srk->user_id, srk->user_id_len); 1284 freezero(srk, sizeof(*srk)); 1285 } 1286 fido_credman_rp_free(&rp); 1287 fido_credman_rk_free(&rk); 1288 fido_credman_metadata_free(&metadata); 1289 return ret; 1290 } 1291 1292 int 1293 sk_load_resident_keys(const char *pin, struct sk_option **options, 1294 struct sk_resident_key ***rksp, size_t *nrksp) 1295 { 1296 int ret = SSH_SK_ERR_GENERAL, r = -1; 1297 size_t i, nrks = 0; 1298 struct sk_resident_key **rks = NULL; 1299 struct sk_usbhid *sk = NULL; 1300 char *device = NULL; 1301 1302 *rksp = NULL; 1303 *nrksp = 0; 1304 1305 fido_init(SSH_FIDO_INIT_ARG); 1306 1307 if (check_sign_load_resident_options(options, &device) != 0) 1308 goto out; /* error already logged */ 1309 if (device != NULL) 1310 sk = sk_open(device); 1311 else 1312 sk = sk_probe(NULL, NULL, 0, 1); 1313 if (sk == NULL) { 1314 ret = SSH_SK_ERR_DEVICE_NOT_FOUND; 1315 skdebug(__func__, "failed to find sk"); 1316 goto out; 1317 } 1318 skdebug(__func__, "trying %s", sk->path); 1319 if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) { 1320 skdebug(__func__, "read_rks failed for %s", sk->path); 1321 ret = r; 1322 goto out; 1323 } 1324 /* success, unless we have no keys but a specific error */ 1325 if (nrks > 0 || ret == SSH_SK_ERR_GENERAL) 1326 ret = 0; 1327 *rksp = rks; 1328 *nrksp = nrks; 1329 rks = NULL; 1330 nrks = 0; 1331 out: 1332 sk_close(sk); 1333 for (i = 0; i < nrks; i++) { 1334 free(rks[i]->application); 1335 freezero(rks[i]->key.public_key, rks[i]->key.public_key_len); 1336 freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len); 1337 freezero(rks[i]->user_id, rks[i]->user_id_len); 1338 freezero(rks[i], sizeof(*rks[i])); 1339 } 1340 free(device); 1341 free(rks); 1342 return ret; 1343 } 1344 1345