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 
5 #ifndef DEVICE_FIDO_GET_ASSERTION_REQUEST_HANDLER_H_
6 #define DEVICE_FIDO_GET_ASSERTION_REQUEST_HANDLER_H_
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "base/callback.h"
13 #include "base/macros.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/optional.h"
16 #include "device/fido/authenticator_get_assertion_response.h"
17 #include "device/fido/ctap_get_assertion_request.h"
18 #include "device/fido/fido_constants.h"
19 #include "device/fido/fido_request_handler_base.h"
20 #include "device/fido/fido_transport_protocol.h"
21 
22 namespace device {
23 
24 class FidoAuthenticator;
25 class FidoDiscoveryFactory;
26 
27 namespace pin {
28 struct RetriesResponse;
29 class TokenResponse;
30 }  // namespace pin
31 
32 enum class GetAssertionStatus {
33   kSuccess,
34   kAuthenticatorResponseInvalid,
35   kUserConsentButCredentialNotRecognized,
36   kUserConsentDenied,
37   kAuthenticatorRemovedDuringPINEntry,
38   kSoftPINBlock,
39   kHardPINBlock,
40   kAuthenticatorMissingResidentKeys,
41   // TODO(agl): kAuthenticatorMissingUserVerification can
42   // also be returned when the authenticator supports UV, but
43   // there's no UI support for collecting a PIN. This could
44   // be clearer.
45   kAuthenticatorMissingUserVerification,
46   kWinNotAllowedError,
47 };
48 
COMPONENT_EXPORT(DEVICE_FIDO)49 class COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionRequestHandler
50     : public FidoRequestHandlerBase {
51  public:
52   using CompletionCallback = base::OnceCallback<void(
53       GetAssertionStatus,
54       base::Optional<std::vector<AuthenticatorGetAssertionResponse>>,
55       const FidoAuthenticator*)>;
56 
57   GetAssertionRequestHandler(
58       FidoDiscoveryFactory* fido_discovery_factory,
59       const base::flat_set<FidoTransportProtocol>& supported_transports,
60       CtapGetAssertionRequest request_parameter,
61       bool allow_skipping_pin_touch,
62       CompletionCallback completion_callback);
63   ~GetAssertionRequestHandler() override;
64 
65  private:
66   enum class State {
67     kWaitingForTouch,
68     kWaitingForSecondTouch,
69     kGettingRetries,
70     kWaitingForPIN,
71     kRequestWithPIN,
72     kReadingMultipleResponses,
73     kFinished,
74   };
75 
76   // FidoRequestHandlerBase:
77   void DispatchRequest(FidoAuthenticator* authenticator) override;
78   void AuthenticatorAdded(FidoDiscoveryBase* discovery,
79                           FidoAuthenticator* authenticator) override;
80   void AuthenticatorRemoved(FidoDiscoveryBase* discovery,
81                             FidoAuthenticator* authenticator) override;
82 
83   void HandleResponse(
84       FidoAuthenticator* authenticator,
85       CtapDeviceResponseCode response_code,
86       base::Optional<AuthenticatorGetAssertionResponse> response);
87   void HandleNextResponse(
88       FidoAuthenticator* authenticator,
89       CtapDeviceResponseCode response_code,
90       base::Optional<AuthenticatorGetAssertionResponse> response);
91   void CollectPINThenSendRequest(FidoAuthenticator* authenticator);
92   void StartPINFallbackForInternalUv(FidoAuthenticator* authenticator);
93   void TerminateUnsatisfiableRequestPostTouch(FidoAuthenticator* authenticator);
94   void OnPinRetriesResponse(CtapDeviceResponseCode status,
95                             base::Optional<pin::RetriesResponse> response);
96   void OnHavePIN(std::string pin);
97   void OnHavePINToken(CtapDeviceResponseCode status,
98                       base::Optional<pin::TokenResponse> response);
99   void OnUvRetriesResponse(CtapDeviceResponseCode status,
100                            base::Optional<pin::RetriesResponse> response);
101   void OnHaveUvToken(FidoAuthenticator* authenticator,
102                      CtapDeviceResponseCode status,
103                      base::Optional<pin::TokenResponse> response);
104   void DispatchRequestWithToken(pin::TokenResponse token);
105 
106   CompletionCallback completion_callback_;
107   State state_ = State::kWaitingForTouch;
108   CtapGetAssertionRequest request_;
109   base::Optional<AndroidClientDataExtensionInput> android_client_data_ext_;
110   // If true, and if at the time the request is dispatched to the first
111   // authenticator no other authenticators are available, the request handler
112   // will skip the initial touch that is usually required to select a PIN
113   // protected authenticator.
114   bool allow_skipping_pin_touch_;
115   // authenticator_ points to the authenticator that will be used for this
116   // operation. It's only set after the user touches an authenticator to select
117   // it, after which point that authenticator will be used exclusively through
118   // requesting PIN etc. The object is owned by the underlying discovery object
119   // and this pointer is cleared if it's removed during processing.
120   FidoAuthenticator* authenticator_ = nullptr;
121   // responses_ holds the set of responses while they are incrementally read
122   // from the device. Only used when more than one response is returned.
123   std::vector<AuthenticatorGetAssertionResponse> responses_;
124   // remaining_responses_ contains the number of responses that remain to be
125   // read when multiple responses are returned.
126   size_t remaining_responses_ = 0;
127   SEQUENCE_CHECKER(my_sequence_checker_);
128   base::WeakPtrFactory<GetAssertionRequestHandler> weak_factory_{this};
129 
130   DISALLOW_COPY_AND_ASSIGN(GetAssertionRequestHandler);
131 };
132 
133 }  // namespace device
134 
135 #endif  // DEVICE_FIDO_GET_ASSERTION_REQUEST_HANDLER_H_
136