cert_database_nss.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 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" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/nss_util.h" 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/scoped_ptr.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/x509_certificate.h" 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/third_party/mozilla_security_manager/nsNSSCertTrust.h" 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// PSM = Mozilla's Personal Security Manager. 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace psm = mozilla_security_manager; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCertDatabase::CertDatabase() { 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::EnsureNSSInit(); 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick psm::EnsurePKCS12Init(); 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CertDatabase::CheckUserCert(X509Certificate* cert_obj) { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!cert_obj) 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_CERT_INVALID; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cert_obj->HasExpired()) 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_CERT_DATE_INVALID; 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check if the private key corresponding to the certificate exist 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We shouldn't accept any random client certificate sent by a CA. 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: The NSS source documentation wrongly suggests that this 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // also imports the certificate if the private key exists. This 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // doesn't seem to be the case. 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CERTCertificate* cert = cert_obj->os_cert_handle(); 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11SlotInfo* slot = PK11_KeyForCertExists(cert, NULL, NULL); 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!slot) { 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "No corresponding private key in store"; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_NO_PRIVATE_KEY_FOR_CERT; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PK11_FreeSlot(slot); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CertDatabase::AddUserCert(X509Certificate* cert_obj) { 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CERTCertificate* cert = cert_obj->os_cert_handle(); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11SlotInfo* slot = NULL; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string nickname; 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Create a nickname for this certificate. 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We use the scheme used by Firefox: 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // --> <subject's common name>'s <issuer's common name> ID. 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string username, ca_name; 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* temp_username = CERT_GetCommonName(&cert->subject); 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* temp_ca_name = CERT_GetCommonName(&cert->issuer); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (temp_username) { 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott username = temp_username; 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PORT_Free(temp_username); 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (temp_ca_name) { 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ca_name = temp_ca_name; 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PORT_Free(temp_ca_name); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nickname = username + "'s " + ca_name + " ID"; 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::AutoNSSWriteLock lock; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch slot = PK11_ImportCertForKey(cert, 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const_cast<char*>(nickname.c_str()), 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!slot) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Couldn't import user certificate."; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_ADD_USER_CERT_FAILED; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11_FreeSlot(slot); 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid CertDatabase::ListCerts(CertificateList* certs) { 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick certs->clear(); 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CERTCertList* cert_list = PK11_ListCerts(PK11CertListUnique, NULL); 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CERTCertListNode* node; 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (node = CERT_LIST_HEAD(cert_list); 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !CERT_LIST_END(node, cert_list); 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick node = CERT_LIST_NEXT(node)) { 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick certs->push_back(X509Certificate::CreateFromHandle( 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick node->cert, 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate::SOURCE_LONE_CERT_IMPORT, 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate::OSCertHandles())); 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CERT_DestroyCertList(cert_list); 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint CertDatabase::ImportFromPKCS12( 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& data, const string16& password) { 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return psm::nsPKCS12Blob_Import(data.data(), data.size(), password); 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint CertDatabase::ExportToPKCS12( 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const CertificateList& certs, 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& password, 117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string* output) const { 1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return psm::nsPKCS12Blob_Export(output, certs, password); 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickX509Certificate* CertDatabase::FindRootInList( 122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const CertificateList& certificates) const { 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GT(certificates.size(), 0U); 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (certificates.size() == 1) 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return certificates[0].get(); 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate* cert0 = certificates[0]; 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate* cert1 = certificates[1]; 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate* certn_2 = certificates[certificates.size() - 2]; 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate* certn_1 = certificates[certificates.size() - 1]; 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (CERT_CompareName(&cert1->os_cert_handle()->issuer, 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &cert0->os_cert_handle()->subject) == SECEqual) 1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return cert0; 1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (CERT_CompareName(&certn_2->os_cert_handle()->issuer, 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &certn_1->os_cert_handle()->subject) == SECEqual) 1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return certn_1; 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "certificate list is not a hierarchy"; 1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return cert0; 1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool CertDatabase::ImportCACerts(const CertificateList& certificates, 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick unsigned int trust_bits, 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ImportCertFailureList* not_imported) { 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate* root = FindRootInList(certificates); 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return psm::ImportCACerts(certificates, root, trust_bits, not_imported); 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool CertDatabase::ImportServerCert(const CertificateList& certificates, 152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ImportCertFailureList* not_imported) { 153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return psm::ImportServerCert(certificates, not_imported); 154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickunsigned int CertDatabase::GetCertTrust( 157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const X509Certificate* cert, CertType type) const { 158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CERTCertTrust nsstrust; 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SECStatus srv = CERT_GetCertTrust(cert->os_cert_handle(), &nsstrust); 160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (srv != SECSuccess) { 161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LOG(ERROR) << "CERT_GetCertTrust failed with error " << PORT_GetError(); 162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return UNTRUSTED; 163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick psm::nsNSSCertTrust trust(&nsstrust); 165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick switch (type) { 166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case CA_CERT: 167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return trust.HasTrustedCA(PR_TRUE, PR_FALSE, PR_FALSE) * TRUSTED_SSL + 168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick trust.HasTrustedCA(PR_FALSE, PR_TRUE, PR_FALSE) * TRUSTED_EMAIL + 169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick trust.HasTrustedCA(PR_FALSE, PR_FALSE, PR_TRUE) * TRUSTED_OBJ_SIGN; 170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case SERVER_CERT: 171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case EMAIL_CERT: 172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return trust.HasTrustedPeer(PR_TRUE, PR_FALSE, PR_FALSE) * TRUSTED_SSL + 173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick trust.HasTrustedPeer(PR_FALSE, PR_TRUE, PR_FALSE) * TRUSTED_EMAIL + 174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick trust.HasTrustedPeer(PR_FALSE, PR_FALSE, PR_TRUE) * TRUSTED_OBJ_SIGN; 175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick default: 176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return UNTRUSTED; 177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool CertDatabase::SetCertTrust(const X509Certificate* cert, 1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CertType type, 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick unsigned int trusted) { 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return psm::SetCertTrust(cert, type, trusted); 1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) { 1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // For some reason, PK11_DeleteTokenCertAndKey only calls 1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // SEC_DeletePermCertificate if the private key is found. So, we check 1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // whether a private key exists before deciding which function to call to 1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // delete the cert. 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert->os_cert_handle(), 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL); 1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (privKey) { 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SECKEY_DestroyPrivateKey(privKey); 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (PK11_DeleteTokenCertAndKey(cert->os_cert_handle(), NULL)) { 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(ERROR) << "PK11_DeleteTokenCertAndKey failed: " << PORT_GetError(); 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (SEC_DeletePermCertificate(cert->os_cert_handle())) { 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(ERROR) << "SEC_DeletePermCertificate failed: " << PORT_GetError(); 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 209