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