1 /* $OpenBSD: sk-usbhid.c,v 1.41 2022/07/20 03:31:42 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) 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 size_t i; 662 663 memset(message, '\0', sizeof(message)); 664 if (pin == NULL) { 665 skdebug(__func__, "NULL pin"); 666 goto out; 667 } 668 if ((assert = fido_assert_new()) == NULL) { 669 skdebug(__func__, "fido_assert_new failed"); 670 goto out; 671 } 672 /* generate an invalid signature on FIDO2 tokens */ 673 if ((r = fido_assert_set_clientdata(assert, message, 674 sizeof(message))) != FIDO_OK) { 675 skdebug(__func__, "fido_assert_set_clientdata: %s", 676 fido_strerr(r)); 677 goto out; 678 } 679 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { 680 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); 681 goto out; 682 } 683 if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) { 684 skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); 685 goto out; 686 } 687 if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) { 688 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); 689 goto out; 690 } 691 r = FIDO_ERR_NO_CREDENTIALS; 692 skdebug(__func__, "%zu signatures returned", fido_assert_count(assert)); 693 for (i = 0; i < fido_assert_count(assert); i++) { 694 if (fido_assert_user_id_len(assert, i) == user_id_len && 695 memcmp(fido_assert_user_id_ptr(assert, i), user_id, 696 user_id_len) == 0) { 697 skdebug(__func__, "credential exists"); 698 r = FIDO_OK; 699 goto out; 700 } 701 } 702 out: 703 fido_assert_free(&assert); 704 705 return r; 706 } 707 708 int 709 sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, 710 const char *application, uint8_t flags, const char *pin, 711 struct sk_option **options, struct sk_enroll_response **enroll_response) 712 { 713 fido_cred_t *cred = NULL; 714 const uint8_t *ptr; 715 uint8_t user_id[32]; 716 struct sk_usbhid *sk = NULL; 717 struct sk_enroll_response *response = NULL; 718 size_t len; 719 int credprot; 720 int internal_uv; 721 int cose_alg; 722 int ret = SSH_SK_ERR_GENERAL; 723 int r; 724 char *device = NULL; 725 726 fido_init(SSH_FIDO_INIT_ARG); 727 728 if (enroll_response == NULL) { 729 skdebug(__func__, "enroll_response == NULL"); 730 goto out; 731 } 732 *enroll_response = NULL; 733 memset(user_id, 0, sizeof(user_id)); 734 if (check_enroll_options(options, &device, user_id, 735 sizeof(user_id)) != 0) 736 goto out; /* error already logged */ 737 738 switch(alg) { 739 #ifdef WITH_OPENSSL 740 case SSH_SK_ECDSA: 741 cose_alg = COSE_ES256; 742 break; 743 #endif /* WITH_OPENSSL */ 744 case SSH_SK_ED25519: 745 cose_alg = COSE_EDDSA; 746 break; 747 default: 748 skdebug(__func__, "unsupported key type %d", alg); 749 goto out; 750 } 751 if (device != NULL) 752 sk = sk_open(device); 753 else 754 sk = sk_probe(NULL, NULL, 0); 755 if (sk == NULL) { 756 ret = SSH_SK_ERR_DEVICE_NOT_FOUND; 757 skdebug(__func__, "failed to find sk"); 758 goto out; 759 } 760 skdebug(__func__, "using device %s", sk->path); 761 if ((flags & SSH_SK_RESIDENT_KEY) != 0 && 762 (flags & SSH_SK_FORCE_OPERATION) == 0 && 763 (r = key_lookup(sk->dev, application, user_id, sizeof(user_id), 764 pin)) != FIDO_ERR_NO_CREDENTIALS) { 765 if (r != FIDO_OK) { 766 ret = fidoerr_to_skerr(r); 767 skdebug(__func__, "key_lookup failed"); 768 } else { 769 ret = SSH_SK_ERR_CREDENTIAL_EXISTS; 770 skdebug(__func__, "key exists"); 771 } 772 goto out; 773 } 774 if ((cred = fido_cred_new()) == NULL) { 775 skdebug(__func__, "fido_cred_new failed"); 776 goto out; 777 } 778 if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) { 779 skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r)); 780 goto out; 781 } 782 if ((r = fido_cred_set_clientdata(cred, 783 challenge, challenge_len)) != FIDO_OK) { 784 skdebug(__func__, "fido_cred_set_clientdata: %s", 785 fido_strerr(r)); 786 goto out; 787 } 788 if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ? 789 FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) { 790 skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r)); 791 goto out; 792 } 793 if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id), 794 "openssh", "openssh", NULL)) != FIDO_OK) { 795 skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r)); 796 goto out; 797 } 798 if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) { 799 skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r)); 800 goto out; 801 } 802 if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) { 803 if (!fido_dev_supports_cred_prot(sk->dev)) { 804 skdebug(__func__, "%s does not support credprot, " 805 "refusing to create unprotected " 806 "resident/verify-required key", sk->path); 807 ret = SSH_SK_ERR_UNSUPPORTED; 808 goto out; 809 } 810 if ((flags & SSH_SK_USER_VERIFICATION_REQD)) 811 credprot = FIDO_CRED_PROT_UV_REQUIRED; 812 else 813 credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID; 814 815 if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) { 816 skdebug(__func__, "fido_cred_set_prot: %s", 817 fido_strerr(r)); 818 ret = fidoerr_to_skerr(r); 819 goto out; 820 } 821 } 822 if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) { 823 skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r)); 824 ret = fidoerr_to_skerr(r); 825 goto out; 826 } 827 if (fido_cred_x5c_ptr(cred) != NULL) { 828 if ((r = fido_cred_verify(cred)) != FIDO_OK) { 829 skdebug(__func__, "fido_cred_verify: %s", 830 fido_strerr(r)); 831 goto out; 832 } 833 } else { 834 skdebug(__func__, "self-attested credential"); 835 if ((r = fido_cred_verify_self(cred)) != FIDO_OK) { 836 skdebug(__func__, "fido_cred_verify_self: %s", 837 fido_strerr(r)); 838 goto out; 839 } 840 } 841 if ((response = calloc(1, sizeof(*response))) == NULL) { 842 skdebug(__func__, "calloc response failed"); 843 goto out; 844 } 845 response->flags = flags; 846 if ((flags & SSH_SK_USER_VERIFICATION_REQD)) { 847 if (check_sk_options(sk->dev, "uv", &internal_uv) == 0 && 848 internal_uv != -1) { 849 /* user verification handled by token */ 850 response->flags &= ~SSH_SK_USER_VERIFICATION_REQD; 851 } 852 } 853 if (pack_public_key(alg, cred, response) != 0) { 854 skdebug(__func__, "pack_public_key failed"); 855 goto out; 856 } 857 if ((ptr = fido_cred_id_ptr(cred)) != NULL) { 858 len = fido_cred_id_len(cred); 859 if ((response->key_handle = calloc(1, len)) == NULL) { 860 skdebug(__func__, "calloc key handle failed"); 861 goto out; 862 } 863 memcpy(response->key_handle, ptr, len); 864 response->key_handle_len = len; 865 } 866 if ((ptr = fido_cred_sig_ptr(cred)) != NULL) { 867 len = fido_cred_sig_len(cred); 868 if ((response->signature = calloc(1, len)) == NULL) { 869 skdebug(__func__, "calloc signature failed"); 870 goto out; 871 } 872 memcpy(response->signature, ptr, len); 873 response->signature_len = len; 874 } 875 if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) { 876 len = fido_cred_x5c_len(cred); 877 skdebug(__func__, "attestation cert len=%zu", len); 878 if ((response->attestation_cert = calloc(1, len)) == NULL) { 879 skdebug(__func__, "calloc attestation cert failed"); 880 goto out; 881 } 882 memcpy(response->attestation_cert, ptr, len); 883 response->attestation_cert_len = len; 884 } 885 if ((ptr = fido_cred_authdata_ptr(cred)) != NULL) { 886 len = fido_cred_authdata_len(cred); 887 skdebug(__func__, "authdata len=%zu", len); 888 if ((response->authdata = calloc(1, len)) == NULL) { 889 skdebug(__func__, "calloc authdata failed"); 890 goto out; 891 } 892 memcpy(response->authdata, ptr, len); 893 response->authdata_len = len; 894 } 895 *enroll_response = response; 896 response = NULL; 897 ret = 0; 898 out: 899 free(device); 900 if (response != NULL) { 901 free(response->public_key); 902 free(response->key_handle); 903 free(response->signature); 904 free(response->attestation_cert); 905 free(response->authdata); 906 free(response); 907 } 908 sk_close(sk); 909 fido_cred_free(&cred); 910 return ret; 911 } 912 913 #ifdef WITH_OPENSSL 914 static int 915 pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response) 916 { 917 ECDSA_SIG *sig = NULL; 918 const BIGNUM *sig_r, *sig_s; 919 const unsigned char *cp; 920 size_t sig_len; 921 int ret = -1; 922 923 cp = fido_assert_sig_ptr(assert, 0); 924 sig_len = fido_assert_sig_len(assert, 0); 925 if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) { 926 skdebug(__func__, "d2i_ECDSA_SIG failed"); 927 goto out; 928 } 929 ECDSA_SIG_get0(sig, &sig_r, &sig_s); 930 response->sig_r_len = BN_num_bytes(sig_r); 931 response->sig_s_len = BN_num_bytes(sig_s); 932 if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL || 933 (response->sig_s = calloc(1, response->sig_s_len)) == NULL) { 934 skdebug(__func__, "calloc signature failed"); 935 goto out; 936 } 937 BN_bn2bin(sig_r, response->sig_r); 938 BN_bn2bin(sig_s, response->sig_s); 939 ret = 0; 940 out: 941 ECDSA_SIG_free(sig); 942 if (ret != 0) { 943 free(response->sig_r); 944 free(response->sig_s); 945 response->sig_r = NULL; 946 response->sig_s = NULL; 947 } 948 return ret; 949 } 950 #endif /* WITH_OPENSSL */ 951 952 static int 953 pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response) 954 { 955 const unsigned char *ptr; 956 size_t len; 957 int ret = -1; 958 959 ptr = fido_assert_sig_ptr(assert, 0); 960 len = fido_assert_sig_len(assert, 0); 961 if (len != 64) { 962 skdebug(__func__, "bad length %zu", len); 963 goto out; 964 } 965 response->sig_r_len = len; 966 if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) { 967 skdebug(__func__, "calloc signature failed"); 968 goto out; 969 } 970 memcpy(response->sig_r, ptr, len); 971 ret = 0; 972 out: 973 if (ret != 0) { 974 free(response->sig_r); 975 response->sig_r = NULL; 976 } 977 return ret; 978 } 979 980 static int 981 pack_sig(uint32_t alg, fido_assert_t *assert, 982 struct sk_sign_response *response) 983 { 984 switch(alg) { 985 #ifdef WITH_OPENSSL 986 case SSH_SK_ECDSA: 987 return pack_sig_ecdsa(assert, response); 988 #endif /* WITH_OPENSSL */ 989 case SSH_SK_ED25519: 990 return pack_sig_ed25519(assert, response); 991 default: 992 return -1; 993 } 994 } 995 996 /* Checks sk_options for sk_sign() and sk_load_resident_keys() */ 997 static int 998 check_sign_load_resident_options(struct sk_option **options, char **devicep) 999 { 1000 size_t i; 1001 1002 if (options == NULL) 1003 return 0; 1004 for (i = 0; options[i] != NULL; i++) { 1005 if (strcmp(options[i]->name, "device") == 0) { 1006 if ((*devicep = strdup(options[i]->value)) == NULL) { 1007 skdebug(__func__, "strdup device failed"); 1008 return -1; 1009 } 1010 skdebug(__func__, "requested device %s", *devicep); 1011 } else { 1012 skdebug(__func__, "requested unsupported option %s", 1013 options[i]->name); 1014 if (options[i]->required) { 1015 skdebug(__func__, "unknown required option"); 1016 return -1; 1017 } 1018 } 1019 } 1020 return 0; 1021 } 1022 1023 int 1024 sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, 1025 const char *application, 1026 const uint8_t *key_handle, size_t key_handle_len, 1027 uint8_t flags, const char *pin, struct sk_option **options, 1028 struct sk_sign_response **sign_response) 1029 { 1030 fido_assert_t *assert = NULL; 1031 char *device = NULL; 1032 struct sk_usbhid *sk = NULL; 1033 struct sk_sign_response *response = NULL; 1034 int ret = SSH_SK_ERR_GENERAL, internal_uv; 1035 int r; 1036 1037 fido_init(SSH_FIDO_INIT_ARG); 1038 1039 if (sign_response == NULL) { 1040 skdebug(__func__, "sign_response == NULL"); 1041 goto out; 1042 } 1043 *sign_response = NULL; 1044 if (check_sign_load_resident_options(options, &device) != 0) 1045 goto out; /* error already logged */ 1046 if (device != NULL) 1047 sk = sk_open(device); 1048 else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD)) 1049 sk = sk_probe(NULL, NULL, 0); 1050 else 1051 sk = sk_probe(application, key_handle, key_handle_len); 1052 if (sk == NULL) { 1053 ret = SSH_SK_ERR_DEVICE_NOT_FOUND; 1054 skdebug(__func__, "failed to find sk"); 1055 goto out; 1056 } 1057 if ((assert = fido_assert_new()) == NULL) { 1058 skdebug(__func__, "fido_assert_new failed"); 1059 goto out; 1060 } 1061 if ((r = fido_assert_set_clientdata(assert, 1062 data, datalen)) != FIDO_OK) { 1063 skdebug(__func__, "fido_assert_set_clientdata: %s", 1064 fido_strerr(r)); 1065 goto out; 1066 } 1067 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { 1068 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); 1069 goto out; 1070 } 1071 if ((r = fido_assert_allow_cred(assert, key_handle, 1072 key_handle_len)) != FIDO_OK) { 1073 skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r)); 1074 goto out; 1075 } 1076 if ((r = fido_assert_set_up(assert, 1077 (flags & SSH_SK_USER_PRESENCE_REQD) ? 1078 FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) { 1079 skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); 1080 goto out; 1081 } 1082 if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD)) { 1083 if (check_sk_options(sk->dev, "uv", &internal_uv) < 0 || 1084 internal_uv != 1) { 1085 skdebug(__func__, "check_sk_options uv"); 1086 ret = SSH_SK_ERR_PIN_REQUIRED; 1087 goto out; 1088 } 1089 if ((r = fido_assert_set_uv(assert, 1090 FIDO_OPT_TRUE)) != FIDO_OK) { 1091 skdebug(__func__, "fido_assert_set_uv: %s", 1092 fido_strerr(r)); 1093 ret = fidoerr_to_skerr(r); 1094 goto out; 1095 } 1096 } 1097 if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) { 1098 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); 1099 ret = fidoerr_to_skerr(r); 1100 goto out; 1101 } 1102 if ((response = calloc(1, sizeof(*response))) == NULL) { 1103 skdebug(__func__, "calloc response failed"); 1104 goto out; 1105 } 1106 response->flags = fido_assert_flags(assert, 0); 1107 response->counter = fido_assert_sigcount(assert, 0); 1108 if (pack_sig(alg, assert, response) != 0) { 1109 skdebug(__func__, "pack_sig failed"); 1110 goto out; 1111 } 1112 *sign_response = response; 1113 response = NULL; 1114 ret = 0; 1115 out: 1116 free(device); 1117 if (response != NULL) { 1118 free(response->sig_r); 1119 free(response->sig_s); 1120 free(response); 1121 } 1122 sk_close(sk); 1123 fido_assert_free(&assert); 1124 return ret; 1125 } 1126 1127 static int 1128 read_rks(struct sk_usbhid *sk, const char *pin, 1129 struct sk_resident_key ***rksp, size_t *nrksp) 1130 { 1131 int ret = SSH_SK_ERR_GENERAL, r = -1, internal_uv; 1132 fido_credman_metadata_t *metadata = NULL; 1133 fido_credman_rp_t *rp = NULL; 1134 fido_credman_rk_t *rk = NULL; 1135 size_t i, j, nrp, nrk, user_id_len; 1136 const fido_cred_t *cred; 1137 const char *rp_id, *rp_name, *user_name; 1138 struct sk_resident_key *srk = NULL, **tmp; 1139 const u_char *user_id; 1140 1141 if (pin == NULL) { 1142 skdebug(__func__, "no PIN specified"); 1143 ret = SSH_SK_ERR_PIN_REQUIRED; 1144 goto out; 1145 } 1146 if ((metadata = fido_credman_metadata_new()) == NULL) { 1147 skdebug(__func__, "alloc failed"); 1148 goto out; 1149 } 1150 if (check_sk_options(sk->dev, "uv", &internal_uv) != 0) { 1151 skdebug(__func__, "check_sk_options failed"); 1152 goto out; 1153 } 1154 1155 if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) { 1156 if (r == FIDO_ERR_INVALID_COMMAND) { 1157 skdebug(__func__, "device %s does not support " 1158 "resident keys", sk->path); 1159 ret = 0; 1160 goto out; 1161 } 1162 skdebug(__func__, "get metadata for %s failed: %s", 1163 sk->path, fido_strerr(r)); 1164 ret = fidoerr_to_skerr(r); 1165 goto out; 1166 } 1167 skdebug(__func__, "existing %llu, remaining %llu", 1168 (unsigned long long)fido_credman_rk_existing(metadata), 1169 (unsigned long long)fido_credman_rk_remaining(metadata)); 1170 if ((rp = fido_credman_rp_new()) == NULL) { 1171 skdebug(__func__, "alloc rp failed"); 1172 goto out; 1173 } 1174 if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) { 1175 skdebug(__func__, "get RPs for %s failed: %s", 1176 sk->path, fido_strerr(r)); 1177 goto out; 1178 } 1179 nrp = fido_credman_rp_count(rp); 1180 skdebug(__func__, "Device %s has resident keys for %zu RPs", 1181 sk->path, nrp); 1182 1183 /* Iterate over RP IDs that have resident keys */ 1184 for (i = 0; i < nrp; i++) { 1185 rp_id = fido_credman_rp_id(rp, i); 1186 rp_name = fido_credman_rp_name(rp, i); 1187 skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu", 1188 i, rp_name == NULL ? "(none)" : rp_name, 1189 rp_id == NULL ? "(none)" : rp_id, 1190 fido_credman_rp_id_hash_len(rp, i)); 1191 1192 /* Skip non-SSH RP IDs */ 1193 if (rp_id == NULL || 1194 strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0) 1195 continue; 1196 1197 fido_credman_rk_free(&rk); 1198 if ((rk = fido_credman_rk_new()) == NULL) { 1199 skdebug(__func__, "alloc rk failed"); 1200 goto out; 1201 } 1202 if ((r = fido_credman_get_dev_rk(sk->dev, 1203 fido_credman_rp_id(rp, i), rk, pin)) != 0) { 1204 skdebug(__func__, "get RKs for %s slot %zu failed: %s", 1205 sk->path, i, fido_strerr(r)); 1206 goto out; 1207 } 1208 nrk = fido_credman_rk_count(rk); 1209 skdebug(__func__, "RP \"%s\" has %zu resident keys", 1210 fido_credman_rp_id(rp, i), nrk); 1211 1212 /* Iterate over resident keys for this RP ID */ 1213 for (j = 0; j < nrk; j++) { 1214 if ((cred = fido_credman_rk(rk, j)) == NULL) { 1215 skdebug(__func__, "no RK in slot %zu", j); 1216 continue; 1217 } 1218 if ((user_name = fido_cred_user_name(cred)) == NULL) 1219 user_name = ""; 1220 user_id = fido_cred_user_id_ptr(cred); 1221 user_id_len = fido_cred_user_id_len(cred); 1222 skdebug(__func__, "Device %s RP \"%s\" user \"%s\" " 1223 "uidlen %zu slot %zu: type %d flags 0x%02x " 1224 "prot 0x%02x", sk->path, rp_id, user_name, 1225 user_id_len, j, fido_cred_type(cred), 1226 fido_cred_flags(cred), fido_cred_prot(cred)); 1227 1228 /* build response entry */ 1229 if ((srk = calloc(1, sizeof(*srk))) == NULL || 1230 (srk->key.key_handle = calloc(1, 1231 fido_cred_id_len(cred))) == NULL || 1232 (srk->application = strdup(rp_id)) == NULL || 1233 (user_id_len > 0 && 1234 (srk->user_id = calloc(1, user_id_len)) == NULL)) { 1235 skdebug(__func__, "alloc sk_resident_key"); 1236 goto out; 1237 } 1238 1239 srk->key.key_handle_len = fido_cred_id_len(cred); 1240 memcpy(srk->key.key_handle, fido_cred_id_ptr(cred), 1241 srk->key.key_handle_len); 1242 srk->user_id_len = user_id_len; 1243 if (srk->user_id_len != 0) 1244 memcpy(srk->user_id, user_id, srk->user_id_len); 1245 1246 switch (fido_cred_type(cred)) { 1247 case COSE_ES256: 1248 srk->alg = SSH_SK_ECDSA; 1249 break; 1250 case COSE_EDDSA: 1251 srk->alg = SSH_SK_ED25519; 1252 break; 1253 default: 1254 skdebug(__func__, "unsupported key type %d", 1255 fido_cred_type(cred)); 1256 goto out; /* XXX free rk and continue */ 1257 } 1258 1259 if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED 1260 && internal_uv == -1) 1261 srk->flags |= SSH_SK_USER_VERIFICATION_REQD; 1262 1263 if ((r = pack_public_key(srk->alg, cred, 1264 &srk->key)) != 0) { 1265 skdebug(__func__, "pack public key failed"); 1266 goto out; 1267 } 1268 /* append */ 1269 if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1, 1270 sizeof(**rksp))) == NULL) { 1271 skdebug(__func__, "alloc rksp"); 1272 goto out; 1273 } 1274 *rksp = tmp; 1275 (*rksp)[(*nrksp)++] = srk; 1276 srk = NULL; 1277 } 1278 } 1279 /* Success */ 1280 ret = 0; 1281 out: 1282 if (srk != NULL) { 1283 free(srk->application); 1284 freezero(srk->key.public_key, srk->key.public_key_len); 1285 freezero(srk->key.key_handle, srk->key.key_handle_len); 1286 freezero(srk->user_id, srk->user_id_len); 1287 freezero(srk, sizeof(*srk)); 1288 } 1289 fido_credman_rp_free(&rp); 1290 fido_credman_rk_free(&rk); 1291 fido_credman_metadata_free(&metadata); 1292 return ret; 1293 } 1294 1295 int 1296 sk_load_resident_keys(const char *pin, struct sk_option **options, 1297 struct sk_resident_key ***rksp, size_t *nrksp) 1298 { 1299 int ret = SSH_SK_ERR_GENERAL, r = -1; 1300 size_t i, nrks = 0; 1301 struct sk_resident_key **rks = NULL; 1302 struct sk_usbhid *sk = NULL; 1303 char *device = NULL; 1304 1305 *rksp = NULL; 1306 *nrksp = 0; 1307 1308 fido_init(SSH_FIDO_INIT_ARG); 1309 1310 if (check_sign_load_resident_options(options, &device) != 0) 1311 goto out; /* error already logged */ 1312 if (device != NULL) 1313 sk = sk_open(device); 1314 else 1315 sk = sk_probe(NULL, NULL, 0); 1316 if (sk == NULL) { 1317 ret = SSH_SK_ERR_DEVICE_NOT_FOUND; 1318 skdebug(__func__, "failed to find sk"); 1319 goto out; 1320 } 1321 skdebug(__func__, "trying %s", sk->path); 1322 if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) { 1323 skdebug(__func__, "read_rks failed for %s", sk->path); 1324 ret = r; 1325 goto out; 1326 } 1327 /* success, unless we have no keys but a specific error */ 1328 if (nrks > 0 || ret == SSH_SK_ERR_GENERAL) 1329 ret = 0; 1330 *rksp = rks; 1331 *nrksp = nrks; 1332 rks = NULL; 1333 nrks = 0; 1334 out: 1335 sk_close(sk); 1336 for (i = 0; i < nrks; i++) { 1337 free(rks[i]->application); 1338 freezero(rks[i]->key.public_key, rks[i]->key.public_key_len); 1339 freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len); 1340 freezero(rks[i]->user_id, rks[i]->user_id_len); 1341 freezero(rks[i], sizeof(*rks[i])); 1342 } 1343 free(device); 1344 free(rks); 1345 return ret; 1346 } 1347 1348