fake_cryptohome_client.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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/fake_cryptohome_client.h" 6 7#include "base/bind.h" 8#include "base/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 "crypto/nss_util.h" 17#include "third_party/cros_system_api/dbus/service_constants.h" 18#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h" 19#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h" 20#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h" 21 22namespace chromeos { 23 24FakeCryptohomeClient::FakeCryptohomeClient() 25 : service_is_available_(true), 26 async_call_id_(1), 27 tpm_is_ready_counter_(0), 28 unmount_result_(true), 29 system_salt_(GetStubSystemSalt()), 30 weak_ptr_factory_(this) { 31 base::FilePath cache_path; 32 locked_ = PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES, &cache_path) && 33 base::PathExists(cache_path); 34} 35 36FakeCryptohomeClient::~FakeCryptohomeClient() {} 37 38void FakeCryptohomeClient::Init(dbus::Bus* bus) { 39} 40 41void FakeCryptohomeClient::SetAsyncCallStatusHandlers( 42 const AsyncCallStatusHandler& handler, 43 const AsyncCallStatusWithDataHandler& data_handler) { 44 async_call_status_handler_ = handler; 45 async_call_status_data_handler_ = data_handler; 46} 47 48void FakeCryptohomeClient::ResetAsyncCallStatusHandlers() { 49 async_call_status_handler_.Reset(); 50 async_call_status_data_handler_.Reset(); 51} 52 53void FakeCryptohomeClient::WaitForServiceToBeAvailable( 54 const WaitForServiceToBeAvailableCallback& callback) { 55 if (service_is_available_) { 56 base::MessageLoop::current()->PostTask(FROM_HERE, 57 base::Bind(callback, true)); 58 } else { 59 pending_wait_for_service_to_be_available_callbacks_.push_back(callback); 60 } 61} 62 63void FakeCryptohomeClient::IsMounted( 64 const BoolDBusMethodCallback& callback) { 65 base::MessageLoop::current()->PostTask( 66 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 67} 68 69bool FakeCryptohomeClient::Unmount(bool* success) { 70 *success = unmount_result_; 71 return true; 72} 73 74void FakeCryptohomeClient::AsyncCheckKey( 75 const std::string& username, 76 const std::string& key, 77 const AsyncMethodCallback& callback) { 78 ReturnAsyncMethodResult(callback, false); 79} 80 81void FakeCryptohomeClient::AsyncMigrateKey( 82 const std::string& username, 83 const std::string& from_key, 84 const std::string& to_key, 85 const AsyncMethodCallback& callback) { 86 ReturnAsyncMethodResult(callback, false); 87} 88 89void FakeCryptohomeClient::AsyncRemove( 90 const std::string& username, 91 const AsyncMethodCallback& callback) { 92 ReturnAsyncMethodResult(callback, false); 93} 94 95void FakeCryptohomeClient::GetSystemSalt( 96 const GetSystemSaltCallback& callback) { 97 base::MessageLoop::current()->PostTask( 98 FROM_HERE, 99 base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, system_salt_)); 100} 101 102void FakeCryptohomeClient::GetSanitizedUsername( 103 const std::string& username, 104 const StringDBusMethodCallback& callback) { 105 // Even for stub implementation we have to return different values so that 106 // multi-profiles would work. 107 std::string sanitized_username = GetStubSanitizedUsername(username); 108 base::MessageLoop::current()->PostTask( 109 FROM_HERE, 110 base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, sanitized_username)); 111} 112 113std::string FakeCryptohomeClient::BlockingGetSanitizedUsername( 114 const std::string& username) { 115 return GetStubSanitizedUsername(username); 116} 117 118void FakeCryptohomeClient::AsyncMount(const std::string& username, 119 const std::string& key, 120 int flags, 121 const AsyncMethodCallback& callback) { 122 ReturnAsyncMethodResult(callback, false); 123} 124 125void FakeCryptohomeClient::AsyncAddKey( 126 const std::string& username, 127 const std::string& key, 128 const std::string& new_key, 129 const AsyncMethodCallback& callback) { 130 ReturnAsyncMethodResult(callback, false); 131} 132 133void FakeCryptohomeClient::AsyncMountGuest( 134 const AsyncMethodCallback& callback) { 135 ReturnAsyncMethodResult(callback, false); 136} 137 138void FakeCryptohomeClient::AsyncMountPublic( 139 const std::string& public_mount_id, 140 int flags, 141 const AsyncMethodCallback& callback) { 142 ReturnAsyncMethodResult(callback, false); 143} 144 145void FakeCryptohomeClient::TpmIsReady( 146 const BoolDBusMethodCallback& callback) { 147 base::MessageLoop::current()->PostTask( 148 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 149} 150 151void FakeCryptohomeClient::TpmIsEnabled( 152 const BoolDBusMethodCallback& callback) { 153 base::MessageLoop::current()->PostTask( 154 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 155} 156 157bool FakeCryptohomeClient::CallTpmIsEnabledAndBlock(bool* enabled) { 158 *enabled = true; 159 return true; 160} 161 162void FakeCryptohomeClient::TpmGetPassword( 163 const StringDBusMethodCallback& callback) { 164 const char kStubTpmPassword[] = "Stub-TPM-password"; 165 base::MessageLoop::current()->PostTask( 166 FROM_HERE, 167 base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, 168 std::string(kStubTpmPassword))); 169} 170 171void FakeCryptohomeClient::TpmIsOwned( 172 const BoolDBusMethodCallback& callback) { 173 base::MessageLoop::current()->PostTask( 174 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 175} 176 177bool FakeCryptohomeClient::CallTpmIsOwnedAndBlock(bool* owned) { 178 *owned = true; 179 return true; 180} 181 182void FakeCryptohomeClient::TpmIsBeingOwned( 183 const BoolDBusMethodCallback& callback) { 184 base::MessageLoop::current()->PostTask( 185 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 186} 187 188bool FakeCryptohomeClient::CallTpmIsBeingOwnedAndBlock(bool* owning) { 189 *owning = true; 190 return true; 191} 192 193void FakeCryptohomeClient::TpmCanAttemptOwnership( 194 const VoidDBusMethodCallback& callback) { 195 base::MessageLoop::current()->PostTask( 196 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS)); 197} 198 199void FakeCryptohomeClient::TpmClearStoredPassword( 200 const VoidDBusMethodCallback& callback) { 201 base::MessageLoop::current()->PostTask( 202 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS)); 203} 204 205bool FakeCryptohomeClient::CallTpmClearStoredPasswordAndBlock() { 206 return true; 207} 208 209void FakeCryptohomeClient::Pkcs11IsTpmTokenReady( 210 const BoolDBusMethodCallback& callback) { 211 base::MessageLoop::current()->PostTask( 212 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 213} 214 215void FakeCryptohomeClient::Pkcs11GetTpmTokenInfo( 216 const Pkcs11GetTpmTokenInfoCallback& callback) { 217 const char kStubUserPin[] = "012345"; 218 const int kStubSlot = 0; 219 base::MessageLoop::current()->PostTask( 220 FROM_HERE, 221 base::Bind(callback, 222 DBUS_METHOD_CALL_SUCCESS, 223 std::string(crypto::kTestTPMTokenName), 224 std::string(kStubUserPin), 225 kStubSlot)); 226} 227 228void FakeCryptohomeClient::Pkcs11GetTpmTokenInfoForUser( 229 const std::string& username, 230 const Pkcs11GetTpmTokenInfoCallback& callback) { 231 Pkcs11GetTpmTokenInfo(callback); 232} 233 234bool FakeCryptohomeClient::InstallAttributesGet(const std::string& name, 235 std::vector<uint8>* value, 236 bool* successful) { 237 if (install_attrs_.find(name) != install_attrs_.end()) { 238 *value = install_attrs_[name]; 239 *successful = true; 240 } else { 241 value->clear(); 242 *successful = false; 243 } 244 return true; 245} 246 247bool FakeCryptohomeClient::InstallAttributesSet( 248 const std::string& name, 249 const std::vector<uint8>& value, 250 bool* successful) { 251 install_attrs_[name] = value; 252 *successful = true; 253 return true; 254} 255 256bool FakeCryptohomeClient::InstallAttributesFinalize(bool* successful) { 257 locked_ = true; 258 *successful = true; 259 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)) 269 return false; 270 271 std::string result; 272 { 273 // |result| can be used only after the StringOutputStream goes out of 274 // scope. 275 google::protobuf::io::StringOutputStream result_stream(&result); 276 google::protobuf::io::CodedOutputStream result_output(&result_stream); 277 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; 283 284 typedef std::map<std::string, std::vector<uint8> >::const_iterator Iter; 285 for (Iter it = install_attrs_.begin(); it != install_attrs_.end(); ++it) { 286 std::string attr; 287 { 288 google::protobuf::io::StringOutputStream attr_stream(&attr); 289 google::protobuf::io::CodedOutputStream attr_output(&attr_stream); 290 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()); 297 } 298 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()); 305 } 306 } 307 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()); 312 313 return true; 314} 315 316void FakeCryptohomeClient::InstallAttributesIsReady( 317 const BoolDBusMethodCallback& callback) { 318 base::MessageLoop::current()->PostTask( 319 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 320} 321 322bool FakeCryptohomeClient::InstallAttributesIsInvalid(bool* is_invalid) { 323 *is_invalid = false; 324 return true; 325} 326 327bool FakeCryptohomeClient::InstallAttributesIsFirstInstall( 328 bool* is_first_install) { 329 *is_first_install = !locked_; 330 return true; 331} 332 333void FakeCryptohomeClient::TpmAttestationIsPrepared( 334 const BoolDBusMethodCallback& callback) { 335 base::MessageLoop::current()->PostTask( 336 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 337} 338 339void FakeCryptohomeClient::TpmAttestationIsEnrolled( 340 const BoolDBusMethodCallback& callback) { 341 base::MessageLoop::current()->PostTask( 342 FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); 343} 344 345void FakeCryptohomeClient::AsyncTpmAttestationCreateEnrollRequest( 346 chromeos::attestation::PrivacyCAType pca_type, 347 const AsyncMethodCallback& callback) { 348 ReturnAsyncMethodResult(callback, true); 349} 350 351void FakeCryptohomeClient::AsyncTpmAttestationEnroll( 352 chromeos::attestation::PrivacyCAType pca_type, 353 const std::string& pca_response, 354 const AsyncMethodCallback& callback) { 355 ReturnAsyncMethodResult(callback, false); 356} 357 358void 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); 365} 366 367void 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); 374} 375 376void 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)); 383} 384 385void 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( 391 FROM_HERE, 392 base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string())); 393} 394 395void 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( 401 FROM_HERE, 402 base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string())); 403} 404 405void 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); 411} 412 413void 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); 423} 424 425void 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); 432} 433 434void 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( 440 FROM_HERE, 441 base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string())); 442} 443 444void 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)); 452} 453 454void 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)); 461} 462 463void FakeCryptohomeClient::CheckKeyEx( 464 const cryptohome::AccountIdentifier& id, 465 const cryptohome::AuthorizationRequest& auth, 466 const cryptohome::CheckKeyRequest& request, 467 const ProtobufMethodCallback& callback) { 468 cryptohome::BaseReply reply; 469 ReturnProtobufMethodCallback(reply, callback); 470} 471 472void FakeCryptohomeClient::MountEx( 473 const cryptohome::AccountIdentifier& id, 474 const cryptohome::AuthorizationRequest& auth, 475 const cryptohome::MountRequest& request, 476 const ProtobufMethodCallback& callback) { 477 cryptohome::BaseReply reply; 478 cryptohome::MountReply* mount = 479 reply.MutableExtension(cryptohome::MountReply::reply); 480 mount->set_sanitized_username(GetStubSanitizedUsername(id.email())); 481 ReturnProtobufMethodCallback(reply, callback); 482} 483 484void FakeCryptohomeClient::AddKeyEx( 485 const cryptohome::AccountIdentifier& id, 486 const cryptohome::AuthorizationRequest& auth, 487 const cryptohome::AddKeyRequest& request, 488 const ProtobufMethodCallback& callback) { 489 cryptohome::BaseReply reply; 490 ReturnProtobufMethodCallback(reply, callback); 491} 492 493void FakeCryptohomeClient::RemoveKeyEx( 494 const cryptohome::AccountIdentifier& id, 495 const cryptohome::AuthorizationRequest& auth, 496 const cryptohome::RemoveKeyRequest& request, 497 const ProtobufMethodCallback& callback) { 498 cryptohome::BaseReply reply; 499 ReturnProtobufMethodCallback(reply, callback); 500} 501 502void FakeCryptohomeClient::UpdateKeyEx( 503 const cryptohome::AccountIdentifier& id, 504 const cryptohome::AuthorizationRequest& auth, 505 const cryptohome::UpdateKeyRequest& request, 506 const ProtobufMethodCallback& callback) { 507 cryptohome::BaseReply reply; 508 ReturnProtobufMethodCallback(reply, callback); 509} 510 511void FakeCryptohomeClient::GetBootAttribute( 512 const cryptohome::GetBootAttributeRequest& request, 513 const ProtobufMethodCallback& callback) { 514 cryptohome::BaseReply reply; 515 cryptohome::GetBootAttributeReply* attr_reply = 516 reply.MutableExtension(cryptohome::GetBootAttributeReply::reply); 517 attr_reply->set_value(""); 518 ReturnProtobufMethodCallback(reply, callback); 519} 520 521void FakeCryptohomeClient::SetBootAttribute( 522 const cryptohome::SetBootAttributeRequest& request, 523 const ProtobufMethodCallback& callback) { 524 cryptohome::BaseReply reply; 525 ReturnProtobufMethodCallback(reply, callback); 526} 527 528void FakeCryptohomeClient::FlushAndSignBootAttributes( 529 const cryptohome::FlushAndSignBootAttributesRequest& request, 530 const ProtobufMethodCallback& callback) { 531 cryptohome::BaseReply reply; 532 ReturnProtobufMethodCallback(reply, callback); 533} 534 535void FakeCryptohomeClient::SetServiceIsAvailable(bool is_available) { 536 service_is_available_ = is_available; 537 if (is_available) { 538 std::vector<WaitForServiceToBeAvailableCallback> callbacks; 539 callbacks.swap(pending_wait_for_service_to_be_available_callbacks_); 540 for (size_t i = 0; i < callbacks.size(); ++i) 541 callbacks[i].Run(is_available); 542 } 543} 544 545// static 546std::vector<uint8> FakeCryptohomeClient::GetStubSystemSalt() { 547 const char kStubSystemSalt[] = "stub_system_salt"; 548 return std::vector<uint8>(kStubSystemSalt, 549 kStubSystemSalt + arraysize(kStubSystemSalt) - 1); 550} 551 552void FakeCryptohomeClient::ReturnProtobufMethodCallback( 553 const cryptohome::BaseReply& reply, 554 const ProtobufMethodCallback& callback) { 555 base::MessageLoop::current()->PostTask( 556 FROM_HERE, 557 base::Bind(callback, 558 DBUS_METHOD_CALL_SUCCESS, 559 true, 560 reply)); 561} 562 563void FakeCryptohomeClient::ReturnAsyncMethodResult( 564 const AsyncMethodCallback& callback, 565 bool returns_data) { 566 base::MessageLoop::current()->PostTask( 567 FROM_HERE, 568 base::Bind(&FakeCryptohomeClient::ReturnAsyncMethodResultInternal, 569 weak_ptr_factory_.GetWeakPtr(), 570 callback, 571 returns_data)); 572} 573 574void FakeCryptohomeClient::ReturnAsyncMethodResultInternal( 575 const AsyncMethodCallback& callback, 576 bool returns_data) { 577 callback.Run(async_call_id_); 578 if (!returns_data && !async_call_status_handler_.is_null()) { 579 base::MessageLoop::current()->PostTask( 580 FROM_HERE, 581 base::Bind(async_call_status_handler_, 582 async_call_id_, 583 true, 584 cryptohome::MOUNT_ERROR_NONE)); 585 } else if (returns_data && !async_call_status_data_handler_.is_null()) { 586 base::MessageLoop::current()->PostTask( 587 FROM_HERE, 588 base::Bind(async_call_status_data_handler_, 589 async_call_id_, 590 true, 591 std::string())); 592 } 593 ++async_call_id_; 594} 595 596} // namespace chromeos 597