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