123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include <string>
- #include <utility>
- #include "base/bind.h"
- #include "base/check_op.h"
- #include "device/fido/fido_authenticator.h"
- #include "device/fido/fido_constants.h"
- #include "device/fido/pin.h"
- #include "device/fido/set_pin_request_handler.h"
- namespace device {
- SetPINRequestHandler::SetPINRequestHandler(
- const base::flat_set<FidoTransportProtocol>& supported_transports,
- GetPINCallback get_pin_callback,
- FinishedCallback finished_callback,
- std::unique_ptr<FidoDiscoveryFactory> fido_discovery_factory)
- : FidoRequestHandlerBase(fido_discovery_factory.get(),
- supported_transports),
- get_pin_callback_(std::move(get_pin_callback)),
- finished_callback_(std::move(finished_callback)),
- fido_discovery_factory_(std::move(fido_discovery_factory)) {
- Start();
- }
- SetPINRequestHandler::~SetPINRequestHandler() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
- }
- void SetPINRequestHandler::ProvidePIN(const std::string& old_pin,
- const std::string& new_pin) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
- DCHECK_EQ(State::kWaitingForPIN, state_);
- DCHECK_EQ(pin::ValidatePIN(new_pin), pin::PINEntryError::kNoError);
- if (authenticator_ == nullptr) {
- // Authenticator was detached.
- state_ = State::kFinished;
- finished_callback_.Run(CtapDeviceResponseCode::kCtap1ErrInvalidChannel);
- return;
- }
- state_ = State::kSettingPIN;
- if (old_pin.empty()) {
- authenticator_->SetPIN(
- new_pin, base::BindOnce(&SetPINRequestHandler::OnSetPINComplete,
- weak_factory_.GetWeakPtr()));
- } else {
- authenticator_->ChangePIN(
- old_pin, new_pin,
- base::BindOnce(&SetPINRequestHandler::OnSetPINComplete,
- weak_factory_.GetWeakPtr()));
- }
- }
- void SetPINRequestHandler::DispatchRequest(FidoAuthenticator* authenticator) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
- authenticator->GetTouch(base::BindOnce(&SetPINRequestHandler::OnTouch,
- weak_factory_.GetWeakPtr(),
- authenticator));
- }
- void SetPINRequestHandler::AuthenticatorRemoved(
- FidoDiscoveryBase* discovery,
- FidoAuthenticator* authenticator) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
- if (authenticator == authenticator_) {
- authenticator_ = nullptr;
- }
- FidoRequestHandlerBase::AuthenticatorRemoved(discovery, authenticator);
- }
- void SetPINRequestHandler::OnTouch(FidoAuthenticator* authenticator) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
- if (state_ != State::kWaitingForTouch) {
- return;
- }
- authenticator_ = authenticator;
- switch (authenticator_->Options()->client_pin_availability) {
- case AuthenticatorSupportedOptions::ClientPinAvailability::kNotSupported:
- state_ = State::kFinished;
- CancelActiveAuthenticators(authenticator->GetId());
- finished_callback_.Run(CtapDeviceResponseCode::kCtap1ErrInvalidCommand);
- return;
- case AuthenticatorSupportedOptions::ClientPinAvailability::
- kSupportedAndPinSet:
- state_ = State::kGettingRetries;
- CancelActiveAuthenticators(authenticator->GetId());
- authenticator_->GetPinRetries(
- base::BindOnce(&SetPINRequestHandler::OnRetriesResponse,
- weak_factory_.GetWeakPtr()));
- break;
- case AuthenticatorSupportedOptions::ClientPinAvailability::
- kSupportedButPinNotSet:
- state_ = State::kWaitingForPIN;
- CancelActiveAuthenticators(authenticator->GetId());
- std::move(get_pin_callback_)
- .Run(authenticator->CurrentMinPINLength(),
- authenticator->NewMinPINLength(), absl::nullopt);
- break;
- }
- }
- void SetPINRequestHandler::OnRetriesResponse(
- CtapDeviceResponseCode status,
- absl::optional<pin::RetriesResponse> response) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
- DCHECK_EQ(state_, State::kGettingRetries);
- if (status != CtapDeviceResponseCode::kSuccess) {
- state_ = State::kFinished;
- finished_callback_.Run(status);
- return;
- }
- state_ = State::kWaitingForPIN;
- std::move(get_pin_callback_)
- .Run(authenticator_->CurrentMinPINLength(),
- authenticator_->NewMinPINLength(), response->retries);
- }
- void SetPINRequestHandler::OnSetPINComplete(
- CtapDeviceResponseCode status,
- absl::optional<pin::EmptyResponse> response) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
- DCHECK_EQ(state_, State::kSettingPIN);
- if (status == CtapDeviceResponseCode::kCtap2ErrPinInvalid) {
- // The caller may try again.
- state_ = State::kWaitingForPIN;
- } else {
- state_ = State::kFinished;
- }
- finished_callback_.Run(status);
- }
- } // namespace device
|