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.
5 #include "chromeos/dbus/fake_cryptohome_client.h"
8 #include "base/files/file_util.h"
9 #include "base/location.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/path_service.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "chromeos/chromeos_paths.h"
14 #include "chromeos/dbus/cryptohome/key.pb.h"
15 #include "chromeos/dbus/cryptohome/rpc.pb.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
17 #include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
18 #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h"
19 #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
23 FakeCryptohomeClient::FakeCryptohomeClient()
24 : service_is_available_(true),
26 tpm_is_ready_counter_(0),
27 unmount_result_(true),
28 system_salt_(GetStubSystemSalt()),
29 weak_ptr_factory_(this) {
30 base::FilePath cache_path
;
31 locked_
= PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES
, &cache_path
) &&
32 base::PathExists(cache_path
);
35 FakeCryptohomeClient::~FakeCryptohomeClient() {}
37 void FakeCryptohomeClient::Init(dbus::Bus
* bus
) {
40 void FakeCryptohomeClient::SetAsyncCallStatusHandlers(
41 const AsyncCallStatusHandler
& handler
,
42 const AsyncCallStatusWithDataHandler
& data_handler
) {
43 async_call_status_handler_
= handler
;
44 async_call_status_data_handler_
= data_handler
;
47 void FakeCryptohomeClient::ResetAsyncCallStatusHandlers() {
48 async_call_status_handler_
.Reset();
49 async_call_status_data_handler_
.Reset();
52 void FakeCryptohomeClient::WaitForServiceToBeAvailable(
53 const WaitForServiceToBeAvailableCallback
& callback
) {
54 if (service_is_available_
) {
55 base::MessageLoop::current()->PostTask(FROM_HERE
,
56 base::Bind(callback
, true));
58 pending_wait_for_service_to_be_available_callbacks_
.push_back(callback
);
62 void FakeCryptohomeClient::IsMounted(
63 const BoolDBusMethodCallback
& callback
) {
64 base::MessageLoop::current()->PostTask(
65 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
68 bool FakeCryptohomeClient::Unmount(bool* success
) {
69 *success
= unmount_result_
;
73 void FakeCryptohomeClient::AsyncCheckKey(
74 const std::string
& username
,
75 const std::string
& key
,
76 const AsyncMethodCallback
& callback
) {
77 ReturnAsyncMethodResult(callback
, false);
80 void FakeCryptohomeClient::AsyncMigrateKey(
81 const std::string
& username
,
82 const std::string
& from_key
,
83 const std::string
& to_key
,
84 const AsyncMethodCallback
& callback
) {
85 ReturnAsyncMethodResult(callback
, false);
88 void FakeCryptohomeClient::AsyncRemove(
89 const std::string
& username
,
90 const AsyncMethodCallback
& callback
) {
91 ReturnAsyncMethodResult(callback
, false);
94 void FakeCryptohomeClient::GetSystemSalt(
95 const GetSystemSaltCallback
& callback
) {
96 base::MessageLoop::current()->PostTask(
98 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, system_salt_
));
101 void FakeCryptohomeClient::GetSanitizedUsername(
102 const std::string
& username
,
103 const StringDBusMethodCallback
& callback
) {
104 // Even for stub implementation we have to return different values so that
105 // multi-profiles would work.
106 std::string sanitized_username
= GetStubSanitizedUsername(username
);
107 base::MessageLoop::current()->PostTask(
109 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, sanitized_username
));
112 std::string
FakeCryptohomeClient::BlockingGetSanitizedUsername(
113 const std::string
& username
) {
114 return GetStubSanitizedUsername(username
);
117 void FakeCryptohomeClient::AsyncMount(const std::string
& username
,
118 const std::string
& key
,
120 const AsyncMethodCallback
& callback
) {
121 ReturnAsyncMethodResult(callback
, false);
124 void FakeCryptohomeClient::AsyncAddKey(
125 const std::string
& username
,
126 const std::string
& key
,
127 const std::string
& new_key
,
128 const AsyncMethodCallback
& callback
) {
129 ReturnAsyncMethodResult(callback
, false);
132 void FakeCryptohomeClient::AsyncMountGuest(
133 const AsyncMethodCallback
& callback
) {
134 ReturnAsyncMethodResult(callback
, false);
137 void FakeCryptohomeClient::AsyncMountPublic(
138 const std::string
& public_mount_id
,
140 const AsyncMethodCallback
& callback
) {
141 ReturnAsyncMethodResult(callback
, false);
144 void FakeCryptohomeClient::TpmIsReady(
145 const BoolDBusMethodCallback
& callback
) {
146 base::MessageLoop::current()->PostTask(
147 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
150 void FakeCryptohomeClient::TpmIsEnabled(
151 const BoolDBusMethodCallback
& callback
) {
152 base::MessageLoop::current()->PostTask(
153 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
156 bool FakeCryptohomeClient::CallTpmIsEnabledAndBlock(bool* enabled
) {
161 void FakeCryptohomeClient::TpmGetPassword(
162 const StringDBusMethodCallback
& callback
) {
163 const char kStubTpmPassword
[] = "Stub-TPM-password";
164 base::MessageLoop::current()->PostTask(
166 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
,
167 std::string(kStubTpmPassword
)));
170 void FakeCryptohomeClient::TpmIsOwned(
171 const BoolDBusMethodCallback
& callback
) {
172 base::MessageLoop::current()->PostTask(
173 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
176 bool FakeCryptohomeClient::CallTpmIsOwnedAndBlock(bool* owned
) {
181 void FakeCryptohomeClient::TpmIsBeingOwned(
182 const BoolDBusMethodCallback
& callback
) {
183 base::MessageLoop::current()->PostTask(
184 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
187 bool FakeCryptohomeClient::CallTpmIsBeingOwnedAndBlock(bool* owning
) {
192 void FakeCryptohomeClient::TpmCanAttemptOwnership(
193 const VoidDBusMethodCallback
& callback
) {
194 base::MessageLoop::current()->PostTask(
195 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
));
198 void FakeCryptohomeClient::TpmClearStoredPassword(
199 const VoidDBusMethodCallback
& callback
) {
200 base::MessageLoop::current()->PostTask(
201 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
));
204 bool FakeCryptohomeClient::CallTpmClearStoredPasswordAndBlock() {
208 void FakeCryptohomeClient::Pkcs11IsTpmTokenReady(
209 const BoolDBusMethodCallback
& callback
) {
210 base::MessageLoop::current()->PostTask(
211 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
214 void FakeCryptohomeClient::Pkcs11GetTpmTokenInfo(
215 const Pkcs11GetTpmTokenInfoCallback
& callback
) {
216 const char kStubTPMTokenName
[] = "StubTPMTokenName";
217 const char kStubUserPin
[] = "012345";
218 const int kStubSlot
= 0;
219 base::MessageLoop::current()->PostTask(
222 DBUS_METHOD_CALL_SUCCESS
,
223 std::string(kStubTPMTokenName
),
224 std::string(kStubUserPin
),
228 void FakeCryptohomeClient::Pkcs11GetTpmTokenInfoForUser(
229 const std::string
& username
,
230 const Pkcs11GetTpmTokenInfoCallback
& callback
) {
231 Pkcs11GetTpmTokenInfo(callback
);
234 bool FakeCryptohomeClient::InstallAttributesGet(const std::string
& name
,
235 std::vector
<uint8
>* value
,
237 if (install_attrs_
.find(name
) != install_attrs_
.end()) {
238 *value
= install_attrs_
[name
];
247 bool FakeCryptohomeClient::InstallAttributesSet(
248 const std::string
& name
,
249 const std::vector
<uint8
>& value
,
251 install_attrs_
[name
] = value
;
256 bool FakeCryptohomeClient::InstallAttributesFinalize(bool* successful
) {
260 // Persist the install attributes so that they can be reloaded if the
261 // browser is restarted. This is used for ease of development when device
262 // enrollment is required.
263 // The cryptohome::SerializedInstallAttributes protobuf lives in
264 // chrome/browser/chromeos, so it can't be used directly here; use the
265 // low-level protobuf API instead to just write the name-value pairs.
266 // The cache file is read by EnterpriseInstallAttributes::ReadCacheFile.
267 base::FilePath cache_path
;
268 if (!PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES
, &cache_path
))
273 // |result| can be used only after the StringOutputStream goes out of
275 google::protobuf::io::StringOutputStream
result_stream(&result
);
276 google::protobuf::io::CodedOutputStream
result_output(&result_stream
);
278 // These tags encode a variable-length value on the wire, which can be
279 // used to encode strings, bytes and messages. We only needs constants
280 // for tag numbers 1 and 2 (see install_attributes.proto).
281 const int kVarLengthTag1
= (1 << 3) | 0x2;
282 const int kVarLengthTag2
= (2 << 3) | 0x2;
284 typedef std::map
<std::string
, std::vector
<uint8
> >::const_iterator Iter
;
285 for (Iter it
= install_attrs_
.begin(); it
!= install_attrs_
.end(); ++it
) {
288 google::protobuf::io::StringOutputStream
attr_stream(&attr
);
289 google::protobuf::io::CodedOutputStream
attr_output(&attr_stream
);
291 attr_output
.WriteVarint32(kVarLengthTag1
);
292 attr_output
.WriteVarint32(it
->first
.size());
293 attr_output
.WriteString(it
->first
);
294 attr_output
.WriteVarint32(kVarLengthTag2
);
295 attr_output
.WriteVarint32(it
->second
.size());
296 attr_output
.WriteRaw(it
->second
.data(), it
->second
.size());
299 // Two CodedOutputStreams are needed because inner messages must be
300 // prefixed by their total length, which can't be easily computed before
301 // writing their tags and values.
302 result_output
.WriteVarint32(kVarLengthTag2
);
303 result_output
.WriteVarint32(attr
.size());
304 result_output
.WriteRaw(attr
.data(), attr
.size());
308 // The real implementation does a blocking wait on the dbus call; the fake
309 // implementation must have this file written before returning.
310 base::ThreadRestrictions::ScopedAllowIO allow_io
;
311 base::WriteFile(cache_path
, result
.data(), result
.size());
316 void FakeCryptohomeClient::InstallAttributesIsReady(
317 const BoolDBusMethodCallback
& callback
) {
318 base::MessageLoop::current()->PostTask(
319 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
322 bool FakeCryptohomeClient::InstallAttributesIsInvalid(bool* is_invalid
) {
327 bool FakeCryptohomeClient::InstallAttributesIsFirstInstall(
328 bool* is_first_install
) {
329 *is_first_install
= !locked_
;
333 void FakeCryptohomeClient::TpmAttestationIsPrepared(
334 const BoolDBusMethodCallback
& callback
) {
335 base::MessageLoop::current()->PostTask(
336 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
339 void FakeCryptohomeClient::TpmAttestationIsEnrolled(
340 const BoolDBusMethodCallback
& callback
) {
341 base::MessageLoop::current()->PostTask(
342 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
345 void FakeCryptohomeClient::AsyncTpmAttestationCreateEnrollRequest(
346 chromeos::attestation::PrivacyCAType pca_type
,
347 const AsyncMethodCallback
& callback
) {
348 ReturnAsyncMethodResult(callback
, true);
351 void FakeCryptohomeClient::AsyncTpmAttestationEnroll(
352 chromeos::attestation::PrivacyCAType pca_type
,
353 const std::string
& pca_response
,
354 const AsyncMethodCallback
& callback
) {
355 ReturnAsyncMethodResult(callback
, false);
358 void FakeCryptohomeClient::AsyncTpmAttestationCreateCertRequest(
359 chromeos::attestation::PrivacyCAType pca_type
,
360 attestation::AttestationCertificateProfile certificate_profile
,
361 const std::string
& user_id
,
362 const std::string
& request_origin
,
363 const AsyncMethodCallback
& callback
) {
364 ReturnAsyncMethodResult(callback
, true);
367 void FakeCryptohomeClient::AsyncTpmAttestationFinishCertRequest(
368 const std::string
& pca_response
,
369 attestation::AttestationKeyType key_type
,
370 const std::string
& user_id
,
371 const std::string
& key_name
,
372 const AsyncMethodCallback
& callback
) {
373 ReturnAsyncMethodResult(callback
, true);
376 void FakeCryptohomeClient::TpmAttestationDoesKeyExist(
377 attestation::AttestationKeyType key_type
,
378 const std::string
& user_id
,
379 const std::string
& key_name
,
380 const BoolDBusMethodCallback
& callback
) {
381 base::MessageLoop::current()->PostTask(
382 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false));
385 void FakeCryptohomeClient::TpmAttestationGetCertificate(
386 attestation::AttestationKeyType key_type
,
387 const std::string
& user_id
,
388 const std::string
& key_name
,
389 const DataMethodCallback
& callback
) {
390 base::MessageLoop::current()->PostTask(
392 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false, std::string()));
395 void FakeCryptohomeClient::TpmAttestationGetPublicKey(
396 attestation::AttestationKeyType key_type
,
397 const std::string
& user_id
,
398 const std::string
& key_name
,
399 const DataMethodCallback
& callback
) {
400 base::MessageLoop::current()->PostTask(
402 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false, std::string()));
405 void FakeCryptohomeClient::TpmAttestationRegisterKey(
406 attestation::AttestationKeyType key_type
,
407 const std::string
& user_id
,
408 const std::string
& key_name
,
409 const AsyncMethodCallback
& callback
) {
410 ReturnAsyncMethodResult(callback
, true);
413 void FakeCryptohomeClient::TpmAttestationSignEnterpriseChallenge(
414 attestation::AttestationKeyType key_type
,
415 const std::string
& user_id
,
416 const std::string
& key_name
,
417 const std::string
& domain
,
418 const std::string
& device_id
,
419 attestation::AttestationChallengeOptions options
,
420 const std::string
& challenge
,
421 const AsyncMethodCallback
& callback
) {
422 ReturnAsyncMethodResult(callback
, true);
425 void FakeCryptohomeClient::TpmAttestationSignSimpleChallenge(
426 attestation::AttestationKeyType key_type
,
427 const std::string
& user_id
,
428 const std::string
& key_name
,
429 const std::string
& challenge
,
430 const AsyncMethodCallback
& callback
) {
431 ReturnAsyncMethodResult(callback
, true);
434 void FakeCryptohomeClient::TpmAttestationGetKeyPayload(
435 attestation::AttestationKeyType key_type
,
436 const std::string
& user_id
,
437 const std::string
& key_name
,
438 const DataMethodCallback
& callback
) {
439 base::MessageLoop::current()->PostTask(
441 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false, std::string()));
444 void FakeCryptohomeClient::TpmAttestationSetKeyPayload(
445 attestation::AttestationKeyType key_type
,
446 const std::string
& user_id
,
447 const std::string
& key_name
,
448 const std::string
& payload
,
449 const BoolDBusMethodCallback
& callback
) {
450 base::MessageLoop::current()->PostTask(
451 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false));
454 void FakeCryptohomeClient::TpmAttestationDeleteKeys(
455 attestation::AttestationKeyType key_type
,
456 const std::string
& user_id
,
457 const std::string
& key_prefix
,
458 const BoolDBusMethodCallback
& callback
) {
459 base::MessageLoop::current()->PostTask(
460 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false));
463 void FakeCryptohomeClient::GetKeyDataEx(
464 const cryptohome::AccountIdentifier
& id
,
465 const cryptohome::AuthorizationRequest
& auth
,
466 const cryptohome::GetKeyDataRequest
& request
,
467 const ProtobufMethodCallback
& callback
) {
468 cryptohome::BaseReply reply
;
469 reply
.MutableExtension(cryptohome::GetKeyDataReply::reply
);
470 ReturnProtobufMethodCallback(reply
, callback
);
473 void FakeCryptohomeClient::CheckKeyEx(
474 const cryptohome::AccountIdentifier
& id
,
475 const cryptohome::AuthorizationRequest
& auth
,
476 const cryptohome::CheckKeyRequest
& request
,
477 const ProtobufMethodCallback
& callback
) {
478 cryptohome::BaseReply reply
;
479 ReturnProtobufMethodCallback(reply
, callback
);
482 void FakeCryptohomeClient::MountEx(
483 const cryptohome::AccountIdentifier
& id
,
484 const cryptohome::AuthorizationRequest
& auth
,
485 const cryptohome::MountRequest
& request
,
486 const ProtobufMethodCallback
& callback
) {
487 cryptohome::BaseReply reply
;
488 cryptohome::MountReply
* mount
=
489 reply
.MutableExtension(cryptohome::MountReply::reply
);
490 mount
->set_sanitized_username(GetStubSanitizedUsername(id
.email()));
491 ReturnProtobufMethodCallback(reply
, callback
);
494 void FakeCryptohomeClient::AddKeyEx(
495 const cryptohome::AccountIdentifier
& id
,
496 const cryptohome::AuthorizationRequest
& auth
,
497 const cryptohome::AddKeyRequest
& request
,
498 const ProtobufMethodCallback
& callback
) {
499 cryptohome::BaseReply reply
;
500 ReturnProtobufMethodCallback(reply
, callback
);
503 void FakeCryptohomeClient::RemoveKeyEx(
504 const cryptohome::AccountIdentifier
& id
,
505 const cryptohome::AuthorizationRequest
& auth
,
506 const cryptohome::RemoveKeyRequest
& request
,
507 const ProtobufMethodCallback
& callback
) {
508 cryptohome::BaseReply reply
;
509 ReturnProtobufMethodCallback(reply
, callback
);
512 void FakeCryptohomeClient::UpdateKeyEx(
513 const cryptohome::AccountIdentifier
& id
,
514 const cryptohome::AuthorizationRequest
& auth
,
515 const cryptohome::UpdateKeyRequest
& request
,
516 const ProtobufMethodCallback
& callback
) {
517 cryptohome::BaseReply reply
;
518 ReturnProtobufMethodCallback(reply
, callback
);
521 void FakeCryptohomeClient::GetBootAttribute(
522 const cryptohome::GetBootAttributeRequest
& request
,
523 const ProtobufMethodCallback
& callback
) {
524 cryptohome::BaseReply reply
;
525 cryptohome::GetBootAttributeReply
* attr_reply
=
526 reply
.MutableExtension(cryptohome::GetBootAttributeReply::reply
);
527 attr_reply
->set_value("");
528 ReturnProtobufMethodCallback(reply
, callback
);
531 void FakeCryptohomeClient::SetBootAttribute(
532 const cryptohome::SetBootAttributeRequest
& request
,
533 const ProtobufMethodCallback
& callback
) {
534 cryptohome::BaseReply reply
;
535 ReturnProtobufMethodCallback(reply
, callback
);
538 void FakeCryptohomeClient::FlushAndSignBootAttributes(
539 const cryptohome::FlushAndSignBootAttributesRequest
& request
,
540 const ProtobufMethodCallback
& callback
) {
541 cryptohome::BaseReply reply
;
542 ReturnProtobufMethodCallback(reply
, callback
);
545 void FakeCryptohomeClient::SetServiceIsAvailable(bool is_available
) {
546 service_is_available_
= is_available
;
548 std::vector
<WaitForServiceToBeAvailableCallback
> callbacks
;
549 callbacks
.swap(pending_wait_for_service_to_be_available_callbacks_
);
550 for (size_t i
= 0; i
< callbacks
.size(); ++i
)
551 callbacks
[i
].Run(is_available
);
556 std::vector
<uint8
> FakeCryptohomeClient::GetStubSystemSalt() {
557 const char kStubSystemSalt
[] = "stub_system_salt";
558 return std::vector
<uint8
>(kStubSystemSalt
,
559 kStubSystemSalt
+ arraysize(kStubSystemSalt
) - 1);
562 void FakeCryptohomeClient::ReturnProtobufMethodCallback(
563 const cryptohome::BaseReply
& reply
,
564 const ProtobufMethodCallback
& callback
) {
565 base::MessageLoop::current()->PostTask(
568 DBUS_METHOD_CALL_SUCCESS
,
573 void FakeCryptohomeClient::ReturnAsyncMethodResult(
574 const AsyncMethodCallback
& callback
,
576 base::MessageLoop::current()->PostTask(
578 base::Bind(&FakeCryptohomeClient::ReturnAsyncMethodResultInternal
,
579 weak_ptr_factory_
.GetWeakPtr(),
584 void FakeCryptohomeClient::ReturnAsyncMethodResultInternal(
585 const AsyncMethodCallback
& callback
,
587 callback
.Run(async_call_id_
);
588 if (!returns_data
&& !async_call_status_handler_
.is_null()) {
589 base::MessageLoop::current()->PostTask(
591 base::Bind(async_call_status_handler_
,
594 cryptohome::MOUNT_ERROR_NONE
));
595 } else if (returns_data
&& !async_call_status_data_handler_
.is_null()) {
596 base::MessageLoop::current()->PostTask(
598 base::Bind(async_call_status_data_handler_
,
606 } // namespace chromeos