xref: /aosp_15_r20/external/cronet/net/cert/ct_objects_extractor_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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