blob: 955a2e8710dc7acf31a4df5eb8b0ca5a98da1eb0 [file] [log] [blame]
// Copyright (c) 2011 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 "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/hash_tables.h"
#include "base/message_loop.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_thread.h"
namespace {
const char kStubSystemSalt[] = "stub_system_salt";
}
namespace chromeos {
// This class handles the interaction with the ChromeOS cryptohome library APIs.
class CryptohomeLibraryImpl : public CryptohomeLibrary {
public:
CryptohomeLibraryImpl() {}
virtual ~CryptohomeLibraryImpl() {}
virtual void Init() OVERRIDE {
DCHECK(CrosLibrary::Get()->libcros_loaded());
cryptohome_connection_ = chromeos::CryptohomeMonitorSession(&Handler, this);
}
virtual bool CheckKey(
const std::string& user_email, const std::string& passhash) OVERRIDE {
return chromeos::CryptohomeCheckKey(user_email.c_str(), passhash.c_str());
}
virtual bool AsyncCheckKey(const std::string& user_email,
const std::string& passhash,
Delegate* d) OVERRIDE {
return CacheCallback(
chromeos::CryptohomeAsyncCheckKey(user_email.c_str(), passhash.c_str()),
d,
"Couldn't initiate async check of user's key.");
}
virtual bool MigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash) OVERRIDE {
return chromeos::CryptohomeMigrateKey(user_email.c_str(),
old_hash.c_str(),
new_hash.c_str());
}
virtual bool AsyncMigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash,
Delegate* d) OVERRIDE {
return CacheCallback(
chromeos::CryptohomeAsyncMigrateKey(user_email.c_str(),
old_hash.c_str(),
new_hash.c_str()),
d,
"Couldn't initiate aync migration of user's key");
}
virtual bool Mount(const std::string& user_email,
const std::string& passhash,
int* error_code) OVERRIDE {
return chromeos::CryptohomeMountAllowFail(user_email.c_str(),
passhash.c_str(),
error_code);
}
virtual bool AsyncMount(const std::string& user_email,
const std::string& passhash,
const bool create_if_missing,
Delegate* d) OVERRIDE {
return CacheCallback(
chromeos::CryptohomeAsyncMountSafe(user_email.c_str(),
passhash.c_str(),
create_if_missing,
false,
NULL),
d,
"Couldn't initiate async mount of cryptohome.");
}
virtual bool MountForBwsi(int* error_code) OVERRIDE {
return chromeos::CryptohomeMountGuest(error_code);
}
virtual bool AsyncMountForBwsi(Delegate* d) OVERRIDE {
return CacheCallback(chromeos::CryptohomeAsyncMountGuest(),
d,
"Couldn't initiate async mount of cryptohome.");
}
virtual bool Unmount() OVERRIDE {
return chromeos::CryptohomeUnmount();
}
virtual bool Remove(const std::string& user_email) OVERRIDE {
return chromeos::CryptohomeRemove(user_email.c_str());
}
virtual bool AsyncRemove(
const std::string& user_email, Delegate* d) OVERRIDE {
return CacheCallback(
chromeos::CryptohomeAsyncRemove(user_email.c_str()),
d,
"Couldn't initiate async removal of cryptohome.");
}
virtual bool IsMounted() OVERRIDE {
return chromeos::CryptohomeIsMounted();
}
virtual CryptohomeBlob GetSystemSalt() OVERRIDE {
CryptohomeBlob system_salt;
char* salt_buf;
int salt_len;
bool result = chromeos::CryptohomeGetSystemSaltSafe(&salt_buf, &salt_len);
if (result) {
system_salt.resize(salt_len);
if ((int)system_salt.size() == salt_len) {
memcpy(&system_salt[0], static_cast<const void*>(salt_buf),
salt_len);
} else {
system_salt.clear();
}
}
return system_salt;
}
virtual bool AsyncDoAutomaticFreeDiskSpaceControl(Delegate* d) OVERRIDE {
return CacheCallback(
chromeos::CryptohomeAsyncDoAutomaticFreeDiskSpaceControl(),
d,
"Couldn't do automatic free disk space control.");
}
virtual bool AsyncSetOwnerUser(
const std::string& username, Delegate* d) OVERRIDE {
return CacheCallback(
chromeos::CryptohomeAsyncSetOwnerUser(username.c_str()),
d,
"Couldn't do set owner user in Cryptohomed.");
}
virtual bool TpmIsReady() OVERRIDE {
return chromeos::CryptohomeTpmIsReady();
}
virtual bool TpmIsEnabled() OVERRIDE {
return chromeos::CryptohomeTpmIsEnabled();
}
virtual bool TpmIsOwned() OVERRIDE {
return chromeos::CryptohomeTpmIsOwned();
}
virtual bool TpmIsBeingOwned() OVERRIDE {
return chromeos::CryptohomeTpmIsBeingOwned();
}
virtual bool TpmGetPassword(std::string* password) OVERRIDE {
char *password_buf;
bool result = chromeos::CryptohomeTpmGetPasswordSafe(&password_buf);
*password = password_buf;
chromeos::CryptohomeFreeString(password_buf);
return result;
}
virtual void TpmCanAttemptOwnership() OVERRIDE {
chromeos::CryptohomeTpmCanAttemptOwnership();
}
virtual void TpmClearStoredPassword() OVERRIDE {
chromeos::CryptohomeTpmClearStoredPassword();
}
virtual bool InstallAttributesGet(
const std::string& name, std::string* value) OVERRIDE {
char* local_value;
bool done =
chromeos::CryptohomeInstallAttributesGet(name.c_str(), &local_value);
if (done) {
*value = local_value;
chromeos::CryptohomeFreeString(local_value);
}
return done;
}
virtual bool InstallAttributesSet(
const std::string& name, const std::string& value) OVERRIDE {
return chromeos::CryptohomeInstallAttributesSet(name.c_str(),
value.c_str());
}
virtual int InstallAttributesCount() OVERRIDE {
return chromeos::CryptohomeInstallAttributesCount();
}
virtual bool InstallAttributesFinalize() OVERRIDE {
return chromeos::CryptohomeInstallAttributesFinalize();
}
virtual bool InstallAttributesIsReady() OVERRIDE {
return chromeos::CryptohomeInstallAttributesIsReady();
}
virtual bool InstallAttributesIsSecure() OVERRIDE {
return chromeos::CryptohomeInstallAttributesIsSecure();
}
virtual bool InstallAttributesIsInvalid() OVERRIDE {
return chromeos::CryptohomeInstallAttributesIsInvalid();
}
virtual bool InstallAttributesIsFirstInstall() OVERRIDE {
return chromeos::CryptohomeInstallAttributesIsFirstInstall();
}
virtual void Pkcs11GetTpmTokenInfo(
std::string* label, std::string* user_pin) OVERRIDE {
chromeos::CryptohomePkcs11GetTpmTokenInfo(label, user_pin);
}
virtual bool Pkcs11IsTpmTokenReady() OVERRIDE {
return chromeos::CryptohomePkcs11IsTpmTokenReady();
}
private:
static void Handler(const chromeos::CryptohomeAsyncCallStatus& event,
void* cryptohome_library) {
CryptohomeLibraryImpl* library =
reinterpret_cast<CryptohomeLibraryImpl*>(cryptohome_library);
library->Dispatch(event);
}
void Dispatch(const chromeos::CryptohomeAsyncCallStatus& event) {
const CallbackMap::iterator callback = callback_map_.find(event.async_id);
if (callback == callback_map_.end()) {
LOG(ERROR) << "Received signal for unknown async_id " << event.async_id;
return;
}
if (callback->second)
callback->second->OnComplete(event.return_status, event.return_code);
callback_map_.erase(callback);
}
bool CacheCallback(int async_id, Delegate* d, const char* error) {
if (async_id == 0) {
LOG(ERROR) << error;
return false;
}
VLOG(1) << "Adding handler for " << async_id;
callback_map_[async_id] = d;
return true;
}
typedef base::hash_map<int, Delegate*> CallbackMap;
mutable CallbackMap callback_map_;
void* cryptohome_connection_;
DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryImpl);
};
class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
public:
CryptohomeLibraryStubImpl()
: locked_(false) {}
virtual ~CryptohomeLibraryStubImpl() {}
virtual void Init() OVERRIDE {}
virtual bool CheckKey(
const std::string& user_email, const std::string& passhash) OVERRIDE {
return true;
}
virtual bool AsyncCheckKey(const std::string& user_email,
const std::string& passhash,
Delegate* callback) OVERRIDE {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DoStubCallback, callback));
return true;
}
virtual bool MigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash) OVERRIDE {
return true;
}
virtual bool AsyncMigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash,
Delegate* callback) OVERRIDE {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DoStubCallback, callback));
return true;
}
virtual bool Mount(const std::string& user_email,
const std::string& passhash,
int* error_code) OVERRIDE {
// For testing password change.
if (user_email ==
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kLoginUserWithNewPassword)) {
*error_code = kCryptohomeMountErrorKeyFailure;
return false;
}
return true;
}
virtual bool AsyncMount(const std::string& user_email,
const std::string& passhash,
const bool create_if_missing,
Delegate* callback) OVERRIDE {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DoStubCallback, callback));
return true;
}
virtual bool MountForBwsi(int* error_code) OVERRIDE {
return true;
}
virtual bool AsyncMountForBwsi(Delegate* callback) OVERRIDE {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DoStubCallback, callback));
return true;
}
virtual bool Unmount() OVERRIDE {
return true;
}
virtual bool Remove(const std::string& user_email) OVERRIDE {
return true;
}
virtual bool AsyncRemove(
const std::string& user_email, Delegate* callback) OVERRIDE {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DoStubCallback, callback));
return true;
}
virtual bool IsMounted() OVERRIDE {
return true;
}
virtual CryptohomeBlob GetSystemSalt() OVERRIDE {
CryptohomeBlob salt = CryptohomeBlob();
for (size_t i = 0; i < strlen(kStubSystemSalt); i++)
salt.push_back(static_cast<unsigned char>(kStubSystemSalt[i]));
return salt;
}
virtual bool AsyncDoAutomaticFreeDiskSpaceControl(
Delegate* callback) OVERRIDE {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DoStubCallback, callback));
return true;
}
virtual bool AsyncSetOwnerUser(
const std::string& username, Delegate* callback) OVERRIDE {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DoStubCallback, callback));
return true;
}
// Tpm begin ready after 20-th call.
virtual bool TpmIsReady() OVERRIDE {
static int counter = 0;
return ++counter > 20;
}
virtual bool TpmIsEnabled() OVERRIDE {
return true;
}
virtual bool TpmIsOwned() OVERRIDE {
return true;
}
virtual bool TpmIsBeingOwned() OVERRIDE {
return true;
}
virtual bool TpmGetPassword(std::string* password) OVERRIDE {
*password = "Stub-TPM-password";
return true;
}
virtual void TpmCanAttemptOwnership() OVERRIDE {}
virtual void TpmClearStoredPassword() OVERRIDE {}
virtual bool InstallAttributesGet(
const std::string& name, std::string* value) OVERRIDE {
if (install_attrs_.find(name) != install_attrs_.end()) {
*value = install_attrs_[name];
return true;
}
return false;
}
virtual bool InstallAttributesSet(
const std::string& name, const std::string& value) OVERRIDE {
install_attrs_[name] = value;
return true;
}
virtual int InstallAttributesCount() OVERRIDE {
return install_attrs_.size();
}
virtual bool InstallAttributesFinalize() OVERRIDE {
locked_ = true;
return true;
}
virtual bool InstallAttributesIsReady() OVERRIDE {
return true;
}
virtual bool InstallAttributesIsSecure() OVERRIDE {
return false;
}
virtual bool InstallAttributesIsInvalid() OVERRIDE {
return false;
}
virtual bool InstallAttributesIsFirstInstall() OVERRIDE {
return !locked_;
}
virtual void Pkcs11GetTpmTokenInfo(std::string* label,
std::string* user_pin) OVERRIDE {
*label = "Stub TPM Token";
*user_pin = "012345";
}
virtual bool Pkcs11IsTpmTokenReady() OVERRIDE { return true; }
private:
static void DoStubCallback(Delegate* callback) {
if (callback)
callback->OnComplete(true, kCryptohomeMountErrorNone);
}
std::map<std::string, std::string> install_attrs_;
bool locked_;
DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryStubImpl);
};
CryptohomeLibrary::CryptohomeLibrary() {}
CryptohomeLibrary::~CryptohomeLibrary() {}
// static
CryptohomeLibrary* CryptohomeLibrary::GetImpl(bool stub) {
CryptohomeLibrary* impl;
if (stub)
impl = new CryptohomeLibraryStubImpl();
else
impl = new CryptohomeLibraryImpl();
impl->Init();
return impl;
}
} // namespace chromeos