1 // Copyright 2013 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/client_cert_store_chromeos.h"
8 #include "base/callback.h"
9 #include "base/file_util.h"
10 #include "base/run_loop.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "crypto/nss_util.h"
13 #include "crypto/nss_util_internal.h"
14 #include "net/cert/nss_cert_database.h"
15 #include "net/ssl/client_cert_store_unittest-inl.h"
19 class ClientCertStoreChromeOSTestDelegate
{
21 ClientCertStoreChromeOSTestDelegate()
22 : store_("usernamehash",
23 ClientCertStoreChromeOS::PasswordDelegateFactory()) {
24 store_
.InitForTesting(
25 crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()),
26 crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()));
29 bool SelectClientCerts(const CertificateList
& input_certs
,
30 const SSLCertRequestInfo
& cert_request_info
,
31 CertificateList
* selected_certs
) {
32 return store_
.SelectClientCertsForTesting(
33 input_certs
, cert_request_info
, selected_certs
);
37 ClientCertStoreChromeOS store_
;
40 class ClientCertStoreChromeOSTest
: public ::testing::Test
{
42 scoped_refptr
<X509Certificate
> ImportCertForUser(
43 const std::string
& username_hash
,
44 const std::string
& filename
,
45 const std::string
& password
) {
46 crypto::ScopedPK11Slot
slot(
47 crypto::GetPublicSlotForChromeOSUser(username_hash
));
48 EXPECT_TRUE(slot
.get());
52 net::CertificateList cert_list
;
54 base::FilePath p12_path
= GetTestCertsDirectory().AppendASCII(filename
);
56 if (!base::ReadFileToString(p12_path
, &p12_data
)) {
61 scoped_refptr
<net::CryptoModule
> module(
62 net::CryptoModule::CreateFromHandle(slot
.get()));
63 int rv
= NSSCertDatabase::GetInstance()->ImportFromPKCS12(
64 module
.get(), p12_data
, base::UTF8ToUTF16(password
), false, &cert_list
);
67 EXPECT_EQ(1U, cert_list
.size());
68 if (rv
|| cert_list
.size() != 1)
75 // TODO(mattm): Do better testing of cert_authorities matching below. Update
76 // net/data/ssl/scripts/generate-client-certificates.sh so that it actually
77 // saves the .p12 files, and regenerate them.
79 TEST_F(ClientCertStoreChromeOSTest
, WaitForNSSInit
) {
80 crypto::ScopedTestNSSChromeOSUser
user("scopeduser");
81 ASSERT_TRUE(user
.constructed_successfully());
82 ClientCertStoreChromeOS
store(
83 user
.username_hash(), ClientCertStoreChromeOS::PasswordDelegateFactory());
84 scoped_refptr
<X509Certificate
> cert_1(
85 ImportCertForUser(user
.username_hash(), "client.p12", "12345"));
86 scoped_refptr
<X509Certificate
> cert_2(
87 ImportCertForUser(user
.username_hash(), "websocket_client_cert.p12", ""));
89 std::vector
<std::string
> authority_1(
91 std::string(reinterpret_cast<const char*>(kAuthority1DN
),
92 sizeof(kAuthority1DN
)));
93 scoped_refptr
<SSLCertRequestInfo
> request_1(new SSLCertRequestInfo());
94 request_1
->cert_authorities
= authority_1
;
96 scoped_refptr
<SSLCertRequestInfo
> request_all(new SSLCertRequestInfo());
98 base::RunLoop run_loop_1
;
99 base::RunLoop run_loop_all
;
100 store
.GetClientCerts(
101 *request_1
, &request_1
->client_certs
, run_loop_1
.QuitClosure());
102 store
.GetClientCerts(
103 *request_all
, &request_all
->client_certs
, run_loop_all
.QuitClosure());
105 // Callbacks won't be run until nss_util init finishes for the user.
111 ASSERT_EQ(0u, request_1
->client_certs
.size());
112 ASSERT_EQ(2u, request_all
->client_certs
.size());
115 TEST_F(ClientCertStoreChromeOSTest
, NSSAlreadyInitialized
) {
116 crypto::ScopedTestNSSChromeOSUser
user("scopeduser");
117 ASSERT_TRUE(user
.constructed_successfully());
120 ClientCertStoreChromeOS
store(
121 user
.username_hash(), ClientCertStoreChromeOS::PasswordDelegateFactory());
122 scoped_refptr
<X509Certificate
> cert_1(
123 ImportCertForUser(user
.username_hash(), "client.p12", "12345"));
124 scoped_refptr
<X509Certificate
> cert_2(
125 ImportCertForUser(user
.username_hash(), "websocket_client_cert.p12", ""));
127 std::vector
<std::string
> authority_1(
129 std::string(reinterpret_cast<const char*>(kAuthority1DN
),
130 sizeof(kAuthority1DN
)));
131 scoped_refptr
<SSLCertRequestInfo
> request_1(new SSLCertRequestInfo());
132 request_1
->cert_authorities
= authority_1
;
134 scoped_refptr
<SSLCertRequestInfo
> request_all(new SSLCertRequestInfo());
136 base::RunLoop run_loop_1
;
137 base::RunLoop run_loop_all
;
138 store
.GetClientCerts(
139 *request_1
, &request_1
->client_certs
, run_loop_1
.QuitClosure());
140 store
.GetClientCerts(
141 *request_all
, &request_all
->client_certs
, run_loop_all
.QuitClosure());
146 ASSERT_EQ(0u, request_1
->client_certs
.size());
147 ASSERT_EQ(2u, request_all
->client_certs
.size());
150 TEST_F(ClientCertStoreChromeOSTest
, TwoUsers
) {
151 crypto::ScopedTestNSSChromeOSUser
user1("scopeduser1");
152 ASSERT_TRUE(user1
.constructed_successfully());
153 crypto::ScopedTestNSSChromeOSUser
user2("scopeduser2");
154 ASSERT_TRUE(user2
.constructed_successfully());
155 ClientCertStoreChromeOS
store1(
156 user1
.username_hash(),
157 ClientCertStoreChromeOS::PasswordDelegateFactory());
158 ClientCertStoreChromeOS
store2(
159 user2
.username_hash(),
160 ClientCertStoreChromeOS::PasswordDelegateFactory());
161 scoped_refptr
<X509Certificate
> cert_1(
162 ImportCertForUser(user1
.username_hash(), "client.p12", "12345"));
163 scoped_refptr
<X509Certificate
> cert_2(ImportCertForUser(
164 user2
.username_hash(), "websocket_client_cert.p12", ""));
166 scoped_refptr
<SSLCertRequestInfo
> request_1(new SSLCertRequestInfo());
167 scoped_refptr
<SSLCertRequestInfo
> request_2(new SSLCertRequestInfo());
169 base::RunLoop run_loop_1
;
170 base::RunLoop run_loop_2
;
171 store1
.GetClientCerts(
172 *request_1
, &request_1
->client_certs
, run_loop_1
.QuitClosure());
173 store2
.GetClientCerts(
174 *request_2
, &request_2
->client_certs
, run_loop_2
.QuitClosure());
176 // Callbacks won't be run until nss_util init finishes for the user.
183 ASSERT_EQ(1u, request_1
->client_certs
.size());
184 EXPECT_TRUE(cert_1
->Equals(request_1
->client_certs
[0]));
185 // TODO(mattm): Request for second user will have zero results due to
186 // crbug.com/315285. Update the test once that is fixed.