Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: crypto/nss_util.cc

Issue 401623006: Extract ScopedTestNSSDB from nss_util. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added a DCHECK to SetTestSystemKeySlot. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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 OpenSoftwareNSSDB(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.
312 tpm_token_enabled_for_nss_ = true; 307 tpm_token_enabled_for_nss_ = true;
313 } 308 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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 CloseChromeOSUserForTesting(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 // Ensure that a previous value of test_system_slot_ is not overwritten.
579 // Unsetting, i.e. setting a NULL, however is allowed.
580 DCHECK(!slot || !test_system_slot_);
581 test_system_slot_ = slot.Pass();
582 }
597 #endif // defined(OS_CHROMEOS) 583 #endif // defined(OS_CHROMEOS)
598 584
599 585 #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() { 586 PK11SlotInfo* GetPersistentNSSKeySlot() {
633 // TODO(mattm): Change to DCHECK when callers have been fixed. 587 // TODO(mattm): Change to DCHECK when callers have been fixed.
634 if (!thread_checker_.CalledOnValidThread()) { 588 if (!thread_checker_.CalledOnValidThread()) {
635 DVLOG(1) << "Called on wrong thread.\n" 589 DVLOG(1) << "Called on wrong thread.\n"
636 << base::debug::StackTrace().ToString(); 590 << base::debug::StackTrace().ToString();
637 } 591 }
638 592
639 if (test_slot_)
640 return PK11_ReferenceSlot(test_slot_);
641 return PK11_GetInternalKeySlot(); 593 return PK11_GetInternalKeySlot();
642 } 594 }
595 #endif
643 596
644 #if defined(OS_CHROMEOS) 597 #if defined(OS_CHROMEOS)
645 PK11SlotInfo* GetSystemNSSKeySlot() { 598 PK11SlotInfo* GetSystemNSSKeySlot() {
646 DCHECK(thread_checker_.CalledOnValidThread()); 599 DCHECK(thread_checker_.CalledOnValidThread());
647 600
648 if (test_slot_)
649 return PK11_ReferenceSlot(test_slot_);
650
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;
660 } 610 }
(...skipping 11 matching lines...) Expand all
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
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
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 } else {
877 LOG(ERROR) << "Error opening persistent database (" << modspec
878 << "): " << GetNSSErrorMessage();
879 }
880 return db_slot;
881 }
882
883 static void DisableAESNIIfNeeded() { 814 static void DisableAESNIIfNeeded() {
884 if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) { 815 if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) {
885 // 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
886 // used without testing whether XSAVE is enabled by the operating system. 817 // 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 818 // 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 819 // that |has_avx()| is false (which includes the XSAVE test). See
889 // https://bugzilla.mozilla.org/show_bug.cgi?id=940794 820 // https://bugzilla.mozilla.org/show_bug.cgi?id=940794
890 base::CPU cpu; 821 base::CPU cpu;
891 822
892 if (cpu.has_avx_hardware() && !cpu.has_avx()) { 823 if (cpu.has_avx_hardware() && !cpu.has_avx()) {
893 base::Environment::Create()->SetVar("NSS_DISABLE_HW_AES", "1"); 824 base::Environment::Create()->SetVar("NSS_DISABLE_HW_AES", "1");
894 } 825 }
895 } 826 }
896 } 827 }
897 828
898 // 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.
899 static bool force_nodb_init_; 830 static bool force_nodb_init_;
900 831
901 bool tpm_token_enabled_for_nss_; 832 bool tpm_token_enabled_for_nss_;
902 bool initializing_tpm_token_; 833 bool initializing_tpm_token_;
903 typedef std::vector<base::Closure> TPMReadyCallbackList; 834 typedef std::vector<base::Closure> TPMReadyCallbackList;
904 TPMReadyCallbackList tpm_ready_callback_list_; 835 TPMReadyCallbackList tpm_ready_callback_list_;
905 SECMODModule* chaps_module_; 836 SECMODModule* chaps_module_;
906 PK11SlotInfo* test_slot_;
907 PK11SlotInfo* tpm_slot_; 837 PK11SlotInfo* tpm_slot_;
908 SECMODModule* root_; 838 SECMODModule* root_;
909 #if defined(OS_CHROMEOS) 839 #if defined(OS_CHROMEOS)
910 typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; 840 typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap;
911 ChromeOSUserMap chromeos_user_map_; 841 ChromeOSUserMap chromeos_user_map_;
842 ScopedPK11Slot test_system_slot_;
912 #endif 843 #endif
913 #if defined(USE_NSS) 844 #if defined(USE_NSS)
914 // 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
915 // is fixed, we will no longer need the lock. 846 // is fixed, we will no longer need the lock.
916 base::Lock write_lock_; 847 base::Lock write_lock_;
917 #endif // defined(USE_NSS) 848 #endif // defined(USE_NSS)
918 849
919 base::ThreadChecker thread_checker_; 850 base::ThreadChecker thread_checker_;
920 }; 851 };
921 852
922 // static 853 // static
923 bool NSSInitSingleton::force_nodb_init_ = false; 854 bool NSSInitSingleton::force_nodb_init_ = false;
924 855
925 base::LazyInstance<NSSInitSingleton>::Leaky 856 base::LazyInstance<NSSInitSingleton>::Leaky
926 g_nss_singleton = LAZY_INSTANCE_INITIALIZER; 857 g_nss_singleton = LAZY_INSTANCE_INITIALIZER;
927 } // namespace 858 } // namespace
928 859
929 const char kTestTPMTokenName[] = "Test DB"; 860 #if defined(USE_NSS)
861 ScopedPK11Slot OpenSoftwareNSSDB(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 }
930 877
931 #if defined(USE_NSS)
932 void EarlySetupForNSSInit() { 878 void EarlySetupForNSSInit() {
933 base::FilePath database_dir = GetInitialConfigDirectory(); 879 base::FilePath database_dir = GetInitialConfigDirectory();
934 if (!database_dir.empty()) 880 if (!database_dir.empty())
935 UseLocalCacheOfNSSDatabaseIfNFS(database_dir); 881 UseLocalCacheOfNSSDatabaseIfNFS(database_dir);
936 } 882 }
937 #endif 883 #endif
938 884
939 void EnsureNSPRInit() { 885 void EnsureNSPRInit() {
940 g_nspr_singleton.Get(); 886 g_nspr_singleton.Get();
941 } 887 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 LOG(ERROR) << "Failed to load NSS libraries."; 966 LOG(ERROR) << "Failed to load NSS libraries.";
1021 } 967 }
1022 #endif // defined(USE_NSS) 968 #endif // defined(USE_NSS)
1023 } 969 }
1024 970
1025 bool CheckNSSVersion(const char* version) { 971 bool CheckNSSVersion(const char* version) {
1026 return !!NSS_VersionCheck(version); 972 return !!NSS_VersionCheck(version);
1027 } 973 }
1028 974
1029 #if defined(USE_NSS) 975 #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() { 976 base::Lock* GetNSSWriteLock() {
1044 return g_nss_singleton.Get().write_lock(); 977 return g_nss_singleton.Get().write_lock();
1045 } 978 }
1046 979
1047 AutoNSSWriteLock::AutoNSSWriteLock() : lock_(GetNSSWriteLock()) { 980 AutoNSSWriteLock::AutoNSSWriteLock() : lock_(GetNSSWriteLock()) {
1048 // May be NULL if the lock is not needed in our version of NSS. 981 // May be NULL if the lock is not needed in our version of NSS.
1049 if (lock_) 982 if (lock_)
1050 lock_->Acquire(); 983 lock_->Acquire();
1051 } 984 }
1052 985
1053 AutoNSSWriteLock::~AutoNSSWriteLock() { 986 AutoNSSWriteLock::~AutoNSSWriteLock() {
1054 if (lock_) { 987 if (lock_) {
1055 lock_->AssertAcquired(); 988 lock_->AssertAcquired();
1056 lock_->Release(); 989 lock_->Release();
1057 } 990 }
1058 } 991 }
1059 992
1060 AutoSECMODListReadLock::AutoSECMODListReadLock() 993 AutoSECMODListReadLock::AutoSECMODListReadLock()
1061 : lock_(SECMOD_GetDefaultModuleListLock()) { 994 : lock_(SECMOD_GetDefaultModuleListLock()) {
1062 SECMOD_GetReadLock(lock_); 995 SECMOD_GetReadLock(lock_);
1063 } 996 }
1064 997
1065 AutoSECMODListReadLock::~AutoSECMODListReadLock() { 998 AutoSECMODListReadLock::~AutoSECMODListReadLock() {
1066 SECMOD_ReleaseReadLock(lock_); 999 SECMOD_ReleaseReadLock(lock_);
1067 } 1000 }
1068
1069 #endif // defined(USE_NSS) 1001 #endif // defined(USE_NSS)
1070 1002
1071 #if defined(OS_CHROMEOS) 1003 #if defined(OS_CHROMEOS)
1072 PK11SlotInfo* GetSystemNSSKeySlot() { 1004 PK11SlotInfo* GetSystemNSSKeySlot() {
1073 return g_nss_singleton.Get().GetSystemNSSKeySlot(); 1005 return g_nss_singleton.Get().GetSystemNSSKeySlot();
1074 } 1006 }
1075 1007
1008 void SetTestSystemKeySlot(ScopedPK11Slot slot) {
Ryan Sleevi 2014/07/23 02:15:28 SetSystemKeySlotForTesting - that way presubmit sc
pneubeck (no reviews) 2014/07/23 14:34:17 Done.
1009 g_nss_singleton.Get().SetTestSystemKeySlot(ScopedPK11Slot());
1010 }
1011
1076 void EnableTPMTokenForNSS() { 1012 void EnableTPMTokenForNSS() {
1077 g_nss_singleton.Get().EnableTPMTokenForNSS(); 1013 g_nss_singleton.Get().EnableTPMTokenForNSS();
1078 } 1014 }
1079 1015
1080 bool IsTPMTokenEnabledForNSS() { 1016 bool IsTPMTokenEnabledForNSS() {
1081 return g_nss_singleton.Get().IsTPMTokenEnabledForNSS(); 1017 return g_nss_singleton.Get().IsTPMTokenEnabledForNSS();
1082 } 1018 }
1083 1019
1084 bool IsTPMTokenReady(const base::Closure& callback) { 1020 bool IsTPMTokenReady(const base::Closure& callback) {
1085 return g_nss_singleton.Get().IsTPMTokenReady(callback); 1021 return g_nss_singleton.Get().IsTPMTokenReady(callback);
1086 } 1022 }
1087 1023
1088 void InitializeTPMTokenAndSystemSlot( 1024 void InitializeTPMTokenAndSystemSlot(
1089 int token_slot_id, 1025 int token_slot_id,
1090 const base::Callback<void(bool)>& callback) { 1026 const base::Callback<void(bool)>& callback) {
1091 g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id, 1027 g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id,
1092 callback); 1028 callback);
1093 } 1029 }
1094 1030
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( 1031 bool InitializeNSSForChromeOSUser(
1120 const std::string& email, 1032 const std::string& email,
1121 const std::string& username_hash, 1033 const std::string& username_hash,
1122 const base::FilePath& path) { 1034 const base::FilePath& path) {
1123 return g_nss_singleton.Get().InitializeNSSForChromeOSUser( 1035 return g_nss_singleton.Get().InitializeNSSForChromeOSUser(
1124 email, username_hash, path); 1036 email, username_hash, path);
1125 } 1037 }
1126 1038
1127 bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { 1039 bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
1128 return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser( 1040 return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser(
1129 username_hash); 1041 username_hash);
1130 } 1042 }
1131 1043
1132 void WillInitializeTPMForChromeOSUser(const std::string& username_hash) { 1044 void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
1133 g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash); 1045 g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash);
1134 } 1046 }
1135 1047
1136 void InitializeTPMForChromeOSUser( 1048 void InitializeTPMForChromeOSUser(
1137 const std::string& username_hash, 1049 const std::string& username_hash,
1138 CK_SLOT_ID slot_id) { 1050 CK_SLOT_ID slot_id) {
1139 g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id); 1051 g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id);
1140 } 1052 }
1053
1141 void InitializePrivateSoftwareSlotForChromeOSUser( 1054 void InitializePrivateSoftwareSlotForChromeOSUser(
1142 const std::string& username_hash) { 1055 const std::string& username_hash) {
1143 g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser( 1056 g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser(
1144 username_hash); 1057 username_hash);
1145 } 1058 }
1059
1146 ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) { 1060 ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) {
1147 return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash); 1061 return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash);
1148 } 1062 }
1063
1149 ScopedPK11Slot GetPrivateSlotForChromeOSUser( 1064 ScopedPK11Slot GetPrivateSlotForChromeOSUser(
1150 const std::string& username_hash, 1065 const std::string& username_hash,
1151 const base::Callback<void(ScopedPK11Slot)>& callback) { 1066 const base::Callback<void(ScopedPK11Slot)>& callback) {
1152 return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(username_hash, 1067 return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(username_hash,
1153 callback); 1068 callback);
1154 } 1069 }
1070
1071 void CloseChromeOSUserForTesting(const std::string& username_hash) {
1072 g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash);
1073 }
1155 #endif // defined(OS_CHROMEOS) 1074 #endif // defined(OS_CHROMEOS)
1156 1075
1157 base::Time PRTimeToBaseTime(PRTime prtime) { 1076 base::Time PRTimeToBaseTime(PRTime prtime) {
1158 return base::Time::FromInternalValue( 1077 return base::Time::FromInternalValue(
1159 prtime + base::Time::UnixEpoch().ToInternalValue()); 1078 prtime + base::Time::UnixEpoch().ToInternalValue());
1160 } 1079 }
1161 1080
1162 PRTime BaseTimeToPRTime(base::Time time) { 1081 PRTime BaseTimeToPRTime(base::Time time) {
1163 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); 1082 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue();
1164 } 1083 }
1165 1084
1085 #if !defined(OS_CHROMEOS)
1166 PK11SlotInfo* GetPersistentNSSKeySlot() { 1086 PK11SlotInfo* GetPersistentNSSKeySlot() {
1167 return g_nss_singleton.Get().GetPersistentNSSKeySlot(); 1087 return g_nss_singleton.Get().GetPersistentNSSKeySlot();
1168 } 1088 }
1089 #endif
1169 1090
1170 } // namespace crypto 1091 } // namespace crypto
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698