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
content / browser / webauth / virtual_authenticator.h [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_WEBAUTH_VIRTUAL_AUTHENTICATOR_H_
#define CONTENT_BROWSER_WEBAUTH_VIRTUAL_AUTHENTICATOR_H_
#include <memory>
#include <string>
#include <vector>
#include "base/containers/span.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "content/common/content_export.h"
#include "device/fido/virtual_fido_device.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
namespace content {
// Implements a stateful virtual authenticator.
//
// This class has very little logic itself, it merely stores a unique ID and the
// state of the authenticator, whereas performing all cryptographic operations
// is delegated to the VirtualFidoDevice class.
class CONTENT_EXPORT VirtualAuthenticator
: public device::VirtualFidoDevice::Observer {
public:
class Observer : public base::CheckedObserver {
public:
virtual void OnCredentialCreated(
VirtualAuthenticator* authenticator,
const device::VirtualFidoDevice::Credential& credential) = 0;
virtual void OnCredentialDeleted(
VirtualAuthenticator* authenticator,
base::span<const uint8_t> credential_id) = 0;
virtual void OnCredentialUpdated(
VirtualAuthenticator* authenticator,
const device::VirtualFidoDevice::Credential& credential) = 0;
virtual void OnAssertion(
VirtualAuthenticator* authenticator,
const device::VirtualFidoDevice::Credential& credential) = 0;
virtual void OnAuthenticatorWillBeDestroyed(
VirtualAuthenticator* authenticator) = 0;
};
// Attributes that the virtual authenticator should simulate.
struct CONTENT_EXPORT Options {
Options();
~Options();
// protocol is the client-to-authenticator protocol that the virtual
// authenticator simulates.
device::ProtocolVersion protocol = device::ProtocolVersion::kCtap2;
// ctap2_version indicates which minor version of CTAP2 the authenticator
// should simulate if |protocol| is CTAP2. It is ignored otherwise.
device::Ctap2Version ctap2_version = device::Ctap2Version::kCtap2_0;
device::FidoTransportProtocol transport =
device::FidoTransportProtocol::kUsbHumanInterfaceDevice;
device::AuthenticatorAttachment attachment =
device::AuthenticatorAttachment::kCrossPlatform;
bool has_resident_key = false;
bool has_user_verification = false;
bool is_user_present = true;
bool has_large_blob = false;
bool has_cred_blob = false;
bool has_min_pin_length = false;
bool has_prf = false;
bool default_backup_eligibility = false;
bool default_backup_state = false;
};
using GetLargeBlobCallback =
base::OnceCallback<void(std::optional<std::vector<uint8_t>>)>;
using SetLargeBlobCallback = base::OnceCallback<void(bool)>;
explicit VirtualAuthenticator(const Options& options);
VirtualAuthenticator(const VirtualAuthenticator&) = delete;
VirtualAuthenticator& operator=(const VirtualAuthenticator&) = delete;
~VirtualAuthenticator() override;
device::VirtualFidoDevice::State::RegistrationsMap& registrations() const {
return state_->registrations;
}
// Register a new credential. Returns true if the registration was successful,
// false otherwise.
bool AddRegistration(std::vector<uint8_t> key_handle,
const std::string& rp_id,
base::span<const uint8_t> private_key,
int32_t counter);
// Register a new resident credential. Returns true if the registration was
// successful, false otherwise.
bool AddResidentRegistration(std::vector<uint8_t> key_handle,
std::string rp_id,
base::span<const uint8_t> private_key,
int32_t counter,
std::vector<uint8_t> user_handle,
std::optional<std::string> user_name,
std::optional<std::string> user_display_name);
// Removes all the credentials.
void ClearRegistrations();
// Remove a credential identified by |key_handle|. Returns true if the
// credential was found and removed, false otherwise.
bool RemoveRegistration(const std::vector<uint8_t>& key_handle);
// Updates the name and display name of registrations matching
// |relying_party_id| and |user_id|.
void UpdateUserDetails(std::string_view relying_party_id,
base::span<const uint8_t> user_id,
std::string_view name,
std::string_view display_name);
// Sets whether tests of user presence succeed or not for new requests sent to
// this authenticator. The default is true.
void SetUserPresence(bool is_user_present);
// Sets whether user verification should succeed or not for new requests sent
// to this authenticator. Defaults to true.
void set_user_verified(bool is_user_verified) {
is_user_verified_ = is_user_verified;
}
// If set, overrides the signature in the authenticator response to be zero.
// Defaults to false.
void set_bogus_signature(bool is_bogus) {
state_->ctap2_invalid_signature = is_bogus;
}
// If set, overrides the UV bit in the flags in the authenticator response to
// be zero. Defaults to false.
void set_bad_uv_bit(bool is_bad_bit) { state_->unset_uv_bit = is_bad_bit; }
// If set, overrides the UP bit in the flags in the authenticator response to
// be zero. Defaults to false.
void set_bad_up_bit(bool is_bad_bit) { state_->unset_up_bit = is_bad_bit; }
bool has_resident_key() const { return has_resident_key_; }
device::FidoTransportProtocol transport() const { return state_->transport; }
const std::string& unique_id() const { return unique_id_; }
bool is_user_verifying_platform_authenticator() const {
return attachment_ == device::AuthenticatorAttachment::kPlatform &&
has_user_verification_;
}
// Constructs a VirtualFidoDevice instance that will perform cryptographic
// operations on behalf of, and using the state stored in this virtual
// authenticator.
//
// There is an N:1 relationship between VirtualFidoDevices and this class, so
// this method can be called any number of times.
std::unique_ptr<device::VirtualFidoDevice> ConstructDevice();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
bool HasObserversForTest();
// Set the BE flag for a given |key_handle|. |key_handle| must match a
// credential.
void SetBackupEligibility(const std::vector<uint8_t>& key_handle,
bool backup_eligibility);
// Set the BS flag for a given |key_handle|. |key_handle| must match a
// credential.
void SetBackupState(const std::vector<uint8_t>& key_handle,
bool backup_state);
void GetLargeBlob(const std::vector<uint8_t>& key_handle,
GetLargeBlobCallback callback);
void SetLargeBlob(const std::vector<uint8_t>& key_handle,
const std::vector<uint8_t>& blob,
SetLargeBlobCallback callback);
private:
void OnLargeBlobUncompressed(
GetLargeBlobCallback callback,
base::expected<mojo_base::BigBuffer, std::string> result);
void OnLargeBlobCompressed(
base::span<const uint8_t> key_handle,
uint64_t original_size,
SetLargeBlobCallback callback,
base::expected<mojo_base::BigBuffer, std::string> result);
// device::VirtualFidoDevice::Observer:
void OnCredentialCreated(
const device::VirtualFidoDevice::Credential& credential) override;
void OnCredentialDeleted(base::span<const uint8_t> credential_id) override;
void OnCredentialUpdated(
const device::VirtualFidoDevice::Credential& credential) override;
void OnAssertion(
const device::VirtualFidoDevice::Credential& credential) override;
const device::ProtocolVersion protocol_;
const device::Ctap2Version ctap2_version_;
const device::AuthenticatorAttachment attachment_;
const bool has_resident_key_;
const bool has_user_verification_;
const bool has_large_blob_;
const bool has_cred_blob_;
const bool has_min_pin_length_;
const bool has_prf_;
bool is_user_verified_ = true;
const std::string unique_id_;
bool is_user_present_;
base::ObserverList<Observer> observers_;
data_decoder::DataDecoder data_decoder_;
scoped_refptr<device::VirtualFidoDevice::State> state_;
base::ScopedObservation<device::VirtualFidoDevice::State,
device::VirtualFidoDevice::Observer>
observation_{this};
base::WeakPtrFactory<VirtualAuthenticator> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WEBAUTH_VIRTUAL_AUTHENTICATOR_H_