| Index: chromeos/cryptohome/cryptohome_library.cc
|
| diff --git a/chrome/browser/chromeos/cros/cryptohome_library.cc b/chromeos/cryptohome/cryptohome_library.cc
|
| similarity index 50%
|
| rename from chrome/browser/chromeos/cros/cryptohome_library.cc
|
| rename to chromeos/cryptohome/cryptohome_library.cc
|
| index 20c92b3760dcbc128a2f7b7db40e9b418957b627..6aae891fa02ea2cc8bf5532f99a1eb338d393332 100644
|
| --- a/chrome/browser/chromeos/cros/cryptohome_library.cc
|
| +++ b/chromeos/cryptohome/cryptohome_library.cc
|
| @@ -2,22 +2,28 @@
|
| // 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 "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) {}
|
| @@ -116,6 +122,35 @@ class CryptohomeLibraryImpl : public CryptohomeLibrary {
|
| 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())
|
| @@ -126,8 +161,77 @@ class CryptohomeLibraryImpl : public CryptohomeLibrary {
|
| 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);
|
| };
|
| @@ -186,6 +290,15 @@ class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
|
| 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_;
|
| @@ -195,14 +308,48 @@ class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
|
| CryptohomeLibrary::CryptohomeLibrary() {}
|
| CryptohomeLibrary::~CryptohomeLibrary() {}
|
|
|
| +static CryptohomeLibrary* g_cryptohome_library = NULL;
|
| +static CryptohomeLibrary* g_test_cryptohome_library = NULL;
|
| +
|
| // static
|
| -CryptohomeLibrary* CryptohomeLibrary::GetImpl(bool stub) {
|
| - CryptohomeLibrary* impl;
|
| - if (stub)
|
| - impl = new CryptohomeLibraryStubImpl();
|
| +void CryptohomeLibrary::Initialize() {
|
| + CHECK(!g_cryptohome_library);
|
| + if (base::chromeos::IsRunningOnChromeOS())
|
| + g_cryptohome_library = new CryptohomeLibraryStubImpl();
|
| else
|
| - impl = new CryptohomeLibraryImpl();
|
| - return impl;
|
| + 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
|
|
|