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 #include "content/browser/webauth/virtual_authenticator.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/guid.h"
11 #include "crypto/ec_private_key.h"
12 #include "device/fido/fido_parsing_utils.h"
13 #include "device/fido/public_key_credential_rp_entity.h"
14 #include "device/fido/public_key_credential_user_entity.h"
15 #include "device/fido/virtual_ctap2_device.h"
16 #include "device/fido/virtual_u2f_device.h"
17 
18 namespace content {
19 
VirtualAuthenticator(::device::ProtocolVersion protocol,::device::FidoTransportProtocol transport,::device::AuthenticatorAttachment attachment,bool has_resident_key,bool has_user_verification)20 VirtualAuthenticator::VirtualAuthenticator(
21     ::device::ProtocolVersion protocol,
22     ::device::FidoTransportProtocol transport,
23     ::device::AuthenticatorAttachment attachment,
24     bool has_resident_key,
25     bool has_user_verification)
26     : protocol_(protocol),
27       attachment_(attachment),
28       has_resident_key_(has_resident_key),
29       has_user_verification_(has_user_verification),
30       unique_id_(base::GenerateGUID()),
31       state_(base::MakeRefCounted<::device::VirtualFidoDevice::State>()) {
32   state_->transport = transport;
33   // If the authenticator has user verification, simulate having set it up
34   // already.
35   state_->fingerprints_enrolled = has_user_verification_;
36   SetUserPresence(true);
37 }
38 
39 VirtualAuthenticator::~VirtualAuthenticator() = default;
40 
AddReceiver(mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticator> receiver)41 void VirtualAuthenticator::AddReceiver(
42     mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticator> receiver) {
43   receiver_set_.Add(this, std::move(receiver));
44 }
45 
AddRegistration(std::vector<uint8_t> key_handle,const std::string & rp_id,const std::vector<uint8_t> & private_key,int32_t counter)46 bool VirtualAuthenticator::AddRegistration(
47     std::vector<uint8_t> key_handle,
48     const std::string& rp_id,
49     const std::vector<uint8_t>& private_key,
50     int32_t counter) {
51   auto ec_private_key =
52       crypto::ECPrivateKey::CreateFromPrivateKeyInfo(private_key);
53   if (!ec_private_key)
54     return false;
55 
56   return state_->registrations
57       .emplace(
58           std::move(key_handle),
59           ::device::VirtualFidoDevice::RegistrationData(
60               std::move(ec_private_key),
61               ::device::fido_parsing_utils::CreateSHA256Hash(rp_id), counter))
62       .second;
63 }
64 
AddResidentRegistration(std::vector<uint8_t> key_handle,std::string rp_id,const std::vector<uint8_t> & private_key,int32_t counter,std::vector<uint8_t> user_handle)65 bool VirtualAuthenticator::AddResidentRegistration(
66     std::vector<uint8_t> key_handle,
67     std::string rp_id,
68     const std::vector<uint8_t>& private_key,
69     int32_t counter,
70     std::vector<uint8_t> user_handle) {
71   auto ec_private_key =
72       crypto::ECPrivateKey::CreateFromPrivateKeyInfo(private_key);
73   if (!ec_private_key)
74     return false;
75 
76   return state_->InjectResidentKey(
77       std::move(key_handle),
78       device::PublicKeyCredentialRpEntity(std::move(rp_id)),
79       device::PublicKeyCredentialUserEntity(std::move(user_handle)), counter,
80       std::move(ec_private_key));
81 }
82 
ClearRegistrations()83 void VirtualAuthenticator::ClearRegistrations() {
84   state_->registrations.clear();
85 }
86 
RemoveRegistration(const std::vector<uint8_t> & key_handle)87 bool VirtualAuthenticator::RemoveRegistration(
88     const std::vector<uint8_t>& key_handle) {
89   return state_->registrations.erase(key_handle) != 0;
90 }
91 
SetUserPresence(bool is_user_present)92 void VirtualAuthenticator::SetUserPresence(bool is_user_present) {
93   is_user_present_ = is_user_present;
94   state_->simulate_press_callback = base::BindRepeating(
95       [](bool is_user_present, device::VirtualFidoDevice* device) {
96         return is_user_present;
97       },
98       is_user_present);
99 }
100 
ConstructDevice()101 std::unique_ptr<::device::FidoDevice> VirtualAuthenticator::ConstructDevice() {
102   switch (protocol_) {
103     case ::device::ProtocolVersion::kU2f:
104       return std::make_unique<::device::VirtualU2fDevice>(state_);
105     case ::device::ProtocolVersion::kCtap2: {
106       device::VirtualCtap2Device::Config config;
107       config.resident_key_support = has_resident_key_;
108       config.internal_uv_support = has_user_verification_;
109       config.is_platform_authenticator =
110           attachment_ == ::device::AuthenticatorAttachment::kPlatform;
111       config.user_verification_succeeds = is_user_verified_;
112       return std::make_unique<::device::VirtualCtap2Device>(state_, config);
113     }
114     default:
115       NOTREACHED();
116       return std::make_unique<::device::VirtualU2fDevice>(state_);
117   }
118 }
119 
GetUniqueId(GetUniqueIdCallback callback)120 void VirtualAuthenticator::GetUniqueId(GetUniqueIdCallback callback) {
121   std::move(callback).Run(unique_id_);
122 }
123 
GetRegistrations(GetRegistrationsCallback callback)124 void VirtualAuthenticator::GetRegistrations(GetRegistrationsCallback callback) {
125   std::vector<blink::test::mojom::RegisteredKeyPtr> mojo_registered_keys;
126   for (const auto& registration : state_->registrations) {
127     auto mojo_registered_key = blink::test::mojom::RegisteredKey::New();
128     mojo_registered_key->key_handle = registration.first;
129     mojo_registered_key->counter = registration.second.counter;
130     mojo_registered_key->rp_id =
131         registration.second.rp ? registration.second.rp->id : "";
132     registration.second.private_key->ExportPrivateKey(
133         &mojo_registered_key->private_key);
134     mojo_registered_keys.push_back(std::move(mojo_registered_key));
135   }
136   std::move(callback).Run(std::move(mojo_registered_keys));
137 }
138 
AddRegistration(blink::test::mojom::RegisteredKeyPtr registration,AddRegistrationCallback callback)139 void VirtualAuthenticator::AddRegistration(
140     blink::test::mojom::RegisteredKeyPtr registration,
141     AddRegistrationCallback callback) {
142   std::move(callback).Run(AddRegistration(
143       std::move(registration->key_handle), std::move(registration->rp_id),
144       registration->private_key, registration->counter));
145 }
146 
ClearRegistrations(ClearRegistrationsCallback callback)147 void VirtualAuthenticator::ClearRegistrations(
148     ClearRegistrationsCallback callback) {
149   ClearRegistrations();
150   std::move(callback).Run();
151 }
152 
RemoveRegistration(const std::vector<uint8_t> & key_handle,RemoveRegistrationCallback callback)153 void VirtualAuthenticator::RemoveRegistration(
154     const std::vector<uint8_t>& key_handle,
155     RemoveRegistrationCallback callback) {
156   std::move(callback).Run(RemoveRegistration(std::move(key_handle)));
157 }
158 
SetUserVerified(bool verified,SetUserVerifiedCallback callback)159 void VirtualAuthenticator::SetUserVerified(bool verified,
160                                            SetUserVerifiedCallback callback) {
161   is_user_verified_ = verified;
162   std::move(callback).Run();
163 }
164 
165 }  // namespace content
166