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