// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chromeos/dbus/cryptohome_client.h" #include "base/bind.h" #include "base/location.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "chromeos/cryptohome/async_method_caller.h" #include "chromeos/dbus/blocking_method_caller.h" #include "chromeos/dbus/cryptohome/key.pb.h" #include "chromeos/dbus/cryptohome/rpc.pb.h" #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_path.h" #include "dbus/object_proxy.h" #include "third_party/cros_system_api/dbus/service_constants.h" namespace chromeos { namespace { // This suffix is appended to user_id to get hash in stub implementation: // stub_hash = "[user_id]-hash"; static const char kUserIdStubHashSuffix[] = "-hash"; // Timeout for TPM operations. On slow machines it should be larger, than // default DBus timeout. TPM operations can take up to 80 seconds, so limit // is 2 minutes. const int kTpmDBusTimeoutMs = 2 * 60 * 1000; // The CryptohomeClient implementation. class CryptohomeClientImpl : public CryptohomeClient { public: CryptohomeClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {} // CryptohomeClient override. virtual void SetAsyncCallStatusHandlers( const AsyncCallStatusHandler& handler, const AsyncCallStatusWithDataHandler& data_handler) OVERRIDE { async_call_status_handler_ = handler; async_call_status_data_handler_ = data_handler; } // CryptohomeClient override. virtual void ResetAsyncCallStatusHandlers() OVERRIDE { async_call_status_handler_.Reset(); async_call_status_data_handler_.Reset(); } // CryptohomeClient override. virtual void WaitForServiceToBeAvailable( const WaitForServiceToBeAvailableCallback& callback) OVERRIDE { proxy_->WaitForServiceToBeAvailable(callback); } // CryptohomeClient override. virtual void IsMounted(const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeIsMounted); CallBoolMethod(&method_call, callback); } // CryptohomeClient override. virtual bool Unmount(bool *success) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeUnmount); return CallBoolMethodAndBlock(&method_call, success); } // CryptohomeClient override. virtual void AsyncCheckKey(const std::string& username, const std::string& key, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncCheckKey); dbus::MessageWriter writer(&method_call); writer.AppendString(username); writer.AppendString(key); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void AsyncMigrateKey(const std::string& username, const std::string& from_key, const std::string& to_key, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncMigrateKey); dbus::MessageWriter writer(&method_call); writer.AppendString(username); writer.AppendString(from_key); writer.AppendString(to_key); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void AsyncRemove(const std::string& username, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncRemove); dbus::MessageWriter writer(&method_call); writer.AppendString(username); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void GetSystemSalt(const GetSystemSaltCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetSystemSalt); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnGetSystemSalt, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override, virtual void GetSanitizedUsername( const std::string& username, const StringDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetSanitizedUsername); dbus::MessageWriter writer(&method_call); writer.AppendString(username); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnStringMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual std::string BlockingGetSanitizedUsername( const std::string& username) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeGetSanitizedUsername); dbus::MessageWriter writer(&method_call); writer.AppendString(username); scoped_ptr<dbus::Response> response = blocking_method_caller_->CallMethodAndBlock(&method_call); std::string sanitized_username; if (response) { dbus::MessageReader reader(response.get()); reader.PopString(&sanitized_username); } return sanitized_username; } // CryptohomeClient override. virtual void AsyncMount(const std::string& username, const std::string& key, int flags, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncMount); dbus::MessageWriter writer(&method_call); writer.AppendString(username); writer.AppendString(key); writer.AppendBool(flags & cryptohome::CREATE_IF_MISSING); writer.AppendBool(flags & cryptohome::ENSURE_EPHEMERAL); // deprecated_tracked_subdirectories writer.AppendArrayOfStrings(std::vector<std::string>()); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void AsyncAddKey(const std::string& username, const std::string& key, const std::string& new_key, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncAddKey); dbus::MessageWriter writer(&method_call); writer.AppendString(username); writer.AppendString(key); writer.AppendString(new_key); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void AsyncMountGuest(const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncMountGuest); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void AsyncMountPublic(const std::string& public_mount_id, int flags, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncMountPublic); dbus::MessageWriter writer(&method_call); writer.AppendString(public_mount_id); writer.AppendBool(flags & cryptohome::CREATE_IF_MISSING); writer.AppendBool(flags & cryptohome::ENSURE_EPHEMERAL); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmIsReady(const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsReady); CallBoolMethod(&method_call, callback); } // CryptohomeClient override. virtual void TpmIsEnabled(const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsEnabled); CallBoolMethod(&method_call, callback); } // CryptohomeClient override. // TODO(hashimoto): Remove this method. crbug.com/141006 virtual bool CallTpmIsEnabledAndBlock(bool* enabled) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsEnabled); return CallBoolMethodAndBlock(&method_call, enabled); } // CryptohomeClient override. virtual void TpmGetPassword( const StringDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmGetPassword); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnStringMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmIsOwned(const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsOwned); CallBoolMethod(&method_call, callback); } // CryptohomeClient override. // TODO(hashimoto): Remove this method. crbug.com/141012 virtual bool CallTpmIsOwnedAndBlock(bool* owned) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsOwned); return CallBoolMethodAndBlock(&method_call, owned); } // CryptohomeClient override. virtual void TpmIsBeingOwned(const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsBeingOwned); CallBoolMethod(&method_call, callback); } // CryptohomeClient override. // TODO(hashimoto): Remove this method. crbug.com/141011 virtual bool CallTpmIsBeingOwnedAndBlock(bool* owning) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsBeingOwned); return CallBoolMethodAndBlock(&method_call, owning); } // CryptohomeClient override. virtual void TpmCanAttemptOwnership( const VoidDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmCanAttemptOwnership); CallVoidMethod(&method_call, callback); } // CryptohomeClient overrides. virtual void TpmClearStoredPassword(const VoidDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmClearStoredPassword); CallVoidMethod(&method_call, callback); } // CryptohomeClient override. // TODO(hashimoto): Remove this method. crbug.com/141010 virtual bool CallTpmClearStoredPasswordAndBlock() OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmClearStoredPassword); scoped_ptr<dbus::Response> response( blocking_method_caller_->CallMethodAndBlock(&method_call)); return response.get() != NULL; } // CryptohomeClient override. virtual void Pkcs11IsTpmTokenReady(const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomePkcs11IsTpmTokenReady); CallBoolMethod(&method_call, callback); } // CryptohomeClient override. virtual void Pkcs11GetTpmTokenInfo( const Pkcs11GetTpmTokenInfoCallback& callback) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomePkcs11GetTpmTokenInfo); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs , base::Bind( &CryptohomeClientImpl::OnPkcs11GetTpmTokenInfo, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void Pkcs11GetTpmTokenInfoForUser( const std::string& user_email, const Pkcs11GetTpmTokenInfoCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomePkcs11GetTpmTokenInfoForUser); dbus::MessageWriter writer(&method_call); writer.AppendString(user_email); proxy_->CallMethod( &method_call, kTpmDBusTimeoutMs , base::Bind( &CryptohomeClientImpl::OnPkcs11GetTpmTokenInfoForUser, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual bool InstallAttributesGet(const std::string& name, std::vector<uint8>* value, bool* successful) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeInstallAttributesGet); dbus::MessageWriter writer(&method_call); writer.AppendString(name); scoped_ptr<dbus::Response> response( blocking_method_caller_->CallMethodAndBlock(&method_call)); if (!response.get()) return false; dbus::MessageReader reader(response.get()); const uint8* bytes = NULL; size_t length = 0; if (!reader.PopArrayOfBytes(&bytes, &length) || !reader.PopBool(successful)) return false; value->assign(bytes, bytes + length); return true; } // CryptohomeClient override. virtual bool InstallAttributesSet(const std::string& name, const std::vector<uint8>& value, bool* successful) OVERRIDE { dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeInstallAttributesSet); dbus::MessageWriter writer(&method_call); writer.AppendString(name); writer.AppendArrayOfBytes(value.data(), value.size()); return CallBoolMethodAndBlock(&method_call, successful); } // CryptohomeClient override. virtual bool InstallAttributesFinalize(bool* successful) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeInstallAttributesFinalize); return CallBoolMethodAndBlock(&method_call, successful); } // CryptohomeClient override. virtual void InstallAttributesIsReady(const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeInstallAttributesIsReady); return CallBoolMethod(&method_call, callback); } // CryptohomeClient override. virtual bool InstallAttributesIsInvalid(bool* is_invalid) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeInstallAttributesIsInvalid); return CallBoolMethodAndBlock(&method_call, is_invalid); } // CryptohomeClient override. virtual bool InstallAttributesIsFirstInstall( bool* is_first_install) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeInstallAttributesIsFirstInstall); return CallBoolMethodAndBlock(&method_call, is_first_install); } // CryptohomeClient override. virtual void TpmAttestationIsPrepared( const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsAttestationPrepared); return CallBoolMethod(&method_call, callback); } // CryptohomeClient override. virtual void TpmAttestationIsEnrolled( const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmIsAttestationEnrolled); return CallBoolMethod(&method_call, callback); } // CryptohomeClient override. virtual void AsyncTpmAttestationCreateEnrollRequest( attestation::PrivacyCAType pca_type, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncTpmAttestationCreateEnrollRequest); dbus::MessageWriter writer(&method_call); writer.AppendInt32(pca_type); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void AsyncTpmAttestationEnroll( attestation::PrivacyCAType pca_type, const std::string& pca_response, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncTpmAttestationEnroll); dbus::MessageWriter writer(&method_call); writer.AppendInt32(pca_type); writer.AppendArrayOfBytes( reinterpret_cast<const uint8*>(pca_response.data()), pca_response.size()); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void AsyncTpmAttestationCreateCertRequest( attestation::PrivacyCAType pca_type, attestation::AttestationCertificateProfile certificate_profile, const std::string& user_id, const std::string& request_origin, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncTpmAttestationCreateCertRequest); dbus::MessageWriter writer(&method_call); writer.AppendInt32(pca_type); writer.AppendInt32(certificate_profile); writer.AppendString(user_id); writer.AppendString(request_origin); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void AsyncTpmAttestationFinishCertRequest( const std::string& pca_response, attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeAsyncTpmAttestationFinishCertRequest); dbus::MessageWriter writer(&method_call); writer.AppendArrayOfBytes( reinterpret_cast<const uint8*>(pca_response.data()), pca_response.size()); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmAttestationDoesKeyExist( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationDoesKeyExist); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); CallBoolMethod(&method_call, callback); } // CryptohomeClient override. virtual void TpmAttestationGetCertificate( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const DataMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationGetCertificate); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnDataMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmAttestationGetPublicKey( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const DataMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationGetPublicKey); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnDataMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmAttestationRegisterKey( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationRegisterKey); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmAttestationSignEnterpriseChallenge( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const std::string& domain, const std::string& device_id, attestation::AttestationChallengeOptions options, const std::string& challenge, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationSignEnterpriseChallenge); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); writer.AppendString(domain); writer.AppendArrayOfBytes(reinterpret_cast<const uint8*>(device_id.data()), device_id.size()); bool include_signed_public_key = (options & attestation::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY); writer.AppendBool(include_signed_public_key); writer.AppendArrayOfBytes(reinterpret_cast<const uint8*>(challenge.data()), challenge.size()); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmAttestationSignSimpleChallenge( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const std::string& challenge, const AsyncMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationSignSimpleChallenge); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); writer.AppendArrayOfBytes(reinterpret_cast<const uint8*>(challenge.data()), challenge.size()); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmAttestationGetKeyPayload( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const DataMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationGetKeyPayload); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnDataMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } // CryptohomeClient override. virtual void TpmAttestationSetKeyPayload( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_name, const std::string& payload, const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationSetKeyPayload); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_name); writer.AppendArrayOfBytes(reinterpret_cast<const uint8*>(payload.data()), payload.size()); CallBoolMethod(&method_call, callback); } // CryptohomeClient override. virtual void TpmAttestationDeleteKeys( attestation::AttestationKeyType key_type, const std::string& user_id, const std::string& key_prefix, const BoolDBusMethodCallback& callback) OVERRIDE { dbus::MethodCall method_call( cryptohome::kCryptohomeInterface, cryptohome::kCryptohomeTpmAttestationDeleteKeys); dbus::MessageWriter writer(&method_call); bool is_user_specific = (key_type == attestation::KEY_USER); writer.AppendBool(is_user_specific); writer.AppendString(user_id); writer.AppendString(key_prefix); CallBoolMethod(&method_call, callback); } virtual void CheckKeyEx( const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::CheckKeyRequest& request, const ProtobufMethodCallback& callback) OVERRIDE { const char* method_name = cryptohome::kCryptohomeCheckKeyEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); dbus::MessageWriter writer(&method_call); writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } virtual void MountEx( const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::MountRequest& request, const ProtobufMethodCallback& callback) OVERRIDE { const char* method_name = cryptohome::kCryptohomeMountEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); dbus::MessageWriter writer(&method_call); writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } virtual void AddKeyEx( const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::AddKeyRequest& request, const ProtobufMethodCallback& callback) OVERRIDE { const char* method_name = cryptohome::kCryptohomeAddKeyEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); dbus::MessageWriter writer(&method_call); writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs, base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } virtual void UpdateKeyEx( const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::UpdateKeyRequest& request, const ProtobufMethodCallback& callback) OVERRIDE { const char* method_name = cryptohome::kCryptohomeUpdateKeyEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); dbus::MessageWriter writer(&method_call); writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } virtual void RemoveKeyEx(const cryptohome::AccountIdentifier& id, const cryptohome::AuthorizationRequest& auth, const cryptohome::RemoveKeyRequest& request, const ProtobufMethodCallback& callback) OVERRIDE { const char* method_name = cryptohome::kCryptohomeRemoveKeyEx; dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name); dbus::MessageWriter writer(&method_call); writer.AppendProtoAsArrayOfBytes(id); writer.AppendProtoAsArrayOfBytes(auth); writer.AppendProtoAsArrayOfBytes(request); proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } protected: virtual void Init(dbus::Bus* bus) OVERRIDE { proxy_ = bus->GetObjectProxy( cryptohome::kCryptohomeServiceName, dbus::ObjectPath(cryptohome::kCryptohomeServicePath)); blocking_method_caller_.reset(new BlockingMethodCaller(bus, proxy_)); proxy_->ConnectToSignal(cryptohome::kCryptohomeInterface, cryptohome::kSignalAsyncCallStatus, base::Bind(&CryptohomeClientImpl::OnAsyncCallStatus, weak_ptr_factory_.GetWeakPtr()), base::Bind(&CryptohomeClientImpl::OnSignalConnected, weak_ptr_factory_.GetWeakPtr())); proxy_->ConnectToSignal( cryptohome::kCryptohomeInterface, cryptohome::kSignalAsyncCallStatusWithData, base::Bind(&CryptohomeClientImpl::OnAsyncCallStatusWithData, weak_ptr_factory_.GetWeakPtr()), base::Bind(&CryptohomeClientImpl::OnSignalConnected, weak_ptr_factory_.GetWeakPtr())); } private: // Handles the result of AsyncXXX methods. void OnAsyncMethodCall(const AsyncMethodCallback& callback, dbus::Response* response) { if (!response) return; dbus::MessageReader reader(response); int async_id = 0; if (!reader.PopInt32(&async_id)) { LOG(ERROR) << "Invalid response: " << response->ToString(); return; } callback.Run(async_id); } // Handles the result of GetSystemSalt(). void OnGetSystemSalt(const GetSystemSaltCallback& callback, dbus::Response* response) { if (!response) { callback.Run(DBUS_METHOD_CALL_FAILURE, std::vector<uint8>()); return; } dbus::MessageReader reader(response); const uint8* bytes = NULL; size_t length = 0; if (!reader.PopArrayOfBytes(&bytes, &length)) { callback.Run(DBUS_METHOD_CALL_FAILURE, std::vector<uint8>()); return; } callback.Run(DBUS_METHOD_CALL_SUCCESS, std::vector<uint8>(bytes, bytes + length)); } // Calls a method without result values. void CallVoidMethod(dbus::MethodCall* method_call, const VoidDBusMethodCallback& callback) { proxy_->CallMethod(method_call, kTpmDBusTimeoutMs , base::Bind(&CryptohomeClientImpl::OnVoidMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } void OnVoidMethod(const VoidDBusMethodCallback& callback, dbus::Response* response) { if (!response) { callback.Run(DBUS_METHOD_CALL_FAILURE); return; } callback.Run(DBUS_METHOD_CALL_SUCCESS); } // Calls a method with a bool value reult and block. bool CallBoolMethodAndBlock(dbus::MethodCall* method_call, bool* result) { scoped_ptr<dbus::Response> response( blocking_method_caller_->CallMethodAndBlock(method_call)); if (!response.get()) return false; dbus::MessageReader reader(response.get()); return reader.PopBool(result); } // Calls a method with a bool value result. void CallBoolMethod(dbus::MethodCall* method_call, const BoolDBusMethodCallback& callback) { proxy_->CallMethod(method_call, kTpmDBusTimeoutMs , base::Bind( &CryptohomeClientImpl::OnBoolMethod, weak_ptr_factory_.GetWeakPtr(), callback)); } // Handles responses for methods with a bool value result. void OnBoolMethod(const BoolDBusMethodCallback& callback, dbus::Response* response) { if (!response) { callback.Run(DBUS_METHOD_CALL_FAILURE, false); return; } dbus::MessageReader reader(response); bool result = false; if (!reader.PopBool(&result)) { callback.Run(DBUS_METHOD_CALL_FAILURE, false); LOG(ERROR) << "Invalid response: " << response->ToString(); return; } callback.Run(DBUS_METHOD_CALL_SUCCESS, result); } // Handles responses for methods with a string value result. void OnStringMethod(const StringDBusMethodCallback& callback, dbus::Response* response) { if (!response) { callback.Run(DBUS_METHOD_CALL_FAILURE, std::string()); return; } dbus::MessageReader reader(response); std::string result; if (!reader.PopString(&result)) { callback.Run(DBUS_METHOD_CALL_FAILURE, std::string()); return; } callback.Run(DBUS_METHOD_CALL_SUCCESS, result); } // Handles responses for methods with a bool result and data. void OnDataMethod(const DataMethodCallback& callback, dbus::Response* response) { if (!response) { callback.Run(DBUS_METHOD_CALL_FAILURE, false, std::string()); return; } dbus::MessageReader reader(response); const uint8* data_buffer = NULL; size_t data_length = 0; bool result = false; if (!reader.PopArrayOfBytes(&data_buffer, &data_length) || !reader.PopBool(&result)) { callback.Run(DBUS_METHOD_CALL_FAILURE, false, std::string()); return; } std::string data(reinterpret_cast<const char*>(data_buffer), data_length); callback.Run(DBUS_METHOD_CALL_SUCCESS, result, data); } // Handles responses for methods with a BaseReply protobuf method. void OnBaseReplyMethod(const ProtobufMethodCallback& callback, dbus::Response* response) { cryptohome::BaseReply reply; if (!response) { callback.Run(DBUS_METHOD_CALL_FAILURE, false, reply); return; } dbus::MessageReader reader(response); if (!reader.PopArrayOfBytesAsProto(&reply)) { callback.Run(DBUS_METHOD_CALL_FAILURE, false, reply); return; } callback.Run(DBUS_METHOD_CALL_SUCCESS, true, reply); } // Handles responses for Pkcs11GetTpmTokenInfo. void OnPkcs11GetTpmTokenInfo(const Pkcs11GetTpmTokenInfoCallback& callback, dbus::Response* response) { if (!response) { callback.Run(DBUS_METHOD_CALL_FAILURE, std::string(), std::string(), -1); return; } dbus::MessageReader reader(response); std::string label; std::string user_pin; if (!reader.PopString(&label) || !reader.PopString(&user_pin)) { callback.Run(DBUS_METHOD_CALL_FAILURE, std::string(), std::string(), -1); LOG(ERROR) << "Invalid response: " << response->ToString(); return; } const int kDefaultSlot = 0; callback.Run(DBUS_METHOD_CALL_SUCCESS, label, user_pin, kDefaultSlot); } // Handles responses for Pkcs11GetTpmTokenInfoForUser. void OnPkcs11GetTpmTokenInfoForUser( const Pkcs11GetTpmTokenInfoCallback& callback, dbus::Response* response) { if (!response) { callback.Run(DBUS_METHOD_CALL_FAILURE, std::string(), std::string(), -1); return; } dbus::MessageReader reader(response); std::string label; std::string user_pin; int slot = 0; if (!reader.PopString(&label) || !reader.PopString(&user_pin) || !reader.PopInt32(&slot)) { callback.Run(DBUS_METHOD_CALL_FAILURE, std::string(), std::string(), -1); LOG(ERROR) << "Invalid response: " << response->ToString(); return; } callback.Run(DBUS_METHOD_CALL_SUCCESS, label, user_pin, slot); } // Handles AsyncCallStatus signal. void OnAsyncCallStatus(dbus::Signal* signal) { dbus::MessageReader reader(signal); int async_id = 0; bool return_status = false; int return_code = 0; if (!reader.PopInt32(&async_id) || !reader.PopBool(&return_status) || !reader.PopInt32(&return_code)) { LOG(ERROR) << "Invalid signal: " << signal->ToString(); return; } if (!async_call_status_handler_.is_null()) async_call_status_handler_.Run(async_id, return_status, return_code); } // Handles AsyncCallStatusWithData signal. void OnAsyncCallStatusWithData(dbus::Signal* signal) { dbus::MessageReader reader(signal); int async_id = 0; bool return_status = false; const uint8* return_data_buffer = NULL; size_t return_data_length = 0; if (!reader.PopInt32(&async_id) || !reader.PopBool(&return_status) || !reader.PopArrayOfBytes(&return_data_buffer, &return_data_length)) { LOG(ERROR) << "Invalid signal: " << signal->ToString(); return; } if (!async_call_status_data_handler_.is_null()) { std::string return_data(reinterpret_cast<const char*>(return_data_buffer), return_data_length); async_call_status_data_handler_.Run(async_id, return_status, return_data); } } // Handles the result of signal connection setup. void OnSignalConnected(const std::string& interface, const std::string& signal, bool succeeded) { LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " << signal << " failed."; } dbus::ObjectProxy* proxy_; scoped_ptr<BlockingMethodCaller> blocking_method_caller_; AsyncCallStatusHandler async_call_status_handler_; AsyncCallStatusWithDataHandler async_call_status_data_handler_; // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed. base::WeakPtrFactory<CryptohomeClientImpl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(CryptohomeClientImpl); }; } // namespace //////////////////////////////////////////////////////////////////////////////// // CryptohomeClient CryptohomeClient::CryptohomeClient() {} CryptohomeClient::~CryptohomeClient() {} // static CryptohomeClient* CryptohomeClient::Create() { return new CryptohomeClientImpl(); } // static std::string CryptohomeClient::GetStubSanitizedUsername( const std::string& username) { return username + kUserIdStubHashSuffix; } } // namespace chromeos