Commit 82531c64 authored by Chris Mumford's avatar Chris Mumford Committed by Commit Bot

Send the AES encryption key to the network service.

Send the encryption key to network service so that the process
does not request the item from the keychain directly, which would
cause macOS to show a confirmation prompt.

Bug: 880522
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: Ia1067bf809472653d843b9007a45574bfe10ed2c
Reviewed-on: https://chromium-review.googlesource.com/1208457
Commit-Queue: John Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#589343}
parent b8985eb3
......@@ -32,6 +32,7 @@
#include "chrome/common/pref_names.h"
#include "components/certificate_transparency/ct_known_logs.h"
#include "components/network_session_configurator/common/network_features.h"
#include "components/os_crypt/os_crypt.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_service.h"
#include "components/policy/policy_constants.h"
......@@ -489,6 +490,10 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(
chrome::GetDefaultUserDataDirectory(&config->user_data_path);
content::GetNetworkService()->SetCryptConfig(std::move(config));
#endif
#if defined(OS_MACOSX)
content::GetNetworkService()->SetEncryptionKey(
OSCrypt::GetRawEncryptionKey());
#endif
// Asynchronously reapply the most recently received CRLSet (if any).
component_updater::CRLSetPolicy::ReconfigureAfterNetworkRestart();
......
......@@ -80,6 +80,16 @@ class OSCrypt {
// mock Keychain. Use OSCryptMocker, instead of calling this method directly.
static COMPONENT_EXPORT(OS_CRYPT) void UseLockedMockKeychainForTesting(
bool use_locked);
// Get the raw encryption key to be used for all AES encryption. Returns an
// empty string in the case password access is denied or key generation error
// occurs. This method is thread-safe.
static COMPONENT_EXPORT(OS_CRYPT) std::string GetRawEncryptionKey();
// Set the raw encryption key to be used for all AES encryption.
// This method is thread-safe.
static COMPONENT_EXPORT(OS_CRYPT) void SetRawEncryptionKey(
const std::string& key);
#endif
private:
......
......@@ -45,22 +45,27 @@ bool use_locked_mock_keychain = false;
// this and migrate to different encryption without data loss.
const char kEncryptionVersionPrefix[] = "v10";
// This lock is used to make the GetEncrytionKey method thread-safe.
// This lock is used to make the GetEncrytionKey and
// OSCrypt::GetRawEncryptionKey methods thread-safe.
base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
// The cached AES encryption key singleton.
crypto::SymmetricKey* g_cached_encryption_key = nullptr;
// true if |g_cached_encryption_key| has been initialized.
bool g_key_is_cached = false;
// Generates a newly allocated SymmetricKey object based on the password found
// in the Keychain. The generated key is for AES encryption. Returns NULL key
// in the case password access is denied or key generation error occurs.
crypto::SymmetricKey* GetEncryptionKey() {
static crypto::SymmetricKey* cached_encryption_key = nullptr;
static bool key_is_cached = false;
base::AutoLock auto_lock(g_lock.Get());
if (use_mock_keychain && use_locked_mock_keychain)
return nullptr;
if (key_is_cached)
return cached_encryption_key;
if (g_key_is_cached)
return g_cached_encryption_key;
static bool mock_keychain_command_line_flag =
base::CommandLine::ForCurrentProcess()->HasSwitch(
......@@ -78,27 +83,45 @@ crypto::SymmetricKey* GetEncryptionKey() {
// Subsequent code must guarantee that the correct key is cached before
// returning.
key_is_cached = true;
g_key_is_cached = true;
if (password.empty())
return cached_encryption_key;
return g_cached_encryption_key;
std::string salt(kSalt);
// Create an encryption key from our password and salt. The key is
// intentionally leaked.
cached_encryption_key =
g_cached_encryption_key =
crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
crypto::SymmetricKey::AES, password, salt, kEncryptionIterations,
kDerivedKeySizeInBits)
.release();
ANNOTATE_LEAKING_OBJECT_PTR(cached_encryption_key);
DCHECK(cached_encryption_key);
return cached_encryption_key;
ANNOTATE_LEAKING_OBJECT_PTR(g_cached_encryption_key);
DCHECK(g_cached_encryption_key);
return g_cached_encryption_key;
}
} // namespace
// static
std::string OSCrypt::GetRawEncryptionKey() {
crypto::SymmetricKey* key = GetEncryptionKey();
if (!key)
return std::string();
return key->key();
}
// static
void OSCrypt::SetRawEncryptionKey(const std::string& raw_key) {
DCHECK(!raw_key.empty());
base::AutoLock auto_lock(g_lock.Get());
auto key = crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key);
DCHECK(!g_key_is_cached) << "Encryption key already set.";
g_cached_encryption_key = key.release();
g_key_is_cached = true;
}
bool OSCrypt::EncryptString16(const base::string16& plaintext,
std::string* ciphertext) {
return EncryptString(base::UTF16ToUTF8(plaintext), ciphertext);
......
......@@ -19,6 +19,7 @@
#include "base/values.h"
#include "components/certificate_transparency/sth_distributor.h"
#include "components/certificate_transparency/sth_observer.h"
#include "components/os_crypt/os_crypt.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/logging_network_change_observer.h"
#include "net/base/network_change_notifier.h"
......@@ -49,7 +50,6 @@
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(IS_CHROMECAST)
#include "components/os_crypt/key_storage_config_linux.h"
#include "components/os_crypt/os_crypt.h"
#endif
namespace network {
......@@ -442,6 +442,12 @@ void NetworkService::SetCryptConfig(mojom::CryptConfigPtr crypt_config) {
}
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
void NetworkService::SetEncryptionKey(const std::string& encryption_key) {
OSCrypt::SetRawEncryptionKey(encryption_key);
}
#endif // OS_MACOSX
void NetworkService::AddCorbExceptionForPlugin(uint32_t process_id) {
DCHECK_NE(mojom::kBrowserProcessId, process_id);
CrossOriginReadBlocking::AddExceptionForPlugin(process_id);
......
......@@ -145,6 +145,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
void UpdateCRLSet(base::span<const uint8_t> crl_set) override;
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
void SetCryptConfig(mojom::CryptConfigPtr crypt_config) override;
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
void SetEncryptionKey(const std::string& encryption_key) override;
#endif
void AddCorbExceptionForPlugin(uint32_t process_id) override;
void RemoveCorbExceptionForPlugin(uint32_t process_id) override;
......
......@@ -301,6 +301,10 @@ interface NetworkService {
[EnableIf=needs_crypt_config]
SetCryptConfig(CryptConfig crypt_config);
// Send the encryption key to the network service to use for AES encryption.
[EnableIf=is_mac]
SetEncryptionKey(string encryption_key);
// Notifies CORB (Cross-Origin Read Blocking) that |process_id| is proxying
// requests on behalf of a universal-access plugin and therefore CORB should
// stop blocking requests marked as RESOURCE_TYPE_PLUGIN_RESOURCE.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment