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