1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/cert/cert_verify_proc_builtin.h"
6
7 #include "base/run_loop.h"
8 #include "base/task/post_task.h"
9 #include "base/task/thread_pool.h"
10 #include "base/test/task_environment.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/cert/cert_verify_proc.h"
13 #include "net/cert/crl_set.h"
14 #include "net/cert/ev_root_ca_metadata.h"
15 #include "net/cert/internal/system_trust_store.h"
16 #include "net/cert_net/cert_net_fetcher_url_request.h"
17 #include "net/der/encode_values.h"
18 #include "net/log/net_log_with_source.h"
19 #include "net/log/test_net_log.h"
20 #include "net/test/cert_builder.h"
21 #include "net/test/cert_test_util.h"
22 #include "net/test/embedded_test_server/embedded_test_server.h"
23 #include "net/test/embedded_test_server/http_request.h"
24 #include "net/test/embedded_test_server/http_response.h"
25 #include "net/test/embedded_test_server/request_handler_util.h"
26 #include "net/test/gtest_util.h"
27 #include "net/url_request/url_request_test_util.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29
30 using net::test::IsError;
31 using net::test::IsOk;
32
33 namespace net {
34
35 namespace {
36
37 class DummySystemTrustStoreProvider : public SystemTrustStoreProvider {
38 public:
CreateSystemTrustStore()39 std::unique_ptr<SystemTrustStore> CreateSystemTrustStore() override {
40 return CreateEmptySystemTrustStore();
41 }
42 };
43
HangRequestAndCallback(base::OnceClosure callback,const test_server::HttpRequest & request)44 std::unique_ptr<test_server::HttpResponse> HangRequestAndCallback(
45 base::OnceClosure callback,
46 const test_server::HttpRequest& request) {
47 std::move(callback).Run();
48 return std::make_unique<test_server::HungResponse>();
49 }
50
FailTest(const std::string & message)51 void FailTest(const std::string& message) {
52 ADD_FAILURE() << message;
53 }
54
FailRequestAndFailTest(const std::string & message,scoped_refptr<base::TaskRunner> main_task_runner,const test_server::HttpRequest & request)55 std::unique_ptr<test_server::HttpResponse> FailRequestAndFailTest(
56 const std::string& message,
57 scoped_refptr<base::TaskRunner> main_task_runner,
58 const test_server::HttpRequest& request) {
59 main_task_runner->PostTask(FROM_HERE, base::BindOnce(FailTest, message));
60 auto response = std::make_unique<test_server::BasicHttpResponse>();
61 response->set_code(HTTP_NOT_ACCEPTABLE);
62 return response;
63 }
64
VerifyOnWorkerThread(const scoped_refptr<CertVerifyProc> & verify_proc,scoped_refptr<X509Certificate> cert,const std::string & hostname,int flags,const CertificateList & additional_trust_anchors,CertVerifyResult * verify_result,NetLogSource * out_source)65 int VerifyOnWorkerThread(const scoped_refptr<CertVerifyProc>& verify_proc,
66 scoped_refptr<X509Certificate> cert,
67 const std::string& hostname,
68 int flags,
69 const CertificateList& additional_trust_anchors,
70 CertVerifyResult* verify_result,
71 NetLogSource* out_source) {
72 base::ScopedAllowBaseSyncPrimitivesForTesting scoped_allow_blocking;
73 scoped_refptr<CRLSet> crl_set = CRLSet::EmptyCRLSetForTesting();
74 NetLogWithSource net_log(NetLogWithSource::Make(
75 net::NetLog::Get(), net::NetLogSourceType::CERT_VERIFIER_TASK));
76 int error =
77 verify_proc->Verify(cert.get(), hostname,
78 /*ocsp_response=*/std::string(),
79 /*sct_list=*/std::string(), flags, crl_set.get(),
80 additional_trust_anchors, verify_result, net_log);
81 verify_result->DetachFromSequence();
82 *out_source = net_log.source();
83 return error;
84 }
85
86 } // namespace
87
88 class CertVerifyProcBuiltinTest : public ::testing::Test {
89 public:
90 // CertVerifyProcBuiltinTest() {}
91
SetUp()92 void SetUp() override {
93 cert_net_fetcher_ = base::MakeRefCounted<CertNetFetcherURLRequest>();
94 verify_proc_ = CreateCertVerifyProcBuiltin(
95 cert_net_fetcher_, std::make_unique<DummySystemTrustStoreProvider>());
96
97 context_ = std::make_unique<net::TestURLRequestContext>();
98
99 cert_net_fetcher_->SetURLRequestContext(context_.get());
100 }
101
TearDown()102 void TearDown() override { cert_net_fetcher_->Shutdown(); }
103
Verify(scoped_refptr<X509Certificate> cert,const std::string & hostname,int flags,const CertificateList & additional_trust_anchors,CertVerifyResult * verify_result,NetLogSource * out_source,CompletionOnceCallback callback)104 void Verify(scoped_refptr<X509Certificate> cert,
105 const std::string& hostname,
106 int flags,
107 const CertificateList& additional_trust_anchors,
108 CertVerifyResult* verify_result,
109 NetLogSource* out_source,
110 CompletionOnceCallback callback) {
111 verify_result->DetachFromSequence();
112 base::ThreadPool::PostTaskAndReplyWithResult(
113 FROM_HERE,
114 {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
115 base::BindOnce(&VerifyOnWorkerThread, verify_proc_, std::move(cert),
116 hostname, flags, additional_trust_anchors, verify_result,
117 out_source),
118 std::move(callback));
119 }
120
task_environment()121 base::test::TaskEnvironment& task_environment() { return task_environment_; }
122
CreateChain(std::unique_ptr<CertBuilder> * out_leaf,std::unique_ptr<CertBuilder> * out_intermediate,std::unique_ptr<CertBuilder> * out_root)123 void CreateChain(std::unique_ptr<CertBuilder>* out_leaf,
124 std::unique_ptr<CertBuilder>* out_intermediate,
125 std::unique_ptr<CertBuilder>* out_root) {
126 CertBuilder::CreateSimpleChain(out_leaf, out_intermediate, out_root);
127 ASSERT_TRUE(*out_leaf && *out_intermediate && *out_root);
128 // This test uses MOCK_TIME, so need to set the cert validity dates based
129 // on whatever the mock time happens to start at.
130 base::Time not_before = base::Time::Now() - base::TimeDelta::FromDays(1);
131 base::Time not_after = base::Time::Now() + base::TimeDelta::FromDays(10);
132 (*out_leaf)->SetValidity(not_before, not_after);
133 (*out_intermediate)->SetValidity(not_before, not_after);
134 (*out_root)->SetValidity(not_before, not_after);
135 }
136
137 private:
138 base::test::TaskEnvironment task_environment_{
139 base::test::TaskEnvironment::TimeSource::MOCK_TIME,
140 base::test::TaskEnvironment::MainThreadType::IO,
141 };
142
143 CertVerifier::Config config_;
144 std::unique_ptr<net::TestURLRequestContext> context_;
145 scoped_refptr<CertVerifyProc> verify_proc_;
146 scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher_;
147 };
148
TEST_F(CertVerifyProcBuiltinTest,SimpleSuccess)149 TEST_F(CertVerifyProcBuiltinTest, SimpleSuccess) {
150 std::unique_ptr<CertBuilder> leaf, intermediate, root;
151 CreateChain(&leaf, &intermediate, &root);
152 ASSERT_TRUE(leaf && intermediate && root);
153
154 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
155 ASSERT_TRUE(chain.get());
156
157 CertVerifyResult verify_result;
158 NetLogSource verify_net_log_source;
159 TestCompletionCallback callback;
160 Verify(chain.get(), "www.example.com", /*flags=*/0,
161 /*additional_trust_anchors=*/{root->GetX509Certificate()},
162 &verify_result, &verify_net_log_source, callback.callback());
163
164 int error = callback.WaitForResult();
165 EXPECT_THAT(error, IsOk());
166 }
167
168 // Tests that if the verification deadline is exceeded during revocation
169 // checking, additional CRL fetches will not be attempted.
TEST_F(CertVerifyProcBuiltinTest,RevocationCheckDeadlineCRL)170 TEST_F(CertVerifyProcBuiltinTest, RevocationCheckDeadlineCRL) {
171 std::unique_ptr<CertBuilder> leaf, intermediate, root;
172 CreateChain(&leaf, &intermediate, &root);
173 ASSERT_TRUE(leaf && intermediate && root);
174
175 const base::TimeDelta timeout_increment =
176 CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
177 base::TimeDelta::FromMilliseconds(1);
178 const int expected_request_count =
179 GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
180
181 EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
182 ASSERT_TRUE(test_server.InitializeAndListen());
183
184 // Set up the test cert to have enough crlDistributionPoint urls that if the
185 // first N-1 requests hang the deadline will be exceeded before the Nth
186 // request is made.
187 std::vector<GURL> crl_urls;
188 std::vector<base::RunLoop> runloops(expected_request_count);
189 for (int i = 0; i < expected_request_count; ++i) {
190 std::string path = base::StringPrintf("/hung/%i", i);
191 crl_urls.emplace_back(test_server.GetURL(path));
192 test_server.RegisterRequestHandler(
193 base::BindRepeating(&test_server::HandlePrefixedRequest, path,
194 base::BindRepeating(&HangRequestAndCallback,
195 runloops[i].QuitClosure())));
196 }
197 // Add CRL URLs and handlers that will add test failures if requested.
198 for (int i = expected_request_count; i < expected_request_count + 1; ++i) {
199 std::string path = base::StringPrintf("/failtest/%i", i);
200 crl_urls.emplace_back(test_server.GetURL(path));
201 test_server.RegisterRequestHandler(base::BindRepeating(
202 &test_server::HandlePrefixedRequest, path,
203 base::BindRepeating(FailRequestAndFailTest,
204 "additional request made after deadline exceeded",
205 base::SequencedTaskRunnerHandle::Get())));
206 }
207 leaf->SetCrlDistributionPointUrls(crl_urls);
208
209 test_server.StartAcceptingConnections();
210
211 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
212 ASSERT_TRUE(chain.get());
213
214 CertVerifyResult verify_result;
215 NetLogSource verify_net_log_source;
216 TestCompletionCallback verify_callback;
217 Verify(chain.get(), "www.example.com",
218 CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
219 /*additional_trust_anchors=*/{root->GetX509Certificate()},
220 &verify_result, &verify_net_log_source, verify_callback.callback());
221
222 for (int i = 0; i < expected_request_count; i++) {
223 // Wait for request #|i| to be made.
224 runloops[i].Run();
225 // Advance virtual time to cause the timeout task to become runnable.
226 task_environment().AdvanceClock(timeout_increment);
227 }
228
229 // Once |expected_request_count| requests have been made and timed out, the
230 // overall deadline should be reached, and no more requests should have been
231 // made. (If they were, the test will fail due to the ADD_FAILURE callback in
232 // the request handlers.)
233 int error = verify_callback.WaitForResult();
234 // Soft-fail revocation checking was used, therefore verification result
235 // should be OK even though none of the CRLs could be retrieved.
236 EXPECT_THAT(error, IsOk());
237 }
238
239 // Tests that if the verification deadline is exceeded during revocation
240 // checking, additional OCSP fetches will not be attempted.
TEST_F(CertVerifyProcBuiltinTest,RevocationCheckDeadlineOCSP)241 TEST_F(CertVerifyProcBuiltinTest, RevocationCheckDeadlineOCSP) {
242 std::unique_ptr<CertBuilder> leaf, intermediate, root;
243 CreateChain(&leaf, &intermediate, &root);
244 ASSERT_TRUE(leaf && intermediate && root);
245
246 const base::TimeDelta timeout_increment =
247 CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
248 base::TimeDelta::FromMilliseconds(1);
249 const int expected_request_count =
250 GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
251
252 EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
253 ASSERT_TRUE(test_server.InitializeAndListen());
254
255 // Set up the test cert to have enough OCSP urls that if the
256 // first N-1 requests hang the deadline will be exceeded before the Nth
257 // request is made.
258 std::vector<GURL> ocsp_urls;
259 std::vector<base::RunLoop> runloops(expected_request_count);
260 for (int i = 0; i < expected_request_count; ++i) {
261 std::string path = base::StringPrintf("/hung/%i", i);
262 ocsp_urls.emplace_back(test_server.GetURL(path));
263 test_server.RegisterRequestHandler(
264 base::BindRepeating(&test_server::HandlePrefixedRequest, path,
265 base::BindRepeating(&HangRequestAndCallback,
266 runloops[i].QuitClosure())));
267 }
268 // Add OCSP URLs and handlers that will add test failures if requested.
269 for (int i = expected_request_count; i < expected_request_count + 1; ++i) {
270 std::string path = base::StringPrintf("/failtest/%i", i);
271 ocsp_urls.emplace_back(test_server.GetURL(path));
272 test_server.RegisterRequestHandler(base::BindRepeating(
273 &test_server::HandlePrefixedRequest, path,
274 base::BindRepeating(FailRequestAndFailTest,
275 "additional request made after deadline exceeded",
276 base::SequencedTaskRunnerHandle::Get())));
277 }
278 leaf->SetCaIssuersAndOCSPUrls({}, ocsp_urls);
279
280 test_server.StartAcceptingConnections();
281
282 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
283 ASSERT_TRUE(chain.get());
284
285 CertVerifyResult verify_result;
286 NetLogSource verify_net_log_source;
287 TestCompletionCallback verify_callback;
288 Verify(chain.get(), "www.example.com",
289 CertVerifyProc::VERIFY_REV_CHECKING_ENABLED,
290 /*additional_trust_anchors=*/{root->GetX509Certificate()},
291 &verify_result, &verify_net_log_source, verify_callback.callback());
292
293 for (int i = 0; i < expected_request_count; i++) {
294 // Wait for request #|i| to be made.
295 runloops[i].Run();
296 // Advance virtual time to cause the timeout task to become runnable.
297 task_environment().AdvanceClock(timeout_increment);
298 }
299
300 // Once |expected_request_count| requests have been made and timed out, the
301 // overall deadline should be reached, and no more requests should have been
302 // made. (If they were, the test will fail due to the ADD_FAILURE callback in
303 // the request handlers.)
304 int error = verify_callback.WaitForResult();
305 // Soft-fail revocation checking was used, therefore verification result
306 // should be OK even though none of the OCSP responses could be retrieved.
307 EXPECT_THAT(error, IsOk());
308 }
309
310 #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
311 // Tests that if the verification deadline is exceeded during EV revocation
312 // checking, the certificate is verified as non-EV.
TEST_F(CertVerifyProcBuiltinTest,EVRevocationCheckDeadline)313 TEST_F(CertVerifyProcBuiltinTest, EVRevocationCheckDeadline) {
314 std::unique_ptr<CertBuilder> leaf, intermediate, root;
315 CreateChain(&leaf, &intermediate, &root);
316 ASSERT_TRUE(leaf && intermediate && root);
317
318 // Add test EV policy to leaf and intermediate.
319 static const char kEVTestCertPolicy[] = "1.2.3.4";
320 leaf->SetCertificatePolicies({kEVTestCertPolicy});
321 intermediate->SetCertificatePolicies({kEVTestCertPolicy});
322
323 const base::TimeDelta timeout_increment =
324 CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
325 base::TimeDelta::FromMilliseconds(1);
326 const int expected_request_count =
327 GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
328
329 EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
330 ASSERT_TRUE(test_server.InitializeAndListen());
331
332 // Set up the test intermediate to have enough OCSP urls that if all the
333 // requests hang the deadline will be exceeded.
334 std::vector<GURL> ocsp_urls;
335 std::vector<base::RunLoop> runloops(expected_request_count);
336 for (int i = 0; i < expected_request_count; ++i) {
337 std::string path = base::StringPrintf("/hung/%i", i);
338 ocsp_urls.emplace_back(test_server.GetURL(path));
339 test_server.RegisterRequestHandler(
340 base::BindRepeating(&test_server::HandlePrefixedRequest, path,
341 base::BindRepeating(&HangRequestAndCallback,
342 runloops[i].QuitClosure())));
343 }
344 intermediate->SetCaIssuersAndOCSPUrls({}, ocsp_urls);
345
346 test_server.StartAcceptingConnections();
347
348 // Consider the root of the test chain a valid EV root for the test policy.
349 ScopedTestEVPolicy scoped_test_ev_policy(
350 EVRootCAMetadata::GetInstance(),
351 X509Certificate::CalculateFingerprint256(root->GetCertBuffer()),
352 kEVTestCertPolicy);
353
354 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
355 ASSERT_TRUE(chain.get());
356
357 RecordingNetLogObserver net_log_observer(NetLogCaptureMode::kDefault);
358 CertVerifyResult verify_result;
359 NetLogSource verify_net_log_source;
360 TestCompletionCallback verify_callback;
361 Verify(chain.get(), "www.example.com",
362 /*flags=*/0,
363 /*additional_trust_anchors=*/{root->GetX509Certificate()},
364 &verify_result, &verify_net_log_source, verify_callback.callback());
365
366 for (int i = 0; i < expected_request_count; i++) {
367 // Wait for request #|i| to be made.
368 runloops[i].Run();
369 // Advance virtual time to cause the timeout task to become runnable.
370 task_environment().AdvanceClock(timeout_increment);
371 }
372
373 // Once |expected_request_count| requests have been made and timed out, the
374 // overall deadline should be reached, causing the EV verification attempt to
375 // fail.
376 int error = verify_callback.WaitForResult();
377 // EV uses soft-fail revocation checking, therefore verification result
378 // should be OK but not EV.
379 EXPECT_THAT(error, IsOk());
380 EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_IS_EV);
381 EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED);
382
383 auto events = net_log_observer.GetEntriesForSource(verify_net_log_source);
384
385 auto event = std::find_if(events.begin(), events.end(), [](const auto& e) {
386 return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT;
387 });
388 ASSERT_NE(event, events.end());
389 EXPECT_EQ(net::NetLogEventPhase::BEGIN, event->phase);
390 ASSERT_TRUE(event->params.is_dict());
391 EXPECT_EQ(true, event->params.FindBoolKey("is_ev_attempt"));
392
393 event = std::find_if(++event, events.end(), [](const auto& e) {
394 return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT;
395 });
396 ASSERT_NE(event, events.end());
397 EXPECT_EQ(net::NetLogEventPhase::NONE, event->phase);
398 ASSERT_TRUE(event->params.is_dict());
399 const std::string* errors = event->params.FindStringKey("errors");
400 ASSERT_TRUE(errors);
401 EXPECT_EQ("----- Certificate i=1 (CN=" +
402 intermediate->GetX509Certificate()->subject().common_name +
403 ") -----\nERROR: Unable to check revocation\n\n",
404 *errors);
405
406 event = std::find_if(++event, events.end(), [](const auto& e) {
407 return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT;
408 });
409 ASSERT_NE(event, events.end());
410 EXPECT_EQ(net::NetLogEventPhase::END, event->phase);
411 ASSERT_TRUE(event->params.is_dict());
412 EXPECT_EQ(false, event->params.FindBoolKey("has_valid_path"));
413
414 event = std::find_if(++event, events.end(), [](const auto& e) {
415 return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT;
416 });
417 ASSERT_NE(event, events.end());
418 EXPECT_EQ(net::NetLogEventPhase::BEGIN, event->phase);
419 ASSERT_TRUE(event->params.is_dict());
420 EXPECT_EQ(base::nullopt, event->params.FindBoolKey("is_ev_attempt"));
421
422 event = std::find_if(++event, events.end(), [](const auto& e) {
423 return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT;
424 });
425 ASSERT_NE(event, events.end());
426 EXPECT_EQ(net::NetLogEventPhase::NONE, event->phase);
427 ASSERT_TRUE(event->params.is_dict());
428 EXPECT_FALSE(event->params.FindStringKey("errors"));
429
430 event = std::find_if(++event, events.end(), [](const auto& e) {
431 return e.type == NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT;
432 });
433 ASSERT_NE(event, events.end());
434 EXPECT_EQ(net::NetLogEventPhase::END, event->phase);
435 ASSERT_TRUE(event->params.is_dict());
436 EXPECT_EQ(true, event->params.FindBoolKey("has_valid_path"));
437 }
438 #endif // defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
439
TEST_F(CertVerifyProcBuiltinTest,DebugData)440 TEST_F(CertVerifyProcBuiltinTest, DebugData) {
441 std::unique_ptr<CertBuilder> leaf, intermediate, root;
442 CreateChain(&leaf, &intermediate, &root);
443 ASSERT_TRUE(leaf && intermediate && root);
444
445 scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain();
446 ASSERT_TRUE(chain.get());
447
448 base::Time time = base::Time::Now();
449
450 CertVerifyResult verify_result;
451 NetLogSource verify_net_log_source;
452 TestCompletionCallback callback;
453 Verify(chain.get(), "www.example.com", /*flags=*/0,
454 /*additional_trust_anchors=*/{root->GetX509Certificate()},
455 &verify_result, &verify_net_log_source, callback.callback());
456
457 int error = callback.WaitForResult();
458 EXPECT_THAT(error, IsOk());
459
460 auto* debug_data = CertVerifyProcBuiltinResultDebugData::Get(&verify_result);
461 ASSERT_TRUE(debug_data);
462 // No delayed tasks involved, so the mock time should not have advanced.
463 EXPECT_EQ(time, debug_data->verification_time());
464
465 base::Time der_verification_time_converted_back_to_base_time;
466 EXPECT_TRUE(net::der::GeneralizedTimeToTime(
467 debug_data->der_verification_time(),
468 &der_verification_time_converted_back_to_base_time));
469 // GeneralizedTime only has seconds precision.
470 EXPECT_EQ(
471 0,
472 (time - der_verification_time_converted_back_to_base_time).InSeconds());
473 }
474
475 } // namespace net
476