Chromium Code Reviews| 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 |