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 unmount_result_(true),
27 system_salt_(GetStubSystemSalt()),
28 weak_ptr_factory_(this) {
29 base::FilePath cache_path
;
30 locked_
= PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES
, &cache_path
) &&
31 base::PathExists(cache_path
);
34 FakeCryptohomeClient::~FakeCryptohomeClient() {}
36 void FakeCryptohomeClient::Init(dbus::Bus
* bus
) {
39 void FakeCryptohomeClient::SetAsyncCallStatusHandlers(
40 const AsyncCallStatusHandler
& handler
,
41 const AsyncCallStatusWithDataHandler
& data_handler
) {
42 async_call_status_handler_
= handler
;
43 async_call_status_data_handler_
= data_handler
;
46 void FakeCryptohomeClient::ResetAsyncCallStatusHandlers() {
47 async_call_status_handler_
.Reset();
48 async_call_status_data_handler_
.Reset();
51 void FakeCryptohomeClient::WaitForServiceToBeAvailable(
52 const WaitForServiceToBeAvailableCallback
& callback
) {
53 if (service_is_available_
) {
54 base::MessageLoop::current()->PostTask(FROM_HERE
,
55 base::Bind(callback
, true));
57 pending_wait_for_service_to_be_available_callbacks_
.push_back(callback
);
61 void FakeCryptohomeClient::IsMounted(
62 const BoolDBusMethodCallback
& callback
) {
63 base::MessageLoop::current()->PostTask(
64 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
67 bool FakeCryptohomeClient::Unmount(bool* success
) {
68 *success
= unmount_result_
;
72 void FakeCryptohomeClient::AsyncCheckKey(
73 const std::string
& username
,
74 const std::string
& key
,
75 const AsyncMethodCallback
& callback
) {
76 ReturnAsyncMethodResult(callback
, false);
79 void FakeCryptohomeClient::AsyncMigrateKey(
80 const std::string
& username
,
81 const std::string
& from_key
,
82 const std::string
& to_key
,
83 const AsyncMethodCallback
& callback
) {
84 ReturnAsyncMethodResult(callback
, false);
87 void FakeCryptohomeClient::AsyncRemove(
88 const std::string
& username
,
89 const AsyncMethodCallback
& callback
) {
90 ReturnAsyncMethodResult(callback
, false);
93 void FakeCryptohomeClient::GetSystemSalt(
94 const GetSystemSaltCallback
& callback
) {
95 base::MessageLoop::current()->PostTask(
97 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, system_salt_
));
100 void FakeCryptohomeClient::GetSanitizedUsername(
101 const std::string
& username
,
102 const StringDBusMethodCallback
& callback
) {
103 // Even for stub implementation we have to return different values so that
104 // multi-profiles would work.
105 std::string sanitized_username
= GetStubSanitizedUsername(username
);
106 base::MessageLoop::current()->PostTask(
108 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, sanitized_username
));
111 std::string
FakeCryptohomeClient::BlockingGetSanitizedUsername(
112 const std::string
& username
) {
113 return GetStubSanitizedUsername(username
);
116 void FakeCryptohomeClient::AsyncMount(const std::string
& username
,
117 const std::string
& key
,
119 const AsyncMethodCallback
& callback
) {
120 ReturnAsyncMethodResult(callback
, false);
123 void FakeCryptohomeClient::AsyncAddKey(
124 const std::string
& username
,
125 const std::string
& key
,
126 const std::string
& new_key
,
127 const AsyncMethodCallback
& callback
) {
128 ReturnAsyncMethodResult(callback
, false);
131 void FakeCryptohomeClient::AsyncMountGuest(
132 const AsyncMethodCallback
& callback
) {
133 ReturnAsyncMethodResult(callback
, false);
136 void FakeCryptohomeClient::AsyncMountPublic(
137 const std::string
& public_mount_id
,
139 const AsyncMethodCallback
& callback
) {
140 ReturnAsyncMethodResult(callback
, false);
143 void FakeCryptohomeClient::TpmIsReady(
144 const BoolDBusMethodCallback
& callback
) {
145 base::MessageLoop::current()->PostTask(
146 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
149 void FakeCryptohomeClient::TpmIsEnabled(
150 const BoolDBusMethodCallback
& callback
) {
151 base::MessageLoop::current()->PostTask(
152 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
155 bool FakeCryptohomeClient::CallTpmIsEnabledAndBlock(bool* enabled
) {
160 void FakeCryptohomeClient::TpmGetPassword(
161 const StringDBusMethodCallback
& callback
) {
162 const char kStubTpmPassword
[] = "Stub-TPM-password";
163 base::MessageLoop::current()->PostTask(
165 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
,
166 std::string(kStubTpmPassword
)));
169 void FakeCryptohomeClient::TpmIsOwned(
170 const BoolDBusMethodCallback
& callback
) {
171 base::MessageLoop::current()->PostTask(
172 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
175 bool FakeCryptohomeClient::CallTpmIsOwnedAndBlock(bool* owned
) {
180 void FakeCryptohomeClient::TpmIsBeingOwned(
181 const BoolDBusMethodCallback
& callback
) {
182 base::MessageLoop::current()->PostTask(
183 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
186 bool FakeCryptohomeClient::CallTpmIsBeingOwnedAndBlock(bool* owning
) {
191 void FakeCryptohomeClient::TpmCanAttemptOwnership(
192 const VoidDBusMethodCallback
& callback
) {
193 base::MessageLoop::current()->PostTask(
194 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
));
197 void FakeCryptohomeClient::TpmClearStoredPassword(
198 const VoidDBusMethodCallback
& callback
) {
199 base::MessageLoop::current()->PostTask(
200 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
));
203 bool FakeCryptohomeClient::CallTpmClearStoredPasswordAndBlock() {
207 void FakeCryptohomeClient::Pkcs11IsTpmTokenReady(
208 const BoolDBusMethodCallback
& callback
) {
209 base::MessageLoop::current()->PostTask(
210 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
213 void FakeCryptohomeClient::Pkcs11GetTpmTokenInfo(
214 const Pkcs11GetTpmTokenInfoCallback
& callback
) {
215 const char kStubTPMTokenName
[] = "StubTPMTokenName";
216 const char kStubUserPin
[] = "012345";
217 const int kStubSlot
= 0;
218 base::MessageLoop::current()->PostTask(
221 DBUS_METHOD_CALL_SUCCESS
,
222 std::string(kStubTPMTokenName
),
223 std::string(kStubUserPin
),
227 void FakeCryptohomeClient::Pkcs11GetTpmTokenInfoForUser(
228 const std::string
& username
,
229 const Pkcs11GetTpmTokenInfoCallback
& callback
) {
230 Pkcs11GetTpmTokenInfo(callback
);
233 bool FakeCryptohomeClient::InstallAttributesGet(const std::string
& name
,
234 std::vector
<uint8
>* value
,
236 if (install_attrs_
.find(name
) != install_attrs_
.end()) {
237 *value
= install_attrs_
[name
];
246 bool FakeCryptohomeClient::InstallAttributesSet(
247 const std::string
& name
,
248 const std::vector
<uint8
>& value
,
250 install_attrs_
[name
] = value
;
255 bool FakeCryptohomeClient::InstallAttributesFinalize(bool* successful
) {
259 // Persist the install attributes so that they can be reloaded if the
260 // browser is restarted. This is used for ease of development when device
261 // enrollment is required.
262 // The cryptohome::SerializedInstallAttributes protobuf lives in
263 // chrome/browser/chromeos, so it can't be used directly here; use the
264 // low-level protobuf API instead to just write the name-value pairs.
265 // The cache file is read by EnterpriseInstallAttributes::ReadCacheFile.
266 base::FilePath cache_path
;
267 if (!PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES
, &cache_path
))
272 // |result| can be used only after the StringOutputStream goes out of
274 google::protobuf::io::StringOutputStream
result_stream(&result
);
275 google::protobuf::io::CodedOutputStream
result_output(&result_stream
);
277 // These tags encode a variable-length value on the wire, which can be
278 // used to encode strings, bytes and messages. We only needs constants
279 // for tag numbers 1 and 2 (see install_attributes.proto).
280 const int kVarLengthTag1
= (1 << 3) | 0x2;
281 const int kVarLengthTag2
= (2 << 3) | 0x2;
283 typedef std::map
<std::string
, std::vector
<uint8
> >::const_iterator Iter
;
284 for (Iter it
= install_attrs_
.begin(); it
!= install_attrs_
.end(); ++it
) {
287 google::protobuf::io::StringOutputStream
attr_stream(&attr
);
288 google::protobuf::io::CodedOutputStream
attr_output(&attr_stream
);
290 attr_output
.WriteVarint32(kVarLengthTag1
);
291 attr_output
.WriteVarint32(it
->first
.size());
292 attr_output
.WriteString(it
->first
);
293 attr_output
.WriteVarint32(kVarLengthTag2
);
294 attr_output
.WriteVarint32(it
->second
.size());
295 attr_output
.WriteRaw(it
->second
.data(), it
->second
.size());
298 // Two CodedOutputStreams are needed because inner messages must be
299 // prefixed by their total length, which can't be easily computed before
300 // writing their tags and values.
301 result_output
.WriteVarint32(kVarLengthTag2
);
302 result_output
.WriteVarint32(attr
.size());
303 result_output
.WriteRaw(attr
.data(), attr
.size());
307 // The real implementation does a blocking wait on the dbus call; the fake
308 // implementation must have this file written before returning.
309 base::ThreadRestrictions::ScopedAllowIO allow_io
;
310 base::WriteFile(cache_path
, result
.data(), result
.size());
315 void FakeCryptohomeClient::InstallAttributesIsReady(
316 const BoolDBusMethodCallback
& callback
) {
317 base::MessageLoop::current()->PostTask(
318 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
321 bool FakeCryptohomeClient::InstallAttributesIsInvalid(bool* is_invalid
) {
326 bool FakeCryptohomeClient::InstallAttributesIsFirstInstall(
327 bool* is_first_install
) {
328 *is_first_install
= !locked_
;
332 void FakeCryptohomeClient::TpmAttestationIsPrepared(
333 const BoolDBusMethodCallback
& callback
) {
334 base::MessageLoop::current()->PostTask(
335 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
338 void FakeCryptohomeClient::TpmAttestationIsEnrolled(
339 const BoolDBusMethodCallback
& callback
) {
340 base::MessageLoop::current()->PostTask(
341 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, true));
344 void FakeCryptohomeClient::AsyncTpmAttestationCreateEnrollRequest(
345 chromeos::attestation::PrivacyCAType pca_type
,
346 const AsyncMethodCallback
& callback
) {
347 ReturnAsyncMethodResult(callback
, true);
350 void FakeCryptohomeClient::AsyncTpmAttestationEnroll(
351 chromeos::attestation::PrivacyCAType pca_type
,
352 const std::string
& pca_response
,
353 const AsyncMethodCallback
& callback
) {
354 ReturnAsyncMethodResult(callback
, false);
357 void FakeCryptohomeClient::AsyncTpmAttestationCreateCertRequest(
358 chromeos::attestation::PrivacyCAType pca_type
,
359 attestation::AttestationCertificateProfile certificate_profile
,
360 const std::string
& user_id
,
361 const std::string
& request_origin
,
362 const AsyncMethodCallback
& callback
) {
363 ReturnAsyncMethodResult(callback
, true);
366 void FakeCryptohomeClient::AsyncTpmAttestationFinishCertRequest(
367 const std::string
& pca_response
,
368 attestation::AttestationKeyType key_type
,
369 const std::string
& user_id
,
370 const std::string
& key_name
,
371 const AsyncMethodCallback
& callback
) {
372 ReturnAsyncMethodResult(callback
, true);
375 void FakeCryptohomeClient::TpmAttestationDoesKeyExist(
376 attestation::AttestationKeyType key_type
,
377 const std::string
& user_id
,
378 const std::string
& key_name
,
379 const BoolDBusMethodCallback
& callback
) {
380 base::MessageLoop::current()->PostTask(
381 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false));
384 void FakeCryptohomeClient::TpmAttestationGetCertificate(
385 attestation::AttestationKeyType key_type
,
386 const std::string
& user_id
,
387 const std::string
& key_name
,
388 const DataMethodCallback
& callback
) {
389 base::MessageLoop::current()->PostTask(
391 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false, std::string()));
394 void FakeCryptohomeClient::TpmAttestationGetPublicKey(
395 attestation::AttestationKeyType key_type
,
396 const std::string
& user_id
,
397 const std::string
& key_name
,
398 const DataMethodCallback
& callback
) {
399 base::MessageLoop::current()->PostTask(
401 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false, std::string()));
404 void FakeCryptohomeClient::TpmAttestationRegisterKey(
405 attestation::AttestationKeyType key_type
,
406 const std::string
& user_id
,
407 const std::string
& key_name
,
408 const AsyncMethodCallback
& callback
) {
409 ReturnAsyncMethodResult(callback
, true);
412 void FakeCryptohomeClient::TpmAttestationSignEnterpriseChallenge(
413 attestation::AttestationKeyType key_type
,
414 const std::string
& user_id
,
415 const std::string
& key_name
,
416 const std::string
& domain
,
417 const std::string
& device_id
,
418 attestation::AttestationChallengeOptions options
,
419 const std::string
& challenge
,
420 const AsyncMethodCallback
& callback
) {
421 ReturnAsyncMethodResult(callback
, true);
424 void FakeCryptohomeClient::TpmAttestationSignSimpleChallenge(
425 attestation::AttestationKeyType key_type
,
426 const std::string
& user_id
,
427 const std::string
& key_name
,
428 const std::string
& challenge
,
429 const AsyncMethodCallback
& callback
) {
430 ReturnAsyncMethodResult(callback
, true);
433 void FakeCryptohomeClient::TpmAttestationGetKeyPayload(
434 attestation::AttestationKeyType key_type
,
435 const std::string
& user_id
,
436 const std::string
& key_name
,
437 const DataMethodCallback
& callback
) {
438 base::MessageLoop::current()->PostTask(
440 base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false, std::string()));
443 void FakeCryptohomeClient::TpmAttestationSetKeyPayload(
444 attestation::AttestationKeyType key_type
,
445 const std::string
& user_id
,
446 const std::string
& key_name
,
447 const std::string
& payload
,
448 const BoolDBusMethodCallback
& callback
) {
449 base::MessageLoop::current()->PostTask(
450 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false));
453 void FakeCryptohomeClient::TpmAttestationDeleteKeys(
454 attestation::AttestationKeyType key_type
,
455 const std::string
& user_id
,
456 const std::string
& key_prefix
,
457 const BoolDBusMethodCallback
& callback
) {
458 base::MessageLoop::current()->PostTask(
459 FROM_HERE
, base::Bind(callback
, DBUS_METHOD_CALL_SUCCESS
, false));
462 void FakeCryptohomeClient::GetKeyDataEx(
463 const cryptohome::AccountIdentifier
& id
,
464 const cryptohome::AuthorizationRequest
& auth
,
465 const cryptohome::GetKeyDataRequest
& request
,
466 const ProtobufMethodCallback
& callback
) {
467 cryptohome::BaseReply reply
;
468 reply
.MutableExtension(cryptohome::GetKeyDataReply::reply
);
469 ReturnProtobufMethodCallback(reply
, callback
);
472 void FakeCryptohomeClient::CheckKeyEx(
473 const cryptohome::AccountIdentifier
& id
,
474 const cryptohome::AuthorizationRequest
& auth
,
475 const cryptohome::CheckKeyRequest
& request
,
476 const ProtobufMethodCallback
& callback
) {
477 cryptohome::BaseReply reply
;
478 ReturnProtobufMethodCallback(reply
, callback
);
481 void FakeCryptohomeClient::MountEx(
482 const cryptohome::AccountIdentifier
& id
,
483 const cryptohome::AuthorizationRequest
& auth
,
484 const cryptohome::MountRequest
& request
,
485 const ProtobufMethodCallback
& callback
) {
486 cryptohome::BaseReply reply
;
487 cryptohome::MountReply
* mount
=
488 reply
.MutableExtension(cryptohome::MountReply::reply
);
489 mount
->set_sanitized_username(GetStubSanitizedUsername(id
.email()));
490 ReturnProtobufMethodCallback(reply
, callback
);
493 void FakeCryptohomeClient::AddKeyEx(
494 const cryptohome::AccountIdentifier
& id
,
495 const cryptohome::AuthorizationRequest
& auth
,
496 const cryptohome::AddKeyRequest
& request
,
497 const ProtobufMethodCallback
& callback
) {
498 cryptohome::BaseReply reply
;
499 ReturnProtobufMethodCallback(reply
, callback
);
502 void FakeCryptohomeClient::RemoveKeyEx(
503 const cryptohome::AccountIdentifier
& id
,
504 const cryptohome::AuthorizationRequest
& auth
,
505 const cryptohome::RemoveKeyRequest
& request
,
506 const ProtobufMethodCallback
& callback
) {
507 cryptohome::BaseReply reply
;
508 ReturnProtobufMethodCallback(reply
, callback
);
511 void FakeCryptohomeClient::UpdateKeyEx(
512 const cryptohome::AccountIdentifier
& id
,
513 const cryptohome::AuthorizationRequest
& auth
,
514 const cryptohome::UpdateKeyRequest
& request
,
515 const ProtobufMethodCallback
& callback
) {
516 cryptohome::BaseReply reply
;
517 ReturnProtobufMethodCallback(reply
, callback
);
520 void FakeCryptohomeClient::GetBootAttribute(
521 const cryptohome::GetBootAttributeRequest
& request
,
522 const ProtobufMethodCallback
& callback
) {
523 cryptohome::BaseReply reply
;
524 cryptohome::GetBootAttributeReply
* attr_reply
=
525 reply
.MutableExtension(cryptohome::GetBootAttributeReply::reply
);
526 attr_reply
->set_value("");
527 ReturnProtobufMethodCallback(reply
, callback
);
530 void FakeCryptohomeClient::SetBootAttribute(
531 const cryptohome::SetBootAttributeRequest
& request
,
532 const ProtobufMethodCallback
& callback
) {
533 cryptohome::BaseReply reply
;
534 ReturnProtobufMethodCallback(reply
, callback
);
537 void FakeCryptohomeClient::FlushAndSignBootAttributes(
538 const cryptohome::FlushAndSignBootAttributesRequest
& request
,
539 const ProtobufMethodCallback
& callback
) {
540 cryptohome::BaseReply reply
;
541 ReturnProtobufMethodCallback(reply
, callback
);
544 void FakeCryptohomeClient::SetServiceIsAvailable(bool is_available
) {
545 service_is_available_
= is_available
;
547 std::vector
<WaitForServiceToBeAvailableCallback
> callbacks
;
548 callbacks
.swap(pending_wait_for_service_to_be_available_callbacks_
);
549 for (size_t i
= 0; i
< callbacks
.size(); ++i
)
550 callbacks
[i
].Run(is_available
);
555 std::vector
<uint8
> FakeCryptohomeClient::GetStubSystemSalt() {
556 const char kStubSystemSalt
[] = "stub_system_salt";
557 return std::vector
<uint8
>(kStubSystemSalt
,
558 kStubSystemSalt
+ arraysize(kStubSystemSalt
) - 1);
561 void FakeCryptohomeClient::ReturnProtobufMethodCallback(
562 const cryptohome::BaseReply
& reply
,
563 const ProtobufMethodCallback
& callback
) {
564 base::MessageLoop::current()->PostTask(
567 DBUS_METHOD_CALL_SUCCESS
,
572 void FakeCryptohomeClient::ReturnAsyncMethodResult(
573 const AsyncMethodCallback
& callback
,
575 base::MessageLoop::current()->PostTask(
577 base::Bind(&FakeCryptohomeClient::ReturnAsyncMethodResultInternal
,
578 weak_ptr_factory_
.GetWeakPtr(),
583 void FakeCryptohomeClient::ReturnAsyncMethodResultInternal(
584 const AsyncMethodCallback
& callback
,
586 callback
.Run(async_call_id_
);
587 if (!returns_data
&& !async_call_status_handler_
.is_null()) {
588 base::MessageLoop::current()->PostTask(
590 base::Bind(async_call_status_handler_
,
593 cryptohome::MOUNT_ERROR_NONE
));
594 } else if (returns_data
&& !async_call_status_data_handler_
.is_null()) {
595 base::MessageLoop::current()->PostTask(
597 base::Bind(async_call_status_data_handler_
,
605 } // namespace chromeos