feat: introduce os_crypt_async in safeStorage (#49054)

* feat: support Freedesktop Secret Service OSCrypt client

Refs https://issues.chromium.org/issues/40086962
Refs https://issues.chromium.org/issues/447372315

* chore: rework to async interface

* refactor: allow customizing freedesktop config

* docs: add more async impl info

* refactor: reject when temporarily unavailable

* chore: feedback from review

* chore: push_back => emplace_back
This commit is contained in:
Shelley Vohr
2026-02-15 19:54:50 +01:00
committed by GitHub
parent dcdbb0397e
commit eb29568e45
19 changed files with 970 additions and 875 deletions

View File

@@ -10,6 +10,7 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/notimplemented.h"
#include "base/path_service.h"
#include "chrome/browser/browser_process.h"
@@ -46,6 +47,28 @@
#include "chrome/browser/printing/print_job_manager.h"
#endif
#if BUILDFLAG(IS_LINUX)
#include "chrome/browser/browser_features.h"
#include "components/os_crypt/async/browser/freedesktop_secret_key_provider.h"
#include "components/os_crypt/async/browser/secret_portal_key_provider.h"
#include "components/password_manager/core/browser/password_manager_switches.h" // nogncheck
#include "shell/common/application_info.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "components/os_crypt/async/browser/dpapi_key_provider.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "chrome/common/chrome_features.h"
#include "components/os_crypt/async/browser/keychain_key_provider.h"
#endif
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
#include "components/os_crypt/async/browser/posix_key_provider.h"
#endif
BrowserProcessImpl::BrowserProcessImpl() {
g_browser_process = this;
}
@@ -116,10 +139,16 @@ void BrowserProcessImpl::PostEarlyInitialization() {
PrefServiceFactory prefs_factory;
auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>();
PrefProxyConfigTrackerImpl::RegisterPrefs(pref_registry.get());
#if BUILDFLAG(IS_WIN)
OSCrypt::RegisterLocalPrefs(pref_registry.get());
#endif
#if BUILDFLAG(IS_LINUX)
os_crypt_async::SecretPortalKeyProvider::RegisterLocalPrefs(
pref_registry.get());
#endif
in_memory_pref_store_ = base::MakeRefCounted<ValueMapPrefStore>();
ApplyProxyModeFromCommandLine(in_memory_pref_store());
prefs_factory.set_command_line_prefs(in_memory_pref_store());
@@ -419,16 +448,63 @@ void BrowserProcessImpl::CreateNetworkQualityObserver() {
}
void BrowserProcessImpl::CreateOSCryptAsync() {
// source: https://chromium-review.googlesource.com/c/chromium/src/+/4455776
std::vector<std::pair<size_t, std::unique_ptr<os_crypt_async::KeyProvider>>>
providers;
// For now, initialize OSCryptAsync with no providers. This delegates all
// encryption operations to OSCrypt.
// TODO(crbug.com/1373092): Add providers behind features, as support for them
// is added.
os_crypt_async_ = std::make_unique<os_crypt_async::OSCryptAsync>(
std::vector<
std::pair<size_t, std::unique_ptr<os_crypt_async::KeyProvider>>>());
#if BUILDFLAG(IS_WIN)
// The DPAPI key provider requires OSCrypt::Init to have already been called
// to initialize the key storage. This happens in
// BrowserMainPartsWin::PreCreateMainMessageLoop.
providers.emplace_back(std::make_pair(
/*precedence=*/10u,
std::make_unique<os_crypt_async::DPAPIKeyProvider>(local_state())));
#endif // BUILDFLAG(IS_WIN)
// Trigger async initialization of OSCrypt key providers.
os_crypt_async_->GetInstance(base::DoNothing());
#if BUILDFLAG(IS_LINUX)
base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
const auto password_store =
cmd_line->GetSwitchValueASCII(password_manager::kPasswordStore);
if (base::FeatureList::IsEnabled(features::kDbusSecretPortal)) {
// Use a higher priority than the FreedesktopSecretKeyProvider.
providers.emplace_back(
/*precedence=*/15u,
std::make_unique<os_crypt_async::SecretPortalKeyProvider>(
local_state(),
base::FeatureList::IsEnabled(
features::kSecretPortalKeyProviderUseForEncryption)));
}
auto freedesktop_config =
os_crypt_async::FreedesktopSecretKeyProvider::GetDefaultConfig();
const std::string app_name = electron::GetApplicationName();
freedesktop_config.app_name = app_name;
freedesktop_config.kwallet_folder = app_name + " Keys";
freedesktop_config.key_name = app_name + " Safe Storage";
providers.emplace_back(
/*precedence=*/10u,
std::make_unique<os_crypt_async::FreedesktopSecretKeyProvider>(
password_store, electron::GetApplicationName(), freedesktop_config,
nullptr));
#endif // BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
// On other POSIX systems, this is the only key provider. On Linux, it is used
// as a fallback.
providers.emplace_back(
/*precedence=*/5u, std::make_unique<os_crypt_async::PosixKeyProvider>());
#endif // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_MAC)
if (base::FeatureList::IsEnabled(features::kUseKeychainKeyProvider)) {
providers.emplace_back(std::make_pair(
/*precedence=*/10u,
std::make_unique<os_crypt_async::KeychainKeyProvider>()));
}
#endif // BUILDFLAG(IS_MAC)
os_crypt_async_ =
std::make_unique<os_crypt_async::OSCryptAsync>(std::move(providers));
}