summaryrefslogtreecommitdiffstats
path: root/chromeos/cert_loader.cc
diff options
context:
space:
mode:
authortbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-21 23:14:53 +0000
committertbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-21 23:14:53 +0000
commitb2390837986574afa95926297767fad126bc9b74 (patch)
tree8744896918af941c5850db968d7f71bf428dfea4 /chromeos/cert_loader.cc
parentb2d1f2dcf6d9181cd8b60804e6cbf0c13fbf9a93 (diff)
downloadchromium_src-b2390837986574afa95926297767fad126bc9b74.zip
chromium_src-b2390837986574afa95926297767fad126bc9b74.tar.gz
chromium_src-b2390837986574afa95926297767fad126bc9b74.tar.bz2
Split chromeos::CertLoader
CertLoader does both TPM token initialization and certificate loading from the cert database. This extracts token initializetion in a separate class. BUG=315343 Review URL: https://codereview.chromium.org/132313004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@246154 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/cert_loader.cc')
-rw-r--r--chromeos/cert_loader.cc254
1 files changed, 31 insertions, 223 deletions
diff --git a/chromeos/cert_loader.cc b/chromeos/cert_loader.cc
index 8b10a9e..70e4981 100644
--- a/chromeos/cert_loader.cc
+++ b/chromeos/cert_loader.cc
@@ -6,55 +6,23 @@
#include <algorithm>
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/observer_list.h"
-#include "base/sequenced_task_runner.h"
+#include "base/bind.h"
+#include "base/location.h"
#include "base/strings/string_number_conversions.h"
-#include "base/sys_info.h"
#include "base/task_runner_util.h"
#include "base/threading/worker_pool.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"
#include "net/cert/nss_cert_database.h"
+#include "net/cert/x509_certificate.h"
namespace chromeos {
namespace {
-const int64 kInitialRequestDelayMs = 100;
-const int64 kMaxRequestDelayMs = 300000; // 5 minutes
-
-// Calculates the delay before running next attempt to initiatialize the TPM
-// token, if |last_delay| was the last or initial delay.
-base::TimeDelta GetNextRequestDelayMs(base::TimeDelta last_delay) {
- // This implements an exponential backoff, as we don't know in which order of
- // magnitude the TPM token changes it's state.
- base::TimeDelta next_delay = last_delay * 2;
-
- // Cap the delay to prevent an overflow. This threshold is arbitrarily chosen.
- const base::TimeDelta max_delay =
- base::TimeDelta::FromMilliseconds(kMaxRequestDelayMs);
- if (next_delay > max_delay)
- next_delay = max_delay;
- return next_delay;
-}
-
-void LoadNSSCertificates(net::CertificateList* cert_list) {
- net::NSSCertDatabase::GetInstance()->ListCerts(cert_list);
-}
-
-void CallOpenPersistentNSSDB() {
- // Called from crypto_task_runner_.
- VLOG(1) << "CallOpenPersistentNSSDB";
-
- // Ensure we've opened the user's key/certificate database.
- if (base::SysInfo::IsRunningOnChromeOS())
- crypto::OpenPersistentNSSDB();
- crypto::EnableTPMTokenForNSS();
+// Loads certificates from |cert_database| into |cert_list|.
+void LoadNSSCertificates(net::NSSCertDatabase* cert_database,
+ net::CertificateList* cert_list) {
+ cert_database->ListCerts(cert_list);
}
} // namespace
@@ -86,29 +54,14 @@ bool CertLoader::IsInitialized() {
}
CertLoader::CertLoader()
- : initialize_tpm_for_test_(false),
- certificates_requested_(false),
+ : certificates_requested_(false),
certificates_loaded_(false),
certificates_update_required_(false),
certificates_update_running_(false),
- tpm_token_state_(TPM_STATE_UNKNOWN),
- tpm_request_delay_(
- base::TimeDelta::FromMilliseconds(kInitialRequestDelayMs)),
tpm_token_slot_id_(-1),
- initialize_token_factory_(this),
- update_certificates_factory_(this) {
- if (LoginState::IsInitialized())
- LoginState::Get()->AddObserver(this);
-}
-
-void CertLoader::InitializeTPMForTest() {
- initialize_tpm_for_test_ = true;
-}
-
-void CertLoader::SetCryptoTaskRunner(
- const scoped_refptr<base::SequencedTaskRunner>& crypto_task_runner) {
- crypto_task_runner_ = crypto_task_runner;
- MaybeRequestCertificates();
+ weak_factory_(this) {
+ if (TPMTokenLoader::IsInitialized())
+ TPMTokenLoader::Get()->AddObserver(this);
}
void CertLoader::SetSlowTaskRunnerForTest(
@@ -118,8 +71,8 @@ void CertLoader::SetSlowTaskRunnerForTest(
CertLoader::~CertLoader() {
net::CertDatabase::GetInstance()->RemoveObserver(this);
- if (LoginState::IsInitialized())
- LoginState::Get()->RemoveObserver(this);
+ if (TPMTokenLoader::IsInitialized())
+ TPMTokenLoader::Get()->RemoveObserver(this);
}
void CertLoader::AddObserver(CertLoader::Observer* observer) {
@@ -130,115 +83,12 @@ void CertLoader::RemoveObserver(CertLoader::Observer* observer) {
observers_.RemoveObserver(observer);
}
-bool CertLoader::CertificatesLoading() const {
- return certificates_requested_ && !certificates_loaded_;
-}
-
bool CertLoader::IsHardwareBacked() const {
return !tpm_token_name_.empty();
}
-void CertLoader::MaybeRequestCertificates() {
- CHECK(thread_checker_.CalledOnValidThread());
-
- // This is the entry point to the TPM token initialization process,
- // which we should do at most once.
- if (certificates_requested_ || !crypto_task_runner_.get())
- return;
-
- if (!LoginState::IsInitialized())
- return;
-
- bool request_certificates = LoginState::Get()->IsUserLoggedIn() ||
- LoginState::Get()->IsInSafeMode();
-
- VLOG(1) << "RequestCertificates: " << request_certificates;
- if (!request_certificates)
- return;
-
- certificates_requested_ = true;
-
- // Ensure we only initialize the TPM token once.
- DCHECK_EQ(tpm_token_state_, TPM_STATE_UNKNOWN);
- if (!initialize_tpm_for_test_ && !base::SysInfo::IsRunningOnChromeOS())
- tpm_token_state_ = TPM_DISABLED;
-
- // Treat TPM as disabled for guest users since they do not store certs.
- if (LoginState::Get()->IsGuestUser())
- tpm_token_state_ = TPM_DISABLED;
-
- InitializeTokenAndLoadCertificates();
-}
-
-void CertLoader::InitializeTokenAndLoadCertificates() {
- CHECK(thread_checker_.CalledOnValidThread());
- VLOG(1) << "InitializeTokenAndLoadCertificates: " << tpm_token_state_;
-
- switch (tpm_token_state_) {
- case TPM_STATE_UNKNOWN: {
- crypto_task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&CallOpenPersistentNSSDB),
- base::Bind(&CertLoader::OnPersistentNSSDBOpened,
- initialize_token_factory_.GetWeakPtr()));
- return;
- }
- case TPM_DB_OPENED: {
- DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled(
- base::Bind(&CertLoader::OnTpmIsEnabled,
- initialize_token_factory_.GetWeakPtr()));
- return;
- }
- case TPM_DISABLED: {
- // TPM is disabled, so proceed with empty tpm token name.
- StartLoadCertificates();
- return;
- }
- case TPM_ENABLED: {
- DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady(
- base::Bind(&CertLoader::OnPkcs11IsTpmTokenReady,
- initialize_token_factory_.GetWeakPtr()));
- return;
- }
- case TPM_TOKEN_READY: {
- // Retrieve token_name_ and user_pin_ here since they will never change
- // and CryptohomeClient calls are not thread safe.
- DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo(
- base::Bind(&CertLoader::OnPkcs11GetTpmTokenInfo,
- initialize_token_factory_.GetWeakPtr()));
- return;
- }
- case TPM_TOKEN_INFO_RECEIVED: {
- base::PostTaskAndReplyWithResult(
- crypto_task_runner_.get(),
- FROM_HERE,
- base::Bind(&crypto::InitializeTPMToken, tpm_token_slot_id_),
- base::Bind(&CertLoader::OnTPMTokenInitialized,
- initialize_token_factory_.GetWeakPtr()));
- return;
- }
- case TPM_TOKEN_INITIALIZED: {
- StartLoadCertificates();
- return;
- }
- }
-}
-
-void CertLoader::RetryTokenInitializationLater() {
- CHECK(thread_checker_.CalledOnValidThread());
- LOG(WARNING) << "Retry token initialization later.";
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&CertLoader::InitializeTokenAndLoadCertificates,
- initialize_token_factory_.GetWeakPtr()),
- tpm_request_delay_);
- tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_);
-}
-
-void CertLoader::OnPersistentNSSDBOpened() {
- VLOG(1) << "PersistentNSSDBOpened";
- tpm_token_state_ = TPM_DB_OPENED;
- InitializeTokenAndLoadCertificates();
+bool CertLoader::CertificatesLoading() const {
+ return certificates_requested_ && !certificates_loaded_;
}
// This is copied from chrome/common/net/x509_certificate_model_nss.cc.
@@ -270,61 +120,11 @@ std::string CertLoader::GetPkcs11IdForCert(const net::X509Certificate& cert) {
return pkcs11_id;
}
-void CertLoader::OnTpmIsEnabled(DBusMethodCallStatus call_status,
- bool tpm_is_enabled) {
- VLOG(1) << "OnTpmIsEnabled: " << tpm_is_enabled;
-
- if (call_status == DBUS_METHOD_CALL_SUCCESS && tpm_is_enabled)
- tpm_token_state_ = TPM_ENABLED;
- else
- tpm_token_state_ = TPM_DISABLED;
-
- InitializeTokenAndLoadCertificates();
-}
-
-void CertLoader::OnPkcs11IsTpmTokenReady(DBusMethodCallStatus call_status,
- bool is_tpm_token_ready) {
- VLOG(1) << "OnPkcs11IsTpmTokenReady: " << is_tpm_token_ready;
-
- if (call_status == DBUS_METHOD_CALL_FAILURE || !is_tpm_token_ready) {
- RetryTokenInitializationLater();
+void CertLoader::RequestCertificates() {
+ if (certificates_requested_)
return;
- }
-
- tpm_token_state_ = TPM_TOKEN_READY;
- InitializeTokenAndLoadCertificates();
-}
-
-void CertLoader::OnPkcs11GetTpmTokenInfo(DBusMethodCallStatus call_status,
- const std::string& token_name,
- const std::string& user_pin,
- int token_slot_id) {
- VLOG(1) << "OnPkcs11GetTpmTokenInfo: " << token_name;
-
- if (call_status == DBUS_METHOD_CALL_FAILURE) {
- RetryTokenInitializationLater();
- return;
- }
-
- tpm_token_name_ = token_name;
- tpm_token_slot_id_ = token_slot_id;
- tpm_user_pin_ = user_pin;
- tpm_token_state_ = TPM_TOKEN_INFO_RECEIVED;
-
- InitializeTokenAndLoadCertificates();
-}
-
-void CertLoader::OnTPMTokenInitialized(bool success) {
- VLOG(1) << "OnTPMTokenInitialized: " << success;
- if (!success) {
- RetryTokenInitializationLater();
- return;
- }
- tpm_token_state_ = TPM_TOKEN_INITIALIZED;
- InitializeTokenAndLoadCertificates();
-}
+ certificates_requested_ = true;
-void CertLoader::StartLoadCertificates() {
DCHECK(!certificates_loaded_ && !certificates_update_running_);
net::CertDatabase::GetInstance()->AddObserver(this);
LoadCertificates();
@@ -348,9 +148,11 @@ void CertLoader::LoadCertificates() {
task_runner = base::WorkerPool::GetTaskRunner(true /* task is slow */);
task_runner->PostTaskAndReply(
FROM_HERE,
- base::Bind(LoadNSSCertificates, cert_list),
+ base::Bind(LoadNSSCertificates,
+ net::NSSCertDatabase::GetInstance(),
+ cert_list),
base::Bind(&CertLoader::UpdateCertificates,
- update_certificates_factory_.GetWeakPtr(),
+ weak_factory_.GetWeakPtr(),
base::Owned(cert_list)));
}
@@ -393,9 +195,15 @@ void CertLoader::OnCertRemoved(const net::X509Certificate* cert) {
LoadCertificates();
}
-void CertLoader::LoggedInStateChanged() {
- VLOG(1) << "LoggedInStateChanged";
- MaybeRequestCertificates();
+void CertLoader::OnTPMTokenReady(const std::string& tpm_user_pin,
+ const std::string& tpm_token_name,
+ int tpm_token_slot_id) {
+ tpm_user_pin_ = tpm_user_pin;
+ tpm_token_name_ = tpm_token_name;
+ tpm_token_slot_id_ = tpm_token_slot_id;
+
+ VLOG(1) << "TPM token ready.";
+ RequestCertificates();
}
} // namespace chromeos