set_pin_request_handler.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <string>
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/check_op.h"
  8. #include "device/fido/fido_authenticator.h"
  9. #include "device/fido/fido_constants.h"
  10. #include "device/fido/pin.h"
  11. #include "device/fido/set_pin_request_handler.h"
  12. namespace device {
  13. SetPINRequestHandler::SetPINRequestHandler(
  14. const base::flat_set<FidoTransportProtocol>& supported_transports,
  15. GetPINCallback get_pin_callback,
  16. FinishedCallback finished_callback,
  17. std::unique_ptr<FidoDiscoveryFactory> fido_discovery_factory)
  18. : FidoRequestHandlerBase(fido_discovery_factory.get(),
  19. supported_transports),
  20. get_pin_callback_(std::move(get_pin_callback)),
  21. finished_callback_(std::move(finished_callback)),
  22. fido_discovery_factory_(std::move(fido_discovery_factory)) {
  23. Start();
  24. }
  25. SetPINRequestHandler::~SetPINRequestHandler() {
  26. DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
  27. }
  28. void SetPINRequestHandler::ProvidePIN(const std::string& old_pin,
  29. const std::string& new_pin) {
  30. DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
  31. DCHECK_EQ(State::kWaitingForPIN, state_);
  32. DCHECK_EQ(pin::ValidatePIN(new_pin), pin::PINEntryError::kNoError);
  33. if (authenticator_ == nullptr) {
  34. // Authenticator was detached.
  35. state_ = State::kFinished;
  36. finished_callback_.Run(CtapDeviceResponseCode::kCtap1ErrInvalidChannel);
  37. return;
  38. }
  39. state_ = State::kSettingPIN;
  40. if (old_pin.empty()) {
  41. authenticator_->SetPIN(
  42. new_pin, base::BindOnce(&SetPINRequestHandler::OnSetPINComplete,
  43. weak_factory_.GetWeakPtr()));
  44. } else {
  45. authenticator_->ChangePIN(
  46. old_pin, new_pin,
  47. base::BindOnce(&SetPINRequestHandler::OnSetPINComplete,
  48. weak_factory_.GetWeakPtr()));
  49. }
  50. }
  51. void SetPINRequestHandler::DispatchRequest(FidoAuthenticator* authenticator) {
  52. DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
  53. authenticator->GetTouch(base::BindOnce(&SetPINRequestHandler::OnTouch,
  54. weak_factory_.GetWeakPtr(),
  55. authenticator));
  56. }
  57. void SetPINRequestHandler::AuthenticatorRemoved(
  58. FidoDiscoveryBase* discovery,
  59. FidoAuthenticator* authenticator) {
  60. DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
  61. if (authenticator == authenticator_) {
  62. authenticator_ = nullptr;
  63. }
  64. FidoRequestHandlerBase::AuthenticatorRemoved(discovery, authenticator);
  65. }
  66. void SetPINRequestHandler::OnTouch(FidoAuthenticator* authenticator) {
  67. DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
  68. if (state_ != State::kWaitingForTouch) {
  69. return;
  70. }
  71. authenticator_ = authenticator;
  72. switch (authenticator_->Options()->client_pin_availability) {
  73. case AuthenticatorSupportedOptions::ClientPinAvailability::kNotSupported:
  74. state_ = State::kFinished;
  75. CancelActiveAuthenticators(authenticator->GetId());
  76. finished_callback_.Run(CtapDeviceResponseCode::kCtap1ErrInvalidCommand);
  77. return;
  78. case AuthenticatorSupportedOptions::ClientPinAvailability::
  79. kSupportedAndPinSet:
  80. state_ = State::kGettingRetries;
  81. CancelActiveAuthenticators(authenticator->GetId());
  82. authenticator_->GetPinRetries(
  83. base::BindOnce(&SetPINRequestHandler::OnRetriesResponse,
  84. weak_factory_.GetWeakPtr()));
  85. break;
  86. case AuthenticatorSupportedOptions::ClientPinAvailability::
  87. kSupportedButPinNotSet:
  88. state_ = State::kWaitingForPIN;
  89. CancelActiveAuthenticators(authenticator->GetId());
  90. std::move(get_pin_callback_)
  91. .Run(authenticator->CurrentMinPINLength(),
  92. authenticator->NewMinPINLength(), absl::nullopt);
  93. break;
  94. }
  95. }
  96. void SetPINRequestHandler::OnRetriesResponse(
  97. CtapDeviceResponseCode status,
  98. absl::optional<pin::RetriesResponse> response) {
  99. DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
  100. DCHECK_EQ(state_, State::kGettingRetries);
  101. if (status != CtapDeviceResponseCode::kSuccess) {
  102. state_ = State::kFinished;
  103. finished_callback_.Run(status);
  104. return;
  105. }
  106. state_ = State::kWaitingForPIN;
  107. std::move(get_pin_callback_)
  108. .Run(authenticator_->CurrentMinPINLength(),
  109. authenticator_->NewMinPINLength(), response->retries);
  110. }
  111. void SetPINRequestHandler::OnSetPINComplete(
  112. CtapDeviceResponseCode status,
  113. absl::optional<pin::EmptyResponse> response) {
  114. DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
  115. DCHECK_EQ(state_, State::kSettingPIN);
  116. if (status == CtapDeviceResponseCode::kCtap2ErrPinInvalid) {
  117. // The caller may try again.
  118. state_ = State::kWaitingForPIN;
  119. } else {
  120. state_ = State::kFinished;
  121. }
  122. finished_callback_.Run(status);
  123. }
  124. } // namespace device