Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Side by Side Diff: crypto/nss_util.cc

Issue 64723006: Start adding threading checks to nss_util. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use ThreadChecker, move DetachFromThread Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
11 #include <prerror.h> 11 #include <prerror.h>
12 #include <prinit.h> 12 #include <prinit.h>
13 #include <prtime.h> 13 #include <prtime.h>
14 #include <secmod.h> 14 #include <secmod.h>
15 15
16 #if defined(OS_LINUX) 16 #if defined(OS_LINUX)
17 #include <linux/nfs_fs.h> 17 #include <linux/nfs_fs.h>
18 #include <sys/vfs.h> 18 #include <sys/vfs.h>
19 #elif defined(OS_OPENBSD) 19 #elif defined(OS_OPENBSD)
20 #include <sys/mount.h> 20 #include <sys/mount.h>
21 #include <sys/param.h> 21 #include <sys/param.h>
22 #endif 22 #endif
23 23
24 #include <vector> 24 #include <vector>
25 25
26 #include "base/debug/alias.h" 26 #include "base/debug/alias.h"
27 #include "base/debug/stack_trace.h"
27 #include "base/environment.h" 28 #include "base/environment.h"
28 #include "base/file_util.h" 29 #include "base/file_util.h"
29 #include "base/files/file_path.h" 30 #include "base/files/file_path.h"
30 #include "base/files/scoped_temp_dir.h" 31 #include "base/files/scoped_temp_dir.h"
31 #include "base/lazy_instance.h" 32 #include "base/lazy_instance.h"
32 #include "base/logging.h" 33 #include "base/logging.h"
33 #include "base/memory/scoped_ptr.h" 34 #include "base/memory/scoped_ptr.h"
34 #include "base/metrics/histogram.h" 35 #include "base/metrics/histogram.h"
35 #include "base/native_library.h" 36 #include "base/native_library.h"
36 #include "base/strings/stringprintf.h" 37 #include "base/strings/stringprintf.h"
38 #include "base/threading/thread_checker.h"
37 #include "base/threading/thread_restrictions.h" 39 #include "base/threading/thread_restrictions.h"
38 #include "build/build_config.h" 40 #include "build/build_config.h"
39 41
40 // USE_NSS means we use NSS for everything crypto-related. If USE_NSS is not 42 // USE_NSS means we use NSS for everything crypto-related. If USE_NSS is not
41 // defined, such as on Mac and Windows, we use NSS for SSL only -- we don't 43 // defined, such as on Mac and Windows, we use NSS for SSL only -- we don't
42 // use NSS for crypto or certificate verification, and we don't use the NSS 44 // use NSS for crypto or certificate verification, and we don't use the NSS
43 // certificate and key databases. 45 // certificate and key databases.
44 #if defined(USE_NSS) 46 #if defined(USE_NSS)
45 #include "base/synchronization/lock.h" 47 #include "base/synchronization/lock.h"
46 #include "crypto/crypto_module_blocking_password_delegate.h" 48 #include "crypto/crypto_module_blocking_password_delegate.h"
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 base::debug::Alias(&os_error); 212 base::debug::Alias(&os_error);
211 LOG(ERROR) << "Error initializing NSS without a persistent database: " 213 LOG(ERROR) << "Error initializing NSS without a persistent database: "
212 << GetNSSErrorMessage(); 214 << GetNSSErrorMessage();
213 LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error; 215 LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error;
214 } 216 }
215 217
216 class NSSInitSingleton { 218 class NSSInitSingleton {
217 public: 219 public:
218 #if defined(OS_CHROMEOS) 220 #if defined(OS_CHROMEOS)
219 void OpenPersistentNSSDB() { 221 void OpenPersistentNSSDB() {
222 DCHECK(thread_checker_.CalledOnValidThread());
223
220 if (!chromeos_user_logged_in_) { 224 if (!chromeos_user_logged_in_) {
221 // GetDefaultConfigDirectory causes us to do blocking IO on UI thread. 225 // GetDefaultConfigDirectory causes us to do blocking IO on UI thread.
222 // Temporarily allow it until we fix http://crbug.com/70119 226 // Temporarily allow it until we fix http://crbug.com/70119
223 base::ThreadRestrictions::ScopedAllowIO allow_io; 227 base::ThreadRestrictions::ScopedAllowIO allow_io;
224 chromeos_user_logged_in_ = true; 228 chromeos_user_logged_in_ = true;
225 229
226 // This creates another DB slot in NSS that is read/write, unlike 230 // This creates another DB slot in NSS that is read/write, unlike
227 // the fake root CA cert DB and the "default" crypto key 231 // the fake root CA cert DB and the "default" crypto key
228 // provider, which are still read-only (because we initialized 232 // provider, which are still read-only (because we initialized
229 // NSS before we had a cryptohome mounted). 233 // NSS before we had a cryptohome mounted).
230 software_slot_ = OpenUserDB(GetDefaultConfigDirectory(), 234 software_slot_ = OpenUserDB(GetDefaultConfigDirectory(),
231 kNSSDatabaseName); 235 kNSSDatabaseName);
232 } 236 }
233 } 237 }
234 238
235 void EnableTPMTokenForNSS() { 239 void EnableTPMTokenForNSS() {
240 DCHECK(thread_checker_.CalledOnValidThread());
241
236 // If this gets set, then we'll use the TPM for certs with 242 // If this gets set, then we'll use the TPM for certs with
237 // private keys, otherwise we'll fall back to the software 243 // private keys, otherwise we'll fall back to the software
238 // implementation. 244 // implementation.
239 tpm_token_enabled_for_nss_ = true; 245 tpm_token_enabled_for_nss_ = true;
240 } 246 }
241 247
242 bool InitializeTPMToken(const std::string& token_name, 248 bool InitializeTPMToken(const std::string& token_name,
243 int token_slot_id, 249 int token_slot_id,
244 const std::string& user_pin) { 250 const std::string& user_pin) {
251 DCHECK(thread_checker_.CalledOnValidThread());
252
245 // If EnableTPMTokenForNSS hasn't been called, return false. 253 // If EnableTPMTokenForNSS hasn't been called, return false.
246 if (!tpm_token_enabled_for_nss_) 254 if (!tpm_token_enabled_for_nss_)
247 return false; 255 return false;
248 256
249 // If everything is already initialized, then return true. 257 // If everything is already initialized, then return true.
250 if (chaps_module_ && tpm_slot_) 258 if (chaps_module_ && tpm_slot_)
251 return true; 259 return true;
252 260
253 tpm_token_name_ = token_name; 261 tpm_token_name_ = token_name;
254 tpm_user_pin_ = user_pin; 262 tpm_user_pin_ = user_pin;
(...skipping 19 matching lines...) Expand all
274 } 282 }
275 if (chaps_module_){ 283 if (chaps_module_){
276 tpm_slot_ = GetTPMSlotForId(token_slot_id); 284 tpm_slot_ = GetTPMSlotForId(token_slot_id);
277 285
278 return tpm_slot_ != NULL; 286 return tpm_slot_ != NULL;
279 } 287 }
280 return false; 288 return false;
281 } 289 }
282 290
283 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) { 291 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) {
292 // TODO(mattm): Change to DCHECK when callers have been fixed.
293 if (!thread_checker_.CalledOnValidThread()) {
294 DVLOG(1) << "Called on wrong thread.\n"
295 << base::debug::StackTrace().ToString();
296 }
297
284 if (!tpm_token_enabled_for_nss_) { 298 if (!tpm_token_enabled_for_nss_) {
285 LOG(ERROR) << "GetTPMTokenInfo called before TPM Token is ready."; 299 LOG(ERROR) << "GetTPMTokenInfo called before TPM Token is ready.";
286 return; 300 return;
287 } 301 }
288 if (token_name) 302 if (token_name)
289 *token_name = tpm_token_name_; 303 *token_name = tpm_token_name_;
290 if (user_pin) 304 if (user_pin)
291 *user_pin = tpm_user_pin_; 305 *user_pin = tpm_user_pin_;
292 } 306 }
293 307
294 bool IsTPMTokenReady() { 308 bool IsTPMTokenReady() {
309 // TODO(mattm): Change to DCHECK when callers have been fixed.
310 if (!thread_checker_.CalledOnValidThread()) {
311 DVLOG(1) << "Called on wrong thread.\n"
312 << base::debug::StackTrace().ToString();
313 }
314
295 return tpm_slot_ != NULL; 315 return tpm_slot_ != NULL;
296 } 316 }
297 317
298 // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot 318 // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot
299 // id as an int. This should be safe since this is only used with chaps, which 319 // id as an int. This should be safe since this is only used with chaps, which
300 // we also control. 320 // we also control.
301 PK11SlotInfo* GetTPMSlotForId(CK_SLOT_ID slot_id) { 321 PK11SlotInfo* GetTPMSlotForId(CK_SLOT_ID slot_id) {
322 DCHECK(thread_checker_.CalledOnValidThread());
323
302 if (!chaps_module_) 324 if (!chaps_module_)
303 return NULL; 325 return NULL;
304 326
305 VLOG(1) << "Poking chaps module."; 327 VLOG(1) << "Poking chaps module.";
306 SECStatus rv = SECMOD_UpdateSlotList(chaps_module_); 328 SECStatus rv = SECMOD_UpdateSlotList(chaps_module_);
307 if (rv != SECSuccess) 329 if (rv != SECSuccess)
308 PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError(); 330 PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError();
309 331
310 PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module_->moduleID, slot_id); 332 PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module_->moduleID, slot_id);
311 if (!slot) 333 if (!slot)
312 LOG(ERROR) << "TPM slot " << slot_id << " not found."; 334 LOG(ERROR) << "TPM slot " << slot_id << " not found.";
313 return slot; 335 return slot;
314 } 336 }
315 #endif // defined(OS_CHROMEOS) 337 #endif // defined(OS_CHROMEOS)
316 338
317 339
318 bool OpenTestNSSDB() { 340 bool OpenTestNSSDB() {
341 DCHECK(thread_checker_.CalledOnValidThread());
342
319 if (test_slot_) 343 if (test_slot_)
320 return true; 344 return true;
321 if (!g_test_nss_db_dir.Get().CreateUniqueTempDir()) 345 if (!g_test_nss_db_dir.Get().CreateUniqueTempDir())
322 return false; 346 return false;
323 test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName); 347 test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName);
324 return !!test_slot_; 348 return !!test_slot_;
325 } 349 }
326 350
327 void CloseTestNSSDB() { 351 void CloseTestNSSDB() {
352 DCHECK(thread_checker_.CalledOnValidThread());
353
328 if (!test_slot_) 354 if (!test_slot_)
329 return; 355 return;
330 SECStatus status = SECMOD_CloseUserDB(test_slot_); 356 SECStatus status = SECMOD_CloseUserDB(test_slot_);
331 if (status != SECSuccess) 357 if (status != SECSuccess)
332 PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); 358 PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
333 PK11_FreeSlot(test_slot_); 359 PK11_FreeSlot(test_slot_);
334 test_slot_ = NULL; 360 test_slot_ = NULL;
335 ignore_result(g_test_nss_db_dir.Get().Delete()); 361 ignore_result(g_test_nss_db_dir.Get().Delete());
336 } 362 }
337 363
338 PK11SlotInfo* GetPublicNSSKeySlot() { 364 PK11SlotInfo* GetPublicNSSKeySlot() {
365 // TODO(mattm): Change to DCHECK when callers have been fixed.
366 if (!thread_checker_.CalledOnValidThread()) {
367 DVLOG(1) << "Called on wrong thread.\n"
368 << base::debug::StackTrace().ToString();
369 }
370
339 if (test_slot_) 371 if (test_slot_)
340 return PK11_ReferenceSlot(test_slot_); 372 return PK11_ReferenceSlot(test_slot_);
341 if (software_slot_) 373 if (software_slot_)
342 return PK11_ReferenceSlot(software_slot_); 374 return PK11_ReferenceSlot(software_slot_);
343 return PK11_GetInternalKeySlot(); 375 return PK11_GetInternalKeySlot();
344 } 376 }
345 377
346 PK11SlotInfo* GetPrivateNSSKeySlot() { 378 PK11SlotInfo* GetPrivateNSSKeySlot() {
379 // TODO(mattm): Change to DCHECK when callers have been fixed.
380 if (!thread_checker_.CalledOnValidThread()) {
381 DVLOG(1) << "Called on wrong thread.\n"
382 << base::debug::StackTrace().ToString();
383 }
384
347 if (test_slot_) 385 if (test_slot_)
348 return PK11_ReferenceSlot(test_slot_); 386 return PK11_ReferenceSlot(test_slot_);
349 387
350 #if defined(OS_CHROMEOS) 388 #if defined(OS_CHROMEOS)
351 if (tpm_token_enabled_for_nss_) { 389 if (tpm_token_enabled_for_nss_) {
352 if (IsTPMTokenReady()) { 390 if (IsTPMTokenReady()) {
353 return PK11_ReferenceSlot(tpm_slot_); 391 return PK11_ReferenceSlot(tpm_slot_);
354 } else { 392 } else {
355 // If we were supposed to get the hardware token, but were 393 // If we were supposed to get the hardware token, but were
356 // unable to, return NULL rather than fall back to sofware. 394 // unable to, return NULL rather than fall back to sofware.
(...skipping 25 matching lines...) Expand all
382 420
383 NSSInitSingleton() 421 NSSInitSingleton()
384 : tpm_token_enabled_for_nss_(false), 422 : tpm_token_enabled_for_nss_(false),
385 chaps_module_(NULL), 423 chaps_module_(NULL),
386 software_slot_(NULL), 424 software_slot_(NULL),
387 test_slot_(NULL), 425 test_slot_(NULL),
388 tpm_slot_(NULL), 426 tpm_slot_(NULL),
389 root_(NULL), 427 root_(NULL),
390 chromeos_user_logged_in_(false) { 428 chromeos_user_logged_in_(false) {
391 base::TimeTicks start_time = base::TimeTicks::Now(); 429 base::TimeTicks start_time = base::TimeTicks::Now();
430
431 // It's safe to construct on any thread, since LazyInstance will prevent any
432 // other threads from accessing until the constructor is done.
433 thread_checker_.DetachFromThread();
434
392 EnsureNSPRInit(); 435 EnsureNSPRInit();
393 436
394 // We *must* have NSS >= 3.14.3. 437 // We *must* have NSS >= 3.14.3.
395 COMPILE_ASSERT( 438 COMPILE_ASSERT(
396 (NSS_VMAJOR == 3 && NSS_VMINOR == 14 && NSS_VPATCH >= 3) || 439 (NSS_VMAJOR == 3 && NSS_VMINOR == 14 && NSS_VPATCH >= 3) ||
397 (NSS_VMAJOR == 3 && NSS_VMINOR > 14) || 440 (NSS_VMAJOR == 3 && NSS_VMINOR > 14) ||
398 (NSS_VMAJOR > 3), 441 (NSS_VMAJOR > 3),
399 nss_version_check_failed); 442 nss_version_check_failed);
400 // Also check the run-time NSS version. 443 // Also check the run-time NSS version.
401 // NSS_VersionCheck is a >= check, not strict equality. 444 // NSS_VersionCheck is a >= check, not strict equality.
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 PK11SlotInfo* software_slot_; 634 PK11SlotInfo* software_slot_;
592 PK11SlotInfo* test_slot_; 635 PK11SlotInfo* test_slot_;
593 PK11SlotInfo* tpm_slot_; 636 PK11SlotInfo* tpm_slot_;
594 SECMODModule* root_; 637 SECMODModule* root_;
595 bool chromeos_user_logged_in_; 638 bool chromeos_user_logged_in_;
596 #if defined(USE_NSS) 639 #if defined(USE_NSS)
597 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 640 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011
598 // is fixed, we will no longer need the lock. 641 // is fixed, we will no longer need the lock.
599 base::Lock write_lock_; 642 base::Lock write_lock_;
600 #endif // defined(USE_NSS) 643 #endif // defined(USE_NSS)
644
645 base::ThreadChecker thread_checker_;
601 }; 646 };
602 647
603 // static 648 // static
604 bool NSSInitSingleton::force_nodb_init_ = false; 649 bool NSSInitSingleton::force_nodb_init_ = false;
605 650
606 base::LazyInstance<NSSInitSingleton>::Leaky 651 base::LazyInstance<NSSInitSingleton>::Leaky
607 g_nss_singleton = LAZY_INSTANCE_INITIALIZER; 652 g_nss_singleton = LAZY_INSTANCE_INITIALIZER;
608 } // namespace 653 } // namespace
609 654
610 const char kTestTPMTokenName[] = "Test DB"; 655 const char kTestTPMTokenName[] = "Test DB";
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 826
782 PK11SlotInfo* GetPublicNSSKeySlot() { 827 PK11SlotInfo* GetPublicNSSKeySlot() {
783 return g_nss_singleton.Get().GetPublicNSSKeySlot(); 828 return g_nss_singleton.Get().GetPublicNSSKeySlot();
784 } 829 }
785 830
786 PK11SlotInfo* GetPrivateNSSKeySlot() { 831 PK11SlotInfo* GetPrivateNSSKeySlot() {
787 return g_nss_singleton.Get().GetPrivateNSSKeySlot(); 832 return g_nss_singleton.Get().GetPrivateNSSKeySlot();
788 } 833 }
789 834
790 } // namespace crypto 835 } // namespace crypto
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698