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 |