summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreranm@google.com <eranm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-19 04:23:10 +0000
committereranm@google.com <eranm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-19 04:23:10 +0000
commitf5c82e82d06b5ecb640e78b549460479f59ea8e7 (patch)
tree47f8b5cbbb2ca33e80d14cbc10f877253e382b95
parent3d6a8298c13dc5062898762839daad2e957f0c99 (diff)
downloadchromium_src-f5c82e82d06b5ecb640e78b549460479f59ea8e7.zip
chromium_src-f5c82e82d06b5ecb640e78b549460479f59ea8e7.tar.gz
chromium_src-f5c82e82d06b5ecb640e78b549460479f59ea8e7.tar.bz2
CT: Adding SCT and PreCertificates extractor. This code creates the
LogEntry structure over which Signed Certificate Timestamps can be verified (and the unit tests demonstrate this). BUG=309578 Review URL: https://codereview.chromium.org/65863002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@235915 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/cert/ct_objects_extractor.h52
-rw-r--r--net/cert/ct_objects_extractor_nss.cc284
-rw-r--r--net/cert/ct_objects_extractor_openssl.cc33
-rw-r--r--net/cert/ct_objects_extractor_unittest.cc125
-rw-r--r--net/cert/ct_serialization_unittest.cc6
-rw-r--r--net/data/ssl/certificates/README3
-rw-r--r--net/data/ssl/certificates/ct-test-embedded-cert.pem126
-rw-r--r--net/net.gyp10
-rw-r--r--net/test/ct_test_util.cc6
-rw-r--r--net/test/ct_test_util.h7
10 files changed, 646 insertions, 6 deletions
diff --git a/net/cert/ct_objects_extractor.h b/net/cert/ct_objects_extractor.h
new file mode 100644
index 0000000..de47c852
--- /dev/null
+++ b/net/cert/ct_objects_extractor.h
@@ -0,0 +1,52 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_CERT_CT_OBJECTS_EXTRACTOR_H_
+#define NET_CERT_CT_OBJECTS_EXTRACTOR_H_
+
+#include <string>
+
+#include "net/base/net_export.h"
+#include "net/cert/x509_certificate.h"
+
+namespace net {
+
+namespace ct {
+
+struct LogEntry;
+
+// Extracts a SignedCertificateTimestampList that has been embedded within a
+// leaf cert as an X.509v3 extension with the OID 1.3.6.1.4.1.11129.2.4.2.
+// If the extension is present, returns true, updating |*sct_list| to contain
+// the encoded list, minus the DER encoding necessary for the extension.
+// |*sct_list| can then be further decoded with ct::DecodeSCTList
+NET_EXPORT_PRIVATE bool ExtractEmbeddedSCTList(
+ X509Certificate::OSCertHandle cert,
+ std::string* sct_list);
+
+// Obtains a PrecertChain log entry for |leaf|, an X.509v3 certificate that
+// contains an X.509v3 extension with the OID 1.3.6.1.4.1.11129.2.4.2. On
+// success, fills |*result| with the data for a PrecertChain log entry and
+// returns true.
+// The filled |*result| should be verified using ct::CTLogVerifier::Verify
+// Note: If |leaf| does not contain the required extension, it is treated as
+// a failure.
+NET_EXPORT_PRIVATE bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf,
+ X509Certificate::OSCertHandle issuer,
+ LogEntry* result);
+
+// Obtains an X509Chain log entry for |leaf|, an X.509v3 certificate that
+// is not expected to contain an X.509v3 extension with the OID
+// 1.3.6.1.4.1.11129.2.4.2 (meaning a certificate without an embedded SCT).
+// On success, fills |result| with the data for an X509Chain log entry and
+// returns true.
+// The filled |*result| should be verified using ct::CTLogVerifier::Verify
+NET_EXPORT_PRIVATE bool GetX509LogEntry(X509Certificate::OSCertHandle leaf,
+ LogEntry* result);
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_CT_OBJECTS_EXTRACTOR_H_
diff --git a/net/cert/ct_objects_extractor_nss.cc b/net/cert/ct_objects_extractor_nss.cc
new file mode 100644
index 0000000..97b8590
--- /dev/null
+++ b/net/cert/ct_objects_extractor_nss.cc
@@ -0,0 +1,284 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/ct_objects_extractor.h"
+
+#include <cert.h>
+#include <secasn1.h>
+#include <secitem.h>
+#include <secoid.h>
+
+#include "base/lazy_instance.h"
+#include "crypto/scoped_nss_types.h"
+#include "crypto/sha2.h"
+#include "net/cert/asn1_util.h"
+#include "net/cert/signed_certificate_timestamp.h"
+
+namespace net {
+
+namespace ct {
+
+namespace {
+
+struct FreeCERTCertificate {
+ public:
+ inline void operator()(CERTCertificate* x) const {
+ CERT_DestroyCertificate(x);
+ }
+};
+
+typedef scoped_ptr_malloc<CERTCertificate, FreeCERTCertificate>
+ ScopedCERTCertificate;
+
+// Wrapper class to convert a X509Certificate::OSCertHandle directly
+// into a CERTCertificate* usable with other NSS functions. This is used for
+// platforms where X509Certificate::OSCertHandle refers to a different type
+// than a CERTCertificate*.
+struct NSSCertWrapper {
+ explicit NSSCertWrapper(X509Certificate::OSCertHandle cert_handle);
+ ~NSSCertWrapper() {}
+
+ ScopedCERTCertificate cert;
+};
+
+NSSCertWrapper::NSSCertWrapper(X509Certificate::OSCertHandle cert_handle) {
+#if defined(USE_NSS)
+ cert.reset(CERT_DupCertificate(cert_handle));
+#else
+ SECItem der_cert;
+ std::string der_data;
+ if (!X509Certificate::GetDEREncoded(cert_handle, &der_data))
+ return;
+ der_cert.data =
+ reinterpret_cast<unsigned char*>(const_cast<char*>(der_data.data()));
+ der_cert.len = der_data.size();
+
+ // Note: CERT_NewTempCertificate may return NULL if the certificate
+ // shares a serial number with another cert issued by the same CA,
+ // which is not supposed to happen.
+ cert.reset(CERT_NewTempCertificate(
+ CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE));
+#endif
+ DCHECK(cert.get() != NULL);
+}
+
+// The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of
+// RFC6962.
+static const unsigned char kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
+ 0xD6, 0x79, 0x02, 0x04, 0x02};
+static const char kEmbeddedSCTDescription[] =
+ "X.509v3 Certificate Transparency Embedded Signed Certificate Timestamp "
+ "List";
+
+// Initializes the necessary NSS internals for use with Certificate
+// Transparency.
+class CTInitSingleton {
+ public:
+ SECOidTag embedded_oid() const { return embedded_oid_; }
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<CTInitSingleton>;
+
+ CTInitSingleton() : embedded_oid_(SEC_OID_UNKNOWN) {
+ embedded_oid_ = RegisterOid(
+ kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), kEmbeddedSCTDescription);
+ }
+
+ ~CTInitSingleton() {}
+
+ SECOidTag RegisterOid(const unsigned char* oid,
+ unsigned int oid_len,
+ const char* description) {
+ SECOidData oid_data;
+ oid_data.oid.len = oid_len;
+ oid_data.oid.data = const_cast<unsigned char*>(oid);
+ oid_data.offset = SEC_OID_UNKNOWN;
+ oid_data.desc = description;
+ oid_data.mechanism = CKM_INVALID_MECHANISM;
+ // Setting this to SUPPORTED_CERT_EXTENSION ensures that if a certificate
+ // contains this extension with the critical bit set, NSS will not reject
+ // it. However, because verification of this extension happens after NSS,
+ // it is currently left as INVALID_CERT_EXTENSION.
+ oid_data.supportedExtension = INVALID_CERT_EXTENSION;
+
+ SECOidTag result = SECOID_AddEntry(&oid_data);
+ CHECK_NE(SEC_OID_UNKNOWN, result);
+
+ return result;
+ }
+
+ SECOidTag embedded_oid_;
+
+ DISALLOW_COPY_AND_ASSIGN(CTInitSingleton);
+};
+
+base::LazyInstance<CTInitSingleton>::Leaky g_ct_singleton =
+ LAZY_INSTANCE_INITIALIZER;
+
+// Obtains the data for an X.509v3 certificate extension identified by |oid|
+// and encoded as an OCTET STRING. Returns true if the extension was found,
+// updating |ext_data| to be the extension data after removing the DER
+// encoding of OCTET STRING.
+bool GetOctetStringExtension(CERTCertificate* cert,
+ SECOidTag oid,
+ std::string* extension_data) {
+ SECItem extension;
+ SECStatus rv = CERT_FindCertExtension(cert, oid, &extension);
+ if (rv != SECSuccess)
+ return false;
+
+ base::StringPiece raw_data(reinterpret_cast<char*>(extension.data),
+ extension.len);
+ base::StringPiece parsed_data;
+ if (!asn1::GetElement(&raw_data, asn1::kOCTETSTRING, &parsed_data)) {
+ rv = SECFailure;
+ } else {
+ if (raw_data.size() > 0)
+ return false; // leftover data
+ parsed_data.CopyToString(extension_data);
+ }
+
+ SECITEM_FreeItem(&extension, PR_FALSE);
+ return rv == SECSuccess;
+}
+
+// Given a |cert|, extract the TBSCertificate from this certificate, also
+// removing X.509 extensions with OID 1.3.6.1.4.1.11129.2.4.2 (that is,
+// the embedded SCT)
+bool ExtractTBSCertWithoutSCTs(CERTCertificate* cert,
+ std::string* to_be_signed) {
+ SECOidData* oid = SECOID_FindOIDByTag(g_ct_singleton.Get().embedded_oid());
+ if (!oid)
+ return false;
+
+ // This is a giant hack, due to the fact that NSS does not expose a good API
+ // for simply removing certificate fields from existing certificates.
+ CERTCertificate temp_cert;
+ temp_cert = *cert;
+ temp_cert.extensions = NULL;
+
+ // Strip out the embedded SCT OID from the new certificate by directly
+ // mutating the extensions in place.
+ std::vector<CERTCertExtension*> new_extensions;
+ if (cert->extensions) {
+ for (CERTCertExtension** exts = cert->extensions; *exts; ++exts) {
+ CERTCertExtension* ext = *exts;
+ SECComparison result = SECITEM_CompareItem(&oid->oid, &ext->id);
+ if (result != SECEqual)
+ new_extensions.push_back(ext);
+ }
+ }
+ if (!new_extensions.empty()) {
+ new_extensions.push_back(NULL);
+ temp_cert.extensions = &new_extensions[0];
+ }
+
+ crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+
+ SECItem tbs_data;
+ tbs_data.len = 0;
+ tbs_data.data = NULL;
+ void* result = SEC_ASN1EncodeItem(arena.get(),
+ &tbs_data,
+ &temp_cert,
+ SEC_ASN1_GET(CERT_CertificateTemplate));
+ if (!result)
+ return false;
+
+ to_be_signed->assign(reinterpret_cast<char*>(tbs_data.data), tbs_data.len);
+ return true;
+}
+
+} // namespace
+
+bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert,
+ std::string* sct_list) {
+ DCHECK(cert);
+
+ NSSCertWrapper leaf_cert(cert);
+ if (!leaf_cert.cert)
+ return false;
+
+ return GetOctetStringExtension(
+ leaf_cert.cert.get(), g_ct_singleton.Get().embedded_oid(), sct_list);
+}
+
+bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf,
+ X509Certificate::OSCertHandle issuer,
+ LogEntry* result) {
+ DCHECK(leaf);
+ DCHECK(issuer);
+
+ NSSCertWrapper leaf_cert(leaf);
+ NSSCertWrapper issuer_cert(issuer);
+
+ result->Reset();
+ // XXX(rsleevi): This check may be overkill, since we should be able to
+ // generate precerts for certs without the extension. For now, just a sanity
+ // check to match the reference implementation.
+ SECItem extension;
+ SECStatus rv = CERT_FindCertExtension(
+ leaf_cert.cert.get(), g_ct_singleton.Get().embedded_oid(), &extension);
+ if (rv != SECSuccess)
+ return false;
+ SECITEM_FreeItem(&extension, PR_FALSE);
+
+ std::string to_be_signed;
+ if (!ExtractTBSCertWithoutSCTs(leaf_cert.cert.get(), &to_be_signed))
+ return false;
+
+ if (!issuer_cert.cert) {
+ // This can happen when the issuer and leaf certs share the same serial
+ // number and are from the same CA, which should never be the case
+ // (but happened with bad test certs).
+ VLOG(1) << "Issuer cert is null, cannot generate Precert entry.";
+ return false;
+ }
+
+ SECKEYPublicKey* issuer_pub_key =
+ SECKEY_ExtractPublicKey(&(issuer_cert.cert->subjectPublicKeyInfo));
+ if (!issuer_pub_key) {
+ VLOG(1) << "Could not extract issuer public key, "
+ << "cannot generate Precert entry.";
+ return false;
+ }
+
+ SECItem* encoded_issuer_pubKey =
+ SECKEY_EncodeDERSubjectPublicKeyInfo(issuer_pub_key);
+ if (!encoded_issuer_pubKey) {
+ SECKEY_DestroyPublicKey(issuer_pub_key);
+ return false;
+ }
+
+ result->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT;
+ result->tbs_certificate.swap(to_be_signed);
+
+ crypto::SHA256HashString(
+ base::StringPiece(reinterpret_cast<char*>(encoded_issuer_pubKey->data),
+ encoded_issuer_pubKey->len),
+ result->issuer_key_hash.data,
+ sizeof(result->issuer_key_hash.data));
+
+ SECITEM_FreeItem(encoded_issuer_pubKey, PR_TRUE);
+ SECKEY_DestroyPublicKey(issuer_pub_key);
+
+ return true;
+}
+
+bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) {
+ DCHECK(leaf);
+
+ std::string encoded;
+ if (!X509Certificate::GetDEREncoded(leaf, &encoded))
+ return false;
+
+ result->Reset();
+ result->type = ct::LogEntry::LOG_ENTRY_TYPE_X509;
+ result->leaf_certificate.swap(encoded);
+ return true;
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/net/cert/ct_objects_extractor_openssl.cc b/net/cert/ct_objects_extractor_openssl.cc
new file mode 100644
index 0000000..3fb5f2c
--- /dev/null
+++ b/net/cert/ct_objects_extractor_openssl.cc
@@ -0,0 +1,33 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/ct_objects_extractor.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+namespace ct {
+
+bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert,
+ std::string* sct_list) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf,
+ X509Certificate::OSCertHandle issuer,
+ LogEntry* result) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/net/cert/ct_objects_extractor_unittest.cc b/net/cert/ct_objects_extractor_unittest.cc
new file mode 100644
index 0000000..30ababd
--- /dev/null
+++ b/net/cert/ct_objects_extractor_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/ct_objects_extractor.h"
+
+#include "base/files/file_path.h"
+#include "net/base/test_data_directory.h"
+#include "net/cert/ct_log_verifier.h"
+#include "net/cert/ct_serialization.h"
+#include "net/cert/signed_certificate_timestamp.h"
+#include "net/cert/x509_certificate.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/ct_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace ct {
+
+class CTObjectsExtractorTest : public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ precert_chain_ =
+ CreateCertificateListFromFile(GetTestCertsDirectory(),
+ "ct-test-embedded-cert.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(2u, precert_chain_.size());
+
+ std::string der_test_cert(ct::GetDerEncodedX509Cert());
+ test_cert_ = X509Certificate::CreateFromBytes(der_test_cert.data(),
+ der_test_cert.length());
+
+ log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog").Pass();
+ ASSERT_TRUE(log_);
+ }
+
+ void ExtractEmbeddedSCT(scoped_refptr<X509Certificate> cert,
+ SignedCertificateTimestamp* sct) {
+ std::string sct_list;
+ EXPECT_TRUE(ExtractEmbeddedSCTList(cert->os_cert_handle(), &sct_list));
+
+ std::vector<base::StringPiece> parsed_scts;
+ base::StringPiece sct_list_sp(sct_list);
+ // Make sure the SCT list can be decoded properly
+ EXPECT_TRUE(DecodeSCTList(&sct_list_sp, &parsed_scts));
+
+ EXPECT_TRUE(DecodeSignedCertificateTimestamp(&parsed_scts[0], sct));
+ }
+
+ protected:
+ CertificateList precert_chain_;
+ scoped_refptr<X509Certificate> test_cert_;
+ scoped_ptr<CTLogVerifier> log_;
+};
+
+// Test that an SCT can be extracted and the extracted SCT contains the
+// expected data.
+TEST_F(CTObjectsExtractorTest, ExtractEmbeddedSCT) {
+ ct::SignedCertificateTimestamp sct;
+ ExtractEmbeddedSCT(precert_chain_[0], &sct);
+
+ EXPECT_EQ(sct.version, SignedCertificateTimestamp::SCT_VERSION_1);
+ EXPECT_EQ(ct::GetTestPublicKeyId(), sct.log_id);
+
+ base::Time expected_timestamp =
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(1365181456275);
+ EXPECT_EQ(expected_timestamp, sct.timestamp);
+}
+
+TEST_F(CTObjectsExtractorTest, ExtractPrecert) {
+ LogEntry entry;
+ ASSERT_TRUE(GetPrecertLogEntry(precert_chain_[0]->os_cert_handle(),
+ precert_chain_[1]->os_cert_handle(),
+ &entry));
+
+ ASSERT_EQ(ct::LogEntry::LOG_ENTRY_TYPE_PRECERT, entry.type);
+ // Should have empty leaf cert for this log entry type.
+ ASSERT_TRUE(entry.leaf_certificate.empty());
+ // Compare hash values of issuer spki.
+ SHA256HashValue expected_issuer_key_hash;
+ memcpy(expected_issuer_key_hash.data, GetDefaultIssuerKeyHash().data(), 32);
+ ASSERT_TRUE(expected_issuer_key_hash.Equals(entry.issuer_key_hash));
+}
+
+TEST_F(CTObjectsExtractorTest, ExtractOrdinaryX509Cert) {
+ LogEntry entry;
+ ASSERT_TRUE(GetX509LogEntry(test_cert_->os_cert_handle(), &entry));
+
+ ASSERT_EQ(ct::LogEntry::LOG_ENTRY_TYPE_X509, entry.type);
+ // Should have empty tbs_certificate for this log entry type.
+ ASSERT_TRUE(entry.tbs_certificate.empty());
+ // Length of leaf_certificate should be 718, see the CT Serialization tests.
+ ASSERT_EQ(718U, entry.leaf_certificate.size());
+}
+
+// Test that the embedded SCT verifies
+TEST_F(CTObjectsExtractorTest, ExtractedSCTVerifies) {
+ ct::SignedCertificateTimestamp sct;
+ ExtractEmbeddedSCT(precert_chain_[0], &sct);
+
+ LogEntry entry;
+ ASSERT_TRUE(GetPrecertLogEntry(precert_chain_[0]->os_cert_handle(),
+ precert_chain_[1]->os_cert_handle(),
+ &entry));
+
+ EXPECT_TRUE(log_->Verify(entry, sct));
+}
+
+// Test that an externally-provided SCT verifies over the LogEntry
+// of a regular X.509 Certificate
+TEST_F(CTObjectsExtractorTest, ComplementarySCTVerifies) {
+ ct::SignedCertificateTimestamp sct;
+ GetX509CertSCT(&sct);
+
+ LogEntry entry;
+ ASSERT_TRUE(GetX509LogEntry(test_cert_->os_cert_handle(), &entry));
+
+ EXPECT_TRUE(log_->Verify(entry, sct));
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/net/cert/ct_serialization_unittest.cc b/net/cert/ct_serialization_unittest.cc
index 9692fb9..03fc034 100644
--- a/net/cert/ct_serialization_unittest.cc
+++ b/net/cert/ct_serialization_unittest.cc
@@ -138,11 +138,7 @@ TEST_F(CtSerializationTest, DecodesSignedCertificateTimestamp) {
ct::SignedCertificateTimestamp sct;
ASSERT_TRUE(ct::DecodeSignedCertificateTimestamp(&encoded_sct, &sct));
EXPECT_EQ(0, sct.version);
- std::string expected_log_key(
- "\xdf\x1c\x2e\xc1\x15\x00\x94\x52\x47\xa9\x61\x68\x32\x5d\xdc\x5c\x79\x59"
- "\xe8\xf7\xc6\xd3\x88\xfc\x00\x2e\x0b\xbd\x3f\x74\xd7\x64",
- 32);
- EXPECT_EQ(expected_log_key, sct.log_id);
+ EXPECT_EQ(ct::GetTestPublicKeyId(), sct.log_id);
base::Time expected_time = base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(1365181456089);
EXPECT_EQ(expected_time, sct.timestamp);
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README
index 01f6dfd..86f10a6 100644
--- a/net/data/ssl/certificates/README
+++ b/net/data/ssl/certificates/README
@@ -226,3 +226,6 @@ unit tests.
http://crbug.com/31497. It is generated by running the script
net/data/ssl/scripts/generate-policy-certs.sh
+- ct-test-embedded-cert.pem
+ Test certificate chain for Certificate Transparency: The leaf certificate
+ in this file contains embedded SCTs, followed by the issuer certificate.
diff --git a/net/data/ssl/certificates/ct-test-embedded-cert.pem b/net/data/ssl/certificates/ct-test-embedded-cert.pem
new file mode 100644
index 0000000..ff4875d
--- /dev/null
+++ b/net/data/ssl/certificates/ct-test-embedded-cert.pem
@@ -0,0 +1,126 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7 (0x7)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:be:ef:98:e7:c2:68:77:ae:38:5f:75:32:5a:0c:
+ 1d:32:9b:ed:f1:8f:aa:f4:d7:96:bf:04:7e:b7:e1:
+ ce:15:c9:5b:a2:f8:0e:e4:58:bd:7d:b8:6f:8a:4b:
+ 25:21:91:a7:9b:d7:00:c3:8e:9c:03:89:b4:5c:d4:
+ dc:9a:12:0a:b2:1e:0c:b4:1c:d0:e7:28:05:a4:10:
+ cd:9c:5b:db:5d:49:27:72:6d:af:17:10:f6:01:87:
+ 37:7e:a2:5b:1a:1e:39:ee:d0:b8:81:19:dc:15:4d:
+ c6:8f:7d:a8:e3:0c:af:15:8a:33:e6:c9:50:9f:4a:
+ 05:b0:14:09:ff:5d:d8:7e:b5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 20:31:54:1A:F2:5C:05:FF:D8:65:8B:68:43:79:4F:5E:90:36:F7:B4
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:FALSE
+ 1.3.6.1.4.1.11129.2.4.2:
+ .z.x.v........RG.ah2].\yY..........?t.d...=.'.......G0E. H/gQ.5..T6...d.=..AB...E0(....>..!.....:.r.....jh.S.}.A.}....Q.....
+ Signature Algorithm: sha1WithRSAEncryption
+ 8a:0c:4b:ef:09:9d:47:92:79:af:a0:a2:8e:68:9f:91:e1:c4:
+ 42:1b:e2:d2:69:a2:ea:6c:a4:e8:21:5d:de:dd:ca:15:04:a1:
+ 1e:7c:87:c4:b7:7e:80:f0:e9:79:03:52:68:f2:7c:a2:0e:16:
+ 68:04:ae:55:6f:31:69:81:f9:6a:39:4a:b7:ab:fd:3e:25:5a:
+ c0:04:45:13:fe:76:57:0c:67:95:ab:e4:70:31:33:d3:03:f8:
+ 9f:3a:fa:6b:bc:fc:51:73:19:df:d9:5b:93:42:41:21:1f:63:
+ 40:35:c3:d0:78:30:7a:68:c6:07:5a:2e:20:c8:9f:36:b8:91:
+ 0c:a0
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIBBzANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMFIxCzAJBgNVBAYTAkdCMSEwHwYDVQQKExhDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kxDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGfMA0G
+CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+75jnwmh3rjhfdTJaDB0ym+3xj6r015a/
+BH634c4VyVui+A7kWL19uG+KSyUhkaeb1wDDjpwDibRc1NyaEgqyHgy0HNDnKAWk
+EM2cW9tdSSdyba8XEPYBhzd+olsaHjnu0LiBGdwVTcaPfajjDK8VijPmyVCfSgWw
+FAn/Xdh+tQIDAQABo4IBOjCCATYwHQYDVR0OBBYEFCAxVBryXAX/2GWLaEN5T16Q
+Nve0MH0GA1UdIwR2MHSAFF+diA3Ic+ZU1PgN2OawwSS0R8NVoVmkVzBVMQswCQYD
+VQQGEwJHQjEkMCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4w
+DAYDVQQIEwVXYWxlczEQMA4GA1UEBxMHRXJ3IFdlboIBADAJBgNVHRMEAjAAMIGK
+BgorBgEEAdZ5AgQCBHwEegB4AHYA3xwuwRUAlFJHqWFoMl3cXHlZ6PfG04j8AC4L
+vT9012QAAAE92yffkwAABAMARzBFAiBIL2dRrzXbplQ2vh/WZA89v5pBQpSVkkUw
+KI+j5eI+BgIhAOTtwNs6xXKx4vXoq2poBlOYfc9BAn3+/6EFUZ2J7b8IMA0GCSqG
+SIb3DQEBBQUAA4GBAIoMS+8JnUeSea+goo5on5HhxEIb4tJpoupspOghXd7dyhUE
+oR58h8S3foDw6XkDUmjyfKIOFmgErlVvMWmB+Wo5Srer/T4lWsAERRP+dlcMZ5Wr
+5HAxM9MD+J86+mu8/FFzGd/ZW5NCQSEfY0A1w9B4MHpoxgdaLiDInza4kQyg
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d5:8a:68:53:62:10:a2:71:19:93:6e:77:83:21:
+ 18:1c:2a:40:13:c6:d0:7b:8c:76:eb:91:57:d3:d0:
+ fb:4b:3b:51:6e:ce:cb:d1:c9:8d:91:c5:2f:74:3f:
+ ab:63:5d:55:09:9c:d1:3a:ba:f3:1a:e5:41:44:24:
+ 51:a7:4c:78:16:f2:24:3c:f8:48:cf:28:31:cc:e6:
+ 7b:a0:4a:5a:23:81:9f:3c:ba:37:e6:24:d9:c3:bd:
+ b2:99:b8:39:dd:fe:26:31:d2:cb:3a:84:fc:7b:b2:
+ b5:c5:2f:cf:c1:4f:ff:40:6f:5c:d4:46:69:cb:b2:
+ f7:cf:df:86:fb:6a:b9:d1:b1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 06:08:cc:4a:6d:64:f2:20:5e:14:6c:04:b2:76:f9:2b:0e:fa:
+ 94:a5:da:f2:3a:fc:38:06:60:6d:39:90:d0:a1:ea:23:3d:40:
+ 29:57:69:46:3b:04:66:61:e7:fa:1d:17:99:15:20:9a:ea:2e:
+ 0a:77:51:76:41:12:27:d7:c0:03:07:c7:47:0e:61:58:4f:d7:
+ 33:42:24:72:7f:51:d6:90:bc:47:a9:df:35:4d:b0:f6:eb:25:
+ 95:5d:e1:89:3c:4d:d5:20:2b:24:a2:f3:e4:40:d2:74:b5:4e:
+ 1b:d3:76:26:9c:a9:62:89:b7:6e:ca:a4:10:90:e1:4f:3b:0a:
+ 94:2e
+-----BEGIN CERTIFICATE-----
+MIIC0DCCAjmgAwIBAgIBADANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVimhTYhCicRmTbneDIRgcKkATxtB7
+jHbrkVfT0PtLO1FuzsvRyY2RxS90P6tjXVUJnNE6uvMa5UFEJFGnTHgW8iQ8+EjP
+KDHM5nugSlojgZ88ujfmJNnDvbKZuDnd/iYx0ss6hPx7srXFL8/BT/9Ab1zURmnL
+svfP34b7arnRsQIDAQABo4GvMIGsMB0GA1UdDgQWBBRfnYgNyHPmVNT4DdjmsMEk
+tEfDVTB9BgNVHSMEdjB0gBRfnYgNyHPmVNT4DdjmsMEktEfDVaFZpFcwVTELMAkG
+A1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5zcGFyZW5jeSBDQTEO
+MAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQUFAAOBgQAGCMxKbWTyIF4UbASydvkrDvqUpdryOvw4BmBt
+OZDQoeojPUApV2lGOwRmYef6HReZFSCa6i4Kd1F2QRIn18ADB8dHDmFYT9czQiRy
+f1HWkLxHqd81TbD26yWVXeGJPE3VICskovPkQNJ0tU4b03YmnKliibduyqQQkOFP
+OwqULg==
+-----END CERTIFICATE-----
diff --git a/net/net.gyp b/net/net.gyp
index 3e5b04b..771fbc8 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -274,6 +274,9 @@
'cert/ct_log_verifier.h',
'cert/ct_log_verifier_nss.cc',
'cert/ct_log_verifier_openssl.cc',
+ 'cert/ct_objects_extractor.h',
+ 'cert/ct_objects_extractor_nss.cc',
+ 'cert/ct_objects_extractor_openssl.cc',
'cert/ct_serialization.cc',
'cert/ct_serialization.h',
'cert/ev_root_ca_metadata.cc',
@@ -1264,6 +1267,7 @@
'cert/cert_verify_proc_nss.cc',
'cert/cert_verify_proc_nss.h',
'cert/ct_log_verifier_nss.cc',
+ 'cert/ct_objects_extractor_nss.cc',
'cert/jwk_serializer_nss.cc',
'cert/nss_cert_database.cc',
'cert/nss_cert_database.h',
@@ -1303,6 +1307,7 @@
'cert/cert_verify_proc_openssl.cc',
'cert/cert_verify_proc_openssl.h',
'cert/ct_log_verifier_openssl.cc',
+ 'cert/ct_objects_extractor_openssl.cc',
'cert/jwk_serializer_openssl.cc',
'cert/test_root_certs_openssl.cc',
'cert/x509_certificate_openssl.cc',
@@ -1592,6 +1597,7 @@
'cert/cert_verify_proc_unittest.cc',
'cert/crl_set_unittest.cc',
'cert/ct_log_verifier_unittest.cc',
+ 'cert/ct_objects_extractor_unittest.cc',
'cert/ct_serialization_unittest.cc',
'cert/ev_root_ca_metadata_unittest.cc',
'cert/jwk_serializer_unittest.cc',
@@ -2053,10 +2059,12 @@
],
}],
[ 'use_openssl==1', {
- # When building for OpenSSL, we need to exclude NSS specific tests.
+ # When building for OpenSSL, we need to exclude NSS specific tests
+ # or functionality not supported by OpenSSL yet.
# TODO(bulach): Add equivalent tests when the underlying
# functionality is ported to OpenSSL.
'sources!': [
+ 'cert/ct_objects_extractor_unittest.cc',
'cert/nss_cert_database_unittest.cc',
'cert/x509_util_nss_unittest.cc',
'quic/test_tools/crypto_test_utils_nss.cc',
diff --git a/net/test/ct_test_util.cc b/net/test/ct_test_util.cc
index b588b13..db690e3 100644
--- a/net/test/ct_test_util.cc
+++ b/net/test/ct_test_util.cc
@@ -108,6 +108,8 @@ void GetX509CertLogEntry(LogEntry* entry) {
entry->leaf_certificate = HexToBytes(kDefaultDerCert);
}
+std::string GetDerEncodedX509Cert() { return HexToBytes(kDefaultDerCert); }
+
void GetPrecertLogEntry(LogEntry* entry) {
entry->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT;
std::string issuer_hash(HexToBytes(kDefaultIssuerKeyHash));
@@ -153,6 +155,10 @@ void GetPrecertSCT(SignedCertificateTimestamp* sct) {
sct->signature.signature_data = HexToBytes(kTestSCTPrecertSignatureData);
}
+std::string GetDefaultIssuerKeyHash() {
+ return HexToBytes(kDefaultIssuerKeyHash);
+}
+
} // namespace ct
} // namespace net
diff --git a/net/test/ct_test_util.h b/net/test/ct_test_util.h
index f12e144..8343cb8 100644
--- a/net/test/ct_test_util.h
+++ b/net/test/ct_test_util.h
@@ -22,6 +22,10 @@ struct SignedCertificateTimestamp;
// Fills |entry| with test data for an X.509 entry.
void GetX509CertLogEntry(LogEntry* entry);
+// Returns a DER-encoded X509 cert. The SCT provided by
+// GetX509CertSCT is signed over this certificate.
+std::string GetDerEncodedX509Cert();
+
// Fills |entry| with test data for a Precertificate entry.
void GetPrecertLogEntry(LogEntry* entry);
@@ -43,6 +47,9 @@ void GetX509CertSCT(SignedCertificateTimestamp* sct);
// SCT for the Precertificate log entry provided above.
void GetPrecertSCT(SignedCertificateTimestamp* sct);
+// Issuer key hash
+std::string GetDefaultIssuerKeyHash();
+
} // namespace ct
} // namespace net