summaryrefslogtreecommitdiff
path: root/sk-usbhid.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-08-27 01:06:18 +0000
committerDamien Miller <djm@mindrot.org>2020-08-27 11:28:36 +1000
commit9b8ad93824c682ce841f53f3b5762cef4e7cc4dc (patch)
treed4523956d4623b19bf5904d1b92afeb2307f69d3 /sk-usbhid.c
parent1196d7f49d4fbc90f37e550de3056561613b0960 (diff)
upstream: support for user-verified FIDO keys
FIDO2 supports a notion of "user verification" where the user is required to demonstrate their identity to the token before particular operations (e.g. signing). Typically this is done by authenticating themselves using a PIN that has been set on the token. This adds support for generating and using user verified keys where the verification happens via PIN (other options might be added in the future, but none are in common use now). Practically, this adds another key generation option "verify-required" that yields a key that requires a PIN before each authentication. feedback markus@ and Pedro Martelletto; ok markus@ OpenBSD-Commit-ID: 57fd461e4366f87c47502c5614ec08573e6d6a15
Diffstat (limited to 'sk-usbhid.c')
-rw-r--r--sk-usbhid.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/sk-usbhid.c b/sk-usbhid.c
index 2a573caa2..1dd834883 100644
--- a/sk-usbhid.c
+++ b/sk-usbhid.c
@@ -163,7 +163,8 @@ pick_first_device(void)
163/* Check if the specified key handle exists on a given device. */ 163/* Check if the specified key handle exists on a given device. */
164static int 164static int
165try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len, 165try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len,
166 const char *application, const uint8_t *key_handle, size_t key_handle_len) 166 const char *application, const uint8_t *key_handle, size_t key_handle_len,
167 uint8_t flags, const char *pin)
167{ 168{
168 fido_assert_t *assert = NULL; 169 fido_assert_t *assert = NULL;
169 int r = FIDO_ERR_INTERNAL; 170 int r = FIDO_ERR_INTERNAL;
@@ -191,7 +192,7 @@ try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len,
191 skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); 192 skdebug(__func__, "fido_assert_up: %s", fido_strerr(r));
192 goto out; 193 goto out;
193 } 194 }
194 r = fido_dev_get_assert(dev, assert, NULL); 195 r = fido_dev_get_assert(dev, assert, pin);
195 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); 196 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
196 if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { 197 if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) {
197 /* U2F tokens may return this */ 198 /* U2F tokens may return this */
@@ -206,7 +207,8 @@ try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len,
206/* Iterate over configured devices looking for a specific key handle */ 207/* Iterate over configured devices looking for a specific key handle */
207static fido_dev_t * 208static fido_dev_t *
208find_device(const char *path, const uint8_t *message, size_t message_len, 209find_device(const char *path, const uint8_t *message, size_t message_len,
209 const char *application, const uint8_t *key_handle, size_t key_handle_len) 210 const char *application, const uint8_t *key_handle, size_t key_handle_len,
211 uint8_t flags, const char *pin)
210{ 212{
211 fido_dev_info_t *devlist = NULL; 213 fido_dev_info_t *devlist = NULL;
212 fido_dev_t *dev = NULL; 214 fido_dev_t *dev = NULL;
@@ -260,7 +262,7 @@ find_device(const char *path, const uint8_t *message, size_t message_len,
260 continue; 262 continue;
261 } 263 }
262 if (try_device(dev, message, message_len, application, 264 if (try_device(dev, message, message_len, application,
263 key_handle, key_handle_len) == 0) { 265 key_handle, key_handle_len, flags, pin) == 0) {
264 skdebug(__func__, "found key"); 266 skdebug(__func__, "found key");
265 break; 267 break;
266 } 268 }
@@ -570,19 +572,23 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
570 skdebug(__func__, "fido_dev_open: %s", fido_strerr(r)); 572 skdebug(__func__, "fido_dev_open: %s", fido_strerr(r));
571 goto out; 573 goto out;
572 } 574 }
573 if ((flags & SSH_SK_RESIDENT_KEY) != 0) { 575 if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) {
574 if (check_sk_extensions(dev, "credProtect", &credprot) < 0) { 576 if (check_sk_extensions(dev, "credProtect", &credprot) < 0) {
575 skdebug(__func__, "check_sk_extensions failed"); 577 skdebug(__func__, "check_sk_extensions failed");
576 goto out; 578 goto out;
577 } 579 }
578 if (credprot == 0) { 580 if (credprot == 0) {
579 skdebug(__func__, "refusing to create unprotected " 581 skdebug(__func__, "refusing to create unprotected "
580 "resident key"); 582 "resident/verify-required key");
581 ret = SSH_SK_ERR_UNSUPPORTED; 583 ret = SSH_SK_ERR_UNSUPPORTED;
582 goto out; 584 goto out;
583 } 585 }
584 if ((r = fido_cred_set_prot(cred, 586 if ((flags & SSH_SK_USER_VERIFICATION_REQD))
585 FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID)) != FIDO_OK) { 587 credprot = FIDO_CRED_PROT_UV_REQUIRED;
588 else
589 credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID;
590
591 if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) {
586 skdebug(__func__, "fido_cred_set_prot: %s", 592 skdebug(__func__, "fido_cred_set_prot: %s",
587 fido_strerr(r)); 593 fido_strerr(r));
588 ret = fidoerr_to_skerr(r); 594 ret = fidoerr_to_skerr(r);
@@ -826,7 +832,7 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
826 goto out; 832 goto out;
827 } 833 }
828 if ((dev = find_device(device, message, sizeof(message), 834 if ((dev = find_device(device, message, sizeof(message),
829 application, key_handle, key_handle_len)) == NULL) { 835 application, key_handle, key_handle_len, flags, pin)) == NULL) {
830 skdebug(__func__, "couldn't find device for key handle"); 836 skdebug(__func__, "couldn't find device for key handle");
831 goto out; 837 goto out;
832 } 838 }
@@ -855,8 +861,15 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
855 skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); 861 skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
856 goto out; 862 goto out;
857 } 863 }
858 if ((r = fido_dev_get_assert(dev, assert, NULL)) != FIDO_OK) { 864 if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD) &&
865 (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) {
866 skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r));
867 ret = FIDO_ERR_PIN_REQUIRED;
868 goto out;
869 }
870 if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) {
859 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); 871 skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
872 ret = fidoerr_to_skerr(r);
860 goto out; 873 goto out;
861 } 874 }
862 if ((response = calloc(1, sizeof(*response))) == NULL) { 875 if ((response = calloc(1, sizeof(*response))) == NULL) {
@@ -978,8 +991,9 @@ read_rks(const char *devpath, const char *pin,
978 continue; 991 continue;
979 } 992 }
980 skdebug(__func__, "Device %s RP \"%s\" slot %zu: " 993 skdebug(__func__, "Device %s RP \"%s\" slot %zu: "
981 "type %d", devpath, fido_credman_rp_id(rp, i), j, 994 "type %d flags 0x%02x prot 0x%02x", devpath,
982 fido_cred_type(cred)); 995 fido_credman_rp_id(rp, i), j, fido_cred_type(cred),
996 fido_cred_flags(cred), fido_cred_prot(cred));
983 997
984 /* build response entry */ 998 /* build response entry */
985 if ((srk = calloc(1, sizeof(*srk))) == NULL || 999 if ((srk = calloc(1, sizeof(*srk))) == NULL ||