1 // Copyright 2015 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/quic/crypto/proof_verifier_chromium.h"
6
7 #include <utility>
8
9 #include "base/memory/ref_counted.h"
10 #include "base/test/metrics/histogram_tester.h"
11 #include "net/base/completion_once_callback.h"
12 #include "net/base/net_errors.h"
13 #include "net/cert/cert_status_flags.h"
14 #include "net/cert/cert_verifier.h"
15 #include "net/cert/ct_log_verifier.h"
16 #include "net/cert/ct_policy_enforcer.h"
17 #include "net/cert/ct_policy_status.h"
18 #include "net/cert/ct_serialization.h"
19 #include "net/cert/mock_cert_verifier.h"
20 #include "net/cert/multi_log_ct_verifier.h"
21 #include "net/cert/x509_util.h"
22 #include "net/http/transport_security_state.h"
23 #include "net/http/transport_security_state_test_util.h"
24 #include "net/quic/crypto/proof_source_chromium.h"
25 #include "net/test/cert_test_util.h"
26 #include "net/test/ct_test_util.h"
27 #include "net/test/test_data_directory.h"
28 #include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 using ::testing::_;
33 using ::testing::Return;
34
35 namespace net {
36 namespace test {
37
38 namespace {
39
40 const char kCTAndPKPHost[] = "pkp-expect-ct.preloaded.test";
41
42 // CertVerifier that will fail the test if it is ever called.
43 class FailsTestCertVerifier : public CertVerifier {
44 public:
FailsTestCertVerifier()45 FailsTestCertVerifier() {}
~FailsTestCertVerifier()46 ~FailsTestCertVerifier() override {}
47
48 // CertVerifier implementation
Verify(const RequestParams & params,CertVerifyResult * verify_result,CompletionOnceCallback callback,std::unique_ptr<Request> * out_req,const NetLogWithSource & net_log)49 int Verify(const RequestParams& params,
50 CertVerifyResult* verify_result,
51 CompletionOnceCallback callback,
52 std::unique_ptr<Request>* out_req,
53 const NetLogWithSource& net_log) override {
54 ADD_FAILURE() << "CertVerifier::Verify() should not be called";
55 return ERR_FAILED;
56 }
SetConfig(const Config & config)57 void SetConfig(const Config& config) override {}
58 };
59
60 // A mock CTPolicyEnforcer that returns a custom verification result.
61 class MockCTPolicyEnforcer : public CTPolicyEnforcer {
62 public:
63 MOCK_METHOD3(CheckCompliance,
64 ct::CTPolicyCompliance(X509Certificate* cert,
65 const ct::SCTList&,
66 const NetLogWithSource&));
67 };
68
69 class MockRequireCTDelegate : public TransportSecurityState::RequireCTDelegate {
70 public:
71 MOCK_METHOD3(IsCTRequiredForHost,
72 CTRequirementLevel(const std::string& host,
73 const X509Certificate* chain,
74 const HashValueVector& hashes));
75 };
76
77 // Proof source callback which saves the signature into |signature|.
78 class SignatureSaver : public quic::ProofSource::Callback {
79 public:
SignatureSaver(std::string * signature)80 explicit SignatureSaver(std::string* signature) : signature_(signature) {}
~SignatureSaver()81 ~SignatureSaver() override {}
82
Run(bool,const quic::QuicReferenceCountedPointer<quic::ProofSource::Chain> &,const quic::QuicCryptoProof & proof,std::unique_ptr<quic::ProofSource::Details>)83 void Run(bool /*ok*/,
84 const quic::QuicReferenceCountedPointer<
85 quic::ProofSource::Chain>& /*chain*/,
86 const quic::QuicCryptoProof& proof,
87 std::unique_ptr<quic::ProofSource::Details> /*details*/) override {
88 *signature_ = proof.signature;
89 }
90
91 std::string* signature_;
92 };
93
94 class DummyProofVerifierCallback : public quic::ProofVerifierCallback {
95 public:
DummyProofVerifierCallback()96 DummyProofVerifierCallback() {}
~DummyProofVerifierCallback()97 ~DummyProofVerifierCallback() override {}
98
Run(bool ok,const std::string & error_details,std::unique_ptr<quic::ProofVerifyDetails> * details)99 void Run(bool ok,
100 const std::string& error_details,
101 std::unique_ptr<quic::ProofVerifyDetails>* details) override {
102 // Do nothing
103 }
104 };
105
106 const char kTestHostname[] = "test.example.com";
107 const char kTestChloHash[] = "CHLO hash";
108 const char kTestEmptySCT[] = "";
109 const uint16_t kTestPort = 8443;
110 const char kTestConfig[] = "server config bytes";
111 const char kLogDescription[] = "somelog";
112
113 } // namespace
114
115 class ProofVerifierChromiumTest : public ::testing::Test {
116 public:
ProofVerifierChromiumTest()117 ProofVerifierChromiumTest()
118 : verify_context_(new ProofVerifyContextChromium(0 /*cert_verify_flags*/,
119 NetLogWithSource())) {}
120
SetUp()121 void SetUp() override {
122 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
123 .WillRepeatedly(
124 Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
125
126 scoped_refptr<const CTLogVerifier> log(
127 CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription));
128 ASSERT_TRUE(log);
129 log_verifiers_.push_back(log);
130
131 ct_verifier_.reset(new MultiLogCTVerifier());
132 ct_verifier_->AddLogs(log_verifiers_);
133
134 static const char kTestCert[] = "quic-chain.pem";
135 test_cert_ = ImportCertFromFile(GetTestCertsDirectory(), kTestCert);
136 ASSERT_TRUE(test_cert_);
137 certs_.clear();
138 certs_.emplace_back(
139 x509_util::CryptoBufferAsStringPiece(test_cert_->cert_buffer()));
140
141 dummy_result_.verified_cert = test_cert_;
142 dummy_result_.is_issued_by_known_root = true;
143 }
144
GetTestSignature()145 std::string GetTestSignature() {
146 ProofSourceChromium source;
147 source.Initialize(GetTestCertsDirectory().AppendASCII("quic-chain.pem"),
148 GetTestCertsDirectory().AppendASCII("quic-leaf-cert.key"),
149 base::FilePath());
150 std::string signature;
151 source.GetProof(quic::QuicSocketAddress(), kTestHostname, kTestConfig,
152 quic::QUIC_VERSION_43, kTestChloHash,
153 std::make_unique<SignatureSaver>(&signature));
154 return signature;
155 }
156
GetSCTTestCertificates(std::vector<std::string> * certs)157 void GetSCTTestCertificates(std::vector<std::string>* certs) {
158 std::string der_test_cert(ct::GetDerEncodedX509Cert());
159 scoped_refptr<X509Certificate> test_cert = X509Certificate::CreateFromBytes(
160 der_test_cert.data(), der_test_cert.length());
161 ASSERT_TRUE(test_cert.get());
162
163 certs->clear();
164 certs->emplace_back(
165 x509_util::CryptoBufferAsStringPiece(test_cert->cert_buffer()));
166 }
167
CheckSCT(bool sct_expected_ok)168 void CheckSCT(bool sct_expected_ok) {
169 ProofVerifyDetailsChromium* proof_details =
170 reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get());
171 const ct::CTVerifyResult& ct_verify_result =
172 proof_details->ct_verify_result;
173 if (sct_expected_ok) {
174 ASSERT_TRUE(ct::CheckForSingleVerifiedSCTInResult(ct_verify_result.scts,
175 kLogDescription));
176 ASSERT_TRUE(ct::CheckForSCTOrigin(
177 ct_verify_result.scts,
178 ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION));
179 } else {
180 EXPECT_EQ(1U, ct_verify_result.scts.size());
181 EXPECT_EQ(ct::SCT_STATUS_LOG_UNKNOWN, ct_verify_result.scts[0].status);
182 }
183 }
184
185 protected:
186 TransportSecurityState transport_security_state_;
187 MockCTPolicyEnforcer ct_policy_enforcer_;
188
189 std::unique_ptr<MultiLogCTVerifier> ct_verifier_;
190 std::vector<scoped_refptr<const CTLogVerifier>> log_verifiers_;
191 std::unique_ptr<quic::ProofVerifyContext> verify_context_;
192 std::unique_ptr<quic::ProofVerifyDetails> details_;
193 std::string error_details_;
194 std::vector<std::string> certs_;
195 CertVerifyResult dummy_result_;
196 scoped_refptr<X509Certificate> test_cert_;
197 };
198
TEST_F(ProofVerifierChromiumTest,VerifyProof)199 TEST_F(ProofVerifierChromiumTest, VerifyProof) {
200 MockCertVerifier dummy_verifier;
201 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
202
203 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
204 &transport_security_state_,
205 ct_verifier_.get(), {});
206
207 std::unique_ptr<DummyProofVerifierCallback> callback(
208 new DummyProofVerifierCallback);
209 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
210 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
211 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
212 verify_context_.get(), &error_details_, &details_, std::move(callback));
213 ASSERT_EQ(quic::QUIC_SUCCESS, status);
214
215 ASSERT_TRUE(details_.get());
216 ProofVerifyDetailsChromium* verify_details =
217 static_cast<ProofVerifyDetailsChromium*>(details_.get());
218 EXPECT_EQ(dummy_result_.cert_status,
219 verify_details->cert_verify_result.cert_status);
220 }
221
222 // Tests that the quic::ProofVerifier fails verification if certificate
223 // verification fails.
TEST_F(ProofVerifierChromiumTest,FailsIfCertFails)224 TEST_F(ProofVerifierChromiumTest, FailsIfCertFails) {
225 MockCertVerifier dummy_verifier;
226 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
227 &transport_security_state_,
228 ct_verifier_.get(), {});
229
230 std::unique_ptr<DummyProofVerifierCallback> callback(
231 new DummyProofVerifierCallback);
232 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
233 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
234 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
235 verify_context_.get(), &error_details_, &details_, std::move(callback));
236 ASSERT_EQ(quic::QUIC_FAILURE, status);
237 }
238
239 // Valid SCT, but invalid signature.
TEST_F(ProofVerifierChromiumTest,ValidSCTList)240 TEST_F(ProofVerifierChromiumTest, ValidSCTList) {
241 // Use different certificates for SCT tests.
242 ASSERT_NO_FATAL_FAILURE(GetSCTTestCertificates(&certs_));
243
244 MockCertVerifier cert_verifier;
245
246 ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
247 &transport_security_state_,
248 ct_verifier_.get(), {});
249
250 std::unique_ptr<DummyProofVerifierCallback> callback(
251 new DummyProofVerifierCallback);
252 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
253 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
254 kTestChloHash, certs_, ct::GetSCTListForTesting(), kTestEmptySCT,
255 verify_context_.get(), &error_details_, &details_, std::move(callback));
256 ASSERT_EQ(quic::QUIC_FAILURE, status);
257 CheckSCT(/*sct_expected_ok=*/true);
258 }
259
260 // Invalid SCT and signature.
TEST_F(ProofVerifierChromiumTest,InvalidSCTList)261 TEST_F(ProofVerifierChromiumTest, InvalidSCTList) {
262 // Use different certificates for SCT tests.
263 ASSERT_NO_FATAL_FAILURE(GetSCTTestCertificates(&certs_));
264
265 MockCertVerifier cert_verifier;
266 ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
267 &transport_security_state_,
268 ct_verifier_.get(), {});
269
270 std::unique_ptr<DummyProofVerifierCallback> callback(
271 new DummyProofVerifierCallback);
272 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
273 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
274 kTestChloHash, certs_, ct::GetSCTListWithInvalidSCT(), kTestEmptySCT,
275 verify_context_.get(), &error_details_, &details_, std::move(callback));
276 ASSERT_EQ(quic::QUIC_FAILURE, status);
277 CheckSCT(/*sct_expected_ok=*/false);
278 }
279
280 // Tests that the quic::ProofVerifier doesn't verify certificates if the config
281 // signature fails.
TEST_F(ProofVerifierChromiumTest,FailsIfSignatureFails)282 TEST_F(ProofVerifierChromiumTest, FailsIfSignatureFails) {
283 FailsTestCertVerifier cert_verifier;
284 ProofVerifierChromium proof_verifier(&cert_verifier, &ct_policy_enforcer_,
285 &transport_security_state_,
286 ct_verifier_.get(), {});
287
288 std::unique_ptr<DummyProofVerifierCallback> callback(
289 new DummyProofVerifierCallback);
290 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
291 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
292 kTestChloHash, certs_, kTestEmptySCT, kTestConfig, verify_context_.get(),
293 &error_details_, &details_, std::move(callback));
294 ASSERT_EQ(quic::QUIC_FAILURE, status);
295 }
296
297 // Tests that the certificate policy enforcer is consulted for EV
298 // and the certificate is allowed to be EV.
TEST_F(ProofVerifierChromiumTest,PreservesEVIfAllowed)299 TEST_F(ProofVerifierChromiumTest, PreservesEVIfAllowed) {
300 dummy_result_.cert_status = CERT_STATUS_IS_EV;
301
302 MockCertVerifier dummy_verifier;
303 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
304
305 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
306 .WillRepeatedly(
307 Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
308
309 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
310 &transport_security_state_,
311 ct_verifier_.get(), {});
312
313 std::unique_ptr<DummyProofVerifierCallback> callback(
314 new DummyProofVerifierCallback);
315 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
316 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
317 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
318 verify_context_.get(), &error_details_, &details_, std::move(callback));
319 ASSERT_EQ(quic::QUIC_SUCCESS, status);
320
321 ASSERT_TRUE(details_.get());
322 ProofVerifyDetailsChromium* verify_details =
323 static_cast<ProofVerifyDetailsChromium*>(details_.get());
324 EXPECT_EQ(dummy_result_.cert_status,
325 verify_details->cert_verify_result.cert_status);
326 }
327
328 // Tests that the certificate policy enforcer is consulted for EV
329 // and the certificate is not allowed to be EV.
TEST_F(ProofVerifierChromiumTest,StripsEVIfNotAllowed)330 TEST_F(ProofVerifierChromiumTest, StripsEVIfNotAllowed) {
331 dummy_result_.cert_status = CERT_STATUS_IS_EV;
332
333 MockCertVerifier dummy_verifier;
334 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
335
336 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
337 .WillRepeatedly(
338 Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
339
340 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
341 &transport_security_state_,
342 ct_verifier_.get(), {});
343
344 std::unique_ptr<DummyProofVerifierCallback> callback(
345 new DummyProofVerifierCallback);
346 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
347 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
348 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
349 verify_context_.get(), &error_details_, &details_, std::move(callback));
350 ASSERT_EQ(quic::QUIC_SUCCESS, status);
351
352 ASSERT_TRUE(details_.get());
353 ProofVerifyDetailsChromium* verify_details =
354 static_cast<ProofVerifyDetailsChromium*>(details_.get());
355 EXPECT_EQ(CERT_STATUS_CT_COMPLIANCE_FAILED,
356 verify_details->cert_verify_result.cert_status &
357 (CERT_STATUS_CT_COMPLIANCE_FAILED | CERT_STATUS_IS_EV));
358 }
359
360 // Tests that the when a certificate's EV status is stripped to EV
361 // non-compliance, the correct histogram is recorded.
TEST_F(ProofVerifierChromiumTest,CTEVHistogramNonCompliant)362 TEST_F(ProofVerifierChromiumTest, CTEVHistogramNonCompliant) {
363 const char kHistogramName[] =
364 "Net.CertificateTransparency.EVCompliance2.QUIC";
365 base::HistogramTester histograms;
366
367 dummy_result_.cert_status = CERT_STATUS_IS_EV;
368 dummy_result_.is_issued_by_known_root = true;
369
370 MockCertVerifier dummy_verifier;
371 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
372
373 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
374 .WillRepeatedly(
375 Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
376
377 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
378 &transport_security_state_,
379 ct_verifier_.get(), {});
380
381 std::unique_ptr<DummyProofVerifierCallback> callback(
382 new DummyProofVerifierCallback);
383 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
384 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
385 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
386 verify_context_.get(), &error_details_, &details_, std::move(callback));
387 ASSERT_EQ(quic::QUIC_SUCCESS, status);
388
389 ASSERT_TRUE(details_.get());
390 ProofVerifyDetailsChromium* verify_details =
391 static_cast<ProofVerifyDetailsChromium*>(details_.get());
392 EXPECT_EQ(CERT_STATUS_CT_COMPLIANCE_FAILED,
393 verify_details->cert_verify_result.cert_status &
394 (CERT_STATUS_CT_COMPLIANCE_FAILED | CERT_STATUS_IS_EV));
395
396 histograms.ExpectUniqueSample(
397 kHistogramName,
398 static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS), 1);
399 }
400
401 // Tests that when a connection is CT-compliant and its EV status is preserved,
402 // the correct histogram is recorded.
TEST_F(ProofVerifierChromiumTest,CTEVHistogramCompliant)403 TEST_F(ProofVerifierChromiumTest, CTEVHistogramCompliant) {
404 const char kHistogramName[] =
405 "Net.CertificateTransparency.EVCompliance2.QUIC";
406 base::HistogramTester histograms;
407
408 dummy_result_.cert_status = CERT_STATUS_IS_EV;
409 dummy_result_.is_issued_by_known_root = true;
410
411 MockCertVerifier dummy_verifier;
412 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
413
414 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
415 .WillRepeatedly(
416 Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
417
418 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
419 &transport_security_state_,
420 ct_verifier_.get(), {});
421
422 std::unique_ptr<DummyProofVerifierCallback> callback(
423 new DummyProofVerifierCallback);
424 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
425 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
426 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
427 verify_context_.get(), &error_details_, &details_, std::move(callback));
428 ASSERT_EQ(quic::QUIC_SUCCESS, status);
429
430 ASSERT_TRUE(details_.get());
431 ProofVerifyDetailsChromium* verify_details =
432 static_cast<ProofVerifyDetailsChromium*>(details_.get());
433 EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
434 CERT_STATUS_IS_EV);
435
436 histograms.ExpectUniqueSample(
437 kHistogramName,
438 static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS), 1);
439 }
440
MakeHashValueVector(uint8_t tag)441 HashValueVector MakeHashValueVector(uint8_t tag) {
442 HashValue hash(HASH_VALUE_SHA256);
443 memset(hash.data(), tag, hash.size());
444 HashValueVector hashes;
445 hashes.push_back(hash);
446 return hashes;
447 }
448
TEST_F(ProofVerifierChromiumTest,IsFatalErrorNotSetForNonFatalError)449 TEST_F(ProofVerifierChromiumTest, IsFatalErrorNotSetForNonFatalError) {
450 dummy_result_.cert_status = CERT_STATUS_DATE_INVALID;
451
452 MockCertVerifier dummy_verifier;
453 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_,
454 ERR_CERT_DATE_INVALID);
455
456 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
457 &transport_security_state_,
458 ct_verifier_.get(), {});
459
460 std::unique_ptr<DummyProofVerifierCallback> callback(
461 new DummyProofVerifierCallback);
462 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
463 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
464 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
465 verify_context_.get(), &error_details_, &details_, std::move(callback));
466 ASSERT_EQ(quic::QUIC_FAILURE, status);
467
468 ProofVerifyDetailsChromium* verify_details =
469 static_cast<ProofVerifyDetailsChromium*>(details_.get());
470 EXPECT_FALSE(verify_details->is_fatal_cert_error);
471 }
472
TEST_F(ProofVerifierChromiumTest,IsFatalErrorSetForFatalError)473 TEST_F(ProofVerifierChromiumTest, IsFatalErrorSetForFatalError) {
474 dummy_result_.cert_status = CERT_STATUS_DATE_INVALID;
475
476 MockCertVerifier dummy_verifier;
477 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_,
478 ERR_CERT_DATE_INVALID);
479
480 const base::Time expiry =
481 base::Time::Now() + base::TimeDelta::FromSeconds(1000);
482 transport_security_state_.AddHSTS(kTestHostname, expiry, true);
483
484 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
485 &transport_security_state_,
486 ct_verifier_.get(), {});
487
488 std::unique_ptr<DummyProofVerifierCallback> callback(
489 new DummyProofVerifierCallback);
490 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
491 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
492 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
493 verify_context_.get(), &error_details_, &details_, std::move(callback));
494 ASSERT_EQ(quic::QUIC_FAILURE, status);
495 ProofVerifyDetailsChromium* verify_details =
496 static_cast<ProofVerifyDetailsChromium*>(details_.get());
497 EXPECT_TRUE(verify_details->is_fatal_cert_error);
498 }
499
500 // Test that PKP is enforced for certificates that chain up to known roots.
TEST_F(ProofVerifierChromiumTest,PKPEnforced)501 TEST_F(ProofVerifierChromiumTest, PKPEnforced) {
502 dummy_result_.is_issued_by_known_root = true;
503 dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
504
505 MockCertVerifier dummy_verifier;
506 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
507
508 transport_security_state_.EnableStaticPinsForTesting();
509 ScopedTransportSecurityStateSource scoped_security_state_source;
510
511 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
512 &transport_security_state_,
513 ct_verifier_.get(), {});
514
515 std::unique_ptr<DummyProofVerifierCallback> callback(
516 new DummyProofVerifierCallback);
517 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
518 kCTAndPKPHost, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
519 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
520 verify_context_.get(), &error_details_, &details_, std::move(callback));
521 ASSERT_EQ(quic::QUIC_FAILURE, status);
522
523 ASSERT_TRUE(details_.get());
524 ProofVerifyDetailsChromium* verify_details =
525 static_cast<ProofVerifyDetailsChromium*>(details_.get());
526 EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
527 CERT_STATUS_PINNED_KEY_MISSING);
528 EXPECT_FALSE(verify_details->pkp_bypassed);
529 EXPECT_NE("", verify_details->pinning_failure_log);
530 }
531
532 // Test |pkp_bypassed| is set when PKP is bypassed due to a local
533 // trust anchor
TEST_F(ProofVerifierChromiumTest,PKPBypassFlagSet)534 TEST_F(ProofVerifierChromiumTest, PKPBypassFlagSet) {
535 dummy_result_.is_issued_by_known_root = false;
536 dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
537
538 MockCertVerifier dummy_verifier;
539 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
540
541 transport_security_state_.EnableStaticPinsForTesting();
542 ScopedTransportSecurityStateSource scoped_security_state_source;
543
544 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
545 &transport_security_state_,
546 ct_verifier_.get(), {kCTAndPKPHost});
547
548 std::unique_ptr<DummyProofVerifierCallback> callback(
549 new DummyProofVerifierCallback);
550 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
551 kCTAndPKPHost, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
552 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
553 verify_context_.get(), &error_details_, &details_, std::move(callback));
554 ASSERT_EQ(quic::QUIC_SUCCESS, status);
555
556 ASSERT_TRUE(details_.get());
557 ProofVerifyDetailsChromium* verify_details =
558 static_cast<ProofVerifyDetailsChromium*>(details_.get());
559 EXPECT_TRUE(verify_details->pkp_bypassed);
560 }
561
562 // Test that when CT is required (in this case, by the delegate), the
563 // absence of CT information is a socket error.
TEST_F(ProofVerifierChromiumTest,CTIsRequired)564 TEST_F(ProofVerifierChromiumTest, CTIsRequired) {
565 dummy_result_.is_issued_by_known_root = true;
566 dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
567
568 MockCertVerifier dummy_verifier;
569 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
570
571 // Set up CT.
572 MockRequireCTDelegate require_ct_delegate;
573 transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
574 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
575 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
576 CTRequirementLevel::NOT_REQUIRED));
577 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname, _, _))
578 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
579 CTRequirementLevel::REQUIRED));
580 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
581 .WillRepeatedly(
582 Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
583
584 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
585 &transport_security_state_,
586 ct_verifier_.get(), {});
587
588 std::unique_ptr<DummyProofVerifierCallback> callback(
589 new DummyProofVerifierCallback);
590 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
591 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
592 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
593 verify_context_.get(), &error_details_, &details_, std::move(callback));
594 ASSERT_EQ(quic::QUIC_FAILURE, status);
595
596 ASSERT_TRUE(details_.get());
597 ProofVerifyDetailsChromium* verify_details =
598 static_cast<ProofVerifyDetailsChromium*>(details_.get());
599 EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
600 CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
601 }
602
603 // Test that when CT is required (in this case, by the delegate) and CT
604 // information is not compliant, then the CT-required histogram is recorded
605 // properly.
TEST_F(ProofVerifierChromiumTest,CTIsRequiredHistogramNonCompliant)606 TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramNonCompliant) {
607 const char kHistogramName[] =
608 "Net.CertificateTransparency.CTRequiredConnectionComplianceStatus2.QUIC";
609 base::HistogramTester histograms;
610
611 dummy_result_.is_issued_by_known_root = true;
612 dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
613
614 MockCertVerifier dummy_verifier;
615 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
616
617 // Set up CT.
618 MockRequireCTDelegate require_ct_delegate;
619 transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
620 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
621 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
622 CTRequirementLevel::NOT_REQUIRED));
623 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname, _, _))
624 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
625 CTRequirementLevel::REQUIRED));
626 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
627 .WillRepeatedly(
628 Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
629
630 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
631 &transport_security_state_,
632 ct_verifier_.get(), {});
633
634 std::unique_ptr<DummyProofVerifierCallback> callback(
635 new DummyProofVerifierCallback);
636 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
637 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
638 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
639 verify_context_.get(), &error_details_, &details_, std::move(callback));
640 ASSERT_EQ(quic::QUIC_FAILURE, status);
641
642 histograms.ExpectUniqueSample(
643 kHistogramName,
644 static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS), 1);
645 }
646
647 // Test that when CT is required (in this case, by the delegate) and CT
648 // information is compliant, then the CT-required histogram is recorded
649 // properly.
TEST_F(ProofVerifierChromiumTest,CTIsRequiredHistogramCompliant)650 TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramCompliant) {
651 const char kHistogramName[] =
652 "Net.CertificateTransparency.CTRequiredConnectionComplianceStatus2.QUIC";
653 base::HistogramTester histograms;
654
655 dummy_result_.is_issued_by_known_root = false;
656 dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
657
658 // Set up CT.
659 MockRequireCTDelegate require_ct_delegate;
660 transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
661 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
662 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
663 CTRequirementLevel::NOT_REQUIRED));
664 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname, _, _))
665 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
666 CTRequirementLevel::REQUIRED));
667 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
668 .WillRepeatedly(
669 Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
670
671 // First test that the histogram is not recorded for locally-installed roots.
672 {
673 MockCertVerifier dummy_verifier;
674 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
675 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
676 &transport_security_state_,
677 ct_verifier_.get(), {kTestHostname});
678
679 std::unique_ptr<DummyProofVerifierCallback> callback(
680 new DummyProofVerifierCallback);
681 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
682 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
683 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
684 verify_context_.get(), &error_details_, &details_, std::move(callback));
685 ASSERT_EQ(quic::QUIC_SUCCESS, status);
686
687 histograms.ExpectTotalCount(kHistogramName, 0);
688 }
689 // Now test that the histogram is recorded for public roots.
690 {
691 dummy_result_.is_issued_by_known_root = true;
692 MockCertVerifier dummy_verifier;
693 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
694 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
695 &transport_security_state_,
696 ct_verifier_.get(), {});
697
698 std::unique_ptr<DummyProofVerifierCallback> callback(
699 new DummyProofVerifierCallback);
700 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
701 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
702 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
703 verify_context_.get(), &error_details_, &details_, std::move(callback));
704 ASSERT_EQ(quic::QUIC_SUCCESS, status);
705
706 histograms.ExpectUniqueSample(
707 kHistogramName,
708 static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS),
709 1);
710 }
711 }
712
713 // Test that when CT is not required (because of a private root, in this case),
714 // the CT-required histogram is not recorded.
TEST_F(ProofVerifierChromiumTest,CTIsNotRequiredHistogram)715 TEST_F(ProofVerifierChromiumTest, CTIsNotRequiredHistogram) {
716 const char kHistogramName[] =
717 "Net.CertificateTransparency.CTRequiredConnectionComplianceStatus2.QUIC";
718 base::HistogramTester histograms;
719
720 dummy_result_.is_issued_by_known_root = false;
721 dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
722
723 MockCertVerifier dummy_verifier;
724 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
725
726 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
727 &transport_security_state_,
728 ct_verifier_.get(), {kTestHostname});
729
730 std::unique_ptr<DummyProofVerifierCallback> callback(
731 new DummyProofVerifierCallback);
732 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
733 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
734 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
735 verify_context_.get(), &error_details_, &details_, std::move(callback));
736 ASSERT_EQ(quic::QUIC_SUCCESS, status);
737
738 histograms.ExpectTotalCount(kHistogramName, 0);
739 }
740
741 // Test that CT is considered even when PKP fails.
TEST_F(ProofVerifierChromiumTest,PKPAndCTBothTested)742 TEST_F(ProofVerifierChromiumTest, PKPAndCTBothTested) {
743 dummy_result_.is_issued_by_known_root = true;
744 dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
745
746 MockCertVerifier dummy_verifier;
747 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
748
749 // Set up PKP.
750 transport_security_state_.EnableStaticPinsForTesting();
751 ScopedTransportSecurityStateSource scoped_security_state_source;
752
753 // Set up CT.
754 MockRequireCTDelegate require_ct_delegate;
755 transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
756 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
757 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
758 CTRequirementLevel::NOT_REQUIRED));
759 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kCTAndPKPHost, _, _))
760 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
761 CTRequirementLevel::REQUIRED));
762 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
763 .WillRepeatedly(
764 Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
765
766 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
767 &transport_security_state_,
768 ct_verifier_.get(), {});
769
770 std::unique_ptr<DummyProofVerifierCallback> callback(
771 new DummyProofVerifierCallback);
772 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
773 kCTAndPKPHost, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
774 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
775 verify_context_.get(), &error_details_, &details_, std::move(callback));
776 ASSERT_EQ(quic::QUIC_FAILURE, status);
777
778 ASSERT_TRUE(details_.get());
779 ProofVerifyDetailsChromium* verify_details =
780 static_cast<ProofVerifyDetailsChromium*>(details_.get());
781 EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
782 CERT_STATUS_PINNED_KEY_MISSING);
783 EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
784 CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
785 }
786
787 // Test that CT compliance status is recorded in a histogram.
TEST_F(ProofVerifierChromiumTest,CTComplianceStatusHistogram)788 TEST_F(ProofVerifierChromiumTest, CTComplianceStatusHistogram) {
789 const char kHistogramName[] =
790 "Net.CertificateTransparency.ConnectionComplianceStatus2.QUIC";
791 base::HistogramTester histograms;
792
793 dummy_result_.is_issued_by_known_root = false;
794
795 // Set up CT.
796 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
797 .WillRepeatedly(
798 Return(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS));
799
800 // First test that the histogram is not recorded for locally-installed roots.
801 {
802 MockCertVerifier dummy_verifier;
803 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
804 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
805 &transport_security_state_,
806 ct_verifier_.get(), {kTestHostname});
807
808 std::unique_ptr<DummyProofVerifierCallback> callback(
809 new DummyProofVerifierCallback);
810 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
811 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
812 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
813 verify_context_.get(), &error_details_, &details_, std::move(callback));
814 ASSERT_EQ(quic::QUIC_SUCCESS, status);
815
816 // The histogram should not have been recorded.
817 histograms.ExpectTotalCount(kHistogramName, 0);
818 }
819
820 // Now test that the histogram is recorded for public roots.
821 {
822 dummy_result_.is_issued_by_known_root = true;
823 MockCertVerifier dummy_verifier;
824 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
825 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
826 &transport_security_state_,
827 ct_verifier_.get(), {});
828
829 std::unique_ptr<DummyProofVerifierCallback> callback(
830 new DummyProofVerifierCallback);
831 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
832 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
833 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
834 verify_context_.get(), &error_details_, &details_, std::move(callback));
835 ASSERT_EQ(quic::QUIC_SUCCESS, status);
836
837 // The histogram should have been recorded with the CT compliance status.
838 histograms.ExpectUniqueSample(
839 kHistogramName,
840 static_cast<int>(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS),
841 1);
842 }
843 }
844
845 // Tests that when CT is required but the connection is not compliant, the
846 // relevant flag is set in the CTVerifyResult.
TEST_F(ProofVerifierChromiumTest,CTRequirementsFlagNotMet)847 TEST_F(ProofVerifierChromiumTest, CTRequirementsFlagNotMet) {
848 dummy_result_.is_issued_by_known_root = true;
849 MockCertVerifier dummy_verifier;
850 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
851
852 // Set up CT.
853 MockRequireCTDelegate require_ct_delegate;
854 transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
855 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
856 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
857 CTRequirementLevel::REQUIRED));
858 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
859 .WillRepeatedly(
860 Return(ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS));
861
862 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
863 &transport_security_state_,
864 ct_verifier_.get(), {});
865
866 std::unique_ptr<DummyProofVerifierCallback> callback(
867 new DummyProofVerifierCallback);
868 proof_verifier.VerifyProof(
869 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
870 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
871 verify_context_.get(), &error_details_, &details_, std::move(callback));
872
873 // The flag should be set in the CTVerifyResult.
874 ProofVerifyDetailsChromium* proof_details =
875 reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get());
876 const ct::CTVerifyResult& ct_verify_result = proof_details->ct_verify_result;
877 EXPECT_TRUE(ct_verify_result.policy_compliance_required);
878 }
879
880 // Tests that when CT is required and the connection is compliant, the relevant
881 // flag is set in the CTVerifyResult.
TEST_F(ProofVerifierChromiumTest,CTRequirementsFlagMet)882 TEST_F(ProofVerifierChromiumTest, CTRequirementsFlagMet) {
883 dummy_result_.is_issued_by_known_root = true;
884 MockCertVerifier dummy_verifier;
885 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
886
887 // Set up CT.
888 MockRequireCTDelegate require_ct_delegate;
889 transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
890 EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
891 .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
892 CTRequirementLevel::REQUIRED));
893 EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
894 .WillRepeatedly(
895 Return(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS));
896
897 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
898 &transport_security_state_,
899 ct_verifier_.get(), {});
900
901 std::unique_ptr<DummyProofVerifierCallback> callback(
902 new DummyProofVerifierCallback);
903 proof_verifier.VerifyProof(
904 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
905 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
906 verify_context_.get(), &error_details_, &details_, std::move(callback));
907
908 // The flag should be set in the CTVerifyResult.
909 ProofVerifyDetailsChromium* proof_details =
910 reinterpret_cast<ProofVerifyDetailsChromium*>(details_.get());
911 const ct::CTVerifyResult& ct_verify_result = proof_details->ct_verify_result;
912 EXPECT_TRUE(ct_verify_result.policy_compliance_required);
913 }
914
TEST_F(ProofVerifierChromiumTest,UnknownRootRejected)915 TEST_F(ProofVerifierChromiumTest, UnknownRootRejected) {
916 dummy_result_.is_issued_by_known_root = false;
917
918 MockCertVerifier dummy_verifier;
919 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
920
921 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
922 &transport_security_state_,
923 ct_verifier_.get(), {});
924
925 std::unique_ptr<DummyProofVerifierCallback> callback(
926 new DummyProofVerifierCallback);
927 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
928 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
929 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
930 verify_context_.get(), &error_details_, &details_, std::move(callback));
931 ASSERT_EQ(quic::QUIC_FAILURE, status);
932 EXPECT_EQ(
933 "Failed to verify certificate chain: net::ERR_QUIC_CERT_ROOT_NOT_KNOWN",
934 error_details_);
935 }
936
TEST_F(ProofVerifierChromiumTest,UnknownRootAcceptedWithOverride)937 TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithOverride) {
938 dummy_result_.is_issued_by_known_root = false;
939
940 MockCertVerifier dummy_verifier;
941 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
942
943 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
944 &transport_security_state_,
945 ct_verifier_.get(), {kTestHostname});
946
947 std::unique_ptr<DummyProofVerifierCallback> callback(
948 new DummyProofVerifierCallback);
949 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
950 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
951 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
952 verify_context_.get(), &error_details_, &details_, std::move(callback));
953 ASSERT_EQ(quic::QUIC_SUCCESS, status);
954
955 ASSERT_TRUE(details_.get());
956 ProofVerifyDetailsChromium* verify_details =
957 static_cast<ProofVerifyDetailsChromium*>(details_.get());
958 EXPECT_EQ(dummy_result_.cert_status,
959 verify_details->cert_verify_result.cert_status);
960 }
961
TEST_F(ProofVerifierChromiumTest,UnknownRootAcceptedWithWildcardOverride)962 TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithWildcardOverride) {
963 dummy_result_.is_issued_by_known_root = false;
964
965 MockCertVerifier dummy_verifier;
966 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
967
968 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
969 &transport_security_state_,
970 ct_verifier_.get(), {""});
971
972 std::unique_ptr<DummyProofVerifierCallback> callback(
973 new DummyProofVerifierCallback);
974 quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
975 kTestHostname, kTestPort, kTestConfig, quic::QUIC_VERSION_43,
976 kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
977 verify_context_.get(), &error_details_, &details_, std::move(callback));
978 ASSERT_EQ(quic::QUIC_SUCCESS, status);
979
980 ASSERT_TRUE(details_.get());
981 ProofVerifyDetailsChromium* verify_details =
982 static_cast<ProofVerifyDetailsChromium*>(details_.get());
983 EXPECT_EQ(dummy_result_.cert_status,
984 verify_details->cert_verify_result.cert_status);
985 }
986
987 // Tests that the VerifyCertChain verifies certificates.
TEST_F(ProofVerifierChromiumTest,VerifyCertChain)988 TEST_F(ProofVerifierChromiumTest, VerifyCertChain) {
989 MockCertVerifier dummy_verifier;
990 dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
991
992 ProofVerifierChromium proof_verifier(&dummy_verifier, &ct_policy_enforcer_,
993 &transport_security_state_,
994 ct_verifier_.get(), {});
995
996 std::unique_ptr<DummyProofVerifierCallback> callback(
997 new DummyProofVerifierCallback);
998 quic::QuicAsyncStatus status = proof_verifier.VerifyCertChain(
999 kTestHostname, certs_, /*ocsp_response=*/std::string(),
1000 /*cert_sct=*/std::string(), verify_context_.get(), &error_details_,
1001 &details_, std::move(callback));
1002 ASSERT_EQ(quic::QUIC_SUCCESS, status);
1003
1004 ASSERT_TRUE(details_.get());
1005 ProofVerifyDetailsChromium* verify_details =
1006 static_cast<ProofVerifyDetailsChromium*>(details_.get());
1007 EXPECT_EQ(0u, verify_details->cert_verify_result.cert_status);
1008 }
1009
1010 } // namespace test
1011 } // namespace net
1012