1 // Copyright 2015 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 "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h"
10 #include "base/stl_util.h"
11 #include "base/test/test_mock_time_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "chrome/browser/chromeos/certificate_provider/certificate_provider.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/test_data_directory.h"
16 #include "net/ssl/client_key_store.h"
17 #include "net/test/cert_test_util.h"
18 #include "testing/gtest/include/gtest/gtest.h"
24 const char kExtension1
[] = "extension1";
25 const char kExtension2
[] = "extension2";
27 void ExpectEmptySignatureAndStoreError(net::Error
* out_error
,
29 const std::vector
<uint8_t>& signature
) {
30 EXPECT_TRUE(signature
.empty());
34 void ExpectOKAndStoreSignature(std::vector
<uint8_t>* out_signature
,
36 const std::vector
<uint8_t>& signature
) {
37 EXPECT_EQ(net::OK
, error
);
38 *out_signature
= signature
;
41 void StoreCertificates(net::CertificateList
* out_certs
,
42 const net::CertificateList
& certs
) {
47 certificate_provider::CertificateInfo
CreateCertInfo(
48 const std::string
& cert_filename
) {
49 certificate_provider::CertificateInfo cert_info
;
50 cert_info
.certificate
=
51 net::ImportCertFromFile(net::GetTestCertsDirectory(), cert_filename
);
52 EXPECT_NE(nullptr, cert_info
.certificate
) << "Could not load "
54 cert_info
.type
= net::SSLPrivateKey::Type::RSA
;
55 cert_info
.supported_hashes
.push_back(net::SSLPrivateKey::Hash::SHA256
);
56 cert_info
.max_signature_length_in_bytes
= 123;
61 bool IsKeyEqualToCertInfo(const certificate_provider::CertificateInfo
& info
,
62 net::SSLPrivateKey
* key
) {
63 const net::SSLPrivateKey::Hash hashes
[] = {
64 net::SSLPrivateKey::Hash::MD5_SHA1
, net::SSLPrivateKey::Hash::SHA1
,
65 net::SSLPrivateKey::Hash::SHA256
, net::SSLPrivateKey::Hash::SHA384
,
66 net::SSLPrivateKey::Hash::SHA512
};
68 for (const net::SSLPrivateKey::Hash hash
: hashes
) {
69 if (ContainsValue(info
.supported_hashes
, hash
) != key
->SupportsHash(hash
)) {
74 return key
->GetType() == info
.type
&&
75 key
->GetMaxSignatureLengthInBytes() ==
76 info
.max_signature_length_in_bytes
;
79 class TestDelegate
: public CertificateProviderService::Delegate
{
81 enum class RequestType
{ NONE
, SIGN
, GET_CERTIFICATES
};
85 std::vector
<std::string
> CertificateProviderExtensions() override
{
86 return std::vector
<std::string
>(provider_extensions_
.begin(),
87 provider_extensions_
.end());
90 void BroadcastCertificateRequest(int cert_request_id
) override
{
91 EXPECT_EQ(expected_request_type_
, RequestType::GET_CERTIFICATES
);
92 last_cert_request_id_
= cert_request_id
;
93 expected_request_type_
= RequestType::NONE
;
96 bool DispatchSignRequestToExtension(
97 const std::string
& extension_id
,
99 net::SSLPrivateKey::Hash hash
,
100 const scoped_refptr
<net::X509Certificate
>& certificate
,
101 const std::string
& input
) override
{
102 EXPECT_EQ(expected_request_type_
, RequestType::SIGN
);
103 last_sign_request_id_
= sign_request_id
;
104 last_extension_id_
= extension_id
;
105 last_certificate_
= certificate
;
106 expected_request_type_
= RequestType::NONE
;
110 // Prepares this delegate for the dispatch of a request of type
111 // |expected_request_type|. The first request of the right type will cause
112 // |expected_request_type_| to be reset to NONE. The request's arguments will
113 // be stored in |last_*_request_id_| and |last_extension_id_|. Any additional
114 // request and any request of the wrong type will fail the test.
115 void ClearAndExpectRequest(RequestType expected_request_type
) {
116 last_extension_id_
.clear();
117 last_sign_request_id_
= -1;
118 last_cert_request_id_
= -1;
119 last_certificate_
= nullptr;
120 expected_request_type_
= expected_request_type
;
123 int last_sign_request_id_
= -1;
124 int last_cert_request_id_
= -1;
125 scoped_refptr
<net::X509Certificate
> last_certificate_
;
126 std::string last_extension_id_
;
127 std::set
<std::string
> provider_extensions_
;
128 RequestType expected_request_type_
= RequestType::NONE
;
131 DISALLOW_COPY_AND_ASSIGN(TestDelegate
);
136 class CertificateProviderServiceTest
: public testing::Test
{
138 CertificateProviderServiceTest()
139 : task_runner_(new base::TestMockTimeTaskRunner()),
140 task_runner_handle_(task_runner_
),
141 client_key_store_(net::ClientKeyStore::GetInstance()),
142 service_(new CertificateProviderService()),
143 cert_info1_(CreateCertInfo("client_1.pem")),
144 cert_info2_(CreateCertInfo("client_2.pem")) {
145 scoped_ptr
<TestDelegate
> test_delegate(new TestDelegate
);
146 test_delegate_
= test_delegate
.get();
147 service_
->SetDelegate(test_delegate
.Pass());
149 certificate_provider_
= service_
->CreateCertificateProvider();
150 EXPECT_TRUE(certificate_provider_
);
152 test_delegate_
->provider_extensions_
.insert(kExtension1
);
155 // Triggers a GetCertificates request and returns the request id. Assumes that
156 // at least one extension is registered as a certificate provider.
157 int RequestCertificatesFromExtensions(net::CertificateList
* certs
) {
158 test_delegate_
->ClearAndExpectRequest(
159 TestDelegate::RequestType::GET_CERTIFICATES
);
161 certificate_provider_
->GetCertificates(
162 base::Bind(&StoreCertificates
, certs
));
164 task_runner_
->RunUntilIdle();
165 EXPECT_EQ(TestDelegate::RequestType::NONE
,
166 test_delegate_
->expected_request_type_
);
167 return test_delegate_
->last_cert_request_id_
;
170 // Provides |cert_info1_| through kExtension1.
171 void ProvideDefaultCert() {
172 const int cert_request_id
= RequestCertificatesFromExtensions(nullptr);
173 SetCertificateProvidedByExtension(kExtension1
, cert_request_id
,
175 task_runner_
->RunUntilIdle();
178 // Like service_->SetCertificatesProvidedByExtension but taking a single
179 // CertificateInfo instead of a list.
180 void SetCertificateProvidedByExtension(
181 const std::string
& extension_id
,
183 const certificate_provider::CertificateInfo
& cert_info
) {
184 certificate_provider::CertificateInfoList infos
;
185 infos
.push_back(cert_info
);
186 service_
->SetCertificatesProvidedByExtension(extension_id
, cert_request_id
,
190 bool CheckLookUpCertificate(
191 const certificate_provider::CertificateInfo
& cert_info
,
192 bool expected_is_certificate_known
,
193 bool expected_is_currently_provided
,
194 const std::string
& expected_extension_id
) {
195 bool is_currently_provided
= !expected_is_currently_provided
;
196 std::string extension_id
;
197 if (expected_is_certificate_known
!=
198 service_
->LookUpCertificate(*cert_info
.certificate
,
199 &is_currently_provided
, &extension_id
)) {
200 LOG(ERROR
) << "Wrong return value.";
203 if (expected_is_currently_provided
!= is_currently_provided
) {
204 LOG(ERROR
) << "Wrong |is_currently_provided|.";
207 if (expected_extension_id
!= extension_id
) {
208 LOG(ERROR
) << "Wrong extension id. Got " << extension_id
;
214 scoped_refptr
<base::TestMockTimeTaskRunner
> task_runner_
;
215 base::ThreadTaskRunnerHandle task_runner_handle_
;
216 TestDelegate
* test_delegate_
= nullptr;
217 net::ClientKeyStore
* const client_key_store_
;
218 scoped_ptr
<CertificateProvider
> certificate_provider_
;
219 scoped_ptr
<CertificateProviderService
> service_
;
220 const certificate_provider::CertificateInfo cert_info1_
;
221 const certificate_provider::CertificateInfo cert_info2_
;
224 DISALLOW_COPY_AND_ASSIGN(CertificateProviderServiceTest
);
227 TEST_F(CertificateProviderServiceTest
, GetCertificates
) {
228 test_delegate_
->provider_extensions_
.insert(kExtension2
);
230 net::CertificateList certs
;
231 const int cert_request_id
= RequestCertificatesFromExtensions(&certs
);
233 task_runner_
->RunUntilIdle();
234 // No certificates set until all registered extensions replied.
235 EXPECT_TRUE(certs
.empty());
237 SetCertificateProvidedByExtension(kExtension1
, cert_request_id
, cert_info1_
);
239 task_runner_
->RunUntilIdle();
240 // No certificates set until all registered extensions replied.
241 EXPECT_TRUE(certs
.empty());
243 SetCertificateProvidedByExtension(kExtension2
, cert_request_id
, cert_info2_
);
245 task_runner_
->RunUntilIdle();
246 EXPECT_EQ(2u, certs
.size());
248 // Verify that the ClientKeyStore returns key handles for the provide certs.
250 client_key_store_
->FetchClientCertPrivateKey(*cert_info1_
.certificate
));
252 client_key_store_
->FetchClientCertPrivateKey(*cert_info2_
.certificate
));
254 // Deregister the extensions as certificate providers. The next
255 // GetCertificates call must report an empty list of certs.
256 test_delegate_
->provider_extensions_
.clear();
258 // No request expected.
259 test_delegate_
->ClearAndExpectRequest(TestDelegate::RequestType::NONE
);
261 certificate_provider_
->GetCertificates(
262 base::Bind(&StoreCertificates
, &certs
));
264 task_runner_
->RunUntilIdle();
265 // As |certs| was not empty before, this ensures that StoreCertificates() was
267 EXPECT_TRUE(certs
.empty());
270 TEST_F(CertificateProviderServiceTest
, LookUpCertificate
) {
271 // Provide only |cert_info1_|.
273 const int cert_request_id
= RequestCertificatesFromExtensions(nullptr);
274 SetCertificateProvidedByExtension(kExtension1
, cert_request_id
,
276 task_runner_
->RunUntilIdle();
279 EXPECT_TRUE(CheckLookUpCertificate(cert_info1_
, true /* is known */,
280 true /* is currently provided */,
283 EXPECT_TRUE(CheckLookUpCertificate(cert_info2_
, false /* is not known */,
284 false /* is currently not provided */,
287 // Provide only |cert_info2_| from |kExtension2|.
288 test_delegate_
->provider_extensions_
.insert(kExtension2
);
290 const int cert_request_id
= RequestCertificatesFromExtensions(nullptr);
291 service_
->SetCertificatesProvidedByExtension(
292 kExtension1
, cert_request_id
,
293 certificate_provider::CertificateInfoList());
294 SetCertificateProvidedByExtension(kExtension2
, cert_request_id
,
296 task_runner_
->RunUntilIdle();
299 EXPECT_TRUE(CheckLookUpCertificate(cert_info1_
, true /* is known */,
300 false /* is currently not provided */,
303 EXPECT_TRUE(CheckLookUpCertificate(cert_info2_
, true /* is known */,
304 true /* is currently provided */,
307 // Deregister |kExtension2| as certificate provider and provide |cert_info1_|
308 // from |kExtension1|.
309 test_delegate_
->provider_extensions_
.erase(kExtension2
);
312 const int cert_request_id
= RequestCertificatesFromExtensions(nullptr);
313 SetCertificateProvidedByExtension(kExtension1
, cert_request_id
,
315 task_runner_
->RunUntilIdle();
318 EXPECT_TRUE(CheckLookUpCertificate(cert_info1_
, true /* is known */,
319 true /* is currently provided */,
322 EXPECT_TRUE(CheckLookUpCertificate(cert_info2_
, true /* is known */,
323 false /* is currently not provided */,
326 // Provide |cert_info2_| from |kExtension1|.
328 const int cert_request_id
= RequestCertificatesFromExtensions(nullptr);
329 SetCertificateProvidedByExtension(kExtension1
, cert_request_id
,
331 task_runner_
->RunUntilIdle();
335 bool is_currently_provided
= true;
336 std::string extension_id
;
337 // |cert_info1_.certificate| was provided before, so this must return true.
338 EXPECT_TRUE(service_
->LookUpCertificate(
339 *cert_info1_
.certificate
, &is_currently_provided
, &extension_id
));
340 EXPECT_FALSE(is_currently_provided
);
341 EXPECT_TRUE(extension_id
.empty());
345 bool is_currently_provided
= false;
346 std::string extension_id
;
347 EXPECT_TRUE(service_
->LookUpCertificate(
348 *cert_info2_
.certificate
, &is_currently_provided
, &extension_id
));
349 EXPECT_TRUE(is_currently_provided
);
350 EXPECT_EQ(kExtension1
, extension_id
);
353 EXPECT_TRUE(CheckLookUpCertificate(cert_info1_
, true /* is known */,
354 false /* is currently not provided */,
357 EXPECT_TRUE(CheckLookUpCertificate(cert_info2_
, true /* is known */,
358 true /* is currently provided */,
362 TEST_F(CertificateProviderServiceTest
, GetCertificatesTimeout
) {
363 test_delegate_
->provider_extensions_
.insert(kExtension2
);
365 net::CertificateList certs
;
366 const int cert_request_id
= RequestCertificatesFromExtensions(&certs
);
368 certificate_provider::CertificateInfoList infos
;
369 SetCertificateProvidedByExtension(kExtension1
, cert_request_id
, cert_info1_
);
371 task_runner_
->RunUntilIdle();
372 // No certificates set until all registered extensions replied or a timeout
374 EXPECT_TRUE(certs
.empty());
376 task_runner_
->FastForwardUntilNoTasksRemain();
377 // After the timeout, only extension1_'s certificates are returned.
378 // This verifies that the timeout delay is > 0 but not how long the delay is.
379 EXPECT_EQ(1u, certs
.size());
382 client_key_store_
->FetchClientCertPrivateKey(*cert_info1_
.certificate
));
385 TEST_F(CertificateProviderServiceTest
, UnloadExtensionAfterGetCertificates
) {
386 test_delegate_
->provider_extensions_
.insert(kExtension2
);
388 const int cert_request_id
= RequestCertificatesFromExtensions(nullptr);
390 SetCertificateProvidedByExtension(kExtension1
, cert_request_id
, cert_info1_
);
391 SetCertificateProvidedByExtension(kExtension2
, cert_request_id
, cert_info2_
);
392 task_runner_
->RunUntilIdle();
394 // Private key handles for both certificates must be available now.
396 client_key_store_
->FetchClientCertPrivateKey(*cert_info1_
.certificate
));
398 client_key_store_
->FetchClientCertPrivateKey(*cert_info2_
.certificate
));
400 // Unload one of the extensions.
401 service_
->OnExtensionUnloaded(kExtension2
);
403 // extension1 isn't affected by the uninstall.
405 client_key_store_
->FetchClientCertPrivateKey(*cert_info1_
.certificate
));
406 // No key handles that were backed by the uninstalled extension must be
409 client_key_store_
->FetchClientCertPrivateKey(*cert_info2_
.certificate
));
412 TEST_F(CertificateProviderServiceTest
, UnloadExtensionDuringGetCertificates
) {
413 test_delegate_
->provider_extensions_
.insert(kExtension2
);
415 net::CertificateList certs
;
416 const int cert_request_id
= RequestCertificatesFromExtensions(&certs
);
418 SetCertificateProvidedByExtension(kExtension1
, cert_request_id
, cert_info1_
);
420 // The pending certificate request is only waiting for kExtension2. Unloading
421 // that extension must cause the request to be finished.
422 service_
->OnExtensionUnloaded(kExtension2
);
424 task_runner_
->RunUntilIdle();
425 EXPECT_EQ(1u, certs
.size());
428 // Trying to sign data using the exposed SSLPrivateKey must cause a sign
429 // request. The reply must be correctly routed back to the private key.
430 TEST_F(CertificateProviderServiceTest
, SignRequest
) {
431 ProvideDefaultCert();
433 scoped_ptr
<net::SSLPrivateKey
> private_key(
434 client_key_store_
->FetchClientCertPrivateKey(*cert_info1_
.certificate
));
436 ASSERT_TRUE(private_key
);
437 EXPECT_TRUE(IsKeyEqualToCertInfo(cert_info1_
, private_key
.get()));
439 test_delegate_
->ClearAndExpectRequest(TestDelegate::RequestType::SIGN
);
441 std::vector
<uint8_t> received_signature
;
442 private_key
->SignDigest(
443 net::SSLPrivateKey::Hash::SHA256
, std::string("any input data"),
444 base::Bind(&ExpectOKAndStoreSignature
, &received_signature
));
446 task_runner_
->RunUntilIdle();
448 const int sign_request_id
= test_delegate_
->last_sign_request_id_
;
449 EXPECT_EQ(TestDelegate::RequestType::NONE
,
450 test_delegate_
->expected_request_type_
);
452 cert_info1_
.certificate
->Equals(test_delegate_
->last_certificate_
.get()));
454 // No signature received until the extension replied to the service.
455 EXPECT_TRUE(received_signature
.empty());
457 std::vector
<uint8_t> signature_reply
;
458 signature_reply
.push_back(5);
459 signature_reply
.push_back(7);
460 signature_reply
.push_back(8);
461 service_
->ReplyToSignRequest(kExtension1
, sign_request_id
, signature_reply
);
463 task_runner_
->RunUntilIdle();
464 EXPECT_EQ(signature_reply
, received_signature
);
467 TEST_F(CertificateProviderServiceTest
, UnloadExtensionDuringSign
) {
468 ProvideDefaultCert();
470 scoped_ptr
<net::SSLPrivateKey
> private_key(
471 client_key_store_
->FetchClientCertPrivateKey(*cert_info1_
.certificate
));
472 ASSERT_TRUE(private_key
);
474 test_delegate_
->ClearAndExpectRequest(TestDelegate::RequestType::SIGN
);
476 net::Error error
= net::OK
;
477 private_key
->SignDigest(
478 net::SSLPrivateKey::Hash::SHA256
, std::string("any input data"),
479 base::Bind(&ExpectEmptySignatureAndStoreError
, &error
));
481 task_runner_
->RunUntilIdle();
483 // No signature received until the extension replied to the service or is
485 EXPECT_EQ(net::OK
, error
);
487 // Unload the extension.
488 service_
->OnExtensionUnloaded(kExtension1
);
490 task_runner_
->RunUntilIdle();
491 EXPECT_EQ(net::ERR_FAILED
, error
);
494 } // namespace chromeos