1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/crypto_module_password_dialog.h"
10 #include "base/logging.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "net/base/crypto_module.h"
13 #include "net/cert/x509_certificate.h"
15 #if defined(OS_CHROMEOS)
16 #include "crypto/nss_util.h"
19 using content::BrowserThread;
23 bool ShouldShowDialog(const net::CryptoModule* module) {
24 // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
25 return (PK11_NeedLogin(module->os_module_handle()) &&
26 !PK11_IsLoggedIn(module->os_module_handle(), NULL /* wincx */));
29 // Basically an asynchronous implementation of NSS's PK11_DoPassword.
30 // Note: This currently handles only the simple case. See the TODOs in
31 // GotPassword for what is yet unimplemented.
34 SlotUnlocker(const net::CryptoModuleList& modules,
35 chrome::CryptoModulePasswordReason reason,
36 const std::string& host,
37 const base::Closure& callback);
42 void GotPassword(const char* password);
46 net::CryptoModuleList modules_;
47 chrome::CryptoModulePasswordReason reason_;
49 base::Closure callback_;
53 SlotUnlocker::SlotUnlocker(const net::CryptoModuleList& modules,
54 chrome::CryptoModulePasswordReason reason,
55 const std::string& host,
56 const base::Closure& callback)
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
66 void SlotUnlocker::Start() {
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
69 for (; current_ < modules_.size(); ++current_) {
70 if (ShouldShowDialog(modules_[current_].get())) {
71 #if defined(OS_CHROMEOS)
72 if (crypto::IsTPMTokenReady()) {
73 std::string token_name;
75 crypto::GetTPMTokenInfo(&token_name, &user_pin);
76 if (modules_[current_]->GetTokenName() == token_name) {
77 // The user PIN is a well known secret on this machine, and
78 // the user didn't set it, so we need to fetch the value and
79 // supply it for them here.
80 GotPassword(user_pin.c_str());
85 ShowCryptoModulePasswordDialog(
86 modules_[current_]->GetTokenName(),
90 base::Bind(&SlotUnlocker::GotPassword, base::Unretained(this)));
97 void SlotUnlocker::GotPassword(const char* password) {
98 // TODO(mattm): PK11_DoPassword has something about PK11_Global.verifyPass.
100 // http://mxr.mozilla.org/mozilla/source/security/nss/lib/pk11wrap/pk11auth.c#577
103 // User cancelled entering password. Oh well.
109 // TODO(mattm): handle protectedAuthPath
110 SECStatus rv = PK11_CheckUserPassword(modules_[current_]->os_module_handle(),
112 if (rv == SECWouldBlock) {
113 // Incorrect password. Try again.
119 // TODO(mattm): PK11_DoPassword calls nssTrustDomain_UpdateCachedTokenCerts on
120 // non-friendly slots. How important is that?
122 // Correct password (SECSuccess) or too many attempts/other failure
123 // (SECFailure). Either way we're done with this slot.
128 void SlotUnlocker::Done() {
129 DCHECK_EQ(current_, modules_.size());
138 void UnlockSlotsIfNecessary(const net::CryptoModuleList& modules,
139 chrome::CryptoModulePasswordReason reason,
140 const std::string& host,
141 const base::Closure& callback) {
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143 for (size_t i = 0; i < modules.size(); ++i) {
144 if (ShouldShowDialog(modules[i].get())) {
145 (new SlotUnlocker(modules, reason, host, callback))->Start();
152 void UnlockCertSlotIfNecessary(net::X509Certificate* cert,
153 chrome::CryptoModulePasswordReason reason,
154 const std::string& host,
155 const base::Closure& callback) {
156 net::CryptoModuleList modules;
157 modules.push_back(net::CryptoModule::CreateFromHandle(
158 cert->os_cert_handle()->slot));
159 UnlockSlotsIfNecessary(modules, reason, host, callback);
162 } // namespace chrome