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

Unified Diff: chrome/browser/net/nss_slot_factory.cc

Issue 18121007: *WIP* Store NSS slots per profile. Move keygen to chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cert manager basics working Created 7 years, 2 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 | « chrome/browser/net/nss_slot_factory.h ('k') | chrome/browser/policy/browser_policy_connector.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/net/nss_slot_factory.cc
diff --git a/chrome/browser/net/nss_slot_factory.cc b/chrome/browser/net/nss_slot_factory.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2fbb04a3e4ee6cd3990cb4dd96b2cb0859fb721e
--- /dev/null
+++ b/chrome/browser/net/nss_slot_factory.cc
@@ -0,0 +1,305 @@
+// 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 "chrome/browser/net/nss_slot_factory.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/lazy_instance.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/stl_util.h"
+#include "chrome/browser/profiles/profile_io_data.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/resource_context.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+#include "net/cert/nss_cert_database.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/dbus/cryptohome_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chrome/browser/chromeos/net/nss_cert_database_cros.h"
+#endif
+
+using content::BrowserThread;
+
+namespace {
+
+#if defined(OS_CHROMEOS)
+void OnPkcs11GetTpmTokenInfoOnUIThread(
+ const base::Callback<void(int)>& callback,
+ chromeos::DBusMethodCallStatus call_status,
+ const std::string& label,
+ const std::string& user_pin,
+ int slot) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ LOG(WARNING) << __func__ << " " << label << " " << slot;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE, base::Bind(callback, slot));
+}
+
+void GetTpmInfoForUserOnUIThread(const std::string& user_name,
+ const base::Callback<void(int)>& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ LOG(WARNING) << __func__ << " " << user_name;
+ chromeos::DBusThreadManager::Get()
+ ->GetCryptohomeClient()
+ ->Pkcs11GetTpmTokenInfoForUser(
+ user_name,
+ base::Bind(&OnPkcs11GetTpmTokenInfoOnUIThread, callback));
+}
+
+// NSSSlotService initializes and holds the public and private key slots for a
+// given profile.
+class NSSSlotService {
+ public:
+ NSSSlotService(const base::FilePath& user_dir,
+ const std::string& user_name);
+ virtual ~NSSSlotService();
+
+ crypto::ScopedPK11Slot GetPublicNSSKeySlot();
+ crypto::ScopedPK11Slot GetPrivateNSSKeySlot();
+ void OnPrivateNSSKeySlotForResourceContextReady(
+ const base::Callback<void(crypto::ScopedPK11Slot)>& callback);
+ void OnNSSCertDatabaseForResourceContextReady(
+ const base::Callback<void(net::NSSCertDatabase*)>& callback);
+
+ private:
+ void OnGotTpmSlot(int slot);
+ void StartTpmSlotInitializion();
+
+ base::FilePath user_dir_;
+ std::string user_name_;
+ crypto::ScopedPK11Slot public_slot_;
+ crypto::ScopedPK11Slot private_slot_;
+ scoped_ptr<chromeos::NSSCertDatabaseCros> cert_db_;
+
+ std::vector<base::Callback<void(crypto::ScopedPK11Slot)> >
+ tpm_ready_callback_list_;
+ std::vector<base::Callback<void(net::NSSCertDatabase*)> >
+ cert_db_ready_callback_list_;
+ base::WeakPtrFactory<NSSSlotService> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NSSSlotService);
+};
+
+// XXX
+// If the profile directory is /home/chronos/u-xxxxxx, the nss db will be at
+// /home/chronos/u-xxxxxx/.pki/nssdb. You can get the profile directory for a
+// given username if you need it by calling libchromeos' GetUserPath().
+//
+NSSSlotService::NSSSlotService(const base::FilePath& user_dir,
+ const std::string& user_name)
+ : user_dir_(user_dir),
+ user_name_(user_name),
+ weak_ptr_factory_(this) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // XXX should we do something to check that we aren't reopening the same
+ // database used by the default public slot?
+ public_slot_.reset(crypto::OpenPersistentNSSDBForPath(user_dir_));
+ LOG(WARNING) << "pub: " << public_slot_.get();
+ if (crypto::IsTPMTokenEnabledForNSS()) {
+ if (crypto::IsTPMTokenReady()) {
+ StartTpmSlotInitializion();
+ } else {
+ LOG(WARNING) << "waiting for tpm ready ...";
+ crypto::OnTPMReady(base::Bind(&NSSSlotService::StartTpmSlotInitializion,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ } else {
+ LOG(WARNING) << "using software private slot";
+ private_slot_ = GetPublicNSSKeySlot();
+ }
+ crypto::DumpNSSSlotInfos();
+}
+
+NSSSlotService::~NSSSlotService() {
+ LOG(WARNING) << __func__;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Don't close when NSS is < 3.15.1, because it would require an additional
+ // sleep for 1 second after closing the database, due to
+ // http://bugzil.la/875601.
+ if (NSS_VersionCheck("3.15.1")) {
+ if (public_slot_) {
+ LOG(WARNING) << "closing nssdb";
+ SECStatus status = SECMOD_CloseUserDB(public_slot_.get());
+ if (status != SECSuccess)
+ PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
+ }
+ }
+}
+
+crypto::ScopedPK11Slot NSSSlotService::GetPublicNSSKeySlot() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return crypto::ScopedPK11Slot(
+ public_slot_ ? PK11_ReferenceSlot(public_slot_.get()) : NULL);
+}
+
+crypto::ScopedPK11Slot NSSSlotService::GetPrivateNSSKeySlot() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return crypto::ScopedPK11Slot(
+ private_slot_ ? PK11_ReferenceSlot(private_slot_.get()) : NULL);
+}
+
+void NSSSlotService::OnPrivateNSSKeySlotForResourceContextReady(
+ const base::Callback<void(crypto::ScopedPK11Slot)>& callback) {
+ VLOG(1) << __func__;
+ if (private_slot_)
+ callback.Run(GetPrivateNSSKeySlot());
+ else
+ tpm_ready_callback_list_.push_back(callback);
+}
+
+void NSSSlotService::OnNSSCertDatabaseForResourceContextReady(
+ const base::Callback<void(net::NSSCertDatabase*)>& callback) {
+ if (cert_db_)
+ callback.Run(cert_db_.get());
+ else
+ cert_db_ready_callback_list_.push_back(callback);
+}
+
+void NSSSlotService::OnGotTpmSlot(int slot) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ LOG(WARNING) << __func__ << " " << slot;
+ if (slot >= 0) {
+ private_slot_.reset(crypto::GetTPMSlotForId(slot));
+ LOG(WARNING) << " private_slot_ " << private_slot_.get();
+ cert_db_.reset(new chromeos::NSSCertDatabaseCros(GetPublicNSSKeySlot(),
+ GetPrivateNSSKeySlot()));
+
+ for (std::vector<base::Callback<void(crypto::ScopedPK11Slot)> >::iterator
+ i = tpm_ready_callback_list_.begin();
+ i != tpm_ready_callback_list_.end();
+ ++i) {
+ (*i).Run(GetPrivateNSSKeySlot());
+ }
+ tpm_ready_callback_list_.clear();
+
+ for (std::vector<base::Callback<void(net::NSSCertDatabase*)> >::iterator
+ i = cert_db_ready_callback_list_.begin();
+ i != cert_db_ready_callback_list_.end();
+ ++i) {
+ (*i).Run(cert_db_.get());
+ }
+ cert_db_ready_callback_list_.clear();
+ }
+ crypto::DumpNSSSlotInfos();
+}
+
+void NSSSlotService::StartTpmSlotInitializion() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ LOG(WARNING) << __func__;
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GetTpmInfoForUserOnUIThread,
+ user_name_,
+ base::Bind(&NSSSlotService::OnGotTpmSlot,
+ weak_ptr_factory_.GetWeakPtr())));
+}
+
+class NSSSlotFactory {
+ public:
+ NSSSlotService* GetService(content::ResourceContext* context);
+
+ ~NSSSlotFactory();
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<NSSSlotFactory>;
+
+ std::map<std::string, NSSSlotService*> service_map_;
+};
+
+base::LazyInstance<NSSSlotFactory>::Leaky
+ g_nss_slot_factory = LAZY_INSTANCE_INITIALIZER;
+
+NSSSlotService* NSSSlotFactory::GetService(content::ResourceContext* context) {
+ ProfileIOData* io_data = ProfileIOData::FromResourceContext(context);
+ std::string user_name = io_data->user_name();
+ if (user_name.empty())
+ return NULL;
+
+ std::map<std::string, NSSSlotService*>::iterator i =
+ service_map_.find(user_name);
+ if (i != service_map_.end())
+ return (*i).second;
+
+ NSSSlotService* service =
+ new NSSSlotService(io_data->profile_path(), io_data->user_name());
+ service_map_[user_name] = service;
+ return service;
+}
+
+// XXX this will be run on UI thread due to lazyinstance atexit thingy?
+// XXX made lazyinstance leaky ... so it won't be run at all, like nss_util
+NSSSlotFactory::~NSSSlotFactory() {
+ LOG(WARNING) << __func__;
+ STLDeleteValues(&service_map_);
+}
+#endif // defined(OS_CHROMEOS)
+
+void PassTPMToCallback(
+ const base::Callback<void(crypto::ScopedPK11Slot)>& callback) {
+ callback.Run(crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()));
+}
+
+} // namespace
+
+crypto::ScopedPK11Slot GetPublicNSSKeySlotForResourceContext(
+ content::ResourceContext* context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+#if defined(OS_CHROMEOS)
+ NSSSlotService* service = g_nss_slot_factory.Get().GetService(context);
+ if (service)
+ return service->GetPublicNSSKeySlot();
+#endif
+ return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot());
+}
+
+crypto::ScopedPK11Slot GetPrivateNSSKeySlotForResourceContext(
+ content::ResourceContext* context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+#if defined(OS_CHROMEOS)
+ NSSSlotService* service = g_nss_slot_factory.Get().GetService(context);
+ if (service)
+ return service->GetPrivateNSSKeySlot();
+#endif
+ return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot());
+}
+
+void OnPrivateNSSKeySlotForResourceContextReady(
+ content::ResourceContext* context,
+ const base::Callback<void(crypto::ScopedPK11Slot)>& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+#if defined(OS_CHROMEOS)
+ NSSSlotService* service = g_nss_slot_factory.Get().GetService(context);
+ if (service) {
+ service->OnPrivateNSSKeySlotForResourceContextReady(callback);
+ return;
+ }
+ crypto::OnTPMReady(base::Bind(&PassTPMToCallback, callback));
+#else
+ PassTPMToCallback(callback);
+#endif
+}
+
+void GetNSSCertDatabaseForResourceContext(
+ content::ResourceContext* context,
+ const base::Callback<void(net::NSSCertDatabase*)>& callback) {
+#if defined(OS_CHROMEOS)
+ NSSSlotService* service = g_nss_slot_factory.Get().GetService(context);
+ if (service) {
+ service->OnNSSCertDatabaseForResourceContextReady(callback);
+ return;
+ }
+#else
+ callback.Run(NSSCertDatabase::GetInstance());
+#endif
+}
« no previous file with comments | « chrome/browser/net/nss_slot_factory.h ('k') | chrome/browser/policy/browser_policy_connector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698