blob: bfc8ef1728a459bbb6cc8b585453af694e21a0b8 [file] [log] [blame]
// Copyright (c) 2010 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/command_line.h"
#include "base/hash_tables.h"
#include "base/message_loop.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/common/chrome_switches.h"
namespace chromeos {
// This class handles the interaction with the ChromeOS cryptohome library APIs.
class CryptohomeLibraryImpl : public CryptohomeLibrary {
public:
CryptohomeLibraryImpl() {
if (CrosLibrary::Get()->EnsureLoaded())
Init();
}
virtual ~CryptohomeLibraryImpl() {}
bool CheckKey(const std::string& user_email, const std::string& passhash) {
return chromeos::CryptohomeCheckKey(user_email.c_str(), passhash.c_str());
}
bool AsyncCheckKey(const std::string& user_email,
const std::string& passhash,
Delegate* d) {
return CacheCallback(
chromeos::CryptohomeAsyncCheckKey(user_email.c_str(), passhash.c_str()),
d,
"Couldn't initiate async check of user's key.");
}
bool MigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash) {
return chromeos::CryptohomeMigrateKey(user_email.c_str(),
old_hash.c_str(),
new_hash.c_str());
}
bool AsyncMigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash,
Delegate* d) {
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");
}
bool Mount(const std::string& user_email,
const std::string& passhash,
int* error_code) {
return chromeos::CryptohomeMountAllowFail(user_email.c_str(),
passhash.c_str(),
error_code);
}
bool AsyncMount(const std::string& user_email,
const std::string& passhash,
const bool create_if_missing,
Delegate* d) {
return CacheCallback(
chromeos::CryptohomeAsyncMount(user_email.c_str(),
passhash.c_str(),
create_if_missing,
"",
std::vector<std::string>()),
d,
"Couldn't initiate async mount of cryptohome.");
}
bool MountForBwsi(int* error_code) {
return chromeos::CryptohomeMountGuest(error_code);
}
bool AsyncMountForBwsi(Delegate* d) {
return CacheCallback(chromeos::CryptohomeAsyncMountGuest(),
d,
"Couldn't initiate async mount of cryptohome.");
}
bool Unmount() {
return chromeos::CryptohomeUnmount();
}
bool Remove(const std::string& user_email) {
return chromeos::CryptohomeRemove(user_email.c_str());
}
bool AsyncRemove(const std::string& user_email, Delegate* d) {
return CacheCallback(
chromeos::CryptohomeAsyncRemove(user_email.c_str()),
d,
"Couldn't initiate async removal of cryptohome.");
}
bool IsMounted() {
return chromeos::CryptohomeIsMounted();
}
CryptohomeBlob GetSystemSalt() {
return chromeos::CryptohomeGetSystemSalt();
}
bool TpmIsReady() {
return chromeos::CryptohomeTpmIsReady();
}
bool TpmIsEnabled() {
return chromeos::CryptohomeTpmIsEnabled();
}
bool TpmIsOwned() {
return chromeos::CryptohomeTpmIsOwned();
}
bool TpmIsBeingOwned() {
return chromeos::CryptohomeTpmIsBeingOwned();
}
bool TpmGetPassword(std::string* password) {
return chromeos::CryptohomeTpmGetPassword(password);
}
void TpmCanAttemptOwnership() {
chromeos::CryptohomeTpmCanAttemptOwnership();
}
void TpmClearStoredPassword() {
chromeos::CryptohomeTpmClearStoredPassword();
}
private:
static void Handler(const chromeos::CryptohomeAsyncCallStatus& event,
void* cryptohome_library) {
CryptohomeLibraryImpl* library =
reinterpret_cast<CryptohomeLibraryImpl*>(cryptohome_library);
library->Dispatch(event);
}
void Init() {
cryptohome_connection_ = chromeos::CryptohomeMonitorSession(&Handler, this);
}
void Dispatch(const chromeos::CryptohomeAsyncCallStatus& event) {
if (!callback_map_[event.async_id]) {
LOG(ERROR) << "Received signal for unknown async_id " << event.async_id;
return;
}
callback_map_[event.async_id]->OnComplete(event.return_status,
event.return_code);
callback_map_[event.async_id] = NULL;
}
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() {}
virtual ~CryptohomeLibraryStubImpl() {}
bool CheckKey(const std::string& user_email, const std::string& passhash) {
return true;
}
bool AsyncCheckKey(const std::string& user_email,
const std::string& passhash,
Delegate* callback) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableFunction(&DoStubCallback, callback));
return true;
}
bool MigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash) {
return true;
}
bool AsyncMigrateKey(const std::string& user_email,
const std::string& old_hash,
const std::string& new_hash,
Delegate* callback) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableFunction(&DoStubCallback, callback));
return true;
}
bool Mount(const std::string& user_email,
const std::string& passhash,
int* error_code) {
// For testing password change.
if (user_email ==
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kLoginUserWithNewPassword)) {
*error_code = kCryptohomeMountErrorKeyFailure;
return false;
}
return true;
}
bool AsyncMount(const std::string& user_email,
const std::string& passhash,
const bool create_if_missing,
Delegate* callback) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableFunction(&DoStubCallback, callback));
return true;
}
bool MountForBwsi(int* error_code) {
return true;
}
bool AsyncMountForBwsi(Delegate* callback) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableFunction(&DoStubCallback, callback));
return true;
}
bool Unmount() {
return true;
}
bool Remove(const std::string& user_email) {
return true;
}
bool AsyncRemove(const std::string& user_email, Delegate* callback) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableFunction(&DoStubCallback, callback));
return true;
}
bool IsMounted() {
return true;
}
CryptohomeBlob GetSystemSalt() {
CryptohomeBlob salt = CryptohomeBlob();
salt.push_back(0);
salt.push_back(0);
return salt;
}
// Tpm begin ready after 20-th call.
bool TpmIsReady() {
static int counter = 0;
return ++counter > 20;
}
bool TpmIsEnabled() {
return true;
}
bool TpmIsOwned() {
return true;
}
bool TpmIsBeingOwned() {
return true;
}
bool TpmGetPassword(std::string* password) {
*password = "Stub-TPM-password";
return true;
}
void TpmCanAttemptOwnership() {}
void TpmClearStoredPassword() {}
private:
static void DoStubCallback(Delegate* callback) {
callback->OnComplete(true, kCryptohomeMountErrorNone);
}
DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryStubImpl);
};
// static
CryptohomeLibrary* CryptohomeLibrary::GetImpl(bool stub) {
if (stub)
return new CryptohomeLibraryStubImpl();
else
return new CryptohomeLibraryImpl();
}
} // namespace chromeos