// 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()), 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(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 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