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 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 SlotReadyCallbackList tpm_ready_callback_list_; | 269 SlotReadyCallbackList tpm_ready_callback_list_; |
270 }; | 270 }; |
271 #endif // defined(OS_CHROMEOS) | 271 #endif // defined(OS_CHROMEOS) |
272 | 272 |
273 class NSSInitSingleton { | 273 class NSSInitSingleton { |
274 public: | 274 public: |
275 #if defined(OS_CHROMEOS) | 275 #if defined(OS_CHROMEOS) |
276 // Used with PostTaskAndReply to pass handles to worker thread and back. | 276 // Used with PostTaskAndReply to pass handles to worker thread and back. |
277 struct TPMModuleAndSlot { | 277 struct TPMModuleAndSlot { |
278 explicit TPMModuleAndSlot(SECMODModule* init_chaps_module) | 278 explicit TPMModuleAndSlot(SECMODModule* init_chaps_module) |
279 : chaps_module(init_chaps_module), tpm_slot(NULL) {} | 279 : chaps_module(init_chaps_module) {} |
280 SECMODModule* chaps_module; | 280 SECMODModule* chaps_module; |
281 PK11SlotInfo* tpm_slot; | 281 crypto::ScopedPK11Slot tpm_slot; |
282 }; | 282 }; |
283 | 283 |
284 ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name, | 284 ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name, |
285 const base::FilePath& path) { | 285 const base::FilePath& path) { |
286 DCHECK(thread_checker_.CalledOnValidThread()); | 286 DCHECK(thread_checker_.CalledOnValidThread()); |
287 // 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 |
288 // to a dedicated thread would still have the affect of blocking | 288 // to a dedicated thread would still have the affect of blocking |
289 // the current thread, due to NSS's internal locking requirements | 289 // the current thread, due to NSS's internal locking requirements |
290 base::ThreadRestrictions::ScopedAllowIO allow_io; | 290 base::ThreadRestrictions::ScopedAllowIO allow_io; |
291 | 291 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 } | 379 } |
380 | 380 |
381 void OnInitializedTPMTokenAndSystemSlot( | 381 void OnInitializedTPMTokenAndSystemSlot( |
382 const base::Callback<void(bool)>& callback, | 382 const base::Callback<void(bool)>& callback, |
383 scoped_ptr<TPMModuleAndSlot> tpm_args) { | 383 scoped_ptr<TPMModuleAndSlot> tpm_args) { |
384 DCHECK(thread_checker_.CalledOnValidThread()); | 384 DCHECK(thread_checker_.CalledOnValidThread()); |
385 DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module | 385 DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module |
386 << ", got tpm slot: " << !!tpm_args->tpm_slot; | 386 << ", got tpm slot: " << !!tpm_args->tpm_slot; |
387 | 387 |
388 chaps_module_ = tpm_args->chaps_module; | 388 chaps_module_ = tpm_args->chaps_module; |
389 tpm_slot_ = tpm_args->tpm_slot; | 389 tpm_slot_ = tpm_args->tpm_slot.Pass(); |
390 if (!chaps_module_ && test_system_slot_) { | 390 if (!chaps_module_ && test_system_slot_) { |
391 // chromeos_unittests try to test the TPM initialization process. If we | 391 // chromeos_unittests try to test the TPM initialization process. If we |
392 // 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. |
393 tpm_slot_ = PK11_ReferenceSlot(test_system_slot_.get()); | 393 tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get())); |
394 } | 394 } |
395 initializing_tpm_token_ = false; | 395 initializing_tpm_token_ = false; |
396 | 396 |
397 if (tpm_slot_) { | 397 if (tpm_slot_) { |
398 TPMReadyCallbackList callback_list; | 398 TPMReadyCallbackList callback_list; |
399 callback_list.swap(tpm_ready_callback_list_); | 399 callback_list.swap(tpm_ready_callback_list_); |
400 for (TPMReadyCallbackList::iterator i = callback_list.begin(); | 400 for (TPMReadyCallbackList::iterator i = callback_list.begin(); |
401 i != callback_list.end(); | 401 i != callback_list.end(); |
402 ++i) { | 402 ++i) { |
403 (*i).Run(); | 403 (*i).Run(); |
404 } | 404 } |
405 } | 405 } |
406 | 406 |
407 callback.Run(!!tpm_slot_); | 407 callback.Run(!!tpm_slot_); |
408 } | 408 } |
409 | 409 |
410 bool IsTPMTokenReady(const base::Closure& callback) { | 410 bool IsTPMTokenReady(const base::Closure& callback) { |
411 if (!callback.is_null()) { | 411 if (!callback.is_null()) { |
412 // Cannot DCHECK in the general case yet, but since the callback is | 412 // Cannot DCHECK in the general case yet, but since the callback is |
413 // a new addition to the API, DCHECK to make sure at least the new uses | 413 // a new addition to the API, DCHECK to make sure at least the new uses |
414 // don't regress. | 414 // don't regress. |
415 DCHECK(thread_checker_.CalledOnValidThread()); | 415 DCHECK(thread_checker_.CalledOnValidThread()); |
416 } else if (!thread_checker_.CalledOnValidThread()) { | 416 } else if (!thread_checker_.CalledOnValidThread()) { |
417 // TODO(mattm): Change to DCHECK when callers have been fixed. | 417 // TODO(mattm): Change to DCHECK when callers have been fixed. |
418 DVLOG(1) << "Called on wrong thread.\n" | 418 DVLOG(1) << "Called on wrong thread.\n" |
419 << base::debug::StackTrace().ToString(); | 419 << base::debug::StackTrace().ToString(); |
420 } | 420 } |
421 | 421 |
422 if (tpm_slot_ != NULL) | 422 if (tpm_slot_) |
423 return true; | 423 return true; |
424 | 424 |
425 if (!callback.is_null()) | 425 if (!callback.is_null()) |
426 tpm_ready_callback_list_.push_back(callback); | 426 tpm_ready_callback_list_.push_back(callback); |
427 | 427 |
428 return false; | 428 return false; |
429 } | 429 } |
430 | 430 |
431 // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot | 431 // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot |
432 // id as an int. This should be safe since this is only used with chaps, which | 432 // id as an int. This should be safe since this is only used with chaps, which |
433 // we also control. | 433 // we also control. |
434 static PK11SlotInfo* GetTPMSlotForIdOnWorkerThread(SECMODModule* chaps_module, | 434 static crypto::ScopedPK11Slot GetTPMSlotForIdOnWorkerThread( |
435 CK_SLOT_ID slot_id) { | 435 SECMODModule* chaps_module, |
| 436 CK_SLOT_ID slot_id) { |
436 DCHECK(chaps_module); | 437 DCHECK(chaps_module); |
437 | 438 |
438 DVLOG(3) << "Poking chaps module."; | 439 DVLOG(3) << "Poking chaps module."; |
439 SECStatus rv = SECMOD_UpdateSlotList(chaps_module); | 440 SECStatus rv = SECMOD_UpdateSlotList(chaps_module); |
440 if (rv != SECSuccess) | 441 if (rv != SECSuccess) |
441 PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError(); | 442 PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError(); |
442 | 443 |
443 PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module->moduleID, slot_id); | 444 PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module->moduleID, slot_id); |
444 if (!slot) | 445 if (!slot) |
445 LOG(ERROR) << "TPM slot " << slot_id << " not found."; | 446 LOG(ERROR) << "TPM slot " << slot_id << " not found."; |
446 return slot; | 447 return crypto::ScopedPK11Slot(slot); |
447 } | 448 } |
448 | 449 |
449 bool InitializeNSSForChromeOSUser( | 450 bool InitializeNSSForChromeOSUser( |
450 const std::string& email, | 451 const std::string& email, |
451 const std::string& username_hash, | 452 const std::string& username_hash, |
452 const base::FilePath& path) { | 453 const base::FilePath& path) { |
453 DCHECK(thread_checker_.CalledOnValidThread()); | 454 DCHECK(thread_checker_.CalledOnValidThread()); |
454 if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) { | 455 if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) { |
455 // This user already exists in our mapping. | 456 // This user already exists in our mapping. |
456 DVLOG(2) << username_hash << " already initialized."; | 457 DVLOG(2) << username_hash << " already initialized."; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 true /* task_is_slow */ | 509 true /* task_is_slow */ |
509 ); | 510 ); |
510 } | 511 } |
511 | 512 |
512 void OnInitializedTPMForChromeOSUser(const std::string& username_hash, | 513 void OnInitializedTPMForChromeOSUser(const std::string& username_hash, |
513 scoped_ptr<TPMModuleAndSlot> tpm_args) { | 514 scoped_ptr<TPMModuleAndSlot> tpm_args) { |
514 DCHECK(thread_checker_.CalledOnValidThread()); | 515 DCHECK(thread_checker_.CalledOnValidThread()); |
515 DVLOG(2) << "Got tpm slot for " << username_hash << " " | 516 DVLOG(2) << "Got tpm slot for " << username_hash << " " |
516 << !!tpm_args->tpm_slot; | 517 << !!tpm_args->tpm_slot; |
517 chromeos_user_map_[username_hash]->SetPrivateSlot( | 518 chromeos_user_map_[username_hash]->SetPrivateSlot( |
518 ScopedPK11Slot(tpm_args->tpm_slot)); | 519 tpm_args->tpm_slot.Pass()); |
519 } | 520 } |
520 | 521 |
521 void InitializePrivateSoftwareSlotForChromeOSUser( | 522 void InitializePrivateSoftwareSlotForChromeOSUser( |
522 const std::string& username_hash) { | 523 const std::string& username_hash) { |
523 DCHECK(thread_checker_.CalledOnValidThread()); | 524 DCHECK(thread_checker_.CalledOnValidThread()); |
524 VLOG(1) << "using software private slot for " << username_hash; | 525 VLOG(1) << "using software private slot for " << username_hash; |
525 DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); | 526 DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); |
526 DCHECK(chromeos_user_map_[username_hash]-> | 527 DCHECK(chromeos_user_map_[username_hash]-> |
527 private_slot_initialization_started()); | 528 private_slot_initialization_started()); |
528 | 529 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 << base::debug::StackTrace().ToString(); | 590 << base::debug::StackTrace().ToString(); |
590 } | 591 } |
591 | 592 |
592 return PK11_GetInternalKeySlot(); | 593 return PK11_GetInternalKeySlot(); |
593 } | 594 } |
594 #endif | 595 #endif |
595 | 596 |
596 #if defined(OS_CHROMEOS) | 597 #if defined(OS_CHROMEOS) |
597 void GetSystemNSSKeySlotCallback( | 598 void GetSystemNSSKeySlotCallback( |
598 const base::Callback<void(ScopedPK11Slot)>& callback) { | 599 const base::Callback<void(ScopedPK11Slot)>& callback) { |
599 callback.Run(ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_))); | 600 callback.Run(ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get()))); |
600 } | 601 } |
601 | 602 |
602 ScopedPK11Slot GetSystemNSSKeySlot( | 603 ScopedPK11Slot GetSystemNSSKeySlot( |
603 const base::Callback<void(ScopedPK11Slot)>& callback) { | 604 const base::Callback<void(ScopedPK11Slot)>& callback) { |
604 DCHECK(thread_checker_.CalledOnValidThread()); | 605 DCHECK(thread_checker_.CalledOnValidThread()); |
605 // TODO(mattm): chromeos::TPMTokenloader always calls | 606 // TODO(mattm): chromeos::TPMTokenloader always calls |
606 // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is | 607 // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is |
607 // disabled, tpm_slot_ will be the first user's slot instead. Can that be | 608 // disabled, tpm_slot_ will be the first user's slot instead. Can that be |
608 // detected and return NULL instead? | 609 // detected and return NULL instead? |
609 | 610 |
610 base::Closure wrapped_callback; | 611 base::Closure wrapped_callback; |
611 if (!callback.is_null()) { | 612 if (!callback.is_null()) { |
612 wrapped_callback = | 613 wrapped_callback = |
613 base::Bind(&NSSInitSingleton::GetSystemNSSKeySlotCallback, | 614 base::Bind(&NSSInitSingleton::GetSystemNSSKeySlotCallback, |
614 base::Unretained(this) /* singleton is leaky */, | 615 base::Unretained(this) /* singleton is leaky */, |
615 callback); | 616 callback); |
616 } | 617 } |
617 if (IsTPMTokenReady(wrapped_callback)) | 618 if (IsTPMTokenReady(wrapped_callback)) |
618 return ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_)); | 619 return ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get())); |
619 return ScopedPK11Slot(); | 620 return ScopedPK11Slot(); |
620 } | 621 } |
621 #endif | 622 #endif |
622 | 623 |
623 #if defined(USE_NSS) | 624 #if defined(USE_NSS) |
624 base::Lock* write_lock() { | 625 base::Lock* write_lock() { |
625 return &write_lock_; | 626 return &write_lock_; |
626 } | 627 } |
627 #endif // defined(USE_NSS) | 628 #endif // defined(USE_NSS) |
628 | 629 |
629 // This method is used to force NSS to be initialized without a DB. | 630 // This method is used to force NSS to be initialized without a DB. |
630 // Call this method before NSSInitSingleton() is constructed. | 631 // Call this method before NSSInitSingleton() is constructed. |
631 static void ForceNoDBInit() { | 632 static void ForceNoDBInit() { |
632 force_nodb_init_ = true; | 633 force_nodb_init_ = true; |
633 } | 634 } |
634 | 635 |
635 private: | 636 private: |
636 friend struct base::DefaultLazyInstanceTraits<NSSInitSingleton>; | 637 friend struct base::DefaultLazyInstanceTraits<NSSInitSingleton>; |
637 | 638 |
638 NSSInitSingleton() | 639 NSSInitSingleton() |
639 : tpm_token_enabled_for_nss_(false), | 640 : tpm_token_enabled_for_nss_(false), |
640 initializing_tpm_token_(false), | 641 initializing_tpm_token_(false), |
641 chaps_module_(NULL), | 642 chaps_module_(NULL), |
642 tpm_slot_(NULL), | |
643 root_(NULL) { | 643 root_(NULL) { |
644 base::TimeTicks start_time = base::TimeTicks::Now(); | 644 base::TimeTicks start_time = base::TimeTicks::Now(); |
645 | 645 |
646 // It's safe to construct on any thread, since LazyInstance will prevent any | 646 // It's safe to construct on any thread, since LazyInstance will prevent any |
647 // other threads from accessing until the constructor is done. | 647 // other threads from accessing until the constructor is done. |
648 thread_checker_.DetachFromThread(); | 648 thread_checker_.DetachFromThread(); |
649 | 649 |
650 DisableAESNIIfNeeded(); | 650 DisableAESNIIfNeeded(); |
651 | 651 |
652 EnsureNSPRInit(); | 652 EnsureNSPRInit(); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 50); | 749 50); |
750 } | 750 } |
751 | 751 |
752 // NOTE(willchan): We don't actually execute this code since we leak NSS to | 752 // NOTE(willchan): We don't actually execute this code since we leak NSS to |
753 // prevent non-joinable threads from using NSS after it's already been shut | 753 // prevent non-joinable threads from using NSS after it's already been shut |
754 // down. | 754 // down. |
755 ~NSSInitSingleton() { | 755 ~NSSInitSingleton() { |
756 #if defined(OS_CHROMEOS) | 756 #if defined(OS_CHROMEOS) |
757 STLDeleteValues(&chromeos_user_map_); | 757 STLDeleteValues(&chromeos_user_map_); |
758 #endif | 758 #endif |
759 if (tpm_slot_) { | 759 tpm_slot_.reset(); |
760 PK11_FreeSlot(tpm_slot_); | |
761 tpm_slot_ = NULL; | |
762 } | |
763 if (root_) { | 760 if (root_) { |
764 SECMOD_UnloadUserModule(root_); | 761 SECMOD_UnloadUserModule(root_); |
765 SECMOD_DestroyModule(root_); | 762 SECMOD_DestroyModule(root_); |
766 root_ = NULL; | 763 root_ = NULL; |
767 } | 764 } |
768 if (chaps_module_) { | 765 if (chaps_module_) { |
769 SECMOD_UnloadUserModule(chaps_module_); | 766 SECMOD_UnloadUserModule(chaps_module_); |
770 SECMOD_DestroyModule(chaps_module_); | 767 SECMOD_DestroyModule(chaps_module_); |
771 chaps_module_ = NULL; | 768 chaps_module_ = NULL; |
772 } | 769 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 } | 834 } |
838 | 835 |
839 // If this is set to true NSS is forced to be initialized without a DB. | 836 // If this is set to true NSS is forced to be initialized without a DB. |
840 static bool force_nodb_init_; | 837 static bool force_nodb_init_; |
841 | 838 |
842 bool tpm_token_enabled_for_nss_; | 839 bool tpm_token_enabled_for_nss_; |
843 bool initializing_tpm_token_; | 840 bool initializing_tpm_token_; |
844 typedef std::vector<base::Closure> TPMReadyCallbackList; | 841 typedef std::vector<base::Closure> TPMReadyCallbackList; |
845 TPMReadyCallbackList tpm_ready_callback_list_; | 842 TPMReadyCallbackList tpm_ready_callback_list_; |
846 SECMODModule* chaps_module_; | 843 SECMODModule* chaps_module_; |
847 PK11SlotInfo* tpm_slot_; | 844 crypto::ScopedPK11Slot tpm_slot_; |
848 SECMODModule* root_; | 845 SECMODModule* root_; |
849 #if defined(OS_CHROMEOS) | 846 #if defined(OS_CHROMEOS) |
850 typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; | 847 typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; |
851 ChromeOSUserMap chromeos_user_map_; | 848 ChromeOSUserMap chromeos_user_map_; |
852 ScopedPK11Slot test_system_slot_; | 849 ScopedPK11Slot test_system_slot_; |
853 #endif | 850 #endif |
854 #if defined(USE_NSS) | 851 #if defined(USE_NSS) |
855 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 | 852 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 |
856 // is fixed, we will no longer need the lock. | 853 // is fixed, we will no longer need the lock. |
857 base::Lock write_lock_; | 854 base::Lock write_lock_; |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); | 1090 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); |
1094 } | 1091 } |
1095 | 1092 |
1096 #if !defined(OS_CHROMEOS) | 1093 #if !defined(OS_CHROMEOS) |
1097 PK11SlotInfo* GetPersistentNSSKeySlot() { | 1094 PK11SlotInfo* GetPersistentNSSKeySlot() { |
1098 return g_nss_singleton.Get().GetPersistentNSSKeySlot(); | 1095 return g_nss_singleton.Get().GetPersistentNSSKeySlot(); |
1099 } | 1096 } |
1100 #endif | 1097 #endif |
1101 | 1098 |
1102 } // namespace crypto | 1099 } // namespace crypto |
OLD | NEW |