| 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 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 // private keys, otherwise we'll fall back to the software | 309 // private keys, otherwise we'll fall back to the software |
| 310 // implementation. | 310 // implementation. |
| 311 tpm_token_enabled_for_nss_ = true; | 311 tpm_token_enabled_for_nss_ = true; |
| 312 } | 312 } |
| 313 | 313 |
| 314 bool IsTPMTokenEnabledForNSS() { | 314 bool IsTPMTokenEnabledForNSS() { |
| 315 DCHECK(thread_checker_.CalledOnValidThread()); | 315 DCHECK(thread_checker_.CalledOnValidThread()); |
| 316 return tpm_token_enabled_for_nss_; | 316 return tpm_token_enabled_for_nss_; |
| 317 } | 317 } |
| 318 | 318 |
| 319 void InitializeTPMToken(int token_slot_id, | 319 void InitializeTPMTokenAndSystemSlot( |
| 320 const base::Callback<void(bool)>& callback) { | 320 int system_slot_id, |
| 321 const base::Callback<void(bool)>& callback) { |
| 321 DCHECK(thread_checker_.CalledOnValidThread()); | 322 DCHECK(thread_checker_.CalledOnValidThread()); |
| 322 // Should not be called while there is already an initialization in | 323 // Should not be called while there is already an initialization in |
| 323 // progress. | 324 // progress. |
| 324 DCHECK(!initializing_tpm_token_); | 325 DCHECK(!initializing_tpm_token_); |
| 325 // If EnableTPMTokenForNSS hasn't been called, return false. | 326 // If EnableTPMTokenForNSS hasn't been called, return false. |
| 326 if (!tpm_token_enabled_for_nss_) { | 327 if (!tpm_token_enabled_for_nss_) { |
| 327 base::MessageLoop::current()->PostTask(FROM_HERE, | 328 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 328 base::Bind(callback, false)); | 329 base::Bind(callback, false)); |
| 329 return; | 330 return; |
| 330 } | 331 } |
| 331 | 332 |
| 332 // If everything is already initialized, then return true. | 333 // If everything is already initialized, then return true. |
| 333 // Note that only |tpm_slot_| is checked, since |chaps_module_| could be | 334 // Note that only |tpm_slot_| is checked, since |chaps_module_| could be |
| 334 // NULL in tests while |tpm_slot_| has been set to the test DB. | 335 // NULL in tests while |tpm_slot_| has been set to the test DB. |
| 335 if (tpm_slot_) { | 336 if (tpm_slot_) { |
| 336 base::MessageLoop::current()->PostTask(FROM_HERE, | 337 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 337 base::Bind(callback, true)); | 338 base::Bind(callback, true)); |
| 338 return; | 339 return; |
| 339 } | 340 } |
| 340 | 341 |
| 341 // Note that a reference is not taken to chaps_module_. This is safe since | 342 // Note that a reference is not taken to chaps_module_. This is safe since |
| 342 // NSSInitSingleton is Leaky, so the reference it holds is never released. | 343 // NSSInitSingleton is Leaky, so the reference it holds is never released. |
| 343 scoped_ptr<TPMModuleAndSlot> tpm_args(new TPMModuleAndSlot(chaps_module_)); | 344 scoped_ptr<TPMModuleAndSlot> tpm_args(new TPMModuleAndSlot(chaps_module_)); |
| 344 TPMModuleAndSlot* tpm_args_ptr = tpm_args.get(); | 345 TPMModuleAndSlot* tpm_args_ptr = tpm_args.get(); |
| 345 if (base::WorkerPool::PostTaskAndReply( | 346 if (base::WorkerPool::PostTaskAndReply( |
| 346 FROM_HERE, | 347 FROM_HERE, |
| 347 base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread, | 348 base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread, |
| 348 token_slot_id, | 349 system_slot_id, |
| 349 tpm_args_ptr), | 350 tpm_args_ptr), |
| 350 base::Bind(&NSSInitSingleton::OnInitializedTPMToken, | 351 base::Bind(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot, |
| 351 base::Unretained(this), // NSSInitSingleton is leaky | 352 base::Unretained(this), // NSSInitSingleton is leaky |
| 352 callback, | 353 callback, |
| 353 base::Passed(&tpm_args)), | 354 base::Passed(&tpm_args)), |
| 354 true /* task_is_slow */ | 355 true /* task_is_slow */ |
| 355 )) { | 356 )) { |
| 356 initializing_tpm_token_ = true; | 357 initializing_tpm_token_ = true; |
| 357 } else { | 358 } else { |
| 358 base::MessageLoop::current()->PostTask(FROM_HERE, | 359 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 359 base::Bind(callback, false)); | 360 base::Bind(callback, false)); |
| 360 } | 361 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 375 // read from this slot without requiring a call to C_Login. | 376 // read from this slot without requiring a call to C_Login. |
| 376 // askpw=only -- Only authenticate to the token when necessary. | 377 // askpw=only -- Only authenticate to the token when necessary. |
| 377 "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\""); | 378 "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\""); |
| 378 } | 379 } |
| 379 if (tpm_args->chaps_module) { | 380 if (tpm_args->chaps_module) { |
| 380 tpm_args->tpm_slot = | 381 tpm_args->tpm_slot = |
| 381 GetTPMSlotForIdOnWorkerThread(tpm_args->chaps_module, token_slot_id); | 382 GetTPMSlotForIdOnWorkerThread(tpm_args->chaps_module, token_slot_id); |
| 382 } | 383 } |
| 383 } | 384 } |
| 384 | 385 |
| 385 void OnInitializedTPMToken(const base::Callback<void(bool)>& callback, | 386 void OnInitializedTPMTokenAndSystemSlot( |
| 386 scoped_ptr<TPMModuleAndSlot> tpm_args) { | 387 const base::Callback<void(bool)>& callback, |
| 388 scoped_ptr<TPMModuleAndSlot> tpm_args) { |
| 387 DCHECK(thread_checker_.CalledOnValidThread()); | 389 DCHECK(thread_checker_.CalledOnValidThread()); |
| 388 DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module | 390 DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module |
| 389 << ", got tpm slot: " << !!tpm_args->tpm_slot; | 391 << ", got tpm slot: " << !!tpm_args->tpm_slot; |
| 390 | 392 |
| 391 chaps_module_ = tpm_args->chaps_module; | 393 chaps_module_ = tpm_args->chaps_module; |
| 392 tpm_slot_ = tpm_args->tpm_slot; | 394 tpm_slot_ = tpm_args->tpm_slot; |
| 393 if (!chaps_module_ && test_slot_) { | 395 if (!chaps_module_ && test_slot_) { |
| 394 // chromeos_unittests try to test the TPM initialization process. If we | 396 // chromeos_unittests try to test the TPM initialization process. If we |
| 395 // have a test DB open, pretend that it is the TPM slot. | 397 // have a test DB open, pretend that it is the TPM slot. |
| 396 tpm_slot_ = PK11_ReferenceSlot(test_slot_); | 398 tpm_slot_ = PK11_ReferenceSlot(test_slot_); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 if (!test_slot_) | 619 if (!test_slot_) |
| 618 return; | 620 return; |
| 619 SECStatus status = SECMOD_CloseUserDB(test_slot_); | 621 SECStatus status = SECMOD_CloseUserDB(test_slot_); |
| 620 if (status != SECSuccess) | 622 if (status != SECSuccess) |
| 621 PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); | 623 PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); |
| 622 PK11_FreeSlot(test_slot_); | 624 PK11_FreeSlot(test_slot_); |
| 623 test_slot_ = NULL; | 625 test_slot_ = NULL; |
| 624 ignore_result(g_test_nss_db_dir.Get().Delete()); | 626 ignore_result(g_test_nss_db_dir.Get().Delete()); |
| 625 } | 627 } |
| 626 | 628 |
| 627 PK11SlotInfo* GetPublicNSSKeySlot() { | 629 PK11SlotInfo* GetPersistentNSSKeySlot() { |
| 628 // TODO(mattm): Change to DCHECK when callers have been fixed. | 630 // TODO(mattm): Change to DCHECK when callers have been fixed. |
| 629 if (!thread_checker_.CalledOnValidThread()) { | 631 if (!thread_checker_.CalledOnValidThread()) { |
| 630 DVLOG(1) << "Called on wrong thread.\n" | 632 DVLOG(1) << "Called on wrong thread.\n" |
| 631 << base::debug::StackTrace().ToString(); | 633 << base::debug::StackTrace().ToString(); |
| 632 } | 634 } |
| 633 | 635 |
| 634 if (test_slot_) | 636 if (test_slot_) |
| 635 return PK11_ReferenceSlot(test_slot_); | 637 return PK11_ReferenceSlot(test_slot_); |
| 636 return PK11_GetInternalKeySlot(); | 638 return PK11_GetInternalKeySlot(); |
| 637 } | 639 } |
| 638 | 640 |
| 639 PK11SlotInfo* GetPrivateNSSKeySlot() { | 641 #if defined(OS_CHROMEOS) |
| 640 // TODO(mattm): Change to DCHECK when callers have been fixed. | 642 PK11SlotInfo* GetSystemNSSKeySlot() { |
| 641 if (!thread_checker_.CalledOnValidThread()) { | 643 DCHECK(thread_checker_.CalledOnValidThread()); |
| 642 DVLOG(1) << "Called on wrong thread.\n" | |
| 643 << base::debug::StackTrace().ToString(); | |
| 644 } | |
| 645 | 644 |
| 646 if (test_slot_) | 645 if (test_slot_) |
| 647 return PK11_ReferenceSlot(test_slot_); | 646 return PK11_ReferenceSlot(test_slot_); |
| 648 | 647 |
| 649 #if defined(OS_CHROMEOS) | 648 // TODO(mattm): chromeos::TPMTokenloader always calls |
| 650 if (tpm_token_enabled_for_nss_) { | 649 // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is |
| 651 if (IsTPMTokenReady(base::Closure())) { | 650 // disabled, tpm_slot_ will be the first user's slot instead. Can that be |
| 652 return PK11_ReferenceSlot(tpm_slot_); | 651 // detected and return NULL instead? |
| 653 } else { | 652 if (tpm_token_enabled_for_nss_ && IsTPMTokenReady(base::Closure())) |
| 654 // If we were supposed to get the hardware token, but were | 653 return PK11_ReferenceSlot(tpm_slot_); |
| 655 // unable to, return NULL rather than fall back to sofware. | 654 // If we were supposed to get the hardware token, but were |
| 656 return NULL; | 655 // unable to, return NULL rather than fall back to sofware. |
| 657 } | 656 return NULL; |
| 658 } | 657 } |
| 659 #endif | 658 #endif |
| 660 return PK11_GetInternalKeySlot(); | |
| 661 } | |
| 662 | 659 |
| 663 #if defined(USE_NSS) | 660 #if defined(USE_NSS) |
| 664 base::Lock* write_lock() { | 661 base::Lock* write_lock() { |
| 665 return &write_lock_; | 662 return &write_lock_; |
| 666 } | 663 } |
| 667 #endif // defined(USE_NSS) | 664 #endif // defined(USE_NSS) |
| 668 | 665 |
| 669 // This method is used to force NSS to be initialized without a DB. | 666 // This method is used to force NSS to be initialized without a DB. |
| 670 // Call this method before NSSInitSingleton() is constructed. | 667 // Call this method before NSSInitSingleton() is constructed. |
| 671 static void ForceNoDBInit() { | 668 static void ForceNoDBInit() { |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 SECMOD_GetReadLock(lock_); | 1059 SECMOD_GetReadLock(lock_); |
| 1063 } | 1060 } |
| 1064 | 1061 |
| 1065 AutoSECMODListReadLock::~AutoSECMODListReadLock() { | 1062 AutoSECMODListReadLock::~AutoSECMODListReadLock() { |
| 1066 SECMOD_ReleaseReadLock(lock_); | 1063 SECMOD_ReleaseReadLock(lock_); |
| 1067 } | 1064 } |
| 1068 | 1065 |
| 1069 #endif // defined(USE_NSS) | 1066 #endif // defined(USE_NSS) |
| 1070 | 1067 |
| 1071 #if defined(OS_CHROMEOS) | 1068 #if defined(OS_CHROMEOS) |
| 1069 PK11SlotInfo* GetSystemNSSKeySlot() { |
| 1070 return g_nss_singleton.Get().GetSystemNSSKeySlot(); |
| 1071 } |
| 1072 |
| 1072 void EnableTPMTokenForNSS() { | 1073 void EnableTPMTokenForNSS() { |
| 1073 g_nss_singleton.Get().EnableTPMTokenForNSS(); | 1074 g_nss_singleton.Get().EnableTPMTokenForNSS(); |
| 1074 } | 1075 } |
| 1075 | 1076 |
| 1076 bool IsTPMTokenEnabledForNSS() { | 1077 bool IsTPMTokenEnabledForNSS() { |
| 1077 return g_nss_singleton.Get().IsTPMTokenEnabledForNSS(); | 1078 return g_nss_singleton.Get().IsTPMTokenEnabledForNSS(); |
| 1078 } | 1079 } |
| 1079 | 1080 |
| 1080 bool IsTPMTokenReady(const base::Closure& callback) { | 1081 bool IsTPMTokenReady(const base::Closure& callback) { |
| 1081 return g_nss_singleton.Get().IsTPMTokenReady(callback); | 1082 return g_nss_singleton.Get().IsTPMTokenReady(callback); |
| 1082 } | 1083 } |
| 1083 | 1084 |
| 1084 void InitializeTPMToken(int token_slot_id, | 1085 void InitializeTPMTokenAndSystemSlot( |
| 1085 const base::Callback<void(bool)>& callback) { | 1086 int token_slot_id, |
| 1086 g_nss_singleton.Get().InitializeTPMToken(token_slot_id, callback); | 1087 const base::Callback<void(bool)>& callback) { |
| 1088 g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id, |
| 1089 callback); |
| 1087 } | 1090 } |
| 1088 | 1091 |
| 1089 ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser( | 1092 ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser( |
| 1090 const std::string& username_hash) | 1093 const std::string& username_hash) |
| 1091 : username_hash_(username_hash), constructed_successfully_(false) { | 1094 : username_hash_(username_hash), constructed_successfully_(false) { |
| 1092 if (!temp_dir_.CreateUniqueTempDir()) | 1095 if (!temp_dir_.CreateUniqueTempDir()) |
| 1093 return; | 1096 return; |
| 1094 constructed_successfully_ = | 1097 constructed_successfully_ = |
| 1095 InitializeNSSForChromeOSUser(username_hash, | 1098 InitializeNSSForChromeOSUser(username_hash, |
| 1096 username_hash, | 1099 username_hash, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 | 1153 |
| 1151 base::Time PRTimeToBaseTime(PRTime prtime) { | 1154 base::Time PRTimeToBaseTime(PRTime prtime) { |
| 1152 return base::Time::FromInternalValue( | 1155 return base::Time::FromInternalValue( |
| 1153 prtime + base::Time::UnixEpoch().ToInternalValue()); | 1156 prtime + base::Time::UnixEpoch().ToInternalValue()); |
| 1154 } | 1157 } |
| 1155 | 1158 |
| 1156 PRTime BaseTimeToPRTime(base::Time time) { | 1159 PRTime BaseTimeToPRTime(base::Time time) { |
| 1157 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); | 1160 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); |
| 1158 } | 1161 } |
| 1159 | 1162 |
| 1160 PK11SlotInfo* GetPublicNSSKeySlot() { | 1163 PK11SlotInfo* GetPersistentNSSKeySlot() { |
| 1161 return g_nss_singleton.Get().GetPublicNSSKeySlot(); | 1164 return g_nss_singleton.Get().GetPersistentNSSKeySlot(); |
| 1162 } | |
| 1163 | |
| 1164 PK11SlotInfo* GetPrivateNSSKeySlot() { | |
| 1165 return g_nss_singleton.Get().GetPrivateNSSKeySlot(); | |
| 1166 } | 1165 } |
| 1167 | 1166 |
| 1168 } // namespace crypto | 1167 } // namespace crypto |
| OLD | NEW |