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

Unified Diff: components/cert_database/cert_database_service_io_part_chromeos.cc

Issue 419013003: Replace c/b/nss_context by a KeyedService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Flattened components/cert_database folders. Created 6 years, 1 month 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
Index: components/cert_database/cert_database_service_io_part_chromeos.cc
diff --git a/components/cert_database/cert_database_service_io_part_chromeos.cc b/components/cert_database/cert_database_service_io_part_chromeos.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3b1ab488dc67c426e76da1f8979d5d0c27f17349
--- /dev/null
+++ b/components/cert_database/cert_database_service_io_part_chromeos.cc
@@ -0,0 +1,345 @@
+// Copyright 2014 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 "components/cert_database/cert_database_service_io_part_chromeos.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "chromeos/dbus/cryptohome_client.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+#include "net/cert/nss_cert_database_chromeos.h"
+
+namespace cert_database {
+
+namespace {
+
+void DidGetTPMInfoOnUICallBackToIO(
+ const chromeos::CryptohomeClient::Pkcs11GetTpmTokenInfoCallback& callback,
+ scoped_refptr<base::SingleThreadTaskRunner> origin_thread,
+ chromeos::DBusMethodCallStatus call_status,
+ const std::string& label,
+ const std::string& user_pin,
+ int slot_id) {
+ DVLOG(1) << "Got TPM info for slot " << slot_id;
+ origin_thread->PostTask(
+ FROM_HERE, base::Bind(callback, call_status, label, user_pin, slot_id));
+}
+
+void GetTPMInfoForUserOnUIThread(
+ const std::string& user_email,
+ const chromeos::CryptohomeClient::Pkcs11GetTpmTokenInfoCallback& callback,
+ scoped_refptr<base::SingleThreadTaskRunner> origin_thread,
+ chromeos::CryptohomeClient* cryptohome_client) {
+ DVLOG(1) << "Getting TPM info from cryptohome for "
+ << " " << user_email;
+ cryptohome_client->Pkcs11GetTpmTokenInfoForUser(
+ user_email,
+ base::Bind(&DidGetTPMInfoOnUICallBackToIO, callback, origin_thread));
+}
+
+void GetTPMInfoForUserOnIOThread(
+ const std::string& user_email,
+ const chromeos::CryptohomeClient::Pkcs11GetTpmTokenInfoCallback& callback,
+ scoped_refptr<base::SequencedTaskRunner> dbus_task_runner,
+ chromeos::CryptohomeClient* cryptohome_client) {
+ dbus_task_runner->PostTask(FROM_HERE,
+ base::Bind(&GetTPMInfoForUserOnUIThread,
+ user_email,
+ callback,
+ base::ThreadTaskRunnerHandle::Get(),
+ cryptohome_client));
+}
+
+} // namespace
+
+class CertDatabaseServiceIOPartChromeOS::Internal {
+ public:
+ Internal(const std::string& user_email,
+ const std::string& username_hash,
+ bool use_system_key_slot,
+ const base::FilePath& path,
+ const scoped_refptr<base::SequencedTaskRunner>& dbus_task_runner,
+ chromeos::CryptohomeClient* cryptohome_client,
+ CertDatabaseServiceIOPartChromeOS* io_part)
+ : user_email_(user_email),
+ username_hash_(username_hash),
+ use_system_key_slot_(use_system_key_slot),
+ path_(path),
+ dbus_task_runner_(dbus_task_runner),
+ state_(NOT_STARTED),
+ system_tpm_token_status_(SYSTEM_TPM_TOKEN_STATUS_UNDETERMINED),
+ cryptohome_client_(cryptohome_client),
+ io_part_(io_part),
+ weak_ptr_factory_(this) {
+ CHECK(dbus_task_runner_.get());
+ CHECK(cryptohome_client_);
+ CHECK(io_part_);
+ }
+
+ void Run() {
+ thread_checker_.DetachFromThread();
+ thread_checker_.CalledOnValidThread();
+ DCHECK_EQ(NOT_STARTED, state_);
+
+ VLOG(1) << "Initialize NSS for chromeos user " << username_hash_;
+ crypto::InitializeNSSForChromeOSUser(username_hash_, path_);
+ RunNextStep(TPM_TOKEN_STATE_UNKNOWN);
+ }
+
+ typedef base::Callback<void(bool system_tpm_token_enabled)>
+ SystemTPMTokenReadyCallback;
+ SystemTPMTokenReadyCallback GetSystemTPMTokenReadyCallback() {
+ return base::Bind(&Internal::OnSystemTPMTokenReady,
+ weak_ptr_factory_.GetWeakPtr());
+ }
+
+ private:
+ enum SystemTPMTokenStatus {
+ SYSTEM_TPM_TOKEN_STATUS_UNDETERMINED,
+ SYSTEM_TPM_TOKEN_STATUS_ENABLED,
+ SYSTEM_TPM_TOKEN_STATUS_DISABLED
+ };
+
+ enum State {
+ NOT_STARTED,
+ TPM_TOKEN_STATE_UNKNOWN,
+ TPM_TOKEN_ENABLED_AND_READY,
+ INITIALIZED_NSS_FOR_USER,
+ GOT_PRIVATE_SLOT_FOR_USER,
+ WAITING_FOR_SYSTEM_TPM_TOKEN,
+ SYSTEM_TPM_TOKEN_READY,
+ GOT_SYSTEM_SLOT,
+ CREATED_NSS_CERTDB
+ };
+
+ void RunNextStep(const State& next_state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ VLOG(1) << "State transition " << state_ << " -> " << next_state;
+ state_ = next_state;
+ switch (state_) {
+ case NOT_STARTED:
+ NOTREACHED();
+ break;
+ case TPM_TOKEN_STATE_UNKNOWN:
+ CheckTPMTokenState();
+ break;
+ case TPM_TOKEN_ENABLED_AND_READY:
+ GetTPMTokenInfo();
+ break;
+ case INITIALIZED_NSS_FOR_USER:
+ GetPrivateSlot();
+ break;
+ case GOT_PRIVATE_SLOT_FOR_USER:
+ if (!use_system_key_slot_) {
+ RunNextStep(GOT_SYSTEM_SLOT);
+ } else if (system_tpm_token_status_ ==
+ SYSTEM_TPM_TOKEN_STATUS_UNDETERMINED) {
+ state_ = WAITING_FOR_SYSTEM_TPM_TOKEN;
+ } else {
+ RunNextStep(SYSTEM_TPM_TOKEN_READY);
+ }
+ break;
+ case WAITING_FOR_SYSTEM_TPM_TOKEN:
+ // This step is waiting for OnSystemTPMTokenReady to be called.
+ NOTREACHED();
+ break;
+ case SYSTEM_TPM_TOKEN_READY:
+ GetSystemSlot();
+ break;
+ case GOT_SYSTEM_SLOT:
+ CreateCertDatabase();
+ break;
+ case CREATED_NSS_CERTDB:
+ NOTREACHED();
+ }
+ }
+
+ void FinishWithState(const State& state) {
+ VLOG(1) << "FinishWithState " << state;
+ state_ = state;
+ }
+
+ void CheckTPMTokenState() {
+ // Check if it's OK to initialize TPM for the user before continuing. This
+ // may not be the case if the TPM slot initialization was previously
+ // requested for the same user.
+ if (!crypto::ShouldInitializeTPMForChromeOSUser(username_hash_)) {
+ RunNextStep(INITIALIZED_NSS_FOR_USER);
+ return;
+ }
+
+ crypto::WillInitializeTPMForChromeOSUser(username_hash_);
+
+ if (crypto::IsTPMTokenEnabledForNSS()) {
+ base::Closure tpm_token_ready_callback =
+ base::Bind(&Internal::RunNextStep,
+ weak_ptr_factory_.GetWeakPtr(),
+ TPM_TOKEN_ENABLED_AND_READY);
+ if (crypto::IsTPMTokenReady(tpm_token_ready_callback))
+ tpm_token_ready_callback.Run();
+ else
+ DVLOG(1) << "Waiting for tpm ready ...";
+ } else {
+ crypto::InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
+ RunNextStep(INITIALIZED_NSS_FOR_USER);
+ }
+ }
+
+ void GetTPMTokenInfo() {
+ GetTPMInfoForUserOnIOThread(
+ user_email_,
+ base::Bind(&Internal::GotTPMTokenInfo, weak_ptr_factory_.GetWeakPtr()),
+ dbus_task_runner_,
+ cryptohome_client_);
+ }
+
+ void GotTPMTokenInfo(chromeos::DBusMethodCallStatus call_status,
+ const std::string& label,
+ const std::string& user_pin,
+ int slot_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (call_status == chromeos::DBUS_METHOD_CALL_FAILURE) {
+ // TODO(pneubeck, tbarzic): Retry instead of just failing.
+ // https://crbug.com/426349
+ LOG(ERROR) << "DBus error while getting TPM info for " << username_hash_;
+ crypto::InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
+ } else {
+ crypto::InitializeTPMForChromeOSUser(username_hash_, slot_id);
+ }
+ RunNextStep(INITIALIZED_NSS_FOR_USER);
+ }
+
+ void GetPrivateSlot() {
+ base::Callback<void(crypto::ScopedPK11Slot)> callback =
+ base::Bind(&Internal::GotPrivateSlot, weak_ptr_factory_.GetWeakPtr());
+
+ crypto::ScopedPK11Slot private_slot(
+ crypto::GetPrivateSlotForChromeOSUser(username_hash_, callback));
+ if (private_slot)
+ callback.Run(private_slot.Pass());
+ }
+
+ void GotPrivateSlot(crypto::ScopedPK11Slot private_slot) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(private_slot);
+
+ private_slot_ = private_slot.Pass();
+ RunNextStep(GOT_PRIVATE_SLOT_FOR_USER);
+ }
+
+ // This is called from external once the TPM token is ready. Must be called at
+ // most once and after Run().
+ void OnSystemTPMTokenReady(bool system_tpm_token_enabled) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_NE(NOT_STARTED, state_);
+ DCHECK_EQ(SYSTEM_TPM_TOKEN_STATUS_UNDETERMINED, system_tpm_token_status_);
+
+ if (!use_system_key_slot_)
+ return;
+ if (system_tpm_token_enabled)
+ system_tpm_token_status_ = SYSTEM_TPM_TOKEN_STATUS_ENABLED;
+ else
+ system_tpm_token_status_ = SYSTEM_TPM_TOKEN_STATUS_DISABLED;
+ if (state_ == WAITING_FOR_SYSTEM_TPM_TOKEN)
+ RunNextStep(SYSTEM_TPM_TOKEN_READY);
+ }
+
+ void GetSystemSlot() {
+ if (!use_system_key_slot_ ||
+ system_tpm_token_status_ == SYSTEM_TPM_TOKEN_STATUS_DISABLED) {
+ VLOG(2) << "Skip system key slot initialization";
+ RunNextStep(GOT_SYSTEM_SLOT);
+ return;
+ }
+
+ base::Callback<void(crypto::ScopedPK11Slot)> callback =
+ base::Bind(&Internal::GotSystemSlot, weak_ptr_factory_.GetWeakPtr());
+
+ crypto::ScopedPK11Slot system_slot = crypto::GetSystemNSSKeySlot(callback);
+ if (system_slot)
+ callback.Run(system_slot.Pass());
+ }
+
+ void GotSystemSlot(crypto::ScopedPK11Slot system_slot) {
+ if (!system_slot)
+ LOG(ERROR) << "Could not get the system key slot.";
+ system_slot_ = system_slot.Pass();
+ RunNextStep(GOT_SYSTEM_SLOT);
+ }
+
+ void CreateCertDatabase() {
+ crypto::ScopedPK11Slot public_slot =
+ crypto::GetPublicSlotForChromeOSUser(username_hash_);
+
+ scoped_ptr<net::NSSCertDatabaseChromeOS> db(
+ new net::NSSCertDatabaseChromeOS(public_slot.Pass(),
+ private_slot_.Pass()));
+ if (system_slot_)
+ db->SetSystemSlot(system_slot_.Pass());
+
+ FinishWithState(CREATED_NSS_CERTDB);
+ io_part_->DidCreateNSSCertDatabase(db.Pass()); // Will delete this.
+ }
+
+ const std::string user_email_;
+ const std::string username_hash_;
+ bool use_system_key_slot_;
+ const base::FilePath path_;
+ scoped_refptr<base::SequencedTaskRunner> dbus_task_runner_;
+ State state_;
+ crypto::ScopedPK11Slot private_slot_;
+ SystemTPMTokenStatus system_tpm_token_status_;
+ crypto::ScopedPK11Slot system_slot_;
+ chromeos::CryptohomeClient* cryptohome_client_;
+ CertDatabaseServiceIOPartChromeOS* io_part_;
+ base::ThreadChecker thread_checker_;
+ base::WeakPtrFactory<Internal> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(Internal);
+};
+
+CertDatabaseServiceIOPartChromeOS::CertDatabaseServiceIOPartChromeOS(
+ const std::string& user_email,
+ const std::string& username_hash,
+ bool use_system_key_slot,
+ const base::FilePath& path,
+ const scoped_refptr<base::SequencedTaskRunner>& dbus_task_runner,
+ chromeos::CryptohomeClient* cryptohome_client)
+ : internal_(new Internal(user_email,
+ username_hash,
+ use_system_key_slot,
+ path,
+ dbus_task_runner,
+ cryptohome_client,
+ this)) {
+}
+
+CertDatabaseServiceIOPartChromeOS::~CertDatabaseServiceIOPartChromeOS() {
+}
+
+void CertDatabaseServiceIOPartChromeOS::Init() {
+ CertDatabaseServiceIOPart::Init();
+ internal_->Run();
+}
+
+void CertDatabaseServiceIOPartChromeOS::DidCreateNSSCertDatabase(
+ scoped_ptr<net::NSSCertDatabase> db) {
+ internal_.reset();
+ SetNSSCertDatabase(db.Pass());
+}
+
+CertDatabaseServiceIOPartChromeOS::SystemTPMTokenReadyCallback
+CertDatabaseServiceIOPartChromeOS::GetSystemTPMTokenReadyCallback() {
+ CHECK(!IsInitialized());
+ return internal_->GetSystemTPMTokenReadyCallback();
+}
+
+} // namespace cert_database

Powered by Google App Engine
This is Rietveld 408576698