version 1.32, 2021/10/28 02:54:18 |
version 1.33, 2021/11/02 22:56:40 |
|
|
(*ps) = sig->s; \ |
(*ps) = sig->s; \ |
} while (0) |
} while (0) |
#endif |
#endif |
|
#ifndef FIDO_ERR_OPERATION_DENIED |
|
#define FIDO_ERR_OPERATION_DENIED 0x27 |
|
#endif |
|
|
struct sk_usbhid { |
struct sk_usbhid { |
fido_dev_t *dev; |
fido_dev_t *dev; |
|
|
return sk; |
return sk; |
} |
} |
|
|
|
static int |
|
check_sk_options(fido_dev_t *dev, const char *opt, int *ret) |
|
{ |
|
fido_cbor_info_t *info; |
|
char * const *name; |
|
const bool *value; |
|
size_t len; |
|
int r; |
|
|
|
*ret = -1; |
|
|
|
if (!fido_dev_is_fido2(dev)) { |
|
skdebug(__func__, "device is not fido2"); |
|
return 0; |
|
} |
|
if ((info = fido_cbor_info_new()) == NULL) { |
|
skdebug(__func__, "fido_cbor_info_new failed"); |
|
return -1; |
|
} |
|
if ((r = fido_dev_get_cbor_info(dev, info)) != FIDO_OK) { |
|
skdebug(__func__, "fido_dev_get_cbor_info: %s", fido_strerr(r)); |
|
fido_cbor_info_free(&info); |
|
return -1; |
|
} |
|
name = fido_cbor_info_options_name_ptr(info); |
|
value = fido_cbor_info_options_value_ptr(info); |
|
len = fido_cbor_info_options_len(info); |
|
for (size_t i = 0; i < len; i++) { |
|
if (!strcmp(name[i], opt)) { |
|
*ret = value[i]; |
|
break; |
|
} |
|
} |
|
fido_cbor_info_free(&info); |
|
if (*ret == -1) |
|
skdebug(__func__, "option %s is unknown", opt); |
|
else |
|
skdebug(__func__, "option %s is %s", opt, *ret ? "on" : "off"); |
|
|
|
return 0; |
|
} |
|
|
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
/* |
/* |
* The key returned via fido_cred_pubkey_ptr() is in affine coordinates, |
* The key returned via fido_cred_pubkey_ptr() is in affine coordinates, |
|
|
return SSH_SK_ERR_UNSUPPORTED; |
return SSH_SK_ERR_UNSUPPORTED; |
case FIDO_ERR_PIN_REQUIRED: |
case FIDO_ERR_PIN_REQUIRED: |
case FIDO_ERR_PIN_INVALID: |
case FIDO_ERR_PIN_INVALID: |
|
case FIDO_ERR_OPERATION_DENIED: |
return SSH_SK_ERR_PIN_REQUIRED; |
return SSH_SK_ERR_PIN_REQUIRED; |
default: |
default: |
return -1; |
return -1; |
|
|
struct sk_enroll_response *response = NULL; |
struct sk_enroll_response *response = NULL; |
size_t len; |
size_t len; |
int credprot; |
int credprot; |
|
int internal_uv; |
int cose_alg; |
int cose_alg; |
int ret = SSH_SK_ERR_GENERAL; |
int ret = SSH_SK_ERR_GENERAL; |
int r; |
int r; |
|
|
skdebug(__func__, "calloc response failed"); |
skdebug(__func__, "calloc response failed"); |
goto out; |
goto out; |
} |
} |
|
response->flags = flags; |
|
if ((flags & SSH_SK_USER_VERIFICATION_REQD)) { |
|
if (check_sk_options(sk->dev, "uv", &internal_uv) == 0 && |
|
internal_uv != -1) { |
|
/* user verification handled by token */ |
|
response->flags &= ~SSH_SK_USER_VERIFICATION_REQD; |
|
} |
|
} |
if (pack_public_key(alg, cred, response) != 0) { |
if (pack_public_key(alg, cred, response) != 0) { |
skdebug(__func__, "pack_public_key failed"); |
skdebug(__func__, "pack_public_key failed"); |
goto out; |
goto out; |
|
|
struct sk_usbhid *sk = NULL; |
struct sk_usbhid *sk = NULL; |
struct sk_sign_response *response = NULL; |
struct sk_sign_response *response = NULL; |
uint8_t message[32]; |
uint8_t message[32]; |
int ret = SSH_SK_ERR_GENERAL; |
int ret = SSH_SK_ERR_GENERAL, internal_uv; |
int r; |
int r; |
|
|
fido_init(SSH_FIDO_INIT_ARG); |
fido_init(SSH_FIDO_INIT_ARG); |
|
|
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 (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD) && |
if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD)) { |
(r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) { |
if (check_sk_options(sk->dev, "uv", &internal_uv) < 0 || |
skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); |
internal_uv != 1) { |
ret = FIDO_ERR_PIN_REQUIRED; |
skdebug(__func__, "check_sk_options uv"); |
goto out; |
ret = SSH_SK_ERR_PIN_REQUIRED; |
|
goto out; |
|
} |
|
if ((r = fido_assert_set_uv(assert, |
|
FIDO_OPT_TRUE)) != FIDO_OK) { |
|
skdebug(__func__, "fido_assert_set_uv: %s", |
|
fido_strerr(r)); |
|
ret = fidoerr_to_skerr(r); |
|
goto out; |
|
} |
} |
} |
if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) { |
if ((r = fido_dev_get_assert(sk->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)); |
|
|
read_rks(struct sk_usbhid *sk, const char *pin, |
read_rks(struct sk_usbhid *sk, const char *pin, |
struct sk_resident_key ***rksp, size_t *nrksp) |
struct sk_resident_key ***rksp, size_t *nrksp) |
{ |
{ |
int ret = SSH_SK_ERR_GENERAL, r = -1; |
int ret = SSH_SK_ERR_GENERAL, r = -1, internal_uv; |
fido_credman_metadata_t *metadata = NULL; |
fido_credman_metadata_t *metadata = NULL; |
fido_credman_rp_t *rp = NULL; |
fido_credman_rp_t *rp = NULL; |
fido_credman_rk_t *rk = NULL; |
fido_credman_rk_t *rk = NULL; |
|
|
skdebug(__func__, "alloc failed"); |
skdebug(__func__, "alloc failed"); |
goto out; |
goto out; |
} |
} |
|
if (check_sk_options(sk->dev, "uv", &internal_uv) != 0) { |
|
skdebug(__func__, "check_sk_options failed"); |
|
goto out; |
|
} |
|
|
if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) { |
if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) { |
if (r == FIDO_ERR_INVALID_COMMAND) { |
if (r == FIDO_ERR_INVALID_COMMAND) { |
|
|
goto out; /* XXX free rk and continue */ |
goto out; /* XXX free rk and continue */ |
} |
} |
|
|
if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED) |
if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED |
|
&& internal_uv == -1) |
srk->flags |= SSH_SK_USER_VERIFICATION_REQD; |
srk->flags |= SSH_SK_USER_VERIFICATION_REQD; |
|
|
if ((r = pack_public_key(srk->alg, cred, |
if ((r = pack_public_key(srk->alg, cred, |