diff options
-rw-r--r-- | chrome/browser/chromeos/cros/network_library.cc | 8 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/onc_network_parser.cc | 163 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/onc_network_parser.h | 12 | ||||
-rw-r--r-- | chrome/browser/chromeos/cros/onc_network_parser_unittest.cc | 198 | ||||
-rw-r--r-- | crypto/nss_util.cc | 2 | ||||
-rw-r--r-- | net/base/cert_database.h | 10 | ||||
-rw-r--r-- | net/base/cert_database_nss.cc | 7 | ||||
-rw-r--r-- | net/base/cert_database_nss_unittest.cc | 2 | ||||
-rw-r--r-- | net/base/cert_database_openssl.cc | 7 |
9 files changed, 396 insertions, 13 deletions
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc index 03ddeea..adfa8b9 100644 --- a/chrome/browser/chromeos/cros/network_library.cc +++ b/chrome/browser/chromeos/cros/network_library.cc @@ -2782,6 +2782,14 @@ void NetworkLibraryImplBase::SwitchToPreferredNetwork() { bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob) { OncNetworkParser parser(onc_blob); + for (int i = 0; i < parser.GetCertificatesSize(); i++) { + // Insert each of the available certs into the certificate DB. + if (!parser.ParseCertificate(i)) { + DLOG(WARNING) << "Cannot parse certificate in ONC file"; + return false; + } + } + for (int i = 0; i < parser.GetNetworkConfigsSize(); i++) { // Parse Open Network Configuration blob into a temporary Network object. Network* network = parser.ParseNetwork(i); diff --git a/chrome/browser/chromeos/cros/onc_network_parser.cc b/chrome/browser/chromeos/cros/onc_network_parser.cc index b1cf7b6..2b0b8d0 100644 --- a/chrome/browser/chromeos/cros/onc_network_parser.cc +++ b/chrome/browser/chromeos/cros/onc_network_parser.cc @@ -4,12 +4,16 @@ #include "chrome/browser/chromeos/cros/onc_network_parser.h" +#include "base/base64.h" +#include "base/json/json_value_serializer.h" #include "base/stringprintf.h" #include "base/values.h" #include "chrome/browser/chromeos/cros/native_network_constants.h" #include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/login/user_manager.h" -#include "base/json/json_value_serializer.h" +#include "net/base/cert_database.h" +#include "net/base/net_errors.h" +#include "net/base/x509_certificate.h" #include "third_party/cros_system_api/dbus/service_constants.h" namespace chromeos { @@ -75,15 +79,18 @@ OncNetworkParser::OncNetworkParser(const std::string& onc_blob) LOG(WARNING) << "OncNetworkParser received bad ONC file: " << error_msg; } else { root_dict_.reset(static_cast<DictionaryValue*>(root.release())); - if (!root_dict_->GetList("NetworkConfigurations", &network_configs_)) { - LOG(WARNING) << "ONC file missing NetworkConfigurations"; + // At least one of NetworkConfigurations or Certificates is required. + if (!root_dict_->GetList("NetworkConfigurations", &network_configs_) && + !root_dict_->GetList("Certificates", &certificates_)) { + LOG(WARNING) << "ONC file has no NetworkConfigurations or Certificates."; } - // Certificates is optional - root_dict_->GetList("Certificates", &certificates_); } } -OncNetworkParser::OncNetworkParser() : NetworkParser(get_onc_mapper()) { +OncNetworkParser::OncNetworkParser() + : NetworkParser(get_onc_mapper()), + network_configs_(NULL), + certificates_(NULL) { } OncNetworkParser::~OncNetworkParser() { @@ -102,6 +109,45 @@ int OncNetworkParser::GetCertificatesSize() const { return certificates_ ? certificates_->GetSize() : 0; } +bool OncNetworkParser::ParseCertificate(int cert_index) { + CHECK(certificates_); + CHECK(static_cast<size_t>(cert_index) < certificates_->GetSize()); + CHECK(cert_index >= 0); + base::DictionaryValue* certificate = NULL; + certificates_->GetDictionary(cert_index, &certificate); + CHECK(certificate); + + // Get out the attributes of the given cert. + std::string guid; + bool remove = false; + if (!certificate->GetString("GUID", &guid) || guid.empty()) { + LOG(WARNING) << "ONC File: certificate missing identifier at index" + << cert_index; + return false; + } + + if (!certificate->GetBoolean("Remove", &remove)) + remove = false; + + net::CertDatabase cert_database; + if (remove) + return cert_database.DeleteCertAndKeyByLabel(guid); + + // Not removing, so let's get the data we need to add this cert. + std::string cert_type; + certificate->GetString("Type", &cert_type); + if (cert_type == "Server" || cert_type == "Authority") { + return ParseServerOrCaCertificate(cert_index, cert_type, certificate); + } + if (cert_type == "Client") { + return ParseClientCertificate(cert_index, certificate); + } + + LOG(WARNING) << "ONC File: certificate of unknown type: " << cert_type + << " at index " << cert_index; + return false; +} + Network* OncNetworkParser::ParseNetwork(int n) { // TODO(chocobo): Change this to parse network into a dictionary. if (!network_configs_) @@ -162,6 +208,111 @@ std::string OncNetworkParser::GetTypeFromDictionary( return type_string; } +bool OncNetworkParser::ParseServerOrCaCertificate( + int cert_index, + const std::string& cert_type, + base::DictionaryValue* certificate) { + net::CertDatabase cert_database; + bool web_trust = false; + base::ListValue* trust_list = NULL; + if (certificate->GetList("Trust", &trust_list)) { + for (size_t i = 0; i < trust_list->GetSize(); ++i) { + std::string trust_type; + if (!trust_list->GetString(i, &trust_type)) { + LOG(WARNING) << "ONC File: certificate trust is invalid at index " + << cert_index; + return false; + } + if (trust_type == "Web") { + web_trust = true; + } else { + LOG(WARNING) << "ONC File: certificate contains unknown " + << "trust type: " << trust_type + << " at index " << cert_index; + return false; + } + } + } + + std::string x509_data; + if (!certificate->GetString("X509", &x509_data) || x509_data.empty()) { + LOG(WARNING) << "ONC File: certificate missing appropriate " + << "certificate data for type: " << cert_type + << " at index " << cert_index; + return false; + } + + std::string decoded_x509; + if (!base::Base64Decode(x509_data, &decoded_x509)) { + LOG(WARNING) << "Unable to base64 decode X509 data: \"" + << x509_data << "\"."; + return false; + } + + scoped_refptr<net::X509Certificate> x509_cert( + net::X509Certificate::CreateFromBytes(decoded_x509.c_str(), + decoded_x509.size())); + if (!x509_cert.get()) { + LOG(WARNING) << "Unable to create X509 certificate from bytes."; + return false; + } + net::CertificateList cert_list; + cert_list.push_back(x509_cert); + net::CertDatabase::ImportCertFailureList failures; + bool success = false; + if (cert_type == "Server") { + success = cert_database.ImportServerCert(cert_list, &failures); + } else { // Authority cert + net::CertDatabase::TrustBits trust = web_trust ? + net::CertDatabase::TRUSTED_SSL : + net::CertDatabase::UNTRUSTED; + success = cert_database.ImportCACerts(cert_list, trust, &failures); + } + if (!failures.empty()) { + LOG(WARNING) << "ONC File: Error (" + << net::ErrorToString(failures[0].net_error) + << ") importing " << cert_type << " certificate at index " + << cert_index; + return false; + } + if (!success) { + LOG(WARNING) << "ONC File: Unknown error importing " << cert_type + << " certificate at index " << cert_index; + return false; + } + return true; +} + +bool OncNetworkParser::ParseClientCertificate( + int cert_index, + base::DictionaryValue* certificate) { + net::CertDatabase cert_database; + std::string pkcs12_data; + if (!certificate->GetString("PKCS12", &pkcs12_data) || + pkcs12_data.empty()) { + LOG(WARNING) << "ONC File: PKCS12 data is missing for Client " + << "certificate at index " << cert_index; + return false; + } + + std::string decoded_pkcs12; + if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { + LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \"" + << pkcs12_data << "\"."; + return false; + } + + // Since this has a private key, always use the private module. + int result = cert_database.ImportFromPKCS12( + cert_database.GetPrivateModule(), decoded_pkcs12, string16(), false); + if (result != net::OK) { + LOG(WARNING) << "ONC File: Unable to import Client certificate at index " + << cert_index + << " (error " << net::ErrorToString(result) << ")."; + return false; + } + return true; +} // -------------------- OncWirelessNetworkParser -------------------- diff --git a/chrome/browser/chromeos/cros/onc_network_parser.h b/chrome/browser/chromeos/cros/onc_network_parser.h index cb624f3..4fd0126 100644 --- a/chrome/browser/chromeos/cros/onc_network_parser.h +++ b/chrome/browser/chromeos/cros/onc_network_parser.h @@ -42,6 +42,10 @@ class OncNetworkParser : public NetworkParser { // (0-based). Returns NULL if there's a parse error or if n is out of range. Network* ParseNetwork(int n); + // Call to parse and import the nth certificate in the certificate + // list. Returns false on failure. + bool ParseCertificate(int n); + virtual Network* CreateNetworkFromInfo(const std::string& service_path, const base::DictionaryValue& info) OVERRIDE; @@ -58,6 +62,14 @@ class OncNetworkParser : public NetworkParser { std::string GetTypeFromDictionary(const base::DictionaryValue& info); private: + bool ParseServerOrCaCertificate( + int cert_index, + const std::string& cert_type, + base::DictionaryValue* certificate); + bool ParseClientCertificate( + int cert_index, + base::DictionaryValue* certificate); + scoped_ptr<base::DictionaryValue> root_dict_; base::ListValue* network_configs_; base::ListValue* certificates_; diff --git a/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc b/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc index 3e2a313..25e9df8 100644 --- a/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc +++ b/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc @@ -4,13 +4,93 @@ #include "chrome/browser/chromeos/cros/onc_network_parser.h" +#include <cert.h> +#include <pk11pub.h> + +#include "base/lazy_instance.h" +#include "base/scoped_temp_dir.h" #include "base/values.h" #include "chrome/browser/chromeos/cros/network_library.h" +#include "crypto/nss_util.h" +#include "net/base/cert_database.h" +#include "net/base/crypto_module.h" +#include "net/base/x509_certificate.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos { -TEST(OncNetworkParserTest, TestCreateNetworkWifi1) { +class OncNetworkParserTest : public testing::Test { + public: + static void SetUpTestCase() { + ASSERT_TRUE(temp_db_dir_.Get().CreateUniqueTempDir()); + // Ideally, we'd open a test DB for each test case, and close it + // again, removing the temp dir, but unfortunately, there's a + // bug in NSS that prevents this from working, so we just open + // it once, and empty it for each test case. Here's the bug: + // https://bugzilla.mozilla.org/show_bug.cgi?id=588269 + ASSERT_TRUE( + crypto::OpenTestNSSDB(temp_db_dir_.Get().path(), + "OncNetworkParserTest db")); + } + + static void TearDownTestCase() { + ASSERT_TRUE(temp_db_dir_.Get().Delete()); + } + + virtual void SetUp() { + slot_ = cert_db_.GetPublicModule(); + + // Don't run the test if the setup failed. + ASSERT_TRUE(slot_->os_module_handle()); + + // Test db should be empty at start of test. + EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size()); + } + + virtual void TearDown() { + EXPECT_TRUE(CleanupSlotContents(slot_->os_module_handle())); + EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size()); + } + + protected: + scoped_refptr<net::CryptoModule> slot_; + net::CertDatabase cert_db_; + + private: + net::CertificateList ListCertsInSlot(PK11SlotInfo* slot) { + net::CertificateList result; + CERTCertList* cert_list = PK11_ListCertsInSlot(slot); + for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); + !CERT_LIST_END(node, cert_list); + node = CERT_LIST_NEXT(node)) { + result.push_back(net::X509Certificate::CreateFromHandle( + node->cert, net::X509Certificate::OSCertHandles())); + } + CERT_DestroyCertList(cert_list); + + // Sort the result so that test comparisons can be deterministic. + std::sort(result.begin(), result.end(), net::X509Certificate::LessThan()); + return result; + } + + bool CleanupSlotContents(PK11SlotInfo* slot) { + bool ok = true; + net::CertificateList certs = ListCertsInSlot(slot); + for (size_t i = 0; i < certs.size(); ++i) { + if (!cert_db_.DeleteCertAndKey(certs[i])) + ok = false; + } + return ok; + } + + static base::LazyInstance<ScopedTempDir> temp_db_dir_; +}; + +// static +base::LazyInstance<ScopedTempDir> OncNetworkParserTest::temp_db_dir_( + base::LINKER_INITIALIZED); + +TEST_F(OncNetworkParserTest, TestCreateNetworkWifi1) { std::string test_blob( "{" " \"NetworkConfigurations\": [{" @@ -39,7 +119,7 @@ TEST(OncNetworkParserTest, TestCreateNetworkWifi1) { EXPECT_EQ(wifi->passphrase(), "pass"); } -TEST(OncNetworkParserTest, TestCreateNetworkWifiEAP1) { +TEST_F(OncNetworkParserTest, TestCreateNetworkWifiEAP1) { std::string test_blob( "{" " \"NetworkConfigurations\": [{" @@ -73,7 +153,7 @@ TEST(OncNetworkParserTest, TestCreateNetworkWifiEAP1) { EXPECT_EQ(wifi->eap_use_system_cas(), false); } -TEST(OncNetworkParserTest, TestCreateNetworkWifiEAP2) { +TEST_F(OncNetworkParserTest, TestCreateNetworkWifiEAP2) { std::string test_blob( "{" " \"NetworkConfigurations\": [{" @@ -112,4 +192,116 @@ TEST(OncNetworkParserTest, TestCreateNetworkWifiEAP2) { EXPECT_EQ(wifi->eap_anonymous_identity(), "anon"); } +TEST_F(OncNetworkParserTest, TestAddServerCertificate) { + std::string test_blob( + "{" + " \"Certificates\": [" + " {" + " \"GUID\": \"{f998f760-272b-6939-4c2beffe428697aa}\"," + " \"Type\": \"Server\"," + " \"X509\": \"MIICWDCCAcECAxAAATANBgkqhkiG9w0BAQQFADCBkzEVM" + "BMGA1UEChMMR29vZ2xlLCBJbmMuMREwDwYDVQQLEwhDaHJvbWVPUzEiMCAGCSqGSIb3DQ" + "EJARYTZ3NwZW5jZXJAZ29vZ2xlLmNvbTEaMBgGA1UEBxMRTW91bnRhaW4gVmlldywgQ0E" + "xCzAJBgNVBAgTAkNBMQswCQYDVQQGEwJVUzENMAsGA1UEAxMEbG1hbzAeFw0xMTAzMTYy" + "MzQ5MzhaFw0xMjAzMTUyMzQ5MzhaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVM" + "BMGA1UEChMMR29vZ2xlLCBJbmMuMREwDwYDVQQLEwhDaHJvbWVPUzENMAsGA1UEAxMEbG" + "1hbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA31WiJ9LvprrhKtDlW0RdLFAO7Qj" + "kvs+sG6j2Vp2aBSrlhALG/0BVHUhWi4F/HHJho+ncLHAg5AGO0sdAjYUdQG6tfPqjLsIA" + "LtoKEZZdFe/JhmqOEaxWsSdu2S2RdPgCQOsP79EH58gXwu2gejCkJDmU22WL4YLuqOc17" + "nxbDC8CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCv4vMD+PMlfnftu4/6Yf/oMLE8yCOqZT" + "Q/dWCxB9PiJnOefiBeSzSZE6Uv3G7qnblZPVZaFeJMd+ostt0viCyPucFsFgLMyyoV1dM" + "VPVwJT5Iq1AHehWXnTBbxUK9wioA5jOEKdroKjuSSsg/Q8Wx6cpJmttQz5olGPgstmACR" + "WA==\"" + " }" + " ]," + "}"); + OncNetworkParser parser(test_blob); + + EXPECT_EQ(1, parser.GetCertificatesSize()); + EXPECT_TRUE(parser.ParseCertificate(0)); +} + +TEST_F(OncNetworkParserTest, TestAddAuthorityCertificate) { + const std::string test_blob("{" + " \"Certificates\": [" + " {" + " \"GUID\": \"{f998f760-272b-6939-4c2beffe428697ab}\"," + " \"Type\": \"Authority\"," + " \"Trust\": [\"Web\"]," + " \"X509\": \"MIIDojCCAwugAwIBAgIJAKGvi5ZgEWDVMA0GCSqGSIb3D" + "QEBBAUAMIGTMRUwEwYDVQQKEwxHb29nbGUsIEluYy4xETAPBgNVBAsTCENocm9tZU9TMS" + "IwIAYJKoZIhvcNAQkBFhNnc3BlbmNlckBnb29nbGUuY29tMRowGAYDVQQHExFNb3VudGF" + "pbiBWaWV3LCBDQTELMAkGA1UECBMCQ0ExCzAJBgNVBAYTAlVTMQ0wCwYDVQQDEwRsbWFv" + "MB4XDTExMDMxNjIzNDcxMFoXDTEyMDMxNTIzNDcxMFowgZMxFTATBgNVBAoTDEdvb2dsZ" + "SwgSW5jLjERMA8GA1UECxMIQ2hyb21lT1MxIjAgBgkqhkiG9w0BCQEWE2dzcGVuY2VyQG" + "dvb2dsZS5jb20xGjAYBgNVBAcTEU1vdW50YWluIFZpZXcsIENBMQswCQYDVQQIEwJDQTE" + "LMAkGA1UEBhMCVVMxDTALBgNVBAMTBGxtYW8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ" + "AoGBAMDX6BQz2JUzIAVjetiXxDznd2wdqVqVHfNkbSRW+xBywgqUaIXmFEGUol7VzPfme" + "FV8o8ok/eFlQB0h6ycqgwwMd0KjtJs2ys/k0F5GuN0G7fsgr+NRnhVgxj21yF6gYTN/8a" + "9kscla/svdmp8ekexbALFnghbLBx3CgcqUxT+tAgMBAAGjgfswgfgwDAYDVR0TBAUwAwE" + "B/zAdBgNVHQ4EFgQUbYygbSkl4kpjCNuxoezFGupA97UwgcgGA1UdIwSBwDCBvYAUbYyg" + "bSkl4kpjCNuxoezFGupA97WhgZmkgZYwgZMxFTATBgNVBAoTDEdvb2dsZSwgSW5jLjERM" + "A8GA1UECxMIQ2hyb21lT1MxIjAgBgkqhkiG9w0BCQEWE2dzcGVuY2VyQGdvb2dsZS5jb2" + "0xGjAYBgNVBAcTEU1vdW50YWluIFZpZXcsIENBMQswCQYDVQQIEwJDQTELMAkGA1UEBhM" + "CVVMxDTALBgNVBAMTBGxtYW+CCQChr4uWYBFg1TANBgkqhkiG9w0BAQQFAAOBgQCDq9wi" + "Q4uVuf1CQU3sXfXCy1yqi5m8AsO9FxHvah5/SVFNwKllqTfedpCaWEswJ55YAojW9e+pY" + "2Fh3Fo/Y9YkF88KCtLuBjjqDKCRLxF4LycjHODKyQQ7mN/t5AtP9yKOsNvWF+M4IfReg5" + "1kohau6FauQx87by5NIRPdkNPvkQ==\"" + " }" + " ]," + "}"); + OncNetworkParser parser(test_blob); + + EXPECT_EQ(1, parser.GetCertificatesSize()); + EXPECT_TRUE(parser.ParseCertificate(0)); +} + +TEST_F(OncNetworkParserTest, TestAddClientCertificate) { + std::string test_blob( + "{" + " \"Certificates\": [" + " {" + " \"GUID\": \"{f998f760-272b-6939-4c2beffe428697ac}\"," + " \"Type\": \"Client\"," + " \"PKCS12\": \"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\"" + " }" + " ]," + "}"); + OncNetworkParser parser(test_blob); + + EXPECT_EQ(1, parser.GetCertificatesSize()); + EXPECT_TRUE(parser.ParseCertificate(0)); +} + } // namespace chromeos diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc index 95afb54..803b01c 100644 --- a/crypto/nss_util.cc +++ b/crypto/nss_util.cc @@ -353,7 +353,7 @@ class NSSInitSingleton { if (test_slot_) { SECStatus status = SECMOD_CloseUserDB(test_slot_); if (status != SECSuccess) - LOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); + PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); PK11_FreeSlot(test_slot_); test_slot_ = NULL; } diff --git a/net/base/cert_database.h b/net/base/cert_database.h index 4851a77..a735e693 100644 --- a/net/base/cert_database.h +++ b/net/base/cert_database.h @@ -174,10 +174,16 @@ class NET_EXPORT CertDatabase { TrustBits trust_bits); // Delete certificate and associated private key (if one exists). - // Returns true on success or false on failure. - // |cert| is still valid when this function returns. + // |cert| is still valid when this function returns. Returns true on + // success. bool DeleteCertAndKey(const X509Certificate* cert); + // Delete the certificate and associated public and private key (if + // one exists) with the given label from the database. Returns true + // on success. ("label" here refers to the NSS Attribute CKA_LABEL, + // also referred to as a nickname or friendly name). + bool DeleteCertAndKeyByLabel(const std::string& label); + // Check whether cert is stored in a readonly slot. bool IsReadOnly(const X509Certificate* cert) const; #endif diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc index 4fa877d..817372d 100644 --- a/net/base/cert_database_nss.cc +++ b/net/base/cert_database_nss.cc @@ -328,6 +328,13 @@ bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) { return true; } +bool CertDatabase::DeleteCertAndKeyByLabel(const std::string& label) { + // TODO(gspencer):Find the certificate with the given CKA_LABEL + // (nickname), and delete it. + NOTIMPLEMENTED(); + return false; +} + bool CertDatabase::IsReadOnly(const X509Certificate* cert) const { PK11SlotInfo* slot = cert->os_cert_handle()->slot; return slot && PK11_IsReadOnly(slot); diff --git a/net/base/cert_database_nss_unittest.cc b/net/base/cert_database_nss_unittest.cc index a7301b8..7b1c3e2 100644 --- a/net/base/cert_database_nss_unittest.cc +++ b/net/base/cert_database_nss_unittest.cc @@ -174,7 +174,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12AsExtractableAndExportAgain) { EXPECT_EQ("testusercert", cert->subject().common_name); - // TODO(mattm): move export test to seperate test case? + // TODO(mattm): move export test to separate test case? std::string exported_data; EXPECT_EQ(1, cert_db_.ExportToPKCS12(cert_list, ASCIIToUTF16("exportpw"), &exported_data)); diff --git a/net/base/cert_database_openssl.cc b/net/base/cert_database_openssl.cc index ca429c08..76bd3f8 100644 --- a/net/base/cert_database_openssl.cc +++ b/net/base/cert_database_openssl.cc @@ -82,6 +82,13 @@ bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) { return false; } +bool CertDatabase::DeleteCertAndKeyByLabel(const std::string& label) { + // TODO(gspencer):Find the certificate with the given label + // (nickname), and delete it. + NOTIMPLEMENTED(); + return false; +} + CertDatabase::TrustBits CertDatabase::GetCertTrust(const X509Certificate* cert, CertType type) const { // TODO(bulach): implement me. |