diff options
-rw-r--r-- | chrome/browser/chromeos/cros/cert_library.cc | 79 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/cryptohome_library.cc | 21 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/cryptohome_library.h | 11 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/mock_cryptohome_library.h | 2 | ||||
-rw-r--r-- | chrome/browser/chromeos/dbus/cryptohome_client.cc | 82 | ||||
-rw-r--r-- | chrome/browser/chromeos/dbus/cryptohome_client.h | 27 | ||||
-rw-r--r-- | chrome/browser/chromeos/dbus/mock_cryptohome_client.h | 7 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/user_manager.cc | 82 | ||||
-rw-r--r-- | chrome/browser/ui/webui/about_ui.cc | 42 | ||||
-rw-r--r-- | chrome/browser/ui/webui/options/certificate_manager_handler.cc | 22 | ||||
-rw-r--r-- | chrome/browser/ui/webui/options/certificate_manager_handler.h | 12 | ||||
-rw-r--r-- | chrome/browser/ui/webui/options2/certificate_manager_handler2.cc | 22 | ||||
-rw-r--r-- | chrome/browser/ui/webui/options2/certificate_manager_handler2.h | 12 | ||||
-rw-r--r-- | crypto/nss_util.cc | 89 | ||||
-rw-r--r-- | crypto/nss_util.h | 23 |
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 |