xref: /aosp_15_r20/external/cronet/net/quic/crypto/proof_verifier_chromium_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/quic/crypto/proof_verifier_chromium.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/memory/raw_ptr.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/strings/string_piece.h"
13 #include "base/test/metrics/histogram_tester.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "net/base/completion_once_callback.h"
16 #include "net/base/features.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/network_anonymization_key.h"
19 #include "net/cert/cert_status_flags.h"
20 #include "net/cert/cert_verifier.h"
21 #include "net/cert/ct_log_verifier.h"
22 #include "net/cert/ct_policy_enforcer.h"
23 #include "net/cert/ct_policy_status.h"
24 #include "net/cert/ct_serialization.h"
25 #include "net/cert/mock_cert_verifier.h"
26 #include "net/cert/multi_log_ct_verifier.h"
27 #include "net/cert/sct_auditing_delegate.h"
28 #include "net/cert/sct_status_flags.h"
29 #include "net/cert/x509_util.h"
30 #include "net/http/transport_security_state.h"
31 #include "net/http/transport_security_state_test_util.h"
32 #include "net/quic/crypto/proof_source_chromium.h"
33 #include "net/quic/quic_context.h"
34 #include "net/test/cert_test_util.h"
35 #include "net/test/test_data_directory.h"
36 #include "net/third_party/quiche/src/quiche/quic/core/crypto/proof_verifier.h"
37 #include "net/third_party/quiche/src/quiche/quic/core/quic_error_codes.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40 
41 using ::testing::_;
42 using ::testing::Return;
43 
44 namespace net::test {
45 
46 namespace {
47 
48 const char kCTAndPKPHost[] = "hsts-hpkp-preloaded.test";
49 
50 // CertVerifier that will fail the test if it is ever called.
51 class FailsTestCertVerifier : public CertVerifier {
52  public:
53   FailsTestCertVerifier() = default;
54   ~FailsTestCertVerifier() override = default;
55 
56   // CertVerifier implementation
Verify(const RequestParams & params,CertVerifyResult * verify_result,CompletionOnceCallback callback,std::unique_ptr<Request> * out_req,const NetLogWithSource & net_log)57   int Verify(const RequestParams& params,
58              CertVerifyResult* verify_result,
59              CompletionOnceCallback callback,
60              std::unique_ptr<Request>* out_req,
61              const NetLogWithSource& net_log) override {
62     ADD_FAILURE() << "CertVerifier::Verify() should not be called";
63     return ERR_FAILED;
64   }
SetConfig(const Config & config)65   void SetConfig(const Config& config) override {}
AddObserver(Observer * observer)66   void AddObserver(Observer* observer) override {}
RemoveObserver(Observer * observer)67   void RemoveObserver(Observer* observer) override {}
68 };
69 
70 class MockRequireCTDelegate : public TransportSecurityState::RequireCTDelegate {
71  public:
72   MOCK_METHOD3(IsCTRequiredForHost,
73                CTRequirementLevel(const std::string& host,
74                                   const X509Certificate* chain,
75                                   const HashValueVector& hashes));
76 };
77 
78 class MockSCTAuditingDelegate : public SCTAuditingDelegate {
79  public:
80   MOCK_METHOD(bool, IsSCTAuditingEnabled, ());
81   MOCK_METHOD(void,
82               MaybeEnqueueReport,
83               (const net::HostPortPair&,
84                const net::X509Certificate*,
85                const net::SignedCertificateTimestampAndStatusList&));
86 };
87 
88 // Proof source callback which saves the signature into |signature|.
89 class SignatureSaver : public quic::ProofSource::Callback {
90  public:
SignatureSaver(std::string * signature)91   explicit SignatureSaver(std::string* signature) : signature_(signature) {}
92   ~SignatureSaver() override = default;
93 
Run(bool,const quiche::QuicheReferenceCountedPointer<quic::ProofSource::Chain> &,const quic::QuicCryptoProof & proof,std::unique_ptr<quic::ProofSource::Details>)94   void Run(bool /*ok*/,
95            const quiche::QuicheReferenceCountedPointer<
96                quic::ProofSource::Chain>& /*chain*/,
97            const quic::QuicCryptoProof& proof,
98            std::unique_ptr<quic::ProofSource::Details> /*details*/) override {
99     *signature_ = proof.signature;
100   }
101 
102   raw_ptr<std::string> signature_;
103 };
104 
105 class DummyProofVerifierCallback : public quic::ProofVerifierCallback {
106  public:
107   DummyProofVerifierCallback() = default;
108   ~DummyProofVerifierCallback() override = default;
109 
Run(bool ok,const std::string & error_details,std::unique_ptr<quic::ProofVerifyDetails> * details)110   void Run(bool ok,
111            const std::string& error_details,
112            std::unique_ptr<quic::ProofVerifyDetails>* details) override {
113     // Do nothing
114   }
115 };
116 
117 const char kTestHostname[] = "test.example.com";
118 const uint16_t kTestPort = 8443;
119 const char kTestConfig[] = "server config bytes";
120 const char kTestChloHash[] = "CHLO hash";
121 const char kTestEmptyOCSPResponse[] = "";
122 const char kTestEmptySCT[] = "";
123 const char kTestEmptySignature[] = "";
124 
125 // This test exercises code that does not depend on the QUIC version in use
126 // but that still requires a version so we just use the first one.
127 const quic::QuicTransportVersion kTestTransportVersion =
128     AllSupportedQuicVersions().front().transport_version;
129 
130 }  // namespace
131 
132 class ProofVerifierChromiumTest : public ::testing::Test {
133  public:
ProofVerifierChromiumTest()134   ProofVerifierChromiumTest()
135       : verify_context_(std::make_unique<ProofVerifyContextChromium>(
136             0 /*cert_verify_flags*/,
137             NetLogWithSource())) {}
138 
SetUp()139   void SetUp() override {
140     static const char kTestCert[] = "quic-chain.pem";
141     test_cert_ = ImportCertFromFile(GetTestCertsDirectory(), kTestCert);
142     ASSERT_TRUE(test_cert_);
143     certs_.clear();
144     certs_.emplace_back(
145         x509_util::CryptoBufferAsStringPiece(test_cert_->cert_buffer()));
146 
147     dummy_result_.verified_cert = test_cert_;
148     dummy_result_.is_issued_by_known_root = true;
149     dummy_result_.policy_compliance =
150         ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
151   }
152 
GetTestSignature()153   std::string GetTestSignature() {
154     ProofSourceChromium source;
155     source.Initialize(GetTestCertsDirectory().AppendASCII("quic-chain.pem"),
156                       GetTestCertsDirectory().AppendASCII("quic-leaf-cert.key"),
157                       base::FilePath());
158     std::string signature;
159     source.GetProof(quic::QuicSocketAddress(), quic::QuicSocketAddress(),
160                     kTestHostname, kTestConfig, kTestTransportVersion,
161                     kTestChloHash,
162                     std::make_unique<SignatureSaver>(&signature));
163     return signature;
164   }
165 
166  protected:
167   TransportSecurityState transport_security_state_;
168 
169   std::unique_ptr<quic::ProofVerifyContext> verify_context_;
170   std::unique_ptr<quic::ProofVerifyDetails> details_;
171   std::string error_details_;
172   uint8_t tls_alert_;
173   std::vector<std::string> certs_;
174   CertVerifyResult dummy_result_;
175   scoped_refptr<X509Certificate> test_cert_;
176 };
177 
TEST_F(ProofVerifierChromiumTest,VerifyProof)178 TEST_F(ProofVerifierChromiumTest, VerifyProof) {
179   MockCertVerifier dummy_verifier;
180   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
181 
182   ProofVerifierChromium proof_verifier(&dummy_verifier,
183                                        &transport_security_state_, nullptr, {},
184                                        NetworkAnonymizationKey());
185 
186   auto callback = std::make_unique<DummyProofVerifierCallback>();
187   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
188       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
189       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
190       verify_context_.get(), &error_details_, &details_, std::move(callback));
191   ASSERT_EQ(quic::QUIC_SUCCESS, status);
192 
193   ASSERT_TRUE(details_.get());
194   ProofVerifyDetailsChromium* verify_details =
195       static_cast<ProofVerifyDetailsChromium*>(details_.get());
196   EXPECT_EQ(dummy_result_.cert_status,
197             verify_details->cert_verify_result.cert_status);
198 
199   callback = std::make_unique<DummyProofVerifierCallback>();
200   status = proof_verifier.VerifyCertChain(
201       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
202       verify_context_.get(), &error_details_, &details_, &tls_alert_,
203       std::move(callback));
204   ASSERT_EQ(quic::QUIC_SUCCESS, status);
205 
206   ASSERT_TRUE(details_.get());
207   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
208   EXPECT_EQ(dummy_result_.cert_status,
209             verify_details->cert_verify_result.cert_status);
210 }
211 
212 // Tests that the quic::ProofVerifier fails verification if certificate
213 // verification fails.
TEST_F(ProofVerifierChromiumTest,FailsIfCertFails)214 TEST_F(ProofVerifierChromiumTest, FailsIfCertFails) {
215   MockCertVerifier dummy_verifier;
216   ProofVerifierChromium proof_verifier(&dummy_verifier,
217                                        &transport_security_state_, nullptr, {},
218                                        NetworkAnonymizationKey());
219 
220   auto callback = std::make_unique<DummyProofVerifierCallback>();
221   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
222       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
223       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
224       verify_context_.get(), &error_details_, &details_, std::move(callback));
225   ASSERT_EQ(quic::QUIC_FAILURE, status);
226 
227   callback = std::make_unique<DummyProofVerifierCallback>();
228   status = proof_verifier.VerifyCertChain(
229       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
230       verify_context_.get(), &error_details_, &details_, &tls_alert_,
231       std::move(callback));
232   ASSERT_EQ(quic::QUIC_FAILURE, status);
233 }
234 
235 // Confirms that the parameters get passed through to the
236 // CertVerifier::RequestParams as expected.
TEST_F(ProofVerifierChromiumTest,PassesCertVerifierRequestParams)237 TEST_F(ProofVerifierChromiumTest, PassesCertVerifierRequestParams) {
238   CertVerifyResult dummy_result;
239   dummy_result.verified_cert = test_cert_;
240   dummy_result.is_issued_by_known_root = true;
241 
242   ParamRecordingMockCertVerifier dummy_verifier;
243   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result, OK);
244 
245   ProofVerifierChromium proof_verifier(&dummy_verifier,
246                                        &transport_security_state_, nullptr, {},
247                                        NetworkAnonymizationKey());
248 
249   const std::string kTestOcspResponse = "ocsp";
250   const std::string kTestSctList = "sct list";
251 
252   auto callback = std::make_unique<DummyProofVerifierCallback>();
253   quic::QuicAsyncStatus status = proof_verifier.VerifyCertChain(
254       kTestHostname, kTestPort, certs_, kTestOcspResponse, kTestSctList,
255       verify_context_.get(), &error_details_, &details_, &tls_alert_,
256       std::move(callback));
257   ASSERT_EQ(quic::QUIC_SUCCESS, status);
258   ASSERT_EQ(dummy_verifier.GetVerifyParams().size(), 1u);
259   const auto& params = dummy_verifier.GetVerifyParams().front();
260   EXPECT_TRUE(params.certificate()->EqualsIncludingChain(test_cert_.get()));
261   EXPECT_EQ(params.hostname(), kTestHostname);
262   EXPECT_EQ(params.ocsp_response(), kTestOcspResponse);
263   EXPECT_EQ(params.sct_list(), kTestSctList);
264 }
265 
266 // Tests that the quic::ProofVerifier doesn't verify certificates if the config
267 // signature fails.
TEST_F(ProofVerifierChromiumTest,FailsIfSignatureFails)268 TEST_F(ProofVerifierChromiumTest, FailsIfSignatureFails) {
269   FailsTestCertVerifier cert_verifier;
270   ProofVerifierChromium proof_verifier(&cert_verifier,
271                                        &transport_security_state_, nullptr, {},
272                                        NetworkAnonymizationKey());
273 
274   auto callback = std::make_unique<DummyProofVerifierCallback>();
275   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
276       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
277       kTestChloHash, certs_, kTestEmptySCT, kTestEmptySignature,
278       verify_context_.get(), &error_details_, &details_, std::move(callback));
279   ASSERT_EQ(quic::QUIC_FAILURE, status);
280 }
281 
MakeHashValueVector(uint8_t tag)282 HashValueVector MakeHashValueVector(uint8_t tag) {
283   HashValue hash(HASH_VALUE_SHA256);
284   memset(hash.data(), tag, hash.size());
285   HashValueVector hashes;
286   hashes.push_back(hash);
287   return hashes;
288 }
289 
TEST_F(ProofVerifierChromiumTest,IsFatalErrorNotSetForNonFatalError)290 TEST_F(ProofVerifierChromiumTest, IsFatalErrorNotSetForNonFatalError) {
291   dummy_result_.cert_status = CERT_STATUS_DATE_INVALID;
292 
293   MockCertVerifier dummy_verifier;
294   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_,
295                                   ERR_CERT_DATE_INVALID);
296 
297   ProofVerifierChromium proof_verifier(&dummy_verifier,
298                                        &transport_security_state_, nullptr, {},
299                                        NetworkAnonymizationKey());
300 
301   auto callback = std::make_unique<DummyProofVerifierCallback>();
302   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
303       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
304       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
305       verify_context_.get(), &error_details_, &details_, std::move(callback));
306   ASSERT_EQ(quic::QUIC_FAILURE, status);
307 
308   ProofVerifyDetailsChromium* verify_details =
309       static_cast<ProofVerifyDetailsChromium*>(details_.get());
310   EXPECT_FALSE(verify_details->is_fatal_cert_error);
311 
312   callback = std::make_unique<DummyProofVerifierCallback>();
313   status = proof_verifier.VerifyCertChain(
314       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
315       verify_context_.get(), &error_details_, &details_, &tls_alert_,
316       std::move(callback));
317   ASSERT_EQ(quic::QUIC_FAILURE, status);
318 
319   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
320   EXPECT_FALSE(verify_details->is_fatal_cert_error);
321 }
322 
TEST_F(ProofVerifierChromiumTest,IsFatalErrorSetForFatalError)323 TEST_F(ProofVerifierChromiumTest, IsFatalErrorSetForFatalError) {
324   dummy_result_.cert_status = CERT_STATUS_DATE_INVALID;
325 
326   MockCertVerifier dummy_verifier;
327   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_,
328                                   ERR_CERT_DATE_INVALID);
329 
330   const base::Time expiry = base::Time::Now() + base::Seconds(1000);
331   transport_security_state_.AddHSTS(kTestHostname, expiry, true);
332 
333   ProofVerifierChromium proof_verifier(&dummy_verifier,
334                                        &transport_security_state_, nullptr, {},
335                                        NetworkAnonymizationKey());
336 
337   auto callback = std::make_unique<DummyProofVerifierCallback>();
338   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
339       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
340       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
341       verify_context_.get(), &error_details_, &details_, std::move(callback));
342   ASSERT_EQ(quic::QUIC_FAILURE, status);
343   ProofVerifyDetailsChromium* verify_details =
344       static_cast<ProofVerifyDetailsChromium*>(details_.get());
345   EXPECT_TRUE(verify_details->is_fatal_cert_error);
346 
347   callback = std::make_unique<DummyProofVerifierCallback>();
348   status = proof_verifier.VerifyCertChain(
349       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
350       verify_context_.get(), &error_details_, &details_, &tls_alert_,
351       std::move(callback));
352   ASSERT_EQ(quic::QUIC_FAILURE, status);
353   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
354   EXPECT_TRUE(verify_details->is_fatal_cert_error);
355 }
356 
357 // Test that PKP is enforced for certificates that chain up to known roots.
TEST_F(ProofVerifierChromiumTest,PKPEnforced)358 TEST_F(ProofVerifierChromiumTest, PKPEnforced) {
359   base::test::ScopedFeatureList scoped_feature_list_;
360   scoped_feature_list_.InitAndEnableFeature(
361       net::features::kStaticKeyPinningEnforcement);
362   dummy_result_.is_issued_by_known_root = true;
363   dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
364 
365   MockCertVerifier dummy_verifier;
366   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
367 
368   transport_security_state_.EnableStaticPinsForTesting();
369   transport_security_state_.SetPinningListAlwaysTimelyForTesting(true);
370   ScopedTransportSecurityStateSource scoped_security_state_source;
371 
372   ProofVerifierChromium proof_verifier(&dummy_verifier,
373                                        &transport_security_state_, nullptr, {},
374                                        NetworkAnonymizationKey());
375 
376   auto callback = std::make_unique<DummyProofVerifierCallback>();
377   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
378       kCTAndPKPHost, kTestPort, kTestConfig, kTestTransportVersion,
379       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
380       verify_context_.get(), &error_details_, &details_, std::move(callback));
381   ASSERT_EQ(quic::QUIC_FAILURE, status);
382 
383   ASSERT_TRUE(details_.get());
384   ProofVerifyDetailsChromium* verify_details =
385       static_cast<ProofVerifyDetailsChromium*>(details_.get());
386   EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
387               CERT_STATUS_PINNED_KEY_MISSING);
388   EXPECT_FALSE(verify_details->pkp_bypassed);
389 
390   callback = std::make_unique<DummyProofVerifierCallback>();
391   status = proof_verifier.VerifyCertChain(
392       kCTAndPKPHost, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
393       verify_context_.get(), &error_details_, &details_, &tls_alert_,
394       std::move(callback));
395   ASSERT_EQ(quic::QUIC_FAILURE, status);
396 
397   ASSERT_TRUE(details_.get());
398   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
399   EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
400               CERT_STATUS_PINNED_KEY_MISSING);
401   EXPECT_FALSE(verify_details->pkp_bypassed);
402 }
403 
404 // Test |pkp_bypassed| is set when PKP is bypassed due to a local
405 // trust anchor
TEST_F(ProofVerifierChromiumTest,PKPBypassFlagSet)406 TEST_F(ProofVerifierChromiumTest, PKPBypassFlagSet) {
407   base::test::ScopedFeatureList scoped_feature_list_;
408   scoped_feature_list_.InitAndEnableFeature(
409       net::features::kStaticKeyPinningEnforcement);
410   dummy_result_.is_issued_by_known_root = false;
411   dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
412 
413   MockCertVerifier dummy_verifier;
414   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
415 
416   transport_security_state_.EnableStaticPinsForTesting();
417   transport_security_state_.SetPinningListAlwaysTimelyForTesting(true);
418   ScopedTransportSecurityStateSource scoped_security_state_source;
419 
420   ProofVerifierChromium proof_verifier(
421       &dummy_verifier, &transport_security_state_, nullptr, {kCTAndPKPHost},
422       NetworkAnonymizationKey());
423 
424   auto callback = std::make_unique<DummyProofVerifierCallback>();
425   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
426       kCTAndPKPHost, kTestPort, kTestConfig, kTestTransportVersion,
427       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
428       verify_context_.get(), &error_details_, &details_, std::move(callback));
429   ASSERT_EQ(quic::QUIC_SUCCESS, status);
430 
431   ASSERT_TRUE(details_.get());
432   ProofVerifyDetailsChromium* verify_details =
433       static_cast<ProofVerifyDetailsChromium*>(details_.get());
434   EXPECT_TRUE(verify_details->pkp_bypassed);
435 
436   callback = std::make_unique<DummyProofVerifierCallback>();
437   status = proof_verifier.VerifyCertChain(
438       kCTAndPKPHost, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
439       verify_context_.get(), &error_details_, &details_, &tls_alert_,
440       std::move(callback));
441   ASSERT_EQ(quic::QUIC_SUCCESS, status);
442 
443   ASSERT_TRUE(details_.get());
444   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
445   EXPECT_TRUE(verify_details->pkp_bypassed);
446 }
447 
448 // Test that when CT is required (in this case, by the delegate), the
449 // absence of CT information is a socket error.
TEST_F(ProofVerifierChromiumTest,CTIsRequired)450 TEST_F(ProofVerifierChromiumTest, CTIsRequired) {
451   dummy_result_.is_issued_by_known_root = true;
452   dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
453   dummy_result_.policy_compliance =
454       ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
455 
456   MockCertVerifier dummy_verifier;
457   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
458 
459   // Set up CT.
460   MockRequireCTDelegate require_ct_delegate;
461   transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
462   EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
463       .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
464                                  CTRequirementLevel::NOT_REQUIRED));
465   EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname, _, _))
466       .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
467                                  CTRequirementLevel::REQUIRED));
468 
469   ProofVerifierChromium proof_verifier(&dummy_verifier,
470                                        &transport_security_state_, nullptr, {},
471                                        NetworkAnonymizationKey());
472 
473   auto callback = std::make_unique<DummyProofVerifierCallback>();
474   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
475       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
476       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
477       verify_context_.get(), &error_details_, &details_, std::move(callback));
478   ASSERT_EQ(quic::QUIC_FAILURE, status);
479 
480   ASSERT_TRUE(details_.get());
481   ProofVerifyDetailsChromium* verify_details =
482       static_cast<ProofVerifyDetailsChromium*>(details_.get());
483   EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
484               CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
485 
486   callback = std::make_unique<DummyProofVerifierCallback>();
487   status = proof_verifier.VerifyCertChain(
488       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
489       verify_context_.get(), &error_details_, &details_, &tls_alert_,
490       std::move(callback));
491   ASSERT_EQ(quic::QUIC_FAILURE, status);
492 
493   ASSERT_TRUE(details_.get());
494   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
495   EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
496               CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
497 
498   transport_security_state_.SetRequireCTDelegate(nullptr);
499 }
500 
501 // Test that CT is considered even when PKP fails.
TEST_F(ProofVerifierChromiumTest,PKPAndCTBothTested)502 TEST_F(ProofVerifierChromiumTest, PKPAndCTBothTested) {
503   base::test::ScopedFeatureList scoped_feature_list_;
504   scoped_feature_list_.InitAndEnableFeature(
505       net::features::kStaticKeyPinningEnforcement);
506   dummy_result_.is_issued_by_known_root = true;
507   dummy_result_.public_key_hashes = MakeHashValueVector(0x01);
508   dummy_result_.policy_compliance =
509       ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
510 
511   MockCertVerifier dummy_verifier;
512   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
513 
514   // Set up PKP.
515   transport_security_state_.EnableStaticPinsForTesting();
516   transport_security_state_.SetPinningListAlwaysTimelyForTesting(true);
517   ScopedTransportSecurityStateSource scoped_security_state_source;
518 
519   // Set up CT.
520   MockRequireCTDelegate require_ct_delegate;
521   transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
522   EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
523       .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
524                                  CTRequirementLevel::NOT_REQUIRED));
525   EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kCTAndPKPHost, _, _))
526       .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
527                                  CTRequirementLevel::REQUIRED));
528 
529   ProofVerifierChromium proof_verifier(&dummy_verifier,
530                                        &transport_security_state_, nullptr, {},
531                                        NetworkAnonymizationKey());
532 
533   auto callback = std::make_unique<DummyProofVerifierCallback>();
534   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
535       kCTAndPKPHost, kTestPort, kTestConfig, kTestTransportVersion,
536       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
537       verify_context_.get(), &error_details_, &details_, std::move(callback));
538   ASSERT_EQ(quic::QUIC_FAILURE, status);
539 
540   ASSERT_TRUE(details_.get());
541   ProofVerifyDetailsChromium* verify_details =
542       static_cast<ProofVerifyDetailsChromium*>(details_.get());
543   EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
544               CERT_STATUS_PINNED_KEY_MISSING);
545   EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
546               CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
547 
548   callback = std::make_unique<DummyProofVerifierCallback>();
549   status = proof_verifier.VerifyCertChain(
550       kCTAndPKPHost, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
551       verify_context_.get(), &error_details_, &details_, &tls_alert_,
552       std::move(callback));
553   ASSERT_EQ(quic::QUIC_FAILURE, status);
554 
555   ASSERT_TRUE(details_.get());
556   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
557   EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
558               CERT_STATUS_PINNED_KEY_MISSING);
559   EXPECT_TRUE(verify_details->cert_verify_result.cert_status &
560               CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
561 
562   transport_security_state_.SetRequireCTDelegate(nullptr);
563 }
564 
TEST_F(ProofVerifierChromiumTest,UnknownRootRejected)565 TEST_F(ProofVerifierChromiumTest, UnknownRootRejected) {
566   dummy_result_.is_issued_by_known_root = false;
567 
568   MockCertVerifier dummy_verifier;
569   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
570 
571   ProofVerifierChromium proof_verifier(&dummy_verifier,
572                                        &transport_security_state_, nullptr, {},
573                                        NetworkAnonymizationKey());
574 
575   auto callback = std::make_unique<DummyProofVerifierCallback>();
576   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
577       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
578       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
579       verify_context_.get(), &error_details_, &details_, std::move(callback));
580   ASSERT_EQ(quic::QUIC_FAILURE, status);
581   EXPECT_EQ(
582       "Failed to verify certificate chain: net::ERR_QUIC_CERT_ROOT_NOT_KNOWN",
583       error_details_);
584 
585   callback = std::make_unique<DummyProofVerifierCallback>();
586   status = proof_verifier.VerifyCertChain(
587       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
588       verify_context_.get(), &error_details_, &details_, &tls_alert_,
589       std::move(callback));
590   ASSERT_EQ(quic::QUIC_FAILURE, status);
591   EXPECT_EQ(
592       "Failed to verify certificate chain: net::ERR_QUIC_CERT_ROOT_NOT_KNOWN",
593       error_details_);
594 }
595 
TEST_F(ProofVerifierChromiumTest,UnknownRootAcceptedWithOverride)596 TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithOverride) {
597   dummy_result_.is_issued_by_known_root = false;
598 
599   MockCertVerifier dummy_verifier;
600   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
601 
602   ProofVerifierChromium proof_verifier(
603       &dummy_verifier, &transport_security_state_, nullptr, {kTestHostname},
604       NetworkAnonymizationKey());
605 
606   auto callback = std::make_unique<DummyProofVerifierCallback>();
607   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
608       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
609       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
610       verify_context_.get(), &error_details_, &details_, std::move(callback));
611   ASSERT_EQ(quic::QUIC_SUCCESS, status);
612 
613   ASSERT_TRUE(details_.get());
614   ProofVerifyDetailsChromium* verify_details =
615       static_cast<ProofVerifyDetailsChromium*>(details_.get());
616   EXPECT_EQ(dummy_result_.cert_status,
617             verify_details->cert_verify_result.cert_status);
618 
619   callback = std::make_unique<DummyProofVerifierCallback>();
620   status = proof_verifier.VerifyCertChain(
621       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
622       verify_context_.get(), &error_details_, &details_, &tls_alert_,
623       std::move(callback));
624   ASSERT_EQ(quic::QUIC_SUCCESS, status);
625 
626   ASSERT_TRUE(details_.get());
627   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
628   EXPECT_EQ(dummy_result_.cert_status,
629             verify_details->cert_verify_result.cert_status);
630 }
631 
TEST_F(ProofVerifierChromiumTest,UnknownRootAcceptedWithWildcardOverride)632 TEST_F(ProofVerifierChromiumTest, UnknownRootAcceptedWithWildcardOverride) {
633   dummy_result_.is_issued_by_known_root = false;
634 
635   MockCertVerifier dummy_verifier;
636   dummy_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
637 
638   ProofVerifierChromium proof_verifier(&dummy_verifier,
639                                        &transport_security_state_, nullptr,
640                                        {""}, NetworkAnonymizationKey());
641 
642   auto callback = std::make_unique<DummyProofVerifierCallback>();
643   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
644       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
645       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
646       verify_context_.get(), &error_details_, &details_, std::move(callback));
647   ASSERT_EQ(quic::QUIC_SUCCESS, status);
648 
649   ASSERT_TRUE(details_.get());
650   ProofVerifyDetailsChromium* verify_details =
651       static_cast<ProofVerifyDetailsChromium*>(details_.get());
652   EXPECT_EQ(dummy_result_.cert_status,
653             verify_details->cert_verify_result.cert_status);
654 
655   callback = std::make_unique<DummyProofVerifierCallback>();
656   status = proof_verifier.VerifyCertChain(
657       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
658       verify_context_.get(), &error_details_, &details_, &tls_alert_,
659       std::move(callback));
660   ASSERT_EQ(quic::QUIC_SUCCESS, status);
661 
662   ASSERT_TRUE(details_.get());
663   verify_details = static_cast<ProofVerifyDetailsChromium*>(details_.get());
664   EXPECT_EQ(dummy_result_.cert_status,
665             verify_details->cert_verify_result.cert_status);
666 }
667 
668 // Tests that the SCTAuditingDelegate is called to enqueue SCT reports when
669 // verifying a good proof and cert.
TEST_F(ProofVerifierChromiumTest,SCTAuditingReportCollected)670 TEST_F(ProofVerifierChromiumTest, SCTAuditingReportCollected) {
671   dummy_result_.policy_compliance =
672       ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS;
673   MockCertVerifier cert_verifier;
674   cert_verifier.AddResultForCert(test_cert_.get(), dummy_result_, OK);
675 
676   MockSCTAuditingDelegate sct_auditing_delegate;
677   EXPECT_CALL(sct_auditing_delegate, IsSCTAuditingEnabled())
678       .WillRepeatedly(Return(true));
679   // MaybeEnqueueReport() will be called twice: once in VerifyProof() (which
680   // calls VerifyCert()) and once in VerifyCertChain().
681   HostPortPair host_port_pair(kTestHostname, kTestPort);
682   EXPECT_CALL(sct_auditing_delegate, MaybeEnqueueReport(host_port_pair, _, _))
683       .Times(2);
684 
685   ProofVerifierChromium proof_verifier(
686       &cert_verifier, &transport_security_state_, &sct_auditing_delegate, {},
687       NetworkAnonymizationKey());
688 
689   auto callback = std::make_unique<DummyProofVerifierCallback>();
690   quic::QuicAsyncStatus status = proof_verifier.VerifyProof(
691       kTestHostname, kTestPort, kTestConfig, kTestTransportVersion,
692       kTestChloHash, certs_, kTestEmptySCT, GetTestSignature(),
693       verify_context_.get(), &error_details_, &details_, std::move(callback));
694   ASSERT_EQ(quic::QUIC_SUCCESS, status);
695 
696   callback = std::make_unique<DummyProofVerifierCallback>();
697   status = proof_verifier.VerifyCertChain(
698       kTestHostname, kTestPort, certs_, kTestEmptyOCSPResponse, kTestEmptySCT,
699       verify_context_.get(), &error_details_, &details_, &tls_alert_,
700       std::move(callback));
701   ASSERT_EQ(quic::QUIC_SUCCESS, status);
702 }
703 
704 }  // namespace net::test
705