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/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/task_runner.h"
15 #include "crypto/ec_private_key.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/cert/asn1_util.h"
19 #include "net/cert/x509_certificate.h"
20 #include "net/ssl/default_server_bound_cert_store.h"
21 #include "testing/gtest/include/gtest/gtest.h"
27 #if !defined(USE_OPENSSL)
28 void FailTest(int /* result */) {
32 // Simple task runner that refuses to actually post any tasks. This simulates
33 // a TaskRunner that has been shutdown, by returning false for any attempt to
35 class FailingTaskRunner
: public base::TaskRunner
{
37 FailingTaskRunner() {}
39 virtual bool PostDelayedTask(const tracked_objects::Location
& from_here
,
40 const base::Closure
& task
,
41 base::TimeDelta delay
) OVERRIDE
{
45 virtual bool RunsTasksOnCurrentThread() const OVERRIDE
{ return true; }
48 virtual ~FailingTaskRunner() {}
51 DISALLOW_COPY_AND_ASSIGN(FailingTaskRunner
);
54 class MockServerBoundCertStoreWithAsyncGet
55 : public DefaultServerBoundCertStore
{
57 MockServerBoundCertStoreWithAsyncGet()
58 : DefaultServerBoundCertStore(NULL
), cert_count_(0) {}
60 virtual int GetServerBoundCert(const std::string
& server_identifier
,
61 base::Time
* expiration_time
,
62 std::string
* private_key_result
,
63 std::string
* cert_result
,
64 const GetCertCallback
& callback
) OVERRIDE
;
66 virtual void SetServerBoundCert(const std::string
& server_identifier
,
67 base::Time creation_time
,
68 base::Time expiration_time
,
69 const std::string
& private_key
,
70 const std::string
& cert
) OVERRIDE
{
74 virtual int GetCertCount() OVERRIDE
{ return cert_count_
; }
76 void CallGetServerBoundCertCallbackWithResult(int err
,
77 base::Time expiration_time
,
78 const std::string
& private_key
,
79 const std::string
& cert
);
82 GetCertCallback callback_
;
83 std::string server_identifier_
;
87 int MockServerBoundCertStoreWithAsyncGet::GetServerBoundCert(
88 const std::string
& server_identifier
,
89 base::Time
* expiration_time
,
90 std::string
* private_key_result
,
91 std::string
* cert_result
,
92 const GetCertCallback
& callback
) {
93 server_identifier_
= server_identifier
;
95 // Reset the cert count, it'll get incremented in either SetServerBoundCert or
96 // CallGetServerBoundCertCallbackWithResult.
98 // Do nothing else: the results to be provided will be specified through
99 // CallGetServerBoundCertCallbackWithResult.
100 return ERR_IO_PENDING
;
104 MockServerBoundCertStoreWithAsyncGet::CallGetServerBoundCertCallbackWithResult(
106 base::Time expiration_time
,
107 const std::string
& private_key
,
108 const std::string
& cert
) {
111 base::MessageLoop::current()->PostTask(FROM_HERE
,
112 base::Bind(callback_
,
120 #endif // !defined(USE_OPENSSL)
122 class ServerBoundCertServiceTest
: public testing::Test
{
124 ServerBoundCertServiceTest()
125 : service_(new ServerBoundCertService(
126 new DefaultServerBoundCertStore(NULL
),
127 base::MessageLoopProxy::current())) {
131 scoped_ptr
<ServerBoundCertService
> service_
;
134 TEST_F(ServerBoundCertServiceTest
, GetDomainForHost
) {
135 EXPECT_EQ("google.com",
136 ServerBoundCertService::GetDomainForHost("google.com"));
137 EXPECT_EQ("google.com",
138 ServerBoundCertService::GetDomainForHost("www.google.com"));
139 EXPECT_EQ("foo.appspot.com",
140 ServerBoundCertService::GetDomainForHost("foo.appspot.com"));
141 EXPECT_EQ("bar.appspot.com",
142 ServerBoundCertService::GetDomainForHost("foo.bar.appspot.com"));
143 EXPECT_EQ("appspot.com",
144 ServerBoundCertService::GetDomainForHost("appspot.com"));
145 EXPECT_EQ("google.com",
146 ServerBoundCertService::GetDomainForHost("www.mail.google.com"));
148 ServerBoundCertService::GetDomainForHost("goto"));
149 EXPECT_EQ("127.0.0.1",
150 ServerBoundCertService::GetDomainForHost("127.0.0.1"));
153 // See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned.
154 #if !defined(USE_OPENSSL)
156 TEST_F(ServerBoundCertServiceTest
, GetCacheMiss
) {
157 std::string
host("encrypted.google.com");
160 TestCompletionCallback callback
;
161 ServerBoundCertService::RequestHandle request_handle
;
163 // Synchronous completion, because the store is initialized.
164 std::string private_key
, der_cert
;
165 EXPECT_EQ(0, service_
->cert_count());
166 error
= service_
->GetDomainBoundCert(
167 host
, &private_key
, &der_cert
, callback
.callback(), &request_handle
);
168 EXPECT_EQ(ERR_FILE_NOT_FOUND
, error
);
169 EXPECT_FALSE(request_handle
.is_active());
170 EXPECT_EQ(0, service_
->cert_count());
171 EXPECT_TRUE(der_cert
.empty());
174 TEST_F(ServerBoundCertServiceTest
, CacheHit
) {
175 std::string
host("encrypted.google.com");
178 TestCompletionCallback callback
;
179 ServerBoundCertService::RequestHandle request_handle
;
181 // Asynchronous completion.
182 std::string private_key_info1
, der_cert1
;
183 EXPECT_EQ(0, service_
->cert_count());
184 error
= service_
->GetOrCreateDomainBoundCert(
185 host
, &private_key_info1
, &der_cert1
,
186 callback
.callback(), &request_handle
);
187 EXPECT_EQ(ERR_IO_PENDING
, error
);
188 EXPECT_TRUE(request_handle
.is_active());
189 error
= callback
.WaitForResult();
190 EXPECT_EQ(OK
, error
);
191 EXPECT_EQ(1, service_
->cert_count());
192 EXPECT_FALSE(private_key_info1
.empty());
193 EXPECT_FALSE(der_cert1
.empty());
194 EXPECT_FALSE(request_handle
.is_active());
196 // Synchronous completion.
197 std::string private_key_info2
, der_cert2
;
198 error
= service_
->GetOrCreateDomainBoundCert(
199 host
, &private_key_info2
, &der_cert2
,
200 callback
.callback(), &request_handle
);
201 EXPECT_FALSE(request_handle
.is_active());
202 EXPECT_EQ(OK
, error
);
203 EXPECT_EQ(1, service_
->cert_count());
204 EXPECT_EQ(private_key_info1
, private_key_info2
);
205 EXPECT_EQ(der_cert1
, der_cert2
);
208 std::string private_key_info3
, der_cert3
;
209 error
= service_
->GetDomainBoundCert(
210 host
, &private_key_info3
, &der_cert3
, callback
.callback(),
212 EXPECT_FALSE(request_handle
.is_active());
213 EXPECT_EQ(OK
, error
);
214 EXPECT_EQ(1, service_
->cert_count());
215 EXPECT_EQ(der_cert1
, der_cert3
);
216 EXPECT_EQ(private_key_info1
, private_key_info3
);
218 EXPECT_EQ(3u, service_
->requests());
219 EXPECT_EQ(2u, service_
->cert_store_hits());
220 EXPECT_EQ(0u, service_
->inflight_joins());
223 TEST_F(ServerBoundCertServiceTest
, StoreCerts
) {
225 TestCompletionCallback callback
;
226 ServerBoundCertService::RequestHandle request_handle
;
228 std::string
host1("encrypted.google.com");
229 std::string private_key_info1
, der_cert1
;
230 EXPECT_EQ(0, service_
->cert_count());
231 error
= service_
->GetOrCreateDomainBoundCert(
232 host1
, &private_key_info1
, &der_cert1
,
233 callback
.callback(), &request_handle
);
234 EXPECT_EQ(ERR_IO_PENDING
, error
);
235 EXPECT_TRUE(request_handle
.is_active());
236 error
= callback
.WaitForResult();
237 EXPECT_EQ(OK
, error
);
238 EXPECT_EQ(1, service_
->cert_count());
240 std::string
host2("www.verisign.com");
241 std::string private_key_info2
, der_cert2
;
242 error
= service_
->GetOrCreateDomainBoundCert(
243 host2
, &private_key_info2
, &der_cert2
,
244 callback
.callback(), &request_handle
);
245 EXPECT_EQ(ERR_IO_PENDING
, error
);
246 EXPECT_TRUE(request_handle
.is_active());
247 error
= callback
.WaitForResult();
248 EXPECT_EQ(OK
, error
);
249 EXPECT_EQ(2, service_
->cert_count());
251 std::string
host3("www.twitter.com");
252 std::string private_key_info3
, der_cert3
;
253 error
= service_
->GetOrCreateDomainBoundCert(
254 host3
, &private_key_info3
, &der_cert3
,
255 callback
.callback(), &request_handle
);
256 EXPECT_EQ(ERR_IO_PENDING
, error
);
257 EXPECT_TRUE(request_handle
.is_active());
258 error
= callback
.WaitForResult();
259 EXPECT_EQ(OK
, error
);
260 EXPECT_EQ(3, service_
->cert_count());
262 EXPECT_NE(private_key_info1
, private_key_info2
);
263 EXPECT_NE(der_cert1
, der_cert2
);
264 EXPECT_NE(private_key_info1
, private_key_info3
);
265 EXPECT_NE(der_cert1
, der_cert3
);
266 EXPECT_NE(private_key_info2
, private_key_info3
);
267 EXPECT_NE(der_cert2
, der_cert3
);
270 // Tests an inflight join.
271 TEST_F(ServerBoundCertServiceTest
, InflightJoin
) {
272 std::string
host("encrypted.google.com");
275 std::string private_key_info1
, der_cert1
;
276 TestCompletionCallback callback1
;
277 ServerBoundCertService::RequestHandle request_handle1
;
279 std::string private_key_info2
, der_cert2
;
280 TestCompletionCallback callback2
;
281 ServerBoundCertService::RequestHandle request_handle2
;
283 error
= service_
->GetOrCreateDomainBoundCert(
284 host
, &private_key_info1
, &der_cert1
,
285 callback1
.callback(), &request_handle1
);
286 EXPECT_EQ(ERR_IO_PENDING
, error
);
287 EXPECT_TRUE(request_handle1
.is_active());
288 // Should join with the original request.
289 error
= service_
->GetOrCreateDomainBoundCert(
290 host
, &private_key_info2
, &der_cert2
,
291 callback2
.callback(), &request_handle2
);
292 EXPECT_EQ(ERR_IO_PENDING
, error
);
293 EXPECT_TRUE(request_handle2
.is_active());
295 error
= callback1
.WaitForResult();
296 EXPECT_EQ(OK
, error
);
297 error
= callback2
.WaitForResult();
298 EXPECT_EQ(OK
, error
);
300 EXPECT_EQ(2u, service_
->requests());
301 EXPECT_EQ(0u, service_
->cert_store_hits());
302 EXPECT_EQ(1u, service_
->inflight_joins());
303 EXPECT_EQ(1u, service_
->workers_created());
306 // Tests an inflight join of a Get request to a GetOrCreate request.
307 TEST_F(ServerBoundCertServiceTest
, InflightJoinGetOrCreateAndGet
) {
308 std::string
host("encrypted.google.com");
311 std::string private_key_info1
, der_cert1
;
312 TestCompletionCallback callback1
;
313 ServerBoundCertService::RequestHandle request_handle1
;
315 std::string private_key_info2
;
316 std::string der_cert2
;
317 TestCompletionCallback callback2
;
318 ServerBoundCertService::RequestHandle request_handle2
;
320 error
= service_
->GetOrCreateDomainBoundCert(
321 host
, &private_key_info1
, &der_cert1
,
322 callback1
.callback(), &request_handle1
);
323 EXPECT_EQ(ERR_IO_PENDING
, error
);
324 EXPECT_TRUE(request_handle1
.is_active());
325 // Should join with the original request.
326 error
= service_
->GetDomainBoundCert(
327 host
, &private_key_info2
, &der_cert2
, callback2
.callback(),
329 EXPECT_EQ(ERR_IO_PENDING
, error
);
330 EXPECT_TRUE(request_handle2
.is_active());
332 error
= callback1
.WaitForResult();
333 EXPECT_EQ(OK
, error
);
334 error
= callback2
.WaitForResult();
335 EXPECT_EQ(OK
, error
);
336 EXPECT_EQ(der_cert1
, der_cert2
);
338 EXPECT_EQ(2u, service_
->requests());
339 EXPECT_EQ(0u, service_
->cert_store_hits());
340 EXPECT_EQ(1u, service_
->inflight_joins());
341 EXPECT_EQ(1u, service_
->workers_created());
344 TEST_F(ServerBoundCertServiceTest
, ExtractValuesFromBytesEC
) {
345 std::string
host("encrypted.google.com");
346 std::string private_key_info
, der_cert
;
348 TestCompletionCallback callback
;
349 ServerBoundCertService::RequestHandle request_handle
;
351 error
= service_
->GetOrCreateDomainBoundCert(
352 host
, &private_key_info
, &der_cert
, callback
.callback(),
354 EXPECT_EQ(ERR_IO_PENDING
, error
);
355 EXPECT_TRUE(request_handle
.is_active());
356 error
= callback
.WaitForResult();
357 EXPECT_EQ(OK
, error
);
359 base::StringPiece spki_piece
;
360 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_cert
, &spki_piece
));
361 std::vector
<uint8
> spki(
363 spki_piece
.data() + spki_piece
.size());
365 // Check that we can retrieve the key from the bytes.
366 std::vector
<uint8
> key_vec(private_key_info
.begin(), private_key_info
.end());
367 scoped_ptr
<crypto::ECPrivateKey
> private_key(
368 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
369 ServerBoundCertService::kEPKIPassword
, key_vec
, spki
));
370 EXPECT_TRUE(private_key
!= NULL
);
372 // Check that we can retrieve the cert from the bytes.
373 scoped_refptr
<X509Certificate
> x509cert(
374 X509Certificate::CreateFromBytes(der_cert
.data(), der_cert
.size()));
375 EXPECT_TRUE(x509cert
.get() != NULL
);
378 // Tests that the callback of a canceled request is never made.
379 TEST_F(ServerBoundCertServiceTest
, CancelRequest
) {
380 std::string
host("encrypted.google.com");
381 std::string private_key_info
, der_cert
;
383 ServerBoundCertService::RequestHandle request_handle
;
385 error
= service_
->GetOrCreateDomainBoundCert(host
,
388 base::Bind(&FailTest
),
390 EXPECT_EQ(ERR_IO_PENDING
, error
);
391 EXPECT_TRUE(request_handle
.is_active());
392 request_handle
.Cancel();
393 EXPECT_FALSE(request_handle
.is_active());
395 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
396 // ServerBoundCertService.
397 base::MessageLoop::current()->RunUntilIdle();
399 // Even though the original request was cancelled, the service will still
400 // store the result, it just doesn't call the callback.
401 EXPECT_EQ(1, service_
->cert_count());
404 // Tests that destructing the RequestHandle cancels the request.
405 TEST_F(ServerBoundCertServiceTest
, CancelRequestByHandleDestruction
) {
406 std::string
host("encrypted.google.com");
407 std::string private_key_info
, der_cert
;
410 ServerBoundCertService::RequestHandle request_handle
;
412 error
= service_
->GetOrCreateDomainBoundCert(host
,
415 base::Bind(&FailTest
),
417 EXPECT_EQ(ERR_IO_PENDING
, error
);
418 EXPECT_TRUE(request_handle
.is_active());
421 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
422 // ServerBoundCertService.
423 base::MessageLoop::current()->RunUntilIdle();
425 // Even though the original request was cancelled, the service will still
426 // store the result, it just doesn't call the callback.
427 EXPECT_EQ(1, service_
->cert_count());
430 TEST_F(ServerBoundCertServiceTest
, DestructionWithPendingRequest
) {
431 std::string
host("encrypted.google.com");
432 std::string private_key_info
, der_cert
;
434 ServerBoundCertService::RequestHandle request_handle
;
436 error
= service_
->GetOrCreateDomainBoundCert(host
,
439 base::Bind(&FailTest
),
441 EXPECT_EQ(ERR_IO_PENDING
, error
);
442 EXPECT_TRUE(request_handle
.is_active());
444 // Cancel request and destroy the ServerBoundCertService.
445 request_handle
.Cancel();
448 // ServerBoundCertServiceWorker should not post anything back to the
449 // non-existent ServerBoundCertService, but run the loop just to be sure it
451 base::MessageLoop::current()->RunUntilIdle();
453 // If we got here without crashing or a valgrind error, it worked.
456 // Tests that shutting down the sequenced worker pool and then making new
457 // requests gracefully fails.
458 // This is a regression test for http://crbug.com/236387
459 TEST_F(ServerBoundCertServiceTest
, RequestAfterPoolShutdown
) {
460 scoped_refptr
<FailingTaskRunner
> task_runner(new FailingTaskRunner
);
461 service_
.reset(new ServerBoundCertService(
462 new DefaultServerBoundCertStore(NULL
), task_runner
));
464 // Make a request that will force synchronous completion.
465 std::string
host("encrypted.google.com");
466 std::string private_key_info
, der_cert
;
468 ServerBoundCertService::RequestHandle request_handle
;
470 error
= service_
->GetOrCreateDomainBoundCert(host
,
473 base::Bind(&FailTest
),
475 // If we got here without crashing or a valgrind error, it worked.
476 ASSERT_EQ(ERR_INSUFFICIENT_RESOURCES
, error
);
477 EXPECT_FALSE(request_handle
.is_active());
480 // Tests that simultaneous creation of different certs works.
481 TEST_F(ServerBoundCertServiceTest
, SimultaneousCreation
) {
484 std::string
host1("encrypted.google.com");
485 std::string private_key_info1
, der_cert1
;
486 TestCompletionCallback callback1
;
487 ServerBoundCertService::RequestHandle request_handle1
;
489 std::string
host2("foo.com");
490 std::string private_key_info2
, der_cert2
;
491 TestCompletionCallback callback2
;
492 ServerBoundCertService::RequestHandle request_handle2
;
494 std::string
host3("bar.com");
495 std::string private_key_info3
, der_cert3
;
496 TestCompletionCallback callback3
;
497 ServerBoundCertService::RequestHandle request_handle3
;
499 error
= service_
->GetOrCreateDomainBoundCert(host1
,
502 callback1
.callback(),
504 EXPECT_EQ(ERR_IO_PENDING
, error
);
505 EXPECT_TRUE(request_handle1
.is_active());
507 error
= service_
->GetOrCreateDomainBoundCert(host2
,
510 callback2
.callback(),
512 EXPECT_EQ(ERR_IO_PENDING
, error
);
513 EXPECT_TRUE(request_handle2
.is_active());
515 error
= service_
->GetOrCreateDomainBoundCert(host3
,
518 callback3
.callback(),
520 EXPECT_EQ(ERR_IO_PENDING
, error
);
521 EXPECT_TRUE(request_handle3
.is_active());
523 error
= callback1
.WaitForResult();
524 EXPECT_EQ(OK
, error
);
525 EXPECT_FALSE(private_key_info1
.empty());
526 EXPECT_FALSE(der_cert1
.empty());
528 error
= callback2
.WaitForResult();
529 EXPECT_EQ(OK
, error
);
530 EXPECT_FALSE(private_key_info2
.empty());
531 EXPECT_FALSE(der_cert2
.empty());
533 error
= callback3
.WaitForResult();
534 EXPECT_EQ(OK
, error
);
535 EXPECT_FALSE(private_key_info3
.empty());
536 EXPECT_FALSE(der_cert3
.empty());
538 EXPECT_NE(private_key_info1
, private_key_info2
);
539 EXPECT_NE(der_cert1
, der_cert2
);
541 EXPECT_NE(private_key_info1
, private_key_info3
);
542 EXPECT_NE(der_cert1
, der_cert3
);
544 EXPECT_NE(private_key_info2
, private_key_info3
);
545 EXPECT_NE(der_cert2
, der_cert3
);
547 EXPECT_EQ(3, service_
->cert_count());
550 TEST_F(ServerBoundCertServiceTest
, Expiration
) {
551 ServerBoundCertStore
* store
= service_
->GetCertStore();
552 base::Time now
= base::Time::Now();
553 store
->SetServerBoundCert("good",
555 now
+ base::TimeDelta::FromDays(1),
558 store
->SetServerBoundCert("expired",
559 now
- base::TimeDelta::FromDays(2),
560 now
- base::TimeDelta::FromDays(1),
563 EXPECT_EQ(2, service_
->cert_count());
566 TestCompletionCallback callback
;
567 ServerBoundCertService::RequestHandle request_handle
;
569 // Cert is valid - synchronous completion.
570 std::string private_key_info1
, der_cert1
;
571 error
= service_
->GetOrCreateDomainBoundCert(
572 "good", &private_key_info1
, &der_cert1
,
573 callback
.callback(), &request_handle
);
574 EXPECT_EQ(OK
, error
);
575 EXPECT_FALSE(request_handle
.is_active());
576 EXPECT_EQ(2, service_
->cert_count());
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 std::string private_key_info2
, der_cert2
;
582 error
= service_
->GetOrCreateDomainBoundCert(
583 "expired", &private_key_info2
, &der_cert2
,
584 callback
.callback(), &request_handle
);
585 EXPECT_EQ(OK
, error
);
586 EXPECT_FALSE(request_handle
.is_active());
587 EXPECT_EQ(2, service_
->cert_count());
588 EXPECT_STREQ("c", private_key_info2
.c_str());
589 EXPECT_STREQ("d", der_cert2
.c_str());
592 TEST_F(ServerBoundCertServiceTest
, AsyncStoreGetOrCreateNoCertsInStore
) {
593 MockServerBoundCertStoreWithAsyncGet
* mock_store
=
594 new MockServerBoundCertStoreWithAsyncGet();
595 service_
= scoped_ptr
<ServerBoundCertService
>(new ServerBoundCertService(
596 mock_store
, base::MessageLoopProxy::current()));
598 std::string
host("encrypted.google.com");
601 TestCompletionCallback callback
;
602 ServerBoundCertService::RequestHandle request_handle
;
604 // Asynchronous completion with no certs in the store.
605 std::string private_key_info
, der_cert
;
606 EXPECT_EQ(0, service_
->cert_count());
607 error
= service_
->GetOrCreateDomainBoundCert(
608 host
, &private_key_info
, &der_cert
, callback
.callback(), &request_handle
);
609 EXPECT_EQ(ERR_IO_PENDING
, error
);
610 EXPECT_TRUE(request_handle
.is_active());
612 mock_store
->CallGetServerBoundCertCallbackWithResult(
613 ERR_FILE_NOT_FOUND
, base::Time(), std::string(), std::string());
615 error
= callback
.WaitForResult();
616 EXPECT_EQ(OK
, error
);
617 EXPECT_EQ(1, service_
->cert_count());
618 EXPECT_FALSE(private_key_info
.empty());
619 EXPECT_FALSE(der_cert
.empty());
620 EXPECT_FALSE(request_handle
.is_active());
623 TEST_F(ServerBoundCertServiceTest
, AsyncStoreGetNoCertsInStore
) {
624 MockServerBoundCertStoreWithAsyncGet
* mock_store
=
625 new MockServerBoundCertStoreWithAsyncGet();
626 service_
= scoped_ptr
<ServerBoundCertService
>(new ServerBoundCertService(
627 mock_store
, base::MessageLoopProxy::current()));
629 std::string
host("encrypted.google.com");
632 TestCompletionCallback callback
;
633 ServerBoundCertService::RequestHandle request_handle
;
635 // Asynchronous completion with no certs in the store.
636 std::string private_key
, der_cert
;
637 EXPECT_EQ(0, service_
->cert_count());
638 error
= service_
->GetDomainBoundCert(
639 host
, &private_key
, &der_cert
, callback
.callback(), &request_handle
);
640 EXPECT_EQ(ERR_IO_PENDING
, error
);
641 EXPECT_TRUE(request_handle
.is_active());
643 mock_store
->CallGetServerBoundCertCallbackWithResult(
644 ERR_FILE_NOT_FOUND
, base::Time(), std::string(), std::string());
646 error
= callback
.WaitForResult();
647 EXPECT_EQ(ERR_FILE_NOT_FOUND
, error
);
648 EXPECT_EQ(0, service_
->cert_count());
649 EXPECT_EQ(0u, service_
->workers_created());
650 EXPECT_TRUE(der_cert
.empty());
651 EXPECT_FALSE(request_handle
.is_active());
654 TEST_F(ServerBoundCertServiceTest
, AsyncStoreGetOrCreateOneCertInStore
) {
655 MockServerBoundCertStoreWithAsyncGet
* mock_store
=
656 new MockServerBoundCertStoreWithAsyncGet();
657 service_
= scoped_ptr
<ServerBoundCertService
>(new ServerBoundCertService(
658 mock_store
, base::MessageLoopProxy::current()));
660 std::string
host("encrypted.google.com");
663 TestCompletionCallback callback
;
664 ServerBoundCertService::RequestHandle request_handle
;
666 // Asynchronous completion with a cert in the store.
667 std::string private_key_info
, der_cert
;
668 EXPECT_EQ(0, service_
->cert_count());
669 error
= service_
->GetOrCreateDomainBoundCert(
670 host
, &private_key_info
, &der_cert
, callback
.callback(), &request_handle
);
671 EXPECT_EQ(ERR_IO_PENDING
, error
);
672 EXPECT_TRUE(request_handle
.is_active());
674 mock_store
->CallGetServerBoundCertCallbackWithResult(
675 OK
, base::Time(), "ab", "cd");
677 error
= callback
.WaitForResult();
678 EXPECT_EQ(OK
, error
);
679 EXPECT_EQ(1, service_
->cert_count());
680 EXPECT_EQ(1u, service_
->requests());
681 EXPECT_EQ(1u, service_
->cert_store_hits());
682 // Because the cert was found in the store, no new workers should have been
684 EXPECT_EQ(0u, service_
->workers_created());
685 EXPECT_STREQ("ab", private_key_info
.c_str());
686 EXPECT_STREQ("cd", der_cert
.c_str());
687 EXPECT_FALSE(request_handle
.is_active());
690 TEST_F(ServerBoundCertServiceTest
, AsyncStoreGetOneCertInStore
) {
691 MockServerBoundCertStoreWithAsyncGet
* mock_store
=
692 new MockServerBoundCertStoreWithAsyncGet();
693 service_
= scoped_ptr
<ServerBoundCertService
>(new ServerBoundCertService(
694 mock_store
, base::MessageLoopProxy::current()));
696 std::string
host("encrypted.google.com");
699 TestCompletionCallback callback
;
700 ServerBoundCertService::RequestHandle request_handle
;
702 // Asynchronous completion with a cert in the store.
703 std::string private_key
, der_cert
;
704 EXPECT_EQ(0, service_
->cert_count());
705 error
= service_
->GetDomainBoundCert(
706 host
, &private_key
, &der_cert
, callback
.callback(), &request_handle
);
707 EXPECT_EQ(ERR_IO_PENDING
, error
);
708 EXPECT_TRUE(request_handle
.is_active());
710 mock_store
->CallGetServerBoundCertCallbackWithResult(
711 OK
, base::Time(), "ab", "cd");
713 error
= callback
.WaitForResult();
714 EXPECT_EQ(OK
, error
);
715 EXPECT_EQ(1, service_
->cert_count());
716 EXPECT_EQ(1u, service_
->requests());
717 EXPECT_EQ(1u, service_
->cert_store_hits());
718 // Because the cert was found in the store, no new workers should have been
720 EXPECT_EQ(0u, service_
->workers_created());
721 EXPECT_STREQ("cd", der_cert
.c_str());
722 EXPECT_FALSE(request_handle
.is_active());
725 TEST_F(ServerBoundCertServiceTest
, AsyncStoreGetThenCreateNoCertsInStore
) {
726 MockServerBoundCertStoreWithAsyncGet
* mock_store
=
727 new MockServerBoundCertStoreWithAsyncGet();
728 service_
= scoped_ptr
<ServerBoundCertService
>(new ServerBoundCertService(
729 mock_store
, base::MessageLoopProxy::current()));
731 std::string
host("encrypted.google.com");
735 // Asynchronous get with no certs in the store.
736 TestCompletionCallback callback1
;
737 ServerBoundCertService::RequestHandle request_handle1
;
738 std::string private_key1
, der_cert1
;
739 EXPECT_EQ(0, service_
->cert_count());
740 error
= service_
->GetDomainBoundCert(
741 host
, &private_key1
, &der_cert1
, callback1
.callback(), &request_handle1
);
742 EXPECT_EQ(ERR_IO_PENDING
, error
);
743 EXPECT_TRUE(request_handle1
.is_active());
745 // Asynchronous get/create with no certs in the store.
746 TestCompletionCallback callback2
;
747 ServerBoundCertService::RequestHandle request_handle2
;
748 std::string private_key2
, der_cert2
;
749 EXPECT_EQ(0, service_
->cert_count());
750 error
= service_
->GetOrCreateDomainBoundCert(
751 host
, &private_key2
, &der_cert2
, callback2
.callback(), &request_handle2
);
752 EXPECT_EQ(ERR_IO_PENDING
, error
);
753 EXPECT_TRUE(request_handle2
.is_active());
755 mock_store
->CallGetServerBoundCertCallbackWithResult(
756 ERR_FILE_NOT_FOUND
, base::Time(), std::string(), std::string());
758 // Even though the first request didn't ask to create a cert, it gets joined
759 // by the second, which does, so both succeed.
760 error
= callback1
.WaitForResult();
761 EXPECT_EQ(OK
, error
);
762 error
= callback2
.WaitForResult();
763 EXPECT_EQ(OK
, error
);
765 // One cert is created, one request is joined.
766 EXPECT_EQ(2U, service_
->requests());
767 EXPECT_EQ(1, service_
->cert_count());
768 EXPECT_EQ(1u, service_
->workers_created());
769 EXPECT_EQ(1u, service_
->inflight_joins());
770 EXPECT_FALSE(der_cert1
.empty());
771 EXPECT_EQ(der_cert1
, der_cert2
);
772 EXPECT_FALSE(private_key1
.empty());
773 EXPECT_EQ(private_key1
, private_key2
);
774 EXPECT_FALSE(request_handle1
.is_active());
775 EXPECT_FALSE(request_handle2
.is_active());
778 #endif // !defined(USE_OPENSSL)