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/base/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/asn1_util.h"
16 #include "net/base/default_server_bound_cert_store.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/base/x509_certificate.h"
20 #include "testing/gtest/include/gtest/gtest.h"
26 void FailTest(int /* result */) {
30 class ServerBoundCertServiceTest
: public testing::Test
{
32 virtual void SetUp() OVERRIDE
{
33 sequenced_worker_pool_
= new base::SequencedWorkerPool(
34 3, "ServerBoundCertServiceTest");
35 service_
.reset(new ServerBoundCertService(
36 new DefaultServerBoundCertStore(NULL
), sequenced_worker_pool_
));
39 virtual void TearDown() OVERRIDE
{
40 sequenced_worker_pool_
->Shutdown();
43 scoped_refptr
<base::SequencedWorkerPool
> sequenced_worker_pool_
;
44 scoped_ptr
<ServerBoundCertService
> service_
;
47 TEST_F(ServerBoundCertServiceTest
, GetDomainForHost
) {
48 EXPECT_EQ("google.com",
49 ServerBoundCertService::GetDomainForHost("google.com"));
50 EXPECT_EQ("google.com",
51 ServerBoundCertService::GetDomainForHost("www.google.com"));
52 // NOTE(rch): we would like to segregate cookies and certificates for
53 // *.appspot.com, but currently we can not do that becaues we want to
54 // allow direct navigation to appspot.com.
55 EXPECT_EQ("appspot.com",
56 ServerBoundCertService::GetDomainForHost("foo.appspot.com"));
57 EXPECT_EQ("google.com",
58 ServerBoundCertService::GetDomainForHost("www.mail.google.com"));
60 ServerBoundCertService::GetDomainForHost("goto"));
61 EXPECT_EQ("127.0.0.1",
62 ServerBoundCertService::GetDomainForHost("127.0.0.1"));
65 // See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned.
66 #if !defined(USE_OPENSSL)
68 TEST_F(ServerBoundCertServiceTest
, CacheHit
) {
69 std::string
origin("https://encrypted.google.com:443");
72 std::vector
<uint8
> types
;
73 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
74 TestCompletionCallback callback
;
75 ServerBoundCertService::RequestHandle request_handle
;
77 // Asynchronous completion.
78 SSLClientCertType type1
;
79 std::string private_key_info1
, der_cert1
;
80 EXPECT_EQ(0, service_
->cert_count());
81 error
= service_
->GetDomainBoundCert(
82 origin
, types
, &type1
, &private_key_info1
, &der_cert1
,
83 callback
.callback(), &request_handle
);
84 EXPECT_EQ(ERR_IO_PENDING
, error
);
85 EXPECT_TRUE(request_handle
.is_active());
86 error
= callback
.WaitForResult();
88 EXPECT_EQ(1, service_
->cert_count());
89 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
90 EXPECT_FALSE(private_key_info1
.empty());
91 EXPECT_FALSE(der_cert1
.empty());
92 EXPECT_FALSE(request_handle
.is_active());
94 // Synchronous completion.
95 SSLClientCertType type2
;
96 std::string private_key_info2
, der_cert2
;
97 error
= service_
->GetDomainBoundCert(
98 origin
, types
, &type2
, &private_key_info2
, &der_cert2
,
99 callback
.callback(), &request_handle
);
100 EXPECT_FALSE(request_handle
.is_active());
101 EXPECT_EQ(OK
, error
);
102 EXPECT_EQ(1, service_
->cert_count());
103 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
104 EXPECT_EQ(private_key_info1
, private_key_info2
);
105 EXPECT_EQ(der_cert1
, der_cert2
);
107 EXPECT_EQ(2u, service_
->requests());
108 EXPECT_EQ(1u, service_
->cert_store_hits());
109 EXPECT_EQ(0u, service_
->inflight_joins());
112 TEST_F(ServerBoundCertServiceTest
, UnsupportedTypes
) {
113 std::string
origin("https://encrypted.google.com:443");
116 std::vector
<uint8
> types
;
117 TestCompletionCallback callback
;
118 ServerBoundCertService::RequestHandle request_handle
;
120 // Empty requested_types.
121 SSLClientCertType type1
;
122 std::string private_key_info1
, der_cert1
;
123 error
= service_
->GetDomainBoundCert(
124 origin
, types
, &type1
, &private_key_info1
, &der_cert1
,
125 callback
.callback(), &request_handle
);
126 EXPECT_EQ(ERR_INVALID_ARGUMENT
, error
);
127 EXPECT_FALSE(request_handle
.is_active());
129 // No supported types in requested_types.
130 types
.push_back(CLIENT_CERT_RSA_SIGN
);
133 error
= service_
->GetDomainBoundCert(
134 origin
, types
, &type1
, &private_key_info1
, &der_cert1
,
135 callback
.callback(), &request_handle
);
136 EXPECT_EQ(ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED
, error
);
137 EXPECT_FALSE(request_handle
.is_active());
139 // Supported types after unsupported ones in requested_types.
140 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
141 // Asynchronous completion.
142 EXPECT_EQ(0, service_
->cert_count());
143 error
= service_
->GetDomainBoundCert(
144 origin
, types
, &type1
, &private_key_info1
, &der_cert1
,
145 callback
.callback(), &request_handle
);
146 EXPECT_EQ(ERR_IO_PENDING
, error
);
147 EXPECT_TRUE(request_handle
.is_active());
148 error
= callback
.WaitForResult();
149 EXPECT_EQ(OK
, error
);
150 EXPECT_EQ(1, service_
->cert_count());
151 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
152 EXPECT_FALSE(private_key_info1
.empty());
153 EXPECT_FALSE(der_cert1
.empty());
155 // Now that the cert is created, doing requests for unsupported types
156 // shouldn't affect the created cert.
157 // Empty requested_types.
159 SSLClientCertType type2
;
160 std::string private_key_info2
, der_cert2
;
161 error
= service_
->GetDomainBoundCert(
162 origin
, types
, &type2
, &private_key_info2
, &der_cert2
,
163 callback
.callback(), &request_handle
);
164 EXPECT_EQ(ERR_INVALID_ARGUMENT
, error
);
165 EXPECT_FALSE(request_handle
.is_active());
167 // No supported types in requested_types.
168 types
.push_back(CLIENT_CERT_RSA_SIGN
);
171 error
= service_
->GetDomainBoundCert(
172 origin
, types
, &type2
, &private_key_info2
, &der_cert2
,
173 callback
.callback(), &request_handle
);
174 EXPECT_EQ(ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED
, error
);
175 EXPECT_FALSE(request_handle
.is_active());
177 // If we request EC, the cert we created before should still be there.
178 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
179 error
= service_
->GetDomainBoundCert(
180 origin
, types
, &type2
, &private_key_info2
, &der_cert2
,
181 callback
.callback(), &request_handle
);
182 EXPECT_FALSE(request_handle
.is_active());
183 EXPECT_EQ(OK
, error
);
184 EXPECT_EQ(1, service_
->cert_count());
185 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
186 EXPECT_EQ(private_key_info1
, private_key_info2
);
187 EXPECT_EQ(der_cert1
, der_cert2
);
190 TEST_F(ServerBoundCertServiceTest
, StoreCerts
) {
192 std::vector
<uint8
> types
;
193 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
194 TestCompletionCallback callback
;
195 ServerBoundCertService::RequestHandle request_handle
;
197 std::string
origin1("https://encrypted.google.com:443");
198 SSLClientCertType type1
;
199 std::string private_key_info1
, der_cert1
;
200 EXPECT_EQ(0, service_
->cert_count());
201 error
= service_
->GetDomainBoundCert(
202 origin1
, types
, &type1
, &private_key_info1
, &der_cert1
,
203 callback
.callback(), &request_handle
);
204 EXPECT_EQ(ERR_IO_PENDING
, error
);
205 EXPECT_TRUE(request_handle
.is_active());
206 error
= callback
.WaitForResult();
207 EXPECT_EQ(OK
, error
);
208 EXPECT_EQ(1, service_
->cert_count());
210 std::string
origin2("https://www.verisign.com:443");
211 SSLClientCertType type2
;
212 std::string private_key_info2
, der_cert2
;
213 error
= service_
->GetDomainBoundCert(
214 origin2
, types
, &type2
, &private_key_info2
, &der_cert2
,
215 callback
.callback(), &request_handle
);
216 EXPECT_EQ(ERR_IO_PENDING
, error
);
217 EXPECT_TRUE(request_handle
.is_active());
218 error
= callback
.WaitForResult();
219 EXPECT_EQ(OK
, error
);
220 EXPECT_EQ(2, service_
->cert_count());
222 std::string
origin3("https://www.twitter.com:443");
223 SSLClientCertType type3
;
224 std::string private_key_info3
, der_cert3
;
225 error
= service_
->GetDomainBoundCert(
226 origin3
, types
, &type3
, &private_key_info3
, &der_cert3
,
227 callback
.callback(), &request_handle
);
228 EXPECT_EQ(ERR_IO_PENDING
, error
);
229 EXPECT_TRUE(request_handle
.is_active());
230 error
= callback
.WaitForResult();
231 EXPECT_EQ(OK
, error
);
232 EXPECT_EQ(3, service_
->cert_count());
234 EXPECT_NE(private_key_info1
, private_key_info2
);
235 EXPECT_NE(der_cert1
, der_cert2
);
236 EXPECT_NE(private_key_info1
, private_key_info3
);
237 EXPECT_NE(der_cert1
, der_cert3
);
238 EXPECT_NE(private_key_info2
, private_key_info3
);
239 EXPECT_NE(der_cert2
, der_cert3
);
240 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
241 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
242 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type3
);
245 // Tests an inflight join.
246 TEST_F(ServerBoundCertServiceTest
, InflightJoin
) {
247 std::string
origin("https://encrypted.google.com:443");
249 std::vector
<uint8
> types
;
250 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
252 SSLClientCertType type1
;
253 std::string private_key_info1
, der_cert1
;
254 TestCompletionCallback callback1
;
255 ServerBoundCertService::RequestHandle request_handle1
;
257 SSLClientCertType type2
;
258 std::string private_key_info2
, der_cert2
;
259 TestCompletionCallback callback2
;
260 ServerBoundCertService::RequestHandle request_handle2
;
262 error
= service_
->GetDomainBoundCert(
263 origin
, types
, &type1
, &private_key_info1
, &der_cert1
,
264 callback1
.callback(), &request_handle1
);
265 EXPECT_EQ(ERR_IO_PENDING
, error
);
266 EXPECT_TRUE(request_handle1
.is_active());
267 // If we request RSA and EC in the 2nd request, should still join with the
269 types
.insert(types
.begin(), CLIENT_CERT_RSA_SIGN
);
270 error
= service_
->GetDomainBoundCert(
271 origin
, types
, &type2
, &private_key_info2
, &der_cert2
,
272 callback2
.callback(), &request_handle2
);
273 EXPECT_EQ(ERR_IO_PENDING
, error
);
274 EXPECT_TRUE(request_handle2
.is_active());
276 error
= callback1
.WaitForResult();
277 EXPECT_EQ(OK
, error
);
278 error
= callback2
.WaitForResult();
279 EXPECT_EQ(OK
, error
);
281 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
282 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
283 EXPECT_EQ(2u, service_
->requests());
284 EXPECT_EQ(0u, service_
->cert_store_hits());
285 EXPECT_EQ(1u, service_
->inflight_joins());
288 TEST_F(ServerBoundCertServiceTest
, ExtractValuesFromBytesEC
) {
289 std::string
origin("https://encrypted.google.com:443");
290 SSLClientCertType type
;
291 std::string private_key_info
, der_cert
;
293 std::vector
<uint8
> types
;
294 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
295 TestCompletionCallback callback
;
296 ServerBoundCertService::RequestHandle request_handle
;
298 error
= service_
->GetDomainBoundCert(
299 origin
, types
, &type
, &private_key_info
, &der_cert
, callback
.callback(),
301 EXPECT_EQ(ERR_IO_PENDING
, error
);
302 EXPECT_TRUE(request_handle
.is_active());
303 error
= callback
.WaitForResult();
304 EXPECT_EQ(OK
, error
);
306 base::StringPiece spki_piece
;
307 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_cert
, &spki_piece
));
308 std::vector
<uint8
> spki(
310 spki_piece
.data() + spki_piece
.size());
312 // Check that we can retrieve the key from the bytes.
313 std::vector
<uint8
> key_vec(private_key_info
.begin(), private_key_info
.end());
314 scoped_ptr
<crypto::ECPrivateKey
> private_key(
315 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
316 ServerBoundCertService::kEPKIPassword
, key_vec
, spki
));
317 EXPECT_TRUE(private_key
!= NULL
);
319 // Check that we can retrieve the cert from the bytes.
320 scoped_refptr
<X509Certificate
> x509cert(
321 X509Certificate::CreateFromBytes(der_cert
.data(), der_cert
.size()));
322 EXPECT_TRUE(x509cert
!= NULL
);
325 // Tests that the callback of a canceled request is never made.
326 TEST_F(ServerBoundCertServiceTest
, CancelRequest
) {
327 std::string
origin("https://encrypted.google.com:443");
328 SSLClientCertType type
;
329 std::string private_key_info
, der_cert
;
331 std::vector
<uint8
> types
;
332 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
333 ServerBoundCertService::RequestHandle request_handle
;
335 error
= service_
->GetDomainBoundCert(origin
,
340 base::Bind(&FailTest
),
342 EXPECT_EQ(ERR_IO_PENDING
, error
);
343 EXPECT_TRUE(request_handle
.is_active());
344 request_handle
.Cancel();
345 EXPECT_FALSE(request_handle
.is_active());
347 // Wait for generation to finish.
348 sequenced_worker_pool_
->FlushForTesting();
349 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
350 // ServerBoundCertService.
351 MessageLoop::current()->RunUntilIdle();
353 // Even though the original request was cancelled, the service will still
354 // store the result, it just doesn't call the callback.
355 EXPECT_EQ(1, service_
->cert_count());
358 // Tests that destructing the RequestHandle cancels the request.
359 TEST_F(ServerBoundCertServiceTest
, CancelRequestByHandleDestruction
) {
360 std::string
origin("https://encrypted.google.com:443");
361 SSLClientCertType type
;
362 std::string private_key_info
, der_cert
;
364 std::vector
<uint8
> types
;
365 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
367 ServerBoundCertService::RequestHandle request_handle
;
369 error
= service_
->GetDomainBoundCert(origin
,
374 base::Bind(&FailTest
),
376 EXPECT_EQ(ERR_IO_PENDING
, error
);
377 EXPECT_TRUE(request_handle
.is_active());
380 // Wait for generation to finish.
381 sequenced_worker_pool_
->FlushForTesting();
382 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
383 // ServerBoundCertService.
384 MessageLoop::current()->RunUntilIdle();
386 // Even though the original request was cancelled, the service will still
387 // store the result, it just doesn't call the callback.
388 EXPECT_EQ(1, service_
->cert_count());
391 TEST_F(ServerBoundCertServiceTest
, DestructionWithPendingRequest
) {
392 std::string
origin("https://encrypted.google.com:443");
393 SSLClientCertType type
;
394 std::string private_key_info
, der_cert
;
396 std::vector
<uint8
> types
;
397 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
398 ServerBoundCertService::RequestHandle request_handle
;
400 error
= service_
->GetDomainBoundCert(origin
,
405 base::Bind(&FailTest
),
407 EXPECT_EQ(ERR_IO_PENDING
, error
);
408 EXPECT_TRUE(request_handle
.is_active());
410 // Cancel request and destroy the ServerBoundCertService.
411 request_handle
.Cancel();
414 // Wait for generation to finish.
415 sequenced_worker_pool_
->FlushForTesting();
416 // ServerBoundCertServiceWorker should not post anything back to the
417 // non-existant ServerBoundCertService, but run the loop just to be sure it
419 MessageLoop::current()->RunUntilIdle();
421 // If we got here without crashing or a valgrind error, it worked.
424 // Tests that simultaneous creation of different certs works.
425 TEST_F(ServerBoundCertServiceTest
, SimultaneousCreation
) {
427 std::vector
<uint8
> types
;
428 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
430 std::string
origin1("https://encrypted.google.com:443");
431 SSLClientCertType type1
;
432 std::string private_key_info1
, der_cert1
;
433 TestCompletionCallback callback1
;
434 ServerBoundCertService::RequestHandle request_handle1
;
436 std::string
origin2("https://foo.com:443");
437 SSLClientCertType type2
;
438 std::string private_key_info2
, der_cert2
;
439 TestCompletionCallback callback2
;
440 ServerBoundCertService::RequestHandle request_handle2
;
442 std::string
origin3("https://bar.com:443");
443 SSLClientCertType type3
;
444 std::string private_key_info3
, der_cert3
;
445 TestCompletionCallback callback3
;
446 ServerBoundCertService::RequestHandle request_handle3
;
448 error
= service_
->GetDomainBoundCert(origin1
,
453 callback1
.callback(),
455 EXPECT_EQ(ERR_IO_PENDING
, error
);
456 EXPECT_TRUE(request_handle1
.is_active());
458 error
= service_
->GetDomainBoundCert(origin2
,
463 callback2
.callback(),
465 EXPECT_EQ(ERR_IO_PENDING
, error
);
466 EXPECT_TRUE(request_handle2
.is_active());
468 error
= service_
->GetDomainBoundCert(origin3
,
473 callback3
.callback(),
475 EXPECT_EQ(ERR_IO_PENDING
, error
);
476 EXPECT_TRUE(request_handle3
.is_active());
478 error
= callback1
.WaitForResult();
479 EXPECT_EQ(OK
, error
);
480 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
481 EXPECT_FALSE(private_key_info1
.empty());
482 EXPECT_FALSE(der_cert1
.empty());
484 error
= callback2
.WaitForResult();
485 EXPECT_EQ(OK
, error
);
486 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
487 EXPECT_FALSE(private_key_info2
.empty());
488 EXPECT_FALSE(der_cert2
.empty());
490 error
= callback3
.WaitForResult();
491 EXPECT_EQ(OK
, error
);
492 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type3
);
493 EXPECT_FALSE(private_key_info3
.empty());
494 EXPECT_FALSE(der_cert3
.empty());
496 EXPECT_NE(private_key_info1
, private_key_info2
);
497 EXPECT_NE(der_cert1
, der_cert2
);
499 EXPECT_NE(private_key_info1
, private_key_info3
);
500 EXPECT_NE(der_cert1
, der_cert3
);
502 EXPECT_NE(private_key_info2
, private_key_info3
);
503 EXPECT_NE(der_cert2
, der_cert3
);
505 EXPECT_EQ(3, service_
->cert_count());
508 TEST_F(ServerBoundCertServiceTest
, Expiration
) {
509 ServerBoundCertStore
* store
= service_
->GetCertStore();
510 base::Time now
= base::Time::Now();
511 store
->SetServerBoundCert("good",
512 CLIENT_CERT_ECDSA_SIGN
,
514 now
+ base::TimeDelta::FromDays(1),
517 store
->SetServerBoundCert("expired",
518 CLIENT_CERT_ECDSA_SIGN
,
519 now
- base::TimeDelta::FromDays(2),
520 now
- base::TimeDelta::FromDays(1),
523 EXPECT_EQ(2, service_
->cert_count());
526 std::vector
<uint8
> types
;
527 types
.push_back(CLIENT_CERT_ECDSA_SIGN
);
528 TestCompletionCallback callback
;
529 ServerBoundCertService::RequestHandle request_handle
;
531 // Cert still valid - synchronous completion.
532 SSLClientCertType type1
;
533 std::string private_key_info1
, der_cert1
;
534 error
= service_
->GetDomainBoundCert(
535 "https://good", types
, &type1
, &private_key_info1
, &der_cert1
,
536 callback
.callback(), &request_handle
);
537 EXPECT_EQ(OK
, error
);
538 EXPECT_FALSE(request_handle
.is_active());
539 EXPECT_EQ(2, service_
->cert_count());
540 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type1
);
541 EXPECT_STREQ("a", private_key_info1
.c_str());
542 EXPECT_STREQ("b", der_cert1
.c_str());
544 // Cert expired - New cert will be generated, asynchronous completion.
545 SSLClientCertType type2
;
546 std::string private_key_info2
, der_cert2
;
547 error
= service_
->GetDomainBoundCert(
548 "https://expired", types
, &type2
, &private_key_info2
, &der_cert2
,
549 callback
.callback(), &request_handle
);
550 EXPECT_EQ(ERR_IO_PENDING
, error
);
551 EXPECT_TRUE(request_handle
.is_active());
552 error
= callback
.WaitForResult();
553 EXPECT_EQ(OK
, error
);
554 EXPECT_EQ(2, service_
->cert_count());
555 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN
, type2
);
556 EXPECT_LT(1U, private_key_info2
.size());
557 EXPECT_LT(1U, der_cert2
.size());
560 #endif // !defined(USE_OPENSSL)