1 /* $OpenBSD: sk-usbhid.c,v 1.30 2021/05/31 06:48:42 djm Exp $ */
3 * Copyright (c) 2019 Markus Friedl
4 * Copyright (c) 2020 Pedro Martelletto
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.
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.
21 #ifdef ENABLE_SK_INTERNAL
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 */
44 #include <fido/credman.h>
46 /* backwards compat for libfido2 */
47 #ifndef HAVE_FIDO_CRED_PROT
48 #define fido_cred_prot(x) (0)
50 #ifndef HAVE_FIDO_CRED_SET_PROT
51 #define fido_cred_set_prot(x, y) (FIDO_ERR_UNSUPPORTED_OPTION)
53 #ifndef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT
54 #define fido_dev_supports_cred_prot(x) (0)
56 #ifndef HAVE_FIDO_DEV_GET_TOUCH_BEGIN
57 #define fido_dev_get_touch_begin(x) (FIDO_ERR_UNSUPPORTED_OPTION)
59 #ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS
60 #define fido_dev_get_touch_status(x, y, z) (FIDO_ERR_UNSUPPORTED_OPTION)
62 #ifndef FIDO_CRED_PROT_UV_REQUIRED
63 #define FIDO_CRED_PROT_UV_REQUIRED 0
65 #ifndef FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID
66 #define FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID 0
74 * If building as part of OpenSSH, then rename exported functions.
75 * This must be done before including sk-api.h.
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 */
85 /* #define SK_DEBUG 1 */
88 #define SSH_FIDO_INIT_ARG FIDO_DEBUG
90 #define SSH_FIDO_INIT_ARG 0
93 #define MAX_FIDO_DEVICES 8
94 #define FIDO_POLL_MS 50
95 #define SELECT_MS 15000
96 #define POLL_SLEEP_NS 200000000
98 /* Compatibility with OpenSSH 1.0.x */
99 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
100 #define ECDSA_SIG_get0(sig, pr, ps) \
112 /* Return the version of the middleware API */
113 uint32_t sk_api_version(void);
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);
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);
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);
130 static void skdebug(const char *func, const char *fmt, ...)
131 __attribute__((__format__ (printf, 2, 3)));
134 skdebug(const char *func, const char *fmt, ...)
136 #if !defined(SK_STANDALONE)
141 xvasprintf(&msg, fmt, ap);
143 debug("%s: %s", func, msg);
145 #elif defined(SK_DEBUG)
149 fprintf(stderr, "%s: ", func);
150 vfprintf(stderr, fmt, ap);
154 (void)func; /* XXX */
162 return SSH_SK_VERSION_MAJOR;
165 static struct sk_usbhid *
166 sk_open(const char *path)
168 struct sk_usbhid *sk;
172 skdebug(__func__, "path == NULL");
175 if ((sk = calloc(1, sizeof(*sk))) == NULL) {
176 skdebug(__func__, "calloc sk failed");
179 if ((sk->path = strdup(path)) == NULL) {
180 skdebug(__func__, "strdup path failed");
184 if ((sk->dev = fido_dev_new()) == NULL) {
185 skdebug(__func__, "fido_dev_new failed");
190 if ((r = fido_dev_open(sk->dev, sk->path)) != FIDO_OK) {
191 skdebug(__func__, "fido_dev_open %s failed: %s", sk->path,
193 fido_dev_free(&sk->dev);
202 sk_close(struct sk_usbhid *sk)
206 fido_dev_cancel(sk->dev); /* cancel any pending operation */
207 fido_dev_close(sk->dev);
208 fido_dev_free(&sk->dev);
213 static struct sk_usbhid **
214 sk_openv(const fido_dev_info_t *devlist, size_t ndevs, size_t *nopen)
216 const fido_dev_info_t *di;
217 struct sk_usbhid **skv;
221 if ((skv = calloc(ndevs, sizeof(*skv))) == NULL) {
222 skdebug(__func__, "calloc skv failed");
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");
234 for (i = 0; i < ndevs; i++)
244 sk_closev(struct sk_usbhid **skv, size_t nsk)
248 for (i = 0; i < nsk; i++)
254 sk_touch_begin(struct sk_usbhid **skv, size_t nsk)
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));
270 sk_touch_poll(struct sk_usbhid **skv, size_t nsk, int *touch, size_t *idx)
272 struct timespec ts_pause;
277 ts_pause.tv_nsec = POLL_SLEEP_NS;
278 nanosleep(&ts_pause, NULL);
280 for (i = 0; i < nsk; i++) {
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 */
291 skdebug(__func__, "no device left to poll");
303 /* Calculate SHA256(m) */
305 sha256_mem(const void *m, size_t mlen, u_char *d, size_t dlen)
315 if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL))
318 SHA256Data(m, mlen, d);
323 /* Check if the specified key handle exists on a given sk. */
325 sk_try(const struct sk_usbhid *sk, const char *application,
326 const uint8_t *key_handle, size_t key_handle_len)
328 fido_assert_t *assert = NULL;
329 /* generate an invalid signature on FIDO2 tokens */
330 const char *data = "";
332 int r = FIDO_ERR_INTERNAL;
334 if (sha256_mem(data, strlen(data), message, sizeof(message)) != 0) {
335 skdebug(__func__, "hash message failed");
338 if ((assert = fido_assert_new()) == NULL) {
339 skdebug(__func__, "fido_assert_new failed");
342 if ((r = fido_assert_set_clientdata_hash(assert, message,
343 sizeof(message))) != FIDO_OK) {
344 skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
348 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
349 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
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));
357 if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) {
358 skdebug(__func__, "fido_assert_up: %s", fido_strerr(r));
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 */
368 fido_assert_free(&assert);
370 return r != FIDO_OK ? -1 : 0;
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)
377 struct sk_usbhid **skv, *sk;
380 if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
381 skdebug(__func__, "sk_openv failed");
390 for (i = 0; i < skvcnt; i++) {
391 if (sk_try(skv[i], application, key_handle,
392 key_handle_len) == 0) {
395 skdebug(__func__, "found key in %s", sk->path);
400 sk_closev(skv, skvcnt);
404 static struct sk_usbhid *
405 sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs)
407 struct sk_usbhid **skv, *sk;
408 struct timeval tv_start, tv_now, tv_delta;
410 int touch, ms_remain;
412 if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
413 skdebug(__func__, "sk_openv failed");
419 /* single candidate */
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");
430 if (sk_touch_begin(skv, skvcnt) == -1) {
431 skdebug(__func__, "sk_touch_begin failed");
434 monotime_tv(&tv_start);
436 if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) {
437 skdebug(__func__, "sk_touch_poll failed");
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");
452 sk_closev(skv, skvcnt);
456 static struct sk_usbhid *
457 sk_probe(const char *application, const uint8_t *key_handle,
458 size_t key_handle_len)
460 struct sk_usbhid *sk;
461 fido_dev_info_t *devlist;
465 if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
466 skdebug(__func__, "fido_dev_info_new failed");
469 if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES,
470 &ndevs)) != FIDO_OK) {
471 skdebug(__func__, "fido_dev_info_manifest failed: %s",
473 fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
476 skdebug(__func__, "%zu device(s) detected", ndevs);
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,
484 skdebug(__func__, "selecting sk by touch");
485 sk = sk_select_by_touch(devlist, ndevs);
487 fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
493 * The key returned via fido_cred_pubkey_ptr() is in affine coordinates,
494 * but the API expects a SEC1 octet string.
497 pack_public_key_ecdsa(const fido_cred_t *cred,
498 struct sk_enroll_response *response)
501 BIGNUM *x = NULL, *y = NULL;
506 response->public_key = NULL;
507 response->public_key_len = 0;
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");
516 if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
517 skdebug(__func__, "fido_cred_pubkey_ptr failed");
520 if (fido_cred_pubkey_len(cred) != 64) {
521 skdebug(__func__, "bad fido_cred_pubkey_len %zu",
522 fido_cred_pubkey_len(cred));
526 if (BN_bin2bn(ptr, 32, x) == NULL ||
527 BN_bin2bn(ptr + 32, 32, y) == NULL) {
528 skdebug(__func__, "BN_bin2bn failed");
531 if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) {
532 skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed");
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);
542 if ((response->public_key = malloc(response->public_key_len)) == NULL) {
543 skdebug(__func__, "malloc pubkey failed");
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");
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;
565 #endif /* WITH_OPENSSL */
568 pack_public_key_ed25519(const fido_cred_t *cred,
569 struct sk_enroll_response *response)
575 response->public_key = NULL;
576 response->public_key_len = 0;
578 if ((len = fido_cred_pubkey_len(cred)) != 32) {
579 skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len);
582 if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
583 skdebug(__func__, "fido_cred_pubkey_ptr failed");
586 response->public_key_len = len;
587 if ((response->public_key = malloc(response->public_key_len)) == NULL) {
588 skdebug(__func__, "malloc pubkey failed");
591 memcpy(response->public_key, ptr, len);
595 free(response->public_key);
600 pack_public_key(uint32_t alg, const fido_cred_t *cred,
601 struct sk_enroll_response *response)
606 return pack_public_key_ecdsa(cred, response);
607 #endif /* WITH_OPENSSL */
609 return pack_public_key_ed25519(cred, response);
616 fidoerr_to_skerr(int 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;
631 check_enroll_options(struct sk_option **options, char **devicep,
632 uint8_t *user_id, size_t user_id_len)
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");
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) >=
648 skdebug(__func__, "user too long");
651 skdebug(__func__, "requested user %s",
654 skdebug(__func__, "requested unsupported option %s",
656 if (options[i]->required) {
657 skdebug(__func__, "unknown required option");
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)
670 fido_cred_t *cred = NULL;
672 uint8_t user_id[32], chall_hash[32];
673 struct sk_usbhid *sk = NULL;
674 struct sk_enroll_response *response = NULL;
678 int ret = SSH_SK_ERR_GENERAL;
682 fido_init(SSH_FIDO_INIT_ARG);
684 if (enroll_response == NULL) {
685 skdebug(__func__, "enroll_response == NULL");
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 */
697 cose_alg = COSE_ES256;
699 #endif /* WITH_OPENSSL */
701 cose_alg = COSE_EDDSA;
704 skdebug(__func__, "unsupported key type %d", alg);
708 sk = sk_open(device);
710 sk = sk_probe(NULL, NULL, 0);
712 skdebug(__func__, "failed to find sk");
715 skdebug(__func__, "using device %s", sk->path);
716 if ((cred = fido_cred_new()) == NULL) {
717 skdebug(__func__, "fido_cred_new failed");
720 if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) {
721 skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r));
724 if (sha256_mem(challenge, challenge_len,
725 chall_hash, sizeof(chall_hash)) != 0) {
726 skdebug(__func__, "hash challenge failed");
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",
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));
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));
745 if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) {
746 skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r));
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;
755 credprot = 0; (void)credprot; /* avoid warning */
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;
764 if ((flags & SSH_SK_USER_VERIFICATION_REQD))
765 credprot = FIDO_CRED_PROT_UV_REQUIRED;
767 credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID;
769 if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) {
770 skdebug(__func__, "fido_cred_set_prot: %s",
772 ret = fidoerr_to_skerr(r);
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);
781 if (fido_cred_x5c_ptr(cred) != NULL) {
782 if ((r = fido_cred_verify(cred)) != FIDO_OK) {
783 skdebug(__func__, "fido_cred_verify: %s",
788 skdebug(__func__, "self-attested credential");
789 if ((r = fido_cred_verify_self(cred)) != FIDO_OK) {
790 skdebug(__func__, "fido_cred_verify_self: %s",
795 if ((response = calloc(1, sizeof(*response))) == NULL) {
796 skdebug(__func__, "calloc response failed");
799 if (pack_public_key(alg, cred, response) != 0) {
800 skdebug(__func__, "pack_public_key failed");
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");
809 memcpy(response->key_handle, ptr, len);
810 response->key_handle_len = len;
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");
818 memcpy(response->signature, ptr, len);
819 response->signature_len = len;
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");
828 memcpy(response->attestation_cert, ptr, len);
829 response->attestation_cert_len = len;
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");
838 memcpy(response->authdata, ptr, len);
839 response->authdata_len = len;
841 *enroll_response = response;
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);
855 fido_cred_free(&cred);
861 pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response)
863 ECDSA_SIG *sig = NULL;
864 const BIGNUM *sig_r, *sig_s;
865 const unsigned char *cp;
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");
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");
883 BN_bn2bin(sig_r, response->sig_r);
884 BN_bn2bin(sig_s, response->sig_s);
889 free(response->sig_r);
890 free(response->sig_s);
891 response->sig_r = NULL;
892 response->sig_s = NULL;
896 #endif /* WITH_OPENSSL */
899 pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response)
901 const unsigned char *ptr;
905 ptr = fido_assert_sig_ptr(assert, 0);
906 len = fido_assert_sig_len(assert, 0);
908 skdebug(__func__, "bad length %zu", len);
911 response->sig_r_len = len;
912 if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
913 skdebug(__func__, "calloc signature failed");
916 memcpy(response->sig_r, ptr, len);
920 free(response->sig_r);
921 response->sig_r = NULL;
927 pack_sig(uint32_t alg, fido_assert_t *assert,
928 struct sk_sign_response *response)
933 return pack_sig_ecdsa(assert, response);
934 #endif /* WITH_OPENSSL */
936 return pack_sig_ed25519(assert, response);
942 /* Checks sk_options for sk_sign() and sk_load_resident_keys() */
944 check_sign_load_resident_options(struct sk_option **options, char **devicep)
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");
956 skdebug(__func__, "requested device %s", *devicep);
958 skdebug(__func__, "requested unsupported option %s",
960 if (options[i]->required) {
961 skdebug(__func__, "unknown required option");
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)
976 fido_assert_t *assert = NULL;
978 struct sk_usbhid *sk = NULL;
979 struct sk_sign_response *response = NULL;
981 int ret = SSH_SK_ERR_GENERAL;
984 fido_init(SSH_FIDO_INIT_ARG);
986 if (sign_response == NULL) {
987 skdebug(__func__, "sign_response == NULL");
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");
999 sk = sk_open(device);
1000 else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD))
1001 sk = sk_probe(NULL, NULL, 0);
1003 sk = sk_probe(application, key_handle, key_handle_len);
1005 skdebug(__func__, "failed to find sk");
1008 if ((assert = fido_assert_new()) == NULL) {
1009 skdebug(__func__, "fido_assert_new failed");
1012 if ((r = fido_assert_set_clientdata_hash(assert, message,
1013 sizeof(message))) != FIDO_OK) {
1014 skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
1018 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
1019 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
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));
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));
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;
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);
1044 if ((response = calloc(1, sizeof(*response))) == NULL) {
1045 skdebug(__func__, "calloc response failed");
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");
1054 *sign_response = response;
1058 explicit_bzero(message, sizeof(message));
1060 if (response != NULL) {
1061 free(response->sig_r);
1062 free(response->sig_s);
1066 fido_assert_free(&assert);
1071 read_rks(struct sk_usbhid *sk, const char *pin,
1072 struct sk_resident_key ***rksp, size_t *nrksp)
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;
1083 skdebug(__func__, "no PIN specified");
1084 ret = SSH_SK_ERR_PIN_REQUIRED;
1087 if ((metadata = fido_credman_metadata_new()) == NULL) {
1088 skdebug(__func__, "alloc failed");
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);
1099 skdebug(__func__, "get metadata for %s failed: %s",
1100 sk->path, fido_strerr(r));
1101 ret = fidoerr_to_skerr(r);
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");
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));
1116 nrp = fido_credman_rp_count(rp);
1117 skdebug(__func__, "Device %s has resident keys for %zu RPs",
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));
1126 /* Skip non-SSH RP IDs */
1127 if (strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0)
1130 fido_credman_rk_free(&rk);
1131 if ((rk = fido_credman_rk_new()) == NULL) {
1132 skdebug(__func__, "alloc rk failed");
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));
1141 nrk = fido_credman_rk_count(rk);
1142 skdebug(__func__, "RP \"%s\" has %zu resident keys",
1143 fido_credman_rp_id(rp, i), nrk);
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);
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));
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,
1162 skdebug(__func__, "alloc sk_resident_key");
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);
1170 switch (fido_cred_type(cred)) {
1172 srk->alg = SSH_SK_ECDSA;
1175 srk->alg = SSH_SK_ED25519;
1178 skdebug(__func__, "unsupported key type %d",
1179 fido_cred_type(cred));
1180 goto out; /* XXX free rk and continue */
1183 if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED)
1184 srk->flags |= SSH_SK_USER_VERIFICATION_REQD;
1186 if ((r = pack_public_key(srk->alg, cred,
1188 skdebug(__func__, "pack public key failed");
1192 if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1,
1193 sizeof(**rksp))) == NULL) {
1194 skdebug(__func__, "alloc rksp");
1198 (*rksp)[(*nrksp)++] = srk;
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));
1211 fido_credman_rp_free(&rp);
1212 fido_credman_rk_free(&rk);
1213 fido_credman_metadata_free(&metadata);
1218 sk_load_resident_keys(const char *pin, struct sk_option **options,
1219 struct sk_resident_key ***rksp, size_t *nrksp)
1221 int ret = SSH_SK_ERR_GENERAL, r = -1;
1223 struct sk_resident_key **rks = NULL;
1224 struct sk_usbhid *sk = NULL;
1225 char *device = NULL;
1230 fido_init(SSH_FIDO_INIT_ARG);
1232 if (check_sign_load_resident_options(options, &device) != 0)
1233 goto out; /* error already logged */
1235 sk = sk_open(device);
1237 sk = sk_probe(NULL, NULL, 0);
1239 skdebug(__func__, "failed to find sk");
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);
1248 /* success, unless we have no keys but a specific error */
1249 if (nrks > 0 || ret == SSH_SK_ERR_GENERAL)
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]));
1267 #endif /* ENABLE_SK_INTERNAL */