123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- // 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/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 "net/test/test_data_directory.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace net::ct {
- class CTObjectsExtractorTest : public ::testing::Test {
- public:
- 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(
- base::as_bytes(base::make_span(der_test_cert)));
- ASSERT_TRUE(test_cert_);
- log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog");
- ASSERT_TRUE(log_);
- }
- void ExtractEmbeddedSCT(scoped_refptr<X509Certificate> cert,
- scoped_refptr<SignedCertificateTimestamp>* sct) {
- std::string sct_list;
- ASSERT_TRUE(ExtractEmbeddedSCTList(cert->cert_buffer(), &sct_list));
- std::vector<base::StringPiece> parsed_scts;
- // Make sure the SCT list can be decoded properly
- ASSERT_TRUE(DecodeSCTList(sct_list, &parsed_scts));
- ASSERT_EQ(1u, parsed_scts.size());
- EXPECT_TRUE(DecodeSignedCertificateTimestamp(&parsed_scts[0], sct));
- }
- protected:
- CertificateList precert_chain_;
- scoped_refptr<X509Certificate> test_cert_;
- scoped_refptr<const CTLogVerifier> log_;
- };
- // Test that an SCT can be extracted and the extracted SCT contains the
- // expected data.
- TEST_F(CTObjectsExtractorTest, ExtractEmbeddedSCT) {
- auto sct = base::MakeRefCounted<ct::SignedCertificateTimestamp>();
- ExtractEmbeddedSCT(precert_chain_[0], &sct);
- EXPECT_EQ(sct->version, SignedCertificateTimestamp::V1);
- EXPECT_EQ(ct::GetTestPublicKeyId(), sct->log_id);
- base::Time expected_timestamp =
- base::Time::UnixEpoch() + base::Milliseconds(1365181456275);
- EXPECT_EQ(expected_timestamp, sct->timestamp);
- }
- // Test that the extractor correctly skips over issuerUniqueID and
- // subjectUniqueID fields. See https://crbug.com/1199744.
- TEST_F(CTObjectsExtractorTest, ExtractEmbeddedSCTListWithUIDs) {
- CertificateList certs = CreateCertificateListFromFile(
- GetTestCertsDirectory(), "ct-test-embedded-with-uids.pem",
- X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
- ASSERT_EQ(1u, certs.size());
- auto sct = base::MakeRefCounted<ct::SignedCertificateTimestamp>();
- ExtractEmbeddedSCT(certs[0], &sct);
- EXPECT_EQ(sct->version, SignedCertificateTimestamp::V1);
- EXPECT_EQ(ct::GetTestPublicKeyId(), sct->log_id);
- base::Time expected_timestamp =
- base::Time::UnixEpoch() + base::Milliseconds(1365181456275);
- EXPECT_EQ(expected_timestamp, sct->timestamp);
- }
- TEST_F(CTObjectsExtractorTest, ExtractPrecert) {
- SignedEntryData entry;
- ASSERT_TRUE(GetPrecertSignedEntry(precert_chain_[0]->cert_buffer(),
- precert_chain_[1]->cert_buffer(), &entry));
- ASSERT_EQ(ct::SignedEntryData::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_EQ(expected_issuer_key_hash, entry.issuer_key_hash);
- }
- TEST_F(CTObjectsExtractorTest, ExtractOrdinaryX509Cert) {
- SignedEntryData entry;
- ASSERT_TRUE(GetX509SignedEntry(test_cert_->cert_buffer(), &entry));
- ASSERT_EQ(ct::SignedEntryData::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) {
- auto sct = base::MakeRefCounted<ct::SignedCertificateTimestamp>();
- ExtractEmbeddedSCT(precert_chain_[0], &sct);
- SignedEntryData entry;
- ASSERT_TRUE(GetPrecertSignedEntry(precert_chain_[0]->cert_buffer(),
- precert_chain_[1]->cert_buffer(), &entry));
- EXPECT_TRUE(log_->Verify(entry, *sct.get()));
- }
- // Test that an externally-provided SCT verifies over the SignedEntryData
- // of a regular X.509 Certificate
- TEST_F(CTObjectsExtractorTest, ComplementarySCTVerifies) {
- auto sct = base::MakeRefCounted<ct::SignedCertificateTimestamp>();
- GetX509CertSCT(&sct);
- SignedEntryData entry;
- ASSERT_TRUE(GetX509SignedEntry(test_cert_->cert_buffer(), &entry));
- EXPECT_TRUE(log_->Verify(entry, *sct.get()));
- }
- // Test that the extractor can parse OCSP responses.
- TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponse) {
- std::string der_subject_cert(ct::GetDerEncodedFakeOCSPResponseCert());
- scoped_refptr<X509Certificate> subject_cert =
- X509Certificate::CreateFromBytes(
- base::as_bytes(base::make_span(der_subject_cert)));
- ASSERT_TRUE(subject_cert);
- std::string der_issuer_cert(ct::GetDerEncodedFakeOCSPResponseIssuerCert());
- scoped_refptr<X509Certificate> issuer_cert = X509Certificate::CreateFromBytes(
- base::as_bytes(base::make_span(der_issuer_cert)));
- ASSERT_TRUE(issuer_cert);
- std::string fake_sct_list = ct::GetFakeOCSPExtensionValue();
- ASSERT_FALSE(fake_sct_list.empty());
- std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
- std::string extracted_sct_list;
- EXPECT_TRUE(ct::ExtractSCTListFromOCSPResponse(
- issuer_cert->cert_buffer(), subject_cert->serial_number(), ocsp_response,
- &extracted_sct_list));
- EXPECT_EQ(extracted_sct_list, fake_sct_list);
- }
- // Test that the extractor honours serial number.
- TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesSerial) {
- std::string der_issuer_cert(ct::GetDerEncodedFakeOCSPResponseIssuerCert());
- scoped_refptr<X509Certificate> issuer_cert = X509Certificate::CreateFromBytes(
- base::as_bytes(base::make_span(der_issuer_cert)));
- ASSERT_TRUE(issuer_cert);
- std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
- std::string extracted_sct_list;
- EXPECT_FALSE(ct::ExtractSCTListFromOCSPResponse(
- issuer_cert->cert_buffer(), test_cert_->serial_number(), ocsp_response,
- &extracted_sct_list));
- }
- // Test that the extractor honours issuer ID.
- TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesIssuer) {
- std::string der_subject_cert(ct::GetDerEncodedFakeOCSPResponseCert());
- scoped_refptr<X509Certificate> subject_cert =
- X509Certificate::CreateFromBytes(
- base::as_bytes(base::make_span(der_subject_cert)));
- ASSERT_TRUE(subject_cert);
- std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
- std::string extracted_sct_list;
- // Use test_cert_ for issuer - it is not the correct issuer of |subject_cert|.
- EXPECT_FALSE(ct::ExtractSCTListFromOCSPResponse(
- test_cert_->cert_buffer(), subject_cert->serial_number(), ocsp_response,
- &extracted_sct_list));
- }
- } // namespace net::ct
|