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