OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/cros/cert_library.h" | 5 #include "chrome/browser/chromeos/cros/cert_library.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/memory/weak_ptr.h" | 10 #include "base/memory/weak_ptr.h" |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 issued_to, | 88 issued_to, |
89 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED)); | 89 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED)); |
90 } else { | 90 } else { |
91 return l10n_util::GetStringFUTF16( | 91 return l10n_util::GetStringFUTF16( |
92 IDS_CERT_MANAGER_KEY_FORMAT_LONG, | 92 IDS_CERT_MANAGER_KEY_FORMAT_LONG, |
93 issued_by, | 93 issued_by, |
94 issued_to); | 94 issued_to); |
95 } | 95 } |
96 } | 96 } |
97 | 97 |
98 class RealTPMTokenInfoDelegate : public crypto::TPMTokenInfoDelegate { | |
99 public: | |
100 RealTPMTokenInfoDelegate(); | |
101 virtual ~RealTPMTokenInfoDelegate(); | |
102 | |
103 // TPMTokenInfoDeleagte overrides: | |
104 virtual void RequestIsTokenReady( | |
105 base::Callback<void(bool result)> callback) const OVERRIDE; | |
106 virtual void GetTokenInfo(std::string* token_name, | |
107 std::string* user_pin) const OVERRIDE; | |
108 | |
109 private: | |
110 // This method is used to implement RequestIsTokenReady. | |
111 void OnPkcs11IsTpmTokenReady(base::Callback<void(bool result)> callback, | |
112 DBusMethodCallStatus call_status, | |
113 bool is_tpm_token_ready) const; | |
114 | |
115 // This method is used to implement RequestIsTokenReady. | |
116 void OnPkcs11GetTpmTokenInfo(base::Callback<void(bool result)> callback, | |
117 DBusMethodCallStatus call_status, | |
118 const std::string& token_name, | |
119 const std::string& user_pin) const; | |
120 | |
121 // These are mutable since we need to cache them in IsTokenReady(). | |
122 mutable bool token_ready_; | |
123 mutable std::string token_name_; | |
124 mutable std::string user_pin_; | |
125 mutable base::WeakPtrFactory<RealTPMTokenInfoDelegate> weak_ptr_factory_; | |
126 }; | |
127 | |
128 RealTPMTokenInfoDelegate::RealTPMTokenInfoDelegate() : token_ready_(false), | |
129 weak_ptr_factory_(this) { | |
130 } | |
131 | |
132 RealTPMTokenInfoDelegate::~RealTPMTokenInfoDelegate() {} | |
133 | |
134 void RealTPMTokenInfoDelegate::RequestIsTokenReady( | |
135 base::Callback<void(bool result)> callback) const { | |
136 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
137 if (token_ready_) { | |
138 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
139 base::Bind(callback, true)); | |
140 return; | |
141 } | |
142 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady( | |
143 base::Bind(&RealTPMTokenInfoDelegate::OnPkcs11IsTpmTokenReady, | |
144 weak_ptr_factory_.GetWeakPtr(), | |
145 callback)); | |
146 } | |
147 | |
148 void RealTPMTokenInfoDelegate::GetTokenInfo(std::string* token_name, | |
149 std::string* user_pin) const { | |
150 // May be called from a non UI thread, but must only be called after | |
151 // IsTokenReady() returns true. | |
152 CHECK(token_ready_); | |
153 if (token_name) | |
154 *token_name = token_name_; | |
155 if (user_pin) | |
156 *user_pin = user_pin_; | |
157 } | |
158 | |
159 void RealTPMTokenInfoDelegate::OnPkcs11IsTpmTokenReady( | |
160 base::Callback<void(bool result)> callback, | |
161 DBusMethodCallStatus call_status, | |
162 bool is_tpm_token_ready) const { | |
163 if (call_status != DBUS_METHOD_CALL_SUCCESS || !is_tpm_token_ready) { | |
164 callback.Run(false); | |
165 return; | |
166 } | |
167 | |
168 // Retrieve token_name_ and user_pin_ here since they will never change | |
169 // and CryptohomeClient calls are not thread safe. | |
170 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo( | |
171 base::Bind(&RealTPMTokenInfoDelegate::OnPkcs11GetTpmTokenInfo, | |
172 weak_ptr_factory_.GetWeakPtr(), | |
173 callback)); | |
174 } | |
175 | |
176 void RealTPMTokenInfoDelegate::OnPkcs11GetTpmTokenInfo( | |
177 base::Callback<void(bool result)> callback, | |
178 DBusMethodCallStatus call_status, | |
179 const std::string& token_name, | |
180 const std::string& user_pin) const { | |
181 if (call_status == DBUS_METHOD_CALL_SUCCESS) { | |
182 token_name_ = token_name; | |
183 user_pin_ = user_pin; | |
184 token_ready_ = true; | |
185 } | |
186 callback.Run(token_ready_); | |
187 } | |
188 | |
189 } // namespace | 98 } // namespace |
190 | 99 |
191 ////////////////////////////////////////////////////////////////////////////// | 100 ////////////////////////////////////////////////////////////////////////////// |
192 | 101 |
193 // base::Unretained(this) in the class is safe. By the time this object is | 102 // base::Unretained(this) in the class is safe. By the time this object is |
194 // deleted as part of CrosLibrary, the DB thread and the UI message loop | 103 // deleted as part of CrosLibrary, the DB thread and the UI message loop |
195 // are already terminated. | 104 // are already terminated. |
196 class CertLibraryImpl | 105 class CertLibraryImpl |
197 : public CertLibrary, | 106 : public CertLibrary, |
198 public net::CertDatabase::Observer { | 107 public net::CertDatabase::Observer { |
199 public: | 108 public: |
200 typedef ObserverListThreadSafe<CertLibrary::Observer> CertLibraryObserverList; | 109 typedef ObserverListThreadSafe<CertLibrary::Observer> CertLibraryObserverList; |
201 | 110 |
202 CertLibraryImpl() : | 111 CertLibraryImpl() : |
203 observer_list_(new CertLibraryObserverList), | 112 observer_list_(new CertLibraryObserverList), |
| 113 tpm_token_ready_(false), |
204 user_logged_in_(false), | 114 user_logged_in_(false), |
205 certificates_requested_(false), | 115 certificates_requested_(false), |
206 certificates_loaded_(false), | 116 certificates_loaded_(false), |
207 key_store_loaded_(false), | 117 key_store_loaded_(false), |
208 ALLOW_THIS_IN_INITIALIZER_LIST(certs_(this)), | 118 ALLOW_THIS_IN_INITIALIZER_LIST(certs_(this)), |
209 ALLOW_THIS_IN_INITIALIZER_LIST(user_certs_(this)), | 119 ALLOW_THIS_IN_INITIALIZER_LIST(user_certs_(this)), |
210 ALLOW_THIS_IN_INITIALIZER_LIST(server_certs_(this)), | 120 ALLOW_THIS_IN_INITIALIZER_LIST(server_certs_(this)), |
211 ALLOW_THIS_IN_INITIALIZER_LIST(server_ca_certs_(this)), | 121 ALLOW_THIS_IN_INITIALIZER_LIST(server_ca_certs_(this)), |
212 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 122 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
213 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 123 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
214 << __FUNCTION__ << " should be called on UI thread."; | |
215 net::CertDatabase::AddObserver(this); | 124 net::CertDatabase::AddObserver(this); |
216 } | 125 } |
217 | 126 |
218 ~CertLibraryImpl() { | 127 ~CertLibraryImpl() { |
219 DCHECK(request_task_.is_null()); | 128 DCHECK(request_task_.is_null()); |
220 net::CertDatabase::RemoveObserver(this); | 129 net::CertDatabase::RemoveObserver(this); |
221 } | 130 } |
222 | 131 |
223 // CertLibrary implementation. | 132 // CertLibrary implementation. |
224 virtual void AddObserver(CertLibrary::Observer* observer) OVERRIDE { | 133 virtual void AddObserver(CertLibrary::Observer* observer) OVERRIDE { |
(...skipping 14 matching lines...) Expand all Loading... |
239 | 148 |
240 // Only load the Opencryptoki library into NSS if we have this switch. | 149 // Only load the Opencryptoki library into NSS if we have this switch. |
241 // TODO(gspencer): Remove this switch once cryptohomed work is finished: | 150 // TODO(gspencer): Remove this switch once cryptohomed work is finished: |
242 // http://crosbug.com/12295 and 12304 | 151 // http://crosbug.com/12295 and 12304 |
243 // Note: ChromeOS login with or without loginmanager will crash when | 152 // Note: ChromeOS login with or without loginmanager will crash when |
244 // the CertLibrary is not there (http://crosbug.com/121456). Before removing | 153 // the CertLibrary is not there (http://crosbug.com/121456). Before removing |
245 // make sure that that case still works. | 154 // make sure that that case still works. |
246 if (CommandLine::ForCurrentProcess()->HasSwitch( | 155 if (CommandLine::ForCurrentProcess()->HasSwitch( |
247 switches::kLoadOpencryptoki) || | 156 switches::kLoadOpencryptoki) || |
248 CommandLine::ForCurrentProcess()->HasSwitch(switches::kStubCros)) { | 157 CommandLine::ForCurrentProcess()->HasSwitch(switches::kStubCros)) { |
249 crypto::EnableTPMTokenForNSS(new RealTPMTokenInfoDelegate()); | 158 crypto::EnableTPMTokenForNSS(); |
250 // Note: this calls crypto::EnsureTPMTokenReady() | 159 // Note: this calls crypto::EnsureTPMTokenReady() |
251 RequestCertificates(); | 160 RequestCertificates(); |
252 } | 161 } |
253 key_store_loaded_ = true; | 162 key_store_loaded_ = true; |
254 } | 163 } |
255 | 164 |
256 virtual bool CertificatesLoading() const OVERRIDE { | 165 virtual bool CertificatesLoading() const OVERRIDE { |
257 return certificates_requested_ && !certificates_loaded_; | 166 return certificates_requested_ && !certificates_loaded_; |
258 } | 167 } |
259 | 168 |
260 virtual bool CertificatesLoaded() const OVERRIDE { | 169 virtual bool CertificatesLoaded() const OVERRIDE { |
261 return certificates_loaded_; | 170 return certificates_loaded_; |
262 } | 171 } |
263 | 172 |
264 virtual bool IsHardwareBacked() const OVERRIDE { | 173 virtual bool IsHardwareBacked() const OVERRIDE { |
265 return !tpm_token_name_.empty(); | 174 return !tpm_token_name_.empty(); |
266 } | 175 } |
267 | 176 |
268 virtual const CertList& GetCertificates() const OVERRIDE { | 177 virtual const CertList& GetCertificates() const OVERRIDE { |
269 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 178 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
270 << __FUNCTION__ << " should be called on UI thread."; | |
271 return certs_; | 179 return certs_; |
272 } | 180 } |
273 | 181 |
274 virtual const CertList& GetUserCertificates() const OVERRIDE { | 182 virtual const CertList& GetUserCertificates() const OVERRIDE { |
275 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 183 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
276 << __FUNCTION__ << " should be called on UI thread."; | |
277 return user_certs_; | 184 return user_certs_; |
278 } | 185 } |
279 | 186 |
280 virtual const CertList& GetServerCertificates() const OVERRIDE { | 187 virtual const CertList& GetServerCertificates() const OVERRIDE { |
281 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 188 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
282 << __FUNCTION__ << " should be called on UI thread."; | |
283 return server_certs_; | 189 return server_certs_; |
284 } | 190 } |
285 | 191 |
286 virtual const CertList& GetCACertificates() const OVERRIDE { | 192 virtual const CertList& GetCACertificates() const OVERRIDE { |
287 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 193 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
288 << __FUNCTION__ << " should be called on UI thread."; | |
289 return server_ca_certs_; | 194 return server_ca_certs_; |
290 } | 195 } |
291 | 196 |
292 virtual std::string EncryptToken(const std::string& token) OVERRIDE { | 197 virtual std::string EncryptToken(const std::string& token) OVERRIDE { |
293 if (!LoadSupplementalUserKey()) | 198 if (!LoadSupplementalUserKey()) |
294 return std::string(); | 199 return std::string(); |
295 crypto::Encryptor encryptor; | 200 crypto::Encryptor encryptor; |
296 if (!encryptor.Init(supplemental_user_key_.get(), crypto::Encryptor::CTR, | 201 if (!encryptor.Init(supplemental_user_key_.get(), crypto::Encryptor::CTR, |
297 std::string())) | 202 std::string())) |
298 return std::string(); | 203 return std::string(); |
(...skipping 14 matching lines...) Expand all Loading... |
313 const std::string& encrypted_token_hex) OVERRIDE { | 218 const std::string& encrypted_token_hex) OVERRIDE { |
314 if (!LoadSupplementalUserKey()) | 219 if (!LoadSupplementalUserKey()) |
315 return std::string(); | 220 return std::string(); |
316 return DecryptTokenWithKey(supplemental_user_key_.get(), | 221 return DecryptTokenWithKey(supplemental_user_key_.get(), |
317 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), | 222 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), |
318 encrypted_token_hex); | 223 encrypted_token_hex); |
319 } | 224 } |
320 | 225 |
321 // net::CertDatabase::Observer implementation. Observer added on UI thread. | 226 // net::CertDatabase::Observer implementation. Observer added on UI thread. |
322 virtual void OnCertTrustChanged(const net::X509Certificate* cert) OVERRIDE { | 227 virtual void OnCertTrustChanged(const net::X509Certificate* cert) OVERRIDE { |
323 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 228 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
324 << __FUNCTION__ << " should be called on UI thread."; | |
325 } | 229 } |
326 | 230 |
327 virtual void OnUserCertAdded(const net::X509Certificate* cert) OVERRIDE { | 231 virtual void OnUserCertAdded(const net::X509Certificate* cert) OVERRIDE { |
328 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 232 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
329 << __FUNCTION__ << " should be called on UI thread."; | |
330 // Only load certificates if we have completed an initial request. | 233 // Only load certificates if we have completed an initial request. |
331 if (certificates_loaded_) { | 234 if (certificates_loaded_) { |
332 BrowserThread::PostTask( | 235 BrowserThread::PostTask( |
333 BrowserThread::DB, FROM_HERE, | 236 BrowserThread::DB, FROM_HERE, |
334 base::Bind(&CertLibraryImpl::LoadCertificates, | 237 base::Bind(&CertLibraryImpl::LoadCertificates, |
335 base::Unretained(this))); | 238 base::Unretained(this))); |
336 } | 239 } |
337 } | 240 } |
338 | 241 |
339 virtual void OnUserCertRemoved(const net::X509Certificate* cert) OVERRIDE { | 242 virtual void OnUserCertRemoved(const net::X509Certificate* cert) OVERRIDE { |
340 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 243 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
341 << __FUNCTION__ << " should be called on UI thread."; | |
342 // Only load certificates if we have completed an initial request. | 244 // Only load certificates if we have completed an initial request. |
343 if (certificates_loaded_) { | 245 if (certificates_loaded_) { |
344 BrowserThread::PostTask( | 246 BrowserThread::PostTask( |
345 BrowserThread::DB, FROM_HERE, | 247 BrowserThread::DB, FROM_HERE, |
346 base::Bind(&CertLibraryImpl::LoadCertificates, | 248 base::Bind(&CertLibraryImpl::LoadCertificates, |
347 base::Unretained(this))); | 249 base::Unretained(this))); |
348 } | 250 } |
349 } | 251 } |
350 | 252 |
351 virtual const std::string& GetTpmTokenName() const OVERRIDE { | 253 virtual const std::string& GetTpmTokenName() const OVERRIDE { |
352 return tpm_token_name_; | 254 return tpm_token_name_; |
353 } | 255 } |
354 | 256 |
355 private: | 257 private: |
356 void LoadCertificates() { | 258 void LoadCertificates() { |
357 VLOG(1) << " Loading Certificates."; | 259 VLOG(1) << " Loading Certificates."; |
358 // Certificate fetch occurs on the DB thread. | 260 // Certificate fetch occurs on the DB thread. |
359 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)) | 261 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
360 << __FUNCTION__ << " should be called on DB thread."; | |
361 net::CertDatabase cert_db; | 262 net::CertDatabase cert_db; |
362 net::CertificateList* cert_list = new net::CertificateList(); | 263 net::CertificateList* cert_list = new net::CertificateList(); |
363 cert_db.ListCerts(cert_list); | 264 cert_db.ListCerts(cert_list); |
364 // Pass the list to the UI thread to safely update the local lists. | 265 // Pass the list to the UI thread to safely update the local lists. |
365 BrowserThread::PostTask( | 266 BrowserThread::PostTask( |
366 BrowserThread::UI, FROM_HERE, | 267 BrowserThread::UI, FROM_HERE, |
367 base::Bind(&CertLibraryImpl::UpdateCertificates, | 268 base::Bind(&CertLibraryImpl::UpdateCertificates, |
368 base::Unretained(this), cert_list)); | 269 base::Unretained(this), cert_list)); |
369 } | 270 } |
370 | 271 |
371 // Comparison functor for locale-sensitive sorting of certificates by name. | 272 // Comparison functor for locale-sensitive sorting of certificates by name. |
372 class CertNameComparator { | 273 class CertNameComparator { |
373 public: | 274 public: |
374 explicit CertNameComparator(icu::Collator* collator) | 275 explicit CertNameComparator(icu::Collator* collator) |
375 : collator_(collator) { } | 276 : collator_(collator) { } |
376 | 277 |
377 bool operator()(const scoped_refptr<net::X509Certificate>& lhs, | 278 bool operator()(const scoped_refptr<net::X509Certificate>& lhs, |
378 const scoped_refptr<net::X509Certificate>& rhs) const { | 279 const scoped_refptr<net::X509Certificate>& rhs) const { |
379 string16 lhs_name = GetDisplayString(lhs.get(), false); | 280 string16 lhs_name = GetDisplayString(lhs.get(), false); |
380 string16 rhs_name = GetDisplayString(rhs.get(), false); | 281 string16 rhs_name = GetDisplayString(rhs.get(), false); |
381 if (collator_ == NULL) | 282 if (collator_ == NULL) |
382 return lhs_name < rhs_name; | 283 return lhs_name < rhs_name; |
383 return l10n_util::CompareString16WithCollator( | 284 return l10n_util::CompareString16WithCollator( |
384 collator_, lhs_name, rhs_name) == UCOL_LESS; | 285 collator_, lhs_name, rhs_name) == UCOL_LESS; |
385 } | 286 } |
386 private: | 287 private: |
387 icu::Collator* collator_; | 288 icu::Collator* collator_; |
388 }; | 289 }; |
389 | 290 |
390 void RequestCertificatesTask() { | |
391 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | |
392 << __FUNCTION__ << " should be called on UI thread."; | |
393 // Reset the task to the initial state so is_null() returns true. | |
394 request_task_ = base::Closure(); | |
395 RequestCertificates(); | |
396 } | |
397 | |
398 void NotifyCertificatesLoaded(bool initial_load) { | 291 void NotifyCertificatesLoaded(bool initial_load) { |
399 observer_list_->Notify( | 292 observer_list_->Notify( |
400 &CertLibrary::Observer::OnCertificatesLoaded, initial_load); | 293 &CertLibrary::Observer::OnCertificatesLoaded, initial_load); |
401 } | 294 } |
402 | 295 |
403 // |cert_list| is allocated in LoadCertificates() and must be deleted here. | 296 // |cert_list| is allocated in LoadCertificates() and must be deleted here. |
404 void UpdateCertificates(net::CertificateList* cert_list) { | 297 void UpdateCertificates(net::CertificateList* cert_list) { |
405 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 298 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
406 << __FUNCTION__ << " should be called on UI thread."; | |
407 DCHECK(cert_list); | 299 DCHECK(cert_list); |
408 | 300 |
409 // Clear any existing certificates. | 301 // Clear any existing certificates. |
410 certs_.Clear(); | 302 certs_.Clear(); |
411 server_ca_certs_.Clear(); | 303 server_ca_certs_.Clear(); |
412 user_certs_.Clear(); | 304 user_certs_.Clear(); |
413 server_certs_.Clear(); | 305 server_certs_.Clear(); |
414 | 306 |
415 // Add certificates to the appropriate list. | 307 // Add certificates to the appropriate list. |
416 for (net::CertificateList::const_iterator iter = cert_list->begin(); | 308 for (net::CertificateList::const_iterator iter = cert_list->begin(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 } | 369 } |
478 if (!supplemental_user_key_.get()) { | 370 if (!supplemental_user_key_.get()) { |
479 supplemental_user_key_.reset(crypto::GetSupplementalUserKey()); | 371 supplemental_user_key_.reset(crypto::GetSupplementalUserKey()); |
480 } | 372 } |
481 return supplemental_user_key_.get() != NULL; | 373 return supplemental_user_key_.get() != NULL; |
482 } | 374 } |
483 | 375 |
484 // Call this to start the certificate list initialization process. | 376 // Call this to start the certificate list initialization process. |
485 // Must be called from the UI thread. | 377 // Must be called from the UI thread. |
486 void RequestCertificates() { | 378 void RequestCertificates() { |
487 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 379 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
488 << __FUNCTION__ << " should be called on UI thread."; | |
489 | 380 |
490 certificates_requested_ = true; | 381 certificates_requested_ = true; |
491 | 382 |
492 if (!UserManager::Get()->IsUserLoggedIn()) { | 383 if (!UserManager::Get()->IsUserLoggedIn()) { |
493 // If we are not logged in, we cannot load any certificates. | 384 // If we are not logged in, we cannot load any certificates. |
494 // Set 'loaded' to true for the UI, since we are not waiting on loading. | 385 // Set 'loaded' to true for the UI, since we are not waiting on loading. |
495 LOG(WARNING) << "Requesting certificates before login."; | 386 LOG(WARNING) << "Requesting certificates before login."; |
496 certificates_loaded_ = true; | 387 certificates_loaded_ = true; |
497 supplemental_user_key_.reset(NULL); | 388 supplemental_user_key_.reset(NULL); |
498 return; | 389 return; |
499 } | 390 } |
500 | 391 |
501 if (!user_logged_in_) { | 392 if (!user_logged_in_) { |
502 user_logged_in_ = true; | 393 user_logged_in_ = true; |
503 certificates_loaded_ = false; | 394 certificates_loaded_ = false; |
504 supplemental_user_key_.reset(NULL); | 395 supplemental_user_key_.reset(NULL); |
505 } | 396 } |
506 | 397 |
507 VLOG(1) << "Requesting Certificates."; | 398 VLOG(1) << "Requesting Certificates."; |
508 DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled( | 399 DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled( |
509 base::Bind(&CertLibraryImpl::RequestCertificatesInternal, | 400 base::Bind(&CertLibraryImpl::OnTpmIsEnabled, |
510 weak_ptr_factory_.GetWeakPtr())); | 401 weak_ptr_factory_.GetWeakPtr())); |
511 } | 402 } |
512 | 403 |
513 // This method is used to implement RequestCertificates. | 404 // This method is used to implement RequestCertificates. |
514 void RequestCertificatesInternal(DBusMethodCallStatus call_status, | 405 void OnTpmIsEnabled(DBusMethodCallStatus call_status, bool tpm_is_enabled) { |
515 bool tpm_is_enabled) { | 406 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
516 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | |
517 << __FUNCTION__ << " should be called on UI thread."; | |
518 if (call_status != DBUS_METHOD_CALL_SUCCESS || !tpm_is_enabled) { | 407 if (call_status != DBUS_METHOD_CALL_SUCCESS || !tpm_is_enabled) { |
519 // TPM is not enabled, so proceed with empty tpm token name. | 408 // TPM is not enabled, so proceed with empty tpm token name. |
520 VLOG(1) << "TPM not available."; | 409 VLOG(1) << "TPM not available."; |
521 BrowserThread::PostTask( | 410 BrowserThread::PostTask( |
522 BrowserThread::DB, FROM_HERE, | 411 BrowserThread::DB, FROM_HERE, |
523 base::Bind(&CertLibraryImpl::LoadCertificates, | 412 base::Bind(&CertLibraryImpl::LoadCertificates, |
524 base::Unretained(this))); | 413 base::Unretained(this))); |
525 } else if (crypto::IsTPMTokenReady()) { | 414 } else if (tpm_token_ready_) { |
526 // Need TPM token name to filter user certificates. | 415 InitializeTPMToken(); |
527 const bool tpm_token_ready = true; | |
528 GetTPMTokenName(tpm_token_ready); | |
529 } else { | 416 } else { |
530 crypto::InitializeTPMToken( | 417 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady( |
531 base::Bind(&CertLibraryImpl::GetTPMTokenName, | 418 base::Bind(&CertLibraryImpl::OnPkcs11IsTpmTokenReady, |
532 weak_ptr_factory_.GetWeakPtr())); | 419 weak_ptr_factory_.GetWeakPtr())); |
533 } | 420 } |
534 } | 421 } |
535 | 422 |
536 // This method is used to implement RequestCertificates. | 423 // This method is used to implement RequestCertificates. |
537 void GetTPMTokenName(bool tpm_token_ready) { | 424 void OnPkcs11IsTpmTokenReady(DBusMethodCallStatus call_status, |
538 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 425 bool is_tpm_token_ready) { |
539 << __FUNCTION__ << " should be called on UI thread."; | 426 if (call_status != DBUS_METHOD_CALL_SUCCESS || !is_tpm_token_ready) { |
540 if (tpm_token_ready) { | 427 MaybeRetryRequestCertificates(); |
541 std::string unused_pin; | |
542 crypto::GetTPMTokenInfo(&tpm_token_name_, &unused_pin); | |
543 } else { | |
544 VLOG(1) << "TPM token not ready."; | |
545 if (request_task_.is_null()) { | |
546 // Cryptohome does not notify us when the token is ready, so call | |
547 // this again after a delay. | |
548 request_task_ = base::Bind(&CertLibraryImpl::RequestCertificatesTask, | |
549 weak_ptr_factory_.GetWeakPtr()); | |
550 BrowserThread::PostDelayedTask( | |
551 BrowserThread::UI, FROM_HERE, request_task_, | |
552 base::TimeDelta::FromMilliseconds(kRequestDelayMs)); | |
553 } | |
554 return; | 428 return; |
555 } | 429 } |
556 | 430 |
| 431 // Retrieve token_name_ and user_pin_ here since they will never change |
| 432 // and CryptohomeClient calls are not thread safe. |
| 433 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo( |
| 434 base::Bind(&CertLibraryImpl::OnPkcs11GetTpmTokenInfo, |
| 435 weak_ptr_factory_.GetWeakPtr())); |
| 436 } |
| 437 |
| 438 // This method is used to implement RequestCertificates. |
| 439 void OnPkcs11GetTpmTokenInfo(DBusMethodCallStatus call_status, |
| 440 const std::string& token_name, |
| 441 const std::string& user_pin) { |
| 442 if (call_status != DBUS_METHOD_CALL_SUCCESS) { |
| 443 MaybeRetryRequestCertificates(); |
| 444 return; |
| 445 } |
| 446 tpm_token_name_ = token_name; |
| 447 tpm_user_pin_ = user_pin; |
| 448 tpm_token_ready_ = true; |
| 449 |
| 450 InitializeTPMToken(); |
| 451 } |
| 452 |
| 453 // This method is used to implement RequestCertificates. |
| 454 void InitializeTPMToken() { |
| 455 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 456 if (!crypto::InitializeTPMToken(tpm_token_name_, tpm_user_pin_)) { |
| 457 MaybeRetryRequestCertificates(); |
| 458 return; |
| 459 } |
| 460 |
557 // tpm_token_name_ is set, load the certificates on the DB thread. | 461 // tpm_token_name_ is set, load the certificates on the DB thread. |
558 BrowserThread::PostTask( | 462 BrowserThread::PostTask( |
559 BrowserThread::DB, FROM_HERE, | 463 BrowserThread::DB, FROM_HERE, |
560 base::Bind(&CertLibraryImpl::LoadCertificates, base::Unretained(this))); | 464 base::Bind(&CertLibraryImpl::LoadCertificates, base::Unretained(this))); |
561 } | 465 } |
562 | 466 |
| 467 void MaybeRetryRequestCertificates() { |
| 468 if (!request_task_.is_null()) |
| 469 return; |
| 470 // Cryptohome does not notify us when the token is ready, so call |
| 471 // this again after a delay. |
| 472 request_task_ = base::Bind(&CertLibraryImpl::RequestCertificatesTask, |
| 473 weak_ptr_factory_.GetWeakPtr()); |
| 474 BrowserThread::PostDelayedTask( |
| 475 BrowserThread::UI, FROM_HERE, request_task_, |
| 476 base::TimeDelta::FromMilliseconds(kRequestDelayMs)); |
| 477 } |
| 478 |
| 479 void RequestCertificatesTask() { |
| 480 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 481 // Reset the task to the initial state so is_null() returns true. |
| 482 request_task_ = base::Closure(); |
| 483 RequestCertificates(); |
| 484 } |
| 485 |
563 // Observers. | 486 // Observers. |
564 const scoped_refptr<CertLibraryObserverList> observer_list_; | 487 const scoped_refptr<CertLibraryObserverList> observer_list_; |
565 | 488 |
566 // Active request task for re-requests while waiting for TPM init. | 489 // Active request task for re-requests while waiting for TPM init. |
567 base::Closure request_task_; | 490 base::Closure request_task_; |
568 | 491 |
| 492 bool tpm_token_ready_; |
| 493 |
569 // Cached TPM token name. | 494 // Cached TPM token name. |
570 std::string tpm_token_name_; | 495 std::string tpm_token_name_; |
571 | 496 |
| 497 // Cached TPM user pin. |
| 498 std::string tpm_user_pin_; |
| 499 |
572 // Supplemental user key. | 500 // Supplemental user key. |
573 scoped_ptr<crypto::SymmetricKey> supplemental_user_key_; | 501 scoped_ptr<crypto::SymmetricKey> supplemental_user_key_; |
574 | 502 |
575 // Local state. | 503 // Local state. |
576 bool user_logged_in_; | 504 bool user_logged_in_; |
577 bool certificates_requested_; | 505 bool certificates_requested_; |
578 bool certificates_loaded_; | 506 bool certificates_loaded_; |
579 // The key store for the current user has been loaded. This flag is needed to | 507 // The key store for the current user has been loaded. This flag is needed to |
580 // ensure that the key store will not be loaded twice in the policy recovery | 508 // ensure that the key store will not be loaded twice in the policy recovery |
581 // "safe-mode". | 509 // "safe-mode". |
(...skipping 17 matching lines...) Expand all Loading... |
599 | 527 |
600 // static | 528 // static |
601 CertLibrary* CertLibrary::GetImpl(bool stub) { | 529 CertLibrary* CertLibrary::GetImpl(bool stub) { |
602 // No libcros dependencies, so always return CertLibraryImpl() (no stub). | 530 // No libcros dependencies, so always return CertLibraryImpl() (no stub). |
603 return new CertLibraryImpl(); | 531 return new CertLibraryImpl(); |
604 } | 532 } |
605 | 533 |
606 ////////////////////////////////////////////////////////////////////////////// | 534 ////////////////////////////////////////////////////////////////////////////// |
607 | 535 |
608 net::X509Certificate* CertLibrary::CertList::GetCertificateAt(int index) const { | 536 net::X509Certificate* CertLibrary::CertList::GetCertificateAt(int index) const { |
609 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | 537 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
610 << __FUNCTION__ << " should be called on UI thread."; | |
611 DCHECK_GE(index, 0); | 538 DCHECK_GE(index, 0); |
612 DCHECK_LT(index, static_cast<int>(list_.size())); | 539 DCHECK_LT(index, static_cast<int>(list_.size())); |
613 return list_[index].get(); | 540 return list_[index].get(); |
614 } | 541 } |
615 | 542 |
616 string16 CertLibrary::CertList::GetDisplayStringAt(int index) const { | 543 string16 CertLibrary::CertList::GetDisplayStringAt(int index) const { |
617 net::X509Certificate* cert = GetCertificateAt(index); | 544 net::X509Certificate* cert = GetCertificateAt(index); |
618 bool hardware_backed = | 545 bool hardware_backed = |
619 !cert_library_->GetTpmTokenName().empty() && IsHardwareBackedAt(index); | 546 !cert_library_->GetTpmTokenName().empty() && IsHardwareBackedAt(index); |
620 return GetDisplayString(cert, hardware_backed); | 547 return GetDisplayString(cert, hardware_backed); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 net::X509Certificate* cert = GetCertificateAt(index); | 582 net::X509Certificate* cert = GetCertificateAt(index); |
656 net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); | 583 net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); |
657 std::string id = x509_certificate_model::GetPkcs11Id(cert_handle); | 584 std::string id = x509_certificate_model::GetPkcs11Id(cert_handle); |
658 if (id == pkcs11_id) | 585 if (id == pkcs11_id) |
659 return index; | 586 return index; |
660 } | 587 } |
661 return -1; // Not found. | 588 return -1; // Not found. |
662 } | 589 } |
663 | 590 |
664 } // chromeos | 591 } // chromeos |
OLD | NEW |