Commit 173b8417 authored by Martin Kreichgauer's avatar Martin Kreichgauer Committed by Commit Bot

fido: make GetAssertionRequestHandler use AuthTokenRequester

This replaces the bits of GetAssertionRequestHandler that request a
PIN/UV Auth Token by calling out to AuthTokenRequester instead. See
CL:2469445 for the equivalent CL for MakeCredential.

Bug: 1139111
Change-Id: I1669258ffabc679a5b6d0592ed14fbdaa710dc3f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2536930Reviewed-by: default avatarNina Satragno <nsatragno@chromium.org>
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#829271}
parent 93bac529
...@@ -73,18 +73,18 @@ void FidoAuthenticator::ChangePIN(const std::string& old_pin, ...@@ -73,18 +73,18 @@ void FidoAuthenticator::ChangePIN(const std::string& old_pin,
NOTREACHED(); NOTREACHED();
} }
FidoAuthenticator::MakeCredentialPINUVDisposition FidoAuthenticator::PINUVDisposition
FidoAuthenticator::PINUVDispositionForMakeCredential( FidoAuthenticator::PINUVDispositionForMakeCredential(
const CtapMakeCredentialRequest& request, const CtapMakeCredentialRequest& request,
const FidoRequestHandlerBase::Observer* observer) { const FidoRequestHandlerBase::Observer* observer) {
return MakeCredentialPINUVDisposition::kNoUV; return PINUVDisposition::kNoUV;
} }
FidoAuthenticator::GetAssertionPINDisposition FidoAuthenticator::PINUVDisposition
FidoAuthenticator::WillNeedPINToGetAssertion( FidoAuthenticator::PINUVDispositionForGetAssertion(
const CtapGetAssertionRequest& request, const CtapGetAssertionRequest& request,
const FidoRequestHandlerBase::Observer* observer) { const FidoRequestHandlerBase::Observer* observer) {
return GetAssertionPINDisposition::kNoPIN; return PINUVDisposition::kNoUV;
} }
void FidoAuthenticator::GetCredentialsMetadata( void FidoAuthenticator::GetCredentialsMetadata(
......
...@@ -146,9 +146,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoAuthenticator { ...@@ -146,9 +146,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoAuthenticator {
const std::string& new_pin, const std::string& new_pin,
SetPINCallback callback); SetPINCallback callback);
// MakeCredentialPINUVDisposition enumerates the possible options for // PINUVDisposition enumerates the possible options for obtaining user
// obtaining user verification when making a credential. // verification when making a CTAP2 request.
enum class MakeCredentialPINUVDisposition { enum class PINUVDisposition {
// No UV (neither clientPIN nor internal) is needed to make this // No UV (neither clientPIN nor internal) is needed to make this
// credential. // credential.
kNoUV, kNoUV,
...@@ -165,31 +165,17 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoAuthenticator { ...@@ -165,31 +165,17 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoAuthenticator {
// The request cannot be satisfied by this authenticator. // The request cannot be satisfied by this authenticator.
kUnsatisfiable, kUnsatisfiable,
}; };
// PINUVDispositionForMakeCredential returns whether and how user verification
// PINUVDisposition returns whether and how user verification
// should be obtained in order to serve the given request on this // should be obtained in order to serve the given request on this
// authenticator. // authenticator.
virtual MakeCredentialPINUVDisposition PINUVDispositionForMakeCredential( virtual PINUVDisposition PINUVDispositionForMakeCredential(
const CtapMakeCredentialRequest& request, const CtapMakeCredentialRequest& request,
const FidoRequestHandlerBase::Observer* observer); const FidoRequestHandlerBase::Observer* observer);
// GetAssertionPINDisposition enumerates the possible interactions between
// a user-verification level and the PIN support of an authenticator when
// getting an assertion.
enum class GetAssertionPINDisposition {
// kNoPIN means that a PIN will not be needed for this assertion.
kNoPIN,
// kUsePIN means that a PIN must be gathered and used for this assertion.
kUsePIN,
// kUsePINForFallback means that a PIN may be used for fallback if internal
// user verification fails.
kUsePINForFallback,
// kUnsatisfiable means that the request cannot be satisfied by this
// authenticator.
kUnsatisfiable,
};
// WillNeedPINToGetAssertion returns whether a PIN prompt will be needed to // WillNeedPINToGetAssertion returns whether a PIN prompt will be needed to
// serve the given request on this authenticator. // serve the given request on this authenticator.
virtual GetAssertionPINDisposition WillNeedPINToGetAssertion( virtual PINUVDisposition PINUVDispositionForGetAssertion(
const CtapGetAssertionRequest& request, const CtapGetAssertionRequest& request,
const FidoRequestHandlerBase::Observer* observer); const FidoRequestHandlerBase::Observer* observer);
......
...@@ -349,7 +349,7 @@ void FidoDeviceAuthenticator::OnHaveEphemeralKeyForChangePIN( ...@@ -349,7 +349,7 @@ void FidoDeviceAuthenticator::OnHaveEphemeralKeyForChangePIN(
std::move(callback), base::BindOnce(&pin::EmptyResponse::Parse)); std::move(callback), base::BindOnce(&pin::EmptyResponse::Parse));
} }
FidoAuthenticator::MakeCredentialPINUVDisposition FidoAuthenticator::PINUVDisposition
FidoDeviceAuthenticator::PINUVDispositionForMakeCredential( FidoDeviceAuthenticator::PINUVDispositionForMakeCredential(
const CtapMakeCredentialRequest& request, const CtapMakeCredentialRequest& request,
const FidoRequestHandlerBase::Observer* observer) { const FidoRequestHandlerBase::Observer* observer) {
...@@ -363,9 +363,6 @@ FidoDeviceAuthenticator::PINUVDispositionForMakeCredential( ...@@ -363,9 +363,6 @@ FidoDeviceAuthenticator::PINUVDispositionForMakeCredential(
Options()->user_verification_availability == Options()->user_verification_availability ==
UserVerificationAvailability::kSupportedAndConfigured; UserVerificationAvailability::kSupportedAndConfigured;
const bool can_get_token =
(can_collect_pin && pin_supported) || CanGetUvToken();
// CTAP 2.0 requires a PIN for credential creation once a PIN has been set. // CTAP 2.0 requires a PIN for credential creation once a PIN has been set.
// Thus, if fallback to U2F isn't possible, a PIN will be needed if set. // Thus, if fallback to U2F isn't possible, a PIN will be needed if set.
const bool u2f_fallback_possible = const bool u2f_fallback_possible =
...@@ -373,73 +370,74 @@ FidoDeviceAuthenticator::PINUVDispositionForMakeCredential( ...@@ -373,73 +370,74 @@ FidoDeviceAuthenticator::PINUVDispositionForMakeCredential(
device()->device_info()->versions.contains(ProtocolVersion::kU2f) && device()->device_info()->versions.contains(ProtocolVersion::kU2f) &&
IsConvertibleToU2fRegisterCommand(request) && IsConvertibleToU2fRegisterCommand(request) &&
!ShouldPreferCTAP2EvenIfItNeedsAPIN(request); !ShouldPreferCTAP2EvenIfItNeedsAPIN(request);
const bool uv_required =
request.user_verification == UserVerificationRequirement::kRequired || const UserVerificationRequirement uv_requirement =
(pin_configured && !u2f_fallback_possible); (pin_configured && !u2f_fallback_possible)
const bool uv_preferred = ? UserVerificationRequirement::kRequired
request.user_verification == UserVerificationRequirement::kPreferred; : request.user_verification;
if (!uv_required && !(uv_preferred && (pin_configured || uv_configured))) { if (uv_requirement == UserVerificationRequirement::kDiscouraged ||
return MakeCredentialPINUVDisposition::kNoUV; (uv_requirement == UserVerificationRequirement::kPreferred &&
((!pin_configured || !can_collect_pin) && !uv_configured))) {
return PINUVDisposition::kNoUV;
} }
// Authenticators with built-in UV that don't support UV token should try // Authenticators with built-in UV that don't support UV token should try
// sending the request as-is with uv=true first. // sending the request as-is with uv=true first.
if (uv_configured && !CanGetUvToken()) { if (uv_configured && !CanGetUvToken()) {
return (can_collect_pin && pin_supported) return (can_collect_pin && pin_supported)
? MakeCredentialPINUVDisposition::kNoTokenInternalUVPINFallback ? PINUVDisposition::kNoTokenInternalUVPINFallback
: MakeCredentialPINUVDisposition::kNoTokenInternalUV; : PINUVDisposition::kNoTokenInternalUV;
} }
const bool can_get_token =
(can_collect_pin && pin_supported) || CanGetUvToken();
if (can_get_token) { if (can_get_token) {
return MakeCredentialPINUVDisposition::kGetToken; return PINUVDisposition::kGetToken;
} }
return MakeCredentialPINUVDisposition::kUnsatisfiable; return PINUVDisposition::kUnsatisfiable;
} }
FidoAuthenticator::GetAssertionPINDisposition FidoAuthenticator::PINUVDisposition
FidoDeviceAuthenticator::WillNeedPINToGetAssertion( FidoDeviceAuthenticator::PINUVDispositionForGetAssertion(
const CtapGetAssertionRequest& request, const CtapGetAssertionRequest& request,
const FidoRequestHandlerBase::Observer* observer) { const FidoRequestHandlerBase::Observer* observer) {
const bool can_use_pin = (Options()->client_pin_availability == // TODO(crbug.com/1149405): GetAssertion requests don't allow in-line UV
AuthenticatorSupportedOptions:: // enrollment. Perhaps we should change this and align with MakeCredential
ClientPinAvailability::kSupportedAndPinSet) && // behavior.
// The PIN is effectively unavailable if there's no const bool can_collect_pin = observer && observer->SupportsPIN();
// UI support for collecting it. const bool pin_configured = Options()->client_pin_availability ==
observer && observer->SupportsPIN(); ClientPinAvailability::kSupportedAndPinSet;
// Authenticators with built-in UV can use that. const bool uv_configured =
if (Options()->user_verification_availability == Options()->user_verification_availability ==
UserVerificationAvailability::kSupportedAndConfigured) { UserVerificationAvailability::kSupportedAndConfigured;
return can_use_pin ? GetAssertionPINDisposition::kUsePINForFallback
: GetAssertionPINDisposition::kNoPIN;
}
const bool resident_key_request = request.allow_list.empty(); const UserVerificationRequirement uv_requirement =
request.allow_list.empty() ? UserVerificationRequirement::kRequired
: request.user_verification;
if (resident_key_request) { if (uv_requirement == UserVerificationRequirement::kDiscouraged ||
if (can_use_pin) { (uv_requirement == UserVerificationRequirement::kPreferred &&
return GetAssertionPINDisposition::kUsePIN; ((!pin_configured || !can_collect_pin) && !uv_configured))) {
} return PINUVDisposition::kNoUV;
return GetAssertionPINDisposition::kUnsatisfiable;
} }
// If UV is required then the PIN must be used if set, or else this request // Authenticators with built-in UV that don't support UV token should try
// cannot be satisfied. // sending the request as-is with uv=true first.
if (request.user_verification == UserVerificationRequirement::kRequired) { if (uv_configured && !CanGetUvToken()) {
if (can_use_pin) { return (can_collect_pin && pin_configured)
return GetAssertionPINDisposition::kUsePIN; ? PINUVDisposition::kNoTokenInternalUVPINFallback
} : PINUVDisposition::kNoTokenInternalUV;
return GetAssertionPINDisposition::kUnsatisfiable;
} }
// If UV is preferred and a PIN is set, use it. if ((can_collect_pin && pin_configured) || CanGetUvToken()) {
if (request.user_verification == UserVerificationRequirement::kPreferred && return PINUVDisposition::kGetToken;
can_use_pin) {
return GetAssertionPINDisposition::kUsePIN;
} }
return GetAssertionPINDisposition::kNoPIN;
return PINUVDisposition::kUnsatisfiable;
} }
void FidoDeviceAuthenticator::GetCredentialsMetadata( void FidoDeviceAuthenticator::GetCredentialsMetadata(
......
...@@ -67,13 +67,13 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDeviceAuthenticator ...@@ -67,13 +67,13 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDeviceAuthenticator
void ChangePIN(const std::string& old_pin, void ChangePIN(const std::string& old_pin,
const std::string& new_pin, const std::string& new_pin,
SetPINCallback callback) override; SetPINCallback callback) override;
MakeCredentialPINUVDisposition PINUVDispositionForMakeCredential( PINUVDisposition PINUVDispositionForMakeCredential(
const CtapMakeCredentialRequest& request, const CtapMakeCredentialRequest& request,
const FidoRequestHandlerBase::Observer* observer) override; const FidoRequestHandlerBase::Observer* observer) override;
// WillNeedPINToGetAssertion returns whether a PIN prompt will be needed to // WillNeedPINToGetAssertion returns whether a PIN prompt will be needed to
// serve the given request on this authenticator. // serve the given request on this authenticator.
GetAssertionPINDisposition WillNeedPINToGetAssertion( PINUVDisposition PINUVDispositionForGetAssertion(
const CtapGetAssertionRequest& request, const CtapGetAssertionRequest& request,
const FidoRequestHandlerBase::Observer* observer) override; const FidoRequestHandlerBase::Observer* observer) override;
......
...@@ -44,15 +44,15 @@ namespace device { ...@@ -44,15 +44,15 @@ namespace device {
namespace { namespace {
using PINDisposition = FidoAuthenticator::GetAssertionPINDisposition; using PINUVDisposition = FidoAuthenticator::PINUVDisposition;
const std::vector<pin::Permissions> GetPinTokenPermissionsFor( const std::set<pin::Permissions> GetPinTokenPermissionsFor(
const FidoAuthenticator& authenticator, const FidoAuthenticator& authenticator,
const CtapGetAssertionRequest& request) { const CtapGetAssertionRequest& request) {
std::vector<pin::Permissions> permissions = {pin::Permissions::kGetAssertion}; std::set<pin::Permissions> permissions = {pin::Permissions::kGetAssertion};
if (request.large_blob_write && authenticator.Options() && if (request.large_blob_write && authenticator.Options() &&
authenticator.Options()->supports_large_blobs) { authenticator.Options()->supports_large_blobs) {
permissions.emplace_back(pin::Permissions::kLargeBlobWrite); permissions.emplace(pin::Permissions::kLargeBlobWrite);
} }
return permissions; return permissions;
} }
...@@ -75,8 +75,7 @@ base::Optional<GetAssertionStatus> ConvertDeviceResponseCode( ...@@ -75,8 +75,7 @@ base::Optional<GetAssertionStatus> ConvertDeviceResponseCode(
return GetAssertionStatus::kUserConsentDenied; return GetAssertionStatus::kUserConsentDenied;
// External authenticators may return this error if internal user // External authenticators may return this error if internal user
// verification fails for a make credential request or if the pin token is // verification fails or if the pin token is not valid.
// not valid.
case CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid: case CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid:
return GetAssertionStatus::kUserConsentDenied; return GetAssertionStatus::kUserConsentDenied;
...@@ -342,23 +341,20 @@ void GetAssertionRequestHandler::DispatchRequest( ...@@ -342,23 +341,20 @@ void GetAssertionRequestHandler::DispatchRequest(
CtapGetAssertionRequest request = CtapGetAssertionRequest request =
SpecializeRequestForAuthenticator(request_, *authenticator); SpecializeRequestForAuthenticator(request_, *authenticator);
switch (authenticator->WillNeedPINToGetAssertion(request, observer())) { PINUVDisposition uv_disposition =
case PINDisposition::kUsePIN: authenticator->PINUVDispositionForGetAssertion(request, observer());
// Skip asking for touch if this is the only available authenticator. switch (uv_disposition) {
if (active_authenticators().size() == 1 && allow_skipping_pin_touch_) { case PINUVDisposition::kNoUV:
CollectPINThenSendRequest(authenticator); case PINUVDisposition::kNoTokenInternalUV:
return; case PINUVDisposition::kNoTokenInternalUVPINFallback:
} // Proceed without a token.
// A PIN will be needed. Just request a touch to let the user select break;
// this authenticator if they wish. case PINUVDisposition::kGetToken:
FIDO_LOG(DEBUG) << "Asking for touch from " ObtainPINUVAuthToken(authenticator,
<< authenticator->GetDisplayName() GetPinTokenPermissionsFor(*authenticator, request),
<< " because a PIN will be required"; allow_skipping_pin_touch_);
authenticator->GetTouch(
base::BindOnce(&GetAssertionRequestHandler::CollectPINThenSendRequest,
weak_factory_.GetWeakPtr(), authenticator));
return; return;
case PINDisposition::kUnsatisfiable: case PINUVDisposition::kUnsatisfiable:
FIDO_LOG(DEBUG) << authenticator->GetDisplayName() FIDO_LOG(DEBUG) << authenticator->GetDisplayName()
<< " cannot satisfy assertion request. Requesting " << " cannot satisfy assertion request. Requesting "
"touch in order to handle error case."; "touch in order to handle error case.";
...@@ -366,23 +362,10 @@ void GetAssertionRequestHandler::DispatchRequest( ...@@ -366,23 +362,10 @@ void GetAssertionRequestHandler::DispatchRequest(
&GetAssertionRequestHandler::TerminateUnsatisfiableRequestPostTouch, &GetAssertionRequestHandler::TerminateUnsatisfiableRequestPostTouch,
weak_factory_.GetWeakPtr(), authenticator)); weak_factory_.GetWeakPtr(), authenticator));
return; return;
case PINDisposition::kNoPIN:
case PINDisposition::kUsePINForFallback:
break;
}
if (request.user_verification != UserVerificationRequirement::kDiscouraged &&
authenticator->CanGetUvToken()) {
authenticator->GetUvRetries(
base::BindOnce(&GetAssertionRequestHandler::OnStartUvTokenOrFallback,
weak_factory_.GetWeakPtr(), authenticator));
return;
} }
ReportGetAssertionRequestTransport(authenticator); ReportGetAssertionRequestTransport(authenticator);
FIDO_LOG(DEBUG) << "Asking for assertion from "
<< authenticator->GetDisplayName();
CtapGetAssertionRequest request_copy(request); CtapGetAssertionRequest request_copy(request);
authenticator->GetAssertion( authenticator->GetAssertion(
std::move(request_copy), options_, std::move(request_copy), options_,
...@@ -425,12 +408,15 @@ void GetAssertionRequestHandler::AuthenticatorRemoved( ...@@ -425,12 +408,15 @@ void GetAssertionRequestHandler::AuthenticatorRemoved(
FidoAuthenticator* authenticator) { FidoAuthenticator* authenticator) {
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
auth_token_requester_map_.erase(authenticator);
FidoRequestHandlerBase::AuthenticatorRemoved(discovery, authenticator); FidoRequestHandlerBase::AuthenticatorRemoved(discovery, authenticator);
if (authenticator == authenticator_) { if (authenticator == selected_authenticator_for_pin_uv_auth_token_) {
authenticator_ = nullptr; selected_authenticator_for_pin_uv_auth_token_ = nullptr;
if (state_ == State::kWaitingForPIN || // Authenticator could have been removed during PIN entry or PIN fallback
state_ == State::kWaitingForSecondTouch) { // after failed internal UV. Bail and show an error.
if (state_ != State::kFinished) {
state_ = State::kFinished; state_ = State::kFinished;
std::move(completion_callback_) std::move(completion_callback_)
.Run(GetAssertionStatus::kAuthenticatorRemovedDuringPINEntry, .Run(GetAssertionStatus::kAuthenticatorRemovedDuringPINEntry,
...@@ -439,6 +425,107 @@ void GetAssertionRequestHandler::AuthenticatorRemoved( ...@@ -439,6 +425,107 @@ void GetAssertionRequestHandler::AuthenticatorRemoved(
} }
} }
void GetAssertionRequestHandler::AuthenticatorSelectedForPINUVAuthToken(
FidoAuthenticator* authenticator) {
DCHECK_EQ(state_, State::kWaitingForTouch);
state_ = State::kWaitingForToken;
selected_authenticator_for_pin_uv_auth_token_ = authenticator;
base::EraseIf(auth_token_requester_map_, [authenticator](auto& entry) {
return entry.first != authenticator;
});
CancelActiveAuthenticators(authenticator->GetId());
}
void GetAssertionRequestHandler::CollectNewPIN(
uint32_t min_pin_length,
ProvidePINCallback provide_pin_cb) {
DCHECK_EQ(state_, State::kWaitingForToken);
observer()->CollectPIN(min_pin_length, /*attempts=*/base::nullopt,
std::move(provide_pin_cb));
}
void GetAssertionRequestHandler::CollectExistingPIN(
int attempts,
uint32_t min_pin_length,
ProvidePINCallback provide_pin_cb) {
DCHECK_EQ(state_, State::kWaitingForToken);
observer()->CollectPIN(min_pin_length, attempts, std::move(provide_pin_cb));
}
void GetAssertionRequestHandler::PromptForInternalUVRetry(int attempts) {
DCHECK(state_ == State::kWaitingForTouch ||
state_ == State::kWaitingForToken);
observer()->OnRetryUserVerification(attempts);
}
void GetAssertionRequestHandler::InternalUVLockedForAuthToken() {
DCHECK(state_ == State::kWaitingForTouch ||
state_ == State::kWaitingForToken);
observer()->OnInternalUserVerificationLocked();
}
void GetAssertionRequestHandler::HavePINUVAuthTokenResultForAuthenticator(
FidoAuthenticator* authenticator,
AuthTokenRequester::Result result,
base::Optional<pin::TokenResponse> token_response) {
DCHECK_EQ(state_, State::kWaitingForToken);
DCHECK_EQ(selected_authenticator_for_pin_uv_auth_token_, authenticator);
base::Optional<GetAssertionStatus> error;
switch (result) {
case AuthTokenRequester::Result::kPreTouchUnsatisfiableRequest:
case AuthTokenRequester::Result::kPreTouchAuthenticatorResponseInvalid:
FIDO_LOG(ERROR) << "Ignoring AuthTokenRequester::Result="
<< static_cast<int>(result) << " from "
<< authenticator->GetId();
return;
case AuthTokenRequester::Result::kPostTouchAuthenticatorInternalUVLock:
error = GetAssertionStatus::kAuthenticatorMissingUserVerification;
break;
case AuthTokenRequester::Result::kPostTouchAuthenticatorResponseInvalid:
error = GetAssertionStatus::kAuthenticatorResponseInvalid;
break;
case AuthTokenRequester::Result::kPostTouchAuthenticatorOperationDenied:
error = GetAssertionStatus::kUserConsentDenied;
break;
case AuthTokenRequester::Result::kPostTouchAuthenticatorPINSoftLock:
error = GetAssertionStatus::kSoftPINBlock;
break;
case AuthTokenRequester::Result::kPostTouchAuthenticatorPINHardLock:
error = GetAssertionStatus::kHardPINBlock;
break;
case AuthTokenRequester::Result::kSuccess:
break;
}
if (error) {
state_ = State::kFinished;
std::move(completion_callback_).Run(*error, base::nullopt, authenticator);
return;
}
DCHECK_EQ(result, AuthTokenRequester::Result::kSuccess);
auto request = std::make_unique<CtapGetAssertionRequest>(request_);
SpecializeRequestForAuthenticator(*request, *authenticator);
DispatchRequestWithToken(std::move(*token_response));
}
void GetAssertionRequestHandler::ObtainPINUVAuthToken(
FidoAuthenticator* authenticator,
std::set<pin::Permissions> permissions,
bool skip_pin_touch) {
AuthTokenRequester::Options options;
options.token_permissions = std::move(permissions);
options.rp_id = request_.rp_id;
options.skip_pin_touch = skip_pin_touch;
auth_token_requester_map_.insert(
{authenticator, std::make_unique<AuthTokenRequester>(
this, authenticator, std::move(options))});
auth_token_requester_map_.at(authenticator)->ObtainPINUVAuthToken();
}
void GetAssertionRequestHandler::HandleResponse( void GetAssertionRequestHandler::HandleResponse(
FidoAuthenticator* authenticator, FidoAuthenticator* authenticator,
CtapGetAssertionRequest request, CtapGetAssertionRequest request,
...@@ -448,7 +535,7 @@ void GetAssertionRequestHandler::HandleResponse( ...@@ -448,7 +535,7 @@ void GetAssertionRequestHandler::HandleResponse(
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
if (state_ != State::kWaitingForTouch && if (state_ != State::kWaitingForTouch &&
state_ != State::kWaitingForSecondTouch) { state_ != State::kWaitingForResponseWithToken) {
FIDO_LOG(DEBUG) << "Ignoring response from " FIDO_LOG(DEBUG) << "Ignoring response from "
<< authenticator->GetDisplayName() << authenticator->GetDisplayName()
<< " because no longer waiting for touch"; << " because no longer waiting for touch";
...@@ -483,34 +570,36 @@ void GetAssertionRequestHandler::HandleResponse( ...@@ -483,34 +570,36 @@ void GetAssertionRequestHandler::HandleResponse(
} }
#endif #endif
// Requests that require a PIN should follow the |GetTouch| path initially. // If we requested UV from an authentiator without uvToken support, UV failed,
DCHECK(state_ == State::kWaitingForSecondTouch || // and the authenticator supports PIN, fall back to that.
authenticator->WillNeedPINToGetAssertion(request, observer()) != if (request.user_verification != UserVerificationRequirement::kDiscouraged &&
PINDisposition::kUsePIN); !request.pin_auth &&
(status == CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid ||
if ((status == CtapDeviceResponseCode::kCtap2ErrPinRequired || status == CtapDeviceResponseCode::kCtap2ErrPinRequired ||
status == CtapDeviceResponseCode::kCtap2ErrOperationDenied) && status == CtapDeviceResponseCode::kCtap2ErrOperationDenied) &&
authenticator->WillNeedPINToGetAssertion(request, observer()) == authenticator->PINUVDispositionForGetAssertion(request, observer()) ==
PINDisposition::kUsePINForFallback) { PINUVDisposition::kNoTokenInternalUVPINFallback) {
// Authenticators without uvToken support will return this error immediately // Authenticators without uvToken support will return this error immediately
// without user interaction when internal UV is locked. // without user interaction when internal UV is locked.
const base::TimeDelta response_time = request_timer.Elapsed(); const base::TimeDelta response_time = request_timer.Elapsed();
if (response_time < kMinExpectedAuthenticatorResponseTime) { if (response_time < kMinExpectedAuthenticatorResponseTime) {
FIDO_LOG(DEBUG) << "Authenticator is probably locked, response_time=" FIDO_LOG(DEBUG) << "Authenticator is probably locked, response_time="
<< response_time; << response_time;
authenticator->GetTouch(base::BindOnce( ObtainPINUVAuthToken(authenticator,
&GetAssertionRequestHandler::StartPINFallbackForInternalUv, GetPinTokenPermissionsFor(*authenticator, request),
weak_factory_.GetWeakPtr(), authenticator)); /*skip_pin_touch=*/false);
return; return;
} }
StartPINFallbackForInternalUv(authenticator); ObtainPINUVAuthToken(authenticator,
GetPinTokenPermissionsFor(*authenticator, request),
/*skip_pin_touch=*/true);
return; return;
} }
const base::Optional<GetAssertionStatus> maybe_result = const base::Optional<GetAssertionStatus> maybe_result =
ConvertDeviceResponseCode(status); ConvertDeviceResponseCode(status);
if (!maybe_result) { if (!maybe_result) {
if (state_ == State::kWaitingForSecondTouch) { if (state_ == State::kWaitingForResponseWithToken) {
std::move(completion_callback_) std::move(completion_callback_)
.Run(GetAssertionStatus::kAuthenticatorResponseInvalid, base::nullopt, .Run(GetAssertionStatus::kAuthenticatorResponseInvalid, base::nullopt,
authenticator); authenticator);
...@@ -613,34 +702,6 @@ void GetAssertionRequestHandler::HandleNextResponse( ...@@ -613,34 +702,6 @@ void GetAssertionRequestHandler::HandleNextResponse(
OnGetAssertionSuccess(authenticator, std::move(request)); OnGetAssertionSuccess(authenticator, std::move(request));
} }
void GetAssertionRequestHandler::CollectPINThenSendRequest(
FidoAuthenticator* authenticator) {
if (state_ != State::kWaitingForTouch) {
return;
}
DCHECK_NE(authenticator->WillNeedPINToGetAssertion(
SpecializeRequestForAuthenticator(request_, *authenticator),
observer()),
PINDisposition::kNoPIN);
DCHECK(observer());
state_ = State::kGettingRetries;
CancelActiveAuthenticators(authenticator->GetId());
authenticator_ = authenticator;
authenticator_->GetPinRetries(
base::BindOnce(&GetAssertionRequestHandler::OnPinRetriesResponse,
weak_factory_.GetWeakPtr()));
}
void GetAssertionRequestHandler::StartPINFallbackForInternalUv(
FidoAuthenticator* authenticator) {
DCHECK_EQ(authenticator->WillNeedPINToGetAssertion(
SpecializeRequestForAuthenticator(request_, *authenticator),
observer()),
PINDisposition::kUsePINForFallback);
observer()->OnInternalUserVerificationLocked();
CollectPINThenSendRequest(authenticator);
}
void GetAssertionRequestHandler::TerminateUnsatisfiableRequestPostTouch( void GetAssertionRequestHandler::TerminateUnsatisfiableRequestPostTouch(
FidoAuthenticator* authenticator) { FidoAuthenticator* authenticator) {
// User touched an authenticator that cannot handle this request or internal // User touched an authenticator that cannot handle this request or internal
...@@ -653,220 +714,27 @@ void GetAssertionRequestHandler::TerminateUnsatisfiableRequestPostTouch( ...@@ -653,220 +714,27 @@ void GetAssertionRequestHandler::TerminateUnsatisfiableRequestPostTouch(
base::nullopt, nullptr); base::nullopt, nullptr);
} }
void GetAssertionRequestHandler::OnPinRetriesResponse(
CtapDeviceResponseCode status,
base::Optional<pin::RetriesResponse> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
DCHECK_EQ(state_, State::kGettingRetries);
if (status != CtapDeviceResponseCode::kSuccess) {
FIDO_LOG(ERROR) << "OnPinRetriesResponse() failed for "
<< authenticator_->GetDisplayName();
state_ = State::kFinished;
std::move(completion_callback_)
.Run(GetAssertionStatus::kAuthenticatorResponseInvalid, base::nullopt,
nullptr);
return;
}
if (response->retries == 0) {
state_ = State::kFinished;
std::move(completion_callback_)
.Run(GetAssertionStatus::kHardPINBlock, base::nullopt, nullptr);
return;
}
state_ = State::kWaitingForPIN;
observer()->CollectPIN(authenticator_->CurrentMinPINLength(),
response->retries,
base::BindOnce(&GetAssertionRequestHandler::OnHavePIN,
weak_factory_.GetWeakPtr()));
}
void GetAssertionRequestHandler::OnHavePIN(std::string pin) {
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
DCHECK_EQ(State::kWaitingForPIN, state_);
DCHECK(pin::IsValid(pin));
if (authenticator_ == nullptr) {
// Authenticator was detached. The request will already have been canceled
// but this callback may have been waiting in a queue.
return;
}
state_ = State::kRequestWithPIN;
authenticator_->GetPINToken(
std::move(pin), GetPinTokenPermissionsFor(*authenticator_, request_),
request_.rp_id,
base::BindOnce(&GetAssertionRequestHandler::OnHavePINToken,
weak_factory_.GetWeakPtr()));
}
void GetAssertionRequestHandler::OnHavePINToken(
CtapDeviceResponseCode status,
base::Optional<pin::TokenResponse> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
DCHECK_EQ(state_, State::kRequestWithPIN);
if (status == CtapDeviceResponseCode::kCtap2ErrPinInvalid) {
state_ = State::kGettingRetries;
authenticator_->GetPinRetries(
base::BindOnce(&GetAssertionRequestHandler::OnPinRetriesResponse,
weak_factory_.GetWeakPtr()));
return;
}
if (status != CtapDeviceResponseCode::kSuccess) {
state_ = State::kFinished;
GetAssertionStatus ret;
switch (status) {
case CtapDeviceResponseCode::kCtap2ErrPinAuthBlocked:
ret = GetAssertionStatus::kSoftPINBlock;
break;
case CtapDeviceResponseCode::kCtap2ErrPinBlocked:
ret = GetAssertionStatus::kHardPINBlock;
break;
default:
ret = GetAssertionStatus::kAuthenticatorResponseInvalid;
break;
}
std::move(completion_callback_).Run(ret, base::nullopt, nullptr);
return;
}
DispatchRequestWithToken(std::move(*response));
}
void GetAssertionRequestHandler::OnStartUvTokenOrFallback(
FidoAuthenticator* authenticator,
CtapDeviceResponseCode status,
base::Optional<pin::RetriesResponse> response) {
size_t retries;
if (status != CtapDeviceResponseCode::kSuccess) {
FIDO_LOG(ERROR) << "OnStartUvTokenOrFallback() failed for "
<< authenticator_->GetDisplayName()
<< ", assuming authenticator locked.";
retries = 0;
} else {
retries = response->retries;
}
if (retries == 0) {
CtapGetAssertionRequest request =
SpecializeRequestForAuthenticator(request_, *authenticator);
if (authenticator->WillNeedPINToGetAssertion(request, observer()) ==
PINDisposition::kUsePINForFallback) {
authenticator->GetTouch(base::BindOnce(
&GetAssertionRequestHandler::StartPINFallbackForInternalUv,
weak_factory_.GetWeakPtr(), authenticator));
return;
}
authenticator->GetTouch(base::BindOnce(
&GetAssertionRequestHandler::TerminateUnsatisfiableRequestPostTouch,
weak_factory_.GetWeakPtr(), authenticator));
}
authenticator->GetUvToken(
GetPinTokenPermissionsFor(*authenticator, request_), request_.rp_id,
base::BindOnce(&GetAssertionRequestHandler::OnHaveUvToken,
weak_factory_.GetWeakPtr(), authenticator));
}
void GetAssertionRequestHandler::OnUvRetriesResponse(
CtapDeviceResponseCode status,
base::Optional<pin::RetriesResponse> response) {
if (status != CtapDeviceResponseCode::kSuccess) {
FIDO_LOG(ERROR) << "OnUvRetriesResponse() failed for "
<< authenticator_->GetDisplayName();
state_ = State::kFinished;
std::move(completion_callback_)
.Run(GetAssertionStatus::kAuthenticatorResponseInvalid, base::nullopt,
nullptr);
return;
}
state_ = State::kWaitingForTouch;
if (response->retries == 0) {
CtapGetAssertionRequest request =
SpecializeRequestForAuthenticator(request_, *authenticator_);
if (authenticator_->WillNeedPINToGetAssertion(request, observer()) ==
PINDisposition::kUsePINForFallback) {
// Fall back to PIN.
StartPINFallbackForInternalUv(authenticator_);
return;
}
// Device does not support fallback to PIN, terminate the request instead.
TerminateUnsatisfiableRequestPostTouch(authenticator_);
return;
}
observer()->OnRetryUserVerification(response->retries);
authenticator_->GetUvToken(
GetPinTokenPermissionsFor(*authenticator_, request_), request_.rp_id,
base::BindOnce(&GetAssertionRequestHandler::OnHaveUvToken,
weak_factory_.GetWeakPtr(), authenticator_));
}
void GetAssertionRequestHandler::OnHaveUvToken(
FidoAuthenticator* authenticator,
CtapDeviceResponseCode status,
base::Optional<pin::TokenResponse> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
if (state_ != State::kWaitingForTouch) {
FIDO_LOG(DEBUG) << "Ignoring uv token response from "
<< authenticator->GetDisplayName()
<< " because no longer waiting for touch";
return;
}
if (status == CtapDeviceResponseCode::kCtap2ErrUvInvalid ||
status == CtapDeviceResponseCode::kCtap2ErrOperationDenied ||
status == CtapDeviceResponseCode::kCtap2ErrUvBlocked) {
if (status == CtapDeviceResponseCode::kCtap2ErrUvBlocked) {
CtapGetAssertionRequest request =
SpecializeRequestForAuthenticator(request_, *authenticator_);
if (authenticator->WillNeedPINToGetAssertion(request, observer()) ==
PINDisposition::kUsePINForFallback) {
StartPINFallbackForInternalUv(authenticator);
return;
}
TerminateUnsatisfiableRequestPostTouch(authenticator);
return;
}
DCHECK(status == CtapDeviceResponseCode::kCtap2ErrUvInvalid ||
status == CtapDeviceResponseCode::kCtap2ErrOperationDenied);
CancelActiveAuthenticators(authenticator->GetId());
authenticator_ = authenticator;
state_ = State::kGettingRetries;
authenticator->GetUvRetries(
base::BindOnce(&GetAssertionRequestHandler::OnUvRetriesResponse,
weak_factory_.GetWeakPtr()));
return;
}
if (status != CtapDeviceResponseCode::kSuccess) {
FIDO_LOG(ERROR) << "Ignoring status " << static_cast<int>(status)
<< " from " << authenticator->GetDisplayName();
return;
}
CancelActiveAuthenticators(authenticator->GetId());
authenticator_ = authenticator;
DispatchRequestWithToken(std::move(*response));
}
void GetAssertionRequestHandler::DispatchRequestWithToken( void GetAssertionRequestHandler::DispatchRequestWithToken(
pin::TokenResponse token) { pin::TokenResponse token) {
DCHECK(selected_authenticator_for_pin_uv_auth_token_);
observer()->FinishCollectToken(); observer()->FinishCollectToken();
pin_token_ = std::move(token); pin_token_ = std::move(token);
state_ = State::kWaitingForSecondTouch; state_ = State::kWaitingForResponseWithToken;
CtapGetAssertionRequest request = CtapGetAssertionRequest request = SpecializeRequestForAuthenticator(
SpecializeRequestForAuthenticator(request_, *authenticator_); request_, *selected_authenticator_for_pin_uv_auth_token_);
std::tie(request.pin_protocol, request.pin_auth) = std::tie(request.pin_protocol, request.pin_auth) =
pin_token_->PinAuth(request.client_data_hash); pin_token_->PinAuth(request.client_data_hash);
ReportGetAssertionRequestTransport(authenticator_); ReportGetAssertionRequestTransport(
selected_authenticator_for_pin_uv_auth_token_);
auto request_copy(request); auto request_copy(request);
authenticator_->GetAssertion( selected_authenticator_for_pin_uv_auth_token_->GetAssertion(
std::move(request_copy), options_, std::move(request_copy), options_,
base::BindOnce(&GetAssertionRequestHandler::HandleResponse, base::BindOnce(&GetAssertionRequestHandler::HandleResponse,
weak_factory_.GetWeakPtr(), authenticator_, weak_factory_.GetWeakPtr(),
selected_authenticator_for_pin_uv_auth_token_,
std::move(request), base::ElapsedTimer())); std::move(request), base::ElapsedTimer()));
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define DEVICE_FIDO_GET_ASSERTION_REQUEST_HANDLER_H_ #define DEVICE_FIDO_GET_ASSERTION_REQUEST_HANDLER_H_
#include <memory> #include <memory>
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -13,6 +14,7 @@ ...@@ -13,6 +14,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "device/fido/auth_token_requester.h"
#include "device/fido/authenticator_get_assertion_response.h" #include "device/fido/authenticator_get_assertion_response.h"
#include "device/fido/ctap_get_assertion_request.h" #include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/fido_constants.h" #include "device/fido/fido_constants.h"
...@@ -29,7 +31,6 @@ class FidoAuthenticator; ...@@ -29,7 +31,6 @@ class FidoAuthenticator;
class FidoDiscoveryFactory; class FidoDiscoveryFactory;
namespace pin { namespace pin {
struct RetriesResponse;
class TokenResponse; class TokenResponse;
} // namespace pin } // namespace pin
...@@ -51,7 +52,8 @@ enum class GetAssertionStatus { ...@@ -51,7 +52,8 @@ enum class GetAssertionStatus {
}; };
class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler
: public FidoRequestHandlerBase { : public FidoRequestHandlerBase,
public AuthTokenRequester::Delegate {
public: public:
using CompletionCallback = base::OnceCallback<void( using CompletionCallback = base::OnceCallback<void(
GetAssertionStatus, GetAssertionStatus,
...@@ -70,10 +72,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler ...@@ -70,10 +72,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler
private: private:
enum class State { enum class State {
kWaitingForTouch, kWaitingForTouch,
kWaitingForSecondTouch, kWaitingForToken,
kGettingRetries, kWaitingForResponseWithToken,
kWaitingForPIN,
kRequestWithPIN,
kReadingMultipleResponses, kReadingMultipleResponses,
kFinished, kFinished,
}; };
...@@ -89,6 +89,24 @@ class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler ...@@ -89,6 +89,24 @@ class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler
void AuthenticatorRemoved(FidoDiscoveryBase* discovery, void AuthenticatorRemoved(FidoDiscoveryBase* discovery,
FidoAuthenticator* authenticator) override; FidoAuthenticator* authenticator) override;
// AuthTokenRequester::Delegate:
void AuthenticatorSelectedForPINUVAuthToken(
FidoAuthenticator* authenticator) override;
void CollectNewPIN(uint32_t min_pin_length,
ProvidePINCallback provide_pin_cb) override;
void CollectExistingPIN(int attempts,
uint32_t min_pin_length,
ProvidePINCallback provide_pin_cb) override;
void PromptForInternalUVRetry(int attempts) override;
void InternalUVLockedForAuthToken() override;
void HavePINUVAuthTokenResultForAuthenticator(
FidoAuthenticator* authenticator,
AuthTokenRequester::Result result,
base::Optional<pin::TokenResponse> response) override;
void ObtainPINUVAuthToken(FidoAuthenticator* authenticator,
std::set<pin::Permissions> permissions,
bool skip_pin_touch);
void HandleResponse( void HandleResponse(
FidoAuthenticator* authenticator, FidoAuthenticator* authenticator,
CtapGetAssertionRequest request, CtapGetAssertionRequest request,
...@@ -100,22 +118,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler ...@@ -100,22 +118,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler
CtapGetAssertionRequest request, CtapGetAssertionRequest request,
CtapDeviceResponseCode response_code, CtapDeviceResponseCode response_code,
base::Optional<AuthenticatorGetAssertionResponse> response); base::Optional<AuthenticatorGetAssertionResponse> response);
void CollectPINThenSendRequest(FidoAuthenticator* authenticator);
void StartPINFallbackForInternalUv(FidoAuthenticator* authenticator);
void TerminateUnsatisfiableRequestPostTouch(FidoAuthenticator* authenticator); void TerminateUnsatisfiableRequestPostTouch(FidoAuthenticator* authenticator);
void OnPinRetriesResponse(CtapDeviceResponseCode status,
base::Optional<pin::RetriesResponse> response);
void OnHavePIN(std::string pin);
void OnHavePINToken(CtapDeviceResponseCode status,
base::Optional<pin::TokenResponse> response);
void OnStartUvTokenOrFallback(FidoAuthenticator* authenticator,
CtapDeviceResponseCode status,
base::Optional<pin::RetriesResponse> response);
void OnUvRetriesResponse(CtapDeviceResponseCode status,
base::Optional<pin::RetriesResponse> response);
void OnHaveUvToken(FidoAuthenticator* authenticator,
CtapDeviceResponseCode status,
base::Optional<pin::TokenResponse> response);
void DispatchRequestWithToken(pin::TokenResponse token); void DispatchRequestWithToken(pin::TokenResponse token);
void OnGetAssertionSuccess(FidoAuthenticator* authenticator, void OnGetAssertionSuccess(FidoAuthenticator* authenticator,
CtapGetAssertionRequest request); CtapGetAssertionRequest request);
...@@ -132,23 +135,32 @@ class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler ...@@ -132,23 +135,32 @@ class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler
CtapGetAssertionRequest request_; CtapGetAssertionRequest request_;
CtapGetAssertionOptions options_; CtapGetAssertionOptions options_;
base::Optional<pin::TokenResponse> pin_token_; base::Optional<pin::TokenResponse> pin_token_;
// If true, and if at the time the request is dispatched to the first // If true, and if at the time the request is dispatched to the first
// authenticator no other authenticators are available, the request handler // authenticator no other authenticators are available, the request handler
// will skip the initial touch that is usually required to select a PIN // will skip the initial touch that is usually required to select a PIN
// protected authenticator. // protected authenticator.
bool allow_skipping_pin_touch_; bool allow_skipping_pin_touch_;
// authenticator_ points to the authenticator that will be used for this
// operation. It's only set after the user touches an authenticator to select // selected_authenticator_for_pin_uv_auth_token_ points to the authenticator
// it, after which point that authenticator will be used exclusively through // that was tapped by the user while requesting a pinUvAuthToken from
// requesting PIN etc. The object is owned by the underlying discovery object // connected authenticators. The object is owned by the underlying discovery
// and this pointer is cleared if it's removed during processing. // object and this pointer is cleared if it's removed during processing.
FidoAuthenticator* authenticator_ = nullptr; FidoAuthenticator* selected_authenticator_for_pin_uv_auth_token_ = nullptr;
// responses_ holds the set of responses while they are incrementally read // responses_ holds the set of responses while they are incrementally read
// from the device. Only used when more than one response is returned. // from the device. Only used when more than one response is returned.
std::vector<AuthenticatorGetAssertionResponse> responses_; std::vector<AuthenticatorGetAssertionResponse> responses_;
// remaining_responses_ contains the number of responses that remain to be // remaining_responses_ contains the number of responses that remain to be
// read when multiple responses are returned. // read when multiple responses are returned.
size_t remaining_responses_ = 0; size_t remaining_responses_ = 0;
// auth_token_requester_map_ holds active AuthTokenRequesters for
// authenticators that need a pinUvAuthToken to service the request.
std::map<FidoAuthenticator*, std::unique_ptr<AuthTokenRequester>>
auth_token_requester_map_;
SEQUENCE_CHECKER(my_sequence_checker_); SEQUENCE_CHECKER(my_sequence_checker_);
base::WeakPtrFactory<GetAssertionRequestHandler> weak_factory_{this}; base::WeakPtrFactory<GetAssertionRequestHandler> weak_factory_{this};
......
...@@ -27,8 +27,7 @@ ...@@ -27,8 +27,7 @@
namespace device { namespace device {
using MakeCredentialPINUVDisposition = using PINUVDisposition = FidoAuthenticator::PINUVDisposition;
FidoAuthenticator::MakeCredentialPINUVDisposition;
using BioEnrollmentAvailability = using BioEnrollmentAvailability =
AuthenticatorSupportedOptions::BioEnrollmentAvailability; AuthenticatorSupportedOptions::BioEnrollmentAvailability;
...@@ -130,7 +129,7 @@ MakeCredentialStatus IsCandidateAuthenticatorPostTouch( ...@@ -130,7 +129,7 @@ MakeCredentialStatus IsCandidateAuthenticatorPostTouch(
} }
if (authenticator->PINUVDispositionForMakeCredential(request, observer) == if (authenticator->PINUVDispositionForMakeCredential(request, observer) ==
MakeCredentialPINUVDisposition::kUnsatisfiable) { PINUVDisposition::kUnsatisfiable) {
return MakeCredentialStatus::kAuthenticatorMissingUserVerification; return MakeCredentialStatus::kAuthenticatorMissingUserVerification;
} }
...@@ -428,14 +427,14 @@ void MakeCredentialRequestHandler::DispatchRequest( ...@@ -428,14 +427,14 @@ void MakeCredentialRequestHandler::DispatchRequest(
auto uv_disposition = authenticator->PINUVDispositionForMakeCredential( auto uv_disposition = authenticator->PINUVDispositionForMakeCredential(
*request.get(), observer()); *request.get(), observer());
switch (uv_disposition) { switch (uv_disposition) {
case MakeCredentialPINUVDisposition::kNoUV: case PINUVDisposition::kNoUV:
case MakeCredentialPINUVDisposition::kNoTokenInternalUV: case PINUVDisposition::kNoTokenInternalUV:
case MakeCredentialPINUVDisposition::kNoTokenInternalUVPINFallback: case PINUVDisposition::kNoTokenInternalUVPINFallback:
break; break;
case MakeCredentialPINUVDisposition::kGetToken: case PINUVDisposition::kGetToken:
ObtainPINUVAuthToken(authenticator, skip_pin_touch); ObtainPINUVAuthToken(authenticator, skip_pin_touch);
return; return;
case MakeCredentialPINUVDisposition::kUnsatisfiable: case PINUVDisposition::kUnsatisfiable:
// |IsCandidateAuthenticatorPostTouch| should have handled this case. // |IsCandidateAuthenticatorPostTouch| should have handled this case.
NOTREACHED(); NOTREACHED();
return; return;
...@@ -529,8 +528,8 @@ void MakeCredentialRequestHandler::HavePINUVAuthTokenResultForAuthenticator( ...@@ -529,8 +528,8 @@ void MakeCredentialRequestHandler::HavePINUVAuthTokenResultForAuthenticator(
<< authenticator->GetId(); << authenticator->GetId();
return; return;
case AuthTokenRequester::Result::kPostTouchAuthenticatorInternalUVLock: case AuthTokenRequester::Result::kPostTouchAuthenticatorInternalUVLock:
HandleInternalUvLocked(authenticator); error = MakeCredentialStatus::kAuthenticatorMissingUserVerification;
return; break;
case AuthTokenRequester::Result::kPostTouchAuthenticatorResponseInvalid: case AuthTokenRequester::Result::kPostTouchAuthenticatorResponseInvalid:
error = MakeCredentialStatus::kAuthenticatorResponseInvalid; error = MakeCredentialStatus::kAuthenticatorResponseInvalid;
break; break;
...@@ -641,7 +640,7 @@ void MakeCredentialRequestHandler::HandleResponse( ...@@ -641,7 +640,7 @@ void MakeCredentialRequestHandler::HandleResponse(
(status == CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid || (status == CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid ||
status == CtapDeviceResponseCode::kCtap2ErrPinRequired) && status == CtapDeviceResponseCode::kCtap2ErrPinRequired) &&
authenticator->PINUVDispositionForMakeCredential(*request, observer()) == authenticator->PINUVDispositionForMakeCredential(*request, observer()) ==
MakeCredentialPINUVDisposition::kNoTokenInternalUVPINFallback) { PINUVDisposition::kNoTokenInternalUVPINFallback) {
// Authenticators without uvToken support will return this error immediately // Authenticators without uvToken support will return this error immediately
// without user interaction when internal UV is locked. // without user interaction when internal UV is locked.
const base::TimeDelta response_time = request_timer.Elapsed(); const base::TimeDelta response_time = request_timer.Elapsed();
...@@ -718,15 +717,6 @@ void MakeCredentialRequestHandler::HandleResponse( ...@@ -718,15 +717,6 @@ void MakeCredentialRequestHandler::HandleResponse(
.Run(MakeCredentialStatus::kSuccess, std::move(*response), authenticator); .Run(MakeCredentialStatus::kSuccess, std::move(*response), authenticator);
} }
void MakeCredentialRequestHandler::HandleInternalUvLocked(
FidoAuthenticator* authenticator) {
state_ = State::kFinished;
CancelActiveAuthenticators(authenticator->GetId());
std::move(completion_callback_)
.Run(MakeCredentialStatus::kAuthenticatorMissingUserVerification,
base::nullopt, nullptr);
}
void MakeCredentialRequestHandler::HandleInapplicableAuthenticator( void MakeCredentialRequestHandler::HandleInapplicableAuthenticator(
FidoAuthenticator* authenticator, FidoAuthenticator* authenticator,
std::unique_ptr<CtapMakeCredentialRequest> request) { std::unique_ptr<CtapMakeCredentialRequest> request) {
......
...@@ -178,7 +178,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) MakeCredentialRequestHandler ...@@ -178,7 +178,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) MakeCredentialRequestHandler
base::ElapsedTimer request_timer, base::ElapsedTimer request_timer,
CtapDeviceResponseCode response_code, CtapDeviceResponseCode response_code,
base::Optional<AuthenticatorMakeCredentialResponse> response); base::Optional<AuthenticatorMakeCredentialResponse> response);
void HandleInternalUvLocked(FidoAuthenticator* authenticator);
void HandleInapplicableAuthenticator( void HandleInapplicableAuthenticator(
FidoAuthenticator* authenticator, FidoAuthenticator* authenticator,
std::unique_ptr<CtapMakeCredentialRequest> request); std::unique_ptr<CtapMakeCredentialRequest> request);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment