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

Side by Side Diff: crypto/nss_util.cc

Issue 18121007: *WIP* Store NSS slots per profile. Move keygen to chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cert manager basics working 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 | « crypto/nss_util.h ('k') | crypto/nss_util_internal.h » ('j') | 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/callback.h"
26 #include "base/debug/alias.h" 27 #include "base/debug/alias.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"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 base::FilePath dir = file_util::GetHomeDir(); 80 base::FilePath dir = file_util::GetHomeDir();
80 if (dir.empty()) { 81 if (dir.empty()) {
81 LOG(ERROR) << "Failed to get home directory."; 82 LOG(ERROR) << "Failed to get home directory.";
82 return dir; 83 return dir;
83 } 84 }
84 dir = dir.AppendASCII(".pki").AppendASCII("nssdb"); 85 dir = dir.AppendASCII(".pki").AppendASCII("nssdb");
85 if (!file_util::CreateDirectory(dir)) { 86 if (!file_util::CreateDirectory(dir)) {
86 LOG(ERROR) << "Failed to create " << dir.value() << " directory."; 87 LOG(ERROR) << "Failed to create " << dir.value() << " directory.";
87 dir.clear(); 88 dir.clear();
88 } 89 }
90 LOG(WARNING) << "GetDefaultConfigDirectory: " << dir.value();
89 return dir; 91 return dir;
90 } 92 }
91 93
92 // On non-Chrome OS platforms, return the default config directory. On Chrome OS 94 // On non-Chrome OS platforms, return the default config directory. On Chrome OS
93 // test images, return a read-only directory with fake root CA certs (which are 95 // test images, return a read-only directory with fake root CA certs (which are
94 // used by the local Google Accounts server mock we use when testing our login 96 // used by the local Google Accounts server mock we use when testing our login
95 // code). On Chrome OS non-test images (where the read-only directory doesn't 97 // code). On Chrome OS non-test images (where the read-only directory doesn't
96 // exist), return an empty path. 98 // exist), return an empty path.
97 base::FilePath GetInitialConfigDirectory() { 99 base::FilePath GetInitialConfigDirectory() {
98 #if defined(OS_CHROMEOS) 100 #if defined(OS_CHROMEOS)
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 241
240 // This creates another DB slot in NSS that is read/write, unlike 242 // This creates another DB slot in NSS that is read/write, unlike
241 // the fake root CA cert DB and the "default" crypto key 243 // the fake root CA cert DB and the "default" crypto key
242 // provider, which are still read-only (because we initialized 244 // provider, which are still read-only (because we initialized
243 // NSS before we had a cryptohome mounted). 245 // NSS before we had a cryptohome mounted).
244 software_slot_ = OpenUserDB(GetDefaultConfigDirectory(), 246 software_slot_ = OpenUserDB(GetDefaultConfigDirectory(),
245 kNSSDatabaseName); 247 kNSSDatabaseName);
246 } 248 }
247 } 249 }
248 250
251 PK11SlotInfo* OpenPersistentNSSDBForPath(const base::FilePath& path) {
252 LOG(WARNING) << __func__ << " " << path.AsUTF8Unsafe();
253 // We do NSS file io on the IO thread.
254 base::ThreadRestrictions::ScopedAllowIO allow_io;
255
256 if (force_nodb_init_) {
257 // XXX probably unneccessary
258 LOG(WARNING) << "force_nodb_init_, returning NULL";
259 return NULL;
260 }
261 base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb");
262 // XXX shoud we be doing this?
263 if (!file_util::CreateDirectory(nssdb_path)) {
264 LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory.";
265 return NULL;
266 }
267 return OpenUserDB(nssdb_path, kNSSDatabaseName);
268 }
269
249 void EnableTPMTokenForNSS() { 270 void EnableTPMTokenForNSS() {
271 // If this gets set, then we'll use the TPM for certs with
272 // private keys, otherwise we'll fall back to the software
273 // implementation.
250 tpm_token_enabled_for_nss_ = true; 274 tpm_token_enabled_for_nss_ = true;
251 } 275 }
252 276
277 bool IsTPMTokenEnabledForNSS() {
278 return tpm_token_enabled_for_nss_;
279 }
280
253 bool InitializeTPMToken(const std::string& token_name, 281 bool InitializeTPMToken(const std::string& token_name,
254 const std::string& user_pin) { 282 const std::string& user_pin,
283 int token_slot_id) {
255 // If EnableTPMTokenForNSS hasn't been called, return false. 284 // If EnableTPMTokenForNSS hasn't been called, return false.
256 if (!tpm_token_enabled_for_nss_) 285 if (!tpm_token_enabled_for_nss_)
257 return false; 286 return false;
258 287
259 // If everything is already initialized, then return true. 288 // If everything is already initialized, then return true.
260 if (chaps_module_ && tpm_slot_) 289 if (chaps_module_ && tpm_slot_)
261 return true; 290 return true;
262 291
263 tpm_token_name_ = token_name; 292 tpm_token_name_ = token_name;
264 tpm_user_pin_ = user_pin; 293 tpm_user_pin_ = user_pin;
265 294
266 // This tries to load the Chaps module so NSS can talk to the hardware 295 // This tries to load the Chaps module so NSS can talk to the hardware
267 // TPM. 296 // TPM.
268 if (!chaps_module_) { 297 if (!chaps_module_) {
269 chaps_module_ = LoadModule( 298 chaps_module_ = LoadModule(
270 kChapsModuleName, 299 kChapsModuleName,
271 kChapsPath, 300 kChapsPath,
272 // For more details on these parameters, see: 301 // For more details on these parameters, see:
273 // https://developer.mozilla.org/en/PKCS11_Module_Specs 302 // https://developer.mozilla.org/en/PKCS11_Module_Specs
274 // slotFlags=[PublicCerts] -- Certificates and public keys can be 303 // slotFlags=[PublicCerts] -- Certificates and public keys can be
275 // read from this slot without requiring a call to C_Login. 304 // read from this slot without requiring a call to C_Login.
276 // askpw=only -- Only authenticate to the token when necessary. 305 // askpw=only -- Only authenticate to the token when necessary.
277 "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\""); 306 "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\"");
278 } 307 }
279 if (chaps_module_){ 308 if (chaps_module_){
280 // If this gets set, then we'll use the TPM for certs with 309 tpm_slot_ = GetTPMSlotForId(token_slot_id);
281 // private keys, otherwise we'll fall back to the software 310
282 // implementation. 311 if (tpm_slot_) {
283 tpm_slot_ = GetTPMSlot(); 312 for (std::vector<base::Closure>::iterator i =
313 tpm_ready_callback_list_.begin();
314 i != tpm_ready_callback_list_.end();
315 ++i) {
316 (*i).Run();
317 }
318 tpm_ready_callback_list_.clear();
319 }
284 320
285 return tpm_slot_ != NULL; 321 return tpm_slot_ != NULL;
286 } 322 }
287 return false; 323 return false;
288 } 324 }
289 325
290 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) { 326 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) {
291 if (!tpm_token_enabled_for_nss_) { 327 if (!tpm_token_enabled_for_nss_) {
292 LOG(ERROR) << "GetTPMTokenInfo called before TPM Token is ready."; 328 LOG(ERROR) << "GetTPMTokenInfo called before TPM Token is ready.";
293 return; 329 return;
294 } 330 }
295 if (token_name) 331 if (token_name)
296 *token_name = tpm_token_name_; 332 *token_name = tpm_token_name_;
297 if (user_pin) 333 if (user_pin)
298 *user_pin = tpm_user_pin_; 334 *user_pin = tpm_user_pin_;
299 } 335 }
300 336
301 bool IsTPMTokenReady() { 337 bool IsTPMTokenReady() {
302 return tpm_slot_ != NULL; 338 return tpm_slot_ != NULL;
303 } 339 }
304 340
305 PK11SlotInfo* GetTPMSlot() { 341 void OnTPMReady(const base::Closure& callback) {
306 std::string token_name; 342 if (IsTPMTokenReady())
307 GetTPMTokenInfo(&token_name, NULL); 343 callback.Run();
308 return FindSlotWithTokenName(token_name); 344 else
345 tpm_ready_callback_list_.push_back(callback);
346 }
347
348 PK11SlotInfo* GetTPMSlotForId(CK_SLOT_ID slot_id) {
349 if (!chaps_module_)
350 return NULL;
351
352 VLOG(1) << "Poking chaps module.";
353 SECStatus rv = SECMOD_UpdateSlotList(chaps_module_);
354 if (rv != SECSuccess)
355 PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError();
356
357 PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module_->moduleID, slot_id);
358 if (!slot)
359 LOG(ERROR) << "TPM slot " << slot_id << " not found.";
360 return slot;
309 } 361 }
310 #endif // defined(OS_CHROMEOS) 362 #endif // defined(OS_CHROMEOS)
311 363
312 364
313 bool OpenTestNSSDB() { 365 bool OpenTestNSSDB() {
314 if (test_slot_) 366 if (test_slot_)
315 return true; 367 return true;
316 if (!g_test_nss_db_dir.Get().CreateUniqueTempDir()) 368 if (!g_test_nss_db_dir.Get().CreateUniqueTempDir())
317 return false; 369 return false;
318 test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName); 370 test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName);
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 } 621 }
570 return db_slot; 622 return db_slot;
571 } 623 }
572 624
573 // If this is set to true NSS is forced to be initialized without a DB. 625 // If this is set to true NSS is forced to be initialized without a DB.
574 static bool force_nodb_init_; 626 static bool force_nodb_init_;
575 627
576 bool tpm_token_enabled_for_nss_; 628 bool tpm_token_enabled_for_nss_;
577 std::string tpm_token_name_; 629 std::string tpm_token_name_;
578 std::string tpm_user_pin_; 630 std::string tpm_user_pin_;
631 std::vector<base::Closure> tpm_ready_callback_list_;
579 SECMODModule* chaps_module_; 632 SECMODModule* chaps_module_;
580 PK11SlotInfo* software_slot_; 633 PK11SlotInfo* software_slot_;
581 PK11SlotInfo* test_slot_; 634 PK11SlotInfo* test_slot_;
582 PK11SlotInfo* tpm_slot_; 635 PK11SlotInfo* tpm_slot_;
583 SECMODModule* root_; 636 SECMODModule* root_;
584 bool chromeos_user_logged_in_; 637 bool chromeos_user_logged_in_;
585 #if defined(USE_NSS) 638 #if defined(USE_NSS)
586 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 639 // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011
587 // is fixed, we will no longer need the lock. 640 // is fixed, we will no longer need the lock.
588 base::Lock write_lock_; 641 base::Lock write_lock_;
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 789
737 #if defined(OS_CHROMEOS) 790 #if defined(OS_CHROMEOS)
738 void OpenPersistentNSSDB() { 791 void OpenPersistentNSSDB() {
739 g_nss_singleton.Get().OpenPersistentNSSDB(); 792 g_nss_singleton.Get().OpenPersistentNSSDB();
740 } 793 }
741 794
742 void EnableTPMTokenForNSS() { 795 void EnableTPMTokenForNSS() {
743 g_nss_singleton.Get().EnableTPMTokenForNSS(); 796 g_nss_singleton.Get().EnableTPMTokenForNSS();
744 } 797 }
745 798
799 bool IsTPMTokenEnabledForNSS() {
800 return g_nss_singleton.Get().IsTPMTokenEnabledForNSS();
801 }
802
746 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) { 803 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) {
747 g_nss_singleton.Get().GetTPMTokenInfo(token_name, user_pin); 804 g_nss_singleton.Get().GetTPMTokenInfo(token_name, user_pin);
748 } 805 }
749 806
750 bool IsTPMTokenReady() { 807 bool IsTPMTokenReady() {
751 return g_nss_singleton.Get().IsTPMTokenReady(); 808 return g_nss_singleton.Get().IsTPMTokenReady();
752 } 809 }
753 810
811 void OnTPMReady(const base::Closure& callback) {
812 g_nss_singleton.Get().OnTPMReady(callback);
813 }
814
754 bool InitializeTPMToken(const std::string& token_name, 815 bool InitializeTPMToken(const std::string& token_name,
755 const std::string& user_pin) { 816 const std::string& user_pin,
756 return g_nss_singleton.Get().InitializeTPMToken(token_name, user_pin); 817 int token_slot_id) {
818 return g_nss_singleton.Get().InitializeTPMToken(
819 token_name, user_pin, token_slot_id);
820 }
821
822 PK11SlotInfo* OpenPersistentNSSDBForPath(const base::FilePath& path) {
823 return g_nss_singleton.Get().OpenPersistentNSSDBForPath(path);
824 }
825
826 PK11SlotInfo* GetTPMSlotForId(CK_SLOT_ID slot_id) {
827 return g_nss_singleton.Get().GetTPMSlotForId(slot_id);
757 } 828 }
758 #endif // defined(OS_CHROMEOS) 829 #endif // defined(OS_CHROMEOS)
759 830
760 base::Time PRTimeToBaseTime(PRTime prtime) { 831 base::Time PRTimeToBaseTime(PRTime prtime) {
761 return base::Time::FromInternalValue( 832 return base::Time::FromInternalValue(
762 prtime + base::Time::UnixEpoch().ToInternalValue()); 833 prtime + base::Time::UnixEpoch().ToInternalValue());
763 } 834 }
764 835
765 PRTime BaseTimeToPRTime(base::Time time) { 836 PRTime BaseTimeToPRTime(base::Time time) {
766 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); 837 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue();
767 } 838 }
768 839
769 PK11SlotInfo* GetPublicNSSKeySlot() { 840 PK11SlotInfo* GetPublicNSSKeySlot() {
770 return g_nss_singleton.Get().GetPublicNSSKeySlot(); 841 return g_nss_singleton.Get().GetPublicNSSKeySlot();
771 } 842 }
772 843
773 PK11SlotInfo* GetPrivateNSSKeySlot() { 844 PK11SlotInfo* GetPrivateNSSKeySlot() {
774 return g_nss_singleton.Get().GetPrivateNSSKeySlot(); 845 return g_nss_singleton.Get().GetPrivateNSSKeySlot();
775 } 846 }
776 847
848 void DumpNSSSlotInfos() {
849 AutoSECMODListReadLock auto_lock;
850 SECMODModuleList* head = SECMOD_GetDefaultModuleList();
851 LOG(WARNING) << "DumpNSSSlotInfos:";
852 for (SECMODModuleList* item = head; item != NULL; item = item->next) {
853 int slot_count = item->module->loaded ? item->module->slotCount : 0;
854 LOG(WARNING) << item->module->moduleID
855 << " module " << item->module->commonName
856 << " loaded:" << item->module->loaded;
857 for (int i = 0; i < slot_count; i++) {
858 PK11SlotInfo* slot = item->module->slots[i];
859 LOG(WARNING) << " " << PK11_GetSlotID(slot)
860 << " tok:" << PK11_GetTokenName(slot)
861 << " slot:" << PK11_GetSlotName(slot)
862 << (PK11_IsInternal(slot) ? " internal" : "")
863 << (PK11_IsInternalKeySlot(slot) ? " internalkeyslot" : "")
864 << (PK11_IsReadOnly(slot) ? " readonly" : "");
865 }
866 }
867 LOG(WARNING) << "";
868 }
869
777 } // namespace crypto 870 } // namespace crypto
OLDNEW
« no previous file with comments | « crypto/nss_util.h ('k') | crypto/nss_util_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698