version 1.20, 2020/05/13 22:38:41 |
version 1.21, 2020/08/27 01:06:18 |
|
|
/* Check if the specified key handle exists on a given device. */ |
/* Check if the specified key handle exists on a given device. */ |
static int |
static int |
try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len, |
try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len, |
const char *application, const uint8_t *key_handle, size_t key_handle_len) |
const char *application, const uint8_t *key_handle, size_t key_handle_len, |
|
uint8_t flags, const char *pin) |
{ |
{ |
fido_assert_t *assert = NULL; |
fido_assert_t *assert = NULL; |
int r = FIDO_ERR_INTERNAL; |
int r = FIDO_ERR_INTERNAL; |
|
|
skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); |
skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); |
goto out; |
goto out; |
} |
} |
r = fido_dev_get_assert(dev, assert, NULL); |
r = fido_dev_get_assert(dev, assert, pin); |
skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); |
skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); |
if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { |
if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { |
/* U2F tokens may return this */ |
/* U2F tokens may return this */ |
|
|
/* Iterate over configured devices looking for a specific key handle */ |
/* Iterate over configured devices looking for a specific key handle */ |
static fido_dev_t * |
static fido_dev_t * |
find_device(const char *path, const uint8_t *message, size_t message_len, |
find_device(const char *path, const uint8_t *message, size_t message_len, |
const char *application, const uint8_t *key_handle, size_t key_handle_len) |
const char *application, const uint8_t *key_handle, size_t key_handle_len, |
|
uint8_t flags, const char *pin) |
{ |
{ |
fido_dev_info_t *devlist = NULL; |
fido_dev_info_t *devlist = NULL; |
fido_dev_t *dev = NULL; |
fido_dev_t *dev = NULL; |
|
|
continue; |
continue; |
} |
} |
if (try_device(dev, message, message_len, application, |
if (try_device(dev, message, message_len, application, |
key_handle, key_handle_len) == 0) { |
key_handle, key_handle_len, flags, pin) == 0) { |
skdebug(__func__, "found key"); |
skdebug(__func__, "found key"); |
break; |
break; |
} |
} |
|
|
skdebug(__func__, "fido_dev_open: %s", fido_strerr(r)); |
skdebug(__func__, "fido_dev_open: %s", fido_strerr(r)); |
goto out; |
goto out; |
} |
} |
if ((flags & SSH_SK_RESIDENT_KEY) != 0) { |
if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) { |
if (check_sk_extensions(dev, "credProtect", &credprot) < 0) { |
if (check_sk_extensions(dev, "credProtect", &credprot) < 0) { |
skdebug(__func__, "check_sk_extensions failed"); |
skdebug(__func__, "check_sk_extensions failed"); |
goto out; |
goto out; |
} |
} |
if (credprot == 0) { |
if (credprot == 0) { |
skdebug(__func__, "refusing to create unprotected " |
skdebug(__func__, "refusing to create unprotected " |
"resident key"); |
"resident/verify-required key"); |
ret = SSH_SK_ERR_UNSUPPORTED; |
ret = SSH_SK_ERR_UNSUPPORTED; |
goto out; |
goto out; |
} |
} |
if ((r = fido_cred_set_prot(cred, |
if ((flags & SSH_SK_USER_VERIFICATION_REQD)) |
FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID)) != FIDO_OK) { |
credprot = FIDO_CRED_PROT_UV_REQUIRED; |
|
else |
|
credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID; |
|
|
|
if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) { |
skdebug(__func__, "fido_cred_set_prot: %s", |
skdebug(__func__, "fido_cred_set_prot: %s", |
fido_strerr(r)); |
fido_strerr(r)); |
ret = fidoerr_to_skerr(r); |
ret = fidoerr_to_skerr(r); |
|
|
goto out; |
goto out; |
} |
} |
if ((dev = find_device(device, message, sizeof(message), |
if ((dev = find_device(device, message, sizeof(message), |
application, key_handle, key_handle_len)) == NULL) { |
application, key_handle, key_handle_len, flags, pin)) == NULL) { |
skdebug(__func__, "couldn't find device for key handle"); |
skdebug(__func__, "couldn't find device for key handle"); |
goto out; |
goto out; |
} |
} |
|
|
skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); |
skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); |
goto out; |
goto out; |
} |
} |
if ((r = fido_dev_get_assert(dev, assert, NULL)) != FIDO_OK) { |
if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD) && |
|
(r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) { |
|
skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); |
|
ret = FIDO_ERR_PIN_REQUIRED; |
|
goto out; |
|
} |
|
if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) { |
skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); |
skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); |
|
ret = fidoerr_to_skerr(r); |
goto out; |
goto out; |
} |
} |
if ((response = calloc(1, sizeof(*response))) == NULL) { |
if ((response = calloc(1, sizeof(*response))) == NULL) { |
|
|
continue; |
continue; |
} |
} |
skdebug(__func__, "Device %s RP \"%s\" slot %zu: " |
skdebug(__func__, "Device %s RP \"%s\" slot %zu: " |
"type %d", devpath, fido_credman_rp_id(rp, i), j, |
"type %d flags 0x%02x prot 0x%02x", devpath, |
fido_cred_type(cred)); |
fido_credman_rp_id(rp, i), j, fido_cred_type(cred), |
|
fido_cred_flags(cred), fido_cred_prot(cred)); |
|
|
/* build response entry */ |
/* build response entry */ |
if ((srk = calloc(1, sizeof(*srk))) == NULL || |
if ((srk = calloc(1, sizeof(*srk))) == NULL || |