blob: 86fe5b7e65ab7ff67ad86c151812aee85abde460 [file] [log] [blame]
// 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 <stddef.h>
#include <stdint.h>
#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "chromeos/cryptohome/async_method_caller.h"
#include "chromeos/cryptohome/cryptohome_parameters.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 {
const int CryptohomeClient::kNotReadyAsyncId = -1;
namespace {
// This suffix is appended to cryptohome_id to get hash in stub implementation:
// stub_hash = "[cryptohome_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;
void FillIdentificationProtobuf(const cryptohome::Identification& id,
cryptohome::AccountIdentifier* id_proto) {
id_proto->set_account_id(id.id());
}
// The CryptohomeClient implementation.
class CryptohomeClientImpl : public CryptohomeClient {
public:
CryptohomeClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {}
// CryptohomeClient override.
void SetAsyncCallStatusHandlers(
const AsyncCallStatusHandler& handler,
const AsyncCallStatusWithDataHandler& data_handler) override {
async_call_status_handler_ = handler;
async_call_status_data_handler_ = data_handler;
}
// CryptohomeClient override.
void ResetAsyncCallStatusHandlers() override {
async_call_status_handler_.Reset();
async_call_status_data_handler_.Reset();
}
// CryptohomeClient override.
void SetLowDiskSpaceHandler(const LowDiskSpaceHandler& handler) override {
low_disk_space_handler_ = handler;
}
// CryptohomeClient override.
void WaitForServiceToBeAvailable(
const WaitForServiceToBeAvailableCallback& callback) override {
proxy_->WaitForServiceToBeAvailable(callback);
}
// CryptohomeClient override.
void IsMounted(const BoolDBusMethodCallback& callback) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeIsMounted);
CallBoolMethod(&method_call, callback);
}
// CryptohomeClient override.
bool Unmount(bool* success) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeUnmount);
return CallBoolMethodAndBlock(&method_call, success);
}
// CryptohomeClient override.
void AsyncCheckKey(const cryptohome::Identification& cryptohome_id,
const std::string& key,
const AsyncMethodCallback& callback) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeAsyncCheckKey);
dbus::MessageWriter writer(&method_call);
writer.AppendString(cryptohome_id.id());
writer.AppendString(key);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void AsyncMigrateKey(const cryptohome::Identification& cryptohome_id,
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(cryptohome_id.id());
writer.AppendString(from_key);
writer.AppendString(to_key);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void AsyncRemove(const cryptohome::Identification& cryptohome_id,
const AsyncMethodCallback& callback) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeAsyncRemove);
dbus::MessageWriter writer(&method_call);
writer.AppendString(cryptohome_id.id());
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void RenameCryptohome(const cryptohome::Identification& cryptohome_id_from,
const cryptohome::Identification& cryptohome_id_to,
const ProtobufMethodCallback& callback) override {
const char* method_name = cryptohome::kCryptohomeRenameCryptohome;
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name);
cryptohome::AccountIdentifier id_from_proto;
cryptohome::AccountIdentifier id_to_proto;
FillIdentificationProtobuf(cryptohome_id_from, &id_from_proto);
FillIdentificationProtobuf(cryptohome_id_to, &id_to_proto);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(id_from_proto);
writer.AppendProtoAsArrayOfBytes(id_to_proto);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(), callback));
}
// CryptohomeClient override.
void GetAccountDiskUsage(const cryptohome::Identification& account_id,
const ProtobufMethodCallback& callback) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeGetAccountDiskUsage);
cryptohome::AccountIdentifier id;
FillIdentificationProtobuf(account_id, &id);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(id);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(), callback));
}
// CryptohomeClient override.
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,
void GetSanitizedUsername(const cryptohome::Identification& cryptohome_id,
const StringDBusMethodCallback& callback) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeGetSanitizedUsername);
dbus::MessageWriter writer(&method_call);
writer.AppendString(cryptohome_id.id());
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnStringMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
std::string BlockingGetSanitizedUsername(
const cryptohome::Identification& cryptohome_id) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeGetSanitizedUsername);
dbus::MessageWriter writer(&method_call);
writer.AppendString(cryptohome_id.id());
std::unique_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.
void AsyncMount(const cryptohome::Identification& cryptohome_id,
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(cryptohome_id.id());
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.
void AsyncAddKey(const cryptohome::Identification& cryptohome_id,
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(cryptohome_id.id());
writer.AppendString(key);
writer.AppendString(new_key);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
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.
void AsyncMountPublic(const cryptohome::Identification& 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.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.
void TpmIsReady(const BoolDBusMethodCallback& callback) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeTpmIsReady);
CallBoolMethod(&method_call, callback);
}
// CryptohomeClient override.
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
bool CallTpmIsEnabledAndBlock(bool* enabled) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeTpmIsEnabled);
return CallBoolMethodAndBlock(&method_call, enabled);
}
// CryptohomeClient override.
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.
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
bool CallTpmIsOwnedAndBlock(bool* owned) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeTpmIsOwned);
return CallBoolMethodAndBlock(&method_call, owned);
}
// CryptohomeClient override.
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
bool CallTpmIsBeingOwnedAndBlock(bool* owning) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeTpmIsBeingOwned);
return CallBoolMethodAndBlock(&method_call, owning);
}
// CryptohomeClient override.
void TpmCanAttemptOwnership(const VoidDBusMethodCallback& callback) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeTpmCanAttemptOwnership);
CallVoidMethod(&method_call, callback);
}
// CryptohomeClient overrides.
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
bool CallTpmClearStoredPasswordAndBlock() override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeTpmClearStoredPassword);
std::unique_ptr<dbus::Response> response(
blocking_method_caller_->CallMethodAndBlock(&method_call));
return response.get() != NULL;
}
// CryptohomeClient override.
void Pkcs11IsTpmTokenReady(const BoolDBusMethodCallback& callback) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomePkcs11IsTpmTokenReady);
CallBoolMethod(&method_call, callback);
}
// CryptohomeClient override.
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.
void Pkcs11GetTpmTokenInfoForUser(
const cryptohome::Identification& cryptohome_id,
const Pkcs11GetTpmTokenInfoCallback& callback) override {
dbus::MethodCall method_call(
cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomePkcs11GetTpmTokenInfoForUser);
dbus::MessageWriter writer(&method_call);
writer.AppendString(cryptohome_id.id());
proxy_->CallMethod(
&method_call, kTpmDBusTimeoutMs ,
base::Bind(
&CryptohomeClientImpl::OnPkcs11GetTpmTokenInfoForUser,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
bool InstallAttributesGet(const std::string& name,
std::vector<uint8_t>* value,
bool* successful) override {
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeInstallAttributesGet);
dbus::MessageWriter writer(&method_call);
writer.AppendString(name);
std::unique_ptr<dbus::Response> response(
blocking_method_caller_->CallMethodAndBlock(&method_call));
if (!response.get())
return false;
dbus::MessageReader reader(response.get());
const uint8_t* 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.
bool InstallAttributesSet(const std::string& name,
const std::vector<uint8_t>& 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.
bool InstallAttributesFinalize(bool* successful) override {
dbus::MethodCall method_call(
cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeInstallAttributesFinalize);
return CallBoolMethodAndBlock(&method_call, successful);
}
// CryptohomeClient override.
void InstallAttributesIsReady(
const BoolDBusMethodCallback& callback) override {
dbus::MethodCall method_call(
cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeInstallAttributesIsReady);
return CallBoolMethod(&method_call, callback);
}
// CryptohomeClient override.
bool InstallAttributesIsInvalid(bool* is_invalid) override {
dbus::MethodCall method_call(
cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeInstallAttributesIsInvalid);
return CallBoolMethodAndBlock(&method_call, is_invalid);
}
// CryptohomeClient override.
bool InstallAttributesIsFirstInstall(bool* is_first_install) override {
dbus::MethodCall method_call(
cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeInstallAttributesIsFirstInstall);
return CallBoolMethodAndBlock(&method_call, is_first_install);
}
// CryptohomeClient override.
void TpmAttestationIsPrepared(
const BoolDBusMethodCallback& callback) override {
dbus::MethodCall method_call(
cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeTpmIsAttestationPrepared);
return CallBoolMethod(&method_call, callback);
}
// CryptohomeClient override.
void TpmAttestationIsEnrolled(
const BoolDBusMethodCallback& callback) override {
dbus::MethodCall method_call(
cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeTpmIsAttestationEnrolled);
return CallBoolMethod(&method_call, callback);
}
// CryptohomeClient override.
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.
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_t*>(pca_response.data()),
pca_response.size());
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void AsyncTpmAttestationCreateCertRequest(
attestation::PrivacyCAType pca_type,
attestation::AttestationCertificateProfile certificate_profile,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(request_origin);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void AsyncTpmAttestationFinishCertRequest(
const std::string& pca_response,
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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_t*>(pca_response.data()),
pca_response.size());
bool is_user_specific = (key_type == attestation::KEY_USER);
writer.AppendBool(is_user_specific);
writer.AppendString(cryptohome_id.id());
writer.AppendString(key_name);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void TpmAttestationDoesKeyExist(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_name);
CallBoolMethod(&method_call, callback);
}
// CryptohomeClient override.
void TpmAttestationGetCertificate(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_name);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnDataMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void TpmAttestationGetPublicKey(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_name);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnDataMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void TpmAttestationRegisterKey(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_name);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void TpmAttestationSignEnterpriseChallenge(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_name);
writer.AppendString(domain);
writer.AppendArrayOfBytes(
reinterpret_cast<const uint8_t*>(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_t*>(challenge.data()), challenge.size());
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void TpmAttestationSignSimpleChallenge(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_name);
writer.AppendArrayOfBytes(
reinterpret_cast<const uint8_t*>(challenge.data()), challenge.size());
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void TpmAttestationGetKeyPayload(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_name);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnDataMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// CryptohomeClient override.
void TpmAttestationSetKeyPayload(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_name);
writer.AppendArrayOfBytes(reinterpret_cast<const uint8_t*>(payload.data()),
payload.size());
CallBoolMethod(&method_call, callback);
}
// CryptohomeClient override.
void TpmAttestationDeleteKeys(
attestation::AttestationKeyType key_type,
const cryptohome::Identification& cryptohome_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(cryptohome_id.id());
writer.AppendString(key_prefix);
CallBoolMethod(&method_call, callback);
}
void GetKeyDataEx(const cryptohome::Identification& id,
const cryptohome::AuthorizationRequest& auth,
const cryptohome::GetKeyDataRequest& request,
const ProtobufMethodCallback& callback) override {
cryptohome::AccountIdentifier id_proto;
FillIdentificationProtobuf(id, &id_proto);
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomeGetKeyDataEx);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(id_proto);
writer.AppendProtoAsArrayOfBytes(auth);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call,
kTpmDBusTimeoutMs,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void CheckKeyEx(const cryptohome::Identification& 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);
cryptohome::AccountIdentifier id_proto;
FillIdentificationProtobuf(id, &id_proto);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(id_proto);
writer.AppendProtoAsArrayOfBytes(auth);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void MountEx(const cryptohome::Identification& 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);
cryptohome::AccountIdentifier id_proto;
FillIdentificationProtobuf(id, &id_proto);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(id_proto);
writer.AppendProtoAsArrayOfBytes(auth);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void AddKeyEx(const cryptohome::Identification& 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);
cryptohome::AccountIdentifier id_proto;
FillIdentificationProtobuf(id, &id_proto);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(id_proto);
writer.AppendProtoAsArrayOfBytes(auth);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call, kTpmDBusTimeoutMs,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void UpdateKeyEx(const cryptohome::Identification& 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);
cryptohome::AccountIdentifier id_proto;
FillIdentificationProtobuf(id, &id_proto);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(id_proto);
writer.AppendProtoAsArrayOfBytes(auth);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call,
kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void RemoveKeyEx(const cryptohome::Identification& 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);
cryptohome::AccountIdentifier id_proto;
FillIdentificationProtobuf(id, &id_proto);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(id_proto);
writer.AppendProtoAsArrayOfBytes(auth);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call,
kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void GetBootAttribute(const cryptohome::GetBootAttributeRequest& request,
const ProtobufMethodCallback& callback) override {
const char* method_name = cryptohome::kCryptohomeGetBootAttribute;
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call,
kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void SetBootAttribute(const cryptohome::SetBootAttributeRequest& request,
const ProtobufMethodCallback& callback) override {
const char* method_name = cryptohome::kCryptohomeSetBootAttribute;
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call,
kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void FlushAndSignBootAttributes(
const cryptohome::FlushAndSignBootAttributesRequest& request,
const ProtobufMethodCallback& callback) override {
const char* method_name = cryptohome::kCryptohomeFlushAndSignBootAttributes;
dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(request);
proxy_->CallMethod(&method_call,
kTpmDBusTimeoutMs ,
base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
protected:
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()));
proxy_->ConnectToSignal(cryptohome::kCryptohomeInterface,
cryptohome::kSignalLowDiskSpace,
base::Bind(&CryptohomeClientImpl::OnLowDiskSpace,
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) {
callback.Run(kNotReadyAsyncId);
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_t>());
return;
}
dbus::MessageReader reader(response);
const uint8_t* bytes = NULL;
size_t length = 0;
if (!reader.PopArrayOfBytes(&bytes, &length)) {
callback.Run(DBUS_METHOD_CALL_FAILURE, std::vector<uint8_t>());
return;
}
callback.Run(DBUS_METHOD_CALL_SUCCESS,
std::vector<uint8_t>(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) {
std::unique_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_t* 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_t* 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 LowDiskSpace signal.
void OnLowDiskSpace(dbus::Signal* signal) {
dbus::MessageReader reader(signal);
uint64_t disk_free_bytes = 0;
if (!reader.PopUint64(&disk_free_bytes)) {
LOG(ERROR) << "Invalid signal: " << signal->ToString();
return;
}
if (!low_disk_space_handler_.is_null())
low_disk_space_handler_.Run(disk_free_bytes);
}
// 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_;
std::unique_ptr<BlockingMethodCaller> blocking_method_caller_;
AsyncCallStatusHandler async_call_status_handler_;
AsyncCallStatusWithDataHandler async_call_status_data_handler_;
LowDiskSpaceHandler low_disk_space_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 cryptohome::Identification& cryptohome_id) {
return cryptohome_id.id() + kUserIdStubHashSuffix;
}
} // namespace chromeos