summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/cros/cert_library.cc79
-rw-r--r--chrome/browser/chromeos/cros/cryptohome_library.cc21
-rw-r--r--chrome/browser/chromeos/cros/cryptohome_library.h11
-rw-r--r--chrome/browser/chromeos/cros/mock_cryptohome_library.h2
-rw-r--r--chrome/browser/chromeos/dbus/cryptohome_client.cc82
-rw-r--r--chrome/browser/chromeos/dbus/cryptohome_client.h27
-rw-r--r--chrome/browser/chromeos/dbus/mock_cryptohome_client.h7
-rw-r--r--chrome/browser/chromeos/login/user_manager.cc82
-rw-r--r--chrome/browser/ui/webui/about_ui.cc42
-rw-r--r--chrome/browser/ui/webui/options/certificate_manager_handler.cc22
-rw-r--r--chrome/browser/ui/webui/options/certificate_manager_handler.h12
-rw-r--r--chrome/browser/ui/webui/options2/certificate_manager_handler2.cc22
-rw-r--r--chrome/browser/ui/webui/options2/certificate_manager_handler2.h12
-rw-r--r--crypto/nss_util.cc89
-rw-r--r--crypto/nss_util.h23
15 files changed, 342 insertions, 191 deletions
diff --git a/chrome/browser/chromeos/cros/cert_library.cc b/chrome/browser/chromeos/cros/cert_library.cc
index c0e0f01..3674981e 100644
--- a/chrome/browser/chromeos/cros/cert_library.cc
+++ b/chrome/browser/chromeos/cros/cert_library.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/memory/weak_ptr.h"
#include "base/observer_list_threadsafe.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
@@ -98,9 +99,6 @@ namespace chromeos {
//////////////////////////////////////////////////////////////////////////////
-// base::Unretained(this) in the class is safe. By the time this object is
-// deleted as part of CrosLibrary, the DB thread and the UI message loop
-// are already terminated.
class CertLibraryImpl
: public CertLibrary,
public net::CertDatabase::Observer {
@@ -115,7 +113,8 @@ class CertLibraryImpl
ALLOW_THIS_IN_INITIALIZER_LIST(certs_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(user_certs_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(server_certs_(this)),
- ALLOW_THIS_IN_INITIALIZER_LIST(server_ca_certs_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(server_ca_certs_(this)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
net::CertDatabase::AddObserver(this);
}
@@ -149,36 +148,14 @@ class CertLibraryImpl
VLOG(1) << "Requesting Certificates.";
// Need TPM token name to filter user certificates.
- // TODO(stevenjb): crypto::EnsureTPMTokenReady() may block if init has
- // not succeeded. It is not clear whether or not TPM / PKCS#11 init can
- // be done safely on a non blocking thread. Blocking time is low.
- if (crypto::EnsureTPMTokenReady()) {
- std::string unused_pin;
- // TODO(stevenjb): Make this asynchronous. It results in a synchronous
- // D-Bus call in cryptohome (~3 ms).
- crypto::GetTPMTokenInfo(&tpm_token_name_, &unused_pin);
+ if (crypto::IsTPMTokenReady()) {
+ const bool tpm_token_ready = true;
+ RequestCertificatesInternal(tpm_token_ready);
} else {
- if (crypto::IsTPMTokenAvailable()) {
- VLOG(1) << "TPM token not ready.";
- if (request_task_.is_null()) {
- // Cryptohome does not notify us when the token is ready, so call
- // this again after a delay.
- request_task_ = base::Bind(&CertLibraryImpl::RequestCertificatesTask,
- base::Unretained(this));
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE, request_task_, kRequestDelayMs);
- }
- return;
- }
- // TPM is not enabled, so proceed with empty tpm token name.
- VLOG(1) << "TPM not available.";
+ crypto::InitializeTPMToken(
+ base::Bind(&CertLibraryImpl::RequestCertificatesInternal,
+ weak_ptr_factory_.GetWeakPtr()));
}
-
- // tpm_token_name_ is set, load the certificates on the DB thread.
- BrowserThread::PostTask(
- BrowserThread::DB, FROM_HERE,
- base::Bind(&CertLibraryImpl::LoadCertificates,
- base::Unretained(this)));
}
virtual void AddObserver(CertLibrary::Observer* observer) OVERRIDE {
@@ -262,7 +239,7 @@ class CertLibraryImpl
BrowserThread::PostTask(
BrowserThread::DB, FROM_HERE,
base::Bind(&CertLibraryImpl::LoadCertificates,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -273,7 +250,7 @@ class CertLibraryImpl
BrowserThread::PostTask(
BrowserThread::DB, FROM_HERE,
base::Bind(&CertLibraryImpl::LoadCertificates,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -293,7 +270,7 @@ class CertLibraryImpl
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&CertLibraryImpl::UpdateCertificates,
- base::Unretained(this), cert_list));
+ weak_ptr_factory_.GetWeakPtr(), cert_list));
}
// Comparison functor for locale-sensitive sorting of certificates by name.
@@ -407,6 +384,36 @@ class CertLibraryImpl
return supplemental_user_key_.get() != NULL;
}
+ // This method is used to implement RequestCertificates.
+ void RequestCertificatesInternal(bool tpm_token_ready) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (tpm_token_ready) {
+ std::string unused_pin;
+ crypto::GetTPMTokenInfo(&tpm_token_name_, &unused_pin);
+ } else {
+ if (crypto::IsTPMTokenAvailable()) {
+ VLOG(1) << "TPM token not ready.";
+ if (request_task_.is_null()) {
+ // Cryptohome does not notify us when the token is ready, so call
+ // this again after a delay.
+ request_task_ = base::Bind(&CertLibraryImpl::RequestCertificatesTask,
+ weak_ptr_factory_.GetWeakPtr());
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE, request_task_, kRequestDelayMs);
+ }
+ return;
+ }
+ // TPM is not enabled, so proceed with empty tpm token name.
+ VLOG(1) << "TPM not available.";
+ }
+
+ // tpm_token_name_ is set, load the certificates on the DB thread.
+ BrowserThread::PostTask(
+ BrowserThread::DB, FROM_HERE,
+ base::Bind(&CertLibraryImpl::LoadCertificates,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
// Observers.
const scoped_refptr<CertLibraryObserverList> observer_list_;
@@ -430,6 +437,8 @@ class CertLibraryImpl
CertList server_certs_;
CertList server_ca_certs_;
+ base::WeakPtrFactory<CertLibraryImpl> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(CertLibraryImpl);
};
diff --git a/chrome/browser/chromeos/cros/cryptohome_library.cc b/chrome/browser/chromeos/cros/cryptohome_library.cc
index 9991055..d8d16d3 100644
--- a/chrome/browser/chromeos/cros/cryptohome_library.cc
+++ b/chrome/browser/chromeos/cros/cryptohome_library.cc
@@ -130,19 +130,6 @@ class CryptohomeLibraryImpl : public CryptohomeLibrary {
return result;
}
- virtual void Pkcs11GetTpmTokenInfo(
- std::string* label, std::string* user_pin) OVERRIDE {
- DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo(
- label, user_pin);
- }
-
- virtual bool Pkcs11IsTpmTokenReady() OVERRIDE {
- bool result = false;
- DBusThreadManager::Get()->GetCryptohomeClient()->
- Pkcs11IsTpmTokenReady(&result);
- return result;
- }
-
virtual std::string HashPassword(const std::string& password) OVERRIDE {
// Get salt, ascii encode, update sha with that, then update with ascii
// of password, then end.
@@ -250,14 +237,6 @@ class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
return !locked_;
}
- virtual void Pkcs11GetTpmTokenInfo(std::string* label,
- std::string* user_pin) OVERRIDE {
- *label = "Stub TPM Token";
- *user_pin = "012345";
- }
-
- virtual bool Pkcs11IsTpmTokenReady() OVERRIDE { return true; }
-
virtual std::string HashPassword(const std::string& password) OVERRIDE {
return StringToLowerASCII(base::HexEncode(
reinterpret_cast<const void*>(password.data()),
diff --git a/chrome/browser/chromeos/cros/cryptohome_library.h b/chrome/browser/chromeos/cros/cryptohome_library.h
index 9457671..3f684b2 100644
--- a/chrome/browser/chromeos/cros/cryptohome_library.h
+++ b/chrome/browser/chromeos/cros/cryptohome_library.h
@@ -54,17 +54,6 @@ class CryptohomeLibrary {
virtual bool InstallAttributesIsInvalid() = 0;
virtual bool InstallAttributesIsFirstInstall() = 0;
- // Get the PKCS#11 token info from the TPM. This is different from
- // the TpmGetPassword because it's getting the PKCS#11 user PIN and
- // not the TPM password.
- virtual void Pkcs11GetTpmTokenInfo(std::string* label,
- std::string* user_pin) = 0;
-
- // Gets the status of the TPM. This is different from TpmIsReady
- // because it's getting the staus of the PKCS#11 initialization of
- // the TPM token, not the TPM itself.
- virtual bool Pkcs11IsTpmTokenReady() = 0;
-
// Returns hash of |password|, salted with the system salt.
virtual std::string HashPassword(const std::string& password) = 0;
diff --git a/chrome/browser/chromeos/cros/mock_cryptohome_library.h b/chrome/browser/chromeos/cros/mock_cryptohome_library.h
index dc50063..1a7c1bb 100644
--- a/chrome/browser/chromeos/cros/mock_cryptohome_library.h
+++ b/chrome/browser/chromeos/cros/mock_cryptohome_library.h
@@ -33,8 +33,6 @@ class MockCryptohomeLibrary : public CryptohomeLibrary {
MOCK_METHOD1(TpmGetPassword, bool(std::string* password));
MOCK_METHOD0(TpmCanAttemptOwnership, void(void));
MOCK_METHOD0(TpmClearStoredPassword, void(void));
- MOCK_METHOD0(Pkcs11IsTpmTokenReady, bool(void));
- MOCK_METHOD2(Pkcs11GetTpmTokenInfo, void(std::string*, std::string*));
MOCK_METHOD2(InstallAttributesGet, bool(const std::string&, std::string*));
MOCK_METHOD2(InstallAttributesSet, bool(const std::string&,
diff --git a/chrome/browser/chromeos/dbus/cryptohome_client.cc b/chrome/browser/chromeos/dbus/cryptohome_client.cc
index 4011768..d234503 100644
--- a/chrome/browser/chromeos/dbus/cryptohome_client.cc
+++ b/chrome/browser/chromeos/dbus/cryptohome_client.cc
@@ -220,26 +220,29 @@ class CryptohomeClientImpl : public CryptohomeClient {
}
// CryptohomeClient override.
- virtual bool Pkcs11IsTpmTokenReady(bool* ready) OVERRIDE {
+ virtual void Pkcs11IsTpmTokenReady(Pkcs11IsTpmTokenReadyCallback callback)
+ OVERRIDE {
INITIALIZE_METHOD_CALL(method_call,
cryptohome::kCryptohomePkcs11IsTpmTokenReady);
- return CallMethodAndBlock(&method_call, base::Bind(&PopBool, ready));
+ proxy_->CallMethod(
+ &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(
+ &CryptohomeClientImpl::OnPkcs11IsTpmTokenReady,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
}
// CryptohomeClient override.
- virtual bool Pkcs11GetTpmTokenInfo(std::string* label,
- std::string* user_pin) OVERRIDE {
+ virtual void Pkcs11GetTpmTokenInfo(Pkcs11GetTpmTokenInfoCallback callback)
+ OVERRIDE {
INITIALIZE_METHOD_CALL(method_call,
cryptohome::kCryptohomePkcs11GetTpmTokenInfo);
- if (!CallMethodAndBlock(&method_call,
- base::Bind(&PopTwoValues,
- base::Bind(&PopString, label),
- base::Bind(&PopString, user_pin)))) {
- label->clear();
- user_pin->clear();
- return false;
- }
- return true;
+ proxy_->CallMethod(
+ &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(
+ &CryptohomeClientImpl::OnPkcs11GetTpmTokenInfo,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
}
// CryptohomeClient override.
@@ -366,6 +369,39 @@ class CryptohomeClientImpl : public CryptohomeClient {
}
}
+ // Handles responses for Pkcs11IsTpmTokenReady.
+ void OnPkcs11IsTpmTokenReady(Pkcs11IsTpmTokenReadyCallback callback,
+ dbus::Response* response) {
+ if (!response) {
+ callback.Run(FAILURE, false);
+ return;
+ }
+ dbus::MessageReader reader(response);
+ bool ready = false;
+ if (!reader.PopBool(&ready)) {
+ callback.Run(FAILURE, false);
+ return;
+ }
+ callback.Run(SUCCESS, ready);
+ }
+
+ // Handles responses for Pkcs11GetTpmtTokenInfo.
+ void OnPkcs11GetTpmTokenInfo(Pkcs11GetTpmTokenInfoCallback callback,
+ dbus::Response* response) {
+ if (!response) {
+ callback.Run(FAILURE, std::string(), std::string());
+ return;
+ }
+ dbus::MessageReader reader(response);
+ std::string label;
+ std::string user_pin;
+ if (!reader.PopString(&label) || !reader.PopString(&user_pin)) {
+ callback.Run(FAILURE, std::string(), std::string());
+ return;
+ }
+ callback.Run(SUCCESS, label, user_pin);
+ }
+
// Handles AsyncCallStatus signal.
void OnAsyncCallStatus(dbus::Signal* signal) {
dbus::MessageReader reader(signal);
@@ -508,19 +544,23 @@ class CryptohomeClientStubImpl : public CryptohomeClient {
virtual bool TpmClearStoredPassword() OVERRIDE { return true; }
// CryptohomeClient override.
- virtual bool Pkcs11IsTpmTokenReady(bool* ready) OVERRIDE {
- *ready = true;
- return true;
+ virtual void Pkcs11IsTpmTokenReady(base::Callback<void(CallStatus call_status,
+ bool ready)> callback)
+ OVERRIDE {
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, SUCCESS, true));
}
// CryptohomeClient override.
- virtual bool Pkcs11GetTpmTokenInfo(std::string* label,
- std::string* user_pin) OVERRIDE {
+ virtual void Pkcs11GetTpmTokenInfo(
+ base::Callback<void(CallStatus call_status,
+ const std::string& label,
+ const std::string& user_pin)> callback) OVERRIDE {
const char kStubLabel[] = "Stub TPM Token";
const char kStubUserPin[] = "012345";
- *label = kStubLabel;
- *user_pin = kStubUserPin;
- return true;
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, SUCCESS, kStubLabel, kStubUserPin));
}
// CryptohomeClient override.
diff --git a/chrome/browser/chromeos/dbus/cryptohome_client.h b/chrome/browser/chromeos/dbus/cryptohome_client.h
index 78e736f..a7a1d05 100644
--- a/chrome/browser/chromeos/dbus/cryptohome_client.h
+++ b/chrome/browser/chromeos/dbus/cryptohome_client.h
@@ -23,11 +23,24 @@ namespace chromeos {
// initializes the DBusThreadManager instance.
class CryptohomeClient {
public:
+ // An enum to describe whether or not a DBus method call succeeded.
+ enum CallStatus{
+ FAILURE,
+ SUCCESS,
+ };
// A callback to handle AsyncCallStatus signals.
typedef base::Callback<void(int async_id, bool return_status, int return_code)
> AsyncCallStatusHandler;
// A callback to handle responses of AsyncXXX methods.
typedef base::Callback<void(int async_id)> AsyncMethodCallback;
+ // A callback to handle responses of Pkcs11IsTpmTokenReady method.
+ typedef base::Callback<void(CallStatus call_status, bool ready)>
+ Pkcs11IsTpmTokenReadyCallback;
+ // A callback to handle responses of Pkcs11GetTpmTokenInfo method.
+ typedef base::Callback<void(
+ CallStatus call_status,
+ const std::string& label,
+ const std::string& user_pin)> Pkcs11GetTpmTokenInfoCallback;
virtual ~CryptohomeClient();
@@ -110,15 +123,13 @@ class CryptohomeClient {
// succeeds. This method blocks until the call returns.
virtual bool TpmClearStoredPassword() = 0;
- // Calls Pkcs11IsTpmTokenReady method and returns true when the call succeeds.
- // This method blocks until the call returns.
- virtual bool Pkcs11IsTpmTokenReady(bool* ready) = 0;
+ // Calls Pkcs11IsTpmTokenReady method.
+ virtual void Pkcs11IsTpmTokenReady(
+ Pkcs11IsTpmTokenReadyCallback callback) = 0;
- // Calls Pkcs11GetTpmTokenInfo method and returns true when the call succeeds.
- // This method blocks until the call returns.
- // The original content of |label| and |user_pin| are lost.
- virtual bool Pkcs11GetTpmTokenInfo(std::string* label,
- std::string* user_pin) = 0;
+ // Calls Pkcs11GetTpmTokenInfo method.
+ virtual void Pkcs11GetTpmTokenInfo(
+ Pkcs11GetTpmTokenInfoCallback callback) = 0;
// Calls InstallAttributesGet method and returns true when the call succeeds.
// This method blocks until the call returns.
diff --git a/chrome/browser/chromeos/dbus/mock_cryptohome_client.h b/chrome/browser/chromeos/dbus/mock_cryptohome_client.h
index f053026..457cc8d 100644
--- a/chrome/browser/chromeos/dbus/mock_cryptohome_client.h
+++ b/chrome/browser/chromeos/dbus/mock_cryptohome_client.h
@@ -46,9 +46,10 @@ class MockCryptohomeClient : public CryptohomeClient {
MOCK_METHOD1(TpmIsBeingOwned, bool(bool* owning));
MOCK_METHOD0(TpmCanAttemptOwnership, bool());
MOCK_METHOD0(TpmClearStoredPassword, bool());
- MOCK_METHOD1(Pkcs11IsTpmTokenReady, bool(bool* ready));
- MOCK_METHOD2(Pkcs11GetTpmTokenInfo,
- bool(std::string* label, std::string* user_pin));
+ MOCK_METHOD1(Pkcs11IsTpmTokenReady,
+ void(Pkcs11IsTpmTokenReadyCallback callback));
+ MOCK_METHOD1(Pkcs11GetTpmTokenInfo,
+ void(Pkcs11GetTpmTokenInfoCallback callback));
MOCK_METHOD3(InstallAttributesGet,
bool(const std::string& name,
std::vector<uint8>* value,
diff --git a/chrome/browser/chromeos/login/user_manager.cc b/chrome/browser/chromeos/login/user_manager.cc
index a8d881b..3b56995 100644
--- a/chrome/browser/chromeos/login/user_manager.cc
+++ b/chrome/browser/chromeos/login/user_manager.cc
@@ -25,9 +25,10 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cert_library.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/cros_settings.h"
#include "chrome/browser/chromeos/cryptohome/async_method_caller.h"
+#include "chrome/browser/chromeos/dbus/cryptohome_client.h"
+#include "chrome/browser/chromeos/dbus/dbus_thread_manager.h"
#include "chrome/browser/chromeos/input_method/input_method_manager.h"
#include "chrome/browser/chromeos/login/default_user_images.h"
#include "chrome/browser/chromeos/login/helper.h"
@@ -197,41 +198,56 @@ class RealTPMTokenInfoDelegate : public crypto::TPMTokenInfoDelegate {
public:
RealTPMTokenInfoDelegate();
virtual ~RealTPMTokenInfoDelegate();
+ // TPMTokenInfoDeleagte overrides:
virtual bool IsTokenAvailable() const OVERRIDE;
- virtual bool IsTokenReady() const OVERRIDE;
+ virtual void RequestIsTokenReady(
+ base::Callback<void(bool result)> callback) const OVERRIDE;
virtual void GetTokenInfo(std::string* token_name,
std::string* user_pin) const OVERRIDE;
private:
+ // This method is used to implement RequestIsTokenReady.
+ void OnPkcs11IsTpmTokenReady(base::Callback<void(bool result)> callback,
+ CryptohomeClient::CallStatus call_status,
+ bool is_tpm_token_ready) const;
+
+ // This method is used to implement RequestIsTokenReady.
+ void OnPkcs11GetTpmTokenInfo(base::Callback<void(bool result)> callback,
+ CryptohomeClient::CallStatus call_status,
+ const std::string& token_name,
+ const std::string& user_pin) const;
+
// These are mutable since we need to cache them in IsTokenReady().
mutable bool token_ready_;
mutable std::string token_name_;
mutable std::string user_pin_;
+ mutable base::WeakPtrFactory<RealTPMTokenInfoDelegate> weak_ptr_factory_;
};
-RealTPMTokenInfoDelegate::RealTPMTokenInfoDelegate() : token_ready_(false) {}
+RealTPMTokenInfoDelegate::RealTPMTokenInfoDelegate() : token_ready_(false),
+ weak_ptr_factory_(this) {
+}
+
RealTPMTokenInfoDelegate::~RealTPMTokenInfoDelegate() {}
bool RealTPMTokenInfoDelegate::IsTokenAvailable() const {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- return CrosLibrary::Get()->GetCryptohomeLibrary()->TpmIsEnabled();
+ bool result = false;
+ DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled(&result);
+ return result;
}
-bool RealTPMTokenInfoDelegate::IsTokenReady() const {
- // Note: This should only be getting called from the UI thread, however
- // if this does get called from another thread and token_ready_ is true,
- // we can safely just return true here.
- // TODO(stevenjb/gspencer): Clean this up to improve thread safety.
- if (token_ready_)
- return true;
+void RealTPMTokenInfoDelegate::RequestIsTokenReady(
+ base::Callback<void(bool result)> callback) const {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // Retrieve token_name_ and user_pin_ here since they will never change
- // and CryptohomeLibrary calls are not thread safe.
- if (CrosLibrary::Get()->GetCryptohomeLibrary()->Pkcs11IsTpmTokenReady()) {
- CrosLibrary::Get()->GetCryptohomeLibrary()->Pkcs11GetTpmTokenInfo(
- &token_name_, &user_pin_);
- token_ready_ = true;
+ if (token_ready_) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, true));
+ return;
}
- return token_ready_;
+ DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady(
+ base::Bind(&RealTPMTokenInfoDelegate::OnPkcs11IsTpmTokenReady,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
}
void RealTPMTokenInfoDelegate::GetTokenInfo(std::string* token_name,
@@ -245,6 +261,36 @@ void RealTPMTokenInfoDelegate::GetTokenInfo(std::string* token_name,
*user_pin = user_pin_;
}
+void RealTPMTokenInfoDelegate::OnPkcs11IsTpmTokenReady(
+ base::Callback<void(bool result)> callback,
+ CryptohomeClient::CallStatus call_status,
+ bool is_tpm_token_ready) const {
+ if (call_status != CryptohomeClient::SUCCESS || !is_tpm_token_ready) {
+ callback.Run(false);
+ return;
+ }
+
+ // 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(&RealTPMTokenInfoDelegate::OnPkcs11GetTpmTokenInfo,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
+}
+
+void RealTPMTokenInfoDelegate::OnPkcs11GetTpmTokenInfo(
+ base::Callback<void(bool result)> callback,
+ CryptohomeClient::CallStatus call_status,
+ const std::string& token_name,
+ const std::string& user_pin) const {
+ if (call_status == CryptohomeClient::SUCCESS) {
+ token_name_ = token_name;
+ user_pin_ = user_pin;
+ token_ready_ = true;
+ }
+ callback.Run(token_ready_);
+}
+
} // namespace
// static
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc
index 7fa4817..be93730 100644
--- a/chrome/browser/ui/webui/about_ui.cc
+++ b/chrome/browser/ui/webui/about_ui.cc
@@ -76,6 +76,8 @@
#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/customization_document.h"
+#include "chrome/browser/chromeos/dbus/cryptohome_client.h"
+#include "chrome/browser/chromeos/dbus/dbus_thread_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/version_loader.h"
#include "chrome/browser/oom_priority_manager.h"
@@ -507,7 +509,15 @@ std::string AddStringRow(const std::string& name, const std::string& value) {
return WrapWithTR(row);
}
-std::string GetCryptohomeHtmlInfo(int refresh) {
+void FinishCryptohomeDataRequestInternal(
+ scoped_refptr<AboutUIHTMLSource> source,
+ int refresh,
+ int request_id,
+ chromeos::CryptohomeClient::CallStatus call_status,
+ bool is_tpm_token_ready) {
+ if (call_status != chromeos::CryptohomeClient::SUCCESS)
+ is_tpm_token_ready = false;
+
chromeos::CryptohomeLibrary* cryptohome =
chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
std::string output;
@@ -522,8 +532,7 @@ std::string GetCryptohomeHtmlInfo(int refresh) {
output.append(AddBoolRow("TpmIsEnabled", cryptohome->TpmIsEnabled()));
output.append(AddBoolRow("TpmIsOwned", cryptohome->TpmIsOwned()));
output.append(AddBoolRow("TpmIsBeingOwned", cryptohome->TpmIsBeingOwned()));
- output.append(AddBoolRow("Pkcs11IsTpmTokenReady",
- cryptohome->Pkcs11IsTpmTokenReady()));
+ output.append(AddBoolRow("Pkcs11IsTpmTokenReady", is_tpm_token_ready));
output.append("</table>");
std::string token_name, user_pin;
@@ -536,13 +545,20 @@ std::string GetCryptohomeHtmlInfo(int refresh) {
output.append("</table>");
AppendFooter(&output);
- return output;
+ source->FinishDataRequest(output, request_id);
}
-std::string AboutCryptohome(const std::string& query) {
+void FinishCryptohomeDataRequest(scoped_refptr<AboutUIHTMLSource> source,
+ const std::string& query,
+ int request_id) {
int refresh;
base::StringToInt(query, &refresh);
- return GetCryptohomeHtmlInfo(refresh);
+
+ chromeos::DBusThreadManager::Get()->GetCryptohomeClient()->
+ Pkcs11IsTpmTokenReady(base::Bind(&FinishCryptohomeDataRequestInternal,
+ source,
+ refresh,
+ request_id));
}
std::string AboutDiscardsRun() {
@@ -742,8 +758,9 @@ std::string AboutHistograms(const std::string& query) {
return data;
}
-void AboutMemory(const std::string& path, AboutUIHTMLSource* source,
- int request_id) {
+void FinishMemoryDataRequest(const std::string& path,
+ AboutUIHTMLSource* source,
+ int request_id) {
if (path == kStringsJsPath) {
// The AboutMemoryHandler cleans itself up, but |StartFetch()| will want
// the refcount to be greater than 0.
@@ -1293,8 +1310,8 @@ AboutUIHTMLSource::~AboutUIHTMLSource() {
}
void AboutUIHTMLSource::StartDataRequest(const std::string& path,
- bool is_incognito,
- int request_id) {
+ bool is_incognito,
+ int request_id) {
std::string response;
std::string host = source_name();
// Add your data source here, in alphabetical order.
@@ -1306,7 +1323,8 @@ void AboutUIHTMLSource::StartDataRequest(const std::string& path,
idr).as_string();
#if defined(OS_CHROMEOS)
} else if (host == chrome::kChromeUICryptohomeHost) {
- response = AboutCryptohome(path);
+ FinishCryptohomeDataRequest(this, path, request_id);
+ return;
} else if (host == chrome::kChromeUIDiscardsHost) {
response = AboutDiscards(path);
#endif
@@ -1322,7 +1340,7 @@ void AboutUIHTMLSource::StartDataRequest(const std::string& path,
} else if (host == chrome::kChromeUIMemoryHost) {
response = GetAboutMemoryRedirectResponse(profile());
} else if (host == chrome::kChromeUIMemoryRedirectHost) {
- AboutMemory(path, this, request_id);
+ FinishMemoryDataRequest(path, this, request_id);
return;
#if defined(OS_CHROMEOS)
} else if (host == chrome::kChromeUINetworkHost) {
diff --git a/chrome/browser/ui/webui/options/certificate_manager_handler.cc b/chrome/browser/ui/webui/options/certificate_manager_handler.cc
index e69d279..e7a8bc6 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_handler.cc
+++ b/chrome/browser/ui/webui/options/certificate_manager_handler.cc
@@ -26,8 +26,8 @@
#include "ui/base/l10n/l10n_util_collator.h"
#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/cryptohome_library.h"
+#include "chrome/browser/chromeos/dbus/cryptohome_client.h"
+#include "chrome/browser/chromeos/dbus/dbus_thread_manager.h"
#endif
using content::BrowserThread;
@@ -244,7 +244,8 @@ void FileAccessProvider::DoWrite(
// CertificateManagerHandler
CertificateManagerHandler::CertificateManagerHandler()
- : file_access_provider_(new FileAccessProvider) {
+ : file_access_provider_(new FileAccessProvider),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
certificate_manager_model_.reset(new CertificateManagerModel(this));
}
@@ -1031,11 +1032,18 @@ void CertificateManagerHandler::ShowImportErrors(
#if defined(OS_CHROMEOS)
void CertificateManagerHandler::CheckTpmTokenReady(const ListValue* args) {
- chromeos::CryptohomeLibrary* cryptohome =
- chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
+ chromeos::CryptohomeClient* cryptohome_client =
+ chromeos::DBusThreadManager::Get()->GetCryptohomeClient();
+ cryptohome_client->Pkcs11IsTpmTokenReady(
+ base::Bind(&CertificateManagerHandler::CheckTpmTokenReadyInternal,
+ weak_ptr_factory_.GetWeakPtr()));
+}
- // TODO(xiyuan): Use async way when underlying supports it.
- base::FundamentalValue ready(cryptohome->Pkcs11IsTpmTokenReady());
+void CertificateManagerHandler::CheckTpmTokenReadyInternal(
+ chromeos::CryptohomeClient::CallStatus call_status,
+ bool is_tpm_token_ready) {
+ base::FundamentalValue ready(
+ call_status == chromeos::CryptohomeClient::SUCCESS && is_tpm_token_ready);
web_ui()->CallJavascriptFunction("CertificateManager.onCheckTpmTokenReady",
ready);
}
diff --git a/chrome/browser/ui/webui/options/certificate_manager_handler.h b/chrome/browser/ui/webui/options/certificate_manager_handler.h
index f1aab66d..5365dc3 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_handler.h
+++ b/chrome/browser/ui/webui/options/certificate_manager_handler.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/certificate_manager_model.h"
#include "chrome/browser/ui/select_file_dialog.h"
@@ -17,6 +18,10 @@
#include "net/base/cert_database.h"
#include "ui/gfx/native_widget_types.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/dbus/cryptohome_client.h"
+#endif
+
class FileAccessProvider;
class CertificateManagerHandler : public OptionsPageUIHandler,
@@ -143,6 +148,9 @@ class CertificateManagerHandler : public OptionsPageUIHandler,
#if defined(OS_CHROMEOS)
// Check whether Tpm token is ready and notifiy JS side.
void CheckTpmTokenReady(const base::ListValue* args);
+ void CheckTpmTokenReadyInternal(
+ chromeos::CryptohomeClient::CallStatus call_status,
+ bool is_tpm_token_ready);
#endif
gfx::NativeWindow GetParentWindow() const;
@@ -165,6 +173,8 @@ class CertificateManagerHandler : public OptionsPageUIHandler,
CancelableRequestConsumer consumer_;
scoped_refptr<FileAccessProvider> file_access_provider_;
+ base::WeakPtrFactory<CertificateManagerHandler> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(CertificateManagerHandler);
};
diff --git a/chrome/browser/ui/webui/options2/certificate_manager_handler2.cc b/chrome/browser/ui/webui/options2/certificate_manager_handler2.cc
index 9e95d9d..e8add47 100644
--- a/chrome/browser/ui/webui/options2/certificate_manager_handler2.cc
+++ b/chrome/browser/ui/webui/options2/certificate_manager_handler2.cc
@@ -26,8 +26,8 @@
#include "ui/base/l10n/l10n_util_collator.h"
#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/cros/cros_library.h"
-#include "chrome/browser/chromeos/cros/cryptohome_library.h"
+#include "chrome/browser/chromeos/dbus/cryptohome_client.h"
+#include "chrome/browser/chromeos/dbus/dbus_thread_manager.h"
#endif
using content::BrowserThread;
@@ -246,7 +246,8 @@ void FileAccessProvider::DoWrite(
// CertificateManagerHandler
CertificateManagerHandler::CertificateManagerHandler()
- : file_access_provider_(new FileAccessProvider()) {
+ : file_access_provider_(new FileAccessProvider()),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
certificate_manager_model_.reset(new CertificateManagerModel(this));
}
@@ -1038,11 +1039,18 @@ void CertificateManagerHandler::ShowImportErrors(
#if defined(OS_CHROMEOS)
void CertificateManagerHandler::CheckTpmTokenReady(const ListValue* args) {
- chromeos::CryptohomeLibrary* cryptohome =
- chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
+ chromeos::CryptohomeClient* cryptohome_client =
+ chromeos::DBusThreadManager::Get()->GetCryptohomeClient();
+ cryptohome_client->Pkcs11IsTpmTokenReady(
+ base::Bind(&CertificateManagerHandler::CheckTpmTokenReadyInternal,
+ weak_ptr_factory_.GetWeakPtr()));
+}
- // TODO(xiyuan): Use async way when underlying supports it.
- base::FundamentalValue ready(cryptohome->Pkcs11IsTpmTokenReady());
+void CertificateManagerHandler::CheckTpmTokenReadyInternal(
+ chromeos::CryptohomeClient::CallStatus call_status,
+ bool is_tpm_token_ready) {
+ base::FundamentalValue ready(
+ call_status == chromeos::CryptohomeClient::SUCCESS && is_tpm_token_ready);
web_ui()->CallJavascriptFunction("CertificateManager.onCheckTpmTokenReady",
ready);
}
diff --git a/chrome/browser/ui/webui/options2/certificate_manager_handler2.h b/chrome/browser/ui/webui/options2/certificate_manager_handler2.h
index c20402d..2b3cd26 100644
--- a/chrome/browser/ui/webui/options2/certificate_manager_handler2.h
+++ b/chrome/browser/ui/webui/options2/certificate_manager_handler2.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/certificate_manager_model.h"
#include "chrome/browser/ui/select_file_dialog.h"
@@ -17,6 +18,10 @@
#include "net/base/cert_database.h"
#include "ui/gfx/native_widget_types.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/dbus/cryptohome_client.h"
+#endif
+
namespace options2 {
class FileAccessProvider;
@@ -145,6 +150,9 @@ class CertificateManagerHandler : public OptionsPageUIHandler,
#if defined(OS_CHROMEOS)
// Check whether Tpm token is ready and notifiy JS side.
void CheckTpmTokenReady(const base::ListValue* args);
+ void CheckTpmTokenReadyInternal(
+ chromeos::CryptohomeClient::CallStatus call_status,
+ bool is_tpm_token_ready);
#endif
gfx::NativeWindow GetParentWindow() const;
@@ -167,6 +175,8 @@ class CertificateManagerHandler : public OptionsPageUIHandler,
CancelableRequestConsumer consumer_;
scoped_refptr<FileAccessProvider> file_access_provider_;
+ base::WeakPtrFactory<CertificateManagerHandler> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(CertificateManagerHandler);
};
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc
index e981cb2..48f356c 100644
--- a/crypto/nss_util.cc
+++ b/crypto/nss_util.cc
@@ -23,12 +23,14 @@
#include <vector>
+#include "base/bind.h"
#include "base/environment.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
#include "base/native_library.h"
#include "base/scoped_temp_dir.h"
#include "base/stringprintf.h"
@@ -250,42 +252,22 @@ class NSSInitSingleton {
tpm_token_info_delegate_.reset(info_delegate);
}
- // This is called whenever we want to make sure Chaps is
- // properly loaded, because it can fail shortly after the initial
- // login while the PINs are being initialized, and we want to retry
- // if this happens.
- bool EnsureTPMTokenReady() {
- // If EnableTPMTokenForNSS hasn't been called, return false.
- if (tpm_token_info_delegate_.get() == NULL)
- return false;
-
- // If everything is already initialized, then return true.
- if (chaps_module_ && tpm_slot_)
- return true;
+ void InitializeTPMToken(InitializeTPMTokenCallback callback) {
+ // If EnableTPMTokenForNSS hasn't been called, run |callback| with false.
+ if (tpm_token_info_delegate_.get() == NULL) {
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, false));
+ return;
+ }
- if (tpm_token_info_delegate_->IsTokenReady()) {
- // This tries to load the Chaps module so NSS can talk to the hardware
- // TPM.
- if (!chaps_module_) {
- chaps_module_ = LoadModule(
- kChapsModuleName,
- kChapsPath,
- // trustOrder=100 -- means it'll select this as the most
- // trusted slot for the mechanisms it provides.
- // slotParams=... -- selects RSA as the only mechanism, and only
- // asks for the password when necessary (instead of every
- // time, or after a timeout).
- "trustOrder=100 slotParams=(1={slotFlags=[RSA] askpw=only})");
- }
- if (chaps_module_) {
- // If this gets set, then we'll use the TPM for certs with
- // private keys, otherwise we'll fall back to the software
- // implementation.
- tpm_slot_ = GetTPMSlot();
- return tpm_slot_ != NULL;
- }
+ // If everything is already initialized, then run |callback| with true.
+ if (chaps_module_ && tpm_slot_) {
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, true));
+ return;
}
- return false;
+ tpm_token_info_delegate_->RequestIsTokenReady(
+ base::Bind(&NSSInitSingleton::InitializeTPMTokenInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
}
bool IsTPMTokenAvailable() {
@@ -420,7 +402,8 @@ class NSSInitSingleton {
test_slot_(NULL),
tpm_slot_(NULL),
root_(NULL),
- chromeos_user_logged_in_(false) {
+ chromeos_user_logged_in_(false),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
EnsureNSPRInit();
// We *must* have NSS >= 3.12.3. See bug 26448.
@@ -544,6 +527,37 @@ class NSSInitSingleton {
}
}
+#if defined(OS_CHROMEOS)
+ // This method is used to implement InitializeTPMToken.
+ void InitializeTPMTokenInternal(InitializeTPMTokenCallback callback,
+ bool is_token_ready) {
+ if (is_token_ready) {
+ // This tries to load the Chaps module so NSS can talk to the hardware
+ // TPM.
+ if (!chaps_module_) {
+ chaps_module_ = LoadModule(
+ kChapsModuleName,
+ kChapsPath,
+ // trustOrder=100 -- means it'll select this as the most
+ // trusted slot for the mechanisms it provides.
+ // slotParams=... -- selects RSA as the only mechanism, and only
+ // asks for the password when necessary (instead of every
+ // time, or after a timeout).
+ "trustOrder=100 slotParams=(1={slotFlags=[RSA] askpw=only})");
+ }
+ if (chaps_module_) {
+ // If this gets set, then we'll use the TPM for certs with
+ // private keys, otherwise we'll fall back to the software
+ // implementation.
+ tpm_slot_ = GetTPMSlot();
+ callback.Run(tpm_slot_ != NULL);
+ return;
+ }
+ }
+ callback.Run(false);
+ }
+#endif
+
#if defined(USE_NSS)
// Load nss's built-in root certs.
SECMODModule* InitDefaultRootCerts() {
@@ -610,6 +624,7 @@ class NSSInitSingleton {
PK11SlotInfo* tpm_slot_;
SECMODModule* root_;
bool chromeos_user_logged_in_;
+ base::WeakPtrFactory<NSSInitSingleton> weak_ptr_factory_;
#if defined(USE_NSS)
// TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011
// is fixed, we will no longer need the lock.
@@ -763,8 +778,8 @@ bool IsTPMTokenReady() {
return g_nss_singleton.Get().IsTPMTokenReady();
}
-bool EnsureTPMTokenReady() {
- return g_nss_singleton.Get().EnsureTPMTokenReady();
+void InitializeTPMToken(InitializeTPMTokenCallback callback) {
+ g_nss_singleton.Get().InitializeTPMToken(callback);
}
SymmetricKey* GetSupplementalUserKey() {
diff --git a/crypto/nss_util.h b/crypto/nss_util.h
index 9cfdf0b..fb5049b 100644
--- a/crypto/nss_util.h
+++ b/crypto/nss_util.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "crypto/crypto_export.h"
#if defined(USE_NSS)
@@ -26,6 +27,9 @@ namespace crypto {
class SymmetricKey;
+// A callback to handle the result of InitializeTPMToken.
+typedef base::Callback<void(bool result)> InitializeTPMTokenCallback;
+
#if defined(USE_NSS)
// EarlySetupForNSSInit performs lightweight setup which must occur before the
// process goes multithreaded. This does not initialise NSS. For test, see
@@ -93,16 +97,22 @@ CRYPTO_EXPORT void OpenPersistentNSSDB();
// communication with cryptohomed and the TPM.
class CRYPTO_EXPORT TPMTokenInfoDelegate {
public:
+ // A callback to handle the result of RequestIsTokenReady.
+ typedef base::Callback<void(bool result)> RequestIsTokenReadyCallback;
+
TPMTokenInfoDelegate();
virtual ~TPMTokenInfoDelegate();
// Returns true if the hardware supports a TPM Token and the TPM is enabled.
virtual bool IsTokenAvailable() const = 0;
- // Returns true if the TPM and PKCS#11 token slot is ready to be used.
- // If IsTokenAvailable() is false this should return false.
- // If IsTokenAvailable() is true, this should eventually return true.
- virtual bool IsTokenReady() const = 0;
+ // Runs |callback| with true if the TPM and PKCS#11 token slot is ready to be
+ // used.
+ // If IsTokenAvailable() is false this should run |callback| with false.
+ // If IsTokenAvailable() is true, this should eventually run |callback| with
+ // true.
+ virtual void RequestIsTokenReady(RequestIsTokenReadyCallback callback) const
+ = 0;
// Fetches token properties. TODO(stevenjb): make this interface asynchronous
// so that the implementation does not have to be blocking.
@@ -132,9 +142,8 @@ CRYPTO_EXPORT bool IsTPMTokenAvailable();
// loaded into NSS.
CRYPTO_EXPORT bool IsTPMTokenReady();
-// Same as IsTPMTokenReady() except this attempts to initialize the token
-// if necessary.
-CRYPTO_EXPORT bool EnsureTPMTokenReady();
+// Initialize the TPM token. Does nothing if it is already initialized.
+CRYPTO_EXPORT void InitializeTPMToken(InitializeTPMTokenCallback callback);
// Gets supplemental user key. Creates one in NSS database if it does not exist.
// The supplemental user key is used for AES encryption of user data that is