blob: 0063f496036854c4c3a1ae2be4cbc1dea394ae66 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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.
4
5#include "net/ssl/server_bound_cert_service.h"
6
7#include <string>
8#include <vector>
9
10#include "base/bind.h"
11#include "base/memory/scoped_ptr.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +010012#include "base/message_loop/message_loop.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010013#include "base/task_runner.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000014#include "base/threading/sequenced_worker_pool.h"
15#include "crypto/ec_private_key.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000016#include "net/base/net_errors.h"
17#include "net/base/test_completion_callback.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010018#include "net/cert/asn1_util.h"
19#include "net/cert/x509_certificate.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000020#include "net/ssl/default_server_bound_cert_store.h"
21#include "testing/gtest/include/gtest/gtest.h"
22
23namespace net {
24
25namespace {
26
27void FailTest(int /* result */) {
28 FAIL();
29}
30
31class ServerBoundCertServiceTest : public testing::Test {
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010032 public:
33 ServerBoundCertServiceTest()
34 : sequenced_worker_pool_(new base::SequencedWorkerPool(
35 3, "ServerBoundCertServiceTest")),
36 service_(new ServerBoundCertService(
37 new DefaultServerBoundCertStore(NULL),
38 sequenced_worker_pool_)) {
39 }
40
41 virtual ~ServerBoundCertServiceTest() {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010042 if (sequenced_worker_pool_.get())
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010043 sequenced_worker_pool_->Shutdown();
44 }
45
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000046 protected:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000047 scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool_;
48 scoped_ptr<ServerBoundCertService> service_;
49};
50
Ben Murdochbb1529c2013-08-08 10:24:53 +010051class MockServerBoundCertStoreWithAsyncGet
52 : public DefaultServerBoundCertStore {
53 public:
54 MockServerBoundCertStoreWithAsyncGet()
55 : DefaultServerBoundCertStore(NULL), cert_count_(0) {}
56
57 virtual int GetServerBoundCert(const std::string& server_identifier,
58 base::Time* expiration_time,
59 std::string* private_key_result,
60 std::string* cert_result,
61 const GetCertCallback& callback) OVERRIDE;
62
63 virtual void SetServerBoundCert(const std::string& server_identifier,
64 base::Time creation_time,
65 base::Time expiration_time,
66 const std::string& private_key,
67 const std::string& cert) OVERRIDE {
68 cert_count_ = 1;
69 }
70
71 virtual int GetCertCount() OVERRIDE { return cert_count_; }
72
73 void CallGetServerBoundCertCallbackWithResult(int err,
74 base::Time expiration_time,
75 const std::string& private_key,
76 const std::string& cert);
77
78 private:
79 GetCertCallback callback_;
80 std::string server_identifier_;
81 int cert_count_;
82};
83
84int MockServerBoundCertStoreWithAsyncGet::GetServerBoundCert(
85 const std::string& server_identifier,
86 base::Time* expiration_time,
87 std::string* private_key_result,
88 std::string* cert_result,
89 const GetCertCallback& callback) {
90 server_identifier_ = server_identifier;
91 callback_ = callback;
92 // Reset the cert count, it'll get incremented in either SetServerBoundCert or
93 // CallGetServerBoundCertCallbackWithResult.
94 cert_count_ = 0;
95 // Do nothing else: the results to be provided will be specified through
96 // CallGetServerBoundCertCallbackWithResult.
97 return ERR_IO_PENDING;
98}
99
100void
101MockServerBoundCertStoreWithAsyncGet::CallGetServerBoundCertCallbackWithResult(
102 int err,
103 base::Time expiration_time,
104 const std::string& private_key,
105 const std::string& cert) {
106 if (err == OK)
107 cert_count_ = 1;
108 callback_.Run(err, server_identifier_, expiration_time, private_key, cert);
109}
110
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000111TEST_F(ServerBoundCertServiceTest, GetDomainForHost) {
112 EXPECT_EQ("google.com",
113 ServerBoundCertService::GetDomainForHost("google.com"));
114 EXPECT_EQ("google.com",
115 ServerBoundCertService::GetDomainForHost("www.google.com"));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100116 EXPECT_EQ("foo.appspot.com",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000117 ServerBoundCertService::GetDomainForHost("foo.appspot.com"));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100118 EXPECT_EQ("bar.appspot.com",
119 ServerBoundCertService::GetDomainForHost("foo.bar.appspot.com"));
120 EXPECT_EQ("appspot.com",
121 ServerBoundCertService::GetDomainForHost("appspot.com"));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000122 EXPECT_EQ("google.com",
123 ServerBoundCertService::GetDomainForHost("www.mail.google.com"));
124 EXPECT_EQ("goto",
125 ServerBoundCertService::GetDomainForHost("goto"));
126 EXPECT_EQ("127.0.0.1",
127 ServerBoundCertService::GetDomainForHost("127.0.0.1"));
128}
129
130// See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned.
131#if !defined(USE_OPENSSL)
132
133TEST_F(ServerBoundCertServiceTest, CacheHit) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100134 std::string host("encrypted.google.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000135
136 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000137 TestCompletionCallback callback;
138 ServerBoundCertService::RequestHandle request_handle;
139
140 // Asynchronous completion.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000141 std::string private_key_info1, der_cert1;
142 EXPECT_EQ(0, service_->cert_count());
143 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100144 host, &private_key_info1, &der_cert1,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000145 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());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000151 EXPECT_FALSE(private_key_info1.empty());
152 EXPECT_FALSE(der_cert1.empty());
153 EXPECT_FALSE(request_handle.is_active());
154
155 // Synchronous completion.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000156 std::string private_key_info2, der_cert2;
157 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100158 host, &private_key_info2, &der_cert2,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000159 callback.callback(), &request_handle);
160 EXPECT_FALSE(request_handle.is_active());
161 EXPECT_EQ(OK, error);
162 EXPECT_EQ(1, service_->cert_count());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000163 EXPECT_EQ(private_key_info1, private_key_info2);
164 EXPECT_EQ(der_cert1, der_cert2);
165
166 EXPECT_EQ(2u, service_->requests());
167 EXPECT_EQ(1u, service_->cert_store_hits());
168 EXPECT_EQ(0u, service_->inflight_joins());
169}
170
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000171TEST_F(ServerBoundCertServiceTest, StoreCerts) {
172 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000173 TestCompletionCallback callback;
174 ServerBoundCertService::RequestHandle request_handle;
175
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100176 std::string host1("encrypted.google.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000177 std::string private_key_info1, der_cert1;
178 EXPECT_EQ(0, service_->cert_count());
179 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100180 host1, &private_key_info1, &der_cert1,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000181 callback.callback(), &request_handle);
182 EXPECT_EQ(ERR_IO_PENDING, error);
183 EXPECT_TRUE(request_handle.is_active());
184 error = callback.WaitForResult();
185 EXPECT_EQ(OK, error);
186 EXPECT_EQ(1, service_->cert_count());
187
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100188 std::string host2("www.verisign.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000189 std::string private_key_info2, der_cert2;
190 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100191 host2, &private_key_info2, &der_cert2,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000192 callback.callback(), &request_handle);
193 EXPECT_EQ(ERR_IO_PENDING, error);
194 EXPECT_TRUE(request_handle.is_active());
195 error = callback.WaitForResult();
196 EXPECT_EQ(OK, error);
197 EXPECT_EQ(2, service_->cert_count());
198
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100199 std::string host3("www.twitter.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000200 std::string private_key_info3, der_cert3;
201 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100202 host3, &private_key_info3, &der_cert3,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000203 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(3, service_->cert_count());
209
210 EXPECT_NE(private_key_info1, private_key_info2);
211 EXPECT_NE(der_cert1, der_cert2);
212 EXPECT_NE(private_key_info1, private_key_info3);
213 EXPECT_NE(der_cert1, der_cert3);
214 EXPECT_NE(private_key_info2, private_key_info3);
215 EXPECT_NE(der_cert2, der_cert3);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000216}
217
218// Tests an inflight join.
219TEST_F(ServerBoundCertServiceTest, InflightJoin) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100220 std::string host("encrypted.google.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000221 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000222
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000223 std::string private_key_info1, der_cert1;
224 TestCompletionCallback callback1;
225 ServerBoundCertService::RequestHandle request_handle1;
226
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000227 std::string private_key_info2, der_cert2;
228 TestCompletionCallback callback2;
229 ServerBoundCertService::RequestHandle request_handle2;
230
231 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100232 host, &private_key_info1, &der_cert1,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000233 callback1.callback(), &request_handle1);
234 EXPECT_EQ(ERR_IO_PENDING, error);
235 EXPECT_TRUE(request_handle1.is_active());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100236 // Should join with the original request.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000237 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100238 host, &private_key_info2, &der_cert2,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000239 callback2.callback(), &request_handle2);
240 EXPECT_EQ(ERR_IO_PENDING, error);
241 EXPECT_TRUE(request_handle2.is_active());
242
243 error = callback1.WaitForResult();
244 EXPECT_EQ(OK, error);
245 error = callback2.WaitForResult();
246 EXPECT_EQ(OK, error);
247
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000248 EXPECT_EQ(2u, service_->requests());
249 EXPECT_EQ(0u, service_->cert_store_hits());
250 EXPECT_EQ(1u, service_->inflight_joins());
251}
252
253TEST_F(ServerBoundCertServiceTest, ExtractValuesFromBytesEC) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100254 std::string host("encrypted.google.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000255 std::string private_key_info, der_cert;
256 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000257 TestCompletionCallback callback;
258 ServerBoundCertService::RequestHandle request_handle;
259
260 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100261 host, &private_key_info, &der_cert, callback.callback(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000262 &request_handle);
263 EXPECT_EQ(ERR_IO_PENDING, error);
264 EXPECT_TRUE(request_handle.is_active());
265 error = callback.WaitForResult();
266 EXPECT_EQ(OK, error);
267
268 base::StringPiece spki_piece;
269 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_cert, &spki_piece));
270 std::vector<uint8> spki(
271 spki_piece.data(),
272 spki_piece.data() + spki_piece.size());
273
274 // Check that we can retrieve the key from the bytes.
275 std::vector<uint8> key_vec(private_key_info.begin(), private_key_info.end());
276 scoped_ptr<crypto::ECPrivateKey> private_key(
277 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
278 ServerBoundCertService::kEPKIPassword, key_vec, spki));
279 EXPECT_TRUE(private_key != NULL);
280
281 // Check that we can retrieve the cert from the bytes.
282 scoped_refptr<X509Certificate> x509cert(
283 X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size()));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100284 EXPECT_TRUE(x509cert.get() != NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000285}
286
287// Tests that the callback of a canceled request is never made.
288TEST_F(ServerBoundCertServiceTest, CancelRequest) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100289 std::string host("encrypted.google.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000290 std::string private_key_info, der_cert;
291 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000292 ServerBoundCertService::RequestHandle request_handle;
293
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100294 error = service_->GetDomainBoundCert(host,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000295 &private_key_info,
296 &der_cert,
297 base::Bind(&FailTest),
298 &request_handle);
299 EXPECT_EQ(ERR_IO_PENDING, error);
300 EXPECT_TRUE(request_handle.is_active());
301 request_handle.Cancel();
302 EXPECT_FALSE(request_handle.is_active());
303
304 // Wait for generation to finish.
305 sequenced_worker_pool_->FlushForTesting();
306 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
307 // ServerBoundCertService.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100308 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000309
310 // Even though the original request was cancelled, the service will still
311 // store the result, it just doesn't call the callback.
312 EXPECT_EQ(1, service_->cert_count());
313}
314
315// Tests that destructing the RequestHandle cancels the request.
316TEST_F(ServerBoundCertServiceTest, CancelRequestByHandleDestruction) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100317 std::string host("encrypted.google.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000318 std::string private_key_info, der_cert;
319 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000320 {
321 ServerBoundCertService::RequestHandle request_handle;
322
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100323 error = service_->GetDomainBoundCert(host,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000324 &private_key_info,
325 &der_cert,
326 base::Bind(&FailTest),
327 &request_handle);
328 EXPECT_EQ(ERR_IO_PENDING, error);
329 EXPECT_TRUE(request_handle.is_active());
330 }
331
332 // Wait for generation to finish.
333 sequenced_worker_pool_->FlushForTesting();
334 // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
335 // ServerBoundCertService.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100336 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000337
338 // Even though the original request was cancelled, the service will still
339 // store the result, it just doesn't call the callback.
340 EXPECT_EQ(1, service_->cert_count());
341}
342
343TEST_F(ServerBoundCertServiceTest, DestructionWithPendingRequest) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100344 std::string host("encrypted.google.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000345 std::string private_key_info, der_cert;
346 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000347 ServerBoundCertService::RequestHandle request_handle;
348
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100349 error = service_->GetDomainBoundCert(host,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100350 &private_key_info,
351 &der_cert,
352 base::Bind(&FailTest),
353 &request_handle);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000354 EXPECT_EQ(ERR_IO_PENDING, error);
355 EXPECT_TRUE(request_handle.is_active());
356
357 // Cancel request and destroy the ServerBoundCertService.
358 request_handle.Cancel();
359 service_.reset();
360
361 // Wait for generation to finish.
362 sequenced_worker_pool_->FlushForTesting();
363 // ServerBoundCertServiceWorker should not post anything back to the
364 // non-existant ServerBoundCertService, but run the loop just to be sure it
365 // doesn't.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100366 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000367
368 // If we got here without crashing or a valgrind error, it worked.
369}
370
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100371// Tests that shutting down the sequenced worker pool and then making new
372// requests gracefully fails.
373// This is a regression test for http://crbug.com/236387
374TEST_F(ServerBoundCertServiceTest, RequestAfterPoolShutdown) {
375 // Shutdown the pool immediately.
376 sequenced_worker_pool_->Shutdown();
377 sequenced_worker_pool_ = NULL;
378
379 // Ensure any shutdown code is processed.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100380 base::MessageLoop::current()->RunUntilIdle();
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100381
382 // Make a request that will force synchronous completion.
383 std::string host("encrypted.google.com");
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100384 std::string private_key_info, der_cert;
385 int error;
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100386 ServerBoundCertService::RequestHandle request_handle;
387
388 error = service_->GetDomainBoundCert(host,
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100389 &private_key_info,
390 &der_cert,
391 base::Bind(&FailTest),
392 &request_handle);
393 // If we got here without crashing or a valgrind error, it worked.
394 ASSERT_EQ(ERR_INSUFFICIENT_RESOURCES, error);
395 EXPECT_FALSE(request_handle.is_active());
396}
397
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000398// Tests that simultaneous creation of different certs works.
399TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) {
400 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000401
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100402 std::string host1("encrypted.google.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000403 std::string private_key_info1, der_cert1;
404 TestCompletionCallback callback1;
405 ServerBoundCertService::RequestHandle request_handle1;
406
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100407 std::string host2("foo.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000408 std::string private_key_info2, der_cert2;
409 TestCompletionCallback callback2;
410 ServerBoundCertService::RequestHandle request_handle2;
411
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100412 std::string host3("bar.com");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000413 std::string private_key_info3, der_cert3;
414 TestCompletionCallback callback3;
415 ServerBoundCertService::RequestHandle request_handle3;
416
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100417 error = service_->GetDomainBoundCert(host1,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000418 &private_key_info1,
419 &der_cert1,
420 callback1.callback(),
421 &request_handle1);
422 EXPECT_EQ(ERR_IO_PENDING, error);
423 EXPECT_TRUE(request_handle1.is_active());
424
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100425 error = service_->GetDomainBoundCert(host2,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000426 &private_key_info2,
427 &der_cert2,
428 callback2.callback(),
429 &request_handle2);
430 EXPECT_EQ(ERR_IO_PENDING, error);
431 EXPECT_TRUE(request_handle2.is_active());
432
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100433 error = service_->GetDomainBoundCert(host3,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000434 &private_key_info3,
435 &der_cert3,
436 callback3.callback(),
437 &request_handle3);
438 EXPECT_EQ(ERR_IO_PENDING, error);
439 EXPECT_TRUE(request_handle3.is_active());
440
441 error = callback1.WaitForResult();
442 EXPECT_EQ(OK, error);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000443 EXPECT_FALSE(private_key_info1.empty());
444 EXPECT_FALSE(der_cert1.empty());
445
446 error = callback2.WaitForResult();
447 EXPECT_EQ(OK, error);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000448 EXPECT_FALSE(private_key_info2.empty());
449 EXPECT_FALSE(der_cert2.empty());
450
451 error = callback3.WaitForResult();
452 EXPECT_EQ(OK, error);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000453 EXPECT_FALSE(private_key_info3.empty());
454 EXPECT_FALSE(der_cert3.empty());
455
456 EXPECT_NE(private_key_info1, private_key_info2);
457 EXPECT_NE(der_cert1, der_cert2);
458
459 EXPECT_NE(private_key_info1, private_key_info3);
460 EXPECT_NE(der_cert1, der_cert3);
461
462 EXPECT_NE(private_key_info2, private_key_info3);
463 EXPECT_NE(der_cert2, der_cert3);
464
465 EXPECT_EQ(3, service_->cert_count());
466}
467
468TEST_F(ServerBoundCertServiceTest, Expiration) {
469 ServerBoundCertStore* store = service_->GetCertStore();
470 base::Time now = base::Time::Now();
471 store->SetServerBoundCert("good",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000472 now,
473 now + base::TimeDelta::FromDays(1),
474 "a",
475 "b");
476 store->SetServerBoundCert("expired",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000477 now - base::TimeDelta::FromDays(2),
478 now - base::TimeDelta::FromDays(1),
479 "c",
480 "d");
481 EXPECT_EQ(2, service_->cert_count());
482
483 int error;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000484 TestCompletionCallback callback;
485 ServerBoundCertService::RequestHandle request_handle;
486
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100487 // Cert is valid - synchronous completion.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000488 std::string private_key_info1, der_cert1;
489 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100490 "good", &private_key_info1, &der_cert1,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000491 callback.callback(), &request_handle);
492 EXPECT_EQ(OK, error);
493 EXPECT_FALSE(request_handle.is_active());
494 EXPECT_EQ(2, service_->cert_count());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000495 EXPECT_STREQ("a", private_key_info1.c_str());
496 EXPECT_STREQ("b", der_cert1.c_str());
497
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100498 // Expired cert is valid as well - synchronous completion.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000499 std::string private_key_info2, der_cert2;
500 error = service_->GetDomainBoundCert(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100501 "expired", &private_key_info2, &der_cert2,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000502 callback.callback(), &request_handle);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000503 EXPECT_EQ(OK, error);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100504 EXPECT_FALSE(request_handle.is_active());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000505 EXPECT_EQ(2, service_->cert_count());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100506 EXPECT_STREQ("c", private_key_info2.c_str());
507 EXPECT_STREQ("d", der_cert2.c_str());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000508}
509
Ben Murdochbb1529c2013-08-08 10:24:53 +0100510TEST_F(ServerBoundCertServiceTest, AsyncStoreGetNoCertsInStore) {
511 MockServerBoundCertStoreWithAsyncGet* mock_store =
512 new MockServerBoundCertStoreWithAsyncGet();
513 service_ = scoped_ptr<ServerBoundCertService>(
514 new ServerBoundCertService(mock_store, sequenced_worker_pool_));
515
516 std::string host("encrypted.google.com");
517
518 int error;
519 TestCompletionCallback callback;
520 ServerBoundCertService::RequestHandle request_handle;
521
522 // Asynchronous completion with no certs in the store.
523 std::string private_key_info, der_cert;
524 EXPECT_EQ(0, service_->cert_count());
525 error = service_->GetDomainBoundCert(
526 host, &private_key_info, &der_cert, callback.callback(), &request_handle);
527 EXPECT_EQ(ERR_IO_PENDING, error);
528 EXPECT_TRUE(request_handle.is_active());
529
530 mock_store->CallGetServerBoundCertCallbackWithResult(
531 ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string());
532
533 error = callback.WaitForResult();
534 EXPECT_EQ(OK, error);
535 EXPECT_EQ(1, service_->cert_count());
536 EXPECT_FALSE(private_key_info.empty());
537 EXPECT_FALSE(der_cert.empty());
538 EXPECT_FALSE(request_handle.is_active());
539}
540
541TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOneCertInStore) {
542 MockServerBoundCertStoreWithAsyncGet* mock_store =
543 new MockServerBoundCertStoreWithAsyncGet();
544 service_ = scoped_ptr<ServerBoundCertService>(
545 new ServerBoundCertService(mock_store, sequenced_worker_pool_));
546
547 std::string host("encrypted.google.com");
548
549 int error;
550 TestCompletionCallback callback;
551 ServerBoundCertService::RequestHandle request_handle;
552
553 // Asynchronous completion with a cert in the store.
554 std::string private_key_info, der_cert;
555 EXPECT_EQ(0, service_->cert_count());
556 error = service_->GetDomainBoundCert(
557 host, &private_key_info, &der_cert, callback.callback(), &request_handle);
558 EXPECT_EQ(ERR_IO_PENDING, error);
559 EXPECT_TRUE(request_handle.is_active());
560
561 mock_store->CallGetServerBoundCertCallbackWithResult(
562 OK, base::Time(), "ab", "cd");
563
564 error = callback.WaitForResult();
565 EXPECT_EQ(OK, error);
566 EXPECT_EQ(1, service_->cert_count());
567 EXPECT_EQ(1u, service_->requests());
568 EXPECT_EQ(1u, service_->cert_store_hits());
569 // Because the cert was found in the store, no new workers should have been
570 // created.
571 EXPECT_EQ(0u, service_->workers_created());
572 EXPECT_STREQ("ab", private_key_info.c_str());
573 EXPECT_STREQ("cd", der_cert.c_str());
574 EXPECT_FALSE(request_handle.is_active());
575}
576
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000577#endif // !defined(USE_OPENSSL)
578
579} // namespace
580
581} // namespace net