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