diff options
author | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-24 16:11:31 +0000 |
---|---|---|
committer | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-24 16:11:31 +0000 |
commit | 932ae79a3b85708c8889b9c37c18cb3403cfae1b (patch) | |
tree | 4d8dff223179c7b24c8a1a9e311b37548d44e909 /chromeos/cryptohome | |
parent | 231274fcb382c876c9f3654dacdbd00d3c9b1df7 (diff) | |
download | chromium_src-932ae79a3b85708c8889b9c37c18cb3403cfae1b.zip chromium_src-932ae79a3b85708c8889b9c37c18cb3403cfae1b.tar.gz chromium_src-932ae79a3b85708c8889b9c37c18cb3403cfae1b.tar.bz2 |
Move cryptohome_library to src/chromeos
This CL does the following:
1. Move [De|En]cryptWithSystemSalt to CryptohomeLibrary
2. Remove CryptohomeLibrary from CrosLibrary
3. Move CryptohomeLibrary to src/chromeos
BUG=233724
For chrome_browser_chromeos.gypi
TBR=sky@chromium.org
Review URL: https://codereview.chromium.org/14179007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196159 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/cryptohome')
-rw-r--r-- | chromeos/cryptohome/cryptohome_library.cc | 355 | ||||
-rw-r--r-- | chromeos/cryptohome/cryptohome_library.h | 84 | ||||
-rw-r--r-- | chromeos/cryptohome/mock_cryptohome_library.cc | 14 | ||||
-rw-r--r-- | chromeos/cryptohome/mock_cryptohome_library.h | 51 |
4 files changed, 504 insertions, 0 deletions
diff --git a/chromeos/cryptohome/cryptohome_library.cc b/chromeos/cryptohome/cryptohome_library.cc new file mode 100644 index 0000000..6aae891 --- /dev/null +++ b/chromeos/cryptohome/cryptohome_library.cc @@ -0,0 +1,355 @@ +// 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/cryptohome/cryptohome_library.h" + +#include <map> + +#include "base/bind.h" +#include "base/chromeos/chromeos_version.h" +#include "base/memory/weak_ptr.h" +#include "base/string_util.h" +#include "base/strings/string_number_conversions.h" +#include "chromeos/dbus/cryptohome_client.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "crypto/encryptor.h" +#include "crypto/nss_util.h" +#include "crypto/sha2.h" +#include "crypto/symmetric_key.h" + +namespace chromeos { + +namespace { + +const char kStubSystemSalt[] = "stub_system_salt"; +const size_t kKeySize = 16; + +// Does nothing. Used as a Cryptohome::VoidMethodCallback. +void DoNothing(DBusMethodCallStatus call_status) {} + +} // namespace + +// This class handles the interaction with the ChromeOS cryptohome library APIs. +class CryptohomeLibraryImpl : public CryptohomeLibrary { + public: + CryptohomeLibraryImpl() : weak_ptr_factory_(this) { + } + + virtual ~CryptohomeLibraryImpl() { + } + + virtual bool TpmIsEnabled() OVERRIDE { + bool result = false; + DBusThreadManager::Get()->GetCryptohomeClient()->CallTpmIsEnabledAndBlock( + &result); + return result; + } + + virtual bool TpmIsOwned() OVERRIDE { + bool result = false; + DBusThreadManager::Get()->GetCryptohomeClient()->CallTpmIsOwnedAndBlock( + &result); + return result; + } + + virtual bool TpmIsBeingOwned() OVERRIDE { + bool result = false; + DBusThreadManager::Get()->GetCryptohomeClient()-> + CallTpmIsBeingOwnedAndBlock(&result); + return result; + } + + virtual void TpmCanAttemptOwnership() OVERRIDE { + DBusThreadManager::Get()->GetCryptohomeClient()->TpmCanAttemptOwnership( + base::Bind(&DoNothing)); + } + + virtual void TpmClearStoredPassword() OVERRIDE { + DBusThreadManager::Get()->GetCryptohomeClient()-> + CallTpmClearStoredPasswordAndBlock(); + } + + virtual bool InstallAttributesGet( + const std::string& name, std::string* value) OVERRIDE { + std::vector<uint8> buf; + bool success = false; + DBusThreadManager::Get()->GetCryptohomeClient()-> + InstallAttributesGet(name, &buf, &success); + if (success) { + // Cryptohome returns 'buf' with a terminating '\0' character. + DCHECK(!buf.empty()); + DCHECK_EQ(buf.back(), 0); + value->assign(reinterpret_cast<char*>(buf.data()), buf.size() - 1); + } + return success; + } + + virtual bool InstallAttributesSet( + const std::string& name, const std::string& value) OVERRIDE { + std::vector<uint8> buf(value.c_str(), value.c_str() + value.size() + 1); + bool success = false; + DBusThreadManager::Get()->GetCryptohomeClient()-> + InstallAttributesSet(name, buf, &success); + return success; + } + + virtual bool InstallAttributesFinalize() OVERRIDE { + bool success = false; + DBusThreadManager::Get()->GetCryptohomeClient()-> + InstallAttributesFinalize(&success); + return success; + } + + virtual bool InstallAttributesIsInvalid() OVERRIDE { + bool result = false; + DBusThreadManager::Get()->GetCryptohomeClient()-> + InstallAttributesIsInvalid(&result); + return result; + } + + virtual bool InstallAttributesIsFirstInstall() OVERRIDE { + bool result = false; + DBusThreadManager::Get()->GetCryptohomeClient()-> + InstallAttributesIsFirstInstall(&result); + return result; + } + + virtual std::string GetSystemSalt() OVERRIDE { + LoadSystemSalt(); // no-op if it's already loaded. + return StringToLowerASCII(base::HexEncode( + reinterpret_cast<const void*>(system_salt_.data()), + system_salt_.size())); + } + + virtual std::string EncryptWithSystemSalt(const std::string& token) OVERRIDE { + // Don't care about token encryption while debugging. + if (!base::chromeos::IsRunningOnChromeOS()) + return token; + + if (!LoadSystemSaltKey()) { + LOG(WARNING) << "System salt key is not available for encrypt."; + return std::string(); + } + return EncryptTokenWithKey(system_salt_key_.get(), + GetSystemSalt(), + token); + } + + virtual std::string DecryptWithSystemSalt( + const std::string& encrypted_token_hex) OVERRIDE { + // Don't care about token encryption while debugging. + if (!base::chromeos::IsRunningOnChromeOS()) + return encrypted_token_hex; + + if (!LoadSystemSaltKey()) { + LOG(WARNING) << "System salt key is not available for decrypt."; + return std::string(); + } + return DecryptTokenWithKey(system_salt_key_.get(), + GetSystemSalt(), + encrypted_token_hex); + } + + private: + void LoadSystemSalt() { + if (!system_salt_.empty()) + return; + DBusThreadManager::Get()->GetCryptohomeClient()-> + GetSystemSalt(&system_salt_); + CHECK(!system_salt_.empty()); + CHECK_EQ(system_salt_.size() % 2, 0U); + } + + // TODO: should this use the system salt for both the password and the salt + // value, or should this use a separate salt value? + bool LoadSystemSaltKey() { + if (!system_salt_key_.get()) + system_salt_key_.reset(PassphraseToKey(GetSystemSalt(), GetSystemSalt())); + return system_salt_key_.get(); + } + + crypto::SymmetricKey* PassphraseToKey(const std::string& passprhase, + const std::string& salt) { + return crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::AES, passprhase, salt, 1000, 256); + } + + + // Encrypts (AES) the token given |key| and |salt|. + std::string EncryptTokenWithKey(crypto::SymmetricKey* key, + const std::string& salt, + const std::string& token) { + crypto::Encryptor encryptor; + if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) { + LOG(WARNING) << "Failed to initialize Encryptor."; + return std::string(); + } + std::string nonce = salt.substr(0, kKeySize); + std::string encoded_token; + CHECK(encryptor.SetCounter(nonce)); + if (!encryptor.Encrypt(token, &encoded_token)) { + LOG(WARNING) << "Failed to encrypt token."; + return std::string(); + } + + return StringToLowerASCII(base::HexEncode( + reinterpret_cast<const void*>(encoded_token.data()), + encoded_token.size())); + } + + // Decrypts (AES) hex encoded encrypted token given |key| and |salt|. + std::string DecryptTokenWithKey(crypto::SymmetricKey* key, + const std::string& salt, + const std::string& encrypted_token_hex) { + std::vector<uint8> encrypted_token_bytes; + if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) { + LOG(WARNING) << "Corrupt encrypted token found."; + return std::string(); + } + + std::string encrypted_token( + reinterpret_cast<char*>(encrypted_token_bytes.data()), + encrypted_token_bytes.size()); + crypto::Encryptor encryptor; + if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) { + LOG(WARNING) << "Failed to initialize Encryptor."; + return std::string(); + } + + std::string nonce = salt.substr(0, kKeySize); + std::string token; + CHECK(encryptor.SetCounter(nonce)); + if (!encryptor.Decrypt(encrypted_token, &token)) { + LOG(WARNING) << "Failed to decrypt token."; + return std::string(); + } + return token; + } + + base::WeakPtrFactory<CryptohomeLibraryImpl> weak_ptr_factory_; + std::vector<uint8> system_salt_; + // A key based on the system salt. Useful for encrypting device-level + // data for which we have no additional credentials. + scoped_ptr<crypto::SymmetricKey> system_salt_key_; + + DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryImpl); +}; + +class CryptohomeLibraryStubImpl : public CryptohomeLibrary { + public: + CryptohomeLibraryStubImpl() + : locked_(false) {} + virtual ~CryptohomeLibraryStubImpl() {} + + virtual bool TpmIsEnabled() OVERRIDE { + return true; + } + + virtual bool TpmIsOwned() OVERRIDE { + return true; + } + + virtual bool TpmIsBeingOwned() OVERRIDE { + 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 bool InstallAttributesFinalize() OVERRIDE { + locked_ = true; + return true; + } + + virtual bool InstallAttributesIsInvalid() OVERRIDE { + return false; + } + + virtual bool InstallAttributesIsFirstInstall() OVERRIDE { + return !locked_; + } + + virtual std::string GetSystemSalt() OVERRIDE { + return kStubSystemSalt; + } + + virtual std::string EncryptWithSystemSalt(const std::string& token) { + return token; + } + + virtual std::string DecryptWithSystemSalt( + const std::string& encrypted_token_hex) { + return encrypted_token_hex; + } + + private: + std::map<std::string, std::string> install_attrs_; + bool locked_; + DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryStubImpl); +}; + +CryptohomeLibrary::CryptohomeLibrary() {} +CryptohomeLibrary::~CryptohomeLibrary() {} + +static CryptohomeLibrary* g_cryptohome_library = NULL; +static CryptohomeLibrary* g_test_cryptohome_library = NULL; + +// static +void CryptohomeLibrary::Initialize() { + CHECK(!g_cryptohome_library); + if (base::chromeos::IsRunningOnChromeOS()) + g_cryptohome_library = new CryptohomeLibraryStubImpl(); + else + g_cryptohome_library = new CryptohomeLibraryImpl(); +} + +// static +bool CryptohomeLibrary::IsInitialized() { + return g_cryptohome_library; +} + +// static +void CryptohomeLibrary::Shutdown() { + CHECK(g_cryptohome_library); + delete g_cryptohome_library; + g_cryptohome_library = NULL; +} + +// static +CryptohomeLibrary* CryptohomeLibrary::Get() { + CHECK(g_cryptohome_library || g_test_cryptohome_library) + << "CryptohomeLibrary::Get() called before Initialize()"; + if (g_test_cryptohome_library) + return g_test_cryptohome_library; + return g_cryptohome_library; +} + +// static +void CryptohomeLibrary::SetForTest(CryptohomeLibrary* impl) { + CHECK(!g_test_cryptohome_library || !impl); + g_test_cryptohome_library = impl; +} + +// static +CryptohomeLibrary* CryptohomeLibrary::GetTestImpl() { + return new CryptohomeLibraryStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/cryptohome/cryptohome_library.h b/chromeos/cryptohome/cryptohome_library.h new file mode 100644 index 0000000..1e3aca9e --- /dev/null +++ b/chromeos/cryptohome/cryptohome_library.h @@ -0,0 +1,84 @@ +// 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. + +#ifndef CHROMEOS_CRYPTOHOME_CRYPTOHOME_LIBRARY_H_ +#define CHROMEOS_CRYPTOHOME_CRYPTOHOME_LIBRARY_H_ + +#include <string> + +#include "base/basictypes.h" +#include "chromeos/chromeos_export.h" + +namespace chromeos { + +// This interface defines the interaction with the ChromeOS cryptohome library +// APIs. +class CHROMEOS_EXPORT CryptohomeLibrary { + public: + // Manage an explicitly initialized global instance. + static void Initialize(); + static bool IsInitialized(); + static void Shutdown(); + static CryptohomeLibrary* Get(); + + // Sets up Get() to return |impl| for testing (e.g. with a mock + // implementation). Call SetForTest(NULL) when |impl| is deleted. + static void SetForTest(CryptohomeLibrary* impl); + + // Returns a CryptohomeLibrary instance for testing. Does not set or affect + // the global instance. + static CryptohomeLibrary* GetTestImpl(); + + // Public so that result of GetTestImpl can be destroyed. + virtual ~CryptohomeLibrary(); + + // Wrappers of the functions for working with Tpm. + + // Returns whether Tpm is presented and enabled. + virtual bool TpmIsEnabled() = 0; + + // Returns whether device has already been owned. + virtual bool TpmIsOwned() = 0; + + // Returns whether device is being owned (Tpm password is generating). + virtual bool TpmIsBeingOwned() = 0; + + // Attempts to start owning (if device isn't owned and isn't being owned). + virtual void TpmCanAttemptOwnership() = 0; + + // Clears Tpm password. Password should be cleared after it was generated and + // shown to user. + virtual void TpmClearStoredPassword() = 0; + + virtual bool InstallAttributesGet(const std::string& name, + std::string* value) = 0; + virtual bool InstallAttributesSet(const std::string& name, + const std::string& value) = 0; + virtual bool InstallAttributesFinalize() = 0; + virtual bool InstallAttributesIsInvalid() = 0; + virtual bool InstallAttributesIsFirstInstall() = 0; + + // Returns system hash in hex encoded ascii format. + virtual std::string GetSystemSalt() = 0; + + // Encrypts |token| with the system salt key (stable for the lifetime + // of the device). Useful to avoid storing plain text in place like + // Local State. + virtual std::string EncryptWithSystemSalt(const std::string& token) = 0; + + // Decrypts |token| with the system salt key (stable for the lifetime + // of the device). + virtual std::string DecryptWithSystemSalt( + const std::string& encrypted_token_hex) = 0; + + protected: + CryptohomeLibrary(); + + private: + DISALLOW_COPY_AND_ASSIGN(CryptohomeLibrary); +}; + +} // namespace chromeos + +#endif // CHROMEOS_CRYPTOHOME_CRYPTOHOME_LIBRARY_H_ diff --git a/chromeos/cryptohome/mock_cryptohome_library.cc b/chromeos/cryptohome/mock_cryptohome_library.cc new file mode 100644 index 0000000..1916f9e --- /dev/null +++ b/chromeos/cryptohome/mock_cryptohome_library.cc @@ -0,0 +1,14 @@ +// 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/cryptohome/mock_cryptohome_library.h" + +namespace chromeos { + +MockCryptohomeLibrary::MockCryptohomeLibrary() { +} + +MockCryptohomeLibrary::~MockCryptohomeLibrary() {} + +} // namespace chromeos diff --git a/chromeos/cryptohome/mock_cryptohome_library.h b/chromeos/cryptohome/mock_cryptohome_library.h new file mode 100644 index 0000000..a8c6ef9 --- /dev/null +++ b/chromeos/cryptohome/mock_cryptohome_library.h @@ -0,0 +1,51 @@ +// 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. + +#ifndef CHROMEOS_CRYPTOHOME_MOCK_CRYPTOHOME_LIBRARY_H_ +#define CHROMEOS_CRYPTOHOME_MOCK_CRYPTOHOME_LIBRARY_H_ + +#include <string> + +#include "base/basictypes.h" +#include "chromeos/cryptohome/cryptohome_library.h" +#include "testing/gmock/include/gmock/gmock.h" + +using ::testing::Invoke; +using ::testing::WithArgs; +using ::testing::_; + +namespace chromeos { + +class MockCryptohomeLibrary : public CryptohomeLibrary { + public: + MockCryptohomeLibrary(); + virtual ~MockCryptohomeLibrary(); + MOCK_METHOD0(GetSystemSalt, std::string(void)); + + MOCK_METHOD0(TpmIsReady, bool(void)); + MOCK_METHOD0(TpmIsEnabled, bool(void)); + MOCK_METHOD0(TpmIsOwned, bool(void)); + MOCK_METHOD0(TpmIsBeingOwned, bool(void)); + MOCK_METHOD1(TpmGetPassword, bool(std::string* password)); + MOCK_METHOD0(TpmCanAttemptOwnership, void(void)); + MOCK_METHOD0(TpmClearStoredPassword, void(void)); + + MOCK_METHOD2(InstallAttributesGet, bool(const std::string&, std::string*)); + MOCK_METHOD2(InstallAttributesSet, bool(const std::string&, + const std::string&)); + MOCK_METHOD0(InstallAttributesFinalize, bool(void)); + MOCK_METHOD0(InstallAttributesIsReady, bool(void)); + MOCK_METHOD0(InstallAttributesIsInvalid, bool(void)); + MOCK_METHOD0(InstallAttributesIsFirstInstall, bool(void)); + + MOCK_METHOD1(EncryptWithSystemSalt, std::string(const std::string&)); + MOCK_METHOD1(DecryptWithSystemSalt, std::string(const std::string&)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockCryptohomeLibrary); +}; + +} // namespace chromeos + +#endif // CHROMEOS_CRYPTOHOME_MOCK_CRYPTOHOME_LIBRARY_H_ |