1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_database.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <cert.h>
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <certdb.h>
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <keyhi.h>
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <pk11pub.h>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <secmod.h>
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/nss_util.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/nss_util_internal.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/base/crypto_module.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/x509_certificate.h"
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/third_party/mozilla_security_manager/nsNSSCertTrust.h"
223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h"
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// PSM = Mozilla's Personal Security Manager.
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace psm = mozilla_security_manager;
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCertDatabase::CertDatabase() {
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::EnsureNSSInit();
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  psm::EnsurePKCS12Init();
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CertDatabase::CheckUserCert(X509Certificate* cert_obj) {
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!cert_obj)
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_CERT_INVALID;
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cert_obj->HasExpired())
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_CERT_DATE_INVALID;
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check if the private key corresponding to the certificate exist
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We shouldn't accept any random client certificate sent by a CA.
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Note: The NSS source documentation wrongly suggests that this
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // also imports the certificate if the private key exists. This
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // doesn't seem to be the case.
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CERTCertificate* cert = cert_obj->os_cert_handle();
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PK11SlotInfo* slot = PK11_KeyForCertExists(cert, NULL, NULL);
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!slot) {
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "No corresponding private key in store";
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_NO_PRIVATE_KEY_FOR_CERT;
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PK11_FreeSlot(slot);
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CertDatabase::AddUserCert(X509Certificate* cert_obj) {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CERTCertificate* cert = cert_obj->os_cert_handle();
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PK11SlotInfo* slot = NULL;
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string nickname;
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Create a nickname for this certificate.
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We use the scheme used by Firefox:
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // --> <subject's common name>'s <issuer's common name> ID.
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string username, ca_name;
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char* temp_username = CERT_GetCommonName(&cert->subject);
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char* temp_ca_name = CERT_GetCommonName(&cert->issuer);
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (temp_username) {
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    username = temp_username;
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PORT_Free(temp_username);
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (temp_ca_name) {
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ca_name = temp_ca_name;
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PORT_Free(temp_ca_name);
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  nickname = username + "'s " + ca_name + " ID";
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    crypto::AutoNSSWriteLock lock;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    slot = PK11_ImportCertForKey(cert,
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 const_cast<char*>(nickname.c_str()),
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 NULL);
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!slot) {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Couldn't import user certificate.";
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_ADD_USER_CERT_FAILED;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PK11_FreeSlot(slot);
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CertDatabase::NotifyObserversOfUserCertAdded(cert_obj);
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid CertDatabase::ListCerts(CertificateList* certs) {
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  certs->clear();
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL);
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CERTCertListNode* node;
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (node = CERT_LIST_HEAD(cert_list);
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       !CERT_LIST_END(node, cert_list);
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       node = CERT_LIST_NEXT(node)) {
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    certs->push_back(X509Certificate::CreateFromHandle(
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        node->cert,
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        X509Certificate::SOURCE_LONE_CERT_IMPORT,
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        X509Certificate::OSCertHandles()));
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CERT_DestroyCertList(cert_list);
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenCryptoModule* CertDatabase::GetPublicModule() const {
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CryptoModule* module =
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CryptoModule::CreateFromHandle(crypto::GetPublicNSSKeySlot());
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The module is already referenced when returned from
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // GetPublicNSSKeySlot, so we need to deref it once.
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PK11_FreeSlot(module->os_module_handle());
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return module;
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenCryptoModule* CertDatabase::GetPrivateModule() const {
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CryptoModule* module =
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      CryptoModule::CreateFromHandle(crypto::GetPrivateNSSKeySlot());
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The module is already referenced when returned from
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // GetPrivateNSSKeySlot, so we need to deref it once.
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  PK11_FreeSlot(module->os_module_handle());
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return module;
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CertDatabase::ListModules(CryptoModuleList* modules, bool need_rw) const {
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  modules->clear();
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PK11SlotList* slot_list = NULL;
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  slot_list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                need_rw ? PR_TRUE : PR_FALSE,  // needRW
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                PR_TRUE,  // loadCerts (unused)
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                NULL);  // wincx
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!slot_list) {
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError();
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list);
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  while (slot_element) {
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot));
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    slot_element = PK11_GetNextSafe(slot_list, slot_element,
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    PR_FALSE);  // restart
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  PK11_FreeSlotList(slot_list);
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint CertDatabase::ImportFromPKCS12(
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CryptoModule* module,
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string& data,
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& password) {
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int result = psm::nsPKCS12Blob_Import(module->os_module_handle(),
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        data.data(), data.size(),
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        password);
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (result == net::OK)
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CertDatabase::NotifyObserversOfUserCertAdded(NULL);
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return result;
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint CertDatabase::ExportToPKCS12(
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const CertificateList& certs,
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& password,
172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::string* output) const {
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return psm::nsPKCS12Blob_Export(output, certs, password);
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickX509Certificate* CertDatabase::FindRootInList(
177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const CertificateList& certificates) const {
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GT(certificates.size(), 0U);
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (certificates.size() == 1)
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return certificates[0].get();
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  X509Certificate* cert0 = certificates[0];
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  X509Certificate* cert1 = certificates[1];
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  X509Certificate* certn_2 = certificates[certificates.size() - 2];
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  X509Certificate* certn_1 = certificates[certificates.size() - 1];
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (CERT_CompareName(&cert1->os_cert_handle()->issuer,
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       &cert0->os_cert_handle()->subject) == SECEqual)
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return cert0;
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (CERT_CompareName(&certn_2->os_cert_handle()->issuer,
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       &certn_1->os_cert_handle()->subject) == SECEqual)
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return certn_1;
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  VLOG(1) << "certificate list is not a hierarchy";
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return cert0;
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool CertDatabase::ImportCACerts(const CertificateList& certificates,
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                 unsigned int trust_bits,
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                 ImportCertFailureList* not_imported) {
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  X509Certificate* root = FindRootInList(certificates);
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool success = psm::ImportCACerts(certificates, root, trust_bits,
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    not_imported);
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (success)
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CertDatabase::NotifyObserversOfCertTrustChanged(NULL);
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return success;
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool CertDatabase::ImportServerCert(const CertificateList& certificates,
212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                    ImportCertFailureList* not_imported) {
213731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return psm::ImportServerCert(certificates, not_imported);
214731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
215731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
216731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickunsigned int CertDatabase::GetCertTrust(
217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const X509Certificate* cert, CertType type) const {
218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  CERTCertTrust nsstrust;
219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust);
220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (srv != SECSuccess) {
221731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError();
222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return UNTRUSTED;
223731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
224731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  psm::nsNSSCertTrust trust(&nsstrust);
225731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  switch (type) {
226731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case CA_CERT:
227731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return trust.HasTrustedCA(PR_TRUE, PR_FALSE, PR_FALSE) * TRUSTED_SSL +
228731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          trust.HasTrustedCA(PR_FALSE, PR_TRUE, PR_FALSE) * TRUSTED_EMAIL +
229731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          trust.HasTrustedCA(PR_FALSE, PR_FALSE, PR_TRUE) * TRUSTED_OBJ_SIGN;
230731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case SERVER_CERT:
231731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return trust.HasTrustedPeer(PR_TRUE, PR_FALSE, PR_FALSE) * TRUSTED_SSL +
232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          trust.HasTrustedPeer(PR_FALSE, PR_TRUE, PR_FALSE) * TRUSTED_EMAIL +
233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          trust.HasTrustedPeer(PR_FALSE, PR_FALSE, PR_TRUE) * TRUSTED_OBJ_SIGN;
234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    default:
235731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return UNTRUSTED;
236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool CertDatabase::SetCertTrust(const X509Certificate* cert,
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                CertType type,
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                unsigned int trusted) {
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool success = psm::SetCertTrust(cert, type, trusted);
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (success)
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CertDatabase::NotifyObserversOfCertTrustChanged(cert);
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return success;
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(xiyuan): Add an Observer method for this event.
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) {
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // For some reason, PK11_DeleteTokenCertAndKey only calls
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // SEC_DeletePermCertificate if the private key is found.  So, we check
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // whether a private key exists before deciding which function to call to
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // delete the cert.
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(),
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                    NULL);
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (privKey) {
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SECKEY_DestroyPrivateKey(privKey);
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) {
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError();
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return false;
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (SEC_DeletePermCertificate(cert->os_cert_handle())) {
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError();
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return false;
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
272513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool CertDatabase::IsReadOnly(const X509Certificate* cert) const {
273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  PK11SlotInfo* slot = cert->os_cert_handle()->slot;
274513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return slot && PK11_IsReadOnly(slot);
275513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
276513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
278