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 
5 #ifndef DEVICE_FIDO_CREDENTIAL_MANAGEMENT_HANDLER_H_
6 #define DEVICE_FIDO_CREDENTIAL_MANAGEMENT_HANDLER_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/callback.h"
12 #include "base/component_export.h"
13 #include "base/containers/flat_set.h"
14 #include "base/macros.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/sequence_checker.h"
17 #include "device/fido/credential_management.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 #include "device/fido/pin.h"
22 
23 namespace device {
24 
25 class FidoAuthenticator;
26 class FidoDiscoveryFactory;
27 
28 enum class CredentialManagementStatus {
29   kSuccess,
30   kAuthenticatorResponseInvalid,
31   kSoftPINBlock,
32   kHardPINBlock,
33   kAuthenticatorMissingCredentialManagement,
34   kNoPINSet,
35 };
36 
37 // CredentialManagementHandler implements the authenticatorCredentialManagement
38 // protocol.
39 //
40 // Public methods on instances of this class may be called only after
41 // ReadyCallback has run, but not after FinishedCallback has run.
COMPONENT_EXPORT(DEVICE_FIDO)42 class COMPONENT_EXPORT(DEVICE_FIDO) CredentialManagementHandler
43     : public FidoRequestHandlerBase {
44  public:
45   using DeleteCredentialCallback =
46       base::OnceCallback<void(CtapDeviceResponseCode)>;
47   using FinishedCallback = base::OnceCallback<void(CredentialManagementStatus)>;
48   using GetCredentialsCallback = base::OnceCallback<void(
49       CtapDeviceResponseCode,
50       base::Optional<std::vector<AggregatedEnumerateCredentialsResponse>>,
51       base::Optional<size_t>)>;
52   using GetPINCallback =
53       base::RepeatingCallback<void(int64_t,
54                                    base::OnceCallback<void(std::string)>)>;
55   using ReadyCallback = base::OnceClosure;
56 
57   CredentialManagementHandler(
58       FidoDiscoveryFactory* fido_discovery_factory,
59       const base::flat_set<FidoTransportProtocol>& supported_transports,
60       ReadyCallback ready_callback,
61       GetPINCallback get_pin_callback,
62       FinishedCallback finished_callback);
63   ~CredentialManagementHandler() override;
64 
65   // GetCredentials invokes a series of commands to fetch all credentials stored
66   // on the device. The supplied callback receives the status returned by the
67   // device and, if successful, the resident credentials stored and remaining
68   // capacity left on the chosen authenticator.
69   //
70   // The returned AggregatedEnumerateCredentialsResponses will be sorted in
71   // ascending order by their RP ID. The |credentials| vector of each response
72   // will be sorted in ascending order by user name.
73   void GetCredentials(GetCredentialsCallback callback);
74 
75   // DeleteCredential attempts to delete the credential with the given
76   // |credential_id|.
77   void DeleteCredential(const PublicKeyCredentialDescriptor& credential_id,
78                         DeleteCredentialCallback callback);
79 
80   // DeleteCredentials deletes a list of credentials. Each entry in
81   // |credential_ids| must be a CBOR-serialized PublicKeyCredentialDescriptor.
82   // If any individual deletion fails, |callback| is invoked with the
83   // respective error, and deletion of the remaining credentials will be
84   // aborted (but others may have been deleted successfully already).
85   void DeleteCredentials(std::vector<std::vector<uint8_t>> credential_ids,
86                          DeleteCredentialCallback callback);
87 
88  private:
89   enum class State {
90     kWaitingForTouch,
91     kGettingRetries,
92     kWaitingForPIN,
93     kGettingPINToken,
94     kReady,
95     kGettingMetadata,
96     kGettingRP,
97     kGettingCredentials,
98     kFinished,
99   };
100 
101   // FidoRequestHandlerBase:
102   void DispatchRequest(FidoAuthenticator* authenticator) override;
103   void AuthenticatorRemoved(FidoDiscoveryBase* discovery,
104                             FidoAuthenticator* authenticator) override;
105 
106   void OnTouch(FidoAuthenticator* authenticator);
107   void OnRetriesResponse(CtapDeviceResponseCode status,
108                          base::Optional<pin::RetriesResponse> response);
109   void OnHavePIN(std::string pin);
110   void OnHavePINToken(CtapDeviceResponseCode status,
111                       base::Optional<pin::TokenResponse> response);
112   void OnCredentialsMetadata(
113       CtapDeviceResponseCode status,
114       base::Optional<CredentialsMetadataResponse> response);
115   void OnEnumerateCredentials(
116       CredentialsMetadataResponse metadata_response,
117       CtapDeviceResponseCode status,
118       base::Optional<std::vector<AggregatedEnumerateCredentialsResponse>>
119           responses);
120   void OnDeleteCredentials(
121       std::vector<std::vector<uint8_t>> remaining_credential_ids,
122       CredentialManagementHandler::DeleteCredentialCallback callback,
123       CtapDeviceResponseCode status,
124       base::Optional<DeleteCredentialResponse> response);
125 
126   SEQUENCE_CHECKER(sequence_checker_);
127 
128   State state_ = State::kWaitingForTouch;
129   FidoAuthenticator* authenticator_ = nullptr;
130   base::Optional<std::vector<uint8_t>> pin_token_;
131 
132   ReadyCallback ready_callback_;
133   GetPINCallback get_pin_callback_;
134   GetCredentialsCallback get_credentials_callback_;
135   FinishedCallback finished_callback_;
136 
137   base::WeakPtrFactory<CredentialManagementHandler> weak_factory_{this};
138 
139   DISALLOW_COPY_AND_ASSIGN(CredentialManagementHandler);
140 };
141 
142 }  // namespace device
143 
144 #endif  // DEVICE_FIDO_CREDENTIAL_MANAGEMENT_HANDLER_H_
145