Add missing mandoline dependencies.
[chromium-blink-merge.git] / net / cert / multi_log_ct_verifier_unittest.cc
blobcd675d3317b84a7bd3a0e667988f01e5109fa4e4
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.
5 #include "net/cert/multi_log_ct_verifier.h"
7 #include <string>
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/histogram_samples.h"
13 #include "base/metrics/statistics_recorder.h"
14 #include "base/values.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/test_data_directory.h"
17 #include "net/cert/ct_log_verifier.h"
18 #include "net/cert/ct_serialization.h"
19 #include "net/cert/ct_verify_result.h"
20 #include "net/cert/pem_tokenizer.h"
21 #include "net/cert/sct_status_flags.h"
22 #include "net/cert/signed_certificate_timestamp.h"
23 #include "net/cert/x509_certificate.h"
24 #include "net/log/net_log.h"
25 #include "net/log/test_net_log.h"
26 #include "net/log/test_net_log_entry.h"
27 #include "net/test/cert_test_util.h"
28 #include "net/test/ct_test_util.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 namespace net {
33 namespace {
35 const char kLogDescription[] = "somelog";
36 const char kSCTCountHistogram[] =
37 "Net.CertificateTransparency.SCTsPerConnection";
39 class MultiLogCTVerifierTest : public ::testing::Test {
40 public:
41 void SetUp() override {
42 scoped_ptr<CTLogVerifier> log(CTLogVerifier::Create(
43 ct::GetTestPublicKey(), kLogDescription, "https://ct.example.com"));
44 ASSERT_TRUE(log);
46 verifier_.reset(new MultiLogCTVerifier());
47 verifier_->AddLog(log.Pass());
48 std::string der_test_cert(ct::GetDerEncodedX509Cert());
49 chain_ = X509Certificate::CreateFromBytes(
50 der_test_cert.data(),
51 der_test_cert.length());
52 ASSERT_TRUE(chain_.get());
54 embedded_sct_chain_ =
55 CreateCertificateChainFromFile(GetTestCertsDirectory(),
56 "ct-test-embedded-cert.pem",
57 X509Certificate::FORMAT_AUTO);
58 ASSERT_TRUE(embedded_sct_chain_.get());
61 bool CheckForSingleVerifiedSCTInResult(const ct::CTVerifyResult& result) {
62 return (result.verified_scts.size() == 1U) &&
63 result.invalid_scts.empty() &&
64 result.unknown_logs_scts.empty() &&
65 result.verified_scts[0]->log_description == kLogDescription;
68 bool CheckForSCTOrigin(
69 const ct::CTVerifyResult& result,
70 ct::SignedCertificateTimestamp::Origin origin) {
71 return (result.verified_scts.size() > 0) &&
72 (result.verified_scts[0]->origin == origin);
75 bool CheckForEmbeddedSCTInNetLog(TestNetLog& net_log) {
76 TestNetLogEntry::List entries;
77 net_log.GetEntries(&entries);
78 if (entries.size() != 2)
79 return false;
81 const TestNetLogEntry& received = entries[0];
82 std::string embedded_scts;
83 if (!received.GetStringValue("embedded_scts", &embedded_scts))
84 return false;
85 if (embedded_scts.empty())
86 return false;
88 const TestNetLogEntry& parsed = entries[1];
89 base::ListValue* verified_scts;
90 if (!parsed.GetListValue("verified_scts", &verified_scts) ||
91 verified_scts->GetSize() != 1) {
92 return false;
95 base::DictionaryValue* the_sct;
96 if (!verified_scts->GetDictionary(0, &the_sct))
97 return false;
99 std::string origin;
100 if (!the_sct->GetString("origin", &origin))
101 return false;
102 if (origin != "embedded_in_certificate")
103 return false;
105 base::ListValue* other_scts;
106 if (!parsed.GetListValue("invalid_scts", &other_scts) ||
107 !other_scts->empty()) {
108 return false;
111 if (!parsed.GetListValue("unknown_logs_scts", &other_scts) ||
112 !other_scts->empty()) {
113 return false;
116 return true;
119 std::string GetSCTListWithInvalidSCT() {
120 std::string sct(ct::GetTestSignedCertificateTimestamp());
122 // Change a byte inside the Log ID part of the SCT so it does
123 // not match the log used in the tests
124 sct[15] = 't';
126 std::string sct_list;
127 ct::EncodeSCTListForTesting(sct, &sct_list);
128 return sct_list;
131 bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain,
132 const BoundNetLog& bound_net_log,
133 ct::CTVerifyResult* result) {
134 return verifier_->Verify(chain.get(),
135 std::string(),
136 std::string(),
137 result,
138 bound_net_log) == OK;
141 bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain) {
142 ct::CTVerifyResult result;
143 TestNetLog net_log;
144 BoundNetLog bound_net_log =
145 BoundNetLog::Make(&net_log, NetLog::SOURCE_CONNECT_JOB);
147 return verifier_->Verify(chain.get(),
148 std::string(),
149 std::string(),
150 &result,
151 bound_net_log) == OK;
154 bool CheckPrecertificateVerification(scoped_refptr<X509Certificate> chain) {
155 ct::CTVerifyResult result;
156 TestNetLog net_log;
157 BoundNetLog bound_net_log =
158 BoundNetLog::Make(&net_log, NetLog::SOURCE_CONNECT_JOB);
159 return (VerifySinglePrecertificateChain(chain, bound_net_log, &result) &&
160 CheckForSingleVerifiedSCTInResult(result) &&
161 CheckForSCTOrigin(result,
162 ct::SignedCertificateTimestamp::SCT_EMBEDDED) &&
163 CheckForEmbeddedSCTInNetLog(net_log));
166 // Histogram-related helper methods
167 int GetValueFromHistogram(std::string histogram_name, int sample_index) {
168 base::Histogram* histogram = static_cast<base::Histogram*>(
169 base::StatisticsRecorder::FindHistogram(histogram_name));
171 if (histogram == NULL)
172 return 0;
174 scoped_ptr<base::HistogramSamples> samples = histogram->SnapshotSamples();
175 return samples->GetCount(sample_index);
178 int NumConnectionsWithSingleSCT() {
179 return GetValueFromHistogram(kSCTCountHistogram, 1);
182 int NumEmbeddedSCTsInHistogram() {
183 return GetValueFromHistogram("Net.CertificateTransparency.SCTOrigin",
184 ct::SignedCertificateTimestamp::SCT_EMBEDDED);
187 int NumValidSCTsInStatusHistogram() {
188 return GetValueFromHistogram("Net.CertificateTransparency.SCTStatus",
189 ct::SCT_STATUS_OK);
192 protected:
193 scoped_ptr<MultiLogCTVerifier> verifier_;
194 scoped_refptr<X509Certificate> chain_;
195 scoped_refptr<X509Certificate> embedded_sct_chain_;
198 TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCT) {
199 ASSERT_TRUE(CheckPrecertificateVerification(embedded_sct_chain_));
202 TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithPreCA) {
203 scoped_refptr<X509Certificate> chain(
204 CreateCertificateChainFromFile(GetTestCertsDirectory(),
205 "ct-test-embedded-with-preca-chain.pem",
206 X509Certificate::FORMAT_AUTO));
207 ASSERT_TRUE(chain.get());
208 ASSERT_TRUE(CheckPrecertificateVerification(chain));
211 TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithIntermediate) {
212 scoped_refptr<X509Certificate> chain(CreateCertificateChainFromFile(
213 GetTestCertsDirectory(),
214 "ct-test-embedded-with-intermediate-chain.pem",
215 X509Certificate::FORMAT_AUTO));
216 ASSERT_TRUE(chain.get());
217 ASSERT_TRUE(CheckPrecertificateVerification(chain));
220 TEST_F(MultiLogCTVerifierTest,
221 VerifiesEmbeddedSCTWithIntermediateAndPreCA) {
222 scoped_refptr<X509Certificate> chain(CreateCertificateChainFromFile(
223 GetTestCertsDirectory(),
224 "ct-test-embedded-with-intermediate-preca-chain.pem",
225 X509Certificate::FORMAT_AUTO));
226 ASSERT_TRUE(chain.get());
227 ASSERT_TRUE(CheckPrecertificateVerification(chain));
230 TEST_F(MultiLogCTVerifierTest,
231 VerifiesSCTOverX509Cert) {
232 std::string sct(ct::GetTestSignedCertificateTimestamp());
234 std::string sct_list;
235 ASSERT_TRUE(ct::EncodeSCTListForTesting(sct, &sct_list));
237 ct::CTVerifyResult result;
238 EXPECT_EQ(OK,
239 verifier_->Verify(
240 chain_.get(), std::string(), sct_list, &result, BoundNetLog()));
241 ASSERT_TRUE(CheckForSingleVerifiedSCTInResult(result));
242 ASSERT_TRUE(CheckForSCTOrigin(
243 result, ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION));
246 TEST_F(MultiLogCTVerifierTest,
247 IdentifiesSCTFromUnknownLog) {
248 std::string sct_list = GetSCTListWithInvalidSCT();
249 ct::CTVerifyResult result;
251 EXPECT_NE(OK,
252 verifier_->Verify(
253 chain_.get(), std::string(), sct_list, &result, BoundNetLog()));
254 EXPECT_EQ(1U, result.unknown_logs_scts.size());
255 EXPECT_EQ("", result.unknown_logs_scts[0]->log_description);
258 TEST_F(MultiLogCTVerifierTest, CountsValidSCTsInStatusHistogram) {
259 int num_valid_scts = NumValidSCTsInStatusHistogram();
261 ASSERT_TRUE(VerifySinglePrecertificateChain(embedded_sct_chain_));
263 EXPECT_EQ(num_valid_scts + 1, NumValidSCTsInStatusHistogram());
266 TEST_F(MultiLogCTVerifierTest, CountsInvalidSCTsInStatusHistogram) {
267 std::string sct_list = GetSCTListWithInvalidSCT();
268 ct::CTVerifyResult result;
269 int num_valid_scts = NumValidSCTsInStatusHistogram();
270 int num_invalid_scts = GetValueFromHistogram(
271 "Net.CertificateTransparency.SCTStatus", ct::SCT_STATUS_LOG_UNKNOWN);
273 EXPECT_NE(OK,
274 verifier_->Verify(
275 chain_.get(), std::string(), sct_list, &result, BoundNetLog()));
277 ASSERT_EQ(num_valid_scts, NumValidSCTsInStatusHistogram());
278 ASSERT_EQ(num_invalid_scts + 1,
279 GetValueFromHistogram("Net.CertificateTransparency.SCTStatus",
280 ct::SCT_STATUS_LOG_UNKNOWN));
283 TEST_F(MultiLogCTVerifierTest, CountsSingleEmbeddedSCTInConnectionsHistogram) {
284 int old_sct_count = NumConnectionsWithSingleSCT();
285 ASSERT_TRUE(CheckPrecertificateVerification(embedded_sct_chain_));
286 EXPECT_EQ(old_sct_count + 1, NumConnectionsWithSingleSCT());
289 TEST_F(MultiLogCTVerifierTest, CountsSingleEmbeddedSCTInOriginsHistogram) {
290 int old_embedded_count = NumEmbeddedSCTsInHistogram();
291 ASSERT_TRUE(CheckPrecertificateVerification(embedded_sct_chain_));
292 EXPECT_EQ(old_embedded_count + 1, NumEmbeddedSCTsInHistogram());
295 TEST_F(MultiLogCTVerifierTest, CountsZeroSCTsCorrectly) {
296 int connections_without_scts = GetValueFromHistogram(kSCTCountHistogram, 0);
297 EXPECT_FALSE(VerifySinglePrecertificateChain(chain_));
298 ASSERT_EQ(connections_without_scts + 1,
299 GetValueFromHistogram(kSCTCountHistogram, 0));
302 } // namespace
304 } // namespace net