Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: chromeos/cert_loader_unittest.cc

Issue 135193007: Use user specific NSSDatabase in CertLoader. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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 "chromeos/cert_loader.h"
6
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "crypto/nss_util.h"
13 #include "crypto/nss_util_internal.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/test_data_directory.h"
16 #include "net/cert/nss_cert_database_chromeos.h"
17 #include "net/cert/x509_certificate.h"
18 #include "net/test/cert_test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace chromeos {
22 namespace {
23
24 bool IsCertInCertificateList(const net::X509Certificate* cert,
25 const net::CertificateList& cert_list) {
26 for (net::CertificateList::const_iterator it = cert_list.begin();
27 it != cert_list.end();
28 ++it) {
29 if (net::X509Certificate::IsSameOSCert((*it)->os_cert_handle(),
30 cert->os_cert_handle()))
31 return true;
32 }
33 return false;
34 }
35
36 void NotReachedPrivateSlotCallback(crypto::ScopedPK11Slot slot) {
37 ASSERT_FALSE(true) << "GetPrivateSlotForChromeOSUser callback called even "
38 << "though the private slot had been initialized.";
39 }
40
41 class CertLoaderTest : public testing::Test,
42 public CertLoader::Observer {
43 public:
44 CertLoaderTest() : cert_loader_(NULL),
45 primary_user_("primary"),
46 new_certificates_loaded_events_count_(0U) {
47 }
48
49 virtual ~CertLoaderTest() {}
50
51 virtual void SetUp() OVERRIDE {
52 ASSERT_TRUE(primary_user_.constructed_successfully());
53 ASSERT_TRUE(
54 crypto::GetPublicSlotForChromeOSUser(primary_user_.username_hash()));
55
56 CertLoader::Initialize();
57 cert_loader_ = CertLoader::Get();
58 cert_loader_->AddObserver(this);
59 cert_loader_->SetSlowTaskRunnerForTest(message_loop_.message_loop_proxy());
60 cert_loader_->SetCryptoTaskRunner(message_loop_.message_loop_proxy());
61 }
62
63 virtual void TearDown() {
64 cert_loader_->RemoveObserver(this);
65 CertLoader::Shutdown();
66 }
67
68 protected:
69 // CertLoader::Observer:
70 // The test keeps count of times the observer method was called.
71 virtual void OnCertificatesLoaded(const net::CertificateList& cert_list,
72 bool initial_load) OVERRIDE {
73 new_certificates_loaded_events_count_++;
74 }
75
76 // Checks if the number of |OnCertificatesLoaded| calls observed since the
77 // last call to this method equals |value|.
78 bool NewCertificatesLoadedEventsCountEquals(size_t value) {
79 bool result = value == new_certificates_loaded_events_count_;
80 new_certificates_loaded_events_count_ = 0;
81 return result;
82 }
83
84 // Finishes initialization for the |user| and returns a user's NSS database
85 // instance.
86 scoped_ptr<net::NSSCertDatabaseChromeOS> FinishUserInitAndGetDatabase(
87 crypto::ScopedTestNSSChromeOSUser* user) {
88 scoped_ptr<net::NSSCertDatabaseChromeOS> database;
89 if (!user->constructed_successfully())
90 return database.Pass();
91
92 user->FinishInit();
93
94 crypto::ScopedPK11Slot private_slot(
95 crypto::GetPrivateSlotForChromeOSUser(
96 user->username_hash(),
97 base::Bind(&NotReachedPrivateSlotCallback)));
98 if (!private_slot)
99 return database.Pass();
100
101 database.reset(new net::NSSCertDatabaseChromeOS(
mattm 2014/01/23 01:45:55 (Creating database objects for the unittest is fin
tbarzic 2014/01/23 04:45:28 ack
102 crypto::GetPublicSlotForChromeOSUser(user->username_hash()),
103 private_slot.Pass()));
104 return database.Pass();
105 }
106
107 int GetDbPrivateSlotId(net::NSSCertDatabase* db) {
108 return static_cast<int>(PK11_GetSlotID(db->GetPrivateSlot().get()));
109 }
110
111 bool ImportCACerts(const std::string& cert_file,
112 net::NSSCertDatabase* database,
113 net::CertificateList* imported_certs) {
114 if (!database || !imported_certs)
115 return false;
116
117 // Add a certificate to the user's db.
118 *imported_certs = net::CreateCertificateListFromFile(
119 net::GetTestCertsDirectory(),
120 cert_file,
121 net::X509Certificate::FORMAT_AUTO);
122
123 net::NSSCertDatabase::ImportCertFailureList failed;
124 bool success = database->ImportCACerts(
125 *imported_certs, net::NSSCertDatabase::TRUSTED_SSL, &failed);
126 success = success && failed.empty();
127
128 if (!success)
129 imported_certs->clear();
130 return success;
131 }
132
133 bool ImportClientCertAndKey(const std::string& pkcs12_file,
134 net::NSSCertDatabase* database,
135 net::CertificateList* imported_certs) {
136 std::string pkcs12_data;
137 base::FilePath pkcs12_file_path =
138 net::GetTestCertsDirectory().Append(pkcs12_file);
139 if (!base::ReadFileToString(pkcs12_file_path, &pkcs12_data))
140 return false;
141
142 net::CertificateList client_cert_list;
143 scoped_refptr<net::CryptoModule> module(net::CryptoModule::CreateFromHandle(
144 database->GetPrivateSlot().get()));
145 return net::OK ==
146 database->ImportFromPKCS12(module, pkcs12_data, base::string16(), false,
147 imported_certs);
148 }
149
150 CertLoader* cert_loader_;
151
152 // The user is primary as the one whose certificates CertLoader handles, it
153 // has nothing to do with crypto::InitializeNSSForChromeOSUser is_primary_user
154 // parameter (which is irrelevant for these tests).
155 crypto::ScopedTestNSSChromeOSUser primary_user_;
156 scoped_ptr<net::NSSCertDatabaseChromeOS> primary_db_;
157
158 base::MessageLoop message_loop_;
159
160 private:
161 size_t new_certificates_loaded_events_count_;
162 };
163
164 TEST_F(CertLoaderTest, Basic) {
165 EXPECT_FALSE(cert_loader_->CertificatesLoading());
166 EXPECT_FALSE(cert_loader_->certificates_loaded());
167 EXPECT_FALSE(cert_loader_->is_hardware_backed());
168
169 primary_db_ = FinishUserInitAndGetDatabase(&primary_user_);
170 ASSERT_TRUE(primary_db_);
171
172 cert_loader_->StartWithUser(primary_user_.username_hash());
173
174 EXPECT_FALSE(cert_loader_->certificates_loaded());
175 EXPECT_TRUE(cert_loader_->CertificatesLoading());
176 EXPECT_TRUE(cert_loader_->cert_list().empty());
177
178 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
179 base::RunLoop().RunUntilIdle();
180 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
181
182 EXPECT_TRUE(cert_loader_->certificates_loaded());
183 EXPECT_FALSE(cert_loader_->CertificatesLoading());
184 EXPECT_FALSE(cert_loader_->is_hardware_backed());
185 EXPECT_EQ(GetDbPrivateSlotId(primary_db_.get()),
186 cert_loader_->tpm_token_slot_id());
187
188 // Default CA cert roots should get loaded.
189 EXPECT_FALSE(cert_loader_->cert_list().empty());
190 }
191
192 TEST_F(CertLoaderTest, CertLoaderInitBeforePrivateSlot) {
193 cert_loader_->StartWithUser(primary_user_.username_hash());
194
195 EXPECT_FALSE(cert_loader_->certificates_loaded());
196 EXPECT_TRUE(cert_loader_->CertificatesLoading());
197 EXPECT_TRUE(cert_loader_->cert_list().empty());
198 // Database should not be set yet, as the private slot hasn't bee initialized.
199 EXPECT_EQ(-1, cert_loader_->tpm_token_slot_id());
200
201 primary_db_ = FinishUserInitAndGetDatabase(&primary_user_);
202 ASSERT_TRUE(primary_db_);
203
204 EXPECT_FALSE(cert_loader_->certificates_loaded());
205 EXPECT_TRUE(cert_loader_->CertificatesLoading());
206 EXPECT_TRUE(cert_loader_->cert_list().empty());
207
208 // Certificate loading should be called asynchronously after the db is loaded.
209 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
210 base::RunLoop().RunUntilIdle();
211 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
212
213 // Default CA cert roots should get loaded.
214 EXPECT_FALSE(cert_loader_->cert_list().empty());
215 }
216
217 TEST_F(CertLoaderTest, CertLoaderUpdatesCertListOnNewCert) {
218 primary_db_ = FinishUserInitAndGetDatabase(&primary_user_);
219 ASSERT_TRUE(primary_db_);
220
221 cert_loader_->StartWithUser(primary_user_.username_hash());
222 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
223 base::RunLoop().RunUntilIdle();
224 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
225
226 ASSERT_TRUE(cert_loader_->certificates_loaded());
227 ASSERT_FALSE(cert_loader_->cert_list().empty());
228
229 net::CertificateList certs;
230 ASSERT_TRUE(ImportCACerts("root_ca_cert.pem", primary_db_.get(), &certs));
231 ASSERT_EQ(1U, certs.size());
232
233 // Certs are loaded asynchronously, so the new cert should not yet be in the
234 // cert list.
235 EXPECT_FALSE(IsCertInCertificateList(certs[0], cert_loader_->cert_list()));
236
237 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
238 base::RunLoop().RunUntilIdle();
239 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
240
241 // The certificate list should be updated now, as the message loop's been run.
242 EXPECT_TRUE(IsCertInCertificateList(certs[0], cert_loader_->cert_list()));
243 }
244
245 TEST_F(CertLoaderTest, CertLoaderNoUpdateOnSecondaryDbChanges) {
246 primary_db_ = FinishUserInitAndGetDatabase(&primary_user_);
247 ASSERT_TRUE(primary_db_);
248 cert_loader_->StartWithUser(primary_user_.username_hash());
249
250 crypto::ScopedTestNSSChromeOSUser secondary_user("secondary");
251 scoped_ptr<net::NSSCertDatabaseChromeOS> secondary_db =
252 FinishUserInitAndGetDatabase(&secondary_user);
253 ASSERT_TRUE(secondary_db);
254
255 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
256 base::RunLoop().RunUntilIdle();
257 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
258
259 ASSERT_TRUE(cert_loader_->certificates_loaded());
260 ASSERT_FALSE(cert_loader_->cert_list().empty());
261
262 net::CertificateList certs;
263 ASSERT_TRUE(ImportCACerts("root_ca_cert.pem", secondary_db.get(), &certs));
264 ASSERT_EQ(1U, certs.size());
265
266 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
267 base::RunLoop().RunUntilIdle();
268 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
269
270 EXPECT_FALSE(IsCertInCertificateList(certs[0], cert_loader_->cert_list()));
271 }
272
273 TEST_F(CertLoaderTest, ClientLoaderUpdateOnNewClientCert) {
274 primary_db_ = FinishUserInitAndGetDatabase(&primary_user_);
275 ASSERT_TRUE(primary_db_);
276 cert_loader_->StartWithUser(primary_user_.username_hash());
277 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
278 base::RunLoop().RunUntilIdle();
279 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
280
281 ASSERT_TRUE(cert_loader_->certificates_loaded());
282 ASSERT_FALSE(cert_loader_->cert_list().empty());
283
284 net::CertificateList client_certs;
285 ASSERT_TRUE(ImportClientCertAndKey("websocket_client_cert.p12",
286 primary_db_.get(),
287 &client_certs));
288 ASSERT_EQ(1U, client_certs.size());
289
290 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
291 base::RunLoop().RunUntilIdle();
292 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
293
294 EXPECT_TRUE(IsCertInCertificateList(client_certs[0],
295 cert_loader_->cert_list()));
296 EXPECT_TRUE(cert_loader_->IsCertificateInPrivateSlot(*client_certs[0]));
297 }
298
299 TEST_F(CertLoaderTest, CertLoaderNoUpdateOnNewClientCertInSecondaryDb) {
300 primary_db_ = FinishUserInitAndGetDatabase(&primary_user_);
301 ASSERT_TRUE(primary_db_);
302 cert_loader_->StartWithUser(primary_user_.username_hash());
303
304 crypto::ScopedTestNSSChromeOSUser secondary_user("secondary");
305 scoped_ptr<net::NSSCertDatabaseChromeOS> secondary_db =
306 FinishUserInitAndGetDatabase(&secondary_user);
307 ASSERT_TRUE(secondary_db);
308
309 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
310 base::RunLoop().RunUntilIdle();
311 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
312
313 ASSERT_TRUE(cert_loader_->certificates_loaded());
314 ASSERT_FALSE(cert_loader_->cert_list().empty());
315
316 net::CertificateList client_certs;
317 ASSERT_TRUE(ImportClientCertAndKey("websocket_client_cert.p12",
318 secondary_db.get(),
319 &client_certs));
320 ASSERT_EQ(1U, client_certs.size());
321
322 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
323 base::RunLoop().RunUntilIdle();
324 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
325
326 EXPECT_FALSE(
327 IsCertInCertificateList(client_certs[0], cert_loader_->cert_list()));
328 EXPECT_FALSE(cert_loader_->IsCertificateInPrivateSlot(*client_certs[0]));
329 }
330
331 TEST_F(CertLoaderTest, UpdatedOnCertRemoval) {
332 primary_db_ = FinishUserInitAndGetDatabase(&primary_user_);
333 ASSERT_TRUE(primary_db_);
334 cert_loader_->StartWithUser(primary_user_.username_hash());
335
336 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
337 base::RunLoop().RunUntilIdle();
338 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
339
340 ASSERT_TRUE(cert_loader_->certificates_loaded());
341 ASSERT_FALSE(cert_loader_->cert_list().empty());
342
343 net::CertificateList client_certs;
344 ASSERT_TRUE(ImportClientCertAndKey("websocket_client_cert.p12",
345 primary_db_.get(),
346 &client_certs));
347 ASSERT_EQ(1U, client_certs.size());
348 base::RunLoop().RunUntilIdle();
349 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
350 ASSERT_TRUE(IsCertInCertificateList(client_certs[0],
351 cert_loader_->cert_list()));
352
353 primary_db_->DeleteCertAndKey(client_certs[0]);
354
355 ASSERT_TRUE(NewCertificatesLoadedEventsCountEquals(0U));
356 base::RunLoop().RunUntilIdle();
357 EXPECT_TRUE(NewCertificatesLoadedEventsCountEquals(1U));
358
359 ASSERT_FALSE(IsCertInCertificateList(client_certs[0],
360 cert_loader_->cert_list()));
361 }
362
363 } // namespace
364 } // namespace chromeos
OLDNEW
« chromeos/cert_loader.cc ('K') | « chromeos/cert_loader.cc ('k') | chromeos/chromeos.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698