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 "crypto/nss_util.h" | 5 #include "crypto/nss_util.h" |
6 #include "crypto/nss_util_internal.h" | 6 #include "crypto/nss_util_internal.h" |
7 | 7 |
8 #include <nss.h> | 8 #include <nss.h> |
9 #include <pk11pub.h> | 9 #include <pk11pub.h> |
10 #include <plarena.h> | 10 #include <plarena.h> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 #include "base/threading/worker_pool.h" | 43 #include "base/threading/worker_pool.h" |
44 #include "build/build_config.h" | 44 #include "build/build_config.h" |
45 | 45 |
46 // USE_NSS means we use NSS for everything crypto-related. If USE_NSS is not | 46 // USE_NSS means we use NSS for everything crypto-related. If USE_NSS is not |
47 // defined, such as on Mac and Windows, we use NSS for SSL only -- we don't | 47 // defined, such as on Mac and Windows, we use NSS for SSL only -- we don't |
48 // use NSS for crypto or certificate verification, and we don't use the NSS | 48 // use NSS for crypto or certificate verification, and we don't use the NSS |
49 // certificate and key databases. | 49 // certificate and key databases. |
50 #if defined(USE_NSS) | 50 #if defined(USE_NSS) |
51 #include "base/synchronization/lock.h" | 51 #include "base/synchronization/lock.h" |
52 #include "crypto/nss_crypto_module_delegate.h" | 52 #include "crypto/nss_crypto_module_delegate.h" |
| 53 #include "crypto/scoped_test_nss_db.h" |
53 #endif // defined(USE_NSS) | 54 #endif // defined(USE_NSS) |
54 | 55 |
55 namespace crypto { | 56 namespace crypto { |
56 | 57 |
57 namespace { | 58 namespace { |
58 | 59 |
59 #if defined(OS_CHROMEOS) | 60 #if defined(OS_CHROMEOS) |
60 const char kUserNSSDatabaseName[] = "UserNSSDB"; | 61 const char kUserNSSDatabaseName[] = "UserNSSDB"; |
61 | 62 |
62 // Constants for loading the Chrome OS TPM-backed PKCS #11 library. | 63 // Constants for loading the Chrome OS TPM-backed PKCS #11 library. |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 PL_ArenaFinish(); | 192 PL_ArenaFinish(); |
192 PRStatus prstatus = PR_Cleanup(); | 193 PRStatus prstatus = PR_Cleanup(); |
193 if (prstatus != PR_SUCCESS) | 194 if (prstatus != PR_SUCCESS) |
194 LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?"; | 195 LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?"; |
195 } | 196 } |
196 }; | 197 }; |
197 | 198 |
198 base::LazyInstance<NSPRInitSingleton>::Leaky | 199 base::LazyInstance<NSPRInitSingleton>::Leaky |
199 g_nspr_singleton = LAZY_INSTANCE_INITIALIZER; | 200 g_nspr_singleton = LAZY_INSTANCE_INITIALIZER; |
200 | 201 |
201 // This is a LazyInstance so that it will be deleted automatically when the | |
202 // unittest exits. NSSInitSingleton is a LeakySingleton, so it would not be | |
203 // deleted if it were a regular member. | |
204 base::LazyInstance<base::ScopedTempDir> g_test_nss_db_dir = | |
205 LAZY_INSTANCE_INITIALIZER; | |
206 | |
207 // Force a crash with error info on NSS_NoDB_Init failure. | 202 // Force a crash with error info on NSS_NoDB_Init failure. |
208 void CrashOnNSSInitFailure() { | 203 void CrashOnNSSInitFailure() { |
209 int nss_error = PR_GetError(); | 204 int nss_error = PR_GetError(); |
210 int os_error = PR_GetOSError(); | 205 int os_error = PR_GetOSError(); |
211 base::debug::Alias(&nss_error); | 206 base::debug::Alias(&nss_error); |
212 base::debug::Alias(&os_error); | 207 base::debug::Alias(&os_error); |
213 LOG(ERROR) << "Error initializing NSS without a persistent database: " | 208 LOG(ERROR) << "Error initializing NSS without a persistent database: " |
214 << GetNSSErrorMessage(); | 209 << GetNSSErrorMessage(); |
215 LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error; | 210 LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error; |
216 } | 211 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 public: | 275 public: |
281 #if defined(OS_CHROMEOS) | 276 #if defined(OS_CHROMEOS) |
282 // Used with PostTaskAndReply to pass handles to worker thread and back. | 277 // Used with PostTaskAndReply to pass handles to worker thread and back. |
283 struct TPMModuleAndSlot { | 278 struct TPMModuleAndSlot { |
284 explicit TPMModuleAndSlot(SECMODModule* init_chaps_module) | 279 explicit TPMModuleAndSlot(SECMODModule* init_chaps_module) |
285 : chaps_module(init_chaps_module), tpm_slot(NULL) {} | 280 : chaps_module(init_chaps_module), tpm_slot(NULL) {} |
286 SECMODModule* chaps_module; | 281 SECMODModule* chaps_module; |
287 PK11SlotInfo* tpm_slot; | 282 PK11SlotInfo* tpm_slot; |
288 }; | 283 }; |
289 | 284 |
290 PK11SlotInfo* OpenPersistentNSSDBForPath(const std::string& db_name, | 285 ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name, |
291 const base::FilePath& path) { | 286 const base::FilePath& path) { |
292 DCHECK(thread_checker_.CalledOnValidThread()); | 287 DCHECK(thread_checker_.CalledOnValidThread()); |
293 // NSS is allowed to do IO on the current thread since dispatching | 288 // NSS is allowed to do IO on the current thread since dispatching |
294 // to a dedicated thread would still have the affect of blocking | 289 // to a dedicated thread would still have the affect of blocking |
295 // the current thread, due to NSS's internal locking requirements | 290 // the current thread, due to NSS's internal locking requirements |
296 base::ThreadRestrictions::ScopedAllowIO allow_io; | 291 base::ThreadRestrictions::ScopedAllowIO allow_io; |
297 | 292 |
298 base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb"); | 293 base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb"); |
299 if (!base::CreateDirectory(nssdb_path)) { | 294 if (!base::CreateDirectory(nssdb_path)) { |
300 LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory."; | 295 LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory."; |
301 return NULL; | 296 return ScopedPK11Slot(); |
302 } | 297 } |
303 return OpenUserDB(nssdb_path, db_name); | 298 return OpenUserDB(nssdb_path, db_name); |
304 } | 299 } |
305 | 300 |
306 void EnableTPMTokenForNSS() { | 301 void EnableTPMTokenForNSS() { |
307 DCHECK(thread_checker_.CalledOnValidThread()); | 302 DCHECK(thread_checker_.CalledOnValidThread()); |
308 | 303 |
309 // If this gets set, then we'll use the TPM for certs with | 304 // If this gets set, then we'll use the TPM for certs with |
310 // private keys, otherwise we'll fall back to the software | 305 // private keys, otherwise we'll fall back to the software |
311 // implementation. | 306 // implementation. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 | 381 |
387 void OnInitializedTPMTokenAndSystemSlot( | 382 void OnInitializedTPMTokenAndSystemSlot( |
388 const base::Callback<void(bool)>& callback, | 383 const base::Callback<void(bool)>& callback, |
389 scoped_ptr<TPMModuleAndSlot> tpm_args) { | 384 scoped_ptr<TPMModuleAndSlot> tpm_args) { |
390 DCHECK(thread_checker_.CalledOnValidThread()); | 385 DCHECK(thread_checker_.CalledOnValidThread()); |
391 DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module | 386 DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module |
392 << ", got tpm slot: " << !!tpm_args->tpm_slot; | 387 << ", got tpm slot: " << !!tpm_args->tpm_slot; |
393 | 388 |
394 chaps_module_ = tpm_args->chaps_module; | 389 chaps_module_ = tpm_args->chaps_module; |
395 tpm_slot_ = tpm_args->tpm_slot; | 390 tpm_slot_ = tpm_args->tpm_slot; |
396 if (!chaps_module_ && test_slot_) { | 391 if (!chaps_module_ && test_system_slot_) { |
397 // chromeos_unittests try to test the TPM initialization process. If we | 392 // chromeos_unittests try to test the TPM initialization process. If we |
398 // have a test DB open, pretend that it is the TPM slot. | 393 // have a test DB open, pretend that it is the TPM slot. |
399 tpm_slot_ = PK11_ReferenceSlot(test_slot_); | 394 tpm_slot_ = PK11_ReferenceSlot(test_system_slot_.get()); |
400 } | 395 } |
401 initializing_tpm_token_ = false; | 396 initializing_tpm_token_ = false; |
402 | 397 |
403 if (tpm_slot_) { | 398 if (tpm_slot_) { |
404 TPMReadyCallbackList callback_list; | 399 TPMReadyCallbackList callback_list; |
405 callback_list.swap(tpm_ready_callback_list_); | 400 callback_list.swap(tpm_ready_callback_list_); |
406 for (TPMReadyCallbackList::iterator i = callback_list.begin(); | 401 for (TPMReadyCallbackList::iterator i = callback_list.begin(); |
407 i != callback_list.end(); | 402 i != callback_list.end(); |
408 ++i) { | 403 ++i) { |
409 (*i).Run(); | 404 (*i).Run(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 const std::string& email, | 451 const std::string& email, |
457 const std::string& username_hash, | 452 const std::string& username_hash, |
458 const base::FilePath& path) { | 453 const base::FilePath& path) { |
459 DCHECK(thread_checker_.CalledOnValidThread()); | 454 DCHECK(thread_checker_.CalledOnValidThread()); |
460 if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) { | 455 if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) { |
461 // This user already exists in our mapping. | 456 // This user already exists in our mapping. |
462 DVLOG(2) << username_hash << " already initialized."; | 457 DVLOG(2) << username_hash << " already initialized."; |
463 return false; | 458 return false; |
464 } | 459 } |
465 | 460 |
466 // If test slot is set, slot getter methods will short circuit | |
467 // checking |chromeos_user_map_|, so there is nothing left to be | |
468 // initialized. | |
469 if (test_slot_) | |
470 return false; | |
471 | |
472 DVLOG(2) << "Opening NSS DB " << path.value(); | 461 DVLOG(2) << "Opening NSS DB " << path.value(); |
473 std::string db_name = base::StringPrintf( | 462 std::string db_name = base::StringPrintf( |
474 "%s %s", kUserNSSDatabaseName, username_hash.c_str()); | 463 "%s %s", kUserNSSDatabaseName, username_hash.c_str()); |
475 ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path)); | 464 ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path)); |
476 chromeos_user_map_[username_hash] = | 465 chromeos_user_map_[username_hash] = |
477 new ChromeOSUserData(public_slot.Pass()); | 466 new ChromeOSUserData(public_slot.Pass()); |
478 return true; | 467 return true; |
479 } | 468 } |
480 | 469 |
481 bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { | 470 bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 | 533 |
545 ScopedPK11Slot GetPublicSlotForChromeOSUser( | 534 ScopedPK11Slot GetPublicSlotForChromeOSUser( |
546 const std::string& username_hash) { | 535 const std::string& username_hash) { |
547 DCHECK(thread_checker_.CalledOnValidThread()); | 536 DCHECK(thread_checker_.CalledOnValidThread()); |
548 | 537 |
549 if (username_hash.empty()) { | 538 if (username_hash.empty()) { |
550 DVLOG(2) << "empty username_hash"; | 539 DVLOG(2) << "empty username_hash"; |
551 return ScopedPK11Slot(); | 540 return ScopedPK11Slot(); |
552 } | 541 } |
553 | 542 |
554 if (test_slot_) { | |
555 DVLOG(2) << "returning test_slot_ for " << username_hash; | |
556 return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_)); | |
557 } | |
558 | |
559 if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) { | 543 if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) { |
560 LOG(ERROR) << username_hash << " not initialized."; | 544 LOG(ERROR) << username_hash << " not initialized."; |
561 return ScopedPK11Slot(); | 545 return ScopedPK11Slot(); |
562 } | 546 } |
563 return chromeos_user_map_[username_hash]->GetPublicSlot(); | 547 return chromeos_user_map_[username_hash]->GetPublicSlot(); |
564 } | 548 } |
565 | 549 |
566 ScopedPK11Slot GetPrivateSlotForChromeOSUser( | 550 ScopedPK11Slot GetPrivateSlotForChromeOSUser( |
567 const std::string& username_hash, | 551 const std::string& username_hash, |
568 const base::Callback<void(ScopedPK11Slot)>& callback) { | 552 const base::Callback<void(ScopedPK11Slot)>& callback) { |
569 DCHECK(thread_checker_.CalledOnValidThread()); | 553 DCHECK(thread_checker_.CalledOnValidThread()); |
570 | 554 |
571 if (username_hash.empty()) { | 555 if (username_hash.empty()) { |
572 DVLOG(2) << "empty username_hash"; | 556 DVLOG(2) << "empty username_hash"; |
573 if (!callback.is_null()) { | 557 if (!callback.is_null()) { |
574 base::MessageLoop::current()->PostTask( | 558 base::MessageLoop::current()->PostTask( |
575 FROM_HERE, base::Bind(callback, base::Passed(ScopedPK11Slot()))); | 559 FROM_HERE, base::Bind(callback, base::Passed(ScopedPK11Slot()))); |
576 } | 560 } |
577 return ScopedPK11Slot(); | 561 return ScopedPK11Slot(); |
578 } | 562 } |
579 | 563 |
580 DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); | 564 DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); |
581 | 565 |
582 if (test_slot_) { | |
583 DVLOG(2) << "returning test_slot_ for " << username_hash; | |
584 return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_)); | |
585 } | |
586 | |
587 return chromeos_user_map_[username_hash]->GetPrivateSlot(callback); | 566 return chromeos_user_map_[username_hash]->GetPrivateSlot(callback); |
588 } | 567 } |
589 | 568 |
590 void CloseTestChromeOSUser(const std::string& username_hash) { | 569 void CloseTestChromeOSUser(const std::string& username_hash) { |
591 DCHECK(thread_checker_.CalledOnValidThread()); | 570 DCHECK(thread_checker_.CalledOnValidThread()); |
592 ChromeOSUserMap::iterator i = chromeos_user_map_.find(username_hash); | 571 ChromeOSUserMap::iterator i = chromeos_user_map_.find(username_hash); |
593 DCHECK(i != chromeos_user_map_.end()); | 572 DCHECK(i != chromeos_user_map_.end()); |
594 delete i->second; | 573 delete i->second; |
595 chromeos_user_map_.erase(i); | 574 chromeos_user_map_.erase(i); |
596 } | 575 } |
| 576 |
| 577 void SetTestSystemKeySlot(ScopedPK11Slot slot) { |
| 578 test_system_slot_ = slot.Pass(); |
| 579 } |
597 #endif // defined(OS_CHROMEOS) | 580 #endif // defined(OS_CHROMEOS) |
598 | 581 |
599 | 582 #if !defined(OS_CHROMEOS) |
600 bool OpenTestNSSDB() { | |
601 DCHECK(thread_checker_.CalledOnValidThread()); | |
602 // NSS is allowed to do IO on the current thread since dispatching | |
603 // to a dedicated thread would still have the affect of blocking | |
604 // the current thread, due to NSS's internal locking requirements | |
605 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
606 | |
607 if (test_slot_) | |
608 return true; | |
609 if (!g_test_nss_db_dir.Get().CreateUniqueTempDir()) | |
610 return false; | |
611 test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName); | |
612 return !!test_slot_; | |
613 } | |
614 | |
615 void CloseTestNSSDB() { | |
616 DCHECK(thread_checker_.CalledOnValidThread()); | |
617 // NSS is allowed to do IO on the current thread since dispatching | |
618 // to a dedicated thread would still have the affect of blocking | |
619 // the current thread, due to NSS's internal locking requirements | |
620 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
621 | |
622 if (!test_slot_) | |
623 return; | |
624 SECStatus status = SECMOD_CloseUserDB(test_slot_); | |
625 if (status != SECSuccess) | |
626 PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); | |
627 PK11_FreeSlot(test_slot_); | |
628 test_slot_ = NULL; | |
629 ignore_result(g_test_nss_db_dir.Get().Delete()); | |
630 } | |
631 | |
632 PK11SlotInfo* GetPersistentNSSKeySlot() { | 583 PK11SlotInfo* GetPersistentNSSKeySlot() { |
633 // TODO(mattm): Change to DCHECK when callers have been fixed. | 584 // TODO(mattm): Change to DCHECK when callers have been fixed. |
634 if (!thread_checker_.CalledOnValidThread()) { | 585 if (!thread_checker_.CalledOnValidThread()) { |
635 DVLOG(1) << "Called on wrong thread.\n" | 586 DVLOG(1) << "Called on wrong thread.\n" |
636 << base::debug::StackTrace().ToString(); | 587 << base::debug::StackTrace().ToString(); |
637 } | 588 } |
638 | 589 |
639 if (test_slot_) | |
640 return PK11_ReferenceSlot(test_slot_); | |
641 return PK11_GetInternalKeySlot(); | 590 return PK11_GetInternalKeySlot(); |
642 } | 591 } |
| 592 #endif |
643 | 593 |
644 #if defined(OS_CHROMEOS) | 594 #if defined(OS_CHROMEOS) |
645 PK11SlotInfo* GetSystemNSSKeySlot() { | 595 PK11SlotInfo* GetSystemNSSKeySlot() { |
646 DCHECK(thread_checker_.CalledOnValidThread()); | 596 DCHECK(thread_checker_.CalledOnValidThread()); |
647 | 597 |
648 if (test_slot_) | 598 if (test_system_slot_) |
649 return PK11_ReferenceSlot(test_slot_); | 599 return PK11_ReferenceSlot(test_system_slot_.get()); |
650 | 600 |
651 // TODO(mattm): chromeos::TPMTokenloader always calls | 601 // TODO(mattm): chromeos::TPMTokenloader always calls |
652 // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is | 602 // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is |
653 // disabled, tpm_slot_ will be the first user's slot instead. Can that be | 603 // disabled, tpm_slot_ will be the first user's slot instead. Can that be |
654 // detected and return NULL instead? | 604 // detected and return NULL instead? |
655 if (tpm_token_enabled_for_nss_ && IsTPMTokenReady(base::Closure())) | 605 if (tpm_token_enabled_for_nss_ && IsTPMTokenReady(base::Closure())) |
656 return PK11_ReferenceSlot(tpm_slot_); | 606 return PK11_ReferenceSlot(tpm_slot_); |
657 // If we were supposed to get the hardware token, but were | 607 // If we were supposed to get the hardware token, but were |
658 // unable to, return NULL rather than fall back to sofware. | 608 // unable to, return NULL rather than fall back to sofware. |
659 return NULL; | 609 return NULL; |
(...skipping 12 matching lines...) Expand all Loading... |
672 force_nodb_init_ = true; | 622 force_nodb_init_ = true; |
673 } | 623 } |
674 | 624 |
675 private: | 625 private: |
676 friend struct base::DefaultLazyInstanceTraits<NSSInitSingleton>; | 626 friend struct base::DefaultLazyInstanceTraits<NSSInitSingleton>; |
677 | 627 |
678 NSSInitSingleton() | 628 NSSInitSingleton() |
679 : tpm_token_enabled_for_nss_(false), | 629 : tpm_token_enabled_for_nss_(false), |
680 initializing_tpm_token_(false), | 630 initializing_tpm_token_(false), |
681 chaps_module_(NULL), | 631 chaps_module_(NULL), |
682 test_slot_(NULL), | |
683 tpm_slot_(NULL), | 632 tpm_slot_(NULL), |
684 root_(NULL) { | 633 root_(NULL) { |
685 base::TimeTicks start_time = base::TimeTicks::Now(); | 634 base::TimeTicks start_time = base::TimeTicks::Now(); |
686 | 635 |
687 // It's safe to construct on any thread, since LazyInstance will prevent any | 636 // It's safe to construct on any thread, since LazyInstance will prevent any |
688 // other threads from accessing until the constructor is done. | 637 // other threads from accessing until the constructor is done. |
689 thread_checker_.DetachFromThread(); | 638 thread_checker_.DetachFromThread(); |
690 | 639 |
691 DisableAESNIIfNeeded(); | 640 DisableAESNIIfNeeded(); |
692 | 641 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 // prevent non-joinable threads from using NSS after it's already been shut | 743 // prevent non-joinable threads from using NSS after it's already been shut |
795 // down. | 744 // down. |
796 ~NSSInitSingleton() { | 745 ~NSSInitSingleton() { |
797 #if defined(OS_CHROMEOS) | 746 #if defined(OS_CHROMEOS) |
798 STLDeleteValues(&chromeos_user_map_); | 747 STLDeleteValues(&chromeos_user_map_); |
799 #endif | 748 #endif |
800 if (tpm_slot_) { | 749 if (tpm_slot_) { |
801 PK11_FreeSlot(tpm_slot_); | 750 PK11_FreeSlot(tpm_slot_); |
802 tpm_slot_ = NULL; | 751 tpm_slot_ = NULL; |
803 } | 752 } |
804 CloseTestNSSDB(); | |
805 if (root_) { | 753 if (root_) { |
806 SECMOD_UnloadUserModule(root_); | 754 SECMOD_UnloadUserModule(root_); |
807 SECMOD_DestroyModule(root_); | 755 SECMOD_DestroyModule(root_); |
808 root_ = NULL; | 756 root_ = NULL; |
809 } | 757 } |
810 if (chaps_module_) { | 758 if (chaps_module_) { |
811 SECMOD_UnloadUserModule(chaps_module_); | 759 SECMOD_UnloadUserModule(chaps_module_); |
812 SECMOD_DestroyModule(chaps_module_); | 760 SECMOD_DestroyModule(chaps_module_); |
813 chaps_module_ = NULL; | 761 chaps_module_ = NULL; |
814 } | 762 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 if (!module->loaded) { | 804 if (!module->loaded) { |
857 LOG(ERROR) << "After loading " << name << ", loaded==false: " | 805 LOG(ERROR) << "After loading " << name << ", loaded==false: " |
858 << GetNSSErrorMessage(); | 806 << GetNSSErrorMessage(); |
859 SECMOD_DestroyModule(module); | 807 SECMOD_DestroyModule(module); |
860 return NULL; | 808 return NULL; |
861 } | 809 } |
862 return module; | 810 return module; |
863 } | 811 } |
864 #endif | 812 #endif |
865 | 813 |
866 static PK11SlotInfo* OpenUserDB(const base::FilePath& path, | |
867 const std::string& description) { | |
868 const std::string modspec = | |
869 base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", | |
870 path.value().c_str(), | |
871 description.c_str()); | |
872 PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); | |
873 if (db_slot) { | |
874 if (PK11_NeedUserInit(db_slot)) | |
875 PK11_InitPin(db_slot, NULL, NULL); | |
876 } | |
877 else { | |
878 LOG(ERROR) << "Error opening persistent database (" << modspec | |
879 << "): " << GetNSSErrorMessage(); | |
880 } | |
881 return db_slot; | |
882 } | |
883 | |
884 static void DisableAESNIIfNeeded() { | 814 static void DisableAESNIIfNeeded() { |
885 if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) { | 815 if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) { |
886 // Some versions of NSS have a bug that causes AVX instructions to be | 816 // Some versions of NSS have a bug that causes AVX instructions to be |
887 // used without testing whether XSAVE is enabled by the operating system. | 817 // used without testing whether XSAVE is enabled by the operating system. |
888 // In order to work around this, we disable AES-NI in NSS when we find | 818 // In order to work around this, we disable AES-NI in NSS when we find |
889 // that |has_avx()| is false (which includes the XSAVE test). See | 819 // that |has_avx()| is false (which includes the XSAVE test). See |
890 // https://bugzilla.mozilla.org/show_bug.cgi?id=940794 | 820 // https://bugzilla.mozilla.org/show_bug.cgi?id=940794 |
891 base::CPU cpu; | 821 base::CPU cpu; |
892 | 822 |
893 if (cpu.has_avx_hardware() && !cpu.has_avx()) { | 823 if (cpu.has_avx_hardware() && !cpu.has_avx()) { |
894 base::Environment::Create()->SetVar("NSS_DISABLE_HW_AES", "1"); | 824 base::Environment::Create()->SetVar("NSS_DISABLE_HW_AES", "1"); |
895 } | 825 } |
896 } | 826 } |
897 } | 827 } |
898 | 828 |
899 // If this is set to true NSS is forced to be initialized without a DB. | 829 // If this is set to true NSS is forced to be initialized without a DB. |
900 static bool force_nodb_init_; | 830 static bool force_nodb_init_; |
901 | 831 |
902 bool tpm_token_enabled_for_nss_; | 832 bool tpm_token_enabled_for_nss_; |
903 bool initializing_tpm_token_; | 833 bool initializing_tpm_token_; |
904 typedef std::vector<base::Closure> TPMReadyCallbackList; | 834 typedef std::vector<base::Closure> TPMReadyCallbackList; |
905 TPMReadyCallbackList tpm_ready_callback_list_; | 835 TPMReadyCallbackList tpm_ready_callback_list_; |
906 SECMODModule* chaps_module_; | 836 SECMODModule* chaps_module_; |
907 PK11SlotInfo* test_slot_; | |
908 PK11SlotInfo* tpm_slot_; | 837 PK11SlotInfo* tpm_slot_; |
909 SECMODModule* root_; | 838 SECMODModule* root_; |
910 #if defined(OS_CHROMEOS) | 839 #if defined(OS_CHROMEOS) |
911 typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; | 840 typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; |
912 ChromeOSUserMap chromeos_user_map_; | 841 ChromeOSUserMap chromeos_user_map_; |
| 842 ScopedPK11Slot test_system_slot_; |
913 #endif | 843 #endif |
914 #if defined(USE_NSS) | 844 #if defined(USE_NSS) |
915 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 | 845 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 |
916 // is fixed, we will no longer need the lock. | 846 // is fixed, we will no longer need the lock. |
917 base::Lock write_lock_; | 847 base::Lock write_lock_; |
918 #endif // defined(USE_NSS) | 848 #endif // defined(USE_NSS) |
919 | 849 |
920 base::ThreadChecker thread_checker_; | 850 base::ThreadChecker thread_checker_; |
921 }; | 851 }; |
922 | 852 |
923 // static | 853 // static |
924 bool NSSInitSingleton::force_nodb_init_ = false; | 854 bool NSSInitSingleton::force_nodb_init_ = false; |
925 | 855 |
926 base::LazyInstance<NSSInitSingleton>::Leaky | 856 base::LazyInstance<NSSInitSingleton>::Leaky |
927 g_nss_singleton = LAZY_INSTANCE_INITIALIZER; | 857 g_nss_singleton = LAZY_INSTANCE_INITIALIZER; |
928 } // namespace | 858 } // namespace |
929 | 859 |
930 const char kTestTPMTokenName[] = "Test DB"; | 860 #if defined(USE_NSS) |
| 861 ScopedPK11Slot OpenUserDB(const base::FilePath& path, |
| 862 const std::string& description) { |
| 863 const std::string modspec = |
| 864 base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", |
| 865 path.value().c_str(), |
| 866 description.c_str()); |
| 867 PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); |
| 868 if (db_slot) { |
| 869 if (PK11_NeedUserInit(db_slot)) |
| 870 PK11_InitPin(db_slot, NULL, NULL); |
| 871 } else { |
| 872 LOG(ERROR) << "Error opening persistent database (" << modspec |
| 873 << "): " << GetNSSErrorMessage(); |
| 874 } |
| 875 return ScopedPK11Slot(db_slot); |
| 876 } |
931 | 877 |
932 #if defined(USE_NSS) | |
933 void EarlySetupForNSSInit() { | 878 void EarlySetupForNSSInit() { |
934 base::FilePath database_dir = GetInitialConfigDirectory(); | 879 base::FilePath database_dir = GetInitialConfigDirectory(); |
935 if (!database_dir.empty()) | 880 if (!database_dir.empty()) |
936 UseLocalCacheOfNSSDatabaseIfNFS(database_dir); | 881 UseLocalCacheOfNSSDatabaseIfNFS(database_dir); |
937 } | 882 } |
938 #endif | 883 #endif |
939 | 884 |
940 void EnsureNSPRInit() { | 885 void EnsureNSPRInit() { |
941 g_nspr_singleton.Get(); | 886 g_nspr_singleton.Get(); |
942 } | 887 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 LOG(ERROR) << "Failed to load NSS libraries."; | 966 LOG(ERROR) << "Failed to load NSS libraries."; |
1022 } | 967 } |
1023 #endif // defined(USE_NSS) | 968 #endif // defined(USE_NSS) |
1024 } | 969 } |
1025 | 970 |
1026 bool CheckNSSVersion(const char* version) { | 971 bool CheckNSSVersion(const char* version) { |
1027 return !!NSS_VersionCheck(version); | 972 return !!NSS_VersionCheck(version); |
1028 } | 973 } |
1029 | 974 |
1030 #if defined(USE_NSS) | 975 #if defined(USE_NSS) |
1031 ScopedTestNSSDB::ScopedTestNSSDB() | 976 #if defined(OS_CHROMEOS) |
1032 : is_open_(g_nss_singleton.Get().OpenTestNSSDB()) { | 977 ScopedTestSystemNSSKeySlot::ScopedTestSystemNSSKeySlot() |
| 978 : test_db_(new ScopedTestNSSDB) { |
| 979 if (!test_db_->is_open()) |
| 980 return; |
| 981 g_nss_singleton.Get().SetTestSystemKeySlot( |
| 982 ScopedPK11Slot(PK11_ReferenceSlot(test_db_->slot()))); |
1033 } | 983 } |
1034 | 984 |
1035 ScopedTestNSSDB::~ScopedTestNSSDB() { | 985 ScopedTestSystemNSSKeySlot::~ScopedTestSystemNSSKeySlot() { |
1036 // Don't close when NSS is < 3.15.1, because it would require an additional | 986 g_nss_singleton.Get().SetTestSystemKeySlot(ScopedPK11Slot()); |
1037 // sleep for 1 second after closing the database, due to | |
1038 // http://bugzil.la/875601. | |
1039 if (NSS_VersionCheck("3.15.1")) { | |
1040 g_nss_singleton.Get().CloseTestNSSDB(); | |
1041 } | |
1042 } | 987 } |
1043 | 988 |
| 989 bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const { |
| 990 return test_db_->is_open(); |
| 991 } |
| 992 #endif // defined(OS_CHROMEOS) |
| 993 |
1044 base::Lock* GetNSSWriteLock() { | 994 base::Lock* GetNSSWriteLock() { |
1045 return g_nss_singleton.Get().write_lock(); | 995 return g_nss_singleton.Get().write_lock(); |
1046 } | 996 } |
1047 | 997 |
1048 AutoNSSWriteLock::AutoNSSWriteLock() : lock_(GetNSSWriteLock()) { | 998 AutoNSSWriteLock::AutoNSSWriteLock() : lock_(GetNSSWriteLock()) { |
1049 // May be NULL if the lock is not needed in our version of NSS. | 999 // May be NULL if the lock is not needed in our version of NSS. |
1050 if (lock_) | 1000 if (lock_) |
1051 lock_->Acquire(); | 1001 lock_->Acquire(); |
1052 } | 1002 } |
1053 | 1003 |
1054 AutoNSSWriteLock::~AutoNSSWriteLock() { | 1004 AutoNSSWriteLock::~AutoNSSWriteLock() { |
1055 if (lock_) { | 1005 if (lock_) { |
1056 lock_->AssertAcquired(); | 1006 lock_->AssertAcquired(); |
1057 lock_->Release(); | 1007 lock_->Release(); |
1058 } | 1008 } |
1059 } | 1009 } |
1060 | 1010 |
1061 AutoSECMODListReadLock::AutoSECMODListReadLock() | 1011 AutoSECMODListReadLock::AutoSECMODListReadLock() |
1062 : lock_(SECMOD_GetDefaultModuleListLock()) { | 1012 : lock_(SECMOD_GetDefaultModuleListLock()) { |
1063 SECMOD_GetReadLock(lock_); | 1013 SECMOD_GetReadLock(lock_); |
1064 } | 1014 } |
1065 | 1015 |
1066 AutoSECMODListReadLock::~AutoSECMODListReadLock() { | 1016 AutoSECMODListReadLock::~AutoSECMODListReadLock() { |
1067 SECMOD_ReleaseReadLock(lock_); | 1017 SECMOD_ReleaseReadLock(lock_); |
1068 } | 1018 } |
1069 | |
1070 #endif // defined(USE_NSS) | 1019 #endif // defined(USE_NSS) |
1071 | 1020 |
1072 #if defined(OS_CHROMEOS) | 1021 #if defined(OS_CHROMEOS) |
1073 PK11SlotInfo* GetSystemNSSKeySlot() { | 1022 PK11SlotInfo* GetSystemNSSKeySlot() { |
1074 return g_nss_singleton.Get().GetSystemNSSKeySlot(); | 1023 return g_nss_singleton.Get().GetSystemNSSKeySlot(); |
1075 } | 1024 } |
1076 | 1025 |
1077 void EnableTPMTokenForNSS() { | 1026 void EnableTPMTokenForNSS() { |
1078 g_nss_singleton.Get().EnableTPMTokenForNSS(); | 1027 g_nss_singleton.Get().EnableTPMTokenForNSS(); |
1079 } | 1028 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 | 1106 |
1158 base::Time PRTimeToBaseTime(PRTime prtime) { | 1107 base::Time PRTimeToBaseTime(PRTime prtime) { |
1159 return base::Time::FromInternalValue( | 1108 return base::Time::FromInternalValue( |
1160 prtime + base::Time::UnixEpoch().ToInternalValue()); | 1109 prtime + base::Time::UnixEpoch().ToInternalValue()); |
1161 } | 1110 } |
1162 | 1111 |
1163 PRTime BaseTimeToPRTime(base::Time time) { | 1112 PRTime BaseTimeToPRTime(base::Time time) { |
1164 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); | 1113 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); |
1165 } | 1114 } |
1166 | 1115 |
| 1116 #if !defined(OS_CHROMEOS) |
1167 PK11SlotInfo* GetPersistentNSSKeySlot() { | 1117 PK11SlotInfo* GetPersistentNSSKeySlot() { |
1168 return g_nss_singleton.Get().GetPersistentNSSKeySlot(); | 1118 return g_nss_singleton.Get().GetPersistentNSSKeySlot(); |
1169 } | 1119 } |
| 1120 #endif |
1170 | 1121 |
1171 } // namespace crypto | 1122 } // namespace crypto |
OLD | NEW |