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

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: . 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/non_thread_safe.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 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 void CrashOnNSSInitFailure() { 208 void CrashOnNSSInitFailure() {
207 int nss_error = PR_GetError(); 209 int nss_error = PR_GetError();
208 int os_error = PR_GetOSError(); 210 int os_error = PR_GetOSError();
209 base::debug::Alias(&nss_error); 211 base::debug::Alias(&nss_error);
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 : public base::NonThreadSafe {
217 public: 219 public:
218 #if defined(OS_CHROMEOS) 220 #if defined(OS_CHROMEOS)
219 void OpenPersistentNSSDB() { 221 void OpenPersistentNSSDB() {
222 DCHECK(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(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(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 (!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 (!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(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(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(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 (!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 (!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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, 518 NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
481 0, NSS_USE_ALG_IN_CERT_SIGNATURE); 519 0, NSS_USE_ALG_IN_CERT_SIGNATURE);
482 520
483 // The UMA bit is conditionally set for this histogram in 521 // The UMA bit is conditionally set for this histogram in
484 // chrome/common/startup_metric_utils.cc . 522 // chrome/common/startup_metric_utils.cc .
485 HISTOGRAM_CUSTOM_TIMES("Startup.SlowStartupNSSInit", 523 HISTOGRAM_CUSTOM_TIMES("Startup.SlowStartupNSSInit",
486 base::TimeTicks::Now() - start_time, 524 base::TimeTicks::Now() - start_time,
487 base::TimeDelta::FromMilliseconds(10), 525 base::TimeDelta::FromMilliseconds(10),
488 base::TimeDelta::FromHours(1), 526 base::TimeDelta::FromHours(1),
489 50); 527 50);
528
529 // It's safe to construct on any thread, since LazyInstance will prevent any
530 // other threads from accessing until the constructor is done.
531 DetachFromThread();
wtc 2013/11/11 22:10:15 If this can be called at the beginning of this fun
mattm 2013/11/12 00:41:34 Done.
490 } 532 }
491 533
492 // NOTE(willchan): We don't actually execute this code since we leak NSS to 534 // NOTE(willchan): We don't actually execute this code since we leak NSS to
493 // prevent non-joinable threads from using NSS after it's already been shut 535 // prevent non-joinable threads from using NSS after it's already been shut
494 // down. 536 // down.
495 ~NSSInitSingleton() { 537 ~NSSInitSingleton() {
496 if (tpm_slot_) { 538 if (tpm_slot_) {
497 PK11_FreeSlot(tpm_slot_); 539 PK11_FreeSlot(tpm_slot_);
498 tpm_slot_ = NULL; 540 tpm_slot_ = NULL;
499 } 541 }
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 823
782 PK11SlotInfo* GetPublicNSSKeySlot() { 824 PK11SlotInfo* GetPublicNSSKeySlot() {
783 return g_nss_singleton.Get().GetPublicNSSKeySlot(); 825 return g_nss_singleton.Get().GetPublicNSSKeySlot();
784 } 826 }
785 827
786 PK11SlotInfo* GetPrivateNSSKeySlot() { 828 PK11SlotInfo* GetPrivateNSSKeySlot() {
787 return g_nss_singleton.Get().GetPrivateNSSKeySlot(); 829 return g_nss_singleton.Get().GetPrivateNSSKeySlot();
788 } 830 }
789 831
790 } // namespace crypto 832 } // 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