diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-29 03:25:04 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-29 03:25:04 +0000 |
commit | 09a1bd76e3fd08b2ba0035af7ee2f0b60661174b (patch) | |
tree | 825db69ff522a1bacecf9b58eef87b01747509c8 /net/base/x509_certificate_win.cc | |
parent | 507bdd1707edb7a90971f90e9b7e654c96cbb810 (diff) | |
download | chromium_src-09a1bd76e3fd08b2ba0035af7ee2f0b60661174b.zip chromium_src-09a1bd76e3fd08b2ba0035af7ee2f0b60661174b.tar.gz chromium_src-09a1bd76e3fd08b2ba0035af7ee2f0b60661174b.tar.bz2 |
Work around our not caching the intermediate CA
certificates by passing the source of each OSCertHandle to
CreateFromHandle and the X509Certificate constructor. If
the OSCertHandle comes from the network layer, we know it
has a complete certificate chain and therefore prefer it to
an OSCertHandle that comes from the HTTP cache, which
doesn't have the intermediate CA certificates. A
certificate from the network layer can kick out a
certificate from the HTTP cache in our certificate cache.
This workaround seems good enough to fix all the known
symptoms of not caching the intermediate CA certificates.
Move the common code in x509_certificate_<os>.cc to
x509_certificate.cc.
R=eroman
BUG=3154,7065
Review URL: http://codereview.chromium.org/18836
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8864 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/x509_certificate_win.cc')
-rw-r--r-- | net/base/x509_certificate_win.cc | 114 |
1 files changed, 39 insertions, 75 deletions
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc index 4e7c4ba..57ce947 100644 --- a/net/base/x509_certificate_win.cc +++ b/net/base/x509_certificate_win.cc @@ -4,7 +4,6 @@ #include "net/base/x509_certificate.h" -#include "base/histogram.h" #include "base/logging.h" #include "base/pickle.h" #include "base/string_tokenizer.h" @@ -21,23 +20,6 @@ namespace net { namespace { -// Calculates the SHA-1 fingerprint of the certificate. Returns an empty -// (all zero) fingerprint on failure. -X509Certificate::Fingerprint CalculateFingerprint(PCCERT_CONTEXT cert) { - DCHECK(NULL != cert->pbCertEncoded); - DCHECK(0 != cert->cbCertEncoded); - - BOOL rv; - X509Certificate::Fingerprint sha1; - DWORD sha1_size = sizeof(sha1.data); - rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, - cert->cbCertEncoded, sha1.data, &sha1_size); - DCHECK(rv && sha1_size == sizeof(sha1.data)); - if (!rv) - memset(sha1.data, 0, sizeof(sha1.data)); - return sha1; -} - // Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the // WINAPI calling convention. void* WINAPI MyCryptAlloc(size_t size) { @@ -255,39 +237,6 @@ void X509Certificate::Initialize() { } // static -X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle) { - DCHECK(cert_handle); - - // Check if we already have this certificate in memory. - X509Certificate::Cache* cache = X509Certificate::Cache::GetInstance(); - X509Certificate* cert = cache->Find(CalculateFingerprint(cert_handle)); - if (cert) { - // We've found a certificate with the same fingerprint in our cache. We own - // the |cert_handle|, which makes it our job to free it. - CertFreeCertificateContext(cert_handle); - DHISTOGRAM_COUNTS(L"X509CertificateReuseCount", 1); - return cert; - } - // Otherwise, allocate a new object. - return new X509Certificate(cert_handle); -} - -// static -X509Certificate* X509Certificate::CreateFromBytes(const char* data, - int length) { - OSCertHandle cert_handle = NULL; - if (!CertAddEncodedCertificateToStore( - NULL, // the cert won't be persisted in any cert store - X509_ASN_ENCODING, - reinterpret_cast<const BYTE*>(data), length, - CERT_STORE_ADD_USE_EXISTING, - &cert_handle)) - return NULL; - - return CreateFromHandle(cert_handle); -} - -// static X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, void** pickle_iter) { const char* data; @@ -303,22 +252,7 @@ X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, NULL, reinterpret_cast<const void **>(&cert_handle))) return NULL; - return CreateFromHandle(cert_handle); -} - -X509Certificate::X509Certificate(OSCertHandle cert_handle) - : cert_handle_(cert_handle) { - Initialize(); -} - -X509Certificate::X509Certificate(std::string subject, std::string issuer, - Time start_date, Time expiration_date) - : subject_(subject), - issuer_(issuer), - valid_start_(start_date), - valid_expiry_(expiration_date), - cert_handle_(NULL) { - memset(fingerprint_.data, 0, sizeof(fingerprint_.data)); + return CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT); } void X509Certificate::Persist(Pickle* pickle) { @@ -337,13 +271,6 @@ void X509Certificate::Persist(Pickle* pickle) { pickle->TrimWriteData(length); } -X509Certificate::~X509Certificate() { - // We might not be in the cache, but it is safe to remove ourselves anyway. - X509Certificate::Cache::GetInstance()->Remove(this); - if (cert_handle_) - CertFreeCertificateContext(cert_handle_); -} - void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { dns_names->clear(); scoped_ptr_malloc<CERT_ALT_NAME_INFO> alt_name_info; @@ -406,7 +333,7 @@ bool X509Certificate::IsEV(int cert_status) const { // Look up the EV policy OID of the root CA. PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext; - X509Certificate::Fingerprint fingerprint = CalculateFingerprint(root_cert); + Fingerprint fingerprint = CalculateFingerprint(root_cert); std::string ev_policy_oid; if (!metadata->GetPolicyOID(fingerprint, &ev_policy_oid)) return false; @@ -422,5 +349,42 @@ bool X509Certificate::IsEV(int cert_status) const { return ContainsPolicy(policies_info.get(), ev_policy_oid.c_str()); } +// static +X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( + const char* data, int length) { + OSCertHandle cert_handle = NULL; + if (!CertAddEncodedCertificateToStore( + NULL, // the cert won't be persisted in any cert store + X509_ASN_ENCODING, + reinterpret_cast<const BYTE*>(data), length, + CERT_STORE_ADD_USE_EXISTING, + &cert_handle)) + return NULL; + + return cert_handle; +} + +// static +void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { + CertFreeCertificateContext(cert_handle); +} + +// static +X509Certificate::Fingerprint X509Certificate::CalculateFingerprint( + OSCertHandle cert) { + DCHECK(NULL != cert->pbCertEncoded); + DCHECK(0 != cert->cbCertEncoded); + + BOOL rv; + Fingerprint sha1; + DWORD sha1_size = sizeof(sha1.data); + rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, + cert->cbCertEncoded, sha1.data, &sha1_size); + DCHECK(rv && sha1_size == sizeof(sha1.data)); + if (!rv) + memset(sha1.data, 0, sizeof(sha1.data)); + return sha1; +} + } // namespace net |