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