[webauthn] Send permissions list with UVToken
When sending getPinUvAuthTokenUsingUvWithPermissions, the permissions list is required [1]. Since we are only using UVToken for make credential and get assertion, and sometimes making a credential involves getting assertions, request those two permissions with every UVToken request. [1] https://drafts.fidoalliance.org/fido-2/stable-links-to-latest/fido-client-to-authenticator-protocol.html#permissions-list Fixed: 1086558 Change-Id: I572850efafb02ab9d292465379d385751adac101 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2220258 Commit-Queue: Nina Satragno <nsatragno@chromium.org> Commit-Queue: Martin Kreichgauer <martinkr@google.com> Auto-Submit: Nina Satragno <nsatragno@chromium.org> Reviewed-by: Martin Kreichgauer <martinkr@google.com> Cr-Commit-Position: refs/heads/master@{#774189}
This commit is contained in:

committed by
Commit Bot

parent
c5df6fa134
commit
4f6b4c4e67
@ -521,6 +521,9 @@ AsCTAPRequestValuePair(const UvTokenRequest& request) {
|
||||
Subcommand::kGetUvToken, [&request](cbor::Value::MapValue* map) {
|
||||
map->emplace(static_cast<int>(RequestKey::kKeyAgreement),
|
||||
std::move(request.cose_key_));
|
||||
map->emplace(static_cast<int>(RequestKey::kPermissions),
|
||||
static_cast<uint8_t>(Permissions::kMakeCredential) |
|
||||
static_cast<uint8_t>(Permissions::kGetAssertion));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -35,12 +35,26 @@ enum class Subcommand : uint8_t {
|
||||
// RequestKey enumerates the keys in the top-level CBOR map for all PIN
|
||||
// commands.
|
||||
enum class RequestKey : int {
|
||||
kProtocol = 1,
|
||||
kSubcommand = 2,
|
||||
kKeyAgreement = 3,
|
||||
kPINAuth = 4,
|
||||
kNewPINEnc = 5,
|
||||
kPINHashEnc = 6,
|
||||
kProtocol = 0x01,
|
||||
kSubcommand = 0x02,
|
||||
kKeyAgreement = 0x03,
|
||||
kPINAuth = 0x04,
|
||||
kNewPINEnc = 0x05,
|
||||
kPINHashEnc = 0x06,
|
||||
kMinPINLength = 0x07,
|
||||
kMinPINLengthRPIDs = 0x08,
|
||||
kPermissions = 0x09,
|
||||
kPermissionsRPID = 0x0A,
|
||||
};
|
||||
|
||||
// Permission list flags. See
|
||||
// https://drafts.fidoalliance.org/fido-2/stable-links-to-latest/fido-client-to-authenticator-protocol.html#permissions
|
||||
enum class Permissions : uint8_t {
|
||||
kMakeCredential = 0x01,
|
||||
kGetAssertion = 0x02,
|
||||
kCredentialManagement = 0x04,
|
||||
kBioEnrollment = 0x08,
|
||||
kPlatformConfiguration = 0x10,
|
||||
};
|
||||
|
||||
// ResponseKey enumerates the keys in the top-level CBOR map for all PIN
|
||||
|
@ -683,7 +683,12 @@ VirtualCtap2Device::CheckUserVerification(
|
||||
kSupportedAndPinSet ||
|
||||
options.supports_uv_token)) {
|
||||
DCHECK(pin_protocol && *pin_protocol == 1);
|
||||
if (CheckPINToken(pin_token, *pin_auth, client_data_hash)) {
|
||||
|
||||
auto permission = is_make_credential ? pin::Permissions::kMakeCredential
|
||||
: pin::Permissions::kGetAssertion;
|
||||
if (mutable_state()->pin_uv_token_permissions &
|
||||
static_cast<uint8_t>(permission) &&
|
||||
CheckPINToken(pin_token, *pin_auth, client_data_hash)) {
|
||||
uv = true;
|
||||
} else {
|
||||
return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid;
|
||||
@ -1331,6 +1336,13 @@ base::Optional<CtapDeviceResponseCode> VirtualCtap2Device::OnPINCommand(
|
||||
return err;
|
||||
};
|
||||
|
||||
mutable_state()->pin_retries = kMaxPinRetries;
|
||||
|
||||
// Set default PinUvAuthToken permissions.
|
||||
mutable_state()->pin_uv_token_permissions =
|
||||
static_cast<uint8_t>(pin::Permissions::kMakeCredential) |
|
||||
static_cast<uint8_t>(pin::Permissions::kGetAssertion);
|
||||
|
||||
response_map.emplace(
|
||||
static_cast<int>(pin::ResponseKey::kPINToken),
|
||||
GenerateAndEncryptToken(shared_key, mutable_state()->pin_token));
|
||||
@ -1344,6 +1356,17 @@ base::Optional<CtapDeviceResponseCode> VirtualCtap2Device::OnPINCommand(
|
||||
return CtapDeviceResponseCode::kCtap2ErrMissingParameter;
|
||||
}
|
||||
|
||||
const auto permissions_it = request_map.find(
|
||||
cbor::Value(static_cast<int>(pin::RequestKey::kPermissions)));
|
||||
if (permissions_it == request_map.end() ||
|
||||
!permissions_it->second.is_unsigned()) {
|
||||
return CtapDeviceResponseCode::kCtap2ErrMissingParameter;
|
||||
}
|
||||
uint8_t permissions = permissions_it->second.GetUnsigned();
|
||||
if (permissions == 0) {
|
||||
return CtapDeviceResponseCode::kCtap1ErrInvalidParameter;
|
||||
}
|
||||
|
||||
if (device_info_->options.user_verification_availability ==
|
||||
AuthenticatorSupportedOptions::UserVerificationAvailability::
|
||||
kSupportedButNotConfigured) {
|
||||
@ -1375,6 +1398,7 @@ base::Optional<CtapDeviceResponseCode> VirtualCtap2Device::OnPINCommand(
|
||||
|
||||
mutable_state()->pin_retries = kMaxPinRetries;
|
||||
mutable_state()->uv_retries = kMaxUvRetries;
|
||||
mutable_state()->pin_uv_token_permissions = permissions;
|
||||
|
||||
response_map.emplace(
|
||||
static_cast<int>(pin::ResponseKey::kPINToken),
|
||||
|
@ -165,6 +165,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) VirtualFidoDevice : public FidoDevice {
|
||||
// The random PIN token that is returned as a placeholder for the PIN
|
||||
// itself.
|
||||
uint8_t pin_token[32];
|
||||
// The permissions parameter for |pin_token|.
|
||||
// TODO(nsatragno): implement permissions RPID.
|
||||
uint8_t pin_uv_token_permissions = 0;
|
||||
|
||||
// Number of internal UV retries remaining.
|
||||
int uv_retries = kMaxUvRetries;
|
||||
|
Reference in New Issue
Block a user