1 // Copyright 2019 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/cert/cert_verify_proc_builtin.h"
6
7 #include "base/memory/raw_ptr.h"
8 #include "base/numerics/safe_conversions.h"
9 #include "base/ranges/algorithm.h"
10 #include "base/run_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/task/sequenced_task_runner.h"
13 #include "base/task/thread_pool.h"
14 #include "base/test/metrics/histogram_tester.h"
15 #include "base/test/scoped_feature_list.h"
16 #include "base/test/task_environment.h"
17 #include "base/time/time.h"
18 #include "net/base/features.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/cert/cert_verify_proc.h"
21 #include "net/cert/crl_set.h"
22 #include "net/cert/ev_root_ca_metadata.h"
23 #include "net/cert/internal/system_trust_store.h"
24 #include "net/cert/time_conversions.h"
25 #include "net/cert_net/cert_net_fetcher_url_request.h"
26 #include "net/http/transport_security_state.h"
27 #include "net/log/net_log_with_source.h"
28 #include "net/log/test_net_log.h"
29 #include "net/test/cert_builder.h"
30 #include "net/test/cert_test_util.h"
31 #include "net/test/embedded_test_server/embedded_test_server.h"
32 #include "net/test/embedded_test_server/http_request.h"
33 #include "net/test/embedded_test_server/http_response.h"
34 #include "net/test/embedded_test_server/request_handler_util.h"
35 #include "net/test/gtest_util.h"
36 #include "net/test/revocation_builder.h"
37 #include "net/url_request/url_request_context.h"
38 #include "net/url_request/url_request_context_builder.h"
39 #include "net/url_request/url_request_test_util.h"
40 #include "testing/gtest/include/gtest/gtest.h"
41 #include "third_party/boringssl/src/pki/trust_store.h"
42 #include "third_party/boringssl/src/pki/trust_store_collection.h"
43 #include "third_party/boringssl/src/pki/trust_store_in_memory.h"
44
45 using net::test::IsError;
46 using net::test::IsOk;
47
48 namespace net {
49
50 namespace {
51
HangRequestAndCallback(base::OnceClosure callback,const test_server::HttpRequest & request)52 std::unique_ptr<test_server::HttpResponse> HangRequestAndCallback(
53 base::OnceClosure callback,
54 const test_server::HttpRequest& request) {
55 std::move(callback).Run();
56 return std::make_unique<test_server::HungResponse>();
57 }
58
FailTest(const std::string & message)59 void FailTest(const std::string& message) {
60 ADD_FAILURE() << message;
61 }
62
FailRequestAndFailTest(const std::string & message,scoped_refptr<base::TaskRunner> main_task_runner,const test_server::HttpRequest & request)63 std::unique_ptr<test_server::HttpResponse> FailRequestAndFailTest(
64 const std::string& message,
65 scoped_refptr<base::TaskRunner> main_task_runner,
66 const test_server::HttpRequest& request) {
67 main_task_runner->PostTask(FROM_HERE, base::BindOnce(FailTest, message));
68 auto response = std::make_unique<test_server::BasicHttpResponse>();
69 response->set_code(HTTP_NOT_ACCEPTABLE);
70 return response;
71 }
72
ServeResponse(HttpStatusCode status_code,const std::string & content_type,const std::string & content,const test_server::HttpRequest & request)73 std::unique_ptr<test_server::HttpResponse> ServeResponse(
74 HttpStatusCode status_code,
75 const std::string& content_type,
76 const std::string& content,
77 const test_server::HttpRequest& request) {
78 auto http_response = std::make_unique<test_server::BasicHttpResponse>();
79
80 http_response->set_code(status_code);
81 http_response->set_content_type(content_type);
82 http_response->set_content(content);
83 return http_response;
84 }
85
MakeRandomHexString(size_t num_bytes)86 std::string MakeRandomHexString(size_t num_bytes) {
87 std::vector<char> rand_bytes;
88 rand_bytes.resize(num_bytes);
89
90 base::RandBytes(rand_bytes.data(), rand_bytes.size());
91 return base::HexEncode(rand_bytes.data(), rand_bytes.size());
92 }
93
MakeRandomPath(base::StringPiece suffix)94 static std::string MakeRandomPath(base::StringPiece suffix) {
95 return "/" + MakeRandomHexString(12) + std::string(suffix);
96 }
97
VerifyOnWorkerThread(const scoped_refptr<CertVerifyProc> & verify_proc,scoped_refptr<X509Certificate> cert,const std::string & hostname,int flags,CertVerifyResult * verify_result,NetLogSource * out_source)98 int VerifyOnWorkerThread(const scoped_refptr<CertVerifyProc>& verify_proc,
99 scoped_refptr<X509Certificate> cert,
100 const std::string& hostname,
101 int flags,
102 CertVerifyResult* verify_result,
103 NetLogSource* out_source) {
104 base::ScopedAllowBaseSyncPrimitivesForTesting scoped_allow_blocking;
105 NetLogWithSource net_log(NetLogWithSource::Make(
106 net::NetLog::Get(), net::NetLogSourceType::CERT_VERIFIER_TASK));
107 int error = verify_proc->Verify(cert.get(), hostname,
108 /*ocsp_response=*/std::string(),
109 /*sct_list=*/std::string(), flags,
110 verify_result, net_log);
111 *out_source = net_log.source();
112 return error;
113 }
114
115 class MockSystemTrustStore : public SystemTrustStore {
116 public:
GetTrustStore()117 bssl::TrustStore* GetTrustStore() override { return &trust_store_; }
118
IsKnownRoot(const bssl::ParsedCertificate * trust_anchor) const119 bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const override {
120 return mock_is_known_root_;
121 }
122
AddTrustStore(bssl::TrustStore * store)123 void AddTrustStore(bssl::TrustStore* store) {
124 trust_store_.AddTrustStore(store);
125 }
126
SetMockIsKnownRoot(bool is_known_root)127 void SetMockIsKnownRoot(bool is_known_root) {
128 mock_is_known_root_ = is_known_root;
129 }
130
131 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
chrome_root_store_version() const132 int64_t chrome_root_store_version() const override { return 0; }
133 #endif
134
135 private:
136 bssl::TrustStoreCollection trust_store_;
137 bool mock_is_known_root_ = false;
138 };
139
140 class BlockingTrustStore : public bssl::TrustStore {
141 public:
GetTrust(const bssl::ParsedCertificate * cert)142 bssl::CertificateTrust GetTrust(
143 const bssl::ParsedCertificate* cert) override {
144 return backing_trust_store_.GetTrust(cert);
145 }
146
SyncGetIssuersOf(const bssl::ParsedCertificate * cert,bssl::ParsedCertificateList * issuers)147 void SyncGetIssuersOf(const bssl::ParsedCertificate* cert,
148 bssl::ParsedCertificateList* issuers) override {
149 sync_get_issuer_started_event_.Signal();
150 sync_get_issuer_ok_to_finish_event_.Wait();
151
152 backing_trust_store_.SyncGetIssuersOf(cert, issuers);
153 }
154
155 base::WaitableEvent sync_get_issuer_started_event_;
156 base::WaitableEvent sync_get_issuer_ok_to_finish_event_;
157 bssl::TrustStoreInMemory backing_trust_store_;
158 };
159
160 } // namespace
161
162 class CertVerifyProcBuiltinTest : public ::testing::Test {
163 public:
SetUp()164 void SetUp() override {
165 cert_net_fetcher_ = base::MakeRefCounted<CertNetFetcherURLRequest>();
166
167 InitializeVerifyProc({});
168
169 context_ = CreateTestURLRequestContextBuilder()->Build();
170
171 cert_net_fetcher_->SetURLRequestContext(context_.get());
172 }
173
TearDown()174 void TearDown() override { cert_net_fetcher_->Shutdown(); }
175
InitializeVerifyProc(const CertificateList & additional_trust_anchors)176 void InitializeVerifyProc(const CertificateList& additional_trust_anchors) {
177 auto mock_system_trust_store = std::make_unique<MockSystemTrustStore>();
178 mock_system_trust_store_ = mock_system_trust_store.get();
179 CertVerifyProc::InstanceParams instance_params;
180 instance_params.additional_trust_anchors = additional_trust_anchors;
181 verify_proc_ = CreateCertVerifyProcBuiltin(
182 cert_net_fetcher_, CRLSet::EmptyCRLSetForTesting(),
183 std::move(mock_system_trust_store), instance_params);
184 }
185
Verify(scoped_refptr<X509Certificate> cert,const std::string & hostname,int flags,CertVerifyResult * verify_result,NetLogSource * out_source,CompletionOnceCallback callback)186 void Verify(scoped_refptr<X509Certificate> cert,
187 const std::string& hostname,
188 int flags,
189 CertVerifyResult* verify_result,
190 NetLogSource* out_source,
191 CompletionOnceCallback callback) {
192 base::ThreadPool::PostTaskAndReplyWithResult(
193 FROM_HERE,
194 {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
195 base::BindOnce(&VerifyOnWorkerThread, verify_proc_, std::move(cert),
196 hostname, flags, verify_result, out_source),
197 std::move(callback));
198 }
199
task_environment()200 base::test::TaskEnvironment& task_environment() { return task_environment_; }
201
202 // Creates a CRL issued and signed by |crl_issuer|, marking |revoked_serials|
203 // as revoked, and registers it to be served by the test server.
204 // Returns the full URL to retrieve the CRL from the test server.
CreateAndServeCrl(EmbeddedTestServer * test_server,CertBuilder * crl_issuer,const std::vector<uint64_t> & revoked_serials,absl::optional<bssl::SignatureAlgorithm> signature_algorithm=absl::nullopt)205 GURL CreateAndServeCrl(EmbeddedTestServer* test_server,
206 CertBuilder* crl_issuer,
207 const std::vector<uint64_t>& revoked_serials,
208 absl::optional<bssl::SignatureAlgorithm>
209 signature_algorithm = absl::nullopt) {
210 std::string crl = BuildCrl(crl_issuer->GetSubject(), crl_issuer->GetKey(),
211 revoked_serials, signature_algorithm);
212 std::string crl_path = MakeRandomPath(".crl");
213 test_server->RegisterRequestHandler(
214 base::BindRepeating(&test_server::HandlePrefixedRequest, crl_path,
215 base::BindRepeating(ServeResponse, HTTP_OK,
216 "application/pkix-crl", crl)));
217 return test_server->GetURL(crl_path);
218 }
219
AddTrustStore(bssl::TrustStore * store)220 void AddTrustStore(bssl::TrustStore* store) {
221 mock_system_trust_store_->AddTrustStore(store);
222 }
223
SetMockIsKnownRoot(bool is_known_root)224 void SetMockIsKnownRoot(bool is_known_root) {
225 mock_system_trust_store_->SetMockIsKnownRoot(is_known_root);
226 }
227
context()228 net::URLRequestContext* context() { return context_.get(); }
229
230 private:
231 base::test::TaskEnvironment task_environment_{
232 base::test::TaskEnvironment::TimeSource::MOCK_TIME,
233 base::test::TaskEnvironment::MainThreadType::IO,
234 };
235
236 CertVerifier::Config config_;
237 std::unique_ptr<net::URLRequestContext> context_;
238
239 // Must outlive `mock_system_trust_store_`.
240 scoped_refptr<CertVerifyProc> verify_proc_;
241
242 raw_ptr<MockSystemTrustStore> mock_system_trust_store_ = nullptr;
243 scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher_;
244 };
245
TEST_F(CertVerifyProcBuiltinTest,ShouldBypassHSTS)246 TEST_F(CertVerifyProcBuiltinTest, ShouldBypassHSTS) {
247 auto [leaf, root] = CertBuilder::CreateSimpleChain2();
248 InitializeVerifyProc(
249 /*additional_trust_anchors=*/{root->GetX509Certificate()});
250
251 EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
252 ASSERT_TRUE(test_server.InitializeAndListen());
253
254 // CRL that marks leaf as revoked.
255 leaf->SetCrlDistributionPointUrl(
256 CreateAndServeCrl(&test_server, root.get(), {leaf->GetSerialNumber()}));
257
258 test_server.StartAcceptingConnections();
259
260 {
261 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
262 ASSERT_TRUE(chain.get());
263
264 NetLogSource verify_net_log_source;
265 CertVerifyResult verify_result;
266 TestCompletionCallback verify_callback;
267 // Ensure HSTS upgrades for the domain which hosts the CRLs.
268 context()->transport_security_state()->AddHSTS(
269 test_server.base_url().host(), base::Time::Now() + base::Seconds(30),
270 /*include_subdomains=*/true);
271 ASSERT_TRUE(context()->transport_security_state()->ShouldUpgradeToSSL(
272 test_server.base_url().host()));
273 Verify(chain.get(), "www.example.com",
274 CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
275 &verify_result, &verify_net_log_source, verify_callback.callback());
276
277 int error = verify_callback.WaitForResult();
278 EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
279 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
280 }
281 }
282
TEST_F(CertVerifyProcBuiltinTest,SimpleSuccess)283 TEST_F(CertVerifyProcBuiltinTest, SimpleSuccess) {
284 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
285 InitializeVerifyProc(
286 /*additional_trust_anchors=*/{root->GetX509Certificate()});
287
288 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
289 ASSERT_TRUE(chain.get());
290
291 base::HistogramTester histogram_tester;
292 CertVerifyResult verify_result;
293 NetLogSource verify_net_log_source;
294 TestCompletionCallback callback;
295 Verify(chain.get(), "www.example.com", /*flags=*/0, &verify_result,
296 &verify_net_log_source, callback.callback());
297
298 int error = callback.WaitForResult();
299 EXPECT_THAT(error, IsOk());
300 EXPECT_THAT(histogram_tester.GetAllSamples(
301 "Net.CertVerifier.PathBuilderIterationCount"),
302 testing::ElementsAre(base::Bucket(/*min=*/2, /*count=*/1)));
303 }
304
TEST_F(CertVerifyProcBuiltinTest,CRLNotCheckedForKnownRoots)305 TEST_F(CertVerifyProcBuiltinTest, CRLNotCheckedForKnownRoots) {
306 auto [leaf, root] = CertBuilder::CreateSimpleChain2();
307 InitializeVerifyProc(
308 /*additional_trust_anchors=*/{root->GetX509Certificate()});
309
310 EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
311 ASSERT_TRUE(test_server.InitializeAndListen());
312
313 // CRL that marks leaf as revoked.
314 leaf->SetCrlDistributionPointUrl(
315 CreateAndServeCrl(&test_server, root.get(), {leaf->GetSerialNumber()}));
316
317 test_server.StartAcceptingConnections();
318
319 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
320 ASSERT_TRUE(chain.get());
321
322 NetLogSource verify_net_log_source;
323
324 {
325 CertVerifyResult verify_result;
326 TestCompletionCallback verify_callback;
327 Verify(chain.get(), "www.example.com",
328 CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
329 &verify_result, &verify_net_log_source, verify_callback.callback());
330
331 int error = verify_callback.WaitForResult();
332 EXPECT_THAT(error, IsError(ERR_CERT_REVOKED));
333 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
334 }
335
336 {
337 // Pretend the root is a known root.
338 SetMockIsKnownRoot(true);
339 base::HistogramTester histogram_tester;
340 CertVerifyResult verify_result;
341 TestCompletionCallback verify_callback;
342 Verify(chain.get(), "www.example.com",
343 CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
344 &verify_result, &verify_net_log_source, verify_callback.callback());
345
346 int error = verify_callback.WaitForResult();
347 // CRLs are not checked for chains issued by known roots, so verification
348 // should be successful.
349 EXPECT_THAT(error, IsOk());
350 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
351 EXPECT_THAT(histogram_tester.GetAllSamples(
352 "Net.CertVerifier.PathBuilderIterationCount"),
353 testing::ElementsAre(base::Bucket(/*min=*/1, /*count=*/1)));
354 }
355 }
356
357 // Tests that if the verification deadline is exceeded during revocation
358 // checking, additional CRL fetches will not be attempted.
TEST_F(CertVerifyProcBuiltinTest,RevocationCheckDeadlineCRL)359 TEST_F(CertVerifyProcBuiltinTest, RevocationCheckDeadlineCRL) {
360 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
361 InitializeVerifyProc(
362 /*additional_trust_anchors=*/{root->GetX509Certificate()});
363
364 const base::TimeDelta timeout_increment =
365 CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
366 base::Milliseconds(1);
367 const int expected_request_count =
368 base::ClampFloor(GetCertVerifyProcBuiltinTimeLimitForTesting() /
369 timeout_increment) +
370 1;
371
372 EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
373 ASSERT_TRUE(test_server.InitializeAndListen());
374
375 // Set up the test cert to have enough crlDistributionPoint urls that if the
376 // first N-1 requests hang the deadline will be exceeded before the Nth
377 // request is made.
378 std::vector<GURL> crl_urls;
379 std::vector<base::RunLoop> runloops(expected_request_count);
380 for (int i = 0; i < expected_request_count; ++i) {
381 std::string path = base::StringPrintf("/hung/%i", i);
382 crl_urls.emplace_back(test_server.GetURL(path));
383 test_server.RegisterRequestHandler(
384 base::BindRepeating(&test_server::HandlePrefixedRequest, path,
385 base::BindRepeating(&HangRequestAndCallback,
386 runloops[i].QuitClosure())));
387 }
388 // Add CRL URLs and handlers that will add test failures if requested.
389 for (int i = expected_request_count; i < expected_request_count + 1; ++i) {
390 std::string path = base::StringPrintf("/failtest/%i", i);
391 crl_urls.emplace_back(test_server.GetURL(path));
392 test_server.RegisterRequestHandler(base::BindRepeating(
393 &test_server::HandlePrefixedRequest, path,
394 base::BindRepeating(FailRequestAndFailTest,
395 "additional request made after deadline exceeded",
396 base::SequencedTaskRunner::GetCurrentDefault())));
397 }
398 leaf->SetCrlDistributionPointUrls(crl_urls);
399
400 test_server.StartAcceptingConnections();
401
402 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
403 ASSERT_TRUE(chain.get());
404
405 base::HistogramTester histogram_tester;
406 CertVerifyResult verify_result;
407 NetLogSource verify_net_log_source;
408 TestCompletionCallback verify_callback;
409 Verify(chain.get(), "www.example.com",
410 CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
411 &verify_result, &verify_net_log_source, verify_callback.callback());
412
413 for (int i = 0; i < expected_request_count; i++) {
414 // Wait for request #|i| to be made.
415 runloops[i].Run();
416 // Advance virtual time to cause the timeout task to become runnable.
417 task_environment().AdvanceClock(timeout_increment);
418 }
419
420 // Once |expected_request_count| requests have been made and timed out, the
421 // overall deadline should be reached, and no more requests should have been
422 // made. (If they were, the test will fail due to the ADD_FAILURE callback in
423 // the request handlers.)
424 int error = verify_callback.WaitForResult();
425 // Soft-fail revocation checking was used, therefore verification result
426 // should be OK even though none of the CRLs could be retrieved.
427 EXPECT_THAT(error, IsOk());
428 EXPECT_THAT(histogram_tester.GetAllSamples(
429 "Net.CertVerifier.PathBuilderIterationCount"),
430 testing::ElementsAre(base::Bucket(/*min=*/2, /*count=*/1)));
431 }
432
433 // Tests that if the verification deadline is exceeded during revocation
434 // checking, additional OCSP fetches will not be attempted.
TEST_F(CertVerifyProcBuiltinTest,RevocationCheckDeadlineOCSP)435 TEST_F(CertVerifyProcBuiltinTest, RevocationCheckDeadlineOCSP) {
436 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
437 InitializeVerifyProc(
438 /*additional_trust_anchors=*/{root->GetX509Certificate()});
439
440 const base::TimeDelta timeout_increment =
441 CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
442 base::Milliseconds(1);
443 const int expected_request_count =
444 base::ClampFloor(GetCertVerifyProcBuiltinTimeLimitForTesting() /
445 timeout_increment) +
446 1;
447
448 EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
449 ASSERT_TRUE(test_server.InitializeAndListen());
450
451 // Set up the test cert to have enough OCSP urls that if the
452 // first N-1 requests hang the deadline will be exceeded before the Nth
453 // request is made.
454 std::vector<GURL> ocsp_urls;
455 std::vector<base::RunLoop> runloops(expected_request_count);
456 for (int i = 0; i < expected_request_count; ++i) {
457 std::string path = base::StringPrintf("/hung/%i", i);
458 ocsp_urls.emplace_back(test_server.GetURL(path));
459 test_server.RegisterRequestHandler(
460 base::BindRepeating(&test_server::HandlePrefixedRequest, path,
461 base::BindRepeating(&HangRequestAndCallback,
462 runloops[i].QuitClosure())));
463 }
464 // Add OCSP URLs and handlers that will add test failures if requested.
465 for (int i = expected_request_count; i < expected_request_count + 1; ++i) {
466 std::string path = base::StringPrintf("/failtest/%i", i);
467 ocsp_urls.emplace_back(test_server.GetURL(path));
468 test_server.RegisterRequestHandler(base::BindRepeating(
469 &test_server::HandlePrefixedRequest, path,
470 base::BindRepeating(FailRequestAndFailTest,
471 "additional request made after deadline exceeded",
472 base::SequencedTaskRunner::GetCurrentDefault())));
473 }
474 leaf->SetCaIssuersAndOCSPUrls({}, ocsp_urls);
475
476 test_server.StartAcceptingConnections();
477
478 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
479 ASSERT_TRUE(chain.get());
480
481 CertVerifyResult verify_result;
482 NetLogSource verify_net_log_source;
483 TestCompletionCallback verify_callback;
484 Verify(chain.get(), "www.example.com",
485 CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
486 &verify_result, &verify_net_log_source, verify_callback.callback());
487
488 for (int i = 0; i < expected_request_count; i++) {
489 // Wait for request #|i| to be made.
490 runloops[i].Run();
491 // Advance virtual time to cause the timeout task to become runnable.
492 task_environment().AdvanceClock(timeout_increment);
493 }
494
495 // Once |expected_request_count| requests have been made and timed out, the
496 // overall deadline should be reached, and no more requests should have been
497 // made. (If they were, the test will fail due to the ADD_FAILURE callback in
498 // the request handlers.)
499 int error = verify_callback.WaitForResult();
500 // Soft-fail revocation checking was used, therefore verification result
501 // should be OK even though none of the OCSP responses could be retrieved.
502 EXPECT_THAT(error, IsOk());
503 }
504
505 #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
506 // Tests that if we're doing EV verification, that no OCSP revocation checking
507 // is done.
TEST_F(CertVerifyProcBuiltinTest,EVNoOCSPRevocationChecks)508 TEST_F(CertVerifyProcBuiltinTest, EVNoOCSPRevocationChecks) {
509 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
510 InitializeVerifyProc(
511 /*additional_trust_anchors=*/{root->GetX509Certificate()});
512
513 // Add test EV policy to leaf and intermediate.
514 static const char kEVTestCertPolicy[] = "1.2.3.4";
515 leaf->SetCertificatePolicies({kEVTestCertPolicy});
516 intermediate->SetCertificatePolicies({kEVTestCertPolicy});
517
518 EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
519 ASSERT_TRUE(test_server.InitializeAndListen());
520
521 // Set up the test intermediate to have an OCSP url that fails the test if
522 // called.
523 std::vector<GURL> ocsp_urls;
524 std::string path = "/failtest";
525 ocsp_urls.emplace_back(test_server.GetURL(path));
526 test_server.RegisterRequestHandler(base::BindRepeating(
527 &test_server::HandlePrefixedRequest, path,
528 base::BindRepeating(FailRequestAndFailTest,
529 "no OCSP requests should be sent",
530 base::SequencedTaskRunner::GetCurrentDefault())));
531 intermediate->SetCaIssuersAndOCSPUrls({}, ocsp_urls);
532 test_server.StartAcceptingConnections();
533
534 // Consider the root of the test chain a valid EV root for the test policy.
535 ScopedTestEVPolicy scoped_test_ev_policy(
536 EVRootCAMetadata::GetInstance(),
537 X509Certificate::CalculateFingerprint256(root->GetCertBuffer()),
538 kEVTestCertPolicy);
539
540 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
541 ASSERT_TRUE(chain.get());
542
543 RecordingNetLogObserver net_log_observer(NetLogCaptureMode::kDefault);
544 CertVerifyResult verify_result;
545 NetLogSource verify_net_log_source;
546 TestCompletionCallback verify_callback;
547 Verify(chain.get(), "www.example.com",
548 /*flags=*/0,
549 &verify_result, &verify_net_log_source, verify_callback.callback());
550
551 // EV doesn't do revocation checking, therefore verification result
552 // should be OK and EV.
553 int error = verify_callback.WaitForResult();
554 EXPECT_THAT(error, IsOk());
555 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
556 EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
557
558 auto events = net_log_observer.GetEntriesForSource(verify_net_log_source);
559
560 auto event = base::ranges::find(
561 events, NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT,
562 &NetLogEntry::type);
563 ASSERT_NE(event, events.end());
564 EXPECT_EQ(net::NetLogEventPhase::BEGIN, event->phase);
565 EXPECT_EQ(true, event->params.FindBool("is_ev_attempt"));
566
567 event = base::ranges::find(++event, events.end(),
568 NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT,
569 &NetLogEntry::type);
570 ASSERT_NE(event, events.end());
571 EXPECT_EQ(net::NetLogEventPhase::NONE, event->phase);
572 EXPECT_FALSE(event->params.FindString("errors"));
573
574 event = base::ranges::find(
575 ++event, events.end(),
576 NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT, &NetLogEntry::type);
577 ASSERT_NE(event, events.end());
578 EXPECT_EQ(net::NetLogEventPhase::END, event->phase);
579 EXPECT_EQ(true, event->params.FindBool("has_valid_path"));
580 }
581 #endif // defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
582
TEST_F(CertVerifyProcBuiltinTest,DeadlineExceededDuringSyncGetIssuers)583 TEST_F(CertVerifyProcBuiltinTest, DeadlineExceededDuringSyncGetIssuers) {
584 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
585 InitializeVerifyProc(
586 /*additional_trust_anchors=*/{root->GetX509Certificate()});
587
588 BlockingTrustStore trust_store;
589 AddTrustStore(&trust_store);
590
591 auto intermediate_parsed_cert = bssl::ParsedCertificate::Create(
592 intermediate->DupCertBuffer(), {}, nullptr);
593 ASSERT_TRUE(intermediate_parsed_cert);
594 trust_store.backing_trust_store_.AddCertificateWithUnspecifiedTrust(
595 intermediate_parsed_cert);
596
597 scoped_refptr<X509Certificate> chain = leaf->GetX509Certificate();
598 ASSERT_TRUE(chain.get());
599
600 CertVerifyResult verify_result;
601 NetLogSource verify_net_log_source;
602 TestCompletionCallback verify_callback;
603 Verify(chain.get(), "www.example.com",
604 /*flags=*/0,
605 &verify_result, &verify_net_log_source, verify_callback.callback());
606
607 // Wait for trust_store.SyncGetIssuersOf to be called.
608 trust_store.sync_get_issuer_started_event_.Wait();
609
610 // Advance the clock past the verifier deadline.
611 const base::TimeDelta timeout_increment =
612 GetCertVerifyProcBuiltinTimeLimitForTesting() + base::Milliseconds(1);
613 task_environment().AdvanceClock(timeout_increment);
614
615 // Signal trust_store.SyncGetIssuersOf to finish.
616 trust_store.sync_get_issuer_ok_to_finish_event_.Signal();
617
618 int error = verify_callback.WaitForResult();
619 // Because the deadline was reached while retrieving the intermediate, path
620 // building should have stopped there and not found the root. The partial
621 // path built up to that point should be returned, and the error should be
622 // CERT_AUTHORITY_INVALID.
623 EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
624 ASSERT_EQ(1u, verify_result.verified_cert->intermediate_buffers().size());
625 EXPECT_EQ(intermediate->GetCertBuffer(),
626 verify_result.verified_cert->intermediate_buffers()[0].get());
627 }
628
629 namespace {
630
631 // Returns a TLV to use as an unknown signature algorithm when building a cert.
632 // The specific contents are as follows (the OID is from
633 // https://davidben.net/oid):
634 //
635 // SEQUENCE {
636 // OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.0 }
637 // NULL {}
638 // }
UnknownSignatureAlgorithmTLV()639 std::string UnknownSignatureAlgorithmTLV() {
640 const uint8_t kInvalidSignatureAlgorithmTLV[] = {
641 0x30, 0x10, 0x06, 0x0c, 0x2a, 0x86, 0x48, 0x86, 0xf7,
642 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00, 0x05, 0x00};
643 return std::string(std::begin(kInvalidSignatureAlgorithmTLV),
644 std::end(kInvalidSignatureAlgorithmTLV));
645 }
646
647 // Returns a TLV to use as an invalid signature algorithm when building a cert.
648 // This is a SEQUENCE so that it will pass the bssl::ParseCertificate code
649 // and fail inside bssl::ParseSignatureAlgorithm.
650 // SEQUENCE {
651 // INTEGER { 42 }
652 // }
InvalidSignatureAlgorithmTLV()653 std::string InvalidSignatureAlgorithmTLV() {
654 const uint8_t kInvalidSignatureAlgorithmTLV[] = {0x30, 0x03, 0x02, 0x01,
655 0x2a};
656 return std::string(std::begin(kInvalidSignatureAlgorithmTLV),
657 std::end(kInvalidSignatureAlgorithmTLV));
658 }
659
660 } // namespace
661
TEST_F(CertVerifyProcBuiltinTest,UnknownSignatureAlgorithmTarget)662 TEST_F(CertVerifyProcBuiltinTest, UnknownSignatureAlgorithmTarget) {
663 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
664 leaf->SetSignatureAlgorithmTLV(UnknownSignatureAlgorithmTLV());
665
666 // Trust the root and build a chain to verify that includes the intermediate.
667 ScopedTestRoot scoped_root(root->GetX509Certificate());
668 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
669 ASSERT_TRUE(chain.get());
670
671 int flags = 0;
672 CertVerifyResult verify_result;
673 NetLogSource verify_net_log_source;
674 TestCompletionCallback callback;
675 Verify(chain.get(), "www.example.com", flags, &verify_result,
676 &verify_net_log_source, callback.callback());
677 int error = callback.WaitForResult();
678 // Unknown signature algorithm in the leaf cert should result in the cert
679 // being invalid.
680 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID);
681 EXPECT_THAT(error, IsError(ERR_CERT_INVALID));
682 }
683
TEST_F(CertVerifyProcBuiltinTest,UnparsableMismatchedTBSSignatureAlgorithmTarget)684 TEST_F(CertVerifyProcBuiltinTest,
685 UnparsableMismatchedTBSSignatureAlgorithmTarget) {
686 auto [leaf, root] = CertBuilder::CreateSimpleChain2();
687 // Set only the tbsCertificate signature to an invalid value.
688 leaf->SetTBSSignatureAlgorithmTLV(InvalidSignatureAlgorithmTLV());
689
690 // Trust the root and build a chain to verify.
691 ScopedTestRoot scoped_root(root->GetX509Certificate());
692 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
693 ASSERT_TRUE(chain.get());
694
695 int flags = 0;
696 CertVerifyResult verify_result;
697 NetLogSource verify_net_log_source;
698 TestCompletionCallback callback;
699 Verify(chain.get(), "www.example.com", flags, &verify_result,
700 &verify_net_log_source, callback.callback());
701 int error = callback.WaitForResult();
702 // Invalid signature algorithm in the leaf cert should result in the
703 // cert being invalid.
704 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID);
705 EXPECT_THAT(error, IsError(ERR_CERT_INVALID));
706 }
707
TEST_F(CertVerifyProcBuiltinTest,UnknownSignatureAlgorithmIntermediate)708 TEST_F(CertVerifyProcBuiltinTest, UnknownSignatureAlgorithmIntermediate) {
709 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
710 intermediate->SetSignatureAlgorithmTLV(UnknownSignatureAlgorithmTLV());
711
712 // Trust the root and build a chain to verify that includes the intermediate.
713 ScopedTestRoot scoped_root(root->GetX509Certificate());
714 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
715 ASSERT_TRUE(chain.get());
716
717 int flags = 0;
718 CertVerifyResult verify_result;
719 NetLogSource verify_net_log_source;
720 TestCompletionCallback callback;
721 Verify(chain.get(), "www.example.com", flags, &verify_result,
722 &verify_net_log_source, callback.callback());
723 int error = callback.WaitForResult();
724 // Unknown signature algorithm in the intermediate cert should result in the
725 // cert being invalid.
726 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID);
727 EXPECT_THAT(error, IsError(ERR_CERT_INVALID));
728 }
729
TEST_F(CertVerifyProcBuiltinTest,UnparsableMismatchedTBSSignatureAlgorithmIntermediate)730 TEST_F(CertVerifyProcBuiltinTest,
731 UnparsableMismatchedTBSSignatureAlgorithmIntermediate) {
732 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
733 // Set only the tbsCertificate signature to an invalid value.
734 intermediate->SetTBSSignatureAlgorithmTLV(InvalidSignatureAlgorithmTLV());
735
736 // Trust the root and build a chain to verify that includes the intermediate.
737 ScopedTestRoot scoped_root(root->GetX509Certificate());
738 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
739 ASSERT_TRUE(chain.get());
740 ASSERT_EQ(chain->intermediate_buffers().size(), 1U);
741
742 int flags = 0;
743 CertVerifyResult verify_result;
744 NetLogSource verify_net_log_source;
745 TestCompletionCallback callback;
746 Verify(chain.get(), "www.example.com", flags, &verify_result,
747 &verify_net_log_source, callback.callback());
748 int error = callback.WaitForResult();
749 // Invalid signature algorithm in the intermediate cert should result in the
750 // cert being invalid.
751 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID);
752 EXPECT_THAT(error, IsError(ERR_CERT_INVALID));
753 }
754
TEST_F(CertVerifyProcBuiltinTest,UnknownSignatureAlgorithmRoot)755 TEST_F(CertVerifyProcBuiltinTest, UnknownSignatureAlgorithmRoot) {
756 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
757 root->SetSignatureAlgorithmTLV(UnknownSignatureAlgorithmTLV());
758
759 // Trust the root and build a chain to verify that includes the intermediate.
760 ScopedTestRoot scoped_root(root->GetX509Certificate());
761 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
762 ASSERT_TRUE(chain.get());
763
764 int flags = 0;
765 CertVerifyResult verify_result;
766 NetLogSource verify_net_log_source;
767 TestCompletionCallback callback;
768 Verify(chain.get(), "www.example.com", flags, &verify_result,
769 &verify_net_log_source, callback.callback());
770 int error = callback.WaitForResult();
771 // Unknown signature algorithm in the root cert should have no effect on
772 // verification.
773 EXPECT_THAT(error, IsOk());
774 }
775
776 // This test is disabled on Android as adding the invalid root through
777 // ScopedTestRoot causes it to be parsed by the Java X509 code which barfs. We
778 // could re-enable if Chrome on Android has fully switched to the
779 // builtin-verifier and ScopedTestRoot no longer has Android-specific code.
780 #if BUILDFLAG(IS_ANDROID)
781 #define MAYBE_UnparsableMismatchedTBSSignatureAlgorithmRoot \
782 DISABLED_UnparsableMismatchedTBSSignatureAlgorithmRoot
783 #else
784 #define MAYBE_UnparsableMismatchedTBSSignatureAlgorithmRoot \
785 UnparsableMismatchedTBSSignatureAlgorithmRoot
786 #endif
TEST_F(CertVerifyProcBuiltinTest,MAYBE_UnparsableMismatchedTBSSignatureAlgorithmRoot)787 TEST_F(CertVerifyProcBuiltinTest,
788 MAYBE_UnparsableMismatchedTBSSignatureAlgorithmRoot) {
789 auto [leaf, intermediate, root] = CertBuilder::CreateSimpleChain3();
790 // Set only the tbsCertificate signature to an invalid value.
791 root->SetTBSSignatureAlgorithmTLV(InvalidSignatureAlgorithmTLV());
792
793 // Trust the root and build a chain to verify that includes the intermediate.
794 ScopedTestRoot scoped_root(root->GetX509Certificate());
795 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
796 ASSERT_TRUE(chain.get());
797
798 int flags = 0;
799 CertVerifyResult verify_result;
800 NetLogSource verify_net_log_source;
801 TestCompletionCallback callback;
802 Verify(chain.get(), "www.example.com", flags, &verify_result,
803 &verify_net_log_source, callback.callback());
804 int error = callback.WaitForResult();
805 // Invalid signature algorithm in the root cert should have no effect on
806 // verification.
807 EXPECT_THAT(error, IsOk());
808 }
809
810 class CertVerifyProcBuiltinIterationTest
811 : public CertVerifyProcBuiltinTest,
812 public testing::WithParamInterface<bool> {
813 public:
CertVerifyProcBuiltinIterationTest()814 CertVerifyProcBuiltinIterationTest() {
815 if (new_iteration_limit()) {
816 feature_list_.InitAndEnableFeature(
817 features::kNewCertPathBuilderIterationLimit);
818 } else {
819 feature_list_.InitAndDisableFeature(
820 features::kNewCertPathBuilderIterationLimit);
821 }
822 }
823
new_iteration_limit() const824 bool new_iteration_limit() const { return GetParam(); }
825
826 private:
827 base::test::ScopedFeatureList feature_list_;
828 };
829
TEST_P(CertVerifyProcBuiltinIterationTest,IterationLimit)830 TEST_P(CertVerifyProcBuiltinIterationTest, IterationLimit) {
831 // Create a chain which will require many iterations in the path builder.
832 std::vector<std::unique_ptr<CertBuilder>> builders =
833 CertBuilder::CreateSimpleChain(6);
834
835 base::Time not_before = base::Time::Now() - base::Days(1);
836 base::Time not_after = base::Time::Now() + base::Days(1);
837 for (auto& builder : builders) {
838 builder->SetValidity(not_before, not_after);
839 }
840
841 // Generate certificates, making two versions of each intermediate.
842 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
843 for (size_t i = 1; i < builders.size(); i++) {
844 intermediates.push_back(builders[i]->DupCertBuffer());
845 builders[i]->SetValidity(not_before, not_after + base::Seconds(1));
846 intermediates.push_back(builders[i]->DupCertBuffer());
847 }
848
849 // The above alone is enough to make the path builder explore many paths, but
850 // it will always return the best path it has found, so the error will be the
851 // same. Instead, arrange for all those paths to be invalid (untrusted root),
852 // and add a separate chain that is valid.
853 CertBuilder root_ok(/*orig_cert=*/builders[2]->GetCertBuffer(),
854 /*issuer=*/nullptr);
855 CertBuilder intermediate_ok(/*orig_cert=*/builders[1]->GetCertBuffer(),
856 /*issuer=*/&root_ok);
857 // Using the old intermediate as a template does not preserve the subject,
858 // SKID, or key.
859 intermediate_ok.SetSubjectTLV(
860 base::as_bytes(base::make_span(builders[1]->GetSubject())));
861 intermediate_ok.SetKey(bssl::UpRef(builders[1]->GetKey()));
862 intermediate_ok.SetSubjectKeyIdentifier(
863 builders[1]->GetSubjectKeyIdentifier());
864 // Make the valid intermediate older than the invalid ones, so that it is
865 // explored last.
866 intermediate_ok.SetValidity(not_before - base::Seconds(10),
867 not_after - base::Seconds(10));
868 intermediates.push_back(intermediate_ok.DupCertBuffer());
869
870 // Verify the chain.
871 ScopedTestRoot scoped_root(root_ok.GetX509Certificate().get());
872 scoped_refptr<X509Certificate> chain = X509Certificate::CreateFromBuffer(
873 builders[0]->DupCertBuffer(), std::move(intermediates));
874 ASSERT_TRUE(chain.get());
875
876 RecordingNetLogObserver net_log_observer(NetLogCaptureMode::kDefault);
877 int flags = 0;
878 CertVerifyResult verify_result;
879 NetLogSource verify_net_log_source;
880 TestCompletionCallback callback;
881 Verify(chain.get(), "www.example.com", flags, &verify_result,
882 &verify_net_log_source, callback.callback());
883 int error = callback.WaitForResult();
884
885 auto events = net_log_observer.GetEntriesForSource(verify_net_log_source);
886 auto event = base::ranges::find_if(events, [](const NetLogEntry& e) {
887 return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT &&
888 e.phase == NetLogEventPhase::END;
889 });
890 ASSERT_NE(event, events.end());
891
892 if (new_iteration_limit()) {
893 // The path builder gives up before it finishes all the invalid paths.
894 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
895 EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
896 EXPECT_EQ(true, event->params.FindBool("exceeded_iteration_limit"));
897 } else {
898 // After exploring many dead ends, the path builder finds the valid path.
899 EXPECT_THAT(error, IsOk());
900 EXPECT_FALSE(event->params.Find("exceeded_iteration_limit"));
901 }
902 }
903
904 INSTANTIATE_TEST_SUITE_P(NewLimit,
905 CertVerifyProcBuiltinIterationTest,
906 testing::Bool());
907
908 } // namespace net
909