Make ChromeOS certificate code use NSS types directly.
Bug: 671420, 736159
Change-Id: Ic480cf5dedc644294b4f11737f3f151243febce6
Reviewed-on: https://chromium-review.googlesource.com/621489
Reviewed-by: Lei Zhang <[email protected]>
Reviewed-by: Steven Bennetts <[email protected]>
Reviewed-by: David Benjamin <[email protected]>
Commit-Queue: Matt Mueller <[email protected]>
Cr-Commit-Position: refs/heads/master@{#500334}
diff --git a/chrome/browser/certificate_manager_model.cc b/chrome/browser/certificate_manager_model.cc
index 1cf49d7..c9e9c827 100644
--- a/chrome/browser/certificate_manager_model.cc
+++ b/chrome/browser/certificate_manager_model.cc
@@ -210,8 +210,8 @@
x509_certificate_model::GetSerialNumberHexified(cert, std::string()));
break;
case COL_EXPIRES_ON: {
- base::Time not_before, not_after;
- if (net::x509_util::GetValidityTimes(cert, ¬_before, ¬_after))
+ base::Time not_after;
+ if (net::x509_util::GetValidityTimes(cert, nullptr, ¬_after))
rv = base::TimeFormatShortDateNumeric(not_after);
break;
}
diff --git a/chrome/browser/chromeos/options/cert_library.cc b/chrome/browser/chromeos/options/cert_library.cc
index dad898a0..e060790 100644
--- a/chrome/browser/chromeos/options/cert_library.cc
+++ b/chrome/browser/chromeos/options/cert_library.cc
@@ -21,6 +21,7 @@
#include "crypto/nss_util.h"
#include "net/cert/cert_database.h"
#include "net/cert/nss_cert_database.h"
+#include "net/cert/x509_util_nss.h"
#include "third_party/icu/source/i18n/unicode/coll.h" // icu::Collator
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/l10n_util_collator.h"
@@ -32,20 +33,14 @@
// Root CA certificates that are built into Chrome use this token name.
const char kRootCertificateTokenName[] = "Builtin Object Token";
-base::string16 GetDisplayString(net::X509Certificate* cert,
- bool hardware_backed) {
- std::string alt_text;
- if (!cert->subject().organization_names.empty())
- alt_text = cert->subject().organization_names[0];
- if (alt_text.empty())
- alt_text = cert->subject().GetDisplayName();
- base::string16 issued_by = base::UTF8ToUTF16(
- certificate::GetIssuerCommonName(cert->os_cert_handle(), alt_text));
+base::string16 GetDisplayString(CERTCertificate* cert, bool hardware_backed) {
+ base::string16 issued_by =
+ base::UTF8ToUTF16(certificate::GetIssuerDisplayName(cert));
- base::string16 issued_to = base::UTF8ToUTF16(
- certificate::GetCertNameOrNickname(cert->os_cert_handle()));
- base::string16 issued_to_ascii = base::UTF8ToUTF16(
- certificate::GetCertAsciiNameOrNickname(cert->os_cert_handle()));
+ base::string16 issued_to =
+ base::UTF8ToUTF16(certificate::GetCertNameOrNickname(cert));
+ base::string16 issued_to_ascii =
+ base::UTF8ToUTF16(certificate::GetCertAsciiNameOrNickname(cert));
if (issued_to_ascii != issued_to) {
// Input contained encoded data, show original and decoded forms.
issued_to = l10n_util::GetStringFUTF16(IDS_CERT_INFO_IDN_VALUE_FORMAT,
@@ -66,10 +61,9 @@
}
}
-std::string CertToPEM(const net::X509Certificate& cert) {
+std::string CertToPEM(CERTCertificate* cert) {
std::string pem_encoded_cert;
- if (!net::X509Certificate::GetPEMEncoded(cert.os_cert_handle(),
- &pem_encoded_cert)) {
+ if (!net::x509_util::GetPEMEncoded(cert, &pem_encoded_cert)) {
LOG(ERROR) << "Couldn't PEM-encode certificate";
return std::string();
}
@@ -84,8 +78,8 @@
: collator_(collator) {
}
- bool operator()(const scoped_refptr<net::X509Certificate>& lhs,
- const scoped_refptr<net::X509Certificate>& rhs) const {
+ bool operator()(const net::ScopedCERTCertificate& lhs,
+ const net::ScopedCERTCertificate& rhs) const {
base::string16 lhs_name = GetDisplayString(lhs.get(), false);
base::string16 rhs_name = GetDisplayString(rhs.get(), false);
if (collator_ == NULL)
@@ -149,28 +143,29 @@
}
int CertLibrary::NumCertificates(CertType type) const {
- const net::CertificateList& cert_list = GetCertificateListForType(type);
+ const net::ScopedCERTCertificateList& cert_list =
+ GetCertificateListForType(type);
return static_cast<int>(cert_list.size());
}
base::string16 CertLibrary::GetCertDisplayStringAt(CertType type,
int index) const {
- net::X509Certificate* cert = GetCertificateAt(type, index);
+ CERTCertificate* cert = GetCertificateAt(type, index);
bool hardware_backed = IsCertHardwareBackedAt(type, index);
return GetDisplayString(cert, hardware_backed);
}
std::string CertLibrary::GetServerCACertPEMAt(int index) const {
- return CertToPEM(*GetCertificateAt(CERT_TYPE_SERVER_CA, index));
+ return CertToPEM(GetCertificateAt(CERT_TYPE_SERVER_CA, index));
}
std::string CertLibrary::GetUserCertPkcs11IdAt(int index, int* slot_id) const {
- net::X509Certificate* cert = GetCertificateAt(CERT_TYPE_USER, index);
- return CertLoader::GetPkcs11IdAndSlotForCert(*cert, slot_id);
+ CERTCertificate* cert = GetCertificateAt(CERT_TYPE_USER, index);
+ return CertLoader::GetPkcs11IdAndSlotForCert(cert, slot_id);
}
bool CertLibrary::IsCertHardwareBackedAt(CertType type, int index) const {
- net::X509Certificate* cert = GetCertificateAt(type, index);
+ CERTCertificate* cert = GetCertificateAt(type, index);
return CertLoader::IsCertificateHardwareBacked(cert);
}
@@ -178,8 +173,8 @@
const std::string& pem_encoded) const {
int num_certs = NumCertificates(CERT_TYPE_SERVER_CA);
for (int index = 0; index < num_certs; ++index) {
- net::X509Certificate* cert = GetCertificateAt(CERT_TYPE_SERVER_CA, index);
- if (CertToPEM(*cert) != pem_encoded)
+ CERTCertificate* cert = GetCertificateAt(CERT_TYPE_SERVER_CA, index);
+ if (CertToPEM(cert) != pem_encoded)
continue;
return index;
}
@@ -190,17 +185,18 @@
const std::string& pkcs11_id) const {
int num_certs = NumCertificates(CERT_TYPE_USER);
for (int index = 0; index < num_certs; ++index) {
- net::X509Certificate* cert = GetCertificateAt(CERT_TYPE_USER, index);
+ CERTCertificate* cert = GetCertificateAt(CERT_TYPE_USER, index);
int slot_id = -1;
- std::string id = CertLoader::GetPkcs11IdAndSlotForCert(*cert, &slot_id);
+ std::string id = CertLoader::GetPkcs11IdAndSlotForCert(cert, &slot_id);
if (id == pkcs11_id)
return index;
}
return -1; // Not found.
}
-void CertLibrary::OnCertificatesLoaded(const net::CertificateList& cert_list,
- bool initial_load) {
+void CertLibrary::OnCertificatesLoaded(
+ const net::ScopedCERTCertificateList& cert_list,
+ bool initial_load) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
VLOG(1) << "CertLibrary::OnCertificatesLoaded: " << cert_list.size();
certs_.clear();
@@ -209,24 +205,23 @@
server_ca_certs_.clear();
// Add certificates to the appropriate list.
- for (net::CertificateList::const_iterator iter = cert_list.begin();
- iter != cert_list.end(); ++iter) {
- certs_.push_back(iter->get());
- net::X509Certificate::OSCertHandle cert_handle =
- iter->get()->os_cert_handle();
- net::CertType type = certificate::GetCertType(cert_handle);
+ certs_.reserve(cert_list.size());
+ for (const net::ScopedCERTCertificate& cert : cert_list) {
+ certs_.push_back(net::x509_util::DupCERTCertificate(cert.get()));
+ net::CertType type = certificate::GetCertType(cert.get());
switch (type) {
case net::USER_CERT:
- user_certs_.push_back(iter->get());
+ user_certs_.push_back(net::x509_util::DupCERTCertificate(cert.get()));
break;
case net::SERVER_CERT:
- server_certs_.push_back(iter->get());
+ server_certs_.push_back(net::x509_util::DupCERTCertificate(cert.get()));
break;
case net::CA_CERT: {
// Exclude root CA certificates that are built into Chrome.
- std::string token_name = certificate::GetCertTokenName(cert_handle);
+ std::string token_name = certificate::GetCertTokenName(cert.get());
if (token_name != kRootCertificateTokenName)
- server_ca_certs_.push_back(iter->get());
+ server_ca_certs_.push_back(
+ net::x509_util::DupCERTCertificate(cert.get()));
break;
}
default:
@@ -256,15 +251,15 @@
observer.OnCertificatesLoaded(initial_load);
}
-net::X509Certificate* CertLibrary::GetCertificateAt(CertType type,
- int index) const {
- const net::CertificateList& cert_list = GetCertificateListForType(type);
+CERTCertificate* CertLibrary::GetCertificateAt(CertType type, int index) const {
+ const net::ScopedCERTCertificateList& cert_list =
+ GetCertificateListForType(type);
DCHECK_GE(index, 0);
DCHECK_LT(index, static_cast<int>(cert_list.size()));
return cert_list[index].get();
}
-const net::CertificateList& CertLibrary::GetCertificateListForType(
+const net::ScopedCERTCertificateList& CertLibrary::GetCertificateListForType(
CertType type) const {
if (type == CERT_TYPE_USER)
return user_certs_;
diff --git a/chrome/browser/chromeos/options/cert_library.h b/chrome/browser/chromeos/options/cert_library.h
index 49b8e1a..a17dd04 100644
--- a/chrome/browser/chromeos/options/cert_library.h
+++ b/chrome/browser/chromeos/options/cert_library.h
@@ -11,7 +11,7 @@
#include "base/strings/string16.h"
#include "base/threading/thread_checker.h"
#include "chromeos/cert_loader.h"
-#include "net/cert/x509_certificate.h"
+#include "net/cert/scoped_nss_types.h"
namespace chromeos {
@@ -79,23 +79,24 @@
int GetUserCertIndexByPkcs11Id(const std::string& pkcs11_id) const;
// CertLoader::Observer
- void OnCertificatesLoaded(const net::CertificateList&,
+ void OnCertificatesLoaded(const net::ScopedCERTCertificateList&,
bool initial_load) override;
private:
CertLibrary();
~CertLibrary() override;
- net::X509Certificate* GetCertificateAt(CertType type, int index) const;
- const net::CertificateList& GetCertificateListForType(CertType type) const;
+ CERTCertificate* GetCertificateAt(CertType type, int index) const;
+ const net::ScopedCERTCertificateList& GetCertificateListForType(
+ CertType type) const;
base::ObserverList<CertLibrary::Observer> observer_list_;
// Sorted certificate lists
- net::CertificateList certs_;
- net::CertificateList user_certs_;
- net::CertificateList server_certs_;
- net::CertificateList server_ca_certs_;
+ net::ScopedCERTCertificateList certs_;
+ net::ScopedCERTCertificateList user_certs_;
+ net::ScopedCERTCertificateList server_certs_;
+ net::ScopedCERTCertificateList server_ca_certs_;
THREAD_CHECKER(thread_checker_);
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc
index ec306f0..81c8c05 100644
--- a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc
+++ b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc
@@ -36,13 +36,19 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/nss_key_util.h"
+#include "crypto/openssl_util.h"
#include "crypto/scoped_nss_types.h"
#include "net/base/net_errors.h"
+#include "net/cert/asn1_util.h"
#include "net/cert/cert_database.h"
#include "net/cert/nss_cert_database.h"
#include "net/cert/x509_util_nss.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
+#include "third_party/boringssl/src/include/openssl/bn.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
using content::BrowserContext;
using content::BrowserThread;
@@ -268,7 +274,7 @@
from, base::Bind(callback_, base::Passed(&certs), error_message));
}
- std::unique_ptr<net::CertificateList> certs_;
+ net::ScopedCERTCertificateList certs_;
private:
// Must be called on origin thread, therefore use CallBack().
@@ -581,10 +587,10 @@
void FilterCertificatesOnWorkerThread(
std::unique_ptr<GetCertificatesState> state) {
std::unique_ptr<net::CertificateList> client_certs(new net::CertificateList);
- for (net::CertificateList::const_iterator it = state->certs_->begin();
- it != state->certs_->end();
- ++it) {
- net::X509Certificate::OSCertHandle cert_handle = (*it)->os_cert_handle();
+ for (net::ScopedCERTCertificateList::const_iterator it =
+ state->certs_.begin();
+ it != state->certs_.end(); ++it) {
+ CERTCertificate* cert_handle = it->get();
crypto::ScopedPK11Slot cert_slot(PK11_KeyForCertExists(cert_handle,
NULL, // keyPtr
NULL)); // wincx
@@ -594,7 +600,12 @@
if (cert_slot != state->slot_)
continue;
- client_certs->push_back(*it);
+ scoped_refptr<net::X509Certificate> cert =
+ net::x509_util::CreateX509CertificateFromCERTCertificate(cert_handle);
+ if (!cert)
+ continue;
+
+ client_certs->push_back(std::move(cert));
}
state->CallBack(FROM_HERE, std::move(client_certs),
@@ -604,7 +615,7 @@
// Passes the obtained certificates to the worker thread for filtering. Used by
// GetCertificatesWithDB().
void DidGetCertificates(std::unique_ptr<GetCertificatesState> state,
- std::unique_ptr<net::CertificateList> all_certs) {
+ net::ScopedCERTCertificateList all_certs) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
state->certs_ = std::move(all_certs);
// This task interacts with the TPM, hence MayBlock().
@@ -641,16 +652,24 @@
return;
}
+ net::ScopedCERTCertificate nss_cert =
+ net::x509_util::CreateCERTCertificateFromX509Certificate(
+ state->certificate_.get());
+ if (!nss_cert) {
+ state->OnError(FROM_HERE, net::ErrorToString(net::ERR_CERT_INVALID));
+ return;
+ }
+
// Check that the private key is in the correct slot.
crypto::ScopedPK11Slot slot(
- PK11_KeyForCertExists(state->certificate_->os_cert_handle(), NULL, NULL));
+ PK11_KeyForCertExists(nss_cert.get(), NULL, NULL));
if (slot.get() != state->slot_.get()) {
state->OnError(FROM_HERE, kErrorKeyNotFound);
return;
}
- const net::Error import_status = static_cast<net::Error>(
- cert_db->ImportUserCert(state->certificate_.get()));
+ const net::Error import_status =
+ static_cast<net::Error>(cert_db->ImportUserCert(nss_cert.get()));
if (import_status != net::OK) {
LOG(ERROR) << "Could not import certificate.";
state->OnError(FROM_HERE, net::ErrorToString(import_status));
@@ -683,13 +702,19 @@
void RemoveCertificateWithDB(std::unique_ptr<RemoveCertificateState> state,
net::NSSCertDatabase* cert_db) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Get the pointer before base::Passed clears |state|.
- scoped_refptr<net::X509Certificate> certificate = state->certificate_;
- bool certificate_found = certificate->os_cert_handle()->isperm;
+
+ net::ScopedCERTCertificate nss_cert =
+ net::x509_util::CreateCERTCertificateFromX509Certificate(
+ state->certificate_.get());
+ if (!nss_cert) {
+ state->OnError(FROM_HERE, net::ErrorToString(net::ERR_CERT_INVALID));
+ return;
+ }
+
+ bool certificate_found = nss_cert->isperm;
cert_db->DeleteCertAndKeyAsync(
- certificate,
- base::Bind(
- &DidRemoveCertificate, base::Passed(&state), certificate_found));
+ std::move(nss_cert), base::Bind(&DidRemoveCertificate,
+ base::Passed(&state), certificate_found));
}
// Does the actual work to determine which tokens are available.
@@ -807,8 +832,15 @@
std::string GetSubjectPublicKeyInfo(
const scoped_refptr<net::X509Certificate>& certificate) {
- const SECItem& spki_der = certificate->os_cert_handle()->derPublicKey;
- return std::string(spki_der.data, spki_der.data + spki_der.len);
+ std::string der_bytes;
+ if (!net::X509Certificate::GetDEREncoded(certificate->os_cert_handle(),
+ &der_bytes))
+ return {};
+
+ base::StringPiece spki_bytes;
+ if (!net::asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
+ return {};
+ return spki_bytes.as_string();
}
bool GetPublicKey(const scoped_refptr<net::X509Certificate>& certificate,
@@ -829,14 +861,24 @@
return false;
}
- crypto::ScopedSECKEYPublicKey public_key(
- CERT_ExtractPublicKey(certificate->os_cert_handle()));
- if (!public_key) {
+ std::string spki = GetSubjectPublicKeyInfo(certificate);
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ CBS cbs;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki.data()), spki.size());
+ bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
+ if (!pkey) {
LOG(WARNING) << "Could not extract public key of certificate.";
return false;
}
- long public_exponent = DER_GetInteger(&public_key->u.rsa.publicExponent);
- if (public_exponent != 65537L) {
+ RSA* rsa = EVP_PKEY_get0_RSA(pkey.get());
+ if (!rsa) {
+ LOG(WARNING) << "Could not get RSA from PKEY.";
+ return false;
+ }
+
+ const BIGNUM* public_exponent;
+ RSA_get0_key(rsa, nullptr /* out_n */, &public_exponent, nullptr /* out_d */);
+ if (BN_get_word(public_exponent) != 65537L) {
LOG(ERROR) << "Rejecting RSA public exponent that is unequal 65537.";
return false;
}
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index e499306..b62c6f5f 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -494,14 +494,12 @@
}
bool SetupCertificates() {
- scoped_refptr<net::X509Certificate> system_ca_cert =
- net::ImportCertFromFile(net::GetTestCertsDirectory(),
- "client_1_ca.pem");
- if (!system_ca_cert)
+ net::ScopedCERTCertificateList cert_list =
+ net::CreateCERTCertificateListFromFile(
+ net::GetTestCertsDirectory(), "client_1_ca.pem",
+ net::X509Certificate::FORMAT_AUTO);
+ if (cert_list.empty())
return false;
-
- net::CertificateList cert_list;
- cert_list.push_back(std::move(system_ca_cert));
// TODO(stevenjb): Figure out a simple way to import a test user cert.
chromeos::NetworkHandler::Get()