1 // Copyright 2013 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 "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/files/file_util.h"
14 #include "base/location.h"
15 #include "base/logging.h"
16 #include "base/optional.h"
17 #include "base/path_service.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/stl_util.h"
20 #include "base/threading/thread_restrictions.h"
21 #include "base/threading/thread_task_runner_handle.h"
22 #include "chromeos/dbus/attestation/attestation.pb.h"
23 #include "chromeos/dbus/constants/dbus_paths.h"
24 #include "chromeos/dbus/cryptohome/account_identifier_operators.h"
25 #include "chromeos/dbus/cryptohome/key.pb.h"
26 #include "chromeos/dbus/cryptohome/rpc.pb.h"
27 #include "components/policy/proto/install_attributes.pb.h"
28 #include "third_party/cros_system_api/dbus/service_constants.h"
29 
30 namespace chromeos {
31 
32 namespace {
33 
34 // Interval to update the progress of MigrateToDircrypto in milliseconds.
35 constexpr int kDircryptoMigrationUpdateIntervalMs = 200;
36 // The number of updates the MigrateToDircrypto will send before it completes.
37 constexpr uint64_t kDircryptoMigrationMaxProgress = 15;
38 // Buffer size for reading install attributes file. 16k should be plenty. The
39 // file contains six attributes only (see InstallAttributes::LockDevice).
40 constexpr size_t kInstallAttributesFileMaxSize = 16384;
41 
42 // Used to track the fake instance, mirrors the instance in the base class.
43 FakeCryptohomeClient* g_instance = nullptr;
44 
45 }  // namespace
46 
47 // static
48 constexpr char FakeCryptohomeClient::kStubTpmPassword[] = "Stub-TPM-password";
49 
FakeCryptohomeClient()50 FakeCryptohomeClient::FakeCryptohomeClient() {
51   DCHECK(!g_instance);
52   g_instance = this;
53 
54   base::FilePath cache_path;
55   locked_ = base::PathService::Get(dbus_paths::FILE_INSTALL_ATTRIBUTES,
56                                    &cache_path) &&
57             base::PathExists(cache_path);
58   if (locked_)
59     LoadInstallAttributes();
60 }
61 
~FakeCryptohomeClient()62 FakeCryptohomeClient::~FakeCryptohomeClient() {
63   DCHECK_EQ(this, g_instance);
64   g_instance = nullptr;
65 }
66 
67 // static
Get()68 FakeCryptohomeClient* FakeCryptohomeClient::Get() {
69   return g_instance;
70 }
71 
AddObserver(Observer * observer)72 void FakeCryptohomeClient::AddObserver(Observer* observer) {
73   observer_list_.AddObserver(observer);
74 }
75 
RemoveObserver(Observer * observer)76 void FakeCryptohomeClient::RemoveObserver(Observer* observer) {
77   observer_list_.RemoveObserver(observer);
78 }
79 
WaitForServiceToBeAvailable(WaitForServiceToBeAvailableCallback callback)80 void FakeCryptohomeClient::WaitForServiceToBeAvailable(
81     WaitForServiceToBeAvailableCallback callback) {
82   if (service_is_available_ || service_reported_not_available_) {
83     base::ThreadTaskRunnerHandle::Get()->PostTask(
84         FROM_HERE, base::BindOnce(std::move(callback), service_is_available_));
85   } else {
86     pending_wait_for_service_to_be_available_callbacks_.push_back(
87         std::move(callback));
88   }
89 }
90 
IsMounted(DBusMethodCallback<bool> callback)91 void FakeCryptohomeClient::IsMounted(DBusMethodCallback<bool> callback) {
92   base::ThreadTaskRunnerHandle::Get()->PostTask(
93       FROM_HERE, base::BindOnce(std::move(callback), true));
94 }
95 
UnmountEx(const cryptohome::UnmountRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)96 void FakeCryptohomeClient::UnmountEx(
97     const cryptohome::UnmountRequest& request,
98     DBusMethodCallback<cryptohome::BaseReply> callback) {
99   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
100 }
101 
MigrateKeyEx(const cryptohome::AccountIdentifier & account,const cryptohome::AuthorizationRequest & auth_request,const cryptohome::MigrateKeyRequest & migrate_request,DBusMethodCallback<cryptohome::BaseReply> callback)102 void FakeCryptohomeClient::MigrateKeyEx(
103     const cryptohome::AccountIdentifier& account,
104     const cryptohome::AuthorizationRequest& auth_request,
105     const cryptohome::MigrateKeyRequest& migrate_request,
106     DBusMethodCallback<cryptohome::BaseReply> callback) {
107   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
108 }
109 
RemoveEx(const cryptohome::AccountIdentifier & account,DBusMethodCallback<cryptohome::BaseReply> callback)110 void FakeCryptohomeClient::RemoveEx(
111     const cryptohome::AccountIdentifier& account,
112     DBusMethodCallback<cryptohome::BaseReply> callback) {
113   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
114 }
115 
RenameCryptohome(const cryptohome::AccountIdentifier & cryptohome_id_from,const cryptohome::AccountIdentifier & cryptohome_id_to,DBusMethodCallback<cryptohome::BaseReply> callback)116 void FakeCryptohomeClient::RenameCryptohome(
117     const cryptohome::AccountIdentifier& cryptohome_id_from,
118     const cryptohome::AccountIdentifier& cryptohome_id_to,
119     DBusMethodCallback<cryptohome::BaseReply> callback) {
120   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
121 }
122 
GetAccountDiskUsage(const cryptohome::AccountIdentifier & account_id,DBusMethodCallback<cryptohome::BaseReply> callback)123 void FakeCryptohomeClient::GetAccountDiskUsage(
124     const cryptohome::AccountIdentifier& account_id,
125     DBusMethodCallback<cryptohome::BaseReply> callback) {
126   cryptohome::BaseReply reply;
127   cryptohome::GetAccountDiskUsageReply* get_account_disk_usage_reply =
128       reply.MutableExtension(cryptohome::GetAccountDiskUsageReply::reply);
129   // Sets 100 MB as a fake usage.
130   get_account_disk_usage_reply->set_size(100 * 1024 * 1024);
131   ReturnProtobufMethodCallback(reply, std::move(callback));
132 }
133 
GetSystemSalt(DBusMethodCallback<std::vector<uint8_t>> callback)134 void FakeCryptohomeClient::GetSystemSalt(
135     DBusMethodCallback<std::vector<uint8_t>> callback) {
136   base::ThreadTaskRunnerHandle::Get()->PostTask(
137       FROM_HERE, base::BindOnce(std::move(callback), system_salt_));
138 }
139 
GetSanitizedUsername(const cryptohome::AccountIdentifier & cryptohome_id,DBusMethodCallback<std::string> callback)140 void FakeCryptohomeClient::GetSanitizedUsername(
141     const cryptohome::AccountIdentifier& cryptohome_id,
142     DBusMethodCallback<std::string> callback) {
143   // Even for stub implementation we have to return different values so that
144   // multi-profiles would work.
145   auto id = service_is_available_
146                 ? base::make_optional(GetStubSanitizedUsername(cryptohome_id))
147                 : base::nullopt;
148   base::ThreadTaskRunnerHandle::Get()->PostTask(
149       FROM_HERE, base::BindOnce(std::move(callback), id));
150 }
151 
BlockingGetSanitizedUsername(const cryptohome::AccountIdentifier & cryptohome_id)152 std::string FakeCryptohomeClient::BlockingGetSanitizedUsername(
153     const cryptohome::AccountIdentifier& cryptohome_id) {
154   return service_is_available_ ? GetStubSanitizedUsername(cryptohome_id)
155                                : std::string();
156 }
157 
MountGuestEx(const cryptohome::MountGuestRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)158 void FakeCryptohomeClient::MountGuestEx(
159     const cryptohome::MountGuestRequest& request,
160     DBusMethodCallback<cryptohome::BaseReply> callback) {
161   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
162 }
163 
GetRsuDeviceId(DBusMethodCallback<cryptohome::BaseReply> callback)164 void FakeCryptohomeClient::GetRsuDeviceId(
165     DBusMethodCallback<cryptohome::BaseReply> callback) {
166   cryptohome::BaseReply reply;
167   cryptohome::GetRsuDeviceIdReply* get_rsu_lookup_key_reply =
168       reply.MutableExtension(cryptohome::GetRsuDeviceIdReply::reply);
169   get_rsu_lookup_key_reply->set_rsu_device_id(rsu_device_id_);
170   ReturnProtobufMethodCallback(reply, std::move(callback));
171 }
172 
TpmIsReady(DBusMethodCallback<bool> callback)173 void FakeCryptohomeClient::TpmIsReady(DBusMethodCallback<bool> callback) {
174   base::ThreadTaskRunnerHandle::Get()->PostTask(
175       FROM_HERE, base::BindOnce(std::move(callback), tpm_is_ready_));
176 }
177 
TpmIsEnabled(DBusMethodCallback<bool> callback)178 void FakeCryptohomeClient::TpmIsEnabled(DBusMethodCallback<bool> callback) {
179   base::ThreadTaskRunnerHandle::Get()->PostTask(
180       FROM_HERE, base::BindOnce(std::move(callback), tpm_is_enabled_));
181 }
182 
CallTpmIsEnabledAndBlock(bool * enabled)183 bool FakeCryptohomeClient::CallTpmIsEnabledAndBlock(bool* enabled) {
184   *enabled = tpm_is_enabled_;
185   return true;
186 }
187 
TpmGetPassword(DBusMethodCallback<std::string> callback)188 void FakeCryptohomeClient::TpmGetPassword(
189     DBusMethodCallback<std::string> callback) {
190   base::ThreadTaskRunnerHandle::Get()->PostTask(
191       FROM_HERE,
192       base::BindOnce(std::move(callback), std::string(kStubTpmPassword)));
193 }
194 
TpmIsOwned(DBusMethodCallback<bool> callback)195 void FakeCryptohomeClient::TpmIsOwned(DBusMethodCallback<bool> callback) {
196   base::ThreadTaskRunnerHandle::Get()->PostTask(
197       FROM_HERE, base::BindOnce(std::move(callback), true));
198 }
199 
CallTpmIsOwnedAndBlock(bool * owned)200 bool FakeCryptohomeClient::CallTpmIsOwnedAndBlock(bool* owned) {
201   *owned = true;
202   return true;
203 }
204 
TpmIsBeingOwned(DBusMethodCallback<bool> callback)205 void FakeCryptohomeClient::TpmIsBeingOwned(DBusMethodCallback<bool> callback) {
206   base::ThreadTaskRunnerHandle::Get()->PostTask(
207       FROM_HERE, base::BindOnce(std::move(callback), true));
208 }
209 
CallTpmIsBeingOwnedAndBlock(bool * owning)210 bool FakeCryptohomeClient::CallTpmIsBeingOwnedAndBlock(bool* owning) {
211   *owning = true;
212   return true;
213 }
214 
TpmCanAttemptOwnership(VoidDBusMethodCallback callback)215 void FakeCryptohomeClient::TpmCanAttemptOwnership(
216     VoidDBusMethodCallback callback) {
217   base::ThreadTaskRunnerHandle::Get()->PostTask(
218       FROM_HERE, base::BindOnce(std::move(callback), true));
219 }
220 
TpmClearStoredPassword(VoidDBusMethodCallback callback)221 void FakeCryptohomeClient::TpmClearStoredPassword(
222     VoidDBusMethodCallback callback) {
223   base::ThreadTaskRunnerHandle::Get()->PostTask(
224       FROM_HERE, base::BindOnce(std::move(callback), true));
225 }
226 
CallTpmClearStoredPasswordAndBlock()227 bool FakeCryptohomeClient::CallTpmClearStoredPasswordAndBlock() {
228   return true;
229 }
230 
Pkcs11IsTpmTokenReady(DBusMethodCallback<bool> callback)231 void FakeCryptohomeClient::Pkcs11IsTpmTokenReady(
232     DBusMethodCallback<bool> callback) {
233   base::ThreadTaskRunnerHandle::Get()->PostTask(
234       FROM_HERE, base::BindOnce(std::move(callback), true));
235 }
236 
Pkcs11GetTpmTokenInfo(DBusMethodCallback<TpmTokenInfo> callback)237 void FakeCryptohomeClient::Pkcs11GetTpmTokenInfo(
238     DBusMethodCallback<TpmTokenInfo> callback) {
239   const char kStubTPMTokenName[] = "StubTPMTokenName";
240   const char kStubUserPin[] = "012345";
241   const int kStubSlot = 0;
242   base::ThreadTaskRunnerHandle::Get()->PostTask(
243       FROM_HERE,
244       base::BindOnce(std::move(callback),
245                      TpmTokenInfo{kStubTPMTokenName, kStubUserPin, kStubSlot}));
246 }
247 
Pkcs11GetTpmTokenInfoForUser(const cryptohome::AccountIdentifier & cryptohome_id,DBusMethodCallback<TpmTokenInfo> callback)248 void FakeCryptohomeClient::Pkcs11GetTpmTokenInfoForUser(
249     const cryptohome::AccountIdentifier& cryptohome_id,
250     DBusMethodCallback<TpmTokenInfo> callback) {
251   Pkcs11GetTpmTokenInfo(std::move(callback));
252 }
253 
InstallAttributesGet(const std::string & name,std::vector<uint8_t> * value,bool * successful)254 bool FakeCryptohomeClient::InstallAttributesGet(const std::string& name,
255                                                 std::vector<uint8_t>* value,
256                                                 bool* successful) {
257   if (install_attrs_.find(name) != install_attrs_.end()) {
258     *value = install_attrs_[name];
259     *successful = true;
260   } else {
261     value->clear();
262     *successful = false;
263   }
264   return true;
265 }
266 
InstallAttributesSet(const std::string & name,const std::vector<uint8_t> & value,bool * successful)267 bool FakeCryptohomeClient::InstallAttributesSet(
268     const std::string& name,
269     const std::vector<uint8_t>& value,
270     bool* successful) {
271   install_attrs_[name] = value;
272   *successful = true;
273   return true;
274 }
275 
InstallAttributesFinalize(bool * successful)276 bool FakeCryptohomeClient::InstallAttributesFinalize(bool* successful) {
277   locked_ = true;
278   *successful = true;
279 
280   // Persist the install attributes so that they can be reloaded if the
281   // browser is restarted. This is used for ease of development when device
282   // enrollment is required.
283   base::FilePath cache_path;
284   if (!base::PathService::Get(dbus_paths::FILE_INSTALL_ATTRIBUTES,
285                               &cache_path)) {
286     return false;
287   }
288 
289   cryptohome::SerializedInstallAttributes install_attrs_proto;
290   for (const auto& it : install_attrs_) {
291     const std::string& name = it.first;
292     const std::vector<uint8_t>& value = it.second;
293     cryptohome::SerializedInstallAttributes::Attribute* attr_entry =
294         install_attrs_proto.add_attributes();
295     attr_entry->set_name(name);
296     attr_entry->mutable_value()->assign(value.data(),
297                                         value.data() + value.size());
298   }
299 
300   std::string result;
301   install_attrs_proto.SerializeToString(&result);
302 
303   // The real implementation does a blocking wait on the dbus call; the fake
304   // implementation must have this file written before returning.
305   base::ThreadRestrictions::ScopedAllowIO allow_io;
306   base::WriteFile(cache_path, result.data(), result.size());
307 
308   return true;
309 }
310 
InstallAttributesIsReady(DBusMethodCallback<bool> callback)311 void FakeCryptohomeClient::InstallAttributesIsReady(
312     DBusMethodCallback<bool> callback) {
313   base::ThreadTaskRunnerHandle::Get()->PostTask(
314       FROM_HERE, base::BindOnce(std::move(callback), true));
315 }
316 
InstallAttributesIsInvalid(bool * is_invalid)317 bool FakeCryptohomeClient::InstallAttributesIsInvalid(bool* is_invalid) {
318   *is_invalid = false;
319   return true;
320 }
321 
InstallAttributesIsFirstInstall(bool * is_first_install)322 bool FakeCryptohomeClient::InstallAttributesIsFirstInstall(
323     bool* is_first_install) {
324   *is_first_install = !locked_;
325   return true;
326 }
327 
TpmGetVersion(DBusMethodCallback<TpmVersionInfo> callback)328 void FakeCryptohomeClient::TpmGetVersion(
329     DBusMethodCallback<TpmVersionInfo> callback) {
330   base::ThreadTaskRunnerHandle::Get()->PostTask(
331       FROM_HERE, base::BindOnce(std::move(callback), TpmVersionInfo()));
332 }
333 
GetKeyDataEx(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::AuthorizationRequest & auth,const cryptohome::GetKeyDataRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)334 void FakeCryptohomeClient::GetKeyDataEx(
335     const cryptohome::AccountIdentifier& cryptohome_id,
336     const cryptohome::AuthorizationRequest& auth,
337     const cryptohome::GetKeyDataRequest& request,
338     DBusMethodCallback<cryptohome::BaseReply> callback) {
339   cryptohome::BaseReply reply;
340   const auto it = key_data_map_.find(cryptohome_id);
341   if (it == key_data_map_.end()) {
342     reply.set_error(cryptohome::CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND);
343   } else if (it->second.empty()) {
344     reply.set_error(cryptohome::CRYPTOHOME_ERROR_KEY_NOT_FOUND);
345   } else {
346     auto key = FindKey(it->second, auth.key().data().label());
347     if (key != it->second.end()) {
348       cryptohome::GetKeyDataReply* key_data_reply =
349           reply.MutableExtension(cryptohome::GetKeyDataReply::reply);
350       *key_data_reply->add_key_data() = key->second.data();
351     } else {
352       reply.set_error(cryptohome::CRYPTOHOME_ERROR_KEY_NOT_FOUND);
353     }
354   }
355   ReturnProtobufMethodCallback(reply, std::move(callback));
356 }
357 
CheckKeyEx(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::AuthorizationRequest & auth,const cryptohome::CheckKeyRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)358 void FakeCryptohomeClient::CheckKeyEx(
359     const cryptohome::AccountIdentifier& cryptohome_id,
360     const cryptohome::AuthorizationRequest& auth,
361     const cryptohome::CheckKeyRequest& request,
362     DBusMethodCallback<cryptohome::BaseReply> callback) {
363   cryptohome::BaseReply reply;
364 
365   if (enable_auth_check_) {
366     const auto it = key_data_map_.find(cryptohome_id);
367     if (it == key_data_map_.end()) {
368       reply.set_error(cryptohome::CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND);
369     } else if (it->second.empty()) {
370       reply.set_error(cryptohome::CRYPTOHOME_ERROR_KEY_NOT_FOUND);
371     } else {
372       auto key = FindKey(it->second, auth.key().data().label());
373       if (key == it->second.end()) {
374         reply.set_error(cryptohome::CRYPTOHOME_ERROR_KEY_NOT_FOUND);
375       } else if (key->second.secret() != auth.key().secret()) {
376         reply.set_error(cryptohome::CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED);
377       }
378     }
379   }
380 
381   ReturnProtobufMethodCallback(reply, std::move(callback));
382 }
383 
MountEx(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::AuthorizationRequest & auth,const cryptohome::MountRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)384 void FakeCryptohomeClient::MountEx(
385     const cryptohome::AccountIdentifier& cryptohome_id,
386     const cryptohome::AuthorizationRequest& auth,
387     const cryptohome::MountRequest& request,
388     DBusMethodCallback<cryptohome::BaseReply> callback) {
389   cryptohome::CryptohomeErrorCode error = cryptohome_error_;
390   last_mount_request_ = request;
391   last_mount_auth_request_ = auth;
392   cryptohome::BaseReply reply;
393   cryptohome::MountReply* mount =
394       reply.MutableExtension(cryptohome::MountReply::reply);
395   mount->set_sanitized_username(GetStubSanitizedUsername(cryptohome_id));
396   if (IsEcryptfsUserHome(cryptohome_id) &&
397       !request.to_migrate_from_ecryptfs() &&
398       request.force_dircrypto_if_available()) {
399     error = cryptohome::CRYPTOHOME_ERROR_MOUNT_OLD_ENCRYPTION;
400   }
401   if (mount_create_required_ && !request.has_create())
402     error = cryptohome::CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND;
403   reply.set_error(error);
404   ReturnProtobufMethodCallback(reply, std::move(callback));
405 }
406 
LockToSingleUserMountUntilReboot(const cryptohome::LockToSingleUserMountUntilRebootRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)407 void FakeCryptohomeClient::LockToSingleUserMountUntilReboot(
408     const cryptohome::LockToSingleUserMountUntilRebootRequest& request,
409     DBusMethodCallback<cryptohome::BaseReply> callback) {
410   cryptohome::BaseReply reply;
411   cryptohome::LockToSingleUserMountUntilRebootReply* mutable_reply =
412       reply.MutableExtension(
413           cryptohome::LockToSingleUserMountUntilRebootReply::reply);
414   if (cryptohome_error_ == cryptohome::CRYPTOHOME_ERROR_NOT_SET) {
415     mutable_reply->set_result(
416         cryptohome::LockToSingleUserMountUntilRebootResult::SUCCESS);
417     is_device_locked_to_single_user_ = true;
418   } else {
419     mutable_reply->set_result(
420         cryptohome::LockToSingleUserMountUntilRebootResult::
421             FAILED_TO_EXTEND_PCR);
422   }
423 
424   ReturnProtobufMethodCallback(reply, std::move(callback));
425 }
426 
AddKeyEx(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::AuthorizationRequest & auth,const cryptohome::AddKeyRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)427 void FakeCryptohomeClient::AddKeyEx(
428     const cryptohome::AccountIdentifier& cryptohome_id,
429     const cryptohome::AuthorizationRequest& auth,
430     const cryptohome::AddKeyRequest& request,
431     DBusMethodCallback<cryptohome::BaseReply> callback) {
432   key_data_map_[cryptohome_id][request.key().data().label()] = request.key();
433   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
434 }
435 
AddDataRestoreKey(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::AuthorizationRequest & auth,DBusMethodCallback<cryptohome::BaseReply> callback)436 void FakeCryptohomeClient::AddDataRestoreKey(
437     const cryptohome::AccountIdentifier& cryptohome_id,
438     const cryptohome::AuthorizationRequest& auth,
439     DBusMethodCallback<cryptohome::BaseReply> callback) {
440   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
441 }
442 
RemoveKeyEx(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::AuthorizationRequest & auth,const cryptohome::RemoveKeyRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)443 void FakeCryptohomeClient::RemoveKeyEx(
444     const cryptohome::AccountIdentifier& cryptohome_id,
445     const cryptohome::AuthorizationRequest& auth,
446     const cryptohome::RemoveKeyRequest& request,
447     DBusMethodCallback<cryptohome::BaseReply> callback) {
448   const auto it = key_data_map_.find(cryptohome_id);
449   if (it != key_data_map_.end()) {
450     auto key = FindKey(it->second, request.key().data().label());
451     if (key != it->second.end())
452       it->second.erase(key);
453   }
454   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
455 }
456 
UpdateKeyEx(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::AuthorizationRequest & auth,const cryptohome::UpdateKeyRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)457 void FakeCryptohomeClient::UpdateKeyEx(
458     const cryptohome::AccountIdentifier& cryptohome_id,
459     const cryptohome::AuthorizationRequest& auth,
460     const cryptohome::UpdateKeyRequest& request,
461     DBusMethodCallback<cryptohome::BaseReply> callback) {
462   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
463 }
464 
MassRemoveKeys(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::AuthorizationRequest & auth,const cryptohome::MassRemoveKeysRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)465 void FakeCryptohomeClient::MassRemoveKeys(
466     const cryptohome::AccountIdentifier& cryptohome_id,
467     const cryptohome::AuthorizationRequest& auth,
468     const cryptohome::MassRemoveKeysRequest& request,
469     DBusMethodCallback<cryptohome::BaseReply> callback) {
470   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
471 }
472 
GetBootAttribute(const cryptohome::GetBootAttributeRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)473 void FakeCryptohomeClient::GetBootAttribute(
474     const cryptohome::GetBootAttributeRequest& request,
475     DBusMethodCallback<cryptohome::BaseReply> callback) {
476   cryptohome::BaseReply reply;
477   cryptohome::GetBootAttributeReply* attr_reply =
478       reply.MutableExtension(cryptohome::GetBootAttributeReply::reply);
479   attr_reply->set_value("");
480   ReturnProtobufMethodCallback(reply, std::move(callback));
481 }
482 
SetBootAttribute(const cryptohome::SetBootAttributeRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)483 void FakeCryptohomeClient::SetBootAttribute(
484     const cryptohome::SetBootAttributeRequest& request,
485     DBusMethodCallback<cryptohome::BaseReply> callback) {
486   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
487 }
488 
FlushAndSignBootAttributes(const cryptohome::FlushAndSignBootAttributesRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)489 void FakeCryptohomeClient::FlushAndSignBootAttributes(
490     const cryptohome::FlushAndSignBootAttributesRequest& request,
491     DBusMethodCallback<cryptohome::BaseReply> callback) {
492   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
493 }
494 
GetTpmStatus(const cryptohome::GetTpmStatusRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)495 void FakeCryptohomeClient::GetTpmStatus(
496     const cryptohome::GetTpmStatusRequest& request,
497     DBusMethodCallback<cryptohome::BaseReply> callback) {
498   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
499 }
500 
MigrateToDircrypto(const cryptohome::AccountIdentifier & cryptohome_id,const cryptohome::MigrateToDircryptoRequest & request,VoidDBusMethodCallback callback)501 void FakeCryptohomeClient::MigrateToDircrypto(
502     const cryptohome::AccountIdentifier& cryptohome_id,
503     const cryptohome::MigrateToDircryptoRequest& request,
504     VoidDBusMethodCallback callback) {
505   id_for_disk_migrated_to_dircrypto_ = cryptohome_id;
506   last_migrate_to_dircrypto_request_ = request;
507   base::ThreadTaskRunnerHandle::Get()->PostTask(
508       FROM_HERE, base::BindOnce(std::move(callback), true));
509   dircrypto_migration_progress_ = 0;
510   if (run_default_dircrypto_migration_) {
511     dircrypto_migration_progress_timer_.Start(
512         FROM_HERE,
513         base::TimeDelta::FromMilliseconds(kDircryptoMigrationUpdateIntervalMs),
514         this, &FakeCryptohomeClient::OnDircryptoMigrationProgressUpdated);
515   }
516 }
517 
RemoveFirmwareManagementParametersFromTpm(const cryptohome::RemoveFirmwareManagementParametersRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)518 void FakeCryptohomeClient::RemoveFirmwareManagementParametersFromTpm(
519     const cryptohome::RemoveFirmwareManagementParametersRequest& request,
520     DBusMethodCallback<cryptohome::BaseReply> callback) {
521   remove_firmware_management_parameters_from_tpm_call_count_++;
522   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
523 }
524 
SetFirmwareManagementParametersInTpm(const cryptohome::SetFirmwareManagementParametersRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)525 void FakeCryptohomeClient::SetFirmwareManagementParametersInTpm(
526     const cryptohome::SetFirmwareManagementParametersRequest& request,
527     DBusMethodCallback<cryptohome::BaseReply> callback) {
528   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
529 }
530 
NeedsDircryptoMigration(const cryptohome::AccountIdentifier & cryptohome_id,DBusMethodCallback<bool> callback)531 void FakeCryptohomeClient::NeedsDircryptoMigration(
532     const cryptohome::AccountIdentifier& cryptohome_id,
533     DBusMethodCallback<bool> callback) {
534   base::ThreadTaskRunnerHandle::Get()->PostTask(
535       FROM_HERE,
536       base::BindOnce(std::move(callback), IsEcryptfsUserHome(cryptohome_id)));
537 }
538 
GetSupportedKeyPolicies(const cryptohome::GetSupportedKeyPoliciesRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)539 void FakeCryptohomeClient::GetSupportedKeyPolicies(
540     const cryptohome::GetSupportedKeyPoliciesRequest& request,
541     DBusMethodCallback<cryptohome::BaseReply> callback) {
542   cryptohome::BaseReply reply;
543   cryptohome::GetSupportedKeyPoliciesReply* attr_reply =
544       reply.MutableExtension(cryptohome::GetSupportedKeyPoliciesReply::reply);
545   attr_reply->set_low_entropy_credentials(supports_low_entropy_credentials_);
546   ReturnProtobufMethodCallback(reply, std::move(callback));
547 }
548 
IsQuotaSupported(DBusMethodCallback<bool> callback)549 void FakeCryptohomeClient::IsQuotaSupported(DBusMethodCallback<bool> callback) {
550 }
551 
GetCurrentSpaceForUid(uid_t android_uid,DBusMethodCallback<int64_t> callback)552 void FakeCryptohomeClient::GetCurrentSpaceForUid(
553     uid_t android_uid,
554     DBusMethodCallback<int64_t> callback) {}
555 
GetCurrentSpaceForGid(gid_t android_gid,DBusMethodCallback<int64_t> callback)556 void FakeCryptohomeClient::GetCurrentSpaceForGid(
557     gid_t android_gid,
558     DBusMethodCallback<int64_t> callback) {}
559 
CheckHealth(const cryptohome::CheckHealthRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)560 void FakeCryptohomeClient::CheckHealth(
561     const cryptohome::CheckHealthRequest& request,
562     DBusMethodCallback<cryptohome::BaseReply> callback) {
563   cryptohome::BaseReply reply;
564   if (cryptohome_error_ == cryptohome::CRYPTOHOME_ERROR_NOT_SET) {
565     cryptohome::CheckHealthReply* state_reply =
566         reply.MutableExtension(cryptohome::CheckHealthReply::reply);
567     state_reply->set_requires_powerwash(requires_powerwash_);
568   }
569 
570   ReturnProtobufMethodCallback(reply, std::move(callback));
571 }
572 
StartFingerprintAuthSession(const cryptohome::AccountIdentifier & id,const cryptohome::StartFingerprintAuthSessionRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)573 void FakeCryptohomeClient::StartFingerprintAuthSession(
574     const cryptohome::AccountIdentifier& id,
575     const cryptohome::StartFingerprintAuthSessionRequest& request,
576     DBusMethodCallback<cryptohome::BaseReply> callback) {
577   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
578 }
579 
EndFingerprintAuthSession(const cryptohome::EndFingerprintAuthSessionRequest & request,DBusMethodCallback<cryptohome::BaseReply> callback)580 void FakeCryptohomeClient::EndFingerprintAuthSession(
581     const cryptohome::EndFingerprintAuthSessionRequest& request,
582     DBusMethodCallback<cryptohome::BaseReply> callback) {
583   ReturnProtobufMethodCallback(cryptohome::BaseReply(), std::move(callback));
584 }
585 
SetServiceIsAvailable(bool is_available)586 void FakeCryptohomeClient::SetServiceIsAvailable(bool is_available) {
587   service_is_available_ = is_available;
588   if (!is_available)
589     return;
590 
591   std::vector<WaitForServiceToBeAvailableCallback> callbacks;
592   callbacks.swap(pending_wait_for_service_to_be_available_callbacks_);
593   for (auto& callback : callbacks)
594     std::move(callback).Run(true);
595 }
596 
ReportServiceIsNotAvailable()597 void FakeCryptohomeClient::ReportServiceIsNotAvailable() {
598   DCHECK(!service_is_available_);
599   service_reported_not_available_ = true;
600 
601   std::vector<WaitForServiceToBeAvailableCallback> callbacks;
602   callbacks.swap(pending_wait_for_service_to_be_available_callbacks_);
603   for (auto& callback : callbacks)
604     std::move(callback).Run(false);
605 }
606 
NotifyLowDiskSpace(uint64_t disk_free_bytes)607 void FakeCryptohomeClient::NotifyLowDiskSpace(uint64_t disk_free_bytes) {
608   for (auto& observer : observer_list_)
609     observer.LowDiskSpace(disk_free_bytes);
610 }
611 
612 // static
GetStubSystemSalt()613 std::vector<uint8_t> FakeCryptohomeClient::GetStubSystemSalt() {
614   const char kStubSystemSalt[] = "stub_system_salt";
615   return std::vector<uint8_t>(
616       kStubSystemSalt, kStubSystemSalt + base::size(kStubSystemSalt) - 1);
617 }
618 
SetEcryptfsUserHome(const cryptohome::AccountIdentifier & cryptohome_id,bool use_ecryptfs)619 void FakeCryptohomeClient::SetEcryptfsUserHome(
620     const cryptohome::AccountIdentifier& cryptohome_id,
621     bool use_ecryptfs) {
622   if (use_ecryptfs)
623     ecryptfs_user_homes_.insert(cryptohome_id);
624   else
625     ecryptfs_user_homes_.erase(cryptohome_id);
626 }
627 
ReturnProtobufMethodCallback(const cryptohome::BaseReply & reply,DBusMethodCallback<cryptohome::BaseReply> callback)628 void FakeCryptohomeClient::ReturnProtobufMethodCallback(
629     const cryptohome::BaseReply& reply,
630     DBusMethodCallback<cryptohome::BaseReply> callback) {
631   base::ThreadTaskRunnerHandle::Get()->PostTask(
632       FROM_HERE, base::BindOnce(std::move(callback), reply));
633 }
634 
ReturnAsyncMethodResult(AsyncMethodCallback callback)635 void FakeCryptohomeClient::ReturnAsyncMethodResult(
636     AsyncMethodCallback callback) {
637   base::ThreadTaskRunnerHandle::Get()->PostTask(
638       FROM_HERE,
639       base::BindOnce(&FakeCryptohomeClient::ReturnAsyncMethodResultInternal,
640                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
641 }
642 
ReturnAsyncMethodData(AsyncMethodCallback callback,const std::string & data)643 void FakeCryptohomeClient::ReturnAsyncMethodData(AsyncMethodCallback callback,
644                                                  const std::string& data) {
645   base::ThreadTaskRunnerHandle::Get()->PostTask(
646       FROM_HERE,
647       base::BindOnce(&FakeCryptohomeClient::ReturnAsyncMethodDataInternal,
648                      weak_ptr_factory_.GetWeakPtr(), std::move(callback),
649                      data));
650 }
651 
ReturnAsyncMethodResultInternal(AsyncMethodCallback callback)652 void FakeCryptohomeClient::ReturnAsyncMethodResultInternal(
653     AsyncMethodCallback callback) {
654   std::move(callback).Run(async_call_id_);
655   base::ThreadTaskRunnerHandle::Get()->PostTask(
656       FROM_HERE, base::BindOnce(&FakeCryptohomeClient::NotifyAsyncCallStatus,
657                                 weak_ptr_factory_.GetWeakPtr(), async_call_id_,
658                                 true, cryptohome::MOUNT_ERROR_NONE));
659   ++async_call_id_;
660 }
661 
ReturnAsyncMethodDataInternal(AsyncMethodCallback callback,const std::string & data)662 void FakeCryptohomeClient::ReturnAsyncMethodDataInternal(
663     AsyncMethodCallback callback,
664     const std::string& data) {
665   std::move(callback).Run(async_call_id_);
666   base::ThreadTaskRunnerHandle::Get()->PostTask(
667       FROM_HERE,
668       base::BindOnce(&FakeCryptohomeClient::NotifyAsyncCallStatusWithData,
669                      weak_ptr_factory_.GetWeakPtr(), async_call_id_, true,
670                      data));
671   ++async_call_id_;
672 }
673 
OnDircryptoMigrationProgressUpdated()674 void FakeCryptohomeClient::OnDircryptoMigrationProgressUpdated() {
675   dircrypto_migration_progress_++;
676 
677   if (dircrypto_migration_progress_ >= kDircryptoMigrationMaxProgress) {
678     NotifyDircryptoMigrationProgress(cryptohome::DIRCRYPTO_MIGRATION_SUCCESS,
679                                      dircrypto_migration_progress_,
680                                      kDircryptoMigrationMaxProgress);
681     SetEcryptfsUserHome(id_for_disk_migrated_to_dircrypto_, false);
682     dircrypto_migration_progress_timer_.Stop();
683     return;
684   }
685   NotifyDircryptoMigrationProgress(cryptohome::DIRCRYPTO_MIGRATION_IN_PROGRESS,
686                                    dircrypto_migration_progress_,
687                                    kDircryptoMigrationMaxProgress);
688 }
689 
NotifyAsyncCallStatus(int async_id,bool return_status,int return_code)690 void FakeCryptohomeClient::NotifyAsyncCallStatus(int async_id,
691                                                  bool return_status,
692                                                  int return_code) {
693   for (auto& observer : observer_list_)
694     observer.AsyncCallStatus(async_id, return_status, return_code);
695 }
696 
NotifyAsyncCallStatusWithData(int async_id,bool return_status,const std::string & data)697 void FakeCryptohomeClient::NotifyAsyncCallStatusWithData(
698     int async_id,
699     bool return_status,
700     const std::string& data) {
701   for (auto& observer : observer_list_)
702     observer.AsyncCallStatusWithData(async_id, return_status, data);
703 }
704 
NotifyTpmInitStatusUpdated(bool ready,bool owned,bool was_owned_this_boot)705 void FakeCryptohomeClient::NotifyTpmInitStatusUpdated(
706     bool ready,
707     bool owned,
708     bool was_owned_this_boot) {
709   for (auto& observer : observer_list_)
710     observer.TpmInitStatusUpdated(ready, owned, was_owned_this_boot);
711 }
712 
NotifyDircryptoMigrationProgress(cryptohome::DircryptoMigrationStatus status,uint64_t current,uint64_t total)713 void FakeCryptohomeClient::NotifyDircryptoMigrationProgress(
714     cryptohome::DircryptoMigrationStatus status,
715     uint64_t current,
716     uint64_t total) {
717   for (auto& observer : observer_list_)
718     observer.DircryptoMigrationProgress(status, current, total);
719 }
720 
LoadInstallAttributes()721 bool FakeCryptohomeClient::LoadInstallAttributes() {
722   base::FilePath cache_file;
723   const bool file_exists =
724       base::PathService::Get(dbus_paths::FILE_INSTALL_ATTRIBUTES,
725                              &cache_file) &&
726       base::PathExists(cache_file);
727   DCHECK(file_exists);
728   // Mostly copied from chrome/browser/chromeos/tpm/install_attributes.cc.
729   std::string file_blob;
730   if (!base::ReadFileToStringWithMaxSize(cache_file, &file_blob,
731                                          kInstallAttributesFileMaxSize)) {
732     PLOG(ERROR) << "Failed to read " << cache_file.value();
733     return false;
734   }
735 
736   cryptohome::SerializedInstallAttributes install_attrs_proto;
737   if (!install_attrs_proto.ParseFromString(file_blob)) {
738     LOG(ERROR) << "Failed to parse install attributes cache.";
739     return false;
740   }
741 
742   for (const auto& entry : install_attrs_proto.attributes()) {
743     install_attrs_[entry.name()].assign(
744         entry.value().data(), entry.value().data() + entry.value().size());
745   }
746 
747   return true;
748 }
749 
IsEcryptfsUserHome(const cryptohome::AccountIdentifier & cryptohome_id)750 bool FakeCryptohomeClient::IsEcryptfsUserHome(
751     const cryptohome::AccountIdentifier& cryptohome_id) {
752   return base::Contains(ecryptfs_user_homes_, cryptohome_id);
753 }
754 
755 std::map<std::string, cryptohome::Key>::const_iterator
FindKey(const std::map<std::string,cryptohome::Key> & keys,const std::string & label)756 FakeCryptohomeClient::FindKey(
757     const std::map<std::string, cryptohome::Key>& keys,
758     const std::string& label) {
759   // Wildcard label.
760   if (label.empty())
761     return keys.begin();
762 
763   // Specific label
764   return keys.find(label);
765 }
766 
767 }  // namespace chromeos
768