Chromium Code Reviews| 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; |
|
Ryan Sleevi
2013/04/26 18:38:20
nit: This is really kNonceSize.
A bit confusing,
|
| // 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, |
|
Ryan Sleevi
2013/04/26 18:38:20
typo: passprhase -> passphrase
|
| + 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 |