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