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" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list_threadsafe.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task_runner.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/task_runner_util.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/worker_pool.h" 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "crypto/scoped_nss_types.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/crypto_module.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_database.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In NSS 3.13, CERTDB_VALID_PEER was renamed CERTDB_TERMINAL_RECORD. So we use 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the new name of the macro. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(CERTDB_TERMINAL_RECORD) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PSM = Mozilla's Personal Security Manager. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace psm = mozilla_security_manager; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(pneubeck): Move this class out of NSSCertDatabase and to the caller of 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the c'tor of NSSCertDatabase, see https://crbug.com/395983 . 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Helper that observes events from the NSSCertDatabase and forwards them to 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// the given CertDatabase. 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass CertNotificationForwarder : public NSSCertDatabase::Observer { 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public: 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch explicit CertNotificationForwarder(CertDatabase* cert_db) 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : cert_db_(cert_db) {} 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual ~CertNotificationForwarder() {} 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // NSSCertDatabase::Observer implementation: 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE { 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cert_db_->NotifyObserversOfCertAdded(cert); 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void OnCertRemoved(const X509Certificate* cert) OVERRIDE { 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cert_db_->NotifyObserversOfCertRemoved(cert); 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE { 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cert_db_->NotifyObserversOfCACertChanged(cert); 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private: 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CertDatabase* cert_db_; 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DISALLOW_COPY_AND_ASSIGN(CertNotificationForwarder); 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::ImportCertFailure::ImportCertFailure( 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const scoped_refptr<X509Certificate>& cert, 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int err) 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : certificate(cert), net_error(err) {} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)NSSCertDatabase::NSSCertDatabase(crypto::ScopedPK11Slot public_slot, 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) crypto::ScopedPK11Slot private_slot) 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : public_slot_(public_slot.Pass()), 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private_slot_(private_slot.Pass()), 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) observer_list_(new ObserverListThreadSafe<Observer>), 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_factory_(this) { 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(public_slot_); 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This also makes sure that NSS has been initialized. 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CertDatabase* cert_db = CertDatabase::GetInstance(); 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cert_notification_forwarder_.reset(new CertNotificationForwarder(cert_db)); 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AddObserver(cert_notification_forwarder_.get()); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) psm::EnsurePKCS12Init(); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::~NSSCertDatabase() {} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NSSCertDatabase::ListCertsSync(CertificateList* certs) { 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ListCertsImpl(crypto::ScopedPK11Slot(), certs); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NSSCertDatabase::ListCerts( 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(scoped_ptr<CertificateList> certs)>& callback) { 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<CertificateList> certs(new CertificateList()); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // base::Passed will NULL out |certs|, so cache the underlying pointer here. 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CertificateList* raw_certs = certs.get(); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetSlowTaskRunner()->PostTaskAndReply( 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&NSSCertDatabase::ListCertsImpl, 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Passed(crypto::ScopedPK11Slot()), 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Unretained(raw_certs)), 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(callback, base::Passed(&certs))); 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NSSCertDatabase::ListCertsInSlot(const ListCertsCallback& callback, 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PK11SlotInfo* slot) { 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(slot); 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<CertificateList> certs(new CertificateList()); 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // base::Passed will NULL out |certs|, so cache the underlying pointer here. 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CertificateList* raw_certs = certs.get(); 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetSlowTaskRunner()->PostTaskAndReply( 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&NSSCertDatabase::ListCertsImpl, 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Passed(crypto::ScopedPK11Slot(PK11_ReferenceSlot(slot))), 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(raw_certs)), 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(callback, base::Passed(&certs))); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_CHROMEOS) 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)crypto::ScopedPK11Slot NSSCertDatabase::GetSystemSlot() const { 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return crypto::ScopedPK11Slot(); 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const { 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return crypto::ScopedPK11Slot(PK11_ReferenceSlot(public_slot_.get())); 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const { 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!private_slot_) 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return crypto::ScopedPK11Slot(); 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return crypto::ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get())); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)CryptoModule* NSSCertDatabase::GetPublicModule() const { 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) crypto::ScopedPK11Slot slot(GetPublicSlot()); 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return CryptoModule::CreateFromHandle(slot.get()); 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)CryptoModule* NSSCertDatabase::GetPrivateModule() const { 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) crypto::ScopedPK11Slot slot(GetPrivateSlot()); 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return CryptoModule::CreateFromHandle(slot.get()); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::ListModules(CryptoModuleList* modules, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool need_rw) const { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modules->clear(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc. 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) crypto::ScopedPK11SlotList slot_list( 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) PK11_GetAllTokens(CKM_INVALID_MECHANISM, 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) need_rw ? PR_TRUE : PR_FALSE, // needRW 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) PR_TRUE, // loadCerts (unused) 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NULL)); // wincx 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!slot_list) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list.get()); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (slot_element) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot)); 1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) slot_element = PK11_GetNextSafe(slot_list.get(), slot_element, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PR_FALSE); // restart 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NSSCertDatabase::ImportFromPKCS12( 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CryptoModule* module, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data, 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& password, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_extractable, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CertificateList* imported_certs) { 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << __func__ << " " 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << PK11_GetModuleID(module->os_module_handle()) << ":" 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << PK11_GetSlotID(module->os_module_handle()); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = psm::nsPKCS12Blob_Import(module->os_module_handle(), 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.data(), data.size(), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_extractable, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) imported_certs); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == net::OK) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyObserversOfCertAdded(NULL); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NSSCertDatabase::ExportToPKCS12( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CertificateList& certs, 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& password, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) const { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return psm::nsPKCS12Blob_Export(output, certs, password); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate* NSSCertDatabase::FindRootInList( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CertificateList& certificates) const { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(certificates.size(), 0U); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (certificates.size() == 1) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return certificates[0].get(); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) X509Certificate* cert0 = certificates[0].get(); 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) X509Certificate* cert1 = certificates[1].get(); 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) X509Certificate* certn_2 = certificates[certificates.size() - 2].get(); 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) X509Certificate* certn_1 = certificates[certificates.size() - 1].get(); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CERT_CompareName(&cert1->os_cert_handle()->issuer, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert0->os_cert_handle()->subject) == SECEqual) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert0; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CERT_CompareName(&certn_2->os_cert_handle()->issuer, 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &certn_1->os_cert_handle()->subject) == SECEqual) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return certn_1; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(WARNING) << "certificate list is not a hierarchy"; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cert0; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrustBits trust_bits, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImportCertFailureList* not_imported) { 234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) crypto::ScopedPK11Slot slot(GetPublicSlot()); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate* root = FindRootInList(certificates); 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool success = psm::ImportCACerts( 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) slot.get(), certificates, root, trust_bits, not_imported); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) 2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NotifyObserversOfCACertChanged(NULL); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates, 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrustBits trust_bits, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImportCertFailureList* not_imported) { 247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) crypto::ScopedPK11Slot slot(GetPublicSlot()); 248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return psm::ImportServerCert( 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) slot.get(), certificates, trust_bits, not_imported); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust( 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const X509Certificate* cert, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertType type) const { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertTrust trust; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &trust); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (srv != SECSuccess) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUST_DEFAULT; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We define our own more "friendly" TrustBits, which means we aren't able to 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // round-trip all possible NSS trust flag combinations. We try to map them in 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a sensible way. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CA_CERT: { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned kTrustedCA = CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned kCAFlags = kTrustedCA | CERTDB_TERMINAL_RECORD; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrustBits trust_bits = TRUST_DEFAULT; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((trust.sslFlags & kCAFlags) == CERTDB_TERMINAL_RECORD) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= DISTRUSTED_SSL; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (trust.sslFlags & kTrustedCA) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= TRUSTED_SSL; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((trust.emailFlags & kCAFlags) == CERTDB_TERMINAL_RECORD) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= DISTRUSTED_EMAIL; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (trust.emailFlags & kTrustedCA) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= TRUSTED_EMAIL; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((trust.objectSigningFlags & kCAFlags) == CERTDB_TERMINAL_RECORD) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= DISTRUSTED_OBJ_SIGN; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (trust.objectSigningFlags & kTrustedCA) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trust_bits |= TRUSTED_OBJ_SIGN; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return trust_bits; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SERVER_CERT: 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trust.sslFlags & CERTDB_TERMINAL_RECORD) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trust.sslFlags & CERTDB_TRUSTED) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUSTED_SSL; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DISTRUSTED_SSL; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUST_DEFAULT; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUST_DEFAULT; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::IsUntrusted(const X509Certificate* cert) const { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertTrust nsstrust; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The CERTCertTrust structure contains three trust records: 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sslFlags, emailFlags, and objectSigningFlags. The three 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // trust records are independent of each other. 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the CERTDB_TERMINAL_RECORD bit in a trust record is set, 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then that trust record is a terminal record. A terminal 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // record is used for explicit trust and distrust of an 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // end-entity or intermediate CA cert. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In a terminal record, if neither CERTDB_TRUSTED_CA nor 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CERTDB_TRUSTED is set, then the terminal record means 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicit distrust. On the other hand, if the terminal 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // record has either CERTDB_TRUSTED_CA or CERTDB_TRUSTED bit 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set, then the terminal record means explicit trust. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For a root CA, the trust record does not have 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the CERTDB_TERMINAL_RECORD bit set. 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const unsigned int kTrusted = CERTDB_TRUSTED_CA | CERTDB_TRUSTED; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((nsstrust.sslFlags & CERTDB_TERMINAL_RECORD) != 0 && 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.sslFlags & kTrusted) == 0) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((nsstrust.emailFlags & CERTDB_TERMINAL_RECORD) != 0 && 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.emailFlags & kTrusted) == 0) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((nsstrust.objectSigningFlags & CERTDB_TERMINAL_RECORD) != 0 && 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.objectSigningFlags & kTrusted) == 0) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Self-signed certificates that don't have any trust bits set are untrusted. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Other certificates that don't have any trust bits set may still be trusted 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if they chain up to a trust anchor. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CERT_CompareName(&cert->os_cert_handle()->issuer, 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cert->os_cert_handle()->subject) == SECEqual) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (nsstrust.sslFlags & kTrusted) == 0 && 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.emailFlags & kTrusted) == 0 && 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nsstrust.objectSigningFlags & kTrusted) == 0; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertType type, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrustBits trust_bits) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = psm::SetCertTrust(cert, type, trust_bits); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) 3571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NotifyObserversOfCACertChanged(cert); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool NSSCertDatabase::DeleteCertAndKey(X509Certificate* cert) { 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!DeleteCertAndKeyImpl(cert)) 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyObserversOfCertRemoved(cert); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NSSCertDatabase::DeleteCertAndKeyAsync( 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const scoped_refptr<X509Certificate>& cert, 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DeleteCertCallback& callback) { 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::PostTaskAndReplyWithResult( 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetSlowTaskRunner().get(), 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&NSSCertDatabase::DeleteCertAndKeyImpl, cert), 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&NSSCertDatabase::NotifyCertRemovalAndCallBack, 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) weak_factory_.GetWeakPtr(), 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cert, 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback)); 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SlotInfo* slot = cert->os_cert_handle()->slot; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return slot && PK11_IsReadOnly(slot); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool NSSCertDatabase::IsHardwareBacked(const X509Certificate* cert) const { 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PK11SlotInfo* slot = cert->os_cert_handle()->slot; 389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return slot && PK11_IsHW(slot); 390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::AddObserver(Observer* observer) { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->AddObserver(observer); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::RemoveObserver(Observer* observer) { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->RemoveObserver(observer); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NSSCertDatabase::SetSlowTaskRunnerForTest( 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::TaskRunner>& task_runner) { 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) slow_task_runner_for_test_ = task_runner; 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NSSCertDatabase::ListCertsImpl(crypto::ScopedPK11Slot slot, 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CertificateList* certs) { 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) certs->clear(); 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CERTCertList* cert_list = NULL; 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (slot) 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cert_list = PK11_ListCertsInSlot(slot.get()); 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cert_list = PK11_ListCerts(PK11CertListUnique, NULL); 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CERTCertListNode* node; 417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) node = CERT_LIST_NEXT(node)) { 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) certs->push_back(X509Certificate::CreateFromHandle( 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) node->cert, X509Certificate::OSCertHandles())); 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CERT_DestroyCertList(cert_list); 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<base::TaskRunner> NSSCertDatabase::GetSlowTaskRunner() const { 4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (slow_task_runner_for_test_.get()) 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return slow_task_runner_for_test_; 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::WorkerPool::GetTaskRunner(true /*task is slow*/); 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void NSSCertDatabase::NotifyCertRemovalAndCallBack( 432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<X509Certificate> cert, 433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const DeleteCertCallback& callback, 434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool success) { 435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (success) 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NotifyObserversOfCertRemoved(cert.get()); 437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) callback.Run(success); 438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert)); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NSSCertDatabase::NotifyObserversOfCertRemoved( 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const X509Certificate* cert) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert)); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void NSSCertDatabase::NotifyObserversOfCACertChanged( 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const X509Certificate* cert) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer_list_->Notify( 4521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) &Observer::OnCACertChanged, make_scoped_refptr(cert)); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool NSSCertDatabase::DeleteCertAndKeyImpl( 457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<X509Certificate> cert) { 458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // For some reason, PK11_DeleteTokenCertAndKey only calls 459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // SEC_DeletePermCertificate if the private key is found. So, we check 460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // whether a private key exists before deciding which function to call to 461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // delete the cert. 462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SECKEYPrivateKey* privKey = 463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PK11_FindKeyByAnyCert(cert->os_cert_handle(), NULL); 464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (privKey) { 465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SECKEY_DestroyPrivateKey(privKey); 466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { 467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); 468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (SEC_DeletePermCertificate(cert->os_cert_handle())) { 472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); 473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 480