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/ssl/server_bound_cert_service.h"
10 #include "base/bind.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "crypto/ec_private_key.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/test_completion_callback.h"
17 #include "net/cert/asn1_util.h"
18 #include "net/cert/x509_certificate.h"
19 #include "net/ssl/default_server_bound_cert_store.h"
20 #include "testing/gtest/include/gtest/gtest.h"
26 void FailTest(int /* result */) {
30 class ServerBoundCertServiceTest
: public testing::Test
{
32 ServerBoundCertServiceTest()
33 : sequenced_worker_pool_(new base::SequencedWorkerPool(
34 3, "ServerBoundCertServiceTest")),
35 service_(new ServerBoundCertService(
36 new DefaultServerBoundCertStore(NULL
),
37 sequenced_worker_pool_
)) {
40 virtual ~ServerBoundCertServiceTest() {
41 if (sequenced_worker_pool_
.get())
42 sequenced_worker_pool_
->Shutdown();
46 scoped_refptr
<base::SequencedWorkerPool
> sequenced_worker_pool_
;
47 scoped_ptr
<ServerBoundCertService
> service_
;
50 TEST_F(ServerBoundCertServiceTest
, GetDomainForHost
) {
51 EXPECT_EQ("google.com",
52 ServerBoundCertService::GetDomainForHost("google.com"));
53 EXPECT_EQ("google.com",
54 ServerBoundCertService::GetDomainForHost("www.google.com"));
55 EXPECT_EQ("foo.appspot.com",
56 ServerBoundCertService::GetDomainForHost("foo.appspot.com"));
57 EXPECT_EQ("bar.appspot.com",
58 ServerBoundCertService::GetDomainForHost("foo.bar.appspot.com"));
59 EXPECT_EQ("appspot.com",
60 ServerBoundCertService::GetDomainForHost("appspot.com"));
61 EXPECT_EQ("google.com",
62 ServerBoundCertService::GetDomainForHost("www.mail.google.com"));
64 ServerBoundCertService::GetDomainForHost("goto"));
65 EXPECT_EQ("127.0.0.1",
66 ServerBoundCertService::GetDomainForHost("127.0.0.1"));
69 // See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned.
70 #if !defined(USE_OPENSSL)
72 TEST_F(ServerBoundCertServiceTest
, CacheHit
) {
73 std::string
host("encrypted.google.com");
76 std::vector
<uint8
> types
;
77 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
78 TestCompletionCallback callback
;
79 ServerBoundCertService::RequestHandle request_handle
;
81 // Asynchronous completion.
82 SSLClientCertType type1
;
83 std::string private_key_info1
, der_cert1
;
84 EXPECT_EQ(0, service_
->cert_count());
85 error
= service_
->GetDomainBoundCert(
86 host
, types
, &type1
, &private_key_info1
, &der_cert1
,
87 callback
.callback(), &request_handle
);
88 EXPECT_EQ(ERR_IO_PENDING
, error
);
89 EXPECT_TRUE(request_handle
.is_active());
90 error
= callback
.WaitForResult();
92 EXPECT_EQ(1, service_
->cert_count());
93 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
94 EXPECT_FALSE(private_key_info1
.empty());
95 EXPECT_FALSE(der_cert1
.empty());
96 EXPECT_FALSE(request_handle
.is_active());
98 // Synchronous completion.
99 SSLClientCertType type2
;
100 std::string private_key_info2
, der_cert2
;
101 error
= service_
->GetDomainBoundCert(
102 host
, types
, &type2
, &private_key_info2
, &der_cert2
,
103 callback
.callback(), &request_handle
);
104 EXPECT_FALSE(request_handle
.is_active());
105 EXPECT_EQ(OK
, error
);
106 EXPECT_EQ(1, service_
->cert_count());
107 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
108 EXPECT_EQ(private_key_info1
, private_key_info2
);
109 EXPECT_EQ(der_cert1
, der_cert2
);
111 EXPECT_EQ(2u, service_
->requests());
112 EXPECT_EQ(1u, service_
->cert_store_hits());
113 EXPECT_EQ(0u, service_
->inflight_joins());
116 TEST_F(ServerBoundCertServiceTest
, UnsupportedTypes
) {
117 std::string
host("encrypted.google.com");
120 std::vector
<uint8
> types
;
121 TestCompletionCallback callback
;
122 ServerBoundCertService::RequestHandle request_handle
;
124 // Empty requested_types.
125 SSLClientCertType type1
;
126 std::string private_key_info1
, der_cert1
;
127 error
= service_
->GetDomainBoundCert(
128 host
, types
, &type1
, &private_key_info1
, &der_cert1
,
129 callback
.callback(), &request_handle
);
130 EXPECT_EQ(ERR_INVALID_ARGUMENT
, error
);
131 EXPECT_FALSE(request_handle
.is_active());
133 // No supported types in requested_types.
134 types
.push_back(CLIENT_CERT_RSA_SIGN
);
137 error
= service_
->GetDomainBoundCert(
138 host
, types
, &type1
, &private_key_info1
, &der_cert1
,
139 callback
.callback(), &request_handle
);
140 EXPECT_EQ(ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED
, error
);
141 EXPECT_FALSE(request_handle
.is_active());
143 // Supported types after unsupported ones in requested_types.
144 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
145 // Asynchronous completion.
146 EXPECT_EQ(0, service_
->cert_count());
147 error
= service_
->GetDomainBoundCert(
148 host
, types
, &type1
, &private_key_info1
, &der_cert1
,
149 callback
.callback(), &request_handle
);
150 EXPECT_EQ(ERR_IO_PENDING
, error
);
151 EXPECT_TRUE(request_handle
.is_active());
152 error
= callback
.WaitForResult();
153 EXPECT_EQ(OK
, error
);
154 EXPECT_EQ(1, service_
->cert_count());
155 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
156 EXPECT_FALSE(private_key_info1
.empty());
157 EXPECT_FALSE(der_cert1
.empty());
159 // Now that the cert is created, doing requests for unsupported types
160 // shouldn't affect the created cert.
161 // Empty requested_types.
163 SSLClientCertType type2
;
164 std::string private_key_info2
, der_cert2
;
165 error
= service_
->GetDomainBoundCert(
166 host
, types
, &type2
, &private_key_info2
, &der_cert2
,
167 callback
.callback(), &request_handle
);
168 EXPECT_EQ(ERR_INVALID_ARGUMENT
, error
);
169 EXPECT_FALSE(request_handle
.is_active());
171 // No supported types in requested_types.
172 types
.push_back(CLIENT_CERT_RSA_SIGN
);
175 error
= service_
->GetDomainBoundCert(
176 host
, types
, &type2
, &private_key_info2
, &der_cert2
,
177 callback
.callback(), &request_handle
);
178 EXPECT_EQ(ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED
, error
);
179 EXPECT_FALSE(request_handle
.is_active());
181 // If we request EC, the cert we created before should still be there.
182 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
183 error
= service_
->GetDomainBoundCert(
184 host
, types
, &type2
, &private_key_info2
, &der_cert2
,
185 callback
.callback(), &request_handle
);
186 EXPECT_FALSE(request_handle
.is_active());
187 EXPECT_EQ(OK
, error
);
188 EXPECT_EQ(1, service_
->cert_count());
189 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
190 EXPECT_EQ(private_key_info1
, private_key_info2
);
191 EXPECT_EQ(der_cert1
, der_cert2
);
194 TEST_F(ServerBoundCertServiceTest
, StoreCerts
) {
196 std::vector
<uint8
> types
;
197 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
198 TestCompletionCallback callback
;
199 ServerBoundCertService::RequestHandle request_handle
;
201 std::string
host1("encrypted.google.com");
202 SSLClientCertType type1
;
203 std::string private_key_info1
, der_cert1
;
204 EXPECT_EQ(0, service_
->cert_count());
205 error
= service_
->GetDomainBoundCert(
206 host1
, types
, &type1
, &private_key_info1
, &der_cert1
,
207 callback
.callback(), &request_handle
);
208 EXPECT_EQ(ERR_IO_PENDING
, error
);
209 EXPECT_TRUE(request_handle
.is_active());
210 error
= callback
.WaitForResult();
211 EXPECT_EQ(OK
, error
);
212 EXPECT_EQ(1, service_
->cert_count());
214 std::string
host2("www.verisign.com");
215 SSLClientCertType type2
;
216 std::string private_key_info2
, der_cert2
;
217 error
= service_
->GetDomainBoundCert(
218 host2
, types
, &type2
, &private_key_info2
, &der_cert2
,
219 callback
.callback(), &request_handle
);
220 EXPECT_EQ(ERR_IO_PENDING
, error
);
221 EXPECT_TRUE(request_handle
.is_active());
222 error
= callback
.WaitForResult();
223 EXPECT_EQ(OK
, error
);
224 EXPECT_EQ(2, service_
->cert_count());
226 std::string
host3("www.twitter.com");
227 SSLClientCertType type3
;
228 std::string private_key_info3
, der_cert3
;
229 error
= service_
->GetDomainBoundCert(
230 host3
, types
, &type3
, &private_key_info3
, &der_cert3
,
231 callback
.callback(), &request_handle
);
232 EXPECT_EQ(ERR_IO_PENDING
, error
);
233 EXPECT_TRUE(request_handle
.is_active());
234 error
= callback
.WaitForResult();
235 EXPECT_EQ(OK
, error
);
236 EXPECT_EQ(3, service_
->cert_count());
238 EXPECT_NE(private_key_info1
, private_key_info2
);
239 EXPECT_NE(der_cert1
, der_cert2
);
240 EXPECT_NE(private_key_info1
, private_key_info3
);
241 EXPECT_NE(der_cert1
, der_cert3
);
242 EXPECT_NE(private_key_info2
, private_key_info3
);
243 EXPECT_NE(der_cert2
, der_cert3
);
244 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
245 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
246 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type3
);
249 // Tests an inflight join.
250 TEST_F(ServerBoundCertServiceTest
, InflightJoin
) {
251 std::string
host("encrypted.google.com");
253 std::vector
<uint8
> types
;
254 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
256 SSLClientCertType type1
;
257 std::string private_key_info1
, der_cert1
;
258 TestCompletionCallback callback1
;
259 ServerBoundCertService::RequestHandle request_handle1
;
261 SSLClientCertType type2
;
262 std::string private_key_info2
, der_cert2
;
263 TestCompletionCallback callback2
;
264 ServerBoundCertService::RequestHandle request_handle2
;
266 error
= service_
->GetDomainBoundCert(
267 host
, types
, &type1
, &private_key_info1
, &der_cert1
,
268 callback1
.callback(), &request_handle1
);
269 EXPECT_EQ(ERR_IO_PENDING
, error
);
270 EXPECT_TRUE(request_handle1
.is_active());
271 // If we request RSA and EC in the 2nd request, should still join with the
273 types
.insert(types
.begin(), CLIENT_CERT_RSA_SIGN
);
274 error
= service_
->GetDomainBoundCert(
275 host
, types
, &type2
, &private_key_info2
, &der_cert2
,
276 callback2
.callback(), &request_handle2
);
277 EXPECT_EQ(ERR_IO_PENDING
, error
);
278 EXPECT_TRUE(request_handle2
.is_active());
280 error
= callback1
.WaitForResult();
281 EXPECT_EQ(OK
, error
);
282 error
= callback2
.WaitForResult();
283 EXPECT_EQ(OK
, error
);
285 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
286 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
287 EXPECT_EQ(2u, service_
->requests());
288 EXPECT_EQ(0u, service_
->cert_store_hits());
289 EXPECT_EQ(1u, service_
->inflight_joins());
292 TEST_F(ServerBoundCertServiceTest
, ExtractValuesFromBytesEC
) {
293 std::string
host("encrypted.google.com");
294 SSLClientCertType type
;
295 std::string private_key_info
, der_cert
;
297 std::vector
<uint8
> types
;
298 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
299 TestCompletionCallback callback
;
300 ServerBoundCertService::RequestHandle request_handle
;
302 error
= service_
->GetDomainBoundCert(
303 host
, types
, &type
, &private_key_info
, &der_cert
, callback
.callback(),
305 EXPECT_EQ(ERR_IO_PENDING
, error
);
306 EXPECT_TRUE(request_handle
.is_active());
307 error
= callback
.WaitForResult();
308 EXPECT_EQ(OK
, error
);
310 base::StringPiece spki_piece
;
311 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_cert
, &spki_piece
));
312 std::vector
<uint8
> spki(
314 spki_piece
.data() + spki_piece
.size());
316 // Check that we can retrieve the key from the bytes.
317 std::vector
<uint8
> key_vec(private_key_info
.begin(), private_key_info
.end());
318 scoped_ptr
<crypto::ECPrivateKey
> private_key(
319 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
320 ServerBoundCertService::kEPKIPassword
, key_vec
, spki
));
321 EXPECT_TRUE(private_key
!= NULL
);
323 // Check that we can retrieve the cert from the bytes.
324 scoped_refptr
<X509Certificate
> x509cert(
325 X509Certificate::CreateFromBytes(der_cert
.data(), der_cert
.size()));
326 EXPECT_TRUE(x509cert
.get() != NULL
);
329 // Tests that the callback of a canceled request is never made.
330 TEST_F(ServerBoundCertServiceTest
, CancelRequest
) {
331 std::string
host("encrypted.google.com");
332 SSLClientCertType type
;
333 std::string private_key_info
, der_cert
;
335 std::vector
<uint8
> types
;
336 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
337 ServerBoundCertService::RequestHandle request_handle
;
339 error
= service_
->GetDomainBoundCert(host
,
344 base::Bind(&FailTest
),
346 EXPECT_EQ(ERR_IO_PENDING
, error
);
347 EXPECT_TRUE(request_handle
.is_active());
348 request_handle
.Cancel();
349 EXPECT_FALSE(request_handle
.is_active());
351 // Wait for generation to finish.
352 sequenced_worker_pool_
->FlushForTesting();
353 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
354 // ServerBoundCertService.
355 base::MessageLoop::current()->RunUntilIdle();
357 // Even though the original request was cancelled, the service will still
358 // store the result, it just doesn't call the callback.
359 EXPECT_EQ(1, service_
->cert_count());
362 // Tests that destructing the RequestHandle cancels the request.
363 TEST_F(ServerBoundCertServiceTest
, CancelRequestByHandleDestruction
) {
364 std::string
host("encrypted.google.com");
365 SSLClientCertType type
;
366 std::string private_key_info
, der_cert
;
368 std::vector
<uint8
> types
;
369 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
371 ServerBoundCertService::RequestHandle request_handle
;
373 error
= service_
->GetDomainBoundCert(host
,
378 base::Bind(&FailTest
),
380 EXPECT_EQ(ERR_IO_PENDING
, error
);
381 EXPECT_TRUE(request_handle
.is_active());
384 // Wait for generation to finish.
385 sequenced_worker_pool_
->FlushForTesting();
386 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
387 // ServerBoundCertService.
388 base::MessageLoop::current()->RunUntilIdle();
390 // Even though the original request was cancelled, the service will still
391 // store the result, it just doesn't call the callback.
392 EXPECT_EQ(1, service_
->cert_count());
395 TEST_F(ServerBoundCertServiceTest
, DestructionWithPendingRequest
) {
396 std::string
host("encrypted.google.com");
397 SSLClientCertType type
;
398 std::string private_key_info
, der_cert
;
400 std::vector
<uint8
> types
;
401 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
402 ServerBoundCertService::RequestHandle request_handle
;
404 error
= service_
->GetDomainBoundCert(host
,
409 base::Bind(&FailTest
),
411 EXPECT_EQ(ERR_IO_PENDING
, error
);
412 EXPECT_TRUE(request_handle
.is_active());
414 // Cancel request and destroy the ServerBoundCertService.
415 request_handle
.Cancel();
418 // Wait for generation to finish.
419 sequenced_worker_pool_
->FlushForTesting();
420 // ServerBoundCertServiceWorker should not post anything back to the
421 // non-existant ServerBoundCertService, but run the loop just to be sure it
423 base::MessageLoop::current()->RunUntilIdle();
425 // If we got here without crashing or a valgrind error, it worked.
428 // Tests that shutting down the sequenced worker pool and then making new
429 // requests gracefully fails.
430 // This is a regression test for http://crbug.com/236387
431 TEST_F(ServerBoundCertServiceTest
, RequestAfterPoolShutdown
) {
432 // Shutdown the pool immediately.
433 sequenced_worker_pool_
->Shutdown();
434 sequenced_worker_pool_
= NULL
;
436 // Ensure any shutdown code is processed.
437 base::MessageLoop::current()->RunUntilIdle();
439 // Make a request that will force synchronous completion.
440 std::string
host("encrypted.google.com");
441 SSLClientCertType type
;
442 std::string private_key_info
, der_cert
;
444 std::vector
<uint8
> types
;
445 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
446 ServerBoundCertService::RequestHandle request_handle
;
448 error
= service_
->GetDomainBoundCert(host
,
453 base::Bind(&FailTest
),
455 // If we got here without crashing or a valgrind error, it worked.
456 ASSERT_EQ(ERR_INSUFFICIENT_RESOURCES
, error
);
457 EXPECT_FALSE(request_handle
.is_active());
460 // Tests that simultaneous creation of different certs works.
461 TEST_F(ServerBoundCertServiceTest
, SimultaneousCreation
) {
463 std::vector
<uint8
> types
;
464 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
466 std::string
host1("encrypted.google.com");
467 SSLClientCertType type1
;
468 std::string private_key_info1
, der_cert1
;
469 TestCompletionCallback callback1
;
470 ServerBoundCertService::RequestHandle request_handle1
;
472 std::string
host2("foo.com");
473 SSLClientCertType type2
;
474 std::string private_key_info2
, der_cert2
;
475 TestCompletionCallback callback2
;
476 ServerBoundCertService::RequestHandle request_handle2
;
478 std::string
host3("bar.com");
479 SSLClientCertType type3
;
480 std::string private_key_info3
, der_cert3
;
481 TestCompletionCallback callback3
;
482 ServerBoundCertService::RequestHandle request_handle3
;
484 error
= service_
->GetDomainBoundCert(host1
,
489 callback1
.callback(),
491 EXPECT_EQ(ERR_IO_PENDING
, error
);
492 EXPECT_TRUE(request_handle1
.is_active());
494 error
= service_
->GetDomainBoundCert(host2
,
499 callback2
.callback(),
501 EXPECT_EQ(ERR_IO_PENDING
, error
);
502 EXPECT_TRUE(request_handle2
.is_active());
504 error
= service_
->GetDomainBoundCert(host3
,
509 callback3
.callback(),
511 EXPECT_EQ(ERR_IO_PENDING
, error
);
512 EXPECT_TRUE(request_handle3
.is_active());
514 error
= callback1
.WaitForResult();
515 EXPECT_EQ(OK
, error
);
516 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
517 EXPECT_FALSE(private_key_info1
.empty());
518 EXPECT_FALSE(der_cert1
.empty());
520 error
= callback2
.WaitForResult();
521 EXPECT_EQ(OK
, error
);
522 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
523 EXPECT_FALSE(private_key_info2
.empty());
524 EXPECT_FALSE(der_cert2
.empty());
526 error
= callback3
.WaitForResult();
527 EXPECT_EQ(OK
, error
);
528 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type3
);
529 EXPECT_FALSE(private_key_info3
.empty());
530 EXPECT_FALSE(der_cert3
.empty());
532 EXPECT_NE(private_key_info1
, private_key_info2
);
533 EXPECT_NE(der_cert1
, der_cert2
);
535 EXPECT_NE(private_key_info1
, private_key_info3
);
536 EXPECT_NE(der_cert1
, der_cert3
);
538 EXPECT_NE(private_key_info2
, private_key_info3
);
539 EXPECT_NE(der_cert2
, der_cert3
);
541 EXPECT_EQ(3, service_
->cert_count());
544 TEST_F(ServerBoundCertServiceTest
, Expiration
) {
545 ServerBoundCertStore
* store
= service_
->GetCertStore();
546 base::Time now
= base::Time::Now();
547 store
->SetServerBoundCert("good",
548 CLIENT_CERT_ECDSA_SIGN
,
550 now
+ base::TimeDelta::FromDays(1),
553 store
->SetServerBoundCert("expired",
554 CLIENT_CERT_ECDSA_SIGN
,
555 now
- base::TimeDelta::FromDays(2),
556 now
- base::TimeDelta::FromDays(1),
559 EXPECT_EQ(2, service_
->cert_count());
562 std::vector
<uint8
> types
;
563 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
564 TestCompletionCallback callback
;
565 ServerBoundCertService::RequestHandle request_handle
;
567 // Cert is valid - synchronous completion.
568 SSLClientCertType type1
;
569 std::string private_key_info1
, der_cert1
;
570 error
= service_
->GetDomainBoundCert(
571 "good", types
, &type1
, &private_key_info1
, &der_cert1
,
572 callback
.callback(), &request_handle
);
573 EXPECT_EQ(OK
, error
);
574 EXPECT_FALSE(request_handle
.is_active());
575 EXPECT_EQ(2, service_
->cert_count());
576 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
577 EXPECT_STREQ("a", private_key_info1
.c_str());
578 EXPECT_STREQ("b", der_cert1
.c_str());
580 // Expired cert is valid as well - synchronous completion.
581 SSLClientCertType type2
;
582 std::string private_key_info2
, der_cert2
;
583 error
= service_
->GetDomainBoundCert(
584 "expired", types
, &type2
, &private_key_info2
, &der_cert2
,
585 callback
.callback(), &request_handle
);
586 EXPECT_EQ(OK
, error
);
587 EXPECT_FALSE(request_handle
.is_active());
588 EXPECT_EQ(2, service_
->cert_count());
589 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
590 EXPECT_STREQ("c", private_key_info2
.c_str());
591 EXPECT_STREQ("d", der_cert2
.c_str());
594 #endif // !defined(USE_OPENSSL)