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