15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/nss_cert_database.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cert.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <certdb.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <keyhi.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11pub.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <secmod.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/callback.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/lazy_instance.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list_threadsafe.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task_runner.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/task_runner_util.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/worker_pool.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util_internal.h" 241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "crypto/scoped_nss_types.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/crypto_module.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_database.h" 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In NSS 3.13, CERTDB_VALID_PEER was renamed CERTDB_TERMINAL_RECORD. So we use 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the new name of the macro. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(CERTDB_TERMINAL_RECORD) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PSM = Mozilla's Personal Security Manager. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace psm = mozilla_security_manager; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::LazyInstance<NSSCertDatabase>::Leaky 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_nss_cert_database = LAZY_INSTANCE_INITIALIZER; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::ImportCertFailure::ImportCertFailure( 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const scoped_refptr<X509Certificate>& cert, 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int err) 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : certificate(cert), net_error(err) {} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase* NSSCertDatabase::GetInstance() { 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(mattm): Remove this ifdef guard once the linux impl of 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // GetNSSCertDatabaseForResourceContext does not call GetInstance. 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS) 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "NSSCertDatabase::GetInstance() is deprecated." 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "See http://crbug.com/329735."; 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return &g_nss_cert_database.Get(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::NSSCertDatabase() 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : observer_list_(new ObserverListThreadSafe<Observer>), 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_factory_(this) { 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This also makes sure that NSS has been initialized. 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CertDatabase::GetInstance()->ObserveNSSCertDatabase(this); 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) psm::EnsurePKCS12Init(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::~NSSCertDatabase() {} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NSSCertDatabase::ListCertsSync(CertificateList* certs) { 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ListCertsImpl(crypto::ScopedPK11Slot(), certs); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NSSCertDatabase::ListCerts( 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(scoped_ptr<CertificateList> certs)>& callback) { 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<CertificateList> certs(new CertificateList()); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // base::Passed will NULL out |certs|, so cache the underlying pointer here. 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CertificateList* raw_certs = certs.get(); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetSlowTaskRunner()->PostTaskAndReply( 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&NSSCertDatabase::ListCertsImpl, 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Passed(crypto::ScopedPK11Slot()), 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Unretained(raw_certs)), 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(callback, base::Passed(&certs))); 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NSSCertDatabase::ListCertsInSlot(const ListCertsCallback& callback, 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PK11SlotInfo* slot) { 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(slot); 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<CertificateList> certs(new CertificateList()); 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // base::Passed will NULL out |certs|, so cache the underlying pointer here. 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CertificateList* raw_certs = certs.get(); 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetSlowTaskRunner()->PostTaskAndReply( 105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&NSSCertDatabase::ListCertsImpl, 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Passed(crypto::ScopedPK11Slot(PK11_ReferenceSlot(slot))), 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(raw_certs)), 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, base::Passed(&certs))); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const { 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()); 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const { 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)CryptoModule* NSSCertDatabase::GetPublicModule() const { 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) crypto::ScopedPK11Slot slot(GetPublicSlot()); 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return CryptoModule::CreateFromHandle(slot.get()); 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)CryptoModule* NSSCertDatabase::GetPrivateModule() const { 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) crypto::ScopedPK11Slot slot(GetPrivateSlot()); 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return CryptoModule::CreateFromHandle(slot.get()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::ListModules(CryptoModuleList* modules, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool need_rw) const { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modules->clear(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) crypto::ScopedPK11SlotList slot_list( 1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) PK11_GetAllTokens(CKM_INVALID_MECHANISM, 1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) need_rw ? PR_TRUE : PR_FALSE, // needRW 1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) PR_TRUE, // loadCerts (unused) 1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NULL)); // wincx 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!slot_list) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list.get()); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (slot_element) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); 1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) slot_element = PK11_GetNextSafe(slot_list.get(), slot_element, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PR_FALSE); // restart 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NSSCertDatabase::ImportFromPKCS12( 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CryptoModule* module, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& password, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_extractable, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CertificateList* imported_certs) { 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << __func__ << " " 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << PK11_GetModuleID(module->os_module_handle()) << ":" 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << PK11_GetSlotID(module->os_module_handle()); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.data(), data.size(), 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_extractable, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) imported_certs); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == net::OK) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyObserversOfCertAdded(NULL); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NSSCertDatabase::ExportToPKCS12( 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CertificateList& certs, 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& password, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) const { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return psm::nsPKCS12Blob_Export(output, certs, password); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate* NSSCertDatabase::FindRootInList( 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CertificateList& certificates) const { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(certificates.size(), 0U); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (certificates.size() == 1) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return certificates[0].get(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) X509Certificate* cert0 = certificates[0].get(); 188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) X509Certificate* cert1 = certificates[1].get(); 189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) X509Certificate* certn_2 = certificates[certificates.size() - 2].get(); 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) X509Certificate* certn_1 = certificates[certificates.size() - 1].get(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CERT_CompareName(&cert1->os_cert_handle()->issuer, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert0->os_cert_handle()->subject) == SECEqual) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert0; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CERT_CompareName(&certn_2->os_cert_handle()->issuer, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &certn_1->os_cert_handle()->subject) == SECEqual) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return certn_1; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(WARNING) << "certificate list is not a hierarchy"; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert0; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrustBits trust_bits, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImportCertFailureList* not_imported) { 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) crypto::ScopedPK11Slot slot(GetPublicSlot()); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate* root = FindRootInList(certificates); 208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool success = psm::ImportCACerts( 209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) slot.get(), certificates, root, trust_bits, not_imported); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) 2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NotifyObserversOfCACertChanged(NULL); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrustBits trust_bits, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImportCertFailureList* not_imported) { 219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) crypto::ScopedPK11Slot slot(GetPublicSlot()); 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return psm::ImportServerCert( 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) slot.get(), certificates, trust_bits, not_imported); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust( 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const X509Certificate* cert, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertType type) const { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertTrust trust; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (srv != SECSuccess) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUST_DEFAULT; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We define our own more "friendly" TrustBits, which means we aren't able to 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // round-trip all possible NSS trust flag combinations. We try to map them in 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a sensible way. 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CA_CERT: { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned kTrustedCA = CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned kCAFlags = kTrustedCA | CERTDB_TERMINAL_RECORD; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrustBits trust_bits = TRUST_DEFAULT; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((trust.sslFlags & kCAFlags) == CERTDB_TERMINAL_RECORD) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= DISTRUSTED_SSL; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (trust.sslFlags & kTrustedCA) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= TRUSTED_SSL; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((trust.emailFlags & kCAFlags) == CERTDB_TERMINAL_RECORD) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= DISTRUSTED_EMAIL; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (trust.emailFlags & kTrustedCA) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= TRUSTED_EMAIL; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((trust.objectSigningFlags & kCAFlags) == CERTDB_TERMINAL_RECORD) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= DISTRUSTED_OBJ_SIGN; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (trust.objectSigningFlags & kTrustedCA) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= TRUSTED_OBJ_SIGN; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return trust_bits; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SERVER_CERT: 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trust.sslFlags & CERTDB_TERMINAL_RECORD) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trust.sslFlags & CERTDB_TRUSTED) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUSTED_SSL; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DISTRUSTED_SSL; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUST_DEFAULT; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUST_DEFAULT; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::IsUntrusted(const X509Certificate* cert) const { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertTrust nsstrust; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The CERTCertTrust structure contains three trust records: 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sslFlags, emailFlags, and objectSigningFlags. The three 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // trust records are independent of each other. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the CERTDB_TERMINAL_RECORD bit in a trust record is set, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then that trust record is a terminal record. A terminal 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // record is used for explicit trust and distrust of an 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // end-entity or intermediate CA cert. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In a terminal record, if neither CERTDB_TRUSTED_CA nor 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CERTDB_TRUSTED is set, then the terminal record means 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicit distrust. On the other hand, if the terminal 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // record has either CERTDB_TRUSTED_CA or CERTDB_TRUSTED bit 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set, then the terminal record means explicit trust. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For a root CA, the trust record does not have 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the CERTDB_TERMINAL_RECORD bit set. 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const unsigned int kTrusted = CERTDB_TRUSTED_CA | CERTDB_TRUSTED; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((nsstrust.sslFlags & CERTDB_TERMINAL_RECORD) != 0 && 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.sslFlags & kTrusted) == 0) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((nsstrust.emailFlags & CERTDB_TERMINAL_RECORD) != 0 && 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.emailFlags & kTrusted) == 0) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((nsstrust.objectSigningFlags & CERTDB_TERMINAL_RECORD) != 0 && 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.objectSigningFlags & kTrusted) == 0) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Self-signed certificates that don't have any trust bits set are untrusted. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Other certificates that don't have any trust bits set may still be trusted 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if they chain up to a trust anchor. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CERT_CompareName(&cert->os_cert_handle()->issuer, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert->os_cert_handle()->subject) == SECEqual) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (nsstrust.sslFlags & kTrusted) == 0 && 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.emailFlags & kTrusted) == 0 && 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.objectSigningFlags & kTrusted) == 0; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertType type, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrustBits trust_bits) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = psm::SetCertTrust(cert, type, trust_bits); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) 3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NotifyObserversOfCACertChanged(cert); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool NSSCertDatabase::DeleteCertAndKey(X509Certificate* cert) { 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!DeleteCertAndKeyImpl(cert)) 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyObserversOfCertRemoved(cert); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NSSCertDatabase::DeleteCertAndKeyAsync( 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const scoped_refptr<X509Certificate>& cert, 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DeleteCertCallback& callback) { 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::PostTaskAndReplyWithResult( 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetSlowTaskRunner().get(), 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&NSSCertDatabase::DeleteCertAndKeyImpl, cert), 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&NSSCertDatabase::NotifyCertRemovalAndCallBack, 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_factory_.GetWeakPtr(), 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cert, 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback)); 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SlotInfo* slot = cert->os_cert_handle()->slot; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return slot && PK11_IsReadOnly(slot); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool NSSCertDatabase::IsHardwareBacked(const X509Certificate* cert) const { 360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PK11SlotInfo* slot = cert->os_cert_handle()->slot; 361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return slot && PK11_IsHW(slot); 362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::AddObserver(Observer* observer) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->AddObserver(observer); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::RemoveObserver(Observer* observer) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->RemoveObserver(observer); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NSSCertDatabase::SetSlowTaskRunnerForTest( 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::TaskRunner>& task_runner) { 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) slow_task_runner_for_test_ = task_runner; 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NSSCertDatabase::ListCertsImpl(crypto::ScopedPK11Slot slot, 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CertificateList* certs) { 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) certs->clear(); 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CERTCertList* cert_list = NULL; 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (slot) 384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cert_list = PK11_ListCertsInSlot(slot.get()); 385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cert_list = PK11_ListCerts(PK11CertListUnique, NULL); 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CERTCertListNode* node; 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) node = CERT_LIST_NEXT(node)) { 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) certs->push_back(X509Certificate::CreateFromHandle( 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) node->cert, X509Certificate::OSCertHandles())); 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CERT_DestroyCertList(cert_list); 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<base::TaskRunner> NSSCertDatabase::GetSlowTaskRunner() const { 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (slow_task_runner_for_test_) 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return slow_task_runner_for_test_; 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::WorkerPool::GetTaskRunner(true /*task is slow*/); 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NSSCertDatabase::NotifyCertRemovalAndCallBack( 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<X509Certificate> cert, 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DeleteCertCallback& callback, 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool success) { 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (success) 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NotifyObserversOfCertRemoved(cert); 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback.Run(success); 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert)); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::NotifyObserversOfCertRemoved( 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const X509Certificate* cert) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert)); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void NSSCertDatabase::NotifyObserversOfCACertChanged( 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const X509Certificate* cert) { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->Notify( 4241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) &Observer::OnCACertChanged, make_scoped_refptr(cert)); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool NSSCertDatabase::DeleteCertAndKeyImpl( 429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<X509Certificate> cert) { 430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // For some reason, PK11_DeleteTokenCertAndKey only calls 431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // SEC_DeletePermCertificate if the private key is found. So, we check 432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // whether a private key exists before deciding which function to call to 433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // delete the cert. 434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SECKEYPrivateKey* privKey = 435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PK11_FindKeyByAnyCert(cert->os_cert_handle(), NULL); 436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (privKey) { 437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SECKEY_DestroyPrivateKey(privKey); 438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { 439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); 440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (SEC_DeletePermCertificate(cert->os_cert_handle())) { 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 452