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