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 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 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 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 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 } 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 Loading... | |
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 |
OLD | NEW |