• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/cert/ct_objects_extractor.h"
6 
7 #include "base/files/file_path.h"
8 #include "net/cert/ct_log_verifier.h"
9 #include "net/cert/ct_serialization.h"
10 #include "net/cert/signed_certificate_timestamp.h"
11 #include "net/cert/x509_certificate.h"
12 #include "net/test/cert_test_util.h"
13 #include "net/test/ct_test_util.h"
14 #include "net/test/test_data_directory.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace net::ct {
18 
19 class CTObjectsExtractorTest : public ::testing::Test {
20  public:
SetUp()21   void SetUp() override {
22     precert_chain_ =
23         CreateCertificateListFromFile(GetTestCertsDirectory(),
24                                       "ct-test-embedded-cert.pem",
25                                       X509Certificate::FORMAT_AUTO);
26     ASSERT_EQ(2u, precert_chain_.size());
27 
28     std::string der_test_cert(ct::GetDerEncodedX509Cert());
29     test_cert_ = X509Certificate::CreateFromBytes(
30         base::as_bytes(base::make_span(der_test_cert)));
31     ASSERT_TRUE(test_cert_);
32 
33     log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog");
34     ASSERT_TRUE(log_);
35   }
36 
ExtractEmbeddedSCT(scoped_refptr<X509Certificate> cert,scoped_refptr<SignedCertificateTimestamp> * sct)37   void ExtractEmbeddedSCT(scoped_refptr<X509Certificate> cert,
38                           scoped_refptr<SignedCertificateTimestamp>* sct) {
39     std::string sct_list;
40     ASSERT_TRUE(ExtractEmbeddedSCTList(cert->cert_buffer(), &sct_list));
41 
42     std::vector<base::StringPiece> parsed_scts;
43     // Make sure the SCT list can be decoded properly
44     ASSERT_TRUE(DecodeSCTList(sct_list, &parsed_scts));
45     ASSERT_EQ(1u, parsed_scts.size());
46     EXPECT_TRUE(DecodeSignedCertificateTimestamp(&parsed_scts[0], sct));
47   }
48 
49  protected:
50   CertificateList precert_chain_;
51   scoped_refptr<X509Certificate> test_cert_;
52   scoped_refptr<const CTLogVerifier> log_;
53 };
54 
55 // Test that an SCT can be extracted and the extracted SCT contains the
56 // expected data.
TEST_F(CTObjectsExtractorTest,ExtractEmbeddedSCT)57 TEST_F(CTObjectsExtractorTest, ExtractEmbeddedSCT) {
58   auto sct = base::MakeRefCounted<ct::SignedCertificateTimestamp>();
59   ExtractEmbeddedSCT(precert_chain_[0], &sct);
60 
61   EXPECT_EQ(sct->version, SignedCertificateTimestamp::V1);
62   EXPECT_EQ(ct::GetTestPublicKeyId(), sct->log_id);
63 
64   base::Time expected_timestamp =
65       base::Time::UnixEpoch() + base::Milliseconds(1365181456275);
66   EXPECT_EQ(expected_timestamp, sct->timestamp);
67 }
68 
69 // Test that the extractor correctly skips over issuerUniqueID and
70 // subjectUniqueID fields. See https://crbug.com/1199744.
TEST_F(CTObjectsExtractorTest,ExtractEmbeddedSCTListWithUIDs)71 TEST_F(CTObjectsExtractorTest, ExtractEmbeddedSCTListWithUIDs) {
72   CertificateList certs = CreateCertificateListFromFile(
73       GetTestCertsDirectory(), "ct-test-embedded-with-uids.pem",
74       X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
75   ASSERT_EQ(1u, certs.size());
76 
77   auto sct = base::MakeRefCounted<ct::SignedCertificateTimestamp>();
78   ExtractEmbeddedSCT(certs[0], &sct);
79 
80   EXPECT_EQ(sct->version, SignedCertificateTimestamp::V1);
81   EXPECT_EQ(ct::GetTestPublicKeyId(), sct->log_id);
82 
83   base::Time expected_timestamp =
84       base::Time::UnixEpoch() + base::Milliseconds(1365181456275);
85   EXPECT_EQ(expected_timestamp, sct->timestamp);
86 }
87 
TEST_F(CTObjectsExtractorTest,ExtractPrecert)88 TEST_F(CTObjectsExtractorTest, ExtractPrecert) {
89   SignedEntryData entry;
90   ASSERT_TRUE(GetPrecertSignedEntry(precert_chain_[0]->cert_buffer(),
91                                     precert_chain_[1]->cert_buffer(), &entry));
92 
93   ASSERT_EQ(ct::SignedEntryData::LOG_ENTRY_TYPE_PRECERT, entry.type);
94   // Should have empty leaf cert for this log entry type.
95   ASSERT_TRUE(entry.leaf_certificate.empty());
96   // Compare hash values of issuer spki.
97   SHA256HashValue expected_issuer_key_hash;
98   memcpy(expected_issuer_key_hash.data, GetDefaultIssuerKeyHash().data(), 32);
99   ASSERT_EQ(expected_issuer_key_hash, entry.issuer_key_hash);
100 }
101 
TEST_F(CTObjectsExtractorTest,ExtractOrdinaryX509Cert)102 TEST_F(CTObjectsExtractorTest, ExtractOrdinaryX509Cert) {
103   SignedEntryData entry;
104   ASSERT_TRUE(GetX509SignedEntry(test_cert_->cert_buffer(), &entry));
105 
106   ASSERT_EQ(ct::SignedEntryData::LOG_ENTRY_TYPE_X509, entry.type);
107   // Should have empty tbs_certificate for this log entry type.
108   ASSERT_TRUE(entry.tbs_certificate.empty());
109   // Length of leaf_certificate should be 718, see the CT Serialization tests.
110   ASSERT_EQ(718U, entry.leaf_certificate.size());
111 }
112 
113 // Test that the embedded SCT verifies
TEST_F(CTObjectsExtractorTest,ExtractedSCTVerifies)114 TEST_F(CTObjectsExtractorTest, ExtractedSCTVerifies) {
115   auto sct = base::MakeRefCounted<ct::SignedCertificateTimestamp>();
116   ExtractEmbeddedSCT(precert_chain_[0], &sct);
117 
118   SignedEntryData entry;
119   ASSERT_TRUE(GetPrecertSignedEntry(precert_chain_[0]->cert_buffer(),
120                                     precert_chain_[1]->cert_buffer(), &entry));
121 
122   EXPECT_TRUE(log_->Verify(entry, *sct.get()));
123 }
124 
125 // Test that an externally-provided SCT verifies over the SignedEntryData
126 // of a regular X.509 Certificate
TEST_F(CTObjectsExtractorTest,ComplementarySCTVerifies)127 TEST_F(CTObjectsExtractorTest, ComplementarySCTVerifies) {
128   auto sct = base::MakeRefCounted<ct::SignedCertificateTimestamp>();
129   GetX509CertSCT(&sct);
130 
131   SignedEntryData entry;
132   ASSERT_TRUE(GetX509SignedEntry(test_cert_->cert_buffer(), &entry));
133 
134   EXPECT_TRUE(log_->Verify(entry, *sct.get()));
135 }
136 
137 // Test that the extractor can parse OCSP responses.
TEST_F(CTObjectsExtractorTest,ExtractSCTListFromOCSPResponse)138 TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponse) {
139   std::string der_subject_cert(ct::GetDerEncodedFakeOCSPResponseCert());
140   scoped_refptr<X509Certificate> subject_cert =
141       X509Certificate::CreateFromBytes(
142           base::as_bytes(base::make_span(der_subject_cert)));
143   ASSERT_TRUE(subject_cert);
144   std::string der_issuer_cert(ct::GetDerEncodedFakeOCSPResponseIssuerCert());
145   scoped_refptr<X509Certificate> issuer_cert = X509Certificate::CreateFromBytes(
146       base::as_bytes(base::make_span(der_issuer_cert)));
147   ASSERT_TRUE(issuer_cert);
148 
149   std::string fake_sct_list = ct::GetFakeOCSPExtensionValue();
150   ASSERT_FALSE(fake_sct_list.empty());
151   std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
152 
153   std::string extracted_sct_list;
154   EXPECT_TRUE(ct::ExtractSCTListFromOCSPResponse(
155       issuer_cert->cert_buffer(), subject_cert->serial_number(), ocsp_response,
156       &extracted_sct_list));
157   EXPECT_EQ(extracted_sct_list, fake_sct_list);
158 }
159 
160 // Test that the extractor honours serial number.
TEST_F(CTObjectsExtractorTest,ExtractSCTListFromOCSPResponseMatchesSerial)161 TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesSerial) {
162   std::string der_issuer_cert(ct::GetDerEncodedFakeOCSPResponseIssuerCert());
163   scoped_refptr<X509Certificate> issuer_cert = X509Certificate::CreateFromBytes(
164       base::as_bytes(base::make_span(der_issuer_cert)));
165   ASSERT_TRUE(issuer_cert);
166 
167   std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
168 
169   std::string extracted_sct_list;
170   EXPECT_FALSE(ct::ExtractSCTListFromOCSPResponse(
171       issuer_cert->cert_buffer(), test_cert_->serial_number(), ocsp_response,
172       &extracted_sct_list));
173 }
174 
175 // Test that the extractor honours issuer ID.
TEST_F(CTObjectsExtractorTest,ExtractSCTListFromOCSPResponseMatchesIssuer)176 TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesIssuer) {
177   std::string der_subject_cert(ct::GetDerEncodedFakeOCSPResponseCert());
178   scoped_refptr<X509Certificate> subject_cert =
179       X509Certificate::CreateFromBytes(
180           base::as_bytes(base::make_span(der_subject_cert)));
181   ASSERT_TRUE(subject_cert);
182 
183   std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
184 
185   std::string extracted_sct_list;
186   // Use test_cert_ for issuer - it is not the correct issuer of |subject_cert|.
187   EXPECT_FALSE(ct::ExtractSCTListFromOCSPResponse(
188       test_cert_->cert_buffer(), subject_cert->serial_number(), ocsp_response,
189       &extracted_sct_list));
190 }
191 
192 }  // namespace net::ct
193