summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-29 23:45:39 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-29 23:45:39 +0000
commitde614d301995efdb349e998cea13c316ae3add7d (patch)
treeb9b3fff405b79a94031214f0561ca3c0933120b1 /net
parentb49cc1f6b42aec81e0b0e83f78dd92576853fa1a (diff)
downloadchromium_src-de614d301995efdb349e998cea13c316ae3add7d.zip
chromium_src-de614d301995efdb349e998cea13c316ae3add7d.tar.gz
chromium_src-de614d301995efdb349e998cea13c316ae3add7d.tar.bz2
Fix the "certificate is not yet valid" error for server certificates
issued by a VeriSign intermediate CA. Change the CertVerifier cache to identify a certificate chain by the hash of the entire chain rather than just the server certificate. This requires adding X509Certificate::chain_fingerprint(), and the X509Certificate::CalculateChainFingerprint() method to compute the chain fingerprint. R=agl@chromium.org,rsleevi@chromium.org BUG=101555 TEST=X509CertificateTest.ChainFingerprints and CertVerifierTest.DifferentCACerts in net_unittests Review URL: http://codereview.chromium.org/8400075 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107888 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/cert_verifier.cc4
-rw-r--r--net/base/cert_verifier_unittest.cc67
-rw-r--r--net/base/x509_certificate.cc3
-rw-r--r--net/base/x509_certificate.h12
-rw-r--r--net/base/x509_certificate_mac.cc25
-rw-r--r--net/base/x509_certificate_nss.cc21
-rw-r--r--net/base/x509_certificate_openssl.cc22
-rw-r--r--net/base/x509_certificate_unittest.cc41
-rw-r--r--net/base/x509_certificate_win.cc28
-rw-r--r--net/data/ssl/certificates/README8
-rw-r--r--net/data/ssl/certificates/salesforce_com_test.pem81
-rw-r--r--net/data/ssl/certificates/verisign_intermediate_ca_2011.pem71
-rw-r--r--net/data/ssl/certificates/verisign_intermediate_ca_2016.pem71
13 files changed, 451 insertions, 3 deletions
diff --git a/net/base/cert_verifier.cc b/net/base/cert_verifier.cc
index 90a728c..1a80b40 100644
--- a/net/base/cert_verifier.cc
+++ b/net/base/cert_verifier.cc
@@ -364,7 +364,7 @@ int CertVerifier::Verify(X509Certificate* cert,
requests_++;
- const RequestParams key = {cert->fingerprint(), hostname, flags};
+ const RequestParams key = {cert->chain_fingerprint(), hostname, flags};
// First check the cache.
std::map<RequestParams, CachedCertVerifyResult>::iterator i;
i = cache_.find(key);
@@ -449,7 +449,7 @@ void CertVerifier::HandleResult(X509Certificate* cert,
uint32 ttl = kTTLSecs;
cached_result.expiry = current_time + base::TimeDelta::FromSeconds(ttl);
- const RequestParams key = {cert->fingerprint(), hostname, flags};
+ const RequestParams key = {cert->chain_fingerprint(), hostname, flags};
DCHECK_GE(max_cache_entries_, 1u);
DCHECK_LE(cache_.size(), max_cache_entries_);
diff --git a/net/base/cert_verifier_unittest.cc b/net/base/cert_verifier_unittest.cc
index 8a026fb..f4c7dcd 100644
--- a/net/base/cert_verifier_unittest.cc
+++ b/net/base/cert_verifier_unittest.cc
@@ -59,6 +59,7 @@ TEST(CertVerifierTest, CacheHit) {
ASSERT_EQ(1u, verifier.requests());
ASSERT_EQ(0u, verifier.cache_hits());
ASSERT_EQ(0u, verifier.inflight_joins());
+ ASSERT_EQ(1u, verifier.GetCacheSize());
error = verifier.Verify(test_cert, "www.example.com", 0, NULL, &verify_result,
callback.callback(), &request_handle, BoundNetLog());
@@ -69,6 +70,72 @@ TEST(CertVerifierTest, CacheHit) {
ASSERT_EQ(2u, verifier.requests());
ASSERT_EQ(1u, verifier.cache_hits());
ASSERT_EQ(0u, verifier.inflight_joins());
+ ASSERT_EQ(1u, verifier.GetCacheSize());
+}
+
+// Tests the same server certificate with different intermediate CA
+// certificates. These should be treated as different certificate chains even
+// though the two X509Certificate objects contain the same server certificate.
+TEST(CertVerifierTest, DifferentCACerts) {
+ TestTimeService* time_service = new TestTimeService;
+ base::Time current_time = base::Time::Now();
+ time_service->set_current_time(current_time);
+ CertVerifier verifier(time_service);
+
+ FilePath certs_dir = GetTestCertsDirectory();
+
+ scoped_refptr<X509Certificate> server_cert =
+ ImportCertFromFile(certs_dir, "salesforce_com_test.pem");
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
+
+ scoped_refptr<X509Certificate> intermediate_cert1 =
+ ImportCertFromFile(certs_dir, "verisign_intermediate_ca_2011.pem");
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert1);
+
+ scoped_refptr<X509Certificate> intermediate_cert2 =
+ ImportCertFromFile(certs_dir, "verisign_intermediate_ca_2016.pem");
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert2);
+
+ X509Certificate::OSCertHandles intermediates;
+ intermediates.push_back(intermediate_cert1->os_cert_handle());
+ scoped_refptr<X509Certificate> cert_chain1 =
+ X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
+ intermediates);
+
+ intermediates.clear();
+ intermediates.push_back(intermediate_cert2->os_cert_handle());
+ scoped_refptr<X509Certificate> cert_chain2 =
+ X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
+ intermediates);
+
+ int error;
+ CertVerifyResult verify_result;
+ TestCompletionCallback callback;
+ CertVerifier::RequestHandle request_handle;
+
+ error = verifier.Verify(cert_chain1, "www.example.com", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, BoundNetLog());
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_EQ(1u, verifier.requests());
+ ASSERT_EQ(0u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+ ASSERT_EQ(1u, verifier.GetCacheSize());
+
+ error = verifier.Verify(cert_chain2, "www.example.com", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, BoundNetLog());
+ ASSERT_EQ(ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle != NULL);
+ error = callback.WaitForResult();
+ ASSERT_TRUE(IsCertificateError(error));
+ ASSERT_EQ(2u, verifier.requests());
+ ASSERT_EQ(0u, verifier.cache_hits());
+ ASSERT_EQ(0u, verifier.inflight_joins());
+ ASSERT_EQ(2u, verifier.GetCacheSize());
}
// Tests an inflight join.
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc
index 5004bf4..d36bfad 100644
--- a/net/base/x509_certificate.cc
+++ b/net/base/x509_certificate.cc
@@ -232,7 +232,7 @@ bool X509Certificate::LessThan::operator()(X509Certificate* lhs,
return false;
SHA1FingerprintLessThan fingerprint_functor;
- return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_);
+ return fingerprint_functor(lhs->chain_fingerprint_, rhs->chain_fingerprint_);
}
X509Certificate::X509Certificate(const std::string& subject,
@@ -245,6 +245,7 @@ X509Certificate::X509Certificate(const std::string& subject,
valid_expiry_(expiration_date),
cert_handle_(NULL) {
memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
+ memset(chain_fingerprint_.data, 0, sizeof(chain_fingerprint_.data));
}
// static
diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h
index b4677d2..aee2447 100644
--- a/net/base/x509_certificate.h
+++ b/net/base/x509_certificate.h
@@ -210,6 +210,11 @@ class NET_EXPORT X509Certificate
// The fingerprint of this certificate.
const SHA1Fingerprint& fingerprint() const { return fingerprint_; }
+ // The fingerprint of this certificate and its intermediate CA certificates.
+ const SHA1Fingerprint& chain_fingerprint() const {
+ return chain_fingerprint_;
+ }
+
// Gets the DNS names in the certificate. Pursuant to RFC 2818, Section 3.1
// Server Identity, if the certificate has a subjectAltName extension of
// type dNSName, this method gets the DNS names in that extension.
@@ -365,6 +370,10 @@ class NET_EXPORT X509Certificate
// (all zero) fingerprint on failure.
static SHA1Fingerprint CalculateFingerprint(OSCertHandle cert_handle);
+ // Calculates the SHA-1 fingerprint of the certificate and its intermediate
+ // CA certificates. Returns an empty (all zero) fingerprint on failure.
+ SHA1Fingerprint CalculateChainFingerprint() const;
+
private:
friend class base::RefCountedThreadSafe<X509Certificate>;
friend class TestRootCerts; // For unit tests
@@ -472,6 +481,9 @@ class NET_EXPORT X509Certificate
// The fingerprint of this certificate.
SHA1Fingerprint fingerprint_;
+ // The fingerprint of this certificate and its intermediate CA certificates.
+ SHA1Fingerprint chain_fingerprint_;
+
// The serial number of this certificate, DER encoded.
std::string serial_number_;
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index dc7d4e9..0b65c77 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -540,6 +540,7 @@ void X509Certificate::Initialize() {
&valid_expiry_);
fingerprint_ = CalculateFingerprint(cert_handle_);
+ chain_fingerprint_ = CalculateChainFingerprint();
serial_number_ = GetCertSerialNumber(cert_handle_);
}
@@ -1069,6 +1070,30 @@ SHA1Fingerprint X509Certificate::CalculateFingerprint(
return sha1;
}
+SHA1Fingerprint X509Certificate::CalculateChainFingerprint() const {
+ SHA1Fingerprint sha1;
+ memset(sha1.data, 0, sizeof(sha1.data));
+
+ // The CC_SHA(3cc) man page says all CC_SHA1_xxx routines return 1, so
+ // we don't check their return values.
+ CC_SHA1_CTX sha1_ctx;
+ CC_SHA1_Init(&sha1_ctx);
+ CSSM_DATA cert_data;
+ OSStatus status = SecCertificateGetData(cert_handle_, &cert_data);
+ if (status)
+ return sha1;
+ CC_SHA1_Update(&sha1_ctx, cert_data.Data, cert_data.Length);
+ for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
+ status = SecCertificateGetData(intermediate_ca_certs_[i], &cert_data);
+ if (status)
+ return sha1;
+ CC_SHA1_Update(&sha1_ctx, cert_data.Data, cert_data.Length);
+ }
+ CC_SHA1_Final(sha1.data, &sha1_ctx);
+
+ return sha1;
+}
+
bool X509Certificate::SupportsSSLClientAuth() const {
CSSMFields fields;
if (GetCertFields(cert_handle_, &fields) != noErr)
diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc
index 2ca31ba..4a8a4e0 100644
--- a/net/base/x509_certificate_nss.cc
+++ b/net/base/x509_certificate_nss.cc
@@ -677,6 +677,7 @@ void X509Certificate::Initialize() {
ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_);
fingerprint_ = CalculateFingerprint(cert_handle_);
+ chain_fingerprint_ = CalculateChainFingerprint();
serial_number_ = std::string(
reinterpret_cast<char*>(cert_handle_->serialNumber.data),
@@ -1005,6 +1006,26 @@ SHA1Fingerprint X509Certificate::CalculateFingerprint(
return sha1;
}
+SHA1Fingerprint X509Certificate::CalculateChainFingerprint() const {
+ SHA1Fingerprint sha1;
+ memset(sha1.data, 0, sizeof(sha1.data));
+
+ HASHContext* sha1_ctx = HASH_Create(HASH_AlgSHA1);
+ if (!sha1_ctx)
+ return sha1;
+ HASH_Begin(sha1_ctx);
+ HASH_Update(sha1_ctx, cert_handle_->derCert.data, cert_handle_->derCert.len);
+ for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
+ CERTCertificate* ca_cert = intermediate_ca_certs_[i];
+ HASH_Update(sha1_ctx, ca_cert->derCert.data, ca_cert->derCert.len);
+ }
+ unsigned int result_len;
+ HASH_End(sha1_ctx, sha1.data, &result_len, HASH_ResultLenContext(sha1_ctx));
+ HASH_Destroy(sha1_ctx);
+
+ return sha1;
+}
+
// static
X509Certificate::OSCertHandle
X509Certificate::ReadOSCertHandleFromPickle(const Pickle& pickle,
diff --git a/net/base/x509_certificate_openssl.cc b/net/base/x509_certificate_openssl.cc
index a0601a7..0c74bc5 100644
--- a/net/base/x509_certificate_openssl.cc
+++ b/net/base/x509_certificate_openssl.cc
@@ -325,6 +325,7 @@ void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
void X509Certificate::Initialize() {
crypto::EnsureOpenSSLInit();
fingerprint_ = CalculateFingerprint(cert_handle_);
+ chain_fingerprint_ = CalculateChainFingerprint();
ASN1_INTEGER* num = X509_get_serialNumber(cert_handle_);
if (num) {
@@ -347,6 +348,7 @@ void X509Certificate::ResetCertStore() {
X509InitSingleton::GetInstance()->ResetCertStore();
}
+// static
SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) {
SHA1Fingerprint sha1;
unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data));
@@ -356,6 +358,26 @@ SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) {
return sha1;
}
+SHA1Fingerprint X509Certificate::CalculateChainFingerprint() const {
+ SHA1Fingerprint sha1;
+ memset(sha1.data, 0, sizeof(sha1.data));
+
+ SHA_CTX sha1_ctx;
+ SHA1_Init(&sha1_ctx);
+ DERCache der_cache;
+ if (!GetDERAndCacheIfNeeded(cert_handle_, &der_cache))
+ return sha1;
+ SHA1_Update(&sha1_ctx, der_cache.data, der_cache.data_length);
+ for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
+ if (!GetDERAndCacheIfNeeded(intermediate_ca_certs_[i], &der_cache))
+ return sha1;
+ SHA1_Update(&sha1_ctx, der_cache.data, der_cache.data_length);
+ }
+ SHA1_Final(sha1.data, &sha1_ctx);
+
+ return sha1;
+}
+
// static
X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
const char* data, int length) {
diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc
index dba04e9..a42799e 100644
--- a/net/base/x509_certificate_unittest.cc
+++ b/net/base/x509_certificate_unittest.cc
@@ -436,6 +436,47 @@ TEST(X509CertificateTest, SerialNumbers) {
paypal_null_serial, sizeof(paypal_null_serial)) == 0);
}
+TEST(X509CertificateTest, ChainFingerprints) {
+ FilePath certs_dir = GetTestCertsDirectory();
+
+ scoped_refptr<X509Certificate> server_cert =
+ ImportCertFromFile(certs_dir, "salesforce_com_test.pem");
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
+
+ scoped_refptr<X509Certificate> intermediate_cert1 =
+ ImportCertFromFile(certs_dir, "verisign_intermediate_ca_2011.pem");
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert1);
+
+ scoped_refptr<X509Certificate> intermediate_cert2 =
+ ImportCertFromFile(certs_dir, "verisign_intermediate_ca_2016.pem");
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert2);
+
+ X509Certificate::OSCertHandles intermediates;
+ intermediates.push_back(intermediate_cert1->os_cert_handle());
+ scoped_refptr<X509Certificate> cert_chain1 =
+ X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
+ intermediates);
+
+ intermediates.clear();
+ intermediates.push_back(intermediate_cert2->os_cert_handle());
+ scoped_refptr<X509Certificate> cert_chain2 =
+ X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
+ intermediates);
+
+ static const uint8 cert_chain1_fingerprint[20] = {
+ 0x67, 0x78, 0x81, 0xd7, 0x78, 0xca, 0xd5, 0x04, 0x73, 0xf8,
+ 0x95, 0xff, 0xf3, 0x39, 0xe4, 0xcd, 0x5e, 0xf0, 0x79, 0x76
+ };
+ static const uint8 cert_chain2_fingerprint[20] = {
+ 0x8c, 0x93, 0x85, 0xb0, 0x15, 0xd3, 0xa3, 0x0e, 0xe7, 0x4f,
+ 0x42, 0xf4, 0x30, 0xc3, 0xe9, 0x14, 0x12, 0x54, 0xb9, 0x9d
+ };
+ EXPECT_TRUE(memcmp(cert_chain1->chain_fingerprint().data,
+ cert_chain1_fingerprint, 20) == 0);
+ EXPECT_TRUE(memcmp(cert_chain2->chain_fingerprint().data,
+ cert_chain2_fingerprint, 20) == 0);
+}
+
// A regression test for http://crbug.com/31497.
// This certificate will expire on 2012-04-08.
TEST(X509CertificateTest, IntermediateCARequireExplicitPolicy) {
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
index d7b28a2..041fe4d5 100644
--- a/net/base/x509_certificate_win.cc
+++ b/net/base/x509_certificate_win.cc
@@ -4,6 +4,9 @@
#include "net/base/x509_certificate.h"
+#define PRArenaPool PLArenaPool // Required by <blapi.h>.
+#include <blapi.h> // Implement CalculateChainFingerprint() with NSS.
+
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/pickle.h"
@@ -541,6 +544,7 @@ void X509Certificate::Initialize() {
valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
fingerprint_ = CalculateFingerprint(cert_handle_);
+ chain_fingerprint_ = CalculateChainFingerprint();
const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber;
scoped_array<uint8> serial_bytes(new uint8[serial->cbData]);
@@ -1018,6 +1022,30 @@ SHA1Fingerprint X509Certificate::CalculateFingerprint(
return sha1;
}
+// TODO(wtc): This function is implemented with NSS low-level hash
+// functions to ensure it is fast. Reimplement this function with
+// CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead.
+SHA1Fingerprint X509Certificate::CalculateChainFingerprint() const {
+ SHA1Fingerprint sha1;
+ memset(sha1.data, 0, sizeof(sha1.data));
+
+ SHA1Context* sha1_ctx = SHA1_NewContext();
+ if (!sha1_ctx)
+ return sha1;
+ SHA1_Begin(sha1_ctx);
+ SHA1_Update(sha1_ctx, cert_handle_->pbCertEncoded,
+ cert_handle_->cbCertEncoded);
+ for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
+ PCCERT_CONTEXT ca_cert = intermediate_ca_certs_[i];
+ SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded);
+ }
+ unsigned int result_len;
+ SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH);
+ SHA1_DestroyContext(sha1_ctx, PR_TRUE);
+
+ return sha1;
+}
+
// static
X509Certificate::OSCertHandle
X509Certificate::ReadOSCertHandleFromPickle(const Pickle& pickle,
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README
index d782cdb4..42e40e6 100644
--- a/net/data/ssl/certificates/README
+++ b/net/data/ssl/certificates/README
@@ -56,3 +56,11 @@ unit tests.
"mail.google.com". Because it is signed by that CA instead of the true CA
for that host, it will fail the
TransportSecurityState::IsChainOfPublicKeysPermitted test.
+
+- salesforce_com_test.pem
+- verisign_intermediate_ca_2011.pem
+- verisign_intermediate_ca_2016.pem : Certificates for testing two
+ X509Certificate objects that contain the same server certificate but
+ different intermediate CA certificates. The two intermediate CA
+ certificates actually represent the same intermediate CA but have
+ different validity periods.
diff --git a/net/data/ssl/certificates/salesforce_com_test.pem b/net/data/ssl/certificates/salesforce_com_test.pem
new file mode 100644
index 0000000..1522d0b
--- /dev/null
+++ b/net/data/ssl/certificates/salesforce_com_test.pem
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 30:88:41:0a:28:b4:3e:3d:9a:f3:b3:90:a0:24:bc:d6
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O=VeriSign Trust Network, OU=VeriSign, Inc., OU=VeriSign International Server CA - Class 3, OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign
+ Validity
+ Not Before: Sep 18 00:00:00 2010 GMT
+ Not After : Sep 18 23:59:59 2012 GMT
+ Subject: C=US, ST=California, L=San Francisco, O=Salesforce.com, Inc., OU=Applications, CN=prerelna1.pre.salesforce.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b8:0d:04:b7:23:60:d2:ff:12:bb:29:43:81:30:
+ 0f:dd:8b:cd:cc:2c:8d:d0:14:de:5c:7b:a3:33:ea:
+ f2:7e:88:6e:04:42:17:70:67:91:a8:20:87:81:a8:
+ be:c4:57:d5:f5:3c:cf:34:96:cb:fb:7c:c3:db:ba:
+ 36:c2:08:9f:c1:1d:91:fa:b7:21:03:50:32:bb:30:
+ be:ff:f8:bf:8d:c0:7d:16:e4:d2:81:ef:e2:1a:89:
+ 13:7c:40:6d:dd:1f:32:9d:3f:ca:a2:ab:e6:ae:9f:
+ 96:91:66:32:e9:e5:ca:e3:9d:fc:62:31:aa:de:a6:
+ 50:21:ba:e2:8e:77:00:41:17
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ X509v3 CRL Distribution Points:
+ URI:http://SVRIntl-crl.verisign.com/SVRIntl.crl
+
+ X509v3 Certificate Policies:
+ Policy: 2.16.840.1.113733.1.7.23.3
+ CPS: https://www.verisign.com/rpa
+
+ X509v3 Extended Key Usage:
+ Netscape Server Gated Crypto, TLS Web Server Authentication, TLS Web Client Authentication
+ Authority Information Access:
+ OCSP - URI:http://ocsp.verisign.com
+ CA Issuers - URI:http://SVRIntl-aia.verisign.com/SVRIntl-aia.cer
+
+ 1.3.6.1.5.5.7.1.12:
+ 0`.^.\0Z0X0V..image/gif0!0.0...+......Kk.(.....R8.).K..!..0&.$http://logo.verisign.com/vslogo1.gif
+ Signature Algorithm: sha1WithRSAEncryption
+ b8:e3:37:ba:5a:37:37:bf:e5:bc:88:fe:1e:fa:b4:4f:7d:52:
+ ca:26:b6:83:a1:de:28:6b:01:a8:cd:5d:f2:9a:2c:f0:6e:89:
+ 69:ab:94:b5:14:f2:c3:ca:d8:5d:2f:6d:13:9a:83:f1:ed:4e:
+ 85:87:93:69:19:53:3a:a4:f1:98:96:b7:28:13:32:7e:d2:e4:
+ 7a:7a:f2:8d:80:7d:af:89:64:43:7b:f6:05:3d:16:7c:f1:2a:
+ 6f:bb:9b:3a:57:a5:f1:f7:77:a0:07:68:92:39:bd:45:c7:c8:
+ 75:ed:ac:c6:ac:45:02:18:0b:41:ba:01:68:3e:c2:3b:f6:8b:
+ 4e:50
+-----BEGIN CERTIFICATE-----
+MIIEhzCCA/CgAwIBAgIQMIhBCii0Pj2a87OQoCS81jANBgkqhkiG9w0BAQUFADCB
+ujEfMB0GA1UEChMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEXMBUGA1UECxMOVmVy
+aVNpZ24sIEluYy4xMzAxBgNVBAsTKlZlcmlTaWduIEludGVybmF0aW9uYWwgU2Vy
+dmVyIENBIC0gQ2xhc3MgMzFJMEcGA1UECxNAd3d3LnZlcmlzaWduLmNvbS9DUFMg
+SW5jb3JwLmJ5IFJlZi4gTElBQklMSVRZIExURC4oYyk5NyBWZXJpU2lnbjAeFw0x
+MDA5MTgwMDAwMDBaFw0xMjA5MTgyMzU5NTlaMIGXMQswCQYDVQQGEwJVUzETMBEG
+A1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxQNU2FuIEZyYW5jaXNjbzEdMBsGA1UE
+ChQUU2FsZXNmb3JjZS5jb20sIEluYy4xFTATBgNVBAsUDEFwcGxpY2F0aW9uczEl
+MCMGA1UEAxQccHJlcmVsbmExLnByZS5zYWxlc2ZvcmNlLmNvbTCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAuA0EtyNg0v8SuylDgTAP3YvNzCyN0BTeXHujM+ry
+fohuBEIXcGeRqCCHgai+xFfV9TzPNJbL+3zD27o2wgifwR2R+rchA1AyuzC+//i/
+jcB9FuTSge/iGokTfEBt3R8ynT/Koqvmrp+WkWYy6eXK4538YjGq3qZQIbrijncA
+QRcCAwEAAaOCAa0wggGpMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMDwGA1UdHwQ1
+MDMwMaAvoC2GK2h0dHA6Ly9TVlJJbnRsLWNybC52ZXJpc2lnbi5jb20vU1ZSSW50
+bC5jcmwwRAYDVR0gBD0wOzA5BgtghkgBhvhFAQcXAzAqMCgGCCsGAQUFBwIBFhxo
+dHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMCgGA1UdJQQhMB8GCWCGSAGG+EIE
+AQYIKwYBBQUHAwEGCCsGAQUFBwMCMHEGCCsGAQUFBwEBBGUwYzAkBggrBgEFBQcw
+AYYYaHR0cDovL29jc3AudmVyaXNpZ24uY29tMDsGCCsGAQUFBzAChi9odHRwOi8v
+U1ZSSW50bC1haWEudmVyaXNpZ24uY29tL1NWUkludGwtYWlhLmNlcjBuBggrBgEF
+BQcBDARiMGChXqBcMFowWDBWFglpbWFnZS9naWYwITAfMAcGBSsOAwIaBBRLa7ko
+lgYMu9BSOJsprEsHiyEFGDAmFiRodHRwOi8vbG9nby52ZXJpc2lnbi5jb20vdnNs
+b2dvMS5naWYwDQYJKoZIhvcNAQEFBQADgYEAuOM3ulo3N7/lvIj+Hvq0T31Syia2
+g6HeKGsBqM1d8pos8G6JaauUtRTyw8rYXS9tE5qD8e1OhYeTaRlTOqTxmJa3KBMy
+ftLkenryjYB9r4lkQ3v2BT0WfPEqb7ubOlel8fd3oAdokjm9RcfIde2sxqxFAhgL
+QboBaD7CO/aLTlA=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/verisign_intermediate_ca_2011.pem b/net/data/ssl/certificates/verisign_intermediate_ca_2011.pem
new file mode 100644
index 0000000..27dc85b
--- /dev/null
+++ b/net/data/ssl/certificates/verisign_intermediate_ca_2011.pem
@@ -0,0 +1,71 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 25:4b:8a:85:38:42:cc:e3:58:f8:c5:dd:ae:22:6e:a4
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
+ Validity
+ Not Before: Apr 17 00:00:00 1997 GMT
+ Not After : Oct 24 23:59:59 2011 GMT
+ Subject: O=VeriSign Trust Network, OU=VeriSign, Inc., OU=VeriSign International Server CA - Class 3, OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d8:82:80:e8:d6:19:02:7d:1f:85:18:39:25:a2:
+ 65:2b:e1:bf:d4:05:d3:bc:e6:36:3b:aa:f0:4c:6c:
+ 5b:b6:e7:aa:3c:73:45:55:b2:f1:bd:ea:97:42:ed:
+ 9a:34:0a:15:d4:a9:5c:f5:40:25:dd:d9:07:c1:32:
+ b2:75:6c:c4:ca:bb:a3:fe:56:27:71:43:aa:63:f5:
+ 30:3e:93:28:e5:fa:f1:09:3b:f3:b7:4d:4e:39:f7:
+ 5c:49:5a:b8:c1:1d:d3:b2:8a:fe:70:30:95:42:cb:
+ fe:2b:51:8b:5a:3c:3a:f9:22:4f:90:b2:02:a7:53:
+ 9c:4f:34:e7:ab:04:b2:7b:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:TRUE, pathlen:0
+ X509v3 Certificate Policies:
+ Policy: 2.16.840.1.113733.1.7.1.1
+ CPS: https://www.verisign.com/CPS
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication, Netscape Server Gated Crypto, 2.16.840.1.113733.1.8.1
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ Netscape Cert Type:
+ SSL CA, S/MIME CA
+ X509v3 CRL Distribution Points:
+ URI:http://crl.verisign.com/pca3.crl
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 08:01:ec:e4:68:94:03:42:f1:73:f1:23:a2:3a:de:e9:f1:da:
+ c6:54:c4:23:3e:86:ea:cf:6a:3a:33:ab:ea:9c:04:14:07:36:
+ 06:0b:f9:88:6f:d5:13:ee:29:2b:c3:e4:72:8d:44:ed:d1:ac:
+ 20:09:2d:e1:f6:e1:19:05:38:b0:3d:0f:9f:7f:f8:9e:02:dc:
+ 86:02:86:61:4e:26:5f:5e:9f:92:1e:0c:24:a4:f5:d0:70:13:
+ cf:26:c3:43:3d:49:1d:9e:82:2e:52:5f:bc:3e:c6:66:29:01:
+ 8e:4e:92:2c:bc:46:75:03:82:ac:73:e9:d9:7e:0b:67:ef:54:
+ 52:1a
+-----BEGIN CERTIFICATE-----
+MIIDgzCCAuygAwIBAgIQJUuKhThCzONY+MXdriJupDANBgkqhkiG9w0BAQUFADBf
+MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT
+LkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
+HhcNOTcwNDE3MDAwMDAwWhcNMTExMDI0MjM1OTU5WjCBujEfMB0GA1UEChMWVmVy
+aVNpZ24gVHJ1c3QgTmV0d29yazEXMBUGA1UECxMOVmVyaVNpZ24sIEluYy4xMzAx
+BgNVBAsTKlZlcmlTaWduIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gQ2xhc3Mg
+MzFJMEcGA1UECxNAd3d3LnZlcmlzaWduLmNvbS9DUFMgSW5jb3JwLmJ5IFJlZi4g
+TElBQklMSVRZIExURC4oYyk5NyBWZXJpU2lnbjCBnzANBgkqhkiG9w0BAQEFAAOB
+jQAwgYkCgYEA2IKA6NYZAn0fhRg5JaJlK+G/1AXTvOY2O6rwTGxbtueqPHNFVbLx
+veqXQu2aNAoV1Klc9UAl3dkHwTKydWzEyruj/lYncUOqY/UwPpMo5frxCTvzt01O
+OfdcSVq4wR3Tsor+cDCVQsv+K1GLWjw6+SJPkLICp1OcTzTnqwSye28CAwEAAaOB
+4zCB4DAPBgNVHRMECDAGAQH/AgEAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQEw
+KjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL0NQUzA0BgNV
+HSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIGCWCGSAGG+EIEAQYKYIZIAYb4RQEI
+ATALBgNVHQ8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgEGMDEGA1UdHwQqMCgwJqAk
+oCKGIGh0dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMuY3JsMA0GCSqGSIb3DQEB
+BQUAA4GBAAgB7ORolANC8XPxI6I63unx2sZUxCM+hurPajozq+qcBBQHNgYL+Yhv
+1RPuKSvD5HKNRO3RrCAJLeH24RkFOLA9D59/+J4C3IYChmFOJl9en5IeDCSk9dBw
+E88mw0M9SR2egi5SX7w+xmYpAY5Okiy8RnUDgqxz6dl+C2fvVFIa
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/verisign_intermediate_ca_2016.pem b/net/data/ssl/certificates/verisign_intermediate_ca_2016.pem
new file mode 100644
index 0000000..195133e79
--- /dev/null
+++ b/net/data/ssl/certificates/verisign_intermediate_ca_2016.pem
@@ -0,0 +1,71 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 46:fc:eb:ba:b4:d0:2f:0f:92:60:98:23:3f:93:07:8f
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
+ Validity
+ Not Before: Apr 17 00:00:00 1997 GMT
+ Not After : Oct 24 23:59:59 2016 GMT
+ Subject: O=VeriSign Trust Network, OU=VeriSign, Inc., OU=VeriSign International Server CA - Class 3, OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d8:82:80:e8:d6:19:02:7d:1f:85:18:39:25:a2:
+ 65:2b:e1:bf:d4:05:d3:bc:e6:36:3b:aa:f0:4c:6c:
+ 5b:b6:e7:aa:3c:73:45:55:b2:f1:bd:ea:97:42:ed:
+ 9a:34:0a:15:d4:a9:5c:f5:40:25:dd:d9:07:c1:32:
+ b2:75:6c:c4:ca:bb:a3:fe:56:27:71:43:aa:63:f5:
+ 30:3e:93:28:e5:fa:f1:09:3b:f3:b7:4d:4e:39:f7:
+ 5c:49:5a:b8:c1:1d:d3:b2:8a:fe:70:30:95:42:cb:
+ fe:2b:51:8b:5a:3c:3a:f9:22:4f:90:b2:02:a7:53:
+ 9c:4f:34:e7:ab:04:b2:7b:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:TRUE, pathlen:0
+ X509v3 Certificate Policies:
+ Policy: 2.16.840.1.113733.1.7.1.1
+ CPS: https://www.verisign.com/CPS
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication, Netscape Server Gated Crypto, 2.16.840.1.113733.1.8.1
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ Netscape Cert Type:
+ SSL CA, S/MIME CA
+ X509v3 CRL Distribution Points:
+ URI:http://crl.verisign.com/pca3.crl
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 40:8e:49:97:96:8a:73:dd:8e:4d:ef:3e:61:b7:ca:a0:62:ad:
+ f4:0e:0a:bb:75:3d:e2:6e:d8:2c:c7:bf:f4:b9:8c:36:9b:ca:
+ a2:d0:9c:72:46:39:f6:a6:82:03:65:11:c4:bc:bf:2d:a6:f5:
+ d9:3b:0a:b5:98:fa:b3:78:b9:1e:f2:2b:4c:62:d5:fd:b2:7a:
+ 1d:df:33:fd:73:f9:a5:d8:2d:8c:2a:ea:d1:fc:b0:28:b6:e9:
+ 49:48:13:4b:83:8a:1b:48:7b:24:f7:38:de:6f:41:54:b8:ab:
+ 57:6b:06:df:c7:a2:d4:a9:f6:f1:36:62:80:88:f2:8b:75:d6:
+ 80:71
+-----BEGIN CERTIFICATE-----
+MIIDgzCCAuygAwIBAgIQRvzrurTQLw+SYJgjP5MHjzANBgkqhkiG9w0BAQUFADBf
+MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT
+LkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
+HhcNOTcwNDE3MDAwMDAwWhcNMTYxMDI0MjM1OTU5WjCBujEfMB0GA1UEChMWVmVy
+aVNpZ24gVHJ1c3QgTmV0d29yazEXMBUGA1UECxMOVmVyaVNpZ24sIEluYy4xMzAx
+BgNVBAsTKlZlcmlTaWduIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gQ2xhc3Mg
+MzFJMEcGA1UECxNAd3d3LnZlcmlzaWduLmNvbS9DUFMgSW5jb3JwLmJ5IFJlZi4g
+TElBQklMSVRZIExURC4oYyk5NyBWZXJpU2lnbjCBnzANBgkqhkiG9w0BAQEFAAOB
+jQAwgYkCgYEA2IKA6NYZAn0fhRg5JaJlK+G/1AXTvOY2O6rwTGxbtueqPHNFVbLx
+veqXQu2aNAoV1Klc9UAl3dkHwTKydWzEyruj/lYncUOqY/UwPpMo5frxCTvzt01O
+OfdcSVq4wR3Tsor+cDCVQsv+K1GLWjw6+SJPkLICp1OcTzTnqwSye28CAwEAAaOB
+4zCB4DAPBgNVHRMECDAGAQH/AgEAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQEw
+KjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL0NQUzA0BgNV
+HSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIGCWCGSAGG+EIEAQYKYIZIAYb4RQEI
+ATALBgNVHQ8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgEGMDEGA1UdHwQqMCgwJqAk
+oCKGIGh0dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMuY3JsMA0GCSqGSIb3DQEB
+BQUAA4GBAECOSZeWinPdjk3vPmG3yqBirfQOCrt1PeJu2CzHv/S5jDabyqLQnHJG
+OfamggNlEcS8vy2m9dk7CrWY+rN4uR7yK0xi1f2yeh3fM/1z+aXYLYwq6tH8sCi2
+6UlIE0uDihtIeyT3ON5vQVS4q1drBt/HotSp9vE2YoCI8ot11oBx
+-----END CERTIFICATE-----