Certificates for Lacros (MVP)
This allows Lacros-Chrome access to the system-wide TPM slot, the per-user TPM slot, and per-user storage for certificates and trust settings, for enterprise-managed devices where the logged-in user is an affiliate of that enterprise. Rather than Lacros-Chrome directly interacting with the login services, it requests that Ash-Chrome notify it when the TPM and Cryptohome are available, receiving the path to the per-user storage and the result of TPM initialization. Lacros-Chrome can then initialize initialize a connection to the TPM (via a PKCS#11 module) and initialize storage at the path provided by Ash-Chrome. For users that are not affiliated, Chrome today enables access to both the per-user TPM and per-user storage. However, for Lacros-Chrome, this is a known issue and not yet supported (crbug.com/1146430). This is because loading the TPM unconditionally loads both the system and user slot today, while non-affiliated users should not have access to the system slot. The per-user storage will be loaded for all users with this CL. Similarly, using the system slot on the login screen is not yet supported, and will be addressed in a follow-up (crbug.com/1146430). Bug: 1145946 Change-Id: I2edc6e04c2de09f4c8a4d3bdca9c9ba5a9dee3fa Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2435642 Commit-Queue: Michael Ershov <miersh@google.com> Reviewed-by: David Roger <droger@chromium.org> Reviewed-by: Roland Bock <rbock@google.com> Reviewed-by: Pavol Marko <pmarko@chromium.org> Reviewed-by: Ryan Sleevi <rsleevi@chromium.org> Reviewed-by: Erik Chen <erikchen@chromium.org> Cr-Commit-Position: refs/heads/master@{#832960}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
1340989ccd
commit
1c50ac9546
chrome
browser
BUILD.gn
chromeos
BUILD.gn
crosapi
lacros
cert_db_initializer.cccert_db_initializer.hcert_db_initializer_factory.cccert_db_initializer_factory.h
net
profiles
resources
settings
ssl
ui
webui
test
data
webui
settings
chromeos
crosapi
lacros
crypto
net/cert
@ -4559,6 +4559,10 @@ static_library("browser") {
|
|||||||
"lacros/account_manager_facade_lacros.h",
|
"lacros/account_manager_facade_lacros.h",
|
||||||
"lacros/account_manager_util.cc",
|
"lacros/account_manager_util.cc",
|
||||||
"lacros/account_manager_util.h",
|
"lacros/account_manager_util.h",
|
||||||
|
"lacros/cert_db_initializer.cc",
|
||||||
|
"lacros/cert_db_initializer.h",
|
||||||
|
"lacros/cert_db_initializer_factory.cc",
|
||||||
|
"lacros/cert_db_initializer_factory.h",
|
||||||
"lacros/feedback_util.cc",
|
"lacros/feedback_util.cc",
|
||||||
"lacros/feedback_util.h",
|
"lacros/feedback_util.h",
|
||||||
"lacros/immersive_context_lacros.cc",
|
"lacros/immersive_context_lacros.cc",
|
||||||
|
@ -1041,6 +1041,8 @@ source_set("chromeos") {
|
|||||||
"crosapi/browser_manager_observer.h",
|
"crosapi/browser_manager_observer.h",
|
||||||
"crosapi/browser_util.cc",
|
"crosapi/browser_util.cc",
|
||||||
"crosapi/browser_util.h",
|
"crosapi/browser_util.h",
|
||||||
|
"crosapi/cert_database_ash.cc",
|
||||||
|
"crosapi/cert_database_ash.h",
|
||||||
"crosapi/environment_provider.cc",
|
"crosapi/environment_provider.cc",
|
||||||
"crosapi/environment_provider.h",
|
"crosapi/environment_provider.h",
|
||||||
"crosapi/fake_browser_manager.cc",
|
"crosapi/fake_browser_manager.cc",
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "chrome/browser/browser_process_platform_part.h"
|
#include "chrome/browser/browser_process_platform_part.h"
|
||||||
#include "chrome/browser/chromeos/crosapi/account_manager_ash.h"
|
#include "chrome/browser/chromeos/crosapi/account_manager_ash.h"
|
||||||
#include "chrome/browser/chromeos/crosapi/browser_manager.h"
|
#include "chrome/browser/chromeos/crosapi/browser_manager.h"
|
||||||
|
#include "chrome/browser/chromeos/crosapi/cert_database_ash.h"
|
||||||
#include "chrome/browser/chromeos/crosapi/feedback_ash.h"
|
#include "chrome/browser/chromeos/crosapi/feedback_ash.h"
|
||||||
#include "chrome/browser/chromeos/crosapi/file_manager_ash.h"
|
#include "chrome/browser/chromeos/crosapi/file_manager_ash.h"
|
||||||
#include "chrome/browser/chromeos/crosapi/keystore_service_ash.h"
|
#include "chrome/browser/chromeos/crosapi/keystore_service_ash.h"
|
||||||
@ -39,7 +40,8 @@ namespace crosapi {
|
|||||||
AshChromeServiceImpl::AshChromeServiceImpl(
|
AshChromeServiceImpl::AshChromeServiceImpl(
|
||||||
mojo::PendingReceiver<mojom::AshChromeService> pending_receiver)
|
mojo::PendingReceiver<mojom::AshChromeService> pending_receiver)
|
||||||
: receiver_(this, std::move(pending_receiver)),
|
: receiver_(this, std::move(pending_receiver)),
|
||||||
screen_manager_ash_(std::make_unique<ScreenManagerAsh>()) {
|
screen_manager_ash_(std::make_unique<ScreenManagerAsh>()),
|
||||||
|
cert_database_ash_(std::make_unique<CertDatabaseAsh>()) {
|
||||||
// TODO(hidehiko): Remove non-critical log from here.
|
// TODO(hidehiko): Remove non-critical log from here.
|
||||||
// Currently this is the signal that the connection is established.
|
// Currently this is the signal that the connection is established.
|
||||||
LOG(WARNING) << "AshChromeService connected.";
|
LOG(WARNING) << "AshChromeService connected.";
|
||||||
@ -146,6 +148,11 @@ void AshChromeServiceImpl::BindMediaSessionAudioFocusDebug(
|
|||||||
std::move(receiver));
|
std::move(receiver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AshChromeServiceImpl::BindCertDatabase(
|
||||||
|
mojo::PendingReceiver<mojom::CertDatabase> receiver) {
|
||||||
|
cert_database_ash_->BindReceiver(std::move(receiver));
|
||||||
|
}
|
||||||
|
|
||||||
void AshChromeServiceImpl::OnLacrosStartup(mojom::LacrosInfoPtr lacros_info) {
|
void AshChromeServiceImpl::OnLacrosStartup(mojom::LacrosInfoPtr lacros_info) {
|
||||||
BrowserManager::Get()->set_lacros_version(lacros_info->lacros_version);
|
BrowserManager::Get()->set_lacros_version(lacros_info->lacros_version);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
namespace crosapi {
|
namespace crosapi {
|
||||||
|
|
||||||
class AccountManagerAsh;
|
class AccountManagerAsh;
|
||||||
|
class CertDatabaseAsh;
|
||||||
class FeedbackAsh;
|
class FeedbackAsh;
|
||||||
class FileManagerAsh;
|
class FileManagerAsh;
|
||||||
class KeystoreServiceAsh;
|
class KeystoreServiceAsh;
|
||||||
@ -45,6 +46,8 @@ class AshChromeServiceImpl : public mojom::AshChromeService {
|
|||||||
void BindHidManager(
|
void BindHidManager(
|
||||||
mojo::PendingReceiver<device::mojom::HidManager> receiver) override;
|
mojo::PendingReceiver<device::mojom::HidManager> receiver) override;
|
||||||
void BindFeedback(mojo::PendingReceiver<mojom::Feedback> receiver) override;
|
void BindFeedback(mojo::PendingReceiver<mojom::Feedback> receiver) override;
|
||||||
|
void BindCertDatabase(
|
||||||
|
mojo::PendingReceiver<mojom::CertDatabase> receiver) override;
|
||||||
void OnLacrosStartup(mojom::LacrosInfoPtr lacros_info) override;
|
void OnLacrosStartup(mojom::LacrosInfoPtr lacros_info) override;
|
||||||
void BindMediaSessionController(
|
void BindMediaSessionController(
|
||||||
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
|
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
|
||||||
@ -66,6 +69,7 @@ class AshChromeServiceImpl : public mojom::AshChromeService {
|
|||||||
std::unique_ptr<ScreenManagerAsh> screen_manager_ash_;
|
std::unique_ptr<ScreenManagerAsh> screen_manager_ash_;
|
||||||
std::unique_ptr<SelectFileAsh> select_file_ash_;
|
std::unique_ptr<SelectFileAsh> select_file_ash_;
|
||||||
std::unique_ptr<FeedbackAsh> feedback_ash_;
|
std::unique_ptr<FeedbackAsh> feedback_ash_;
|
||||||
|
std::unique_ptr<CertDatabaseAsh> cert_database_ash_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace crosapi
|
} // namespace crosapi
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "chrome/common/pref_names.h"
|
#include "chrome/common/pref_names.h"
|
||||||
#include "chromeos/constants/chromeos_features.h"
|
#include "chromeos/constants/chromeos_features.h"
|
||||||
#include "chromeos/crosapi/cpp/crosapi_constants.h"
|
#include "chromeos/crosapi/cpp/crosapi_constants.h"
|
||||||
|
#include "chromeos/crosapi/mojom/cert_database.mojom.h"
|
||||||
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
|
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
|
||||||
#include "components/exo/shell_surface_util.h"
|
#include "components/exo/shell_surface_util.h"
|
||||||
#include "components/metrics/metrics_pref_names.h"
|
#include "components/metrics/metrics_pref_names.h"
|
||||||
@ -156,11 +157,12 @@ bool IsLacrosWindow(const aura::Window* window) {
|
|||||||
|
|
||||||
base::flat_map<base::Token, uint32_t> GetInterfaceVersions() {
|
base::flat_map<base::Token, uint32_t> GetInterfaceVersions() {
|
||||||
static_assert(
|
static_assert(
|
||||||
crosapi::mojom::AshChromeService::Version_ == 6,
|
crosapi::mojom::AshChromeService::Version_ == 7,
|
||||||
"if you add a new crosapi, please add it to the version map here");
|
"if you add a new crosapi, please add it to the version map here");
|
||||||
InterfaceVersions versions;
|
InterfaceVersions versions;
|
||||||
AddVersion<crosapi::mojom::AccountManager>(&versions);
|
AddVersion<crosapi::mojom::AccountManager>(&versions);
|
||||||
AddVersion<crosapi::mojom::AshChromeService>(&versions);
|
AddVersion<crosapi::mojom::AshChromeService>(&versions);
|
||||||
|
AddVersion<crosapi::mojom::CertDatabase>(&versions);
|
||||||
AddVersion<crosapi::mojom::Feedback>(&versions);
|
AddVersion<crosapi::mojom::Feedback>(&versions);
|
||||||
AddVersion<crosapi::mojom::FileManager>(&versions);
|
AddVersion<crosapi::mojom::FileManager>(&versions);
|
||||||
AddVersion<crosapi::mojom::KeystoreService>(&versions);
|
AddVersion<crosapi::mojom::KeystoreService>(&versions);
|
||||||
|
115
chrome/browser/chromeos/crosapi/cert_database_ash.cc
Normal file
115
chrome/browser/chromeos/crosapi/cert_database_ash.cc
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// Copyright 2020 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 "chrome/browser/chromeos/crosapi/cert_database_ash.h"
|
||||||
|
|
||||||
|
#include "chrome/browser/chromeos/profiles/profile_helper.h"
|
||||||
|
#include "chrome/browser/profiles/profile_manager.h"
|
||||||
|
#include "chromeos/crosapi/mojom/cert_database.mojom.h"
|
||||||
|
#include "chromeos/login/login_state/login_state.h"
|
||||||
|
|
||||||
|
#include "chromeos/tpm/tpm_token_info_getter.h"
|
||||||
|
#include "components/account_id/account_id.h"
|
||||||
|
#include "components/user_manager/user.h"
|
||||||
|
#include "content/public/browser/browser_thread.h"
|
||||||
|
#include "crypto/nss_util_internal.h"
|
||||||
|
|
||||||
|
namespace crosapi {
|
||||||
|
|
||||||
|
CertDatabaseAsh::CertDatabaseAsh() {
|
||||||
|
DCHECK(chromeos::LoginState::IsInitialized());
|
||||||
|
chromeos::LoginState::Get()->AddObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CertDatabaseAsh::~CertDatabaseAsh() {
|
||||||
|
chromeos::LoginState::Get()->RemoveObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CertDatabaseAsh::BindReceiver(
|
||||||
|
mojo::PendingReceiver<mojom::CertDatabase> pending_receiver) {
|
||||||
|
receivers_.Add(this, std::move(pending_receiver));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CertDatabaseAsh::GetCertDatabaseInfo(
|
||||||
|
GetCertDatabaseInfoCallback callback) {
|
||||||
|
// TODO(crbug.com/1146430): For now Lacros-Chrome will initialize certificate
|
||||||
|
// database only in session. Revisit later to decide what to do on the login
|
||||||
|
// screen.
|
||||||
|
if (!chromeos::LoginState::Get()->IsUserLoggedIn()) {
|
||||||
|
LOG(ERROR) << "Not implemented";
|
||||||
|
std::move(callback).Run(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is the first attempt to load the TPM, begin the async load.
|
||||||
|
if (!is_tpm_token_ready_.has_value()) {
|
||||||
|
WaitForTpmTokenReady(std::move(callback));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user_manager::User* user =
|
||||||
|
user_manager::UserManager::Get()->GetPrimaryUser();
|
||||||
|
|
||||||
|
// If user is not available or the TPM was previously attempted to be loaded,
|
||||||
|
// and failed, don't retry, just return an empty result that indicates error.
|
||||||
|
if (!user || !is_tpm_token_ready_.value()) {
|
||||||
|
std::move(callback).Run(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, if the TPM was already loaded previously, let the
|
||||||
|
// caller know.
|
||||||
|
// TODO(crbug.com/1146430) For now Lacros-Chrome loads chaps and has access to
|
||||||
|
// TPM operations only for affiliated users, because it gives access to
|
||||||
|
// system token. Find a way to give unaffiliated users access only to user TPM
|
||||||
|
// token.
|
||||||
|
mojom::GetCertDatabaseInfoResultPtr result =
|
||||||
|
mojom::GetCertDatabaseInfoResult::New();
|
||||||
|
result->should_load_chaps = user->IsAffiliated();
|
||||||
|
result->software_nss_db_path =
|
||||||
|
crypto::GetSoftwareNSSDBPath(
|
||||||
|
ProfileManager::GetPrimaryUserProfile()->GetPath())
|
||||||
|
.value();
|
||||||
|
std::move(callback).Run(std::move(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CertDatabaseAsh::WaitForTpmTokenReady(
|
||||||
|
GetCertDatabaseInfoCallback callback) {
|
||||||
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||||
|
|
||||||
|
Profile* profile = ProfileManager::GetPrimaryUserProfile();
|
||||||
|
AccountId account_id =
|
||||||
|
chromeos::ProfileHelper::Get()->GetUserByProfile(profile)->GetAccountId();
|
||||||
|
|
||||||
|
std::unique_ptr<chromeos::TPMTokenInfoGetter> scoped_token_info_getter =
|
||||||
|
chromeos::TPMTokenInfoGetter::CreateForUserToken(
|
||||||
|
account_id, chromeos::CryptohomeClient::Get(),
|
||||||
|
base::ThreadTaskRunnerHandle::Get());
|
||||||
|
chromeos::TPMTokenInfoGetter* token_info_getter =
|
||||||
|
scoped_token_info_getter.get();
|
||||||
|
|
||||||
|
token_info_getter->Start(base::BindOnce(
|
||||||
|
&CertDatabaseAsh::OnTpmTokenReady, weak_factory_.GetWeakPtr(),
|
||||||
|
std::move(scoped_token_info_getter), std::move(callback)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CertDatabaseAsh::OnTpmTokenReady(
|
||||||
|
std::unique_ptr<chromeos::TPMTokenInfoGetter> token_getter,
|
||||||
|
GetCertDatabaseInfoCallback callback,
|
||||||
|
base::Optional<chromeos::CryptohomeClient::TpmTokenInfo> token_info) {
|
||||||
|
is_tpm_token_ready_ = token_info.has_value();
|
||||||
|
|
||||||
|
// Calling the initial method again. Since |is_tpm_token_ready_| is not empty
|
||||||
|
// this time, it will return some result via mojo.
|
||||||
|
GetCertDatabaseInfo(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CertDatabaseAsh::LoggedInStateChanged() {
|
||||||
|
// Cached result is valid only within one session and should be reset on
|
||||||
|
// sign out. Currently it is not necessary to reset it on sign in, but doesn't
|
||||||
|
// hurt.
|
||||||
|
is_tpm_token_ready_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace crosapi
|
70
chrome/browser/chromeos/crosapi/cert_database_ash.h
Normal file
70
chrome/browser/chromeos/crosapi/cert_database_ash.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2020 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 CHROME_BROWSER_CHROMEOS_CROSAPI_CERT_DATABASE_ASH_H_
|
||||||
|
#define CHROME_BROWSER_CHROMEOS_CROSAPI_CERT_DATABASE_ASH_H_
|
||||||
|
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
|
#include "base/optional.h"
|
||||||
|
#include "chromeos/crosapi/mojom/cert_database.mojom.h"
|
||||||
|
#include "chromeos/dbus/cryptohome/cryptohome_client.h"
|
||||||
|
#include "chromeos/login/login_state/login_state.h"
|
||||||
|
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||||
|
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||||
|
|
||||||
|
namespace chromeos {
|
||||||
|
class TPMTokenInfoGetter;
|
||||||
|
} // namespace chromeos
|
||||||
|
|
||||||
|
namespace crosapi {
|
||||||
|
|
||||||
|
// Implements the crosapi interface for certificate database. Lives in
|
||||||
|
// Ash-Chrome on the UI thread.
|
||||||
|
//
|
||||||
|
// It is expected that during Lacros-Chrome initialization when it creates the
|
||||||
|
// main profile (that contains device account), it will call GetCertDatabaseInfo
|
||||||
|
// mojo API. If the ChromeOS user session was just started, it can take time for
|
||||||
|
// Ash-Chrome to initialize TPM and certificate database. When it is done, the
|
||||||
|
// API call will be resolved. If Lacros-Chrome is restarted, it will call
|
||||||
|
// GetCertDatabaseInfo again and receive a cached result from the first call.
|
||||||
|
// The cached result is reset on login state change (i.e. sign in / sign out).
|
||||||
|
class CertDatabaseAsh : public mojom::CertDatabase,
|
||||||
|
chromeos::LoginState::Observer {
|
||||||
|
public:
|
||||||
|
CertDatabaseAsh();
|
||||||
|
CertDatabaseAsh(const CertDatabaseAsh&) = delete;
|
||||||
|
CertDatabaseAsh& operator=(const CertDatabaseAsh&) = delete;
|
||||||
|
~CertDatabaseAsh() override;
|
||||||
|
|
||||||
|
void BindReceiver(mojo::PendingReceiver<mojom::CertDatabase> receiver);
|
||||||
|
|
||||||
|
// Returns to Lacros-Chrome all necessary data to initialize certificate
|
||||||
|
// database when it is ready. Caches the result of first call for all
|
||||||
|
// subsequent calls during current user session.
|
||||||
|
void GetCertDatabaseInfo(GetCertDatabaseInfoCallback callback) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// chromeos::LoginState::Observer
|
||||||
|
void LoggedInStateChanged() override;
|
||||||
|
|
||||||
|
// The fact that TpmTokenInfo can be retrieved is used as a signal that
|
||||||
|
// certificate database is ready to be initialized in Lacros-Chrome.
|
||||||
|
void WaitForTpmTokenReady(GetCertDatabaseInfoCallback callback);
|
||||||
|
void OnTpmTokenReady(
|
||||||
|
std::unique_ptr<chromeos::TPMTokenInfoGetter> token_getter,
|
||||||
|
GetCertDatabaseInfoCallback callback,
|
||||||
|
base::Optional<chromeos::CryptohomeClient::TpmTokenInfo> token_info);
|
||||||
|
|
||||||
|
base::Optional<bool> is_tpm_token_ready_;
|
||||||
|
|
||||||
|
// This class supports any number of connections. This allows the client to
|
||||||
|
// have multiple, potentially thread-affine, remotes.
|
||||||
|
mojo::ReceiverSet<mojom::CertDatabase> receivers_;
|
||||||
|
|
||||||
|
base::WeakPtrFactory<CertDatabaseAsh> weak_factory_{this};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace crosapi
|
||||||
|
|
||||||
|
#endif // CHROME_BROWSER_CHROMEOS_CROSAPI_CERT_DATABASE_ASH_H_
|
117
chrome/browser/lacros/cert_db_initializer.cc
Normal file
117
chrome/browser/lacros/cert_db_initializer.cc
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// Copyright 2020 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 "chrome/browser/lacros/cert_db_initializer.h"
|
||||||
|
|
||||||
|
#include "base/callback_forward.h"
|
||||||
|
#include "base/check.h"
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
|
#include "chrome/browser/profiles/profile.h"
|
||||||
|
#include "chromeos/crosapi/cpp/crosapi_constants.h"
|
||||||
|
#include "chromeos/crosapi/mojom/cert_database.mojom.h"
|
||||||
|
#include "components/signin/public/identity_manager/identity_manager.h"
|
||||||
|
#include "crypto/chaps_support.h"
|
||||||
|
#include "crypto/nss_util.h"
|
||||||
|
#include "crypto/nss_util_internal.h"
|
||||||
|
#include "mojo/public/cpp/bindings/remote.h"
|
||||||
|
|
||||||
|
class IdentityManagerObserver : public signin::IdentityManager::Observer {
|
||||||
|
public:
|
||||||
|
explicit IdentityManagerObserver(signin::IdentityManager* identity_manager)
|
||||||
|
: identity_manager_(identity_manager) {
|
||||||
|
DCHECK(identity_manager_);
|
||||||
|
identity_manager_->AddObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
IdentityManagerObserver(const IdentityManagerObserver&) = delete;
|
||||||
|
IdentityManagerObserver& operator==(const IdentityManagerObserver&) = delete;
|
||||||
|
|
||||||
|
~IdentityManagerObserver() override {
|
||||||
|
identity_manager_->RemoveObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForRefreshTokensLoaded(base::OnceClosure callback) {
|
||||||
|
DCHECK(callback_.is_null());
|
||||||
|
callback_ = std::move(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnRefreshTokensLoaded() override {
|
||||||
|
if (!callback_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::move(callback_).Run(); // NOTE: may delete `this`.
|
||||||
|
}
|
||||||
|
|
||||||
|
signin::IdentityManager* identity_manager_ = nullptr;
|
||||||
|
base::OnceClosure callback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
CertDbInitializer::CertDbInitializer(
|
||||||
|
mojo::Remote<crosapi::mojom::CertDatabase>& cert_database_remote,
|
||||||
|
Profile* profile)
|
||||||
|
: cert_database_remote_(cert_database_remote), profile_(profile) {}
|
||||||
|
|
||||||
|
CertDbInitializer::~CertDbInitializer() = default;
|
||||||
|
|
||||||
|
void CertDbInitializer::Start(signin::IdentityManager* identity_manager) {
|
||||||
|
DCHECK(identity_manager);
|
||||||
|
// TODO(crbug.com/1148300): This is temporary. Until ~2021
|
||||||
|
// `Profile::IsMainProfile()` method can return a false negative response if
|
||||||
|
// called before refresh tokens are loaded. This should be removed together
|
||||||
|
// with the entire usage of `IdentityManager` in this class when it is not the
|
||||||
|
// case anymore.
|
||||||
|
if (!identity_manager->AreRefreshTokensLoaded()) {
|
||||||
|
identity_manager_observer_ =
|
||||||
|
std::make_unique<IdentityManagerObserver>(identity_manager);
|
||||||
|
identity_manager_observer_->WaitForRefreshTokensLoaded(base::BindOnce(
|
||||||
|
&CertDbInitializer::OnRefreshTokensLoaded, weak_factory_.GetWeakPtr()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WaitForCertDbReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CertDbInitializer::OnRefreshTokensLoaded() {
|
||||||
|
identity_manager_observer_.reset();
|
||||||
|
WaitForCertDbReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CertDbInitializer::WaitForCertDbReady() {
|
||||||
|
if (!profile_->IsMainProfile()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cert_database_remote_->GetCertDatabaseInfo(base::BindOnce(
|
||||||
|
&CertDbInitializer::OnCertDbInfoReceived, weak_factory_.GetWeakPtr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CertDbInitializer::OnCertDbInfoReceived(
|
||||||
|
crosapi::mojom::GetCertDatabaseInfoResultPtr cert_db_info) {
|
||||||
|
if (!cert_db_info) {
|
||||||
|
LOG(WARNING) << "Certificate database is not accesible";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto::EnsureNSSInit();
|
||||||
|
|
||||||
|
// There's no need to save the result of `LoadChaps()`, chaps will stay loaded
|
||||||
|
// and can be used anyway. Using the result only to determine success/failure.
|
||||||
|
if (cert_db_info->should_load_chaps && !crypto::LoadChaps()) {
|
||||||
|
LOG(ERROR) << "Failed to load chaps.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The slot doesn't need to be saved either. `description` doesn't affect
|
||||||
|
// anything. `software_nss_db_path` file path should be already created by
|
||||||
|
// Ash-Chrome.
|
||||||
|
base::FilePath software_nss_db_path(cert_db_info->software_nss_db_path);
|
||||||
|
auto slot = crypto::OpenSoftwareNSSDB(software_nss_db_path,
|
||||||
|
/*description=*/"cert_db");
|
||||||
|
if (!slot) {
|
||||||
|
LOG(ERROR) << "Failed to open user certificate database";
|
||||||
|
}
|
||||||
|
}
|
47
chrome/browser/lacros/cert_db_initializer.h
Normal file
47
chrome/browser/lacros/cert_db_initializer.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2020 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 CHROME_BROWSER_LACROS_CERT_DB_INITIALIZER_H_
|
||||||
|
#define CHROME_BROWSER_LACROS_CERT_DB_INITIALIZER_H_
|
||||||
|
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
|
#include "chromeos/crosapi/mojom/cert_database.mojom.h"
|
||||||
|
#include "components/keyed_service/core/keyed_service.h"
|
||||||
|
#include "components/signin/public/identity_manager/identity_manager.h"
|
||||||
|
#include "mojo/public/cpp/bindings/remote.h"
|
||||||
|
|
||||||
|
class Profile;
|
||||||
|
class IdentityManagerObserver;
|
||||||
|
|
||||||
|
// Initializes certificate database in Lacros-Chrome.
|
||||||
|
class CertDbInitializer : public KeyedService {
|
||||||
|
public:
|
||||||
|
CertDbInitializer(
|
||||||
|
mojo::Remote<crosapi::mojom::CertDatabase>& cert_database_remote,
|
||||||
|
Profile* profile);
|
||||||
|
~CertDbInitializer() override;
|
||||||
|
|
||||||
|
void Start(signin::IdentityManager* identity_manager);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Starts the initialization. The first step is to wait for IdentityManager.
|
||||||
|
|
||||||
|
void OnRefreshTokensLoaded();
|
||||||
|
|
||||||
|
// Checks that the current profile is the main profile and, if yes, makes a
|
||||||
|
// mojo request to Ash-Chrome to get information about certificate database.
|
||||||
|
void WaitForCertDbReady();
|
||||||
|
|
||||||
|
// Checks from the result that the certificate database should be initialized.
|
||||||
|
// If yes, loads Chaps and opens user's certificate database.
|
||||||
|
void OnCertDbInfoReceived(
|
||||||
|
crosapi::mojom::GetCertDatabaseInfoResultPtr result);
|
||||||
|
|
||||||
|
mojo::Remote<crosapi::mojom::CertDatabase>& cert_database_remote_;
|
||||||
|
Profile* profile_ = nullptr;
|
||||||
|
std::unique_ptr<IdentityManagerObserver> identity_manager_observer_;
|
||||||
|
base::WeakPtrFactory<CertDbInitializer> weak_factory_{this};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHROME_BROWSER_LACROS_CERT_DB_INITIALIZER_H_
|
49
chrome/browser/lacros/cert_db_initializer_factory.cc
Normal file
49
chrome/browser/lacros/cert_db_initializer_factory.cc
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2020 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 "chrome/browser/lacros/cert_db_initializer_factory.h"
|
||||||
|
|
||||||
|
#include "chrome/browser/lacros/cert_db_initializer.h"
|
||||||
|
#include "chrome/browser/profiles/profile.h"
|
||||||
|
#include "chrome/browser/signin/identity_manager_factory.h"
|
||||||
|
#include "chromeos/lacros/lacros_chrome_service_impl.h"
|
||||||
|
#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
||||||
|
|
||||||
|
class Profile;
|
||||||
|
|
||||||
|
// static
|
||||||
|
CertDbInitializerFactory* CertDbInitializerFactory::GetInstance() {
|
||||||
|
static base::NoDestructor<CertDbInitializerFactory> factory;
|
||||||
|
return factory.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
CertDbInitializerFactory::CertDbInitializerFactory()
|
||||||
|
: BrowserContextKeyedServiceFactory(
|
||||||
|
"CertDbInitializerFactory",
|
||||||
|
BrowserContextDependencyManager::GetInstance()) {
|
||||||
|
DependsOn(IdentityManagerFactory::GetInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CertDbInitializerFactory::ServiceIsCreatedWithBrowserContext() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyedService* CertDbInitializerFactory::BuildServiceInstanceFor(
|
||||||
|
content::BrowserContext* context) const {
|
||||||
|
Profile* profile = Profile::FromBrowserContext(context);
|
||||||
|
|
||||||
|
if (!chromeos::LacrosChromeServiceImpl::Get()->IsCertDbAvailable()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CertDbInitializer* result = new CertDbInitializer(
|
||||||
|
chromeos::LacrosChromeServiceImpl::Get()->cert_database_remote(),
|
||||||
|
profile);
|
||||||
|
// TODO(crbug.com/1145946): Enable certificate database initialization when
|
||||||
|
// the policy stack is ready (expected to happen before Feb 2021).
|
||||||
|
if (/* DISABLES CODE */ (false)) {
|
||||||
|
result->Start(IdentityManagerFactory::GetForProfile(profile));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
27
chrome/browser/lacros/cert_db_initializer_factory.h
Normal file
27
chrome/browser/lacros/cert_db_initializer_factory.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2020 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 CHROME_BROWSER_LACROS_CERT_DB_INITIALIZER_FACTORY_H_
|
||||||
|
#define CHROME_BROWSER_LACROS_CERT_DB_INITIALIZER_FACTORY_H_
|
||||||
|
|
||||||
|
#include "base/no_destructor.h"
|
||||||
|
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
|
||||||
|
|
||||||
|
class CertDbInitializerFactory : public BrowserContextKeyedServiceFactory {
|
||||||
|
public:
|
||||||
|
static CertDbInitializerFactory* GetInstance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class base::NoDestructor<CertDbInitializerFactory>;
|
||||||
|
|
||||||
|
CertDbInitializerFactory();
|
||||||
|
~CertDbInitializerFactory() override = default;
|
||||||
|
|
||||||
|
// BrowserStateKeyedServiceFactory
|
||||||
|
bool ServiceIsCreatedWithBrowserContext() const override;
|
||||||
|
KeyedService* BuildServiceInstanceFor(
|
||||||
|
content::BrowserContext* context) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHROME_BROWSER_LACROS_CERT_DB_INITIALIZER_FACTORY_H_
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "chrome/browser/net/nss_context.h"
|
#include "chrome/browser/net/nss_context.h"
|
||||||
|
|
||||||
|
#include "build/chromeos_buildflags.h"
|
||||||
#include "content/public/browser/browser_thread.h"
|
#include "content/public/browser/browser_thread.h"
|
||||||
#include "crypto/nss_util.h"
|
#include "crypto/nss_util.h"
|
||||||
#include "net/cert/nss_cert_database.h"
|
#include "net/cert/nss_cert_database.h"
|
||||||
@ -18,6 +19,13 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
|
|||||||
// This initialization is not thread safe. This CHECK ensures that this code
|
// This initialization is not thread safe. This CHECK ensures that this code
|
||||||
// is only run on a single thread.
|
// is only run on a single thread.
|
||||||
CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
|
CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_LACROS)
|
||||||
|
// TODO(crbug.com/1147032): remove the CHECK after the certificates settings
|
||||||
|
// page is updated.
|
||||||
|
CHECK(false) << "Currently disabled for Lacros-Chrome.";
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!g_nss_cert_database) {
|
if (!g_nss_cert_database) {
|
||||||
// Linux has only a single persistent slot compared to ChromeOS's separate
|
// Linux has only a single persistent slot compared to ChromeOS's separate
|
||||||
// public and private slot.
|
// public and private slot.
|
||||||
|
@ -576,6 +576,15 @@ ProfileNetworkContextService::CreateClientCertStore() {
|
|||||||
base::BindRepeating(&CreateCryptoModuleBlockingPasswordDelegate,
|
base::BindRepeating(&CreateCryptoModuleBlockingPasswordDelegate,
|
||||||
kCryptoModulePasswordClientAuth));
|
kCryptoModulePasswordClientAuth));
|
||||||
#elif defined(USE_NSS_CERTS)
|
#elif defined(USE_NSS_CERTS)
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_LACROS)
|
||||||
|
if (!profile_->IsMainProfile()) {
|
||||||
|
// TODO(crbug.com/1148298): return some cert store for secondary profiles in
|
||||||
|
// Lacros-Chrome.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif // BUILDFLAG(IS_LACROS)
|
||||||
|
|
||||||
return std::make_unique<net::ClientCertStoreNSS>(
|
return std::make_unique<net::ClientCertStoreNSS>(
|
||||||
base::BindRepeating(&CreateCryptoModuleBlockingPasswordDelegate,
|
base::BindRepeating(&CreateCryptoModuleBlockingPasswordDelegate,
|
||||||
kCryptoModulePasswordClientAuth));
|
kCryptoModulePasswordClientAuth));
|
||||||
|
@ -189,6 +189,10 @@
|
|||||||
#include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h"
|
#include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_LACROS)
|
||||||
|
#include "chrome/browser/lacros/cert_db_initializer_factory.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace chrome {
|
namespace chrome {
|
||||||
|
|
||||||
void AddProfilesExtraParts(ChromeBrowserMainParts* main_parts) {
|
void AddProfilesExtraParts(ChromeBrowserMainParts* main_parts) {
|
||||||
@ -432,6 +436,10 @@ void ChromeBrowserMainExtraPartsProfiles::
|
|||||||
#endif
|
#endif
|
||||||
WebDataServiceFactory::GetInstance();
|
WebDataServiceFactory::GetInstance();
|
||||||
webrtc_event_logging::WebRtcEventLogManagerKeyedServiceFactory::GetInstance();
|
webrtc_event_logging::WebRtcEventLogManagerKeyedServiceFactory::GetInstance();
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_LACROS)
|
||||||
|
CertDbInitializerFactory::GetInstance();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChromeBrowserMainExtraPartsProfiles::PreProfileInit() {
|
void ChromeBrowserMainExtraPartsProfiles::PreProfileInit() {
|
||||||
|
@ -18,7 +18,9 @@ function addPrivacyChildRoutes(r) {
|
|||||||
r.COOKIES = r.PRIVACY.createChild('/cookies');
|
r.COOKIES = r.PRIVACY.createChild('/cookies');
|
||||||
r.SECURITY = r.PRIVACY.createChild('/security');
|
r.SECURITY = r.PRIVACY.createChild('/security');
|
||||||
|
|
||||||
// <if expr="use_nss_certs">
|
// TODO(crbug.com/1147032): The certificates settings page is temporarily
|
||||||
|
// disabled for Lacros-Chrome until a better solution is found.
|
||||||
|
// <if expr="use_nss_certs and not lacros">
|
||||||
r.CERTIFICATES = r.SECURITY.createChild('/certificates');
|
r.CERTIFICATES = r.SECURITY.createChild('/certificates');
|
||||||
// </if>
|
// </if>
|
||||||
|
|
||||||
|
@ -1994,6 +1994,11 @@ IN_PROC_BROWSER_TEST_F(SSLUITestWithHttpDangerous, MarkBlobAsNonSecure) {
|
|||||||
EXPECT_EQ(security_state::NONE, helper->GetSecurityLevel());
|
EXPECT_EQ(security_state::NONE, helper->GetSecurityLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(crbug.com/1148302): This class directly calls
|
||||||
|
// `GetNSSCertDatabaseForProfile()` that causes crash at the moment and is never
|
||||||
|
// called from Lacros-Chrome. This should be revisited when there is a solution
|
||||||
|
// for the client certificates settings page on Lacros-Chrome.
|
||||||
|
#if !BUILDFLAG(IS_LACROS)
|
||||||
#if defined(USE_NSS_CERTS)
|
#if defined(USE_NSS_CERTS)
|
||||||
class SSLUITestWithClientCert : public SSLUITestBase {
|
class SSLUITestWithClientCert : public SSLUITestBase {
|
||||||
public:
|
public:
|
||||||
@ -2084,6 +2089,7 @@ IN_PROC_BROWSER_TEST_F(SSLUITestWithClientCert, TestWSSClientCert) {
|
|||||||
EXPECT_TRUE(base::LowerCaseEqualsASCII(result, "pass"));
|
EXPECT_TRUE(base::LowerCaseEqualsASCII(result, "pass"));
|
||||||
}
|
}
|
||||||
#endif // defined(USE_NSS_CERTS)
|
#endif // defined(USE_NSS_CERTS)
|
||||||
|
#endif // !BUILDFLAG(IS_LACROS)
|
||||||
|
|
||||||
// A stub ClientCertStore that returns a FakeClientCertIdentity.
|
// A stub ClientCertStore that returns a FakeClientCertIdentity.
|
||||||
class ClientCertStoreStub : public net::ClientCertStore {
|
class ClientCertStoreStub : public net::ClientCertStore {
|
||||||
|
@ -701,8 +701,12 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
|
|||||||
return &NewWebUI<chromeos::BluetoothPairingDialogUI>;
|
return &NewWebUI<chromeos::BluetoothPairingDialogUI>;
|
||||||
if (url.host_piece() == chrome::kChromeUICellularSetupHost)
|
if (url.host_piece() == chrome::kChromeUICellularSetupHost)
|
||||||
return &NewWebUI<chromeos::cellular_setup::CellularSetupDialogUI>;
|
return &NewWebUI<chromeos::cellular_setup::CellularSetupDialogUI>;
|
||||||
|
// TODO(crbug.com/1147032): The certificates settings page is temporarily
|
||||||
|
// disabled for Lacros-Chrome until a better solution is found.
|
||||||
|
#if !BUILDFLAG(IS_LACROS)
|
||||||
if (url.host_piece() == chrome::kChromeUICertificateManagerHost)
|
if (url.host_piece() == chrome::kChromeUICertificateManagerHost)
|
||||||
return &NewWebUI<chromeos::CertificateManagerDialogUI>;
|
return &NewWebUI<chromeos::CertificateManagerDialogUI>;
|
||||||
|
#endif // !BUILDFLAG(IS_LACROS)
|
||||||
if (base::FeatureList::IsEnabled(
|
if (base::FeatureList::IsEnabled(
|
||||||
chromeos::features::kConnectivityDiagnosticsWebUi) &&
|
chromeos::features::kConnectivityDiagnosticsWebUi) &&
|
||||||
url.host_piece() == chromeos::kChromeUIConnectivityDiagnosticsHost) {
|
url.host_piece() == chromeos::kChromeUIConnectivityDiagnosticsHost) {
|
||||||
|
@ -166,6 +166,9 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
|
|||||||
|
|
||||||
AddSettingsPageUIHandler(std::make_unique<AppearanceHandler>(web_ui));
|
AddSettingsPageUIHandler(std::make_unique<AppearanceHandler>(web_ui));
|
||||||
|
|
||||||
|
// TODO(crbug.com/1147032): The certificates settings page is temporarily
|
||||||
|
// disabled for Lacros-Chrome until a better solution is found.
|
||||||
|
#if !BUILDFLAG(IS_LACROS)
|
||||||
#if defined(USE_NSS_CERTS)
|
#if defined(USE_NSS_CERTS)
|
||||||
AddSettingsPageUIHandler(
|
AddSettingsPageUIHandler(
|
||||||
std::make_unique<certificate_manager::CertificatesHandler>());
|
std::make_unique<certificate_manager::CertificatesHandler>());
|
||||||
@ -176,7 +179,8 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
|
|||||||
AddSettingsPageUIHandler(
|
AddSettingsPageUIHandler(
|
||||||
chromeos::cert_provisioning::CertificateProvisioningUiHandler::
|
chromeos::cert_provisioning::CertificateProvisioningUiHandler::
|
||||||
CreateForProfile(profile));
|
CreateForProfile(profile));
|
||||||
#endif
|
#endif // defined(OS_CHROMEOS)
|
||||||
|
#endif // !BUILDFLAG(IS_LACROS)
|
||||||
|
|
||||||
AddSettingsPageUIHandler(std::make_unique<AccessibilityMainHandler>());
|
AddSettingsPageUIHandler(std::make_unique<AccessibilityMainHandler>());
|
||||||
AddSettingsPageUIHandler(std::make_unique<BrowserLifetimeHandler>());
|
AddSettingsPageUIHandler(std::make_unique<BrowserLifetimeHandler>());
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
import {isMac, isWindows} from 'chrome://resources/js/cr.m.js';
|
import {isLacros, isMac, isWindows} from 'chrome://resources/js/cr.m.js';
|
||||||
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
|
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
|
||||||
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
|
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
|
||||||
import {SafeBrowsingSetting} from 'chrome://settings/lazy_load.js';
|
import {SafeBrowsingSetting} from 'chrome://settings/lazy_load.js';
|
||||||
@ -87,12 +87,18 @@ suite('CrSettingsSecurityPageTest', function() {
|
|||||||
assertTrue(page.$$('#safeBrowsingStandard').expanded);
|
assertTrue(page.$$('#safeBrowsingStandard').expanded);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('LogManageCerfificatesClick', async function() {
|
// TODO(crbug.com/1148302): This class directly calls
|
||||||
page.$$('#manageCertificates').click();
|
// `GetNSSCertDatabaseForProfile()` that causes crash at the moment and is
|
||||||
const result =
|
// never called from Lacros-Chrome. This should be revisited when there is a
|
||||||
await testMetricsBrowserProxy.whenCalled('recordSettingsPageHistogram');
|
// solution for the client certificates settings page on Lacros-Chrome.
|
||||||
assertEquals(PrivacyElementInteractions.MANAGE_CERTIFICATES, result);
|
if (!isLacros) {
|
||||||
});
|
test('LogManageCerfificatesClick', async function() {
|
||||||
|
page.$$('#manageCertificates').click();
|
||||||
|
const result = await testMetricsBrowserProxy.whenCalled(
|
||||||
|
'recordSettingsPageHistogram');
|
||||||
|
assertEquals(PrivacyElementInteractions.MANAGE_CERTIFICATES, result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
test('ManageSecurityKeysSubpageVisible', function() {
|
test('ManageSecurityKeysSubpageVisible', function() {
|
||||||
assertTrue(isChildVisible(page, '#security-keys-subpage-trigger'));
|
assertTrue(isChildVisible(page, '#security-keys-subpage-trigger'));
|
||||||
|
@ -8,6 +8,7 @@ mojom("mojom") {
|
|||||||
sources = [
|
sources = [
|
||||||
"account_manager.mojom",
|
"account_manager.mojom",
|
||||||
"bitmap.mojom",
|
"bitmap.mojom",
|
||||||
|
"cert_database.mojom",
|
||||||
"crosapi.mojom",
|
"crosapi.mojom",
|
||||||
"feedback.mojom",
|
"feedback.mojom",
|
||||||
"file_manager.mojom",
|
"file_manager.mojom",
|
||||||
|
19
chromeos/crosapi/mojom/cert_database.mojom
Normal file
19
chromeos/crosapi/mojom/cert_database.mojom
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2020 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.
|
||||||
|
|
||||||
|
module crosapi.mojom;
|
||||||
|
|
||||||
|
[Stable, Extensible]
|
||||||
|
struct GetCertDatabaseInfoResult {
|
||||||
|
string software_nss_db_path@0;
|
||||||
|
bool should_load_chaps@1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This interface is implemented by Ash-Chrome.
|
||||||
|
[Stable, Uuid="e7f924bf-0e10-4aef-98d3-6e2f216dc914"]
|
||||||
|
interface CertDatabase {
|
||||||
|
// Waits until Ash-Chrome finishes certificate database initialization and
|
||||||
|
// returns necessary data for Lacros-Chrome to connect to it.
|
||||||
|
GetCertDatabaseInfo@0() => (GetCertDatabaseInfoResult? result);
|
||||||
|
};
|
@ -5,6 +5,7 @@
|
|||||||
module crosapi.mojom;
|
module crosapi.mojom;
|
||||||
|
|
||||||
import "chromeos/crosapi/mojom/account_manager.mojom";
|
import "chromeos/crosapi/mojom/account_manager.mojom";
|
||||||
|
import "chromeos/crosapi/mojom/cert_database.mojom";
|
||||||
import "chromeos/crosapi/mojom/feedback.mojom";
|
import "chromeos/crosapi/mojom/feedback.mojom";
|
||||||
import "chromeos/crosapi/mojom/file_manager.mojom";
|
import "chromeos/crosapi/mojom/file_manager.mojom";
|
||||||
import "chromeos/crosapi/mojom/keystore_service.mojom";
|
import "chromeos/crosapi/mojom/keystore_service.mojom";
|
||||||
@ -39,8 +40,8 @@ struct LacrosInfo {
|
|||||||
// milestone when you added it, to help us reason about compatibility between
|
// milestone when you added it, to help us reason about compatibility between
|
||||||
// lacros-chrome and older ash-chrome binaries.
|
// lacros-chrome and older ash-chrome binaries.
|
||||||
//
|
//
|
||||||
// Next version: 7
|
// Next version: 8
|
||||||
// Next method id: 12
|
// Next method id: 13
|
||||||
[Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e"]
|
[Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e"]
|
||||||
interface AshChromeService {
|
interface AshChromeService {
|
||||||
// Binds Chrome OS Account Manager for Identity management.
|
// Binds Chrome OS Account Manager for Identity management.
|
||||||
@ -96,6 +97,11 @@ interface AshChromeService {
|
|||||||
[MinVersion=6] BindMediaSessionAudioFocusDebug@11(
|
[MinVersion=6] BindMediaSessionAudioFocusDebug@11(
|
||||||
pending_receiver<media_session.mojom.AudioFocusManagerDebug> receiver);
|
pending_receiver<media_session.mojom.AudioFocusManagerDebug> receiver);
|
||||||
|
|
||||||
|
// Binds the CertDatabase interface for initializing certificate database in
|
||||||
|
// Lacros-Chrome.
|
||||||
|
// Added in M89.
|
||||||
|
[MinVersion=7] BindCertDatabase@12(pending_receiver<CertDatabase> receiver);
|
||||||
|
|
||||||
// Passes generic lacros information such as lacros version, etc into ash
|
// Passes generic lacros information such as lacros version, etc into ash
|
||||||
// in |lacros_info| during startup.
|
// in |lacros_info| during startup.
|
||||||
// Added in M87.
|
// Added in M87.
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/task/task_traits.h"
|
#include "base/task/task_traits.h"
|
||||||
#include "base/task/thread_pool.h"
|
#include "base/task/thread_pool.h"
|
||||||
|
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
|
||||||
#include "chromeos/lacros/lacros_chrome_service_delegate.h"
|
#include "chromeos/lacros/lacros_chrome_service_delegate.h"
|
||||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||||
#include "url/gurl.h"
|
#include "url/gurl.h"
|
||||||
@ -164,6 +165,12 @@ class LacrosChromeServiceNeverBlockingState
|
|||||||
ash_chrome_service_->BindFeedback(std::move(pending_receiver));
|
ash_chrome_service_->BindFeedback(std::move(pending_receiver));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BindCertDbReceiver(
|
||||||
|
mojo::PendingReceiver<crosapi::mojom::CertDatabase> pending_receiver) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
ash_chrome_service_->BindCertDatabase(std::move(pending_receiver));
|
||||||
|
}
|
||||||
|
|
||||||
void OnLacrosStartup(crosapi::mojom::LacrosInfoPtr lacros_info) {
|
void OnLacrosStartup(crosapi::mojom::LacrosInfoPtr lacros_info) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
ash_chrome_service_->OnLacrosStartup(std::move(lacros_info));
|
ash_chrome_service_->OnLacrosStartup(std::move(lacros_info));
|
||||||
@ -355,6 +362,15 @@ void LacrosChromeServiceImpl::BindReceiver(
|
|||||||
feedback_remote_.BindNewPipeAndPassReceiver()));
|
feedback_remote_.BindNewPipeAndPassReceiver()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsCertDbAvailable()) {
|
||||||
|
never_blocking_sequence_->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::BindOnce(
|
||||||
|
&LacrosChromeServiceNeverBlockingState::BindCertDbReceiver,
|
||||||
|
weak_sequenced_state_,
|
||||||
|
cert_database_remote_.BindNewPipeAndPassReceiver()));
|
||||||
|
}
|
||||||
|
|
||||||
if (IsOnLacrosStartupAvailable()) {
|
if (IsOnLacrosStartupAvailable()) {
|
||||||
never_blocking_sequence_->PostTask(
|
never_blocking_sequence_->PostTask(
|
||||||
FROM_HERE,
|
FROM_HERE,
|
||||||
@ -500,6 +516,13 @@ void LacrosChromeServiceImpl::BindMediaControllerManager(
|
|||||||
weak_sequenced_state_, std::move(remote)));
|
weak_sequenced_state_, std::move(remote)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LacrosChromeServiceImpl::IsCertDbAvailable() {
|
||||||
|
base::Optional<uint32_t> version = AshChromeServiceVersion();
|
||||||
|
return version &&
|
||||||
|
version.value() >=
|
||||||
|
AshChromeService::MethodMinVersions::kBindCertDatabaseMinVersion;
|
||||||
|
}
|
||||||
|
|
||||||
bool LacrosChromeServiceImpl::IsOnLacrosStartupAvailable() {
|
bool LacrosChromeServiceImpl::IsOnLacrosStartupAvailable() {
|
||||||
base::Optional<uint32_t> version = AshChromeServiceVersion();
|
base::Optional<uint32_t> version = AshChromeServiceVersion();
|
||||||
return version &&
|
return version &&
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "base/sequence_checker.h"
|
#include "base/sequence_checker.h"
|
||||||
#include "base/sequenced_task_runner.h"
|
#include "base/sequenced_task_runner.h"
|
||||||
#include "chromeos/crosapi/mojom/account_manager.mojom.h"
|
#include "chromeos/crosapi/mojom/account_manager.mojom.h"
|
||||||
|
#include "chromeos/crosapi/mojom/cert_database.mojom.h"
|
||||||
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
|
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
|
||||||
#include "chromeos/crosapi/mojom/feedback.mojom.h"
|
#include "chromeos/crosapi/mojom/feedback.mojom.h"
|
||||||
#include "chromeos/crosapi/mojom/keystore_service.mojom.h"
|
#include "chromeos/crosapi/mojom/keystore_service.mojom.h"
|
||||||
@ -161,6 +162,15 @@ class COMPONENT_EXPORT(CHROMEOS_LACROS) LacrosChromeServiceImpl {
|
|||||||
void BindMediaControllerManager(
|
void BindMediaControllerManager(
|
||||||
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
|
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
|
||||||
remote);
|
remote);
|
||||||
|
// cert_database_remote() can only be used when this method returns true;
|
||||||
|
bool IsCertDbAvailable();
|
||||||
|
|
||||||
|
// This must be called on the affine sequence.
|
||||||
|
mojo::Remote<crosapi::mojom::CertDatabase>& cert_database_remote() {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(affine_sequence_checker_);
|
||||||
|
DCHECK(IsCertDbAvailable());
|
||||||
|
return cert_database_remote_;
|
||||||
|
}
|
||||||
|
|
||||||
// file_manager_remote() can only be used if this method returns true.
|
// file_manager_remote() can only be used if this method returns true.
|
||||||
bool IsFileManagerAvailable();
|
bool IsFileManagerAvailable();
|
||||||
@ -251,6 +261,7 @@ class COMPONENT_EXPORT(CHROMEOS_LACROS) LacrosChromeServiceImpl {
|
|||||||
mojo::Remote<crosapi::mojom::SelectFile> select_file_remote_;
|
mojo::Remote<crosapi::mojom::SelectFile> select_file_remote_;
|
||||||
mojo::Remote<device::mojom::HidManager> hid_manager_remote_;
|
mojo::Remote<device::mojom::HidManager> hid_manager_remote_;
|
||||||
mojo::Remote<crosapi::mojom::Feedback> feedback_remote_;
|
mojo::Remote<crosapi::mojom::Feedback> feedback_remote_;
|
||||||
|
mojo::Remote<crosapi::mojom::CertDatabase> cert_database_remote_;
|
||||||
mojo::Remote<crosapi::mojom::KeystoreService> keystore_service_remote_;
|
mojo::Remote<crosapi::mojom::KeystoreService> keystore_service_remote_;
|
||||||
mojo::Remote<crosapi::mojom::FileManager> file_manager_remote_;
|
mojo::Remote<crosapi::mojom::FileManager> file_manager_remote_;
|
||||||
|
|
||||||
|
@ -123,6 +123,13 @@ component("crypto") {
|
|||||||
sources += [ "nss_util_chromeos.cc" ]
|
sources += [ "nss_util_chromeos.cc" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_chromeos || is_lacros) {
|
||||||
|
sources += [
|
||||||
|
"chaps_support.cc",
|
||||||
|
"chaps_support.h",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
defines = [ "CRYPTO_IMPLEMENTATION" ]
|
defines = [ "CRYPTO_IMPLEMENTATION" ]
|
||||||
|
|
||||||
if (is_nacl) {
|
if (is_nacl) {
|
||||||
|
88
crypto/chaps_support.cc
Normal file
88
crypto/chaps_support.cc
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Copyright 2020 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 "crypto/chaps_support.h"
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <secmodt.h>
|
||||||
|
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/threading/scoped_blocking_call.h"
|
||||||
|
#include "nss_util_internal.h"
|
||||||
|
|
||||||
|
namespace crypto {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Constants for loading the Chrome OS TPM-backed PKCS #11 library.
|
||||||
|
const char kChapsModuleName[] = "Chaps";
|
||||||
|
const char kChapsPath[] = "libchaps.so";
|
||||||
|
|
||||||
|
class ScopedChapsLoadFixup {
|
||||||
|
public:
|
||||||
|
ScopedChapsLoadFixup();
|
||||||
|
~ScopedChapsLoadFixup();
|
||||||
|
|
||||||
|
private:
|
||||||
|
#if defined(COMPONENT_BUILD)
|
||||||
|
void* chaps_handle_;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(COMPONENT_BUILD)
|
||||||
|
|
||||||
|
ScopedChapsLoadFixup::ScopedChapsLoadFixup() {
|
||||||
|
// HACK: libchaps links the system protobuf and there are symbol conflicts
|
||||||
|
// with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround.
|
||||||
|
chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {
|
||||||
|
// LoadNSSModule() will have taken a 2nd reference.
|
||||||
|
if (chaps_handle_)
|
||||||
|
dlclose(chaps_handle_);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
ScopedChapsLoadFixup::ScopedChapsLoadFixup() = default;
|
||||||
|
ScopedChapsLoadFixup::~ScopedChapsLoadFixup() = default;
|
||||||
|
|
||||||
|
#endif // defined(COMPONENT_BUILD)
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
SECMODModule* LoadChaps() {
|
||||||
|
// NSS functions may reenter //net via extension hooks. If the reentered
|
||||||
|
// code needs to synchronously wait for a task to run but the thread pool in
|
||||||
|
// which that task must run doesn't have enough threads to schedule it, a
|
||||||
|
// deadlock occurs. To prevent that, the base::ScopedBlockingCall below
|
||||||
|
// increments the thread pool capacity for the duration of the TPM
|
||||||
|
// initialization.
|
||||||
|
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
|
||||||
|
base::BlockingType::WILL_BLOCK);
|
||||||
|
|
||||||
|
ScopedChapsLoadFixup chaps_loader;
|
||||||
|
|
||||||
|
DVLOG(3) << "Loading chaps...";
|
||||||
|
return LoadNSSModule(
|
||||||
|
kChapsModuleName, kChapsPath,
|
||||||
|
// For more details on these parameters, see:
|
||||||
|
// https://developer.mozilla.org/en/PKCS11_Module_Specs
|
||||||
|
// slotFlags=[PublicCerts] -- Certificates and public keys can be
|
||||||
|
// read from this slot without requiring a call to C_Login.
|
||||||
|
// askpw=only -- Only authenticate to the token when necessary.
|
||||||
|
"NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSlotProvidedByChaps(PK11SlotInfo* slot) {
|
||||||
|
if (!slot)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SECMODModule* pk11_module = PK11_GetModule(slot);
|
||||||
|
return pk11_module && base::StringPiece(pk11_module->commonName) ==
|
||||||
|
base::StringPiece(kChapsModuleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace crypto
|
22
crypto/chaps_support.h
Normal file
22
crypto/chaps_support.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2020 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 CRYPTO_CHAPS_SUPPORT_H_
|
||||||
|
#define CRYPTO_CHAPS_SUPPORT_H_
|
||||||
|
|
||||||
|
#include <secmodt.h>
|
||||||
|
|
||||||
|
#include "crypto/crypto_export.h"
|
||||||
|
|
||||||
|
namespace crypto {
|
||||||
|
|
||||||
|
// Loads chaps module for this NSS session.
|
||||||
|
CRYPTO_EXPORT SECMODModule* LoadChaps();
|
||||||
|
|
||||||
|
// Returns true if chaps is the module to which |slot| is attached.
|
||||||
|
CRYPTO_EXPORT bool IsSlotProvidedByChaps(PK11SlotInfo* slot);
|
||||||
|
|
||||||
|
} // namespace crypto
|
||||||
|
|
||||||
|
#endif // CRYPTO_CHAPS_SUPPORT_H_
|
@ -35,13 +35,14 @@ namespace crypto {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_LACROS)
|
||||||
|
|
||||||
// Fake certificate authority database used for testing.
|
// Fake certificate authority database used for testing.
|
||||||
static const base::FilePath::CharType kReadOnlyCertDB[] =
|
static const base::FilePath::CharType kReadOnlyCertDB[] =
|
||||||
FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb");
|
FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb");
|
||||||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
|
||||||
|
|
||||||
#if !BUILDFLAG(IS_CHROMEOS_ASH)
|
#else
|
||||||
|
|
||||||
base::FilePath GetDefaultConfigDirectory() {
|
base::FilePath GetDefaultConfigDirectory() {
|
||||||
base::FilePath dir;
|
base::FilePath dir;
|
||||||
base::PathService::Get(base::DIR_HOME, &dir);
|
base::PathService::Get(base::DIR_HOME, &dir);
|
||||||
@ -57,7 +58,8 @@ base::FilePath GetDefaultConfigDirectory() {
|
|||||||
DVLOG(2) << "DefaultConfigDirectory: " << dir.value();
|
DVLOG(2) << "DefaultConfigDirectory: " << dir.value();
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
|
|
||||||
|
#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_LACROS)
|
||||||
|
|
||||||
// On non-Chrome OS platforms, return the default config directory. On Chrome OS
|
// On non-Chrome OS platforms, return the default config directory. On Chrome OS
|
||||||
// test images, return a read-only directory with fake root CA certs (which are
|
// test images, return a read-only directory with fake root CA certs (which are
|
||||||
@ -65,7 +67,7 @@ base::FilePath GetDefaultConfigDirectory() {
|
|||||||
// code). On Chrome OS non-test images (where the read-only directory doesn't
|
// code). On Chrome OS non-test images (where the read-only directory doesn't
|
||||||
// exist), return an empty path.
|
// exist), return an empty path.
|
||||||
base::FilePath GetInitialConfigDirectory() {
|
base::FilePath GetInitialConfigDirectory() {
|
||||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_LACROS)
|
||||||
base::FilePath database_dir = base::FilePath(kReadOnlyCertDB);
|
base::FilePath database_dir = base::FilePath(kReadOnlyCertDB);
|
||||||
if (!base::PathExists(database_dir))
|
if (!base::PathExists(database_dir))
|
||||||
database_dir.clear();
|
database_dir.clear();
|
||||||
@ -158,7 +160,7 @@ class NSSInitSingleton {
|
|||||||
// Use "sql:" which can be shared by multiple processes safely.
|
// Use "sql:" which can be shared by multiple processes safely.
|
||||||
std::string nss_config_dir =
|
std::string nss_config_dir =
|
||||||
base::StringPrintf("sql:%s", database_dir.value().c_str());
|
base::StringPrintf("sql:%s", database_dir.value().c_str());
|
||||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_LACROS)
|
||||||
status = NSS_Init(nss_config_dir.c_str());
|
status = NSS_Init(nss_config_dir.c_str());
|
||||||
#else
|
#else
|
||||||
status = NSS_InitReadWrite(nss_config_dir.c_str());
|
status = NSS_InitReadWrite(nss_config_dir.c_str());
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "crypto/nss_util.h"
|
#include "crypto/nss_util.h"
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <nss.h>
|
#include <nss.h>
|
||||||
#include <pk11pub.h>
|
#include <pk11pub.h>
|
||||||
#include <plarena.h>
|
#include <plarena.h>
|
||||||
@ -35,6 +34,7 @@
|
|||||||
#include "base/threading/thread_restrictions.h"
|
#include "base/threading/thread_restrictions.h"
|
||||||
#include "base/threading/thread_task_runner_handle.h"
|
#include "base/threading/thread_task_runner_handle.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
#include "crypto/chaps_support.h"
|
||||||
#include "crypto/nss_util_internal.h"
|
#include "crypto/nss_util_internal.h"
|
||||||
|
|
||||||
namespace crypto {
|
namespace crypto {
|
||||||
@ -43,10 +43,6 @@ namespace {
|
|||||||
|
|
||||||
const char kUserNSSDatabaseName[] = "UserNSSDB";
|
const char kUserNSSDatabaseName[] = "UserNSSDB";
|
||||||
|
|
||||||
// Constants for loading the Chrome OS TPM-backed PKCS #11 library.
|
|
||||||
const char kChapsModuleName[] = "Chaps";
|
|
||||||
const char kChapsPath[] = "libchaps.so";
|
|
||||||
|
|
||||||
class ChromeOSUserData {
|
class ChromeOSUserData {
|
||||||
public:
|
public:
|
||||||
using SlotReadyCallback = base::OnceCallback<void(ScopedPK11Slot)>;
|
using SlotReadyCallback = base::OnceCallback<void(ScopedPK11Slot)>;
|
||||||
@ -110,38 +106,6 @@ class ChromeOSUserData {
|
|||||||
SlotReadyCallbackList tpm_ready_callback_list_;
|
SlotReadyCallbackList tpm_ready_callback_list_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScopedChapsLoadFixup {
|
|
||||||
public:
|
|
||||||
ScopedChapsLoadFixup();
|
|
||||||
~ScopedChapsLoadFixup();
|
|
||||||
|
|
||||||
private:
|
|
||||||
#if defined(COMPONENT_BUILD)
|
|
||||||
void* chaps_handle_;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(COMPONENT_BUILD)
|
|
||||||
|
|
||||||
ScopedChapsLoadFixup::ScopedChapsLoadFixup() {
|
|
||||||
// HACK: libchaps links the system protobuf and there are symbol conflicts
|
|
||||||
// with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround.
|
|
||||||
chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {
|
|
||||||
// LoadNSSModule() will have taken a 2nd reference.
|
|
||||||
if (chaps_handle_)
|
|
||||||
dlclose(chaps_handle_);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
ScopedChapsLoadFixup::ScopedChapsLoadFixup() {}
|
|
||||||
ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {}
|
|
||||||
|
|
||||||
#endif // defined(COMPONENT_BUILD)
|
|
||||||
|
|
||||||
class ChromeOSTokenManager {
|
class ChromeOSTokenManager {
|
||||||
public:
|
public:
|
||||||
// Used with PostTaskAndReply to pass handles to worker thread and back.
|
// Used with PostTaskAndReply to pass handles to worker thread and back.
|
||||||
@ -160,7 +124,7 @@ class ChromeOSTokenManager {
|
|||||||
// the current thread, due to NSS's internal locking requirements
|
// the current thread, due to NSS's internal locking requirements
|
||||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||||
|
|
||||||
base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb");
|
base::FilePath nssdb_path = GetSoftwareNSSDBPath(path);
|
||||||
if (!base::CreateDirectory(nssdb_path)) {
|
if (!base::CreateDirectory(nssdb_path)) {
|
||||||
LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory.";
|
LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory.";
|
||||||
return ScopedPK11Slot();
|
return ScopedPK11Slot();
|
||||||
@ -235,17 +199,7 @@ class ChromeOSTokenManager {
|
|||||||
FROM_HERE, base::BlockingType::WILL_BLOCK);
|
FROM_HERE, base::BlockingType::WILL_BLOCK);
|
||||||
|
|
||||||
if (!tpm_args->chaps_module) {
|
if (!tpm_args->chaps_module) {
|
||||||
ScopedChapsLoadFixup chaps_loader;
|
tpm_args->chaps_module = LoadChaps();
|
||||||
|
|
||||||
DVLOG(3) << "Loading chaps...";
|
|
||||||
tpm_args->chaps_module = LoadNSSModule(
|
|
||||||
kChapsModuleName, kChapsPath,
|
|
||||||
// For more details on these parameters, see:
|
|
||||||
// https://developer.mozilla.org/en/PKCS11_Module_Specs
|
|
||||||
// slotFlags=[PublicCerts] -- Certificates and public keys can be
|
|
||||||
// read from this slot without requiring a call to C_Login.
|
|
||||||
// askpw=only -- Only authenticate to the token when necessary.
|
|
||||||
"NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\"");
|
|
||||||
}
|
}
|
||||||
if (tpm_args->chaps_module) {
|
if (tpm_args->chaps_module) {
|
||||||
tpm_args->tpm_slot =
|
tpm_args->tpm_slot =
|
||||||
@ -527,6 +481,11 @@ base::LazyInstance<ChromeOSTokenManager>::Leaky g_token_manager =
|
|||||||
LAZY_INSTANCE_INITIALIZER;
|
LAZY_INSTANCE_INITIALIZER;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
base::FilePath GetSoftwareNSSDBPath(
|
||||||
|
const base::FilePath& profile_directory_path) {
|
||||||
|
return profile_directory_path.AppendASCII(".pki").AppendASCII("nssdb");
|
||||||
|
}
|
||||||
|
|
||||||
ScopedPK11Slot GetSystemNSSKeySlot(
|
ScopedPK11Slot GetSystemNSSKeySlot(
|
||||||
base::OnceCallback<void(ScopedPK11Slot)> callback) {
|
base::OnceCallback<void(ScopedPK11Slot)> callback) {
|
||||||
return g_token_manager.Get().GetSystemNSSKeySlot(std::move(callback));
|
return g_token_manager.Get().GetSystemNSSKeySlot(std::move(callback));
|
||||||
@ -605,13 +564,4 @@ void SetPrivateSoftwareSlotForChromeOSUserForTesting(ScopedPK11Slot slot) {
|
|||||||
std::move(slot));
|
std::move(slot));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsSlotProvidedByChaps(PK11SlotInfo* slot) {
|
|
||||||
if (!slot)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
SECMODModule* pk11_module = PK11_GetModule(slot);
|
|
||||||
return pk11_module && base::StringPiece(pk11_module->commonName) ==
|
|
||||||
base::StringPiece(kChapsModuleName);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace crypto
|
} // namespace crypto
|
||||||
|
@ -44,6 +44,11 @@ class CRYPTO_EXPORT AutoSECMODListReadLock {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||||
|
// Returns path to the NSS database file in the provided profile
|
||||||
|
// directory.
|
||||||
|
CRYPTO_EXPORT base::FilePath GetSoftwareNSSDBPath(
|
||||||
|
const base::FilePath& profile_directory_path);
|
||||||
|
|
||||||
// Returns a reference to the system-wide TPM slot if it is loaded. If it is not
|
// Returns a reference to the system-wide TPM slot if it is loaded. If it is not
|
||||||
// loaded and |callback| is non-null, the |callback| will be run once the slot
|
// loaded and |callback| is non-null, the |callback| will be run once the slot
|
||||||
// is loaded.
|
// is loaded.
|
||||||
@ -122,9 +127,6 @@ CRYPTO_EXPORT void CloseChromeOSUserForTesting(
|
|||||||
CRYPTO_EXPORT void SetPrivateSoftwareSlotForChromeOSUserForTesting(
|
CRYPTO_EXPORT void SetPrivateSoftwareSlotForChromeOSUserForTesting(
|
||||||
ScopedPK11Slot slot);
|
ScopedPK11Slot slot);
|
||||||
|
|
||||||
// Returns true if chaps is the module to which |slot| is attached.
|
|
||||||
CRYPTO_EXPORT bool IsSlotProvidedByChaps(PK11SlotInfo* slot);
|
|
||||||
|
|
||||||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
||||||
|
|
||||||
// Loads the given module for this NSS session.
|
// Loads the given module for this NSS session.
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
|
#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
|
||||||
#include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h"
|
#include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h"
|
||||||
|
|
||||||
|
#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
|
||||||
|
#include "crypto/chaps_support.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// PSM = Mozilla's Personal Security Manager.
|
// PSM = Mozilla's Personal Security Manager.
|
||||||
namespace psm = mozilla_security_manager;
|
namespace psm = mozilla_security_manager;
|
||||||
|
|
||||||
@ -436,7 +440,7 @@ bool NSSCertDatabase::IsHardwareBacked(const CERTCertificate* cert) {
|
|||||||
if (!slot || !PK11_IsHW(slot))
|
if (!slot || !PK11_IsHW(slot))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_LACROS)
|
||||||
// Chaps announces PK11_IsHW(slot) for all slots. However, it is possible for
|
// Chaps announces PK11_IsHW(slot) for all slots. However, it is possible for
|
||||||
// a key in chaps to be not truly hardware-backed, either because it has been
|
// a key in chaps to be not truly hardware-backed, either because it has been
|
||||||
// requested to be software-backed, or because the TPM does not support the
|
// requested to be software-backed, or because the TPM does not support the
|
||||||
|
Reference in New Issue
Block a user