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