fido_request_handler_base.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // Copyright 2018 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. #ifndef DEVICE_FIDO_FIDO_REQUEST_HANDLER_BASE_H_
  5. #define DEVICE_FIDO_FIDO_REQUEST_HANDLER_BASE_H_
  6. #include <array>
  7. #include <functional>
  8. #include <map>
  9. #include <memory>
  10. #include <set>
  11. #include <string>
  12. #include <vector>
  13. #include "base/callback.h"
  14. #include "base/check.h"
  15. #include "base/component_export.h"
  16. #include "base/containers/flat_set.h"
  17. #include "base/memory/raw_ptr.h"
  18. #include "base/memory/weak_ptr.h"
  19. #include "base/strings/string_piece_forward.h"
  20. #include "build/build_config.h"
  21. #include "device/fido/fido_constants.h"
  22. #include "device/fido/fido_discovery_base.h"
  23. #include "device/fido/fido_transport_protocol.h"
  24. #include "device/fido/pin.h"
  25. #include "third_party/abseil-cpp/absl/types/optional.h"
  26. namespace device {
  27. class BleAdapterManager;
  28. class FidoAuthenticator;
  29. class FidoDiscoveryFactory;
  30. class DiscoverableCredentialMetadata;
  31. struct TransportAvailabilityCallbackReadiness;
  32. // Base class that handles authenticator discovery/removal. Its lifetime is
  33. // equivalent to that of a single WebAuthn request. For each authenticator, the
  34. // per-device work is carried out by one FidoAuthenticator instance, which is
  35. // constructed in a FidoDiscoveryBase and passed to the request handler via its
  36. // Observer interface.
  37. class COMPONENT_EXPORT(DEVICE_FIDO) FidoRequestHandlerBase
  38. : public FidoDiscoveryBase::Observer {
  39. public:
  40. using RequestCallback = base::RepeatingCallback<void(const std::string&)>;
  41. using AuthenticatorMap =
  42. std::map<std::string, FidoAuthenticator*, std::less<>>;
  43. enum class RecognizedCredential {
  44. kUnknown,
  45. kHasRecognizedCredential,
  46. kNoRecognizedCredential
  47. };
  48. // Encapsulates data required to initiate WebAuthN UX dialog. Once all
  49. // components of TransportAvailabilityInfo is set,
  50. // AuthenticatorRequestClientDelegate should be notified.
  51. struct COMPONENT_EXPORT(DEVICE_FIDO) TransportAvailabilityInfo {
  52. TransportAvailabilityInfo();
  53. TransportAvailabilityInfo(const TransportAvailabilityInfo& other);
  54. TransportAvailabilityInfo& operator=(
  55. const TransportAvailabilityInfo& other);
  56. ~TransportAvailabilityInfo();
  57. FidoRequestType request_type = FidoRequestType::kMakeCredential;
  58. // Indicates whether this is a GetAssertion request with an empty allow
  59. // list.
  60. bool has_empty_allow_list = false;
  61. // The intersection of transports supported by the client and allowed by the
  62. // relying party.
  63. base::flat_set<FidoTransportProtocol> available_transports;
  64. // Whether the platform authenticator has a matching credential for the
  65. // request. This is only set for a GetAssertion request.
  66. RecognizedCredential has_platform_authenticator_credential =
  67. RecognizedCredential::kUnknown;
  68. // The set of recognized platform credential user entities that can fulfill
  69. // a GetAssertion request. Not all platform authenticators report this, so
  70. // the set might be empty even if
  71. // |has_platform_authenticator_credential| is |kHasRecognizedCredential|.
  72. std::vector<DiscoverableCredentialMetadata>
  73. recognized_platform_authenticator_credentials;
  74. bool is_ble_powered = false;
  75. bool can_power_on_ble_adapter = false;
  76. // ble_access_denied is set to true if Chromium does not have permission
  77. // to use the BLE adaptor. Resolving this is a platform-specific operation.
  78. bool ble_access_denied = false;
  79. // Indicates whether the native Windows WebAuthn API is available.
  80. // Dispatching to it should be controlled by the embedder.
  81. //
  82. // The embedder:
  83. // - may choose not to dispatch immediately if caBLE is available
  84. // - should dispatch immediately if no other transport is available
  85. bool has_win_native_api_authenticator = false;
  86. // Indicates whether the Windows native UI will include a privacy notice
  87. // when creating a resident credential.
  88. bool win_native_ui_shows_resident_credential_notice = false;
  89. // Contains the authenticator ID of the native Windows
  90. // authenticator if |has_win_native_api_authenticator| is true.
  91. // This allows the observer to distinguish it from other
  92. // authenticators.
  93. std::string win_native_api_authenticator_id;
  94. // Indicates whether the request is occurring in an off-the-record
  95. // BrowserContext (e.g. Chrome Incognito mode).
  96. bool is_off_the_record_context = false;
  97. // Indicates the ResidentKeyRequirement of the current request. Only valid
  98. // if |request_type| is |RequestType::kMakeCredential|. Requests with a
  99. // value of |ResidentKeyRequirement::kPreferred| or
  100. // |ResidentKeyRequirement::kRequired| can create a resident credential,
  101. // which could be discovered by someone with physical access to the
  102. // authenticator and thus have privacy implications.
  103. ResidentKeyRequirement resident_key_requirement =
  104. ResidentKeyRequirement::kDiscouraged;
  105. };
  106. class COMPONENT_EXPORT(DEVICE_FIDO) Observer {
  107. public:
  108. struct COMPONENT_EXPORT(DEVICE_FIDO) CollectPINOptions {
  109. // Why this PIN is being collected.
  110. pin::PINEntryReason reason;
  111. // The error for which we are prompting for a PIN.
  112. pin::PINEntryError error = pin::PINEntryError::kNoError;
  113. // The minimum PIN length the authenticator will accept for the PIN.
  114. uint32_t min_pin_length = device::kMinPinLength;
  115. // The number of attempts remaining before a hard lock. Should be ignored
  116. // unless |mode| is kChallenge.
  117. int attempts = 0;
  118. };
  119. virtual ~Observer();
  120. // This method will not be invoked until the observer is set.
  121. virtual void OnTransportAvailabilityEnumerated(
  122. TransportAvailabilityInfo data) = 0;
  123. // If true, the request handler will defer dispatch of its request onto the
  124. // given authenticator to the embedder. The embedder needs to call
  125. // |StartAuthenticatorRequest| when it wants to initiate request dispatch.
  126. //
  127. // This method is invoked before |FidoAuthenticatorAdded|, and may be
  128. // invoked multiple times for the same authenticator. Depending on the
  129. // result, the request handler might decide not to make the authenticator
  130. // available, in which case it never gets passed to
  131. // |FidoAuthenticatorAdded|.
  132. virtual bool EmbedderControlsAuthenticatorDispatch(
  133. const FidoAuthenticator& authenticator) = 0;
  134. virtual void BluetoothAdapterPowerChanged(bool is_powered_on) = 0;
  135. virtual void FidoAuthenticatorAdded(
  136. const FidoAuthenticator& authenticator) = 0;
  137. virtual void FidoAuthenticatorRemoved(base::StringPiece device_id) = 0;
  138. // SupportsPIN returns true if this observer supports collecting a PIN from
  139. // the user. If this function returns false, |CollectPIN| and
  140. // |FinishCollectPIN| will not be called.
  141. virtual bool SupportsPIN() const = 0;
  142. // CollectPIN is called when a PIN is needed to complete a request. The
  143. // |attempts| parameter is either |nullopt| to indicate that the user needs
  144. // to set a PIN, or contains the number of PIN attempts remaining before a
  145. // hard lock.
  146. virtual void CollectPIN(
  147. CollectPINOptions options,
  148. base::OnceCallback<void(std::u16string)> provide_pin_cb) = 0;
  149. virtual void FinishCollectToken() = 0;
  150. // Called when a biometric enrollment may be completed as part of the
  151. // request and the user should be notified to collect samples.
  152. // |next_callback| must be executed asynchronously at any time to move on to
  153. // the next step of the request.
  154. virtual void StartBioEnrollment(base::OnceClosure next_callback) = 0;
  155. // Called when a biometric enrollment sample has been collected.
  156. // |bio_samples_remaining| is the number of samples needed to finish the
  157. // enrollment.
  158. virtual void OnSampleCollected(int bio_samples_remaining) = 0;
  159. // Called when an authenticator reports internal user verification has
  160. // failed (e.g. not recognising the user's fingerprints) and the user should
  161. // try again. Receives the number of |attempts| before the device locks
  162. // internal user verification.
  163. virtual void OnRetryUserVerification(int attempts) = 0;
  164. };
  165. // ScopedAlwaysAllowBLECalls allows BLE API calls to always be made, even if
  166. // they would be disabled on macOS because Chromium was not launched with
  167. // self-responsibility.
  168. class COMPONENT_EXPORT(DEVICE_FIDO) ScopedAlwaysAllowBLECalls {
  169. public:
  170. ScopedAlwaysAllowBLECalls();
  171. ~ScopedAlwaysAllowBLECalls();
  172. };
  173. FidoRequestHandlerBase();
  174. // The |available_transports| should be the intersection of transports
  175. // supported by the client and allowed by the relying party.
  176. FidoRequestHandlerBase(
  177. FidoDiscoveryFactory* fido_discovery_factory,
  178. const base::flat_set<FidoTransportProtocol>& available_transports);
  179. FidoRequestHandlerBase(const FidoRequestHandlerBase&) = delete;
  180. FidoRequestHandlerBase& operator=(const FidoRequestHandlerBase&) = delete;
  181. ~FidoRequestHandlerBase() override;
  182. // Triggers DispatchRequest() if |active_authenticators_| hold
  183. // FidoAuthenticator with given |authenticator_id|.
  184. void StartAuthenticatorRequest(const std::string& authenticator_id);
  185. // Invokes |FidoAuthenticator::Cancel| on all authenticators, except if
  186. // matching |exclude_id|, if one is provided. Cancelled authenticators are
  187. // immediately removed from |active_authenticators_|.
  188. //
  189. // This function is invoked either when: (a) the entire WebAuthn API request
  190. // is canceled or, (b) a successful response or "invalid state error" is
  191. // received from the any one of the connected authenticators, in which case
  192. // all other authenticators are cancelled.
  193. // https://w3c.github.io/webauthn/#iface-pkcredential
  194. void CancelActiveAuthenticators(base::StringPiece exclude_id = "");
  195. virtual void OnBluetoothAdapterEnumerated(bool is_present,
  196. bool is_powered_on,
  197. bool can_power_on,
  198. bool is_peripheral_role_supported);
  199. void OnBluetoothAdapterPowerChanged(bool is_powered_on);
  200. void PowerOnBluetoothAdapter();
  201. base::WeakPtr<FidoRequestHandlerBase> GetWeakPtr();
  202. void set_observer(Observer* observer);
  203. // Returns whether FidoAuthenticator with id equal to |authenticator_id|
  204. // exists. Fake FidoRequestHandler objects used in testing overrides this
  205. // function to simulate scenarios where authenticator with |authenticator_id|
  206. // is known to the system.
  207. virtual bool HasAuthenticator(const std::string& authentiator_id) const;
  208. TransportAvailabilityInfo& transport_availability_info() {
  209. return transport_availability_info_;
  210. }
  211. const AuthenticatorMap& AuthenticatorsForTesting() {
  212. return active_authenticators_;
  213. }
  214. std::unique_ptr<BleAdapterManager>&
  215. get_bluetooth_adapter_manager_for_testing() {
  216. return bluetooth_adapter_manager_;
  217. }
  218. void StopDiscoveries();
  219. protected:
  220. // Authenticators that return a response in less than this time are likely to
  221. // have done so without interaction from the user.
  222. static constexpr base::TimeDelta kMinExpectedAuthenticatorResponseTime =
  223. base::Milliseconds(300);
  224. // Subclasses implement this method to dispatch their request onto the given
  225. // FidoAuthenticator. The FidoAuthenticator is owned by this
  226. // FidoRequestHandler and stored in active_authenticators().
  227. virtual void DispatchRequest(FidoAuthenticator*) = 0;
  228. void InitDiscoveries(
  229. FidoDiscoveryFactory* fido_discovery_factory,
  230. base::flat_set<FidoTransportProtocol> available_transports);
  231. void Start();
  232. AuthenticatorMap& active_authenticators() { return active_authenticators_; }
  233. std::vector<std::unique_ptr<FidoDiscoveryBase>>& discoveries() {
  234. return discoveries_;
  235. }
  236. Observer* observer() const { return observer_; }
  237. // FidoDiscoveryBase::Observer
  238. void DiscoveryStarted(
  239. FidoDiscoveryBase* discovery,
  240. bool success,
  241. std::vector<FidoAuthenticator*> authenticators) override;
  242. void AuthenticatorAdded(FidoDiscoveryBase* discovery,
  243. FidoAuthenticator* authenticator) override;
  244. void AuthenticatorRemoved(FidoDiscoveryBase* discovery,
  245. FidoAuthenticator* authenticator) override;
  246. void BleDenied() override;
  247. // GetPlatformCredentialStatus is called to learn whether a platform
  248. // authenticator has credentials responsive to the current request. If this
  249. // method is overridden in a subclass then either:
  250. // · The method in this base class must be called immediately, or
  251. // · |OnHavePlatformCredentialStatus| must eventually called.
  252. //
  253. // This method runs only after the platform discovery has started
  254. // successfully. (The Windows API doesn't count as a platform authenticator
  255. // for the purposes of this call.)
  256. virtual void GetPlatformCredentialStatus(
  257. FidoAuthenticator* platform_authenticator);
  258. // OnHavePlatformCredentialStatus is called by subclasses (after
  259. // |GetPlatformCredentialStatus| has been called) to report on whether the
  260. // platform authenticator whether it has responsive discoverable credentials
  261. // and whether it has responsive credentials at all.
  262. void OnHavePlatformCredentialStatus(
  263. std::vector<DiscoverableCredentialMetadata> user_entities,
  264. bool have_credential);
  265. private:
  266. friend class FidoRequestHandlerTest;
  267. void MaybeSignalTransportsEnumerated();
  268. // Invokes FidoAuthenticator::InitializeAuthenticator(), followed by
  269. // DispatchRequest(). InitializeAuthenticator() sends a GetInfo command
  270. // to FidoDeviceAuthenticator instances in order to determine their protocol
  271. // versions before a request can be dispatched.
  272. void InitializeAuthenticatorAndDispatchRequest(
  273. const std::string& authenticator_id);
  274. void ConstructBleAdapterPowerManager();
  275. AuthenticatorMap active_authenticators_;
  276. std::vector<std::unique_ptr<FidoDiscoveryBase>> discoveries_;
  277. raw_ptr<Observer> observer_ = nullptr;
  278. TransportAvailabilityInfo transport_availability_info_;
  279. std::unique_ptr<BleAdapterManager> bluetooth_adapter_manager_;
  280. // transport_availability_callback_readiness_ keeps track of state which
  281. // determines whether this object is ready to call
  282. // |OnTransportAvailabilityEnumerated| on |observer_|.
  283. std::unique_ptr<TransportAvailabilityCallbackReadiness>
  284. transport_availability_callback_readiness_;
  285. // internal_authenticator_found_ is used to check that at most one kInternal
  286. // authenticator is discovered.
  287. bool internal_authenticator_found_ = false;
  288. base::WeakPtrFactory<FidoRequestHandlerBase> weak_factory_{this};
  289. };
  290. } // namespace device
  291. #endif // DEVICE_FIDO_FIDO_REQUEST_HANDLER_BASE_H_