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