-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebauthn_handler.h
278 lines (223 loc) · 11 KB
/
webauthn_handler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef U2FD_WEBAUTHN_HANDLER_H_
#define U2FD_WEBAUTHN_HANDLER_H_
#include <functional>
#include <memory>
#include <optional>
#include <queue>
#include <string>
#include <vector>
#include <brillo/dbus/dbus_method_response.h>
#include <cryptohome/proto_bindings/UserDataAuth.pb.h>
#include <cryptohome/proto_bindings/rpc.pb.h>
#include <metrics/metrics_library.h>
#include <u2f/proto_bindings/u2f_interface.pb.h>
#include <user_data_auth-client/user_data_auth/dbus-proxies.h>
#include "u2fd/allowlisting_util.h"
#include "u2fd/client/user_state.h"
#include "u2fd/u2f_mode.h"
#include "u2fd/webauthn_storage.h"
namespace u2f {
class U2fCommandProcessor;
using MakeCredentialMethodResponse =
brillo::dbus_utils::DBusMethodResponse<MakeCredentialResponse>;
using GetAssertionMethodResponse =
brillo::dbus_utils::DBusMethodResponse<GetAssertionResponse>;
using IsUvpaaMethodResponse =
brillo::dbus_utils::DBusMethodResponse<IsUvpaaResponse>;
using ::google::protobuf::RepeatedPtrField;
struct MakeCredentialSession {
bool empty() { return !response; }
uint64_t session_id;
MakeCredentialRequest request;
std::unique_ptr<MakeCredentialMethodResponse> response;
bool canceled = false;
};
struct GetAssertionSession {
bool empty() { return !response; }
uint64_t session_id;
GetAssertionRequest request;
// The credential_id to send to the TPM. May be a resident credential.
std::string credential_id;
std::unique_ptr<GetAssertionMethodResponse> response;
bool canceled = false;
};
struct MatchedCredentials {
std::vector<std::string> platform_credentials;
std::vector<std::string> legacy_credentials_for_rp_id;
std::vector<std::string> legacy_credentials_for_app_id;
bool has_internal_error = false;
};
enum class PresenceRequirement {
kNone, // Does not require presence. Used only after user-verification in
// MakeCredential.
kPowerButton, // Requires a power button press as indication of presence.
kFingerprint, // Requires the GPIO line from fingerprint MCU to be active.
kAuthorizationSecret, // Requires the correct authorization secret.
};
// COSE algorithm ID
// https://www.iana.org/assignments/cose/cose.xhtml#algorithms
enum class CoseAlgorithmIdentifier : int32_t {
kEs256 = -7,
kRs256 = -257,
};
// Implementation of the WebAuthn DBus API.
// More detailed documentation is available in u2f_interface.proto
class WebAuthnHandler {
public:
WebAuthnHandler();
~WebAuthnHandler();
// Initializes WebAuthnHandler.
// |bus| - DBus pointer.
// |user_state| - pointer to a UserState instance, for requesting user secret.
// Owned by U2fDaemon and should outlive WebAuthnHandler.
// |u2f_mode| - whether u2f or g2f is enabled.
// |u2f_command_processor| - processor for executing u2f commands.
// |allowlisting_util| - utility to append allowlisting data to g2f certs.
// |metrics| pointer to metrics library object.
void Initialize(dbus::Bus* bus,
UserState* user_state,
U2fMode u2f_mode,
std::unique_ptr<U2fCommandProcessor> u2f_command_processor,
std::unique_ptr<AllowlistingUtil> allowlisting_util,
MetricsLibraryInterface* metrics);
// Called when session state changed. Loads/clears state for primary user.
void OnSessionStarted(const std::string& account_id);
void OnSessionStopped();
// Generates a new credential.
void MakeCredential(
std::unique_ptr<MakeCredentialMethodResponse> method_response,
const MakeCredentialRequest& request);
// Signs a challenge from the relaying party.
void GetAssertion(std::unique_ptr<GetAssertionMethodResponse> method_response,
const GetAssertionRequest& request);
// Tests validity and/or presence of specified credentials, including u2fhid
// credentials.
HasCredentialsResponse HasCredentials(const HasCredentialsRequest& request);
// Tests whether any credential were registered using the u2fhid (on either
// WebAuthn API or U2F API).
HasCredentialsResponse HasLegacyCredentials(
const HasCredentialsRequest& request);
// Dismisses user verification UI and abort the operation. This is expected to
// be called by the browser only in UV operations, because UP operations
// themselves will timeout after ~5 seconds.
CancelWebAuthnFlowResponse Cancel(const CancelWebAuthnFlowRequest& request);
// Checks whether the platform authenticator is initialized. Before
// initialized, most operations will directly return an error.
IsPlatformAuthenticatorInitializedResponse IsPlatformAuthenticatorInitialized(
const IsPlatformAuthenticatorInitializedRequest& request);
// Checks whether user-verifying platform authenticator is available.
void IsUvpaa(std::unique_ptr<IsUvpaaMethodResponse> method_response,
const IsUvpaaRequest& request);
// Checks whether u2f is enabled (therefore power button mode is supported).
IsU2fEnabledResponse IsU2fEnabled(const IsU2fEnabledRequest& request);
// Count how many WebAuthn platform credentials are created within the
// specified time range.
CountCredentialsInTimeRangeResponse CountCredentialsInTimeRange(
const CountCredentialsInTimeRangeRequest& request);
// Delete all WebAuthn platform credentials created within the specified time
// range.
DeleteCredentialsInTimeRangeResponse DeleteCredentialsInTimeRange(
const DeleteCredentialsInTimeRangeRequest& request);
// Get the supported algorithms of the platform authenticator. Currently we
// have no plan to support multiple algorithms on one platform so the response
// will only contain one entry.
GetAlgorithmsResponse GetAlgorithms(const GetAlgorithmsRequest& request);
// Get the supported features of u2fd. currently it only contains whether
// WebAuthn is enabled on Lacros. This is equivalent to whether the request_id
// field in WebAuthn requests has changed to str type currently, which is
// always true.
GetSupportedFeaturesResponse GetSupportedFeatures(
const GetSupportedFeaturesRequest& request);
void SetWebAuthnStorageForTesting(std::unique_ptr<WebAuthnStorage> storage);
void SetCryptohomeInterfaceProxyForTesting(
std::unique_ptr<org::chromium::UserDataAuthInterfaceProxyInterface>
cryptohome_proxy);
private:
friend class WebAuthnHandlerTestBase;
friend class WebAuthnHandlerTestAllowUP;
bool Initialized();
// Fetches auth-time WebAuthn secret and keep the hash of it.
void GetWebAuthnSecretHashAsync(const std::string& account_id);
void OnGetWebAuthnSecretHashResp(
const user_data_auth::GetWebAuthnSecretHashReply& reply);
void OnGetWebAuthnSecretHashCallFailed(brillo::Error* error);
// Callbacks invoked when UI completes user verification flow.
void HandleUVFlowResultMakeCredential(dbus::Response* flow_response);
void HandleUVFlowResultGetAssertion(dbus::Response* flow_response);
// Proceeds for the current MakeCredential request, and responds to the
// request with authenticator data. Called directly if the request is
// user-presence only. Called on user verification success if the request is
// user-verification.
void DoMakeCredential(struct MakeCredentialSession session,
PresenceRequirement presence_requirement);
// Find all matching credentials and return them in 3 categories (see struct
// MatchedCredentials definition). If a legacy credential matches both rp_id
// and app_id, it will only appear in "legacy_credentials_for_rp_id".
MatchedCredentials FindMatchedCredentials(
const RepeatedPtrField<std::string>& all_credentials,
const std::string& rp_id,
const std::string& app_id);
// Called on user verification success if the request is user-verification.
void DoGetAssertion(struct GetAssertionSession session,
PresenceRequirement presence_requirement);
// Creates and returns authenticator data. |include_attested_credential_data|
// should be set to true for MakeCredential, false for GetAssertion.
std::optional<std::vector<uint8_t>> MakeAuthenticatorData(
const std::vector<uint8_t>& rp_id_hash,
const std::vector<uint8_t>& credential_id,
const std::vector<uint8_t>& credential_public_key,
bool user_verified,
bool include_attested_credential_data,
bool is_u2f_authenticator_credential);
// Appends a none attestation to |response|. Only used in MakeCredential.
void AppendNoneAttestation(MakeCredentialResponse* response);
// Creates and returns an U2F attestation statement, or nullopt if attestation
// fails.
std::optional<std::vector<uint8_t>> MakeFidoU2fAttestationStatement(
const std::vector<uint8_t>& app_id,
const std::vector<uint8_t>& challenge,
const std::vector<uint8_t>& pub_key,
const std::vector<uint8_t>& key_handle,
const MakeCredentialRequest::AttestationConveyancePreference
attestation_conveyance_preference);
// Runs U2F_SIGN command with "check only" flag on each excluded credential
// id. Returns true if one of them belongs to this device.
HasCredentialsResponse::HasCredentialsStatus HasExcludedCredentials(
const MakeCredentialRequest& request);
// Checks whether the user with |account_id| has PIN set up.
bool HasPin(const std::string& account_id);
// Checks whether the user with |account_id| has fingerprint set up.
bool HasFingerprint(const std::string& account_id);
// Returns whether presence-only mode (power button mode) is allowed.
bool AllowPresenceMode();
UserState* user_state_ = nullptr;
dbus::Bus* bus_ = nullptr;
// Proxy to user authentication dialog in Ash. Used only in UV requests.
dbus::ObjectProxy* auth_dialog_dbus_proxy_ = nullptr;
std::unique_ptr<org::chromium::UserDataAuthInterfaceProxyInterface>
cryptohome_proxy_;
// Presence-only mode (power button mode) should only be allowed if u2f or
// g2f is enabled for the device (it's a per-device policy). The mode also
// determines the attestation to add to MakeCredential.
U2fMode u2f_mode_;
// Util to append allowlisting data to g2f certificates.
std::unique_ptr<AllowlistingUtil> allowlisting_util_;
// The MakeCredential session that's waiting on UI. There can only be one
// such session. UP sessions should not use this since there can be multiple.
std::optional<MakeCredentialSession> pending_uv_make_credential_session_;
// The GetAssertion session that's waiting on UI. There can only be one
// such session. UP sessions should not use this since there can be multiple.
std::optional<GetAssertionSession> pending_uv_get_assertion_session_;
// Hash of the per-user auth-time secret for WebAuthn.
std::unique_ptr<brillo::Blob> auth_time_secret_hash_;
// Storage for WebAuthn credential records.
std::unique_ptr<WebAuthnStorage> webauthn_storage_;
// Processor for u2f commands.
std::unique_ptr<U2fCommandProcessor> u2f_command_processor_;
MetricsLibraryInterface* metrics_;
};
} // namespace u2f
#endif // U2FD_WEBAUTHN_HANDLER_H_