summaryrefslogtreecommitdiffstats
path: root/net/base/x509_certificate_win.cc
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-29 03:25:04 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-29 03:25:04 +0000
commit09a1bd76e3fd08b2ba0035af7ee2f0b60661174b (patch)
tree825db69ff522a1bacecf9b58eef87b01747509c8 /net/base/x509_certificate_win.cc
parent507bdd1707edb7a90971f90e9b7e654c96cbb810 (diff)
downloadchromium_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.cc114
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