Index: crypto/nss_util.cc |
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc |
index f6b61330e91979e52d1ef9edaa9f7deac280a2a3..10501e0777800ec4d6f2031028e8830324852a37 100644 |
--- a/crypto/nss_util.cc |
+++ b/crypto/nss_util.cc |
@@ -50,6 +50,7 @@ |
#if defined(USE_NSS) |
#include "base/synchronization/lock.h" |
#include "crypto/nss_crypto_module_delegate.h" |
+#include "crypto/scoped_test_nss_db.h" |
#endif // defined(USE_NSS) |
namespace crypto { |
@@ -198,12 +199,6 @@ class NSPRInitSingleton { |
base::LazyInstance<NSPRInitSingleton>::Leaky |
g_nspr_singleton = LAZY_INSTANCE_INITIALIZER; |
-// This is a LazyInstance so that it will be deleted automatically when the |
-// unittest exits. NSSInitSingleton is a LeakySingleton, so it would not be |
-// deleted if it were a regular member. |
-base::LazyInstance<base::ScopedTempDir> g_test_nss_db_dir = |
- LAZY_INSTANCE_INITIALIZER; |
- |
// Force a crash with error info on NSS_NoDB_Init failure. |
void CrashOnNSSInitFailure() { |
int nss_error = PR_GetError(); |
@@ -287,8 +282,8 @@ class NSSInitSingleton { |
PK11SlotInfo* tpm_slot; |
}; |
- PK11SlotInfo* OpenPersistentNSSDBForPath(const std::string& db_name, |
- const base::FilePath& path) { |
+ ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name, |
+ const base::FilePath& path) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
// NSS is allowed to do IO on the current thread since dispatching |
// to a dedicated thread would still have the affect of blocking |
@@ -298,7 +293,7 @@ class NSSInitSingleton { |
base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb"); |
if (!base::CreateDirectory(nssdb_path)) { |
LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory."; |
- return NULL; |
+ return ScopedPK11Slot(); |
} |
return OpenUserDB(nssdb_path, db_name); |
} |
@@ -393,10 +388,10 @@ class NSSInitSingleton { |
chaps_module_ = tpm_args->chaps_module; |
tpm_slot_ = tpm_args->tpm_slot; |
- if (!chaps_module_ && test_slot_) { |
+ if (!chaps_module_ && test_system_slot_) { |
// chromeos_unittests try to test the TPM initialization process. If we |
// have a test DB open, pretend that it is the TPM slot. |
- tpm_slot_ = PK11_ReferenceSlot(test_slot_); |
+ tpm_slot_ = PK11_ReferenceSlot(test_system_slot_.get()); |
} |
initializing_tpm_token_ = false; |
@@ -463,12 +458,6 @@ class NSSInitSingleton { |
return false; |
} |
- // If test slot is set, slot getter methods will short circuit |
- // checking |chromeos_user_map_|, so there is nothing left to be |
- // initialized. |
- if (test_slot_) |
- return false; |
- |
DVLOG(2) << "Opening NSS DB " << path.value(); |
std::string db_name = base::StringPrintf( |
"%s %s", kUserNSSDatabaseName, username_hash.c_str()); |
@@ -551,11 +540,6 @@ class NSSInitSingleton { |
return ScopedPK11Slot(); |
} |
- if (test_slot_) { |
- DVLOG(2) << "returning test_slot_ for " << username_hash; |
- return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_)); |
- } |
- |
if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) { |
LOG(ERROR) << username_hash << " not initialized."; |
return ScopedPK11Slot(); |
@@ -579,11 +563,6 @@ class NSSInitSingleton { |
DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); |
- if (test_slot_) { |
- DVLOG(2) << "returning test_slot_ for " << username_hash; |
- return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_)); |
- } |
- |
return chromeos_user_map_[username_hash]->GetPrivateSlot(callback); |
} |
@@ -594,41 +573,13 @@ class NSSInitSingleton { |
delete i->second; |
chromeos_user_map_.erase(i); |
} |
-#endif // defined(OS_CHROMEOS) |
- |
- bool OpenTestNSSDB() { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- // NSS is allowed to do IO on the current thread since dispatching |
- // to a dedicated thread would still have the affect of blocking |
- // the current thread, due to NSS's internal locking requirements |
- base::ThreadRestrictions::ScopedAllowIO allow_io; |
- |
- if (test_slot_) |
- return true; |
- if (!g_test_nss_db_dir.Get().CreateUniqueTempDir()) |
- return false; |
- test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName); |
- return !!test_slot_; |
- } |
- |
- void CloseTestNSSDB() { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- // NSS is allowed to do IO on the current thread since dispatching |
- // to a dedicated thread would still have the affect of blocking |
- // the current thread, due to NSS's internal locking requirements |
- base::ThreadRestrictions::ScopedAllowIO allow_io; |
- |
- if (!test_slot_) |
- return; |
- SECStatus status = SECMOD_CloseUserDB(test_slot_); |
- if (status != SECSuccess) |
- PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); |
- PK11_FreeSlot(test_slot_); |
- test_slot_ = NULL; |
- ignore_result(g_test_nss_db_dir.Get().Delete()); |
+ void SetTestSystemKeySlot(ScopedPK11Slot slot) { |
+ test_system_slot_ = slot.Pass(); |
} |
+#endif // defined(OS_CHROMEOS) |
+#if !defined(OS_CHROMEOS) |
PK11SlotInfo* GetPersistentNSSKeySlot() { |
// TODO(mattm): Change to DCHECK when callers have been fixed. |
if (!thread_checker_.CalledOnValidThread()) { |
@@ -636,17 +587,16 @@ class NSSInitSingleton { |
<< base::debug::StackTrace().ToString(); |
} |
- if (test_slot_) |
- return PK11_ReferenceSlot(test_slot_); |
return PK11_GetInternalKeySlot(); |
} |
+#endif |
#if defined(OS_CHROMEOS) |
PK11SlotInfo* GetSystemNSSKeySlot() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
- if (test_slot_) |
- return PK11_ReferenceSlot(test_slot_); |
+ if (test_system_slot_) |
+ return PK11_ReferenceSlot(test_system_slot_.get()); |
// TODO(mattm): chromeos::TPMTokenloader always calls |
// InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is |
@@ -679,7 +629,6 @@ class NSSInitSingleton { |
: tpm_token_enabled_for_nss_(false), |
initializing_tpm_token_(false), |
chaps_module_(NULL), |
- test_slot_(NULL), |
tpm_slot_(NULL), |
root_(NULL) { |
base::TimeTicks start_time = base::TimeTicks::Now(); |
@@ -801,7 +750,6 @@ class NSSInitSingleton { |
PK11_FreeSlot(tpm_slot_); |
tpm_slot_ = NULL; |
} |
- CloseTestNSSDB(); |
if (root_) { |
SECMOD_UnloadUserModule(root_); |
SECMOD_DestroyModule(root_); |
@@ -863,24 +811,6 @@ class NSSInitSingleton { |
} |
#endif |
- static PK11SlotInfo* OpenUserDB(const base::FilePath& path, |
- const std::string& description) { |
- const std::string modspec = |
- base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", |
- path.value().c_str(), |
- description.c_str()); |
- PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); |
- if (db_slot) { |
- if (PK11_NeedUserInit(db_slot)) |
- PK11_InitPin(db_slot, NULL, NULL); |
- } |
- else { |
- LOG(ERROR) << "Error opening persistent database (" << modspec |
- << "): " << GetNSSErrorMessage(); |
- } |
- return db_slot; |
- } |
- |
static void DisableAESNIIfNeeded() { |
if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) { |
// Some versions of NSS have a bug that causes AVX instructions to be |
@@ -904,12 +834,12 @@ class NSSInitSingleton { |
typedef std::vector<base::Closure> TPMReadyCallbackList; |
TPMReadyCallbackList tpm_ready_callback_list_; |
SECMODModule* chaps_module_; |
- PK11SlotInfo* test_slot_; |
PK11SlotInfo* tpm_slot_; |
SECMODModule* root_; |
#if defined(OS_CHROMEOS) |
typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; |
ChromeOSUserMap chromeos_user_map_; |
+ ScopedPK11Slot test_system_slot_; |
#endif |
#if defined(USE_NSS) |
// TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 |
@@ -927,9 +857,24 @@ base::LazyInstance<NSSInitSingleton>::Leaky |
g_nss_singleton = LAZY_INSTANCE_INITIALIZER; |
} // namespace |
-const char kTestTPMTokenName[] = "Test DB"; |
- |
#if defined(USE_NSS) |
+ScopedPK11Slot OpenUserDB(const base::FilePath& path, |
+ const std::string& description) { |
+ const std::string modspec = |
+ base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", |
+ path.value().c_str(), |
+ description.c_str()); |
+ PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); |
+ if (db_slot) { |
+ if (PK11_NeedUserInit(db_slot)) |
+ PK11_InitPin(db_slot, NULL, NULL); |
+ } else { |
+ LOG(ERROR) << "Error opening persistent database (" << modspec |
+ << "): " << GetNSSErrorMessage(); |
+ } |
+ return ScopedPK11Slot(db_slot); |
+} |
+ |
void EarlySetupForNSSInit() { |
base::FilePath database_dir = GetInitialConfigDirectory(); |
if (!database_dir.empty()) |
@@ -1028,19 +973,24 @@ bool CheckNSSVersion(const char* version) { |
} |
#if defined(USE_NSS) |
-ScopedTestNSSDB::ScopedTestNSSDB() |
- : is_open_(g_nss_singleton.Get().OpenTestNSSDB()) { |
+#if defined(OS_CHROMEOS) |
+ScopedTestSystemNSSKeySlot::ScopedTestSystemNSSKeySlot() |
+ : test_db_(new ScopedTestNSSDB) { |
+ if (!test_db_->is_open()) |
+ return; |
+ g_nss_singleton.Get().SetTestSystemKeySlot( |
+ ScopedPK11Slot(PK11_ReferenceSlot(test_db_->slot()))); |
} |
-ScopedTestNSSDB::~ScopedTestNSSDB() { |
- // Don't close when NSS is < 3.15.1, because it would require an additional |
- // sleep for 1 second after closing the database, due to |
- // http://bugzil.la/875601. |
- if (NSS_VersionCheck("3.15.1")) { |
- g_nss_singleton.Get().CloseTestNSSDB(); |
- } |
+ScopedTestSystemNSSKeySlot::~ScopedTestSystemNSSKeySlot() { |
+ g_nss_singleton.Get().SetTestSystemKeySlot(ScopedPK11Slot()); |
} |
+bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const { |
+ return test_db_->is_open(); |
+} |
+#endif // defined(OS_CHROMEOS) |
+ |
base::Lock* GetNSSWriteLock() { |
return g_nss_singleton.Get().write_lock(); |
} |
@@ -1066,7 +1016,6 @@ AutoSECMODListReadLock::AutoSECMODListReadLock() |
AutoSECMODListReadLock::~AutoSECMODListReadLock() { |
SECMOD_ReleaseReadLock(lock_); |
} |
- |
#endif // defined(USE_NSS) |
#if defined(OS_CHROMEOS) |
@@ -1164,8 +1113,10 @@ PRTime BaseTimeToPRTime(base::Time time) { |
return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); |
} |
+#if !defined(OS_CHROMEOS) |
PK11SlotInfo* GetPersistentNSSKeySlot() { |
return g_nss_singleton.Get().GetPersistentNSSKeySlot(); |
} |
+#endif |
} // namespace crypto |