blob: eb0ca150a70ff16f89e5da6f059a1b07b5e163ed [file] [log] [blame]
Pavol Markob429f542018-08-23 06:08:191// Copyright 2018 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
Gabriel Charetteb69fcd42019-08-23 02:13:295#include "chrome/browser/certificate_manager_model.h"
Gabriel Charettec7108742019-08-23 03:31:406
Pavol Markob429f542018-08-23 06:08:197#include "base/observer_list.h"
8#include "base/run_loop.h"
9#include "base/strings/utf_string_conversions.h"
Yuta Hijikata235fc62b2020-12-08 03:48:3210#include "build/chromeos_buildflags.h"
Gabriel Charettec7108742019-08-23 03:31:4011#include "content/public/test/browser_task_environment.h"
Pavol Markob429f542018-08-23 06:08:1912#include "crypto/scoped_test_nss_db.h"
13#include "net/cert/nss_cert_database.h"
14#include "net/cert/scoped_nss_types.h"
15#include "net/cert/x509_util_nss.h"
16#include "net/ssl/client_cert_identity_test_util.h"
Michael Ershov9a5525c2019-11-28 09:37:4817#include "net/test/cert_builder.h"
Pavol Markob429f542018-08-23 06:08:1918#include "net/test/cert_test_util.h"
19#include "net/test/test_data_directory.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
Yuta Hijikata235fc62b2020-12-08 03:48:3222#if BUILDFLAG(IS_CHROMEOS_ASH)
Yeunjoo Choi75455e92021-02-22 07:26:1223#include "chrome/browser/ash/certificate_provider/certificate_provider.h"
Michael Ershov06586a72021-12-10 13:49:3924#include "chromeos/components/onc/certificate_scope.h"
Steven Bennetts8e97939f2019-01-11 16:11:3125#include "chromeos/network/policy_certificate_provider.h"
Pavol Markob429f542018-08-23 06:08:1926#endif
27
28namespace {
29
30// A fake CertificateManagerModel::Observer that has the ability to execute a
31// OnceClosure passed to it when |CertificatesRefreshed| is called.
32class FakeObserver : public CertificateManagerModel::Observer {
33 public:
34 void CertificatesRefreshed() override {
35 if (!run_on_refresh_.is_null())
36 std::move(run_on_refresh_).Run();
37 }
38
39 // Execute |closure| on the next |CertificatesRefreshed| invocation.
40 void RunOnNextRefresh(base::OnceClosure closure) {
41 run_on_refresh_ = std::move(closure);
42 }
43
44 private:
45 base::OnceClosure run_on_refresh_;
46};
47
48// Looks up a |CertInfo| in |org_grouping_map| corresponding to |cert|. Returns
49// nullptr if no such |CertInfo| was found.
50CertificateManagerModel::CertInfo* GetCertInfoFromOrgGroupingMap(
51 const CertificateManagerModel::OrgGroupingMap& org_grouping_map,
52 CERTCertificate* cert) {
53 for (const auto& org_and_cert_info_list : org_grouping_map) {
54 for (const auto& cert_info : org_and_cert_info_list.second) {
55 if (net::x509_util::IsSameCertificate(cert_info->cert(), cert))
56 return cert_info.get();
57 }
58 }
59 return nullptr;
60}
61
62} // namespace
63
64class CertificateManagerModelTest : public testing::Test {
65 public:
66 CertificateManagerModelTest() {}
67
Peter Boströmfadb1752021-09-30 19:17:0168 CertificateManagerModelTest(const CertificateManagerModelTest&) = delete;
69 CertificateManagerModelTest& operator=(const CertificateManagerModelTest&) =
70 delete;
71
Pavol Markob429f542018-08-23 06:08:1972 protected:
73 void SetUp() override {
74 ASSERT_TRUE(test_nssdb_.is_open());
75
76 nss_cert_db_ = std::make_unique<net::NSSCertDatabase>(
77 crypto::ScopedPK11Slot(
78 PK11_ReferenceSlot(test_nssdb_.slot())) /* public slot */,
79 crypto::ScopedPK11Slot(
80 PK11_ReferenceSlot(test_nssdb_.slot())) /* private slot */);
81
82 fake_observer_ = std::make_unique<FakeObserver>();
83 certificate_manager_model_ = std::make_unique<CertificateManagerModel>(
84 GetCertificateManagerModelParams(), fake_observer_.get(),
Michael Ershov42775512021-08-30 10:11:4085 nss_cert_db_.get());
Pavol Markob429f542018-08-23 06:08:1986 }
87
88 void TearDown() override {
89 certificate_manager_model_.reset();
90 nss_cert_db_.reset();
91 }
92
93 // Provides the platform-specific |Params| (containing policy/extension
94 // certificate provides on Chrome OS).
95 virtual std::unique_ptr<CertificateManagerModel::Params>
96 GetCertificateManagerModelParams() {
97 return std::make_unique<CertificateManagerModel::Params>();
98 }
99
100 protected:
Irem Uguz2e7009c2021-01-14 09:55:40101 // Invoke an explicit Refresh if the refresh is triggered and wait until the
102 // observer has been notified.
103 void WaitForRefresh(bool trigger_refresh) {
Pavol Markob429f542018-08-23 06:08:19104 base::RunLoop run_loop;
105 fake_observer_->RunOnNextRefresh(run_loop.QuitClosure());
Irem Uguz2e7009c2021-01-14 09:55:40106 if (trigger_refresh) {
107 certificate_manager_model_->Refresh();
108 }
Pavol Markob429f542018-08-23 06:08:19109 run_loop.Run();
110 }
111
Gabriel Charette798fde72019-08-20 22:24:04112 content::BrowserTaskEnvironment task_environment_;
Pavol Markob429f542018-08-23 06:08:19113 crypto::ScopedTestNSSDB test_nssdb_;
114 std::unique_ptr<net::NSSCertDatabase> nss_cert_db_;
115 std::unique_ptr<FakeObserver> fake_observer_;
116 std::unique_ptr<CertificateManagerModel> certificate_manager_model_;
Pavol Markob429f542018-08-23 06:08:19117};
118
119// CertificateManagerModel correctly lists CA certificates from the platform NSS
120// Database.
Michael Ershov9a5525c2019-11-28 09:37:48121TEST_F(CertificateManagerModelTest, ListsCertsFromPlatform) {
122 net::CertificateList orig_certs = CreateCertificateListFromFile(
Pavol Markob429f542018-08-23 06:08:19123 net::GetTestCertsDirectory(), "websocket_cacert.pem",
124 net::X509Certificate::FORMAT_AUTO);
Michael Ershov9a5525c2019-11-28 09:37:48125 ASSERT_EQ(1U, orig_certs.size());
126
127 net::CertBuilder cert_builder(orig_certs[0]->cert_buffer(), nullptr);
128 scoped_refptr<net::X509Certificate> x509_cert =
129 cert_builder.GetX509Certificate();
130
131 net::ScopedCERTCertificate cert =
132 net::x509_util::CreateCERTCertificateFromX509Certificate(x509_cert.get());
133 std::string cert_subject_name = x509_cert->subject().GetDisplayName();
Pavol Markob429f542018-08-23 06:08:19134
135 ASSERT_EQ(SECSuccess,
Michael Ershov9a5525c2019-11-28 09:37:48136 PK11_ImportCert(test_nssdb_.slot(), cert.get(), CK_INVALID_HANDLE,
137 "cert", PR_FALSE /* includeTrust (unused) */));
Irem Uguz2e7009c2021-01-14 09:55:40138 WaitForRefresh(true /*tigger_for_refresh*/);
Pavol Markob429f542018-08-23 06:08:19139
140 {
141 CertificateManagerModel::OrgGroupingMap org_grouping_map;
142 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
143 net::CertType::CA_CERT, &org_grouping_map);
144 CertificateManagerModel::CertInfo* cert_info =
Michael Ershov9a5525c2019-11-28 09:37:48145 GetCertInfoFromOrgGroupingMap(org_grouping_map, cert.get());
Pavol Markob429f542018-08-23 06:08:19146 ASSERT_TRUE(cert_info);
147
148 EXPECT_EQ(net::CertType::CA_CERT, cert_info->type());
Michael Ershov9a5525c2019-11-28 09:37:48149 EXPECT_EQ(base::UTF8ToUTF16(cert_subject_name), cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30150 EXPECT_TRUE(cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19151 // This platform cert is untrusted because it is self-signed and has no
152 // trust bits.
153 EXPECT_TRUE(cert_info->untrusted());
154 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPlatform,
155 cert_info->source());
156 EXPECT_FALSE(cert_info->web_trust_anchor());
157 EXPECT_FALSE(cert_info->hardware_backed());
158 }
159
Michael Ershov9a5525c2019-11-28 09:37:48160 certificate_manager_model_->SetCertTrust(cert.get(), net::CertType::CA_CERT,
Pavol Markob429f542018-08-23 06:08:19161 net::NSSCertDatabase::TRUSTED_SSL);
Irem Uguz2e7009c2021-01-14 09:55:40162 // Wait for refresh without triggering because observer should be notified by
163 // net::CertDatabase and refresh automatically.
164 WaitForRefresh(false /*tigger_for_refresh*/);
Pavol Markob429f542018-08-23 06:08:19165 {
166 CertificateManagerModel::OrgGroupingMap org_grouping_map;
167 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
168 net::CertType::CA_CERT, &org_grouping_map);
169 CertificateManagerModel::CertInfo* cert_info =
Michael Ershov9a5525c2019-11-28 09:37:48170 GetCertInfoFromOrgGroupingMap(org_grouping_map, cert.get());
Pavol Markob429f542018-08-23 06:08:19171 ASSERT_TRUE(cert_info);
172
173 EXPECT_FALSE(cert_info->untrusted());
174 EXPECT_TRUE(cert_info->web_trust_anchor());
175 }
176}
177
178// CertificateManagerModel correctly lists client certificates from the platform
179// NSS Database.
180TEST_F(CertificateManagerModelTest, ListsClientCertsFromPlatform) {
181 net::ScopedCERTCertificate platform_client_cert;
182 net::ImportClientCertAndKeyFromFile(
183 net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8",
184 test_nssdb_.slot(), &platform_client_cert);
185
Irem Uguz2e7009c2021-01-14 09:55:40186 WaitForRefresh(true /*tigger_for_refresh*/);
Pavol Markob429f542018-08-23 06:08:19187
188 CertificateManagerModel::OrgGroupingMap org_grouping_map;
189 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
190 net::CertType::USER_CERT, &org_grouping_map);
191 CertificateManagerModel::CertInfo* platform_cert_info =
192 GetCertInfoFromOrgGroupingMap(org_grouping_map,
193 platform_client_cert.get());
194 ASSERT_TRUE(platform_cert_info);
195
196 EXPECT_EQ(net::CertType::USER_CERT, platform_cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24197 EXPECT_EQ(u"Client Cert A", platform_cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30198 EXPECT_TRUE(platform_cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19199 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPlatform,
200 platform_cert_info->source());
201 EXPECT_FALSE(platform_cert_info->web_trust_anchor());
202 EXPECT_FALSE(platform_cert_info->hardware_backed());
203}
204
Yuta Hijikata235fc62b2020-12-08 03:48:32205#if BUILDFLAG(IS_CHROMEOS_ASH)
Pavol Markob429f542018-08-23 06:08:19206namespace {
207
Pavol Marko3bab3afd2018-09-24 14:42:17208class FakePolicyCertificateProvider
209 : public chromeos::PolicyCertificateProvider {
Pavol Markob429f542018-08-23 06:08:19210 public:
211 void AddPolicyProvidedCertsObserver(Observer* observer) override {
212 observer_list_.AddObserver(observer);
213 }
214
215 void RemovePolicyProvidedCertsObserver(Observer* observer) override {
216 observer_list_.RemoveObserver(observer);
217 }
218
Pavol Markoc14be9c2019-08-13 20:25:02219 net::CertificateList GetAllServerAndAuthorityCertificates(
220 const chromeos::onc::CertificateScope& scope) const override {
221 // The CertificateManagerModel only retrieves profile-wide certificates.
222 EXPECT_EQ(chromeos::onc::CertificateScope::Default(), scope);
223
Pavol Markob429f542018-08-23 06:08:19224 net::CertificateList merged;
225 merged.insert(merged.end(), web_trusted_certs_.begin(),
226 web_trusted_certs_.end());
227 merged.insert(merged.end(), not_web_trusted_certs_.begin(),
228 not_web_trusted_certs_.end());
229 return merged;
230 }
231
Pavol Markoc14be9c2019-08-13 20:25:02232 net::CertificateList GetAllAuthorityCertificates(
233 const chromeos::onc::CertificateScope& scope) const override {
Pavol Marko3bab3afd2018-09-24 14:42:17234 // This function is not called by CertificateManagerModel.
235 NOTREACHED();
236 return net::CertificateList();
237 }
238
Pavol Markoc14be9c2019-08-13 20:25:02239 net::CertificateList GetWebTrustedCertificates(
240 const chromeos::onc::CertificateScope& scope) const override {
241 // The CertificateManagerModel only retrieves profile-wide certificates.
242 EXPECT_EQ(chromeos::onc::CertificateScope::Default(), scope);
243
Pavol Markob429f542018-08-23 06:08:19244 return web_trusted_certs_;
245 }
246
Pavol Markoc14be9c2019-08-13 20:25:02247 net::CertificateList GetCertificatesWithoutWebTrust(
248 const chromeos::onc::CertificateScope& scope) const override {
249 // The CertificateManagerModel only retrieves profile-wide certificates.
250 EXPECT_EQ(chromeos::onc::CertificateScope::Default(), scope);
251
Pavol Markob429f542018-08-23 06:08:19252 return not_web_trusted_certs_;
253 }
254
Pavol Markoc14be9c2019-08-13 20:25:02255 const std::set<std::string>& GetExtensionIdsWithPolicyCertificates()
256 const override {
257 // This function is not called by CertificateManagerModel.
258 NOTREACHED();
259 return kNoExtensions;
260 }
261
Pavol Markob429f542018-08-23 06:08:19262 void SetPolicyProvidedCertificates(
263 const net::CertificateList& web_trusted_certs,
264 const net::CertificateList& not_web_trusted_certs) {
265 web_trusted_certs_ = web_trusted_certs;
266 not_web_trusted_certs_ = not_web_trusted_certs;
267 }
268
269 void NotifyObservers() {
Pavol Marko67556732019-08-05 09:56:39270 for (auto& observer : observer_list_)
271 observer.OnPolicyProvidedCertsChanged();
Pavol Markob429f542018-08-23 06:08:19272 }
273
274 private:
275 base::ObserverList<PolicyCertificateProvider::Observer,
276 true /* check_empty */>::Unchecked observer_list_;
277 net::CertificateList web_trusted_certs_;
278 net::CertificateList not_web_trusted_certs_;
Pavol Markoc14be9c2019-08-13 20:25:02279 const std::set<std::string> kNoExtensions = {};
Pavol Markob429f542018-08-23 06:08:19280};
281
282class FakeExtensionCertificateProvider : public chromeos::CertificateProvider {
283 public:
284 FakeExtensionCertificateProvider(
285 const net::CertificateList* extension_client_certificates,
286 const bool* extensions_hang)
287 : extension_client_certificates_(extension_client_certificates),
288 extensions_hang_(extensions_hang) {}
289
290 void GetCertificates(
David Benjamin0cda2042019-04-08 23:00:58291 base::OnceCallback<void(net::ClientCertIdentityList)> callback) override {
Pavol Markob429f542018-08-23 06:08:19292 if (*extensions_hang_)
293 return;
294
David Benjamin0cda2042019-04-08 23:00:58295 std::move(callback).Run(FakeClientCertIdentityListFromCertificateList(
Pavol Markob429f542018-08-23 06:08:19296 *extension_client_certificates_));
297 }
298
Pavol Markob429f542018-08-23 06:08:19299 private:
300 const net::CertificateList* extension_client_certificates_;
301
302 // If *|extensions_hang| is true, the |FakeExtensionCertificateProvider| hangs
303 // - it never calls the callbacks passed to |GetCertificates|.
304 const bool* extensions_hang_;
305};
306
307// Looks up a |CertInfo| in |org_grouping_map| corresponding to |cert|. Returns
308// nullptr if no such |CertInfo| was found.
309CertificateManagerModel::CertInfo* GetCertInfoFromOrgGroupingMap(
310 const CertificateManagerModel::OrgGroupingMap& org_grouping_map,
311 const net::X509Certificate* cert) {
312 for (const auto& org_and_cert_info_list : org_grouping_map) {
313 for (const auto& cert_info : org_and_cert_info_list.second) {
314 if (net::x509_util::IsSameCertificate(cert_info->cert(), cert))
315 return cert_info.get();
316 }
317 }
318 return nullptr;
319}
320
321} // namespace
322
323class CertificateManagerModelChromeOSTest : public CertificateManagerModelTest {
324 protected:
325 std::unique_ptr<CertificateManagerModel::Params>
326 GetCertificateManagerModelParams() override {
327 auto params = std::make_unique<CertificateManagerModel::Params>();
328 params->policy_certs_provider = &policy_certs_provider_;
329 params->extension_certificate_provider =
330 std::make_unique<FakeExtensionCertificateProvider>(
331 &extension_client_certs_, &extensions_hang_);
332 return params;
333 }
334
335 void NotifyPolicyObserversAndWaitForRefresh() {
336 base::RunLoop run_loop;
337 fake_observer_->RunOnNextRefresh(run_loop.QuitClosure());
338 policy_certs_provider_.NotifyObservers();
339 run_loop.Run();
340 }
341
342 // Provider for policy certificates. In a non-test environment, this would
343 // usually be the UserNetworkConfigurationUpdater.
344 FakePolicyCertificateProvider policy_certs_provider_;
345
346 // List of certificates that will be returned from the
347 // FakeExtensionCertificateProvider.
348 net::CertificateList extension_client_certs_;
349 // If true, the FakeExtensionCertificateProvider hangs.
350 bool extensions_hang_ = false;
351};
352
353// CertificateManagerModel correctly lists policy-provided certificates with web
354// trust.
355TEST_F(CertificateManagerModelChromeOSTest, ListsWebTrustedCertsFromPolicy) {
356 scoped_refptr<net::X509Certificate> cert = net::ImportCertFromFile(
357 net::GetTestCertsDirectory(), "websocket_cacert.pem");
358 ASSERT_TRUE(cert.get());
359 policy_certs_provider_.SetPolicyProvidedCertificates({cert}, {});
360
361 NotifyPolicyObserversAndWaitForRefresh();
362
363 CertificateManagerModel::OrgGroupingMap org_grouping_map;
364 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
365 net::CertType::CA_CERT, &org_grouping_map);
366 CertificateManagerModel::CertInfo* cert_info =
367 GetCertInfoFromOrgGroupingMap(org_grouping_map, cert.get());
368 ASSERT_TRUE(cert_info);
369
370 EXPECT_EQ(net::CertType::CA_CERT, cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24371 EXPECT_EQ(u"pywebsocket", cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30372 EXPECT_FALSE(cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19373 EXPECT_FALSE(cert_info->untrusted());
374 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPolicy,
375 cert_info->source());
376 EXPECT_TRUE(cert_info->web_trust_anchor());
377 EXPECT_FALSE(cert_info->hardware_backed());
378}
379
380// CertificateManagerModel correctly lists policy-provided certificates without
381// web trust.
382TEST_F(CertificateManagerModelChromeOSTest, ListsNotWebTrustedCertsFromPolicy) {
383 scoped_refptr<net::X509Certificate> cert = net::ImportCertFromFile(
384 net::GetTestCertsDirectory(), "websocket_cacert.pem");
385 ASSERT_TRUE(cert.get());
386 policy_certs_provider_.SetPolicyProvidedCertificates({}, {cert});
387
388 NotifyPolicyObserversAndWaitForRefresh();
389
390 CertificateManagerModel::OrgGroupingMap org_grouping_map;
391 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
392 net::CertType::CA_CERT, &org_grouping_map);
393 CertificateManagerModel::CertInfo* cert_info =
394 GetCertInfoFromOrgGroupingMap(org_grouping_map, cert.get());
395 ASSERT_TRUE(cert_info);
396
397 EXPECT_EQ(net::CertType::CA_CERT, cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24398 EXPECT_EQ(u"pywebsocket", cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30399 EXPECT_FALSE(cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19400 EXPECT_FALSE(cert_info->untrusted());
401 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPolicy,
402 cert_info->source());
403 EXPECT_FALSE(cert_info->web_trust_anchor());
404 EXPECT_FALSE(cert_info->hardware_backed());
405}
406
407// CertificateManagerModel correctly lists CA certificates that are in the
408// platform NSS database and provided by policy with web trust. The
409// policy-provided certificate hides the platform certificate in this case.
410TEST_F(CertificateManagerModelChromeOSTest,
411 WebTrustedPolicyCertsWinOverPlatformCerts) {
412 net::ScopedCERTCertificateList certs = CreateCERTCertificateListFromFile(
413 net::GetTestCertsDirectory(), "websocket_cacert.pem",
414 net::X509Certificate::FORMAT_AUTO);
415 ASSERT_EQ(1U, certs.size());
416 CERTCertificate* platform_cert = certs[0].get();
417 ASSERT_EQ(SECSuccess, PK11_ImportCert(test_nssdb_.slot(), platform_cert,
418 CK_INVALID_HANDLE, "cert",
419 PR_FALSE /* includeTrust (unused) */));
420
421 scoped_refptr<net::X509Certificate> policy_cert = net::ImportCertFromFile(
422 net::GetTestCertsDirectory(), "websocket_cacert.pem");
423 ASSERT_TRUE(policy_cert.get());
424 policy_certs_provider_.SetPolicyProvidedCertificates({policy_cert}, {});
425
Irem Uguz2e7009c2021-01-14 09:55:40426 WaitForRefresh(true /*tigger_for_refresh*/);
Pavol Markob429f542018-08-23 06:08:19427
428 {
429 CertificateManagerModel::OrgGroupingMap org_grouping_map;
430 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
431 net::CertType::CA_CERT, &org_grouping_map);
432 CertificateManagerModel::CertInfo* platform_cert_info =
433 GetCertInfoFromOrgGroupingMap(org_grouping_map, platform_cert);
434 ASSERT_TRUE(platform_cert_info);
435 CertificateManagerModel::CertInfo* policy_cert_info =
436 GetCertInfoFromOrgGroupingMap(org_grouping_map, policy_cert.get());
437 ASSERT_TRUE(policy_cert_info);
438
439 EXPECT_EQ(platform_cert_info, policy_cert_info);
440
441 EXPECT_EQ(net::CertType::CA_CERT, policy_cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24442 EXPECT_EQ(u"pywebsocket", policy_cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30443 EXPECT_FALSE(policy_cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19444 EXPECT_FALSE(policy_cert_info->untrusted());
445 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPolicy,
446 policy_cert_info->source());
447 EXPECT_TRUE(policy_cert_info->web_trust_anchor());
448 EXPECT_FALSE(policy_cert_info->hardware_backed());
449 }
450
451 // Remove the cert from policy-provided certs again. The platform certificate
452 // should be visible afterwards.
453 policy_certs_provider_.SetPolicyProvidedCertificates({}, {});
454 NotifyPolicyObserversAndWaitForRefresh();
455
456 {
457 CertificateManagerModel::OrgGroupingMap org_grouping_map;
458 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
459 net::CertType::CA_CERT, &org_grouping_map);
460 CertificateManagerModel::CertInfo* platform_cert_info =
461 GetCertInfoFromOrgGroupingMap(org_grouping_map, platform_cert);
462 ASSERT_TRUE(platform_cert_info);
463
464 EXPECT_EQ(net::CertType::CA_CERT, platform_cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24465 EXPECT_EQ(u"pywebsocket", platform_cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30466 EXPECT_TRUE(platform_cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19467 EXPECT_TRUE(platform_cert_info->untrusted());
468 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPlatform,
469 platform_cert_info->source());
470 EXPECT_FALSE(platform_cert_info->web_trust_anchor());
471 EXPECT_FALSE(platform_cert_info->hardware_backed());
472 }
473}
474
475// CertificateManagerModel correctly lists CA certificates that are in the
476// platform NSS database and provided by policy without web trust. The platform
477// certificate hides the policy-provided certificate in this case.
478TEST_F(CertificateManagerModelChromeOSTest,
479 PlatformCertsWinOverNotWebTrustedCerts) {
480 net::ScopedCERTCertificateList certs = CreateCERTCertificateListFromFile(
481 net::GetTestCertsDirectory(), "websocket_cacert.pem",
482 net::X509Certificate::FORMAT_AUTO);
483 ASSERT_EQ(1U, certs.size());
484 CERTCertificate* platform_cert = certs[0].get();
485 ASSERT_EQ(SECSuccess, PK11_ImportCert(test_nssdb_.slot(), platform_cert,
486 CK_INVALID_HANDLE, "cert",
487 PR_FALSE /* includeTrust (unused) */));
488
489 scoped_refptr<net::X509Certificate> policy_cert = net::ImportCertFromFile(
490 net::GetTestCertsDirectory(), "websocket_cacert.pem");
491 ASSERT_TRUE(policy_cert.get());
492 policy_certs_provider_.SetPolicyProvidedCertificates({}, {policy_cert});
493
Irem Uguz2e7009c2021-01-14 09:55:40494 WaitForRefresh(true /*tigger_for_refresh*/);
Pavol Markob429f542018-08-23 06:08:19495
496 {
497 CertificateManagerModel::OrgGroupingMap org_grouping_map;
498 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
499 net::CertType::CA_CERT, &org_grouping_map);
500 CertificateManagerModel::CertInfo* platform_cert_info =
501 GetCertInfoFromOrgGroupingMap(org_grouping_map, platform_cert);
502 ASSERT_TRUE(platform_cert_info);
503 CertificateManagerModel::CertInfo* policy_cert_info =
504 GetCertInfoFromOrgGroupingMap(org_grouping_map, policy_cert.get());
505 ASSERT_TRUE(policy_cert_info);
506
507 EXPECT_EQ(platform_cert_info, policy_cert_info);
508
509 EXPECT_EQ(net::CertType::CA_CERT, platform_cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24510 EXPECT_EQ(u"pywebsocket", platform_cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30511 EXPECT_TRUE(platform_cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19512 EXPECT_TRUE(platform_cert_info->untrusted());
513 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPlatform,
514 platform_cert_info->source());
515 EXPECT_FALSE(platform_cert_info->web_trust_anchor());
516 EXPECT_FALSE(platform_cert_info->hardware_backed());
517 }
518
519 // Remove the certificate from the platform NSS database. The policy-provided
520 // certificate should be visible afterwards.
521 base::RunLoop run_loop;
522 fake_observer_->RunOnNextRefresh(run_loop.QuitClosure());
523 certificate_manager_model_->Delete(platform_cert);
524 run_loop.Run();
525
526 {
527 CertificateManagerModel::OrgGroupingMap org_grouping_map;
528 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
529 net::CertType::CA_CERT, &org_grouping_map);
530 CertificateManagerModel::CertInfo* policy_cert_info =
531 GetCertInfoFromOrgGroupingMap(org_grouping_map, policy_cert.get());
532 ASSERT_TRUE(policy_cert_info);
533
534 EXPECT_EQ(net::CertType::CA_CERT, policy_cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24535 EXPECT_EQ(u"pywebsocket", policy_cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30536 EXPECT_FALSE(policy_cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19537 EXPECT_FALSE(policy_cert_info->untrusted());
538 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPolicy,
539 policy_cert_info->source());
540 EXPECT_FALSE(policy_cert_info->web_trust_anchor());
541 EXPECT_FALSE(policy_cert_info->hardware_backed());
542 }
543}
544
545// When the Extension CertificateProvider hangs (e.g. because an extension is
546// not responding), policy and platform certificates are still listed.
547TEST_F(CertificateManagerModelChromeOSTest,
548 PlatformAndPolicyCertsListedWhenExtensionsHang) {
549 extensions_hang_ = true;
550
551 net::ScopedCERTCertificateList certs = CreateCERTCertificateListFromFile(
552 net::GetTestCertsDirectory(), "websocket_cacert.pem",
553 net::X509Certificate::FORMAT_AUTO);
554 ASSERT_EQ(1U, certs.size());
555 CERTCertificate* platform_cert = certs[0].get();
556 ASSERT_EQ(SECSuccess, PK11_ImportCert(test_nssdb_.slot(), platform_cert,
557 CK_INVALID_HANDLE, "cert",
558 PR_FALSE /* includeTrust (unused) */));
559
560 scoped_refptr<net::X509Certificate> policy_cert =
561 net::ImportCertFromFile(net::GetTestCertsDirectory(), "root_ca_cert.pem");
562 ASSERT_TRUE(policy_cert.get());
563 policy_certs_provider_.SetPolicyProvidedCertificates({policy_cert}, {});
564
Irem Uguz2e7009c2021-01-14 09:55:40565 WaitForRefresh(true /*tigger_for_refresh*/);
Pavol Markob429f542018-08-23 06:08:19566
567 CertificateManagerModel::OrgGroupingMap org_grouping_map;
568 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
569 net::CertType::CA_CERT, &org_grouping_map);
570 CertificateManagerModel::CertInfo* platform_cert_info =
571 GetCertInfoFromOrgGroupingMap(org_grouping_map, platform_cert);
572 ASSERT_TRUE(platform_cert_info);
573 CertificateManagerModel::CertInfo* policy_cert_info =
574 GetCertInfoFromOrgGroupingMap(org_grouping_map, policy_cert.get());
575 ASSERT_TRUE(policy_cert_info);
576
577 EXPECT_NE(platform_cert_info, policy_cert_info);
578}
579
580// CertificateManagerModel lists client certificates provided by extensions.
581TEST_F(CertificateManagerModelChromeOSTest, ListsExtensionCerts) {
582 scoped_refptr<net::X509Certificate> extension_cert =
583 net::ImportCertFromFile(net::GetTestCertsDirectory(), "client_1.pem");
584 ASSERT_TRUE(extension_cert.get());
585 extension_client_certs_.push_back(extension_cert);
586
Irem Uguz2e7009c2021-01-14 09:55:40587 WaitForRefresh(true /*tigger_for_refresh*/);
Pavol Markob429f542018-08-23 06:08:19588
589 CertificateManagerModel::OrgGroupingMap org_grouping_map;
590 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
591 net::CertType::USER_CERT, &org_grouping_map);
592 CertificateManagerModel::CertInfo* extension_cert_info =
593 GetCertInfoFromOrgGroupingMap(org_grouping_map, extension_cert.get());
594 ASSERT_TRUE(extension_cert_info);
595
596 EXPECT_EQ(net::CertType::USER_CERT, extension_cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24597 EXPECT_EQ(u"Client Cert A (extension provided)", extension_cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30598 EXPECT_FALSE(extension_cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19599 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kExtension,
600 extension_cert_info->source());
601 EXPECT_FALSE(extension_cert_info->web_trust_anchor());
602 EXPECT_FALSE(extension_cert_info->hardware_backed());
603}
604
605TEST_F(CertificateManagerModelChromeOSTest,
606 PlatformCertsWinOverExtensionCerts) {
607 net::ScopedCERTCertificate platform_client_cert;
608 net::ImportClientCertAndKeyFromFile(
609 net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8",
610 test_nssdb_.slot(), &platform_client_cert);
611
612 scoped_refptr<net::X509Certificate> extension_cert =
613 net::ImportCertFromFile(net::GetTestCertsDirectory(), "client_1.pem");
614 ASSERT_TRUE(extension_cert.get());
615 extension_client_certs_.push_back(extension_cert);
616
Irem Uguz2e7009c2021-01-14 09:55:40617 WaitForRefresh(true /*tigger_for_refresh*/);
Pavol Markob429f542018-08-23 06:08:19618
619 {
620 CertificateManagerModel::OrgGroupingMap org_grouping_map;
621 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
622 net::CertType::USER_CERT, &org_grouping_map);
623 CertificateManagerModel::CertInfo* platform_cert_info =
624 GetCertInfoFromOrgGroupingMap(org_grouping_map,
625 platform_client_cert.get());
626 ASSERT_TRUE(platform_cert_info);
627 CertificateManagerModel::CertInfo* extension_cert_info =
628 GetCertInfoFromOrgGroupingMap(org_grouping_map, extension_cert.get());
629 ASSERT_TRUE(extension_cert_info);
630
631 EXPECT_EQ(platform_cert_info, extension_cert_info);
632
633 EXPECT_EQ(net::CertType::USER_CERT, platform_cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24634 EXPECT_EQ(u"Client Cert A", platform_cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30635 EXPECT_TRUE(platform_cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19636 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kPlatform,
637 platform_cert_info->source());
638 EXPECT_FALSE(platform_cert_info->web_trust_anchor());
639 EXPECT_FALSE(platform_cert_info->hardware_backed());
640 }
641
642 // Remove the platform client certificate. The extension-provided client
643 // certificate should be visible afterwards.
644 base::RunLoop run_loop;
645 fake_observer_->RunOnNextRefresh(run_loop.QuitClosure());
646 certificate_manager_model_->Delete(platform_client_cert.get());
647 run_loop.Run();
648
649 {
650 CertificateManagerModel::OrgGroupingMap org_grouping_map;
651 certificate_manager_model_->FilterAndBuildOrgGroupingMap(
652 net::CertType::USER_CERT, &org_grouping_map);
653 CertificateManagerModel::CertInfo* extension_cert_info =
654 GetCertInfoFromOrgGroupingMap(org_grouping_map, extension_cert.get());
655 ASSERT_TRUE(extension_cert_info);
656
657 EXPECT_EQ(net::CertType::USER_CERT, extension_cert_info->type());
Jan Wilken Dörrie2c470ea2021-03-22 22:26:24658 EXPECT_EQ(u"Client Cert A (extension provided)",
Pavol Markob429f542018-08-23 06:08:19659 extension_cert_info->name());
Andreea Costinasa45a6052019-07-22 09:42:30660 EXPECT_FALSE(extension_cert_info->can_be_deleted());
Pavol Markob429f542018-08-23 06:08:19661 EXPECT_EQ(CertificateManagerModel::CertInfo::Source::kExtension,
662 extension_cert_info->source());
663 EXPECT_FALSE(extension_cert_info->web_trust_anchor());
664 EXPECT_FALSE(extension_cert_info->hardware_backed());
665 }
666}
667
Yuta Hijikata235fc62b2020-12-08 03:48:32668#endif // BUILDFLAG(IS_CHROMEOS_ASH)