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