1 /* $OpenBSD: sk-usbhid.c,v 1.38 2022/02/07 01:25:12 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 * Almost every use of OpenSSL in this file is for ECDSA-NISTP256.
36 * This is strictly a larger hammer than necessary, but it reduces changes
39 #ifndef OPENSSL_HAS_ECC
44 #include <openssl/opensslv.h>
45 #include <openssl/crypto.h>
46 #include <openssl/bn.h>
47 #include <openssl/ec.h>
48 #include <openssl/ecdsa.h>
49 #include <openssl/evp.h>
50 #endif /* WITH_OPENSSL */
53 #include <fido/credman.h>
55 /* backwards compat for libfido2 */
56 #ifndef HAVE_FIDO_CRED_PROT
57 #define fido_cred_prot(x) (0)
59 #ifndef HAVE_FIDO_CRED_SET_PROT
60 #define fido_cred_set_prot(x, y) (FIDO_ERR_UNSUPPORTED_OPTION)
62 #ifndef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT
63 #define fido_dev_supports_cred_prot(x) (0)
65 #ifndef HAVE_FIDO_DEV_GET_TOUCH_BEGIN
66 #define fido_dev_get_touch_begin(x) (FIDO_ERR_UNSUPPORTED_OPTION)
68 #ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS
69 #define fido_dev_get_touch_status(x, y, z) (FIDO_ERR_UNSUPPORTED_OPTION)
71 #ifndef FIDO_CRED_PROT_UV_REQUIRED
72 #define FIDO_CRED_PROT_UV_REQUIRED 0
74 #ifndef FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID
75 #define FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID 0
83 * If building as part of OpenSSH, then rename exported functions.
84 * This must be done before including sk-api.h.
86 # define sk_api_version ssh_sk_api_version
87 # define sk_enroll ssh_sk_enroll
88 # define sk_sign ssh_sk_sign
89 # define sk_load_resident_keys ssh_sk_load_resident_keys
90 #endif /* !SK_STANDALONE */
94 /* #define SK_DEBUG 1 */
97 #define SSH_FIDO_INIT_ARG FIDO_DEBUG
99 #define SSH_FIDO_INIT_ARG 0
102 #define MAX_FIDO_DEVICES 8
103 #define FIDO_POLL_MS 50
104 #define SELECT_MS 15000
105 #define POLL_SLEEP_NS 200000000
107 /* Compatibility with OpenSSH 1.0.x */
108 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
109 #define ECDSA_SIG_get0(sig, pr, ps) \
115 #ifndef FIDO_ERR_OPERATION_DENIED
116 #define FIDO_ERR_OPERATION_DENIED 0x27
124 /* Return the version of the middleware API */
125 uint32_t sk_api_version(void);
127 /* Enroll a U2F key (private key generation) */
128 int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
129 const char *application, uint8_t flags, const char *pin,
130 struct sk_option **options, struct sk_enroll_response **enroll_response);
132 /* Sign a challenge */
133 int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len,
134 const char *application, const uint8_t *key_handle, size_t key_handle_len,
135 uint8_t flags, const char *pin, struct sk_option **options,
136 struct sk_sign_response **sign_response);
138 /* Load resident keys */
139 int sk_load_resident_keys(const char *pin, struct sk_option **options,
140 struct sk_resident_key ***rks, size_t *nrks);
142 static void skdebug(const char *func, const char *fmt, ...)
143 __attribute__((__format__ (printf, 2, 3)));
146 skdebug(const char *func, const char *fmt, ...)
148 #if !defined(SK_STANDALONE)
153 xvasprintf(&msg, fmt, ap);
155 debug("%s: %s", func, msg);
157 #elif defined(SK_DEBUG)
161 fprintf(stderr, "%s: ", func);
162 vfprintf(stderr, fmt, ap);
166 (void)func; /* XXX */
174 return SSH_SK_VERSION_MAJOR;
177 static struct sk_usbhid *
178 sk_open(const char *path)
180 struct sk_usbhid *sk;
184 skdebug(__func__, "path == NULL");
187 if ((sk = calloc(1, sizeof(*sk))) == NULL) {
188 skdebug(__func__, "calloc sk failed");
191 if ((sk->path = strdup(path)) == NULL) {
192 skdebug(__func__, "strdup path failed");
196 if ((sk->dev = fido_dev_new()) == NULL) {
197 skdebug(__func__, "fido_dev_new failed");
202 if ((r = fido_dev_open(sk->dev, sk->path)) != FIDO_OK) {
203 skdebug(__func__, "fido_dev_open %s failed: %s", sk->path,
205 fido_dev_free(&sk->dev);
214 sk_close(struct sk_usbhid *sk)
218 fido_dev_cancel(sk->dev); /* cancel any pending operation */
219 fido_dev_close(sk->dev);
220 fido_dev_free(&sk->dev);
225 static struct sk_usbhid **
226 sk_openv(const fido_dev_info_t *devlist, size_t ndevs, size_t *nopen)
228 const fido_dev_info_t *di;
229 struct sk_usbhid **skv;
233 if ((skv = calloc(ndevs, sizeof(*skv))) == NULL) {
234 skdebug(__func__, "calloc skv failed");
237 for (i = 0; i < ndevs; i++) {
238 if ((di = fido_dev_info_ptr(devlist, i)) == NULL)
239 skdebug(__func__, "fido_dev_info_ptr failed");
240 else if ((skv[*nopen] = sk_open(fido_dev_info_path(di))) == NULL)
241 skdebug(__func__, "sk_open failed");
246 for (i = 0; i < ndevs; i++)
256 sk_closev(struct sk_usbhid **skv, size_t nsk)
260 for (i = 0; i < nsk; i++)
266 sk_touch_begin(struct sk_usbhid **skv, size_t nsk)
271 for (i = 0; i < nsk; i++)
272 if ((r = fido_dev_get_touch_begin(skv[i]->dev)) != FIDO_OK)
273 skdebug(__func__, "fido_dev_get_touch_begin %s failed:"
274 " %s", skv[i]->path, fido_strerr(r));
282 sk_touch_poll(struct sk_usbhid **skv, size_t nsk, int *touch, size_t *idx)
284 struct timespec ts_pause;
289 ts_pause.tv_nsec = POLL_SLEEP_NS;
290 nanosleep(&ts_pause, NULL);
292 for (i = 0; i < nsk; i++) {
294 continue; /* device discarded */
295 skdebug(__func__, "polling %s", skv[i]->path);
296 if ((r = fido_dev_get_touch_status(skv[i]->dev, touch,
297 FIDO_POLL_MS)) != FIDO_OK) {
298 skdebug(__func__, "fido_dev_get_touch_status %s: %s",
299 skv[i]->path, fido_strerr(r));
300 sk_close(skv[i]); /* discard device */
303 skdebug(__func__, "no device left to poll");
315 #if !defined(HAVE_FIDO_ASSERT_SET_CLIENTDATA) || \
316 !defined(HAVE_FIDO_CRED_SET_CLIENTDATA)
317 /* Calculate SHA256(m) */
319 sha256_mem(const void *m, size_t mlen, u_char *d, size_t dlen)
331 if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL))
335 SHA256Update(&ctx, (const uint8_t *)m, mlen);
336 SHA256Final(d, &ctx);
340 #endif /* !HAVE_FIDO_ASSERT_SET_CLIENTDATA || !HAVE_FIDO_CRED_SET_CLIENTDATA */
342 #ifndef HAVE_FIDO_CRED_SET_CLIENTDATA
344 fido_cred_set_clientdata(fido_cred_t *cred, const u_char *ptr, size_t len)
349 if (sha256_mem(ptr, len, d, sizeof(d)) != 0) {
350 skdebug(__func__, "hash challenge failed");
351 return FIDO_ERR_INTERNAL;
353 r = fido_cred_set_clientdata_hash(cred, d, sizeof(d));
354 explicit_bzero(d, sizeof(d));
356 skdebug(__func__, "fido_cred_set_clientdata_hash failed: %s",
361 #endif /* HAVE_FIDO_CRED_SET_CLIENTDATA */
363 #ifndef HAVE_FIDO_ASSERT_SET_CLIENTDATA
365 fido_assert_set_clientdata(fido_assert_t *assert, const u_char *ptr, size_t len)
370 if (sha256_mem(ptr, len, d, sizeof(d)) != 0) {
371 skdebug(__func__, "hash challenge failed");
372 return FIDO_ERR_INTERNAL;
374 r = fido_assert_set_clientdata_hash(assert, d, sizeof(d));
375 explicit_bzero(d, sizeof(d));
377 skdebug(__func__, "fido_assert_set_clientdata_hash failed: %s",
382 #endif /* HAVE_FIDO_ASSERT_SET_CLIENTDATA */
384 /* Check if the specified key handle exists on a given sk. */
386 sk_try(const struct sk_usbhid *sk, const char *application,
387 const uint8_t *key_handle, size_t key_handle_len)
389 fido_assert_t *assert = NULL;
390 int r = FIDO_ERR_INTERNAL;
393 memset(message, '\0', sizeof(message));
394 if ((assert = fido_assert_new()) == NULL) {
395 skdebug(__func__, "fido_assert_new failed");
398 /* generate an invalid signature on FIDO2 tokens */
399 if ((r = fido_assert_set_clientdata(assert, message,
400 sizeof(message))) != FIDO_OK) {
401 skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
405 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
406 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
409 if ((r = fido_assert_allow_cred(assert, key_handle,
410 key_handle_len)) != FIDO_OK) {
411 skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
414 if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) {
415 skdebug(__func__, "fido_assert_up: %s", fido_strerr(r));
418 r = fido_dev_get_assert(sk->dev, assert, NULL);
419 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
420 if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) {
421 /* U2F tokens may return this */
425 fido_assert_free(&assert);
427 return r != FIDO_OK ? -1 : 0;
431 check_sk_options(fido_dev_t *dev, const char *opt, int *ret)
433 fido_cbor_info_t *info;
441 if (!fido_dev_is_fido2(dev)) {
442 skdebug(__func__, "device is not fido2");
445 if ((info = fido_cbor_info_new()) == NULL) {
446 skdebug(__func__, "fido_cbor_info_new failed");
449 if ((r = fido_dev_get_cbor_info(dev, info)) != FIDO_OK) {
450 skdebug(__func__, "fido_dev_get_cbor_info: %s", fido_strerr(r));
451 fido_cbor_info_free(&info);
454 name = fido_cbor_info_options_name_ptr(info);
455 value = fido_cbor_info_options_value_ptr(info);
456 len = fido_cbor_info_options_len(info);
457 for (i = 0; i < len; i++) {
458 if (!strcmp(name[i], opt)) {
463 fido_cbor_info_free(&info);
465 skdebug(__func__, "option %s is unknown", opt);
467 skdebug(__func__, "option %s is %s", opt, *ret ? "on" : "off");
472 static struct sk_usbhid *
473 sk_select_by_cred(const fido_dev_info_t *devlist, size_t ndevs,
474 const char *application, const uint8_t *key_handle, size_t key_handle_len)
476 struct sk_usbhid **skv, *sk;
480 if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
481 skdebug(__func__, "sk_openv failed");
484 if (skvcnt == 1 && check_sk_options(skv[0]->dev, "uv",
485 &internal_uv) == 0 && internal_uv != -1) {
491 for (i = 0; i < skvcnt; i++) {
492 if (sk_try(skv[i], application, key_handle,
493 key_handle_len) == 0) {
496 skdebug(__func__, "found key in %s", sk->path);
501 sk_closev(skv, skvcnt);
505 static struct sk_usbhid *
506 sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs)
508 struct sk_usbhid **skv, *sk;
509 struct timeval tv_start, tv_now, tv_delta;
511 int touch, ms_remain;
513 if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
514 skdebug(__func__, "sk_openv failed");
520 /* single candidate */
526 #ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS
527 skdebug(__func__, "libfido2 version does not support a feature needed for multiple tokens. Please upgrade to >=1.5.0");
531 if (sk_touch_begin(skv, skvcnt) == -1) {
532 skdebug(__func__, "sk_touch_begin failed");
535 monotime_tv(&tv_start);
537 if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) {
538 skdebug(__func__, "sk_touch_poll failed");
546 monotime_tv(&tv_now);
547 timersub(&tv_now, &tv_start, &tv_delta);
548 ms_remain = SELECT_MS - tv_delta.tv_sec * 1000 -
549 tv_delta.tv_usec / 1000;
550 } while (ms_remain >= FIDO_POLL_MS);
551 skdebug(__func__, "timeout");
553 sk_closev(skv, skvcnt);
557 static struct sk_usbhid *
558 sk_probe(const char *application, const uint8_t *key_handle,
559 size_t key_handle_len)
561 struct sk_usbhid *sk;
562 fido_dev_info_t *devlist;
566 if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
567 skdebug(__func__, "fido_dev_info_new failed");
570 if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES,
571 &ndevs)) != FIDO_OK) {
572 skdebug(__func__, "fido_dev_info_manifest failed: %s",
574 fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
577 skdebug(__func__, "%zu device(s) detected", ndevs);
580 } else if (application != NULL && key_handle != NULL) {
581 skdebug(__func__, "selecting sk by cred");
582 sk = sk_select_by_cred(devlist, ndevs, application, key_handle,
585 skdebug(__func__, "selecting sk by touch");
586 sk = sk_select_by_touch(devlist, ndevs);
588 fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
594 * The key returned via fido_cred_pubkey_ptr() is in affine coordinates,
595 * but the API expects a SEC1 octet string.
598 pack_public_key_ecdsa(const fido_cred_t *cred,
599 struct sk_enroll_response *response)
602 BIGNUM *x = NULL, *y = NULL;
607 response->public_key = NULL;
608 response->public_key_len = 0;
610 if ((x = BN_new()) == NULL ||
611 (y = BN_new()) == NULL ||
612 (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL ||
613 (q = EC_POINT_new(g)) == NULL) {
614 skdebug(__func__, "libcrypto setup failed");
617 if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
618 skdebug(__func__, "fido_cred_pubkey_ptr failed");
621 if (fido_cred_pubkey_len(cred) != 64) {
622 skdebug(__func__, "bad fido_cred_pubkey_len %zu",
623 fido_cred_pubkey_len(cred));
627 if (BN_bin2bn(ptr, 32, x) == NULL ||
628 BN_bin2bn(ptr + 32, 32, y) == NULL) {
629 skdebug(__func__, "BN_bin2bn failed");
632 if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) {
633 skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed");
636 response->public_key_len = EC_POINT_point2oct(g, q,
637 POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
638 if (response->public_key_len == 0 || response->public_key_len > 2048) {
639 skdebug(__func__, "bad pubkey length %zu",
640 response->public_key_len);
643 if ((response->public_key = malloc(response->public_key_len)) == NULL) {
644 skdebug(__func__, "malloc pubkey failed");
647 if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
648 response->public_key, response->public_key_len, NULL) == 0) {
649 skdebug(__func__, "EC_POINT_point2oct failed");
655 if (ret != 0 && response->public_key != NULL) {
656 memset(response->public_key, 0, response->public_key_len);
657 free(response->public_key);
658 response->public_key = NULL;
666 #endif /* WITH_OPENSSL */
669 pack_public_key_ed25519(const fido_cred_t *cred,
670 struct sk_enroll_response *response)
676 response->public_key = NULL;
677 response->public_key_len = 0;
679 if ((len = fido_cred_pubkey_len(cred)) != 32) {
680 skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len);
683 if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
684 skdebug(__func__, "fido_cred_pubkey_ptr failed");
687 response->public_key_len = len;
688 if ((response->public_key = malloc(response->public_key_len)) == NULL) {
689 skdebug(__func__, "malloc pubkey failed");
692 memcpy(response->public_key, ptr, len);
696 free(response->public_key);
701 pack_public_key(uint32_t alg, const fido_cred_t *cred,
702 struct sk_enroll_response *response)
707 return pack_public_key_ecdsa(cred, response);
708 #endif /* WITH_OPENSSL */
710 return pack_public_key_ed25519(cred, response);
717 fidoerr_to_skerr(int fidoerr)
720 case FIDO_ERR_UNSUPPORTED_OPTION:
721 case FIDO_ERR_UNSUPPORTED_ALGORITHM:
722 return SSH_SK_ERR_UNSUPPORTED;
723 case FIDO_ERR_PIN_REQUIRED:
724 case FIDO_ERR_PIN_INVALID:
725 case FIDO_ERR_OPERATION_DENIED:
726 return SSH_SK_ERR_PIN_REQUIRED;
733 check_enroll_options(struct sk_option **options, char **devicep,
734 uint8_t *user_id, size_t user_id_len)
740 for (i = 0; options[i] != NULL; i++) {
741 if (strcmp(options[i]->name, "device") == 0) {
742 if ((*devicep = strdup(options[i]->value)) == NULL) {
743 skdebug(__func__, "strdup device failed");
746 skdebug(__func__, "requested device %s", *devicep);
747 } else if (strcmp(options[i]->name, "user") == 0) {
748 if (strlcpy(user_id, options[i]->value, user_id_len) >=
750 skdebug(__func__, "user too long");
753 skdebug(__func__, "requested user %s",
756 skdebug(__func__, "requested unsupported option %s",
758 if (options[i]->required) {
759 skdebug(__func__, "unknown required option");
768 sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
769 const char *application, uint8_t flags, const char *pin,
770 struct sk_option **options, struct sk_enroll_response **enroll_response)
772 fido_cred_t *cred = NULL;
775 struct sk_usbhid *sk = NULL;
776 struct sk_enroll_response *response = NULL;
781 int ret = SSH_SK_ERR_GENERAL;
785 fido_init(SSH_FIDO_INIT_ARG);
787 if (enroll_response == NULL) {
788 skdebug(__func__, "enroll_response == NULL");
791 *enroll_response = NULL;
792 memset(user_id, 0, sizeof(user_id));
793 if (check_enroll_options(options, &device, user_id,
794 sizeof(user_id)) != 0)
795 goto out; /* error already logged */
800 cose_alg = COSE_ES256;
802 #endif /* WITH_OPENSSL */
804 cose_alg = COSE_EDDSA;
807 skdebug(__func__, "unsupported key type %d", alg);
811 sk = sk_open(device);
813 sk = sk_probe(NULL, NULL, 0);
815 ret = SSH_SK_ERR_DEVICE_NOT_FOUND;
816 skdebug(__func__, "failed to find sk");
819 skdebug(__func__, "using device %s", sk->path);
820 if ((cred = fido_cred_new()) == NULL) {
821 skdebug(__func__, "fido_cred_new failed");
824 if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) {
825 skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r));
828 if ((r = fido_cred_set_clientdata(cred,
829 challenge, challenge_len)) != FIDO_OK) {
830 skdebug(__func__, "fido_cred_set_clientdata: %s",
834 if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ?
835 FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) {
836 skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r));
839 if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id),
840 "openssh", "openssh", NULL)) != FIDO_OK) {
841 skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r));
844 if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) {
845 skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r));
848 if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) {
849 #if !defined(HAVE_FIDO_DEV_SUPPORTS_CRED_PROT) || \
850 !defined(HAVE_FIDO_CRED_SET_PROT)
851 skdebug(__func__, "libfido2 version does not support a feature required for this operation. Please upgrade to >=1.5.0");
852 ret = SSH_SK_ERR_UNSUPPORTED;
854 credprot = 0; (void)credprot; /* avoid warning */
856 if (!fido_dev_supports_cred_prot(sk->dev)) {
857 skdebug(__func__, "%s does not support credprot, "
858 "refusing to create unprotected "
859 "resident/verify-required key", sk->path);
860 ret = SSH_SK_ERR_UNSUPPORTED;
863 if ((flags & SSH_SK_USER_VERIFICATION_REQD))
864 credprot = FIDO_CRED_PROT_UV_REQUIRED;
866 credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID;
868 if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) {
869 skdebug(__func__, "fido_cred_set_prot: %s",
871 ret = fidoerr_to_skerr(r);
875 if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) {
876 skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r));
877 ret = fidoerr_to_skerr(r);
880 if (fido_cred_x5c_ptr(cred) != NULL) {
881 if ((r = fido_cred_verify(cred)) != FIDO_OK) {
882 skdebug(__func__, "fido_cred_verify: %s",
887 skdebug(__func__, "self-attested credential");
888 if ((r = fido_cred_verify_self(cred)) != FIDO_OK) {
889 skdebug(__func__, "fido_cred_verify_self: %s",
894 if ((response = calloc(1, sizeof(*response))) == NULL) {
895 skdebug(__func__, "calloc response failed");
898 response->flags = flags;
899 if ((flags & SSH_SK_USER_VERIFICATION_REQD)) {
900 if (check_sk_options(sk->dev, "uv", &internal_uv) == 0 &&
902 /* user verification handled by token */
903 response->flags &= ~SSH_SK_USER_VERIFICATION_REQD;
906 if (pack_public_key(alg, cred, response) != 0) {
907 skdebug(__func__, "pack_public_key failed");
910 if ((ptr = fido_cred_id_ptr(cred)) != NULL) {
911 len = fido_cred_id_len(cred);
912 if ((response->key_handle = calloc(1, len)) == NULL) {
913 skdebug(__func__, "calloc key handle failed");
916 memcpy(response->key_handle, ptr, len);
917 response->key_handle_len = len;
919 if ((ptr = fido_cred_sig_ptr(cred)) != NULL) {
920 len = fido_cred_sig_len(cred);
921 if ((response->signature = calloc(1, len)) == NULL) {
922 skdebug(__func__, "calloc signature failed");
925 memcpy(response->signature, ptr, len);
926 response->signature_len = len;
928 if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) {
929 len = fido_cred_x5c_len(cred);
930 skdebug(__func__, "attestation cert len=%zu", len);
931 if ((response->attestation_cert = calloc(1, len)) == NULL) {
932 skdebug(__func__, "calloc attestation cert failed");
935 memcpy(response->attestation_cert, ptr, len);
936 response->attestation_cert_len = len;
938 if ((ptr = fido_cred_authdata_ptr(cred)) != NULL) {
939 len = fido_cred_authdata_len(cred);
940 skdebug(__func__, "authdata len=%zu", len);
941 if ((response->authdata = calloc(1, len)) == NULL) {
942 skdebug(__func__, "calloc authdata failed");
945 memcpy(response->authdata, ptr, len);
946 response->authdata_len = len;
948 *enroll_response = response;
953 if (response != NULL) {
954 free(response->public_key);
955 free(response->key_handle);
956 free(response->signature);
957 free(response->attestation_cert);
958 free(response->authdata);
962 fido_cred_free(&cred);
968 pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response)
970 ECDSA_SIG *sig = NULL;
971 const BIGNUM *sig_r, *sig_s;
972 const unsigned char *cp;
976 cp = fido_assert_sig_ptr(assert, 0);
977 sig_len = fido_assert_sig_len(assert, 0);
978 if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) {
979 skdebug(__func__, "d2i_ECDSA_SIG failed");
982 ECDSA_SIG_get0(sig, &sig_r, &sig_s);
983 response->sig_r_len = BN_num_bytes(sig_r);
984 response->sig_s_len = BN_num_bytes(sig_s);
985 if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
986 (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
987 skdebug(__func__, "calloc signature failed");
990 BN_bn2bin(sig_r, response->sig_r);
991 BN_bn2bin(sig_s, response->sig_s);
996 free(response->sig_r);
997 free(response->sig_s);
998 response->sig_r = NULL;
999 response->sig_s = NULL;
1003 #endif /* WITH_OPENSSL */
1006 pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response)
1008 const unsigned char *ptr;
1012 ptr = fido_assert_sig_ptr(assert, 0);
1013 len = fido_assert_sig_len(assert, 0);
1015 skdebug(__func__, "bad length %zu", len);
1018 response->sig_r_len = len;
1019 if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
1020 skdebug(__func__, "calloc signature failed");
1023 memcpy(response->sig_r, ptr, len);
1027 free(response->sig_r);
1028 response->sig_r = NULL;
1034 pack_sig(uint32_t alg, fido_assert_t *assert,
1035 struct sk_sign_response *response)
1040 return pack_sig_ecdsa(assert, response);
1041 #endif /* WITH_OPENSSL */
1042 case SSH_SK_ED25519:
1043 return pack_sig_ed25519(assert, response);
1049 /* Checks sk_options for sk_sign() and sk_load_resident_keys() */
1051 check_sign_load_resident_options(struct sk_option **options, char **devicep)
1055 if (options == NULL)
1057 for (i = 0; options[i] != NULL; i++) {
1058 if (strcmp(options[i]->name, "device") == 0) {
1059 if ((*devicep = strdup(options[i]->value)) == NULL) {
1060 skdebug(__func__, "strdup device failed");
1063 skdebug(__func__, "requested device %s", *devicep);
1065 skdebug(__func__, "requested unsupported option %s",
1067 if (options[i]->required) {
1068 skdebug(__func__, "unknown required option");
1077 sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
1078 const char *application,
1079 const uint8_t *key_handle, size_t key_handle_len,
1080 uint8_t flags, const char *pin, struct sk_option **options,
1081 struct sk_sign_response **sign_response)
1083 fido_assert_t *assert = NULL;
1084 char *device = NULL;
1085 struct sk_usbhid *sk = NULL;
1086 struct sk_sign_response *response = NULL;
1087 int ret = SSH_SK_ERR_GENERAL, internal_uv;
1090 fido_init(SSH_FIDO_INIT_ARG);
1092 if (sign_response == NULL) {
1093 skdebug(__func__, "sign_response == NULL");
1096 *sign_response = NULL;
1097 if (check_sign_load_resident_options(options, &device) != 0)
1098 goto out; /* error already logged */
1100 sk = sk_open(device);
1101 else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD))
1102 sk = sk_probe(NULL, NULL, 0);
1104 sk = sk_probe(application, key_handle, key_handle_len);
1106 ret = SSH_SK_ERR_DEVICE_NOT_FOUND;
1107 skdebug(__func__, "failed to find sk");
1110 if ((assert = fido_assert_new()) == NULL) {
1111 skdebug(__func__, "fido_assert_new failed");
1114 if ((r = fido_assert_set_clientdata(assert,
1115 data, datalen)) != FIDO_OK) {
1116 skdebug(__func__, "fido_assert_set_clientdata: %s",
1120 if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
1121 skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
1124 if ((r = fido_assert_allow_cred(assert, key_handle,
1125 key_handle_len)) != FIDO_OK) {
1126 skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
1129 if ((r = fido_assert_set_up(assert,
1130 (flags & SSH_SK_USER_PRESENCE_REQD) ?
1131 FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) {
1132 skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
1135 if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD)) {
1136 if (check_sk_options(sk->dev, "uv", &internal_uv) < 0 ||
1138 skdebug(__func__, "check_sk_options uv");
1139 ret = SSH_SK_ERR_PIN_REQUIRED;
1142 if ((r = fido_assert_set_uv(assert,
1143 FIDO_OPT_TRUE)) != FIDO_OK) {
1144 skdebug(__func__, "fido_assert_set_uv: %s",
1146 ret = fidoerr_to_skerr(r);
1150 if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) {
1151 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
1152 ret = fidoerr_to_skerr(r);
1155 if ((response = calloc(1, sizeof(*response))) == NULL) {
1156 skdebug(__func__, "calloc response failed");
1159 response->flags = fido_assert_flags(assert, 0);
1160 response->counter = fido_assert_sigcount(assert, 0);
1161 if (pack_sig(alg, assert, response) != 0) {
1162 skdebug(__func__, "pack_sig failed");
1165 *sign_response = response;
1170 if (response != NULL) {
1171 free(response->sig_r);
1172 free(response->sig_s);
1176 fido_assert_free(&assert);
1181 read_rks(struct sk_usbhid *sk, const char *pin,
1182 struct sk_resident_key ***rksp, size_t *nrksp)
1184 int ret = SSH_SK_ERR_GENERAL, r = -1, internal_uv;
1185 fido_credman_metadata_t *metadata = NULL;
1186 fido_credman_rp_t *rp = NULL;
1187 fido_credman_rk_t *rk = NULL;
1188 size_t i, j, nrp, nrk, user_id_len;
1189 const fido_cred_t *cred;
1190 const char *rp_id, *rp_name, *user_name;
1191 struct sk_resident_key *srk = NULL, **tmp;
1192 const u_char *user_id;
1195 skdebug(__func__, "no PIN specified");
1196 ret = SSH_SK_ERR_PIN_REQUIRED;
1199 if ((metadata = fido_credman_metadata_new()) == NULL) {
1200 skdebug(__func__, "alloc failed");
1203 if (check_sk_options(sk->dev, "uv", &internal_uv) != 0) {
1204 skdebug(__func__, "check_sk_options failed");
1208 if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) {
1209 if (r == FIDO_ERR_INVALID_COMMAND) {
1210 skdebug(__func__, "device %s does not support "
1211 "resident keys", sk->path);
1215 skdebug(__func__, "get metadata for %s failed: %s",
1216 sk->path, fido_strerr(r));
1217 ret = fidoerr_to_skerr(r);
1220 skdebug(__func__, "existing %llu, remaining %llu",
1221 (unsigned long long)fido_credman_rk_existing(metadata),
1222 (unsigned long long)fido_credman_rk_remaining(metadata));
1223 if ((rp = fido_credman_rp_new()) == NULL) {
1224 skdebug(__func__, "alloc rp failed");
1227 if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) {
1228 skdebug(__func__, "get RPs for %s failed: %s",
1229 sk->path, fido_strerr(r));
1232 nrp = fido_credman_rp_count(rp);
1233 skdebug(__func__, "Device %s has resident keys for %zu RPs",
1236 /* Iterate over RP IDs that have resident keys */
1237 for (i = 0; i < nrp; i++) {
1238 rp_id = fido_credman_rp_id(rp, i);
1239 rp_name = fido_credman_rp_name(rp, i);
1240 skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu",
1241 i, rp_name == NULL ? "(none)" : rp_name,
1242 rp_id == NULL ? "(none)" : rp_id,
1243 fido_credman_rp_id_hash_len(rp, i));
1245 /* Skip non-SSH RP IDs */
1246 if (rp_id == NULL ||
1247 strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0)
1250 fido_credman_rk_free(&rk);
1251 if ((rk = fido_credman_rk_new()) == NULL) {
1252 skdebug(__func__, "alloc rk failed");
1255 if ((r = fido_credman_get_dev_rk(sk->dev,
1256 fido_credman_rp_id(rp, i), rk, pin)) != 0) {
1257 skdebug(__func__, "get RKs for %s slot %zu failed: %s",
1258 sk->path, i, fido_strerr(r));
1261 nrk = fido_credman_rk_count(rk);
1262 skdebug(__func__, "RP \"%s\" has %zu resident keys",
1263 fido_credman_rp_id(rp, i), nrk);
1265 /* Iterate over resident keys for this RP ID */
1266 for (j = 0; j < nrk; j++) {
1267 if ((cred = fido_credman_rk(rk, j)) == NULL) {
1268 skdebug(__func__, "no RK in slot %zu", j);
1271 if ((user_name = fido_cred_user_name(cred)) == NULL)
1273 user_id = fido_cred_user_id_ptr(cred);
1274 user_id_len = fido_cred_user_id_len(cred);
1275 skdebug(__func__, "Device %s RP \"%s\" user \"%s\" "
1276 "uidlen %zu slot %zu: type %d flags 0x%02x "
1277 "prot 0x%02x", sk->path, rp_id, user_name,
1278 user_id_len, j, fido_cred_type(cred),
1279 fido_cred_flags(cred), fido_cred_prot(cred));
1281 /* build response entry */
1282 if ((srk = calloc(1, sizeof(*srk))) == NULL ||
1283 (srk->key.key_handle = calloc(1,
1284 fido_cred_id_len(cred))) == NULL ||
1285 (srk->application = strdup(rp_id)) == NULL ||
1287 (srk->user_id = calloc(1, user_id_len)) == NULL)) {
1288 skdebug(__func__, "alloc sk_resident_key");
1292 srk->key.key_handle_len = fido_cred_id_len(cred);
1293 memcpy(srk->key.key_handle, fido_cred_id_ptr(cred),
1294 srk->key.key_handle_len);
1295 srk->user_id_len = user_id_len;
1296 if (srk->user_id_len != 0)
1297 memcpy(srk->user_id, user_id, srk->user_id_len);
1299 switch (fido_cred_type(cred)) {
1301 srk->alg = SSH_SK_ECDSA;
1304 srk->alg = SSH_SK_ED25519;
1307 skdebug(__func__, "unsupported key type %d",
1308 fido_cred_type(cred));
1309 goto out; /* XXX free rk and continue */
1312 if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED
1313 && internal_uv == -1)
1314 srk->flags |= SSH_SK_USER_VERIFICATION_REQD;
1316 if ((r = pack_public_key(srk->alg, cred,
1318 skdebug(__func__, "pack public key failed");
1322 if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1,
1323 sizeof(**rksp))) == NULL) {
1324 skdebug(__func__, "alloc rksp");
1328 (*rksp)[(*nrksp)++] = srk;
1336 free(srk->application);
1337 freezero(srk->key.public_key, srk->key.public_key_len);
1338 freezero(srk->key.key_handle, srk->key.key_handle_len);
1339 freezero(srk->user_id, srk->user_id_len);
1340 freezero(srk, sizeof(*srk));
1342 fido_credman_rp_free(&rp);
1343 fido_credman_rk_free(&rk);
1344 fido_credman_metadata_free(&metadata);
1349 sk_load_resident_keys(const char *pin, struct sk_option **options,
1350 struct sk_resident_key ***rksp, size_t *nrksp)
1352 int ret = SSH_SK_ERR_GENERAL, r = -1;
1354 struct sk_resident_key **rks = NULL;
1355 struct sk_usbhid *sk = NULL;
1356 char *device = NULL;
1361 fido_init(SSH_FIDO_INIT_ARG);
1363 if (check_sign_load_resident_options(options, &device) != 0)
1364 goto out; /* error already logged */
1366 sk = sk_open(device);
1368 sk = sk_probe(NULL, NULL, 0);
1370 ret = SSH_SK_ERR_DEVICE_NOT_FOUND;
1371 skdebug(__func__, "failed to find sk");
1374 skdebug(__func__, "trying %s", sk->path);
1375 if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) {
1376 skdebug(__func__, "read_rks failed for %s", sk->path);
1380 /* success, unless we have no keys but a specific error */
1381 if (nrks > 0 || ret == SSH_SK_ERR_GENERAL)
1389 for (i = 0; i < nrks; i++) {
1390 free(rks[i]->application);
1391 freezero(rks[i]->key.public_key, rks[i]->key.public_key_len);
1392 freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len);
1393 freezero(rks[i]->user_id, rks[i]->user_id_len);
1394 freezero(rks[i], sizeof(*rks[i]));
1400 #endif /* ENABLE_SK_INTERNAL */