| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "net/base/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" | |
| 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" | |
| 21 | |
| 22 namespace net { | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 void FailTest(int /* result */) { | |
| 27 FAIL(); | |
| 28 } | |
| 29 | |
| 30 class ServerBoundCertServiceTest : public testing::Test { | |
| 31 protected: | |
| 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_)); | |
| 37 } | |
| 38 | |
| 39 virtual void TearDown() OVERRIDE { | |
| 40 sequenced_worker_pool_->Shutdown(); | |
| 41 } | |
| 42 | |
| 43 scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool_; | |
| 44 scoped_ptr<ServerBoundCertService> service_; | |
| 45 }; | |
| 46 | |
| 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")); | |
| 59 EXPECT_EQ("goto", | |
| 60 ServerBoundCertService::GetDomainForHost("goto")); | |
| 61 EXPECT_EQ("127.0.0.1", | |
| 62 ServerBoundCertService::GetDomainForHost("127.0.0.1")); | |
| 63 } | |
| 64 | |
| 65 // See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned. | |
| 66 #if !defined(USE_OPENSSL) | |
| 67 | |
| 68 TEST_F(ServerBoundCertServiceTest, CacheHit) { | |
| 69 std::string origin("https://encrypted.google.com:443"); | |
| 70 | |
| 71 int error; | |
| 72 std::vector<uint8> types; | |
| 73 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 74 TestCompletionCallback callback; | |
| 75 ServerBoundCertService::RequestHandle request_handle; | |
| 76 | |
| 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(); | |
| 87 EXPECT_EQ(OK, error); | |
| 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()); | |
| 93 | |
| 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); | |
| 106 | |
| 107 EXPECT_EQ(2u, service_->requests()); | |
| 108 EXPECT_EQ(1u, service_->cert_store_hits()); | |
| 109 EXPECT_EQ(0u, service_->inflight_joins()); | |
| 110 } | |
| 111 | |
| 112 TEST_F(ServerBoundCertServiceTest, UnsupportedTypes) { | |
| 113 std::string origin("https://encrypted.google.com:443"); | |
| 114 | |
| 115 int error; | |
| 116 std::vector<uint8> types; | |
| 117 TestCompletionCallback callback; | |
| 118 ServerBoundCertService::RequestHandle request_handle; | |
| 119 | |
| 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()); | |
| 128 | |
| 129 // No supported types in requested_types. | |
| 130 types.push_back(CLIENT_CERT_RSA_SIGN); | |
| 131 types.push_back(2); | |
| 132 types.push_back(3); | |
| 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()); | |
| 138 | |
| 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()); | |
| 154 | |
| 155 // Now that the cert is created, doing requests for unsupported types | |
| 156 // shouldn't affect the created cert. | |
| 157 // Empty requested_types. | |
| 158 types.clear(); | |
| 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()); | |
| 166 | |
| 167 // No supported types in requested_types. | |
| 168 types.push_back(CLIENT_CERT_RSA_SIGN); | |
| 169 types.push_back(2); | |
| 170 types.push_back(3); | |
| 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()); | |
| 176 | |
| 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); | |
| 188 } | |
| 189 | |
| 190 TEST_F(ServerBoundCertServiceTest, StoreCerts) { | |
| 191 int error; | |
| 192 std::vector<uint8> types; | |
| 193 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 194 TestCompletionCallback callback; | |
| 195 ServerBoundCertService::RequestHandle request_handle; | |
| 196 | |
| 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()); | |
| 209 | |
| 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()); | |
| 221 | |
| 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()); | |
| 233 | |
| 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); | |
| 243 } | |
| 244 | |
| 245 // Tests an inflight join. | |
| 246 TEST_F(ServerBoundCertServiceTest, InflightJoin) { | |
| 247 std::string origin("https://encrypted.google.com:443"); | |
| 248 int error; | |
| 249 std::vector<uint8> types; | |
| 250 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 251 | |
| 252 SSLClientCertType type1; | |
| 253 std::string private_key_info1, der_cert1; | |
| 254 TestCompletionCallback callback1; | |
| 255 ServerBoundCertService::RequestHandle request_handle1; | |
| 256 | |
| 257 SSLClientCertType type2; | |
| 258 std::string private_key_info2, der_cert2; | |
| 259 TestCompletionCallback callback2; | |
| 260 ServerBoundCertService::RequestHandle request_handle2; | |
| 261 | |
| 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 | |
| 268 // original request. | |
| 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()); | |
| 275 | |
| 276 error = callback1.WaitForResult(); | |
| 277 EXPECT_EQ(OK, error); | |
| 278 error = callback2.WaitForResult(); | |
| 279 EXPECT_EQ(OK, error); | |
| 280 | |
| 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()); | |
| 286 } | |
| 287 | |
| 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; | |
| 292 int error; | |
| 293 std::vector<uint8> types; | |
| 294 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 295 TestCompletionCallback callback; | |
| 296 ServerBoundCertService::RequestHandle request_handle; | |
| 297 | |
| 298 error = service_->GetDomainBoundCert( | |
| 299 origin, types, &type, &private_key_info, &der_cert, callback.callback(), | |
| 300 &request_handle); | |
| 301 EXPECT_EQ(ERR_IO_PENDING, error); | |
| 302 EXPECT_TRUE(request_handle.is_active()); | |
| 303 error = callback.WaitForResult(); | |
| 304 EXPECT_EQ(OK, error); | |
| 305 | |
| 306 base::StringPiece spki_piece; | |
| 307 ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_cert, &spki_piece)); | |
| 308 std::vector<uint8> spki( | |
| 309 spki_piece.data(), | |
| 310 spki_piece.data() + spki_piece.size()); | |
| 311 | |
| 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); | |
| 318 | |
| 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); | |
| 323 } | |
| 324 | |
| 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; | |
| 330 int error; | |
| 331 std::vector<uint8> types; | |
| 332 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 333 ServerBoundCertService::RequestHandle request_handle; | |
| 334 | |
| 335 error = service_->GetDomainBoundCert(origin, | |
| 336 types, | |
| 337 &type, | |
| 338 &private_key_info, | |
| 339 &der_cert, | |
| 340 base::Bind(&FailTest), | |
| 341 &request_handle); | |
| 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()); | |
| 346 | |
| 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(); | |
| 352 | |
| 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()); | |
| 356 } | |
| 357 | |
| 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; | |
| 363 int error; | |
| 364 std::vector<uint8> types; | |
| 365 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 366 { | |
| 367 ServerBoundCertService::RequestHandle request_handle; | |
| 368 | |
| 369 error = service_->GetDomainBoundCert(origin, | |
| 370 types, | |
| 371 &type, | |
| 372 &private_key_info, | |
| 373 &der_cert, | |
| 374 base::Bind(&FailTest), | |
| 375 &request_handle); | |
| 376 EXPECT_EQ(ERR_IO_PENDING, error); | |
| 377 EXPECT_TRUE(request_handle.is_active()); | |
| 378 } | |
| 379 | |
| 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(); | |
| 385 | |
| 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()); | |
| 389 } | |
| 390 | |
| 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; | |
| 395 int error; | |
| 396 std::vector<uint8> types; | |
| 397 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 398 ServerBoundCertService::RequestHandle request_handle; | |
| 399 | |
| 400 error = service_->GetDomainBoundCert(origin, | |
| 401 types, | |
| 402 &type, | |
| 403 &private_key_info, | |
| 404 &der_cert, | |
| 405 base::Bind(&FailTest), | |
| 406 &request_handle); | |
| 407 EXPECT_EQ(ERR_IO_PENDING, error); | |
| 408 EXPECT_TRUE(request_handle.is_active()); | |
| 409 | |
| 410 // Cancel request and destroy the ServerBoundCertService. | |
| 411 request_handle.Cancel(); | |
| 412 service_.reset(); | |
| 413 | |
| 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 | |
| 418 // doesn't. | |
| 419 MessageLoop::current()->RunUntilIdle(); | |
| 420 | |
| 421 // If we got here without crashing or a valgrind error, it worked. | |
| 422 } | |
| 423 | |
| 424 // Tests that simultaneous creation of different certs works. | |
| 425 TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) { | |
| 426 int error; | |
| 427 std::vector<uint8> types; | |
| 428 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 429 | |
| 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; | |
| 435 | |
| 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; | |
| 441 | |
| 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; | |
| 447 | |
| 448 error = service_->GetDomainBoundCert(origin1, | |
| 449 types, | |
| 450 &type1, | |
| 451 &private_key_info1, | |
| 452 &der_cert1, | |
| 453 callback1.callback(), | |
| 454 &request_handle1); | |
| 455 EXPECT_EQ(ERR_IO_PENDING, error); | |
| 456 EXPECT_TRUE(request_handle1.is_active()); | |
| 457 | |
| 458 error = service_->GetDomainBoundCert(origin2, | |
| 459 types, | |
| 460 &type2, | |
| 461 &private_key_info2, | |
| 462 &der_cert2, | |
| 463 callback2.callback(), | |
| 464 &request_handle2); | |
| 465 EXPECT_EQ(ERR_IO_PENDING, error); | |
| 466 EXPECT_TRUE(request_handle2.is_active()); | |
| 467 | |
| 468 error = service_->GetDomainBoundCert(origin3, | |
| 469 types, | |
| 470 &type3, | |
| 471 &private_key_info3, | |
| 472 &der_cert3, | |
| 473 callback3.callback(), | |
| 474 &request_handle3); | |
| 475 EXPECT_EQ(ERR_IO_PENDING, error); | |
| 476 EXPECT_TRUE(request_handle3.is_active()); | |
| 477 | |
| 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()); | |
| 483 | |
| 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()); | |
| 489 | |
| 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()); | |
| 495 | |
| 496 EXPECT_NE(private_key_info1, private_key_info2); | |
| 497 EXPECT_NE(der_cert1, der_cert2); | |
| 498 | |
| 499 EXPECT_NE(private_key_info1, private_key_info3); | |
| 500 EXPECT_NE(der_cert1, der_cert3); | |
| 501 | |
| 502 EXPECT_NE(private_key_info2, private_key_info3); | |
| 503 EXPECT_NE(der_cert2, der_cert3); | |
| 504 | |
| 505 EXPECT_EQ(3, service_->cert_count()); | |
| 506 } | |
| 507 | |
| 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, | |
| 513 now, | |
| 514 now + base::TimeDelta::FromDays(1), | |
| 515 "a", | |
| 516 "b"); | |
| 517 store->SetServerBoundCert("expired", | |
| 518 CLIENT_CERT_ECDSA_SIGN, | |
| 519 now - base::TimeDelta::FromDays(2), | |
| 520 now - base::TimeDelta::FromDays(1), | |
| 521 "c", | |
| 522 "d"); | |
| 523 EXPECT_EQ(2, service_->cert_count()); | |
| 524 | |
| 525 int error; | |
| 526 std::vector<uint8> types; | |
| 527 types.push_back(CLIENT_CERT_ECDSA_SIGN); | |
| 528 TestCompletionCallback callback; | |
| 529 ServerBoundCertService::RequestHandle request_handle; | |
| 530 | |
| 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()); | |
| 543 | |
| 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()); | |
| 558 } | |
| 559 | |
| 560 #endif // !defined(USE_OPENSSL) | |
| 561 | |
| 562 } // namespace | |
| 563 | |
| 564 } // namespace net | |
| OLD | NEW |