Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Unified Diff: chromeos/network/cert_loader.cc

Issue 20130002: Call crypto::InitializeTPMToken on the IO thread (Take 2) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromeos/network/cert_loader.h ('k') | chromeos/network/network_connection_handler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromeos/network/cert_loader.cc
diff --git a/chromeos/network/cert_loader.cc b/chromeos/network/cert_loader.cc
deleted file mode 100644
index f75f8bb959b6f2863e1254336eb9d77bb1ee5bde..0000000000000000000000000000000000000000
--- a/chromeos/network/cert_loader.cc
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright (c) 2013 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 "chromeos/network/cert_loader.h"
-
-#include <algorithm>
-
-#include "base/chromeos/chromeos_version.h"
-#include "base/observer_list.h"
-#include "base/strings/string_number_conversions.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"
-
-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) {
- if (base::chromeos::IsRunningOnChromeOS())
- net::NSSCertDatabase::GetInstance()->ListCerts(cert_list);
-}
-
-} // namespace
-
-CertLoader::CertLoader()
- : 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)),
- initialize_token_factory_(this),
- update_certificates_factory_(this) {
- net::CertDatabase::GetInstance()->AddObserver(this);
- if (LoginState::IsInitialized())
- LoginState::Get()->AddObserver(this);
- RequestCertificates();
-}
-
-CertLoader::~CertLoader() {
- net::CertDatabase::GetInstance()->RemoveObserver(this);
- if (LoginState::IsInitialized())
- LoginState::Get()->RemoveObserver(this);
-}
-
-void CertLoader::AddObserver(CertLoader::Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-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::RequestCertificates() {
- CHECK(thread_checker_.CalledOnValidThread());
- const bool logged_in = LoginState::IsInitialized() ?
- LoginState::Get()->IsUserLoggedIn() : false;
- VLOG(1) << "RequestCertificates: " << logged_in;
- if (certificates_requested_ || !logged_in)
- return;
-
- certificates_requested_ = true;
-
- // Ensure we've opened the user's key/certificate database.
- crypto::OpenPersistentNSSDB();
- if (base::chromeos::IsRunningOnChromeOS())
- crypto::EnableTPMTokenForNSS();
-
- // This is the entry point to the TPM token initialization process, which we
- // should do at most once.
- DCHECK(!initialize_token_factory_.HasWeakPtrs());
- InitializeTokenAndLoadCertificates();
-}
-
-void CertLoader::InitializeTokenAndLoadCertificates() {
- CHECK(thread_checker_.CalledOnValidThread());
- VLOG(1) << "InitializeTokenAndLoadCertificates";
-
- switch (tpm_token_state_) {
- case TPM_STATE_UNKNOWN: {
- 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: {
- InitializeNSSForTPMToken();
- return;
- }
- case TPM_TOKEN_NSS_INITIALIZED: {
- StartLoadCertificates();
- return;
- }
- }
-}
-
-void CertLoader::RetryTokenInitializationLater() {
- LOG(WARNING) << "Re-Requesting Certificates 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_);
-}
-
-// For background see this discussion on dev-tech-crypto.lists.mozilla.org:
-// http://web.archiveorange.com/archive/v/6JJW7E40sypfZGtbkzxX
-//
-// NOTE: This function relies on the convention that the same PKCS#11 ID
-// is shared between a certificate and its associated private and public
-// keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(),
-// but that always returns NULL on Chrome OS for me.
-std::string CertLoader::GetPkcs11IdForCert(
- const net::X509Certificate& cert) const {
- if (!IsHardwareBacked())
- return std::string();
-
- CERTCertificateStr* cert_handle = cert.os_cert_handle();
- SECKEYPrivateKey *priv_key =
- PK11_FindKeyByAnyCert(cert_handle, NULL /* wincx */);
- if (!priv_key)
- return std::string();
-
- // Get the CKA_ID attribute for a key.
- SECItem* sec_item = PK11_GetLowLevelKeyIDForPrivateKey(priv_key);
- std::string pkcs11_id;
- if (sec_item) {
- pkcs11_id = base::HexEncode(sec_item->data, sec_item->len);
- SECITEM_FreeItem(sec_item, PR_TRUE);
- }
- SECKEY_DestroyPrivateKey(priv_key);
-
- 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();
- return;
- }
-
- tpm_token_state_ = TPM_TOKEN_READY;
- InitializeTokenAndLoadCertificates();
-}
-
-void CertLoader::OnPkcs11GetTpmTokenInfo(DBusMethodCallStatus call_status,
- const std::string& token_name,
- const std::string& user_pin) {
- VLOG(1) << "OnPkcs11GetTpmTokenInfo: " << token_name;
-
- if (call_status == DBUS_METHOD_CALL_FAILURE) {
- RetryTokenInitializationLater();
- return;
- }
-
- tpm_token_name_ = token_name;
- // TODO(stevenjb): The network code expects a slot ID, not a label. See
- // crbug.com/201101. For now, use a hard coded, well known slot instead.
- const char kHardcodedTpmSlot[] = "0";
- tpm_token_slot_ = kHardcodedTpmSlot;
- tpm_user_pin_ = user_pin;
- tpm_token_state_ = TPM_TOKEN_INFO_RECEIVED;
-
- InitializeTokenAndLoadCertificates();
-}
-
-void CertLoader::InitializeNSSForTPMToken() {
- VLOG(1) << "InitializeNSSForTPMToken";
-
- if (base::chromeos::IsRunningOnChromeOS() &&
- !crypto::InitializeTPMToken(tpm_token_name_, tpm_user_pin_)) {
- RetryTokenInitializationLater();
- return;
- }
-
- tpm_token_state_ = TPM_TOKEN_NSS_INITIALIZED;
- InitializeTokenAndLoadCertificates();
-}
-
-void CertLoader::StartLoadCertificates() {
- VLOG(1) << "StartLoadCertificates";
-
- if (certificates_update_running_) {
- certificates_update_required_ = true;
- return;
- }
-
- net::CertificateList* cert_list = new net::CertificateList;
- certificates_update_running_ = true;
- certificates_update_required_ = false;
- base::WorkerPool::GetTaskRunner(true /* task_is_slow */)->
- PostTaskAndReply(
- FROM_HERE,
- base::Bind(LoadNSSCertificates, cert_list),
- base::Bind(&CertLoader::UpdateCertificates,
- update_certificates_factory_.GetWeakPtr(),
- base::Owned(cert_list)));
-}
-
-void CertLoader::UpdateCertificates(net::CertificateList* cert_list) {
- CHECK(thread_checker_.CalledOnValidThread());
- DCHECK(certificates_update_running_);
- VLOG(1) << "UpdateCertificates: " << cert_list->size();
-
- // Ignore any existing certificates.
- cert_list_.swap(*cert_list);
-
- NotifyCertificatesLoaded(!certificates_loaded_);
- certificates_loaded_ = true;
-
- certificates_update_running_ = false;
- if (certificates_update_required_)
- StartLoadCertificates();
-}
-
-void CertLoader::NotifyCertificatesLoaded(bool initial_load) {
- FOR_EACH_OBSERVER(Observer, observers_,
- OnCertificatesLoaded(cert_list_, initial_load));
-}
-
-void CertLoader::OnCertTrustChanged(const net::X509Certificate* cert) {
-}
-
-void CertLoader::OnCertAdded(const net::X509Certificate* cert) {
- VLOG(1) << "OnCertAdded";
- StartLoadCertificates();
-}
-
-void CertLoader::OnCertRemoved(const net::X509Certificate* cert) {
- VLOG(1) << "OnCertRemoved";
- StartLoadCertificates();
-}
-
-void CertLoader::LoggedInStateChanged(LoginState::LoggedInState state) {
- VLOG(1) << "LoggedInStateChanged: " << state;
- RequestCertificates();
-}
-
-} // namespace chromeos
« no previous file with comments | « chromeos/network/cert_loader.h ('k') | chromeos/network/network_connection_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698