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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 #endif | 161 #endif |
162 scoped_ptr<base::Environment> env(base::Environment::Create()); | 162 scoped_ptr<base::Environment> env(base::Environment::Create()); |
163 const char* use_cache_env_var = "NSS_SDB_USE_CACHE"; | 163 const char* use_cache_env_var = "NSS_SDB_USE_CACHE"; |
164 if (!env->HasVar(use_cache_env_var)) | 164 if (!env->HasVar(use_cache_env_var)) |
165 env->SetVar(use_cache_env_var, "yes"); | 165 env->SetVar(use_cache_env_var, "yes"); |
166 } | 166 } |
167 } | 167 } |
168 #endif // defined(OS_LINUX) || defined(OS_OPENBSD) | 168 #endif // defined(OS_LINUX) || defined(OS_OPENBSD) |
169 } | 169 } |
170 | 170 |
171 PK11SlotInfo* FindSlotWithTokenName(const std::string& token_name) { | |
172 AutoSECMODListReadLock auto_lock; | |
173 SECMODModuleList* head = SECMOD_GetDefaultModuleList(); | |
174 for (SECMODModuleList* item = head; item != NULL; item = item->next) { | |
175 int slot_count = item->module->loaded ? item->module->slotCount : 0; | |
176 for (int i = 0; i < slot_count; i++) { | |
177 PK11SlotInfo* slot = item->module->slots[i]; | |
178 if (PK11_GetTokenName(slot) == token_name) | |
179 return PK11_ReferenceSlot(slot); | |
180 } | |
181 } | |
182 return NULL; | |
183 } | |
184 | |
185 #endif // defined(USE_NSS) | 171 #endif // defined(USE_NSS) |
186 | 172 |
187 // A singleton to initialize/deinitialize NSPR. | 173 // A singleton to initialize/deinitialize NSPR. |
188 // Separate from the NSS singleton because we initialize NSPR on the UI thread. | 174 // Separate from the NSS singleton because we initialize NSPR on the UI thread. |
189 // Now that we're leaking the singleton, we could merge back with the NSS | 175 // Now that we're leaking the singleton, we could merge back with the NSS |
190 // singleton. | 176 // singleton. |
191 class NSPRInitSingleton { | 177 class NSPRInitSingleton { |
192 private: | 178 private: |
193 friend struct base::DefaultLazyInstanceTraits<NSPRInitSingleton>; | 179 friend struct base::DefaultLazyInstanceTraits<NSPRInitSingleton>; |
194 | 180 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 // This creates another DB slot in NSS that is read/write, unlike | 226 // This creates another DB slot in NSS that is read/write, unlike |
241 // the fake root CA cert DB and the "default" crypto key | 227 // the fake root CA cert DB and the "default" crypto key |
242 // provider, which are still read-only (because we initialized | 228 // provider, which are still read-only (because we initialized |
243 // NSS before we had a cryptohome mounted). | 229 // NSS before we had a cryptohome mounted). |
244 software_slot_ = OpenUserDB(GetDefaultConfigDirectory(), | 230 software_slot_ = OpenUserDB(GetDefaultConfigDirectory(), |
245 kNSSDatabaseName); | 231 kNSSDatabaseName); |
246 } | 232 } |
247 } | 233 } |
248 | 234 |
249 void EnableTPMTokenForNSS() { | 235 void EnableTPMTokenForNSS() { |
| 236 // If this gets set, then we'll use the TPM for certs with |
| 237 // private keys, otherwise we'll fall back to the software |
| 238 // implementation. |
250 tpm_token_enabled_for_nss_ = true; | 239 tpm_token_enabled_for_nss_ = true; |
251 } | 240 } |
252 | 241 |
253 bool InitializeTPMToken(const std::string& token_name, | 242 bool InitializeTPMToken(const std::string& token_name, |
| 243 int token_slot_id, |
254 const std::string& user_pin) { | 244 const std::string& user_pin) { |
255 // If EnableTPMTokenForNSS hasn't been called, return false. | 245 // If EnableTPMTokenForNSS hasn't been called, return false. |
256 if (!tpm_token_enabled_for_nss_) | 246 if (!tpm_token_enabled_for_nss_) |
257 return false; | 247 return false; |
258 | 248 |
259 // If everything is already initialized, then return true. | 249 // If everything is already initialized, then return true. |
260 if (chaps_module_ && tpm_slot_) | 250 if (chaps_module_ && tpm_slot_) |
261 return true; | 251 return true; |
262 | 252 |
263 tpm_token_name_ = token_name; | 253 tpm_token_name_ = token_name; |
264 tpm_user_pin_ = user_pin; | 254 tpm_user_pin_ = user_pin; |
265 | 255 |
266 // This tries to load the Chaps module so NSS can talk to the hardware | 256 // This tries to load the Chaps module so NSS can talk to the hardware |
267 // TPM. | 257 // TPM. |
268 if (!chaps_module_) { | 258 if (!chaps_module_) { |
269 chaps_module_ = LoadModule( | 259 chaps_module_ = LoadModule( |
270 kChapsModuleName, | 260 kChapsModuleName, |
271 kChapsPath, | 261 kChapsPath, |
272 // For more details on these parameters, see: | 262 // For more details on these parameters, see: |
273 // https://developer.mozilla.org/en/PKCS11_Module_Specs | 263 // https://developer.mozilla.org/en/PKCS11_Module_Specs |
274 // slotFlags=[PublicCerts] -- Certificates and public keys can be | 264 // slotFlags=[PublicCerts] -- Certificates and public keys can be |
275 // read from this slot without requiring a call to C_Login. | 265 // read from this slot without requiring a call to C_Login. |
276 // askpw=only -- Only authenticate to the token when necessary. | 266 // askpw=only -- Only authenticate to the token when necessary. |
277 "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\""); | 267 "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\""); |
| 268 if (!chaps_module_ && test_slot_) { |
| 269 // chromeos_unittests try to test the TPM initialization process. If we |
| 270 // have a test DB open, pretend that it is the TPM slot. |
| 271 tpm_slot_ = PK11_ReferenceSlot(test_slot_); |
| 272 return true; |
| 273 } |
278 } | 274 } |
279 if (chaps_module_){ | 275 if (chaps_module_){ |
280 // If this gets set, then we'll use the TPM for certs with | 276 tpm_slot_ = GetTPMSlotForId(token_slot_id); |
281 // private keys, otherwise we'll fall back to the software | |
282 // implementation. | |
283 tpm_slot_ = GetTPMSlot(); | |
284 | 277 |
285 return tpm_slot_ != NULL; | 278 return tpm_slot_ != NULL; |
286 } | 279 } |
287 return false; | 280 return false; |
288 } | 281 } |
289 | 282 |
290 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) { | 283 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) { |
291 if (!tpm_token_enabled_for_nss_) { | 284 if (!tpm_token_enabled_for_nss_) { |
292 LOG(ERROR) << "GetTPMTokenInfo called before TPM Token is ready."; | 285 LOG(ERROR) << "GetTPMTokenInfo called before TPM Token is ready."; |
293 return; | 286 return; |
294 } | 287 } |
295 if (token_name) | 288 if (token_name) |
296 *token_name = tpm_token_name_; | 289 *token_name = tpm_token_name_; |
297 if (user_pin) | 290 if (user_pin) |
298 *user_pin = tpm_user_pin_; | 291 *user_pin = tpm_user_pin_; |
299 } | 292 } |
300 | 293 |
301 bool IsTPMTokenReady() { | 294 bool IsTPMTokenReady() { |
302 return tpm_slot_ != NULL; | 295 return tpm_slot_ != NULL; |
303 } | 296 } |
304 | 297 |
305 PK11SlotInfo* GetTPMSlot() { | 298 // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot |
306 std::string token_name; | 299 // id as an int. This should be safe since this is only used with chaps, which |
307 GetTPMTokenInfo(&token_name, NULL); | 300 // we also control. |
308 return FindSlotWithTokenName(token_name); | 301 PK11SlotInfo* GetTPMSlotForId(CK_SLOT_ID slot_id) { |
| 302 if (!chaps_module_) |
| 303 return NULL; |
| 304 |
| 305 VLOG(1) << "Poking chaps module."; |
| 306 SECStatus rv = SECMOD_UpdateSlotList(chaps_module_); |
| 307 if (rv != SECSuccess) |
| 308 PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError(); |
| 309 |
| 310 PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module_->moduleID, slot_id); |
| 311 if (!slot) |
| 312 LOG(ERROR) << "TPM slot " << slot_id << " not found."; |
| 313 return slot; |
309 } | 314 } |
310 #endif // defined(OS_CHROMEOS) | 315 #endif // defined(OS_CHROMEOS) |
311 | 316 |
312 | 317 |
313 bool OpenTestNSSDB() { | 318 bool OpenTestNSSDB() { |
314 if (test_slot_) | 319 if (test_slot_) |
315 return true; | 320 return true; |
316 if (!g_test_nss_db_dir.Get().CreateUniqueTempDir()) | 321 if (!g_test_nss_db_dir.Get().CreateUniqueTempDir()) |
317 return false; | 322 return false; |
318 test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName); | 323 test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 | 524 |
520 #if defined(USE_NSS) || defined(OS_IOS) | 525 #if defined(USE_NSS) || defined(OS_IOS) |
521 // Load nss's built-in root certs. | 526 // Load nss's built-in root certs. |
522 SECMODModule* InitDefaultRootCerts() { | 527 SECMODModule* InitDefaultRootCerts() { |
523 SECMODModule* root = LoadModule("Root Certs", "libnssckbi.so", NULL); | 528 SECMODModule* root = LoadModule("Root Certs", "libnssckbi.so", NULL); |
524 if (root) | 529 if (root) |
525 return root; | 530 return root; |
526 | 531 |
527 // Aw, snap. Can't find/load root cert shared library. | 532 // Aw, snap. Can't find/load root cert shared library. |
528 // This will make it hard to talk to anybody via https. | 533 // This will make it hard to talk to anybody via https. |
529 NOTREACHED(); | 534 // TODO(mattm): Re-add the NOTREACHED here when crbug.com/310972 is fixed. |
530 return NULL; | 535 return NULL; |
531 } | 536 } |
532 | 537 |
533 // Load the given module for this NSS session. | 538 // Load the given module for this NSS session. |
534 SECMODModule* LoadModule(const char* name, | 539 SECMODModule* LoadModule(const char* name, |
535 const char* library_path, | 540 const char* library_path, |
536 const char* params) { | 541 const char* params) { |
537 std::string modparams = base::StringPrintf( | 542 std::string modparams = base::StringPrintf( |
538 "name=\"%s\" library=\"%s\" %s", | 543 "name=\"%s\" library=\"%s\" %s", |
539 name, library_path, params ? params : ""); | 544 name, library_path, params ? params : ""); |
540 | 545 |
541 // Shouldn't need to const_cast here, but SECMOD doesn't properly | 546 // Shouldn't need to const_cast here, but SECMOD doesn't properly |
542 // declare input string arguments as const. Bug | 547 // declare input string arguments as const. Bug |
543 // https://bugzilla.mozilla.org/show_bug.cgi?id=642546 was filed | 548 // https://bugzilla.mozilla.org/show_bug.cgi?id=642546 was filed |
544 // on NSS codebase to address this. | 549 // on NSS codebase to address this. |
545 SECMODModule* module = SECMOD_LoadUserModule( | 550 SECMODModule* module = SECMOD_LoadUserModule( |
546 const_cast<char*>(modparams.c_str()), NULL, PR_FALSE); | 551 const_cast<char*>(modparams.c_str()), NULL, PR_FALSE); |
547 if (!module) { | 552 if (!module) { |
548 LOG(ERROR) << "Error loading " << name << " module into NSS: " | 553 LOG(ERROR) << "Error loading " << name << " module into NSS: " |
549 << GetNSSErrorMessage(); | 554 << GetNSSErrorMessage(); |
550 return NULL; | 555 return NULL; |
551 } | 556 } |
| 557 if (!module->loaded) { |
| 558 LOG(ERROR) << "After loading " << name << ", loaded==false: " |
| 559 << GetNSSErrorMessage(); |
| 560 SECMOD_DestroyModule(module); |
| 561 return NULL; |
| 562 } |
552 return module; | 563 return module; |
553 } | 564 } |
554 #endif | 565 #endif |
555 | 566 |
556 static PK11SlotInfo* OpenUserDB(const base::FilePath& path, | 567 static PK11SlotInfo* OpenUserDB(const base::FilePath& path, |
557 const char* description) { | 568 const char* description) { |
558 const std::string modspec = | 569 const std::string modspec = |
559 base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", | 570 base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", |
560 path.value().c_str(), description); | 571 path.value().c_str(), description); |
561 PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); | 572 PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 | 756 |
746 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) { | 757 void GetTPMTokenInfo(std::string* token_name, std::string* user_pin) { |
747 g_nss_singleton.Get().GetTPMTokenInfo(token_name, user_pin); | 758 g_nss_singleton.Get().GetTPMTokenInfo(token_name, user_pin); |
748 } | 759 } |
749 | 760 |
750 bool IsTPMTokenReady() { | 761 bool IsTPMTokenReady() { |
751 return g_nss_singleton.Get().IsTPMTokenReady(); | 762 return g_nss_singleton.Get().IsTPMTokenReady(); |
752 } | 763 } |
753 | 764 |
754 bool InitializeTPMToken(const std::string& token_name, | 765 bool InitializeTPMToken(const std::string& token_name, |
| 766 int token_slot_id, |
755 const std::string& user_pin) { | 767 const std::string& user_pin) { |
756 return g_nss_singleton.Get().InitializeTPMToken(token_name, user_pin); | 768 return g_nss_singleton.Get().InitializeTPMToken( |
| 769 token_name, token_slot_id, user_pin); |
757 } | 770 } |
758 #endif // defined(OS_CHROMEOS) | 771 #endif // defined(OS_CHROMEOS) |
759 | 772 |
760 base::Time PRTimeToBaseTime(PRTime prtime) { | 773 base::Time PRTimeToBaseTime(PRTime prtime) { |
761 return base::Time::FromInternalValue( | 774 return base::Time::FromInternalValue( |
762 prtime + base::Time::UnixEpoch().ToInternalValue()); | 775 prtime + base::Time::UnixEpoch().ToInternalValue()); |
763 } | 776 } |
764 | 777 |
765 PRTime BaseTimeToPRTime(base::Time time) { | 778 PRTime BaseTimeToPRTime(base::Time time) { |
766 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); | 779 return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); |
767 } | 780 } |
768 | 781 |
769 PK11SlotInfo* GetPublicNSSKeySlot() { | 782 PK11SlotInfo* GetPublicNSSKeySlot() { |
770 return g_nss_singleton.Get().GetPublicNSSKeySlot(); | 783 return g_nss_singleton.Get().GetPublicNSSKeySlot(); |
771 } | 784 } |
772 | 785 |
773 PK11SlotInfo* GetPrivateNSSKeySlot() { | 786 PK11SlotInfo* GetPrivateNSSKeySlot() { |
774 return g_nss_singleton.Get().GetPrivateNSSKeySlot(); | 787 return g_nss_singleton.Get().GetPrivateNSSKeySlot(); |
775 } | 788 } |
776 | 789 |
777 } // namespace crypto | 790 } // namespace crypto |
OLD | NEW |