Add include.
[chromium-blink-merge.git] / net / cert / multi_threaded_cert_verifier_unittest.cc
bloba3464e0496a59747c8123c48488e3f1f25fddd18
1 // Copyright (c) 2012 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.
5 #include "net/cert/multi_threaded_cert_verifier.h"
7 #include "base/bind.h"
8 #include "base/files/file_path.h"
9 #include "base/format_macros.h"
10 #include "base/strings/stringprintf.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/net_log.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/base/test_data_directory.h"
15 #include "net/cert/cert_trust_anchor_provider.h"
16 #include "net/cert/cert_verify_proc.h"
17 #include "net/cert/cert_verify_result.h"
18 #include "net/cert/x509_certificate.h"
19 #include "net/test/cert_test_util.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using testing::Mock;
24 using testing::ReturnRef;
26 namespace net {
28 namespace {
30 void FailTest(int /* result */) {
31 FAIL();
34 class MockCertVerifyProc : public CertVerifyProc {
35 public:
36 MockCertVerifyProc() {}
38 private:
39 ~MockCertVerifyProc() override {}
41 // CertVerifyProc implementation
42 bool SupportsAdditionalTrustAnchors() const override { return false; }
44 int VerifyInternal(X509Certificate* cert,
45 const std::string& hostname,
46 int flags,
47 CRLSet* crl_set,
48 const CertificateList& additional_trust_anchors,
49 CertVerifyResult* verify_result) override {
50 verify_result->Reset();
51 verify_result->verified_cert = cert;
52 verify_result->cert_status = CERT_STATUS_COMMON_NAME_INVALID;
53 return ERR_CERT_COMMON_NAME_INVALID;
57 class MockCertTrustAnchorProvider : public CertTrustAnchorProvider {
58 public:
59 MockCertTrustAnchorProvider() {}
60 virtual ~MockCertTrustAnchorProvider() {}
62 MOCK_METHOD0(GetAdditionalTrustAnchors, const CertificateList&());
65 } // namespace
67 class MultiThreadedCertVerifierTest : public ::testing::Test {
68 public:
69 MultiThreadedCertVerifierTest() : verifier_(new MockCertVerifyProc()) {}
70 ~MultiThreadedCertVerifierTest() override {}
72 protected:
73 MultiThreadedCertVerifier verifier_;
76 TEST_F(MultiThreadedCertVerifierTest, CacheHit) {
77 base::FilePath certs_dir = GetTestCertsDirectory();
78 scoped_refptr<X509Certificate> test_cert(
79 ImportCertFromFile(certs_dir, "ok_cert.pem"));
80 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
82 int error;
83 CertVerifyResult verify_result;
84 TestCompletionCallback callback;
85 CertVerifier::RequestHandle request_handle;
87 error = verifier_.Verify(test_cert.get(),
88 "www.example.com",
90 NULL,
91 &verify_result,
92 callback.callback(),
93 &request_handle,
94 BoundNetLog());
95 ASSERT_EQ(ERR_IO_PENDING, error);
96 EXPECT_TRUE(request_handle);
97 error = callback.WaitForResult();
98 ASSERT_TRUE(IsCertificateError(error));
99 ASSERT_EQ(1u, verifier_.requests());
100 ASSERT_EQ(0u, verifier_.cache_hits());
101 ASSERT_EQ(0u, verifier_.inflight_joins());
102 ASSERT_EQ(1u, verifier_.GetCacheSize());
104 error = verifier_.Verify(test_cert.get(),
105 "www.example.com",
107 NULL,
108 &verify_result,
109 callback.callback(),
110 &request_handle,
111 BoundNetLog());
112 // Synchronous completion.
113 ASSERT_NE(ERR_IO_PENDING, error);
114 ASSERT_TRUE(IsCertificateError(error));
115 ASSERT_TRUE(request_handle == NULL);
116 ASSERT_EQ(2u, verifier_.requests());
117 ASSERT_EQ(1u, verifier_.cache_hits());
118 ASSERT_EQ(0u, verifier_.inflight_joins());
119 ASSERT_EQ(1u, verifier_.GetCacheSize());
122 // Tests the same server certificate with different intermediate CA
123 // certificates. These should be treated as different certificate chains even
124 // though the two X509Certificate objects contain the same server certificate.
125 TEST_F(MultiThreadedCertVerifierTest, DifferentCACerts) {
126 base::FilePath certs_dir = GetTestCertsDirectory();
128 scoped_refptr<X509Certificate> server_cert =
129 ImportCertFromFile(certs_dir, "salesforce_com_test.pem");
130 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get());
132 scoped_refptr<X509Certificate> intermediate_cert1 =
133 ImportCertFromFile(certs_dir, "verisign_intermediate_ca_2011.pem");
134 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert1.get());
136 scoped_refptr<X509Certificate> intermediate_cert2 =
137 ImportCertFromFile(certs_dir, "verisign_intermediate_ca_2016.pem");
138 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert2.get());
140 X509Certificate::OSCertHandles intermediates;
141 intermediates.push_back(intermediate_cert1->os_cert_handle());
142 scoped_refptr<X509Certificate> cert_chain1 =
143 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
144 intermediates);
146 intermediates.clear();
147 intermediates.push_back(intermediate_cert2->os_cert_handle());
148 scoped_refptr<X509Certificate> cert_chain2 =
149 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(),
150 intermediates);
152 int error;
153 CertVerifyResult verify_result;
154 TestCompletionCallback callback;
155 CertVerifier::RequestHandle request_handle;
157 error = verifier_.Verify(cert_chain1.get(),
158 "www.example.com",
160 NULL,
161 &verify_result,
162 callback.callback(),
163 &request_handle,
164 BoundNetLog());
165 ASSERT_EQ(ERR_IO_PENDING, error);
166 EXPECT_TRUE(request_handle);
167 error = callback.WaitForResult();
168 ASSERT_TRUE(IsCertificateError(error));
169 ASSERT_EQ(1u, verifier_.requests());
170 ASSERT_EQ(0u, verifier_.cache_hits());
171 ASSERT_EQ(0u, verifier_.inflight_joins());
172 ASSERT_EQ(1u, verifier_.GetCacheSize());
174 error = verifier_.Verify(cert_chain2.get(),
175 "www.example.com",
177 NULL,
178 &verify_result,
179 callback.callback(),
180 &request_handle,
181 BoundNetLog());
182 ASSERT_EQ(ERR_IO_PENDING, error);
183 EXPECT_TRUE(request_handle);
184 error = callback.WaitForResult();
185 ASSERT_TRUE(IsCertificateError(error));
186 ASSERT_EQ(2u, verifier_.requests());
187 ASSERT_EQ(0u, verifier_.cache_hits());
188 ASSERT_EQ(0u, verifier_.inflight_joins());
189 ASSERT_EQ(2u, verifier_.GetCacheSize());
192 // Tests an inflight join.
193 TEST_F(MultiThreadedCertVerifierTest, InflightJoin) {
194 base::FilePath certs_dir = GetTestCertsDirectory();
195 scoped_refptr<X509Certificate> test_cert(
196 ImportCertFromFile(certs_dir, "ok_cert.pem"));
197 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
199 int error;
200 CertVerifyResult verify_result;
201 TestCompletionCallback callback;
202 CertVerifier::RequestHandle request_handle;
203 CertVerifyResult verify_result2;
204 TestCompletionCallback callback2;
205 CertVerifier::RequestHandle request_handle2;
207 error = verifier_.Verify(test_cert.get(),
208 "www.example.com",
210 NULL,
211 &verify_result,
212 callback.callback(),
213 &request_handle,
214 BoundNetLog());
215 ASSERT_EQ(ERR_IO_PENDING, error);
216 EXPECT_TRUE(request_handle);
217 error = verifier_.Verify(test_cert.get(),
218 "www.example.com",
220 NULL,
221 &verify_result2,
222 callback2.callback(),
223 &request_handle2,
224 BoundNetLog());
225 EXPECT_EQ(ERR_IO_PENDING, error);
226 EXPECT_TRUE(request_handle2 != NULL);
227 error = callback.WaitForResult();
228 EXPECT_TRUE(IsCertificateError(error));
229 error = callback2.WaitForResult();
230 ASSERT_TRUE(IsCertificateError(error));
231 ASSERT_EQ(2u, verifier_.requests());
232 ASSERT_EQ(0u, verifier_.cache_hits());
233 ASSERT_EQ(1u, verifier_.inflight_joins());
236 // Tests that the callback of a canceled request is never made.
237 TEST_F(MultiThreadedCertVerifierTest, CancelRequest) {
238 base::FilePath certs_dir = GetTestCertsDirectory();
239 scoped_refptr<X509Certificate> test_cert(
240 ImportCertFromFile(certs_dir, "ok_cert.pem"));
241 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
243 int error;
244 CertVerifyResult verify_result;
245 CertVerifier::RequestHandle request_handle;
247 error = verifier_.Verify(test_cert.get(),
248 "www.example.com",
250 NULL,
251 &verify_result,
252 base::Bind(&FailTest),
253 &request_handle,
254 BoundNetLog());
255 ASSERT_EQ(ERR_IO_PENDING, error);
256 ASSERT_TRUE(request_handle != NULL);
257 verifier_.CancelRequest(request_handle);
259 // Issue a few more requests to the worker pool and wait for their
260 // completion, so that the task of the canceled request (which runs on a
261 // worker thread) is likely to complete by the end of this test.
262 TestCompletionCallback callback;
263 for (int i = 0; i < 5; ++i) {
264 error = verifier_.Verify(test_cert.get(),
265 "www2.example.com",
267 NULL,
268 &verify_result,
269 callback.callback(),
270 &request_handle,
271 BoundNetLog());
272 ASSERT_EQ(ERR_IO_PENDING, error);
273 EXPECT_TRUE(request_handle);
274 error = callback.WaitForResult();
275 verifier_.ClearCache();
279 // Tests that a canceled request is not leaked.
280 #if !defined(LEAK_SANITIZER)
281 #define MAYBE_CancelRequestThenQuit CancelRequestThenQuit
282 #else
283 // See PR303886. LeakSanitizer flags a leak here.
284 #define MAYBE_CancelRequestThenQuit DISABLED_CancelRequestThenQuit
285 #endif
286 TEST_F(MultiThreadedCertVerifierTest, MAYBE_CancelRequestThenQuit) {
287 base::FilePath certs_dir = GetTestCertsDirectory();
288 scoped_refptr<X509Certificate> test_cert(
289 ImportCertFromFile(certs_dir, "ok_cert.pem"));
290 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get());
292 int error;
293 CertVerifyResult verify_result;
294 TestCompletionCallback callback;
295 CertVerifier::RequestHandle request_handle;
297 error = verifier_.Verify(test_cert.get(),
298 "www.example.com",
300 NULL,
301 &verify_result,
302 callback.callback(),
303 &request_handle,
304 BoundNetLog());
305 ASSERT_EQ(ERR_IO_PENDING, error);
306 EXPECT_TRUE(request_handle);
307 verifier_.CancelRequest(request_handle);
308 // Destroy |verifier| by going out of scope.
311 TEST_F(MultiThreadedCertVerifierTest, RequestParamsComparators) {
312 SHA1HashValue a_key;
313 memset(a_key.data, 'a', sizeof(a_key.data));
315 SHA1HashValue z_key;
316 memset(z_key.data, 'z', sizeof(z_key.data));
318 const CertificateList empty_list;
319 CertificateList test_list;
320 test_list.push_back(
321 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"));
323 struct {
324 // Keys to test
325 MultiThreadedCertVerifier::RequestParams key1;
326 MultiThreadedCertVerifier::RequestParams key2;
328 // Expectation:
329 // -1 means key1 is less than key2
330 // 0 means key1 equals key2
331 // 1 means key1 is greater than key2
332 int expected_result;
333 } tests[] = {
334 { // Test for basic equivalence.
335 MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
336 0, test_list),
337 MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
338 0, test_list),
341 { // Test that different certificates but with the same CA and for
342 // the same host are different validation keys.
343 MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
344 0, test_list),
345 MultiThreadedCertVerifier::RequestParams(z_key, a_key, "www.example.test",
346 0, test_list),
349 { // Test that the same EE certificate for the same host, but with
350 // different chains are different validation keys.
351 MultiThreadedCertVerifier::RequestParams(a_key, z_key, "www.example.test",
352 0, test_list),
353 MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
354 0, test_list),
357 { // The same certificate, with the same chain, but for different
358 // hosts are different validation keys.
359 MultiThreadedCertVerifier::RequestParams(a_key, a_key,
360 "www1.example.test", 0,
361 test_list),
362 MultiThreadedCertVerifier::RequestParams(a_key, a_key,
363 "www2.example.test", 0,
364 test_list),
367 { // The same certificate, chain, and host, but with different flags
368 // are different validation keys.
369 MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
370 CertVerifier::VERIFY_EV_CERT,
371 test_list),
372 MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
373 0, test_list),
376 { // Different additional_trust_anchors.
377 MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
378 0, empty_list),
379 MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test",
380 0, test_list),
384 for (size_t i = 0; i < arraysize(tests); ++i) {
385 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
387 const MultiThreadedCertVerifier::RequestParams& key1 = tests[i].key1;
388 const MultiThreadedCertVerifier::RequestParams& key2 = tests[i].key2;
390 switch (tests[i].expected_result) {
391 case -1:
392 EXPECT_TRUE(key1 < key2);
393 EXPECT_FALSE(key2 < key1);
394 break;
395 case 0:
396 EXPECT_FALSE(key1 < key2);
397 EXPECT_FALSE(key2 < key1);
398 break;
399 case 1:
400 EXPECT_FALSE(key1 < key2);
401 EXPECT_TRUE(key2 < key1);
402 break;
403 default:
404 FAIL() << "Invalid expectation. Can be only -1, 0, 1";
409 TEST_F(MultiThreadedCertVerifierTest, CertTrustAnchorProvider) {
410 MockCertTrustAnchorProvider trust_provider;
411 verifier_.SetCertTrustAnchorProvider(&trust_provider);
413 scoped_refptr<X509Certificate> test_cert(
414 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"));
415 ASSERT_TRUE(test_cert.get());
417 const CertificateList empty_cert_list;
418 CertificateList cert_list;
419 cert_list.push_back(test_cert);
421 // Check that Verify() asks the |trust_provider| for the current list of
422 // additional trust anchors.
423 int error;
424 CertVerifyResult verify_result;
425 TestCompletionCallback callback;
426 CertVerifier::RequestHandle request_handle;
427 EXPECT_CALL(trust_provider, GetAdditionalTrustAnchors())
428 .WillOnce(ReturnRef(empty_cert_list));
429 error = verifier_.Verify(test_cert.get(),
430 "www.example.com",
432 NULL,
433 &verify_result,
434 callback.callback(),
435 &request_handle,
436 BoundNetLog());
437 Mock::VerifyAndClearExpectations(&trust_provider);
438 ASSERT_EQ(ERR_IO_PENDING, error);
439 EXPECT_TRUE(request_handle);
440 error = callback.WaitForResult();
441 EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error);
442 ASSERT_EQ(1u, verifier_.requests());
443 ASSERT_EQ(0u, verifier_.cache_hits());
445 // The next Verify() uses the cached result.
446 EXPECT_CALL(trust_provider, GetAdditionalTrustAnchors())
447 .WillOnce(ReturnRef(empty_cert_list));
448 error = verifier_.Verify(test_cert.get(),
449 "www.example.com",
451 NULL,
452 &verify_result,
453 callback.callback(),
454 &request_handle,
455 BoundNetLog());
456 Mock::VerifyAndClearExpectations(&trust_provider);
457 EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error);
458 EXPECT_FALSE(request_handle);
459 ASSERT_EQ(2u, verifier_.requests());
460 ASSERT_EQ(1u, verifier_.cache_hits());
462 // Another Verify() for the same certificate but with a different list of
463 // trust anchors will not reuse the cache.
464 EXPECT_CALL(trust_provider, GetAdditionalTrustAnchors())
465 .WillOnce(ReturnRef(cert_list));
466 error = verifier_.Verify(test_cert.get(),
467 "www.example.com",
469 NULL,
470 &verify_result,
471 callback.callback(),
472 &request_handle,
473 BoundNetLog());
474 Mock::VerifyAndClearExpectations(&trust_provider);
475 ASSERT_EQ(ERR_IO_PENDING, error);
476 EXPECT_TRUE(request_handle);
477 error = callback.WaitForResult();
478 EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error);
479 ASSERT_EQ(3u, verifier_.requests());
480 ASSERT_EQ(1u, verifier_.cache_hits());
483 } // namespace net