blob: 28c991c5d6db22d0d880bf492f25d9c16b11cd9c [file] [log] [blame]
Avi Drissman4a8573c2022-09-09 19:35:541// Copyright 2022 The Chromium Authors
Matt Mueller5a85dd42022-08-17 17:07:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Arthur Sonzognife132ee2024-01-15 11:01:045#include <optional>
6
Matt Muellere06ddcc2024-06-15 00:32:267#include "base/strings/string_number_conversions.h"
Hubert Chaoe0f69902022-10-27 18:37:568#include "base/test/scoped_feature_list.h"
Matt Mueller5a85dd42022-08-17 17:07:569#include "build/build_config.h"
Matt Muellere6df72cb2023-04-12 22:08:3710#include "chrome/browser/browser_process.h"
11#include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
12#include "chrome/browser/net/system_network_context_manager.h"
Matt Mueller5a85dd42022-08-17 17:07:5613#include "chrome/browser/policy/policy_test_utils.h"
Matt Muellerdd3443572024-10-11 22:47:2214#include "chrome/browser/ssl/ssl_browsertest_util.h"
Matt Muellerd98bb87b2023-02-17 21:07:3515#include "chrome/common/buildflags.h"
Devlin Cronindbf91b22024-08-22 22:35:5616#include "chrome/test/base/platform_browser_test.h"
Matt Mueller5a85dd42022-08-17 17:07:5617#include "components/policy/core/common/policy_map.h"
18#include "components/policy/policy_constants.h"
Matt Muellerdd3443572024-10-11 22:47:2219#include "components/security_state/core/security_state.h"
Matt Mueller5a85dd42022-08-17 17:07:5620#include "content/public/browser/network_service_instance.h"
21#include "content/public/test/browser_test.h"
Takuto Ikutaa47d7852024-02-19 03:46:5822#include "content/public/test/browser_test_utils.h"
Matt Mueller5a85dd42022-08-17 17:07:5623#include "net/base/features.h"
Matt Muellere6df72cb2023-04-12 22:08:3724#include "net/cert/internal/trust_store_chrome.h"
Matt Muellere06ddcc2024-06-15 00:32:2625#include "net/cert/test_root_certs.h"
Matt Muellere6df72cb2023-04-12 22:08:3726#include "net/cert/x509_util.h"
Emily Stark25f01b82024-04-19 00:04:5027#include "net/dns/mock_host_resolver.h"
Matt Muellerd98bb87b2023-02-17 21:07:3528#include "net/net_buildflags.h"
Matt Muellere6df72cb2023-04-12 22:08:3729#include "net/test/cert_test_util.h"
30#include "net/test/embedded_test_server/embedded_test_server.h"
Matt Mueller5a85dd42022-08-17 17:07:5631#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
32#include "testing/gtest/include/gtest/gtest.h"
Matt Mueller5a85dd42022-08-17 17:07:5633
Hubert Chao7299aa6b2024-10-03 18:20:2234#if BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
35#include "base/containers/span.h"
36#include "base/containers/to_vector.h"
37#include "base/test/test_future.h"
38#include "chrome/browser/net/profile_network_context_service.h"
39#include "chrome/browser/net/profile_network_context_service_factory.h"
40#include "chrome/browser/net/server_certificate_database.h" // nogncheck
41#include "chrome/browser/net/server_certificate_database.pb.h" // nogncheck
42#include "chrome/browser/net/server_certificate_database_service.h" // nogncheck
43#include "chrome/browser/net/server_certificate_database_service_factory.h" // nogncheck
44#include "chrome/browser/profiles/profile.h"
45#include "chrome/browser/ui/browser.h"
46#include "chrome/common/chrome_features.h"
47#include "chrome/test/base/chrome_test_utils.h"
48#include "chrome/test/base/ui_test_utils.h"
49#include "crypto/sha2.h"
Hubert Chao28f5cfa2024-10-07 22:57:0850#include "third_party/boringssl/src/pki/trust_store.h"
Hubert Chao7299aa6b2024-10-03 18:20:2251#endif // BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
52
Matt Muellerdd3443572024-10-11 22:47:2253#if BUILDFLAG(IS_CHROMEOS)
54#include "base/test/metrics/histogram_tester.h"
55#include "chrome/browser/net/nss_service.h"
56#include "chrome/browser/net/nss_service_factory.h"
57#include "chrome/common/pref_names.h"
58#include "components/prefs/pref_service.h"
59#include "net/cert/cert_type.h"
60#include "net/cert/nss_cert_database.h"
61#include "net/cert/x509_util_nss.h"
62#endif
63
Matt Mueller8b02b1902023-03-07 00:06:3664#if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
Hubert Chao71a14a02023-12-01 18:04:3765class CertVerifierServiceChromeRootStoreOptionalTest
66 : public PlatformBrowserTest,
67 public testing::WithParamInterface<bool> {
Matt Mueller5a85dd42022-08-17 17:07:5668 public:
Hubert Chao71a14a02023-12-01 18:04:3769 void SetUpOnMainThread() override {
Matt Muellere6df72cb2023-04-12 22:08:3770 // This test puts a test cert in the Chrome Root Store, which will fail in
71 // builds where Certificate Transparency is required, so disable CT
72 // during this test.
73 SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting(
74 false);
Matt Mueller5a85dd42022-08-17 17:07:5675
Emily Stark25f01b82024-04-19 00:04:5076 host_resolver()->AddRule("*", "127.0.0.1");
77
Hubert Chao71a14a02023-12-01 18:04:3778 content::GetCertVerifierServiceFactory()->SetUseChromeRootStore(
79 use_chrome_root_store(), base::DoNothing());
Matt Mueller5a85dd42022-08-17 17:07:5680 }
81
Hubert Chao71a14a02023-12-01 18:04:3782 void TearDownOnMainThread() override {
Matt Muellere6df72cb2023-04-12 22:08:3783 SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting(
Arthur Sonzognife132ee2024-01-15 11:01:0484 std::nullopt);
Hubert Chao659fd1a62024-02-23 15:53:5885 // Reset to default.
Hubert Chao71a14a02023-12-01 18:04:3786 content::GetCertVerifierServiceFactory()->SetUseChromeRootStore(
Hubert Chao659fd1a62024-02-23 15:53:5887 true, base::DoNothing());
Francois Pierre Doray34347e762023-04-11 20:03:0488 }
89
Hubert Chao71a14a02023-12-01 18:04:3790 bool use_chrome_root_store() const { return GetParam(); }
Matt Mueller5a85dd42022-08-17 17:07:5691
Hubert Chao71a14a02023-12-01 18:04:3792 protected:
93 content::WebContents* GetActiveWebContents() {
94 return chrome_test_utils::GetActiveWebContents(this);
Matt Mueller5a85dd42022-08-17 17:07:5695 }
Matt Mueller5a85dd42022-08-17 17:07:5696};
97
Hubert Chao71a14a02023-12-01 18:04:3798IN_PROC_BROWSER_TEST_P(CertVerifierServiceChromeRootStoreOptionalTest, Test) {
Matt Muellere6df72cb2023-04-12 22:08:3799 net::EmbeddedTestServer https_test_server(
100 net::EmbeddedTestServer::TYPE_HTTPS);
101 // Use a runtime generated cert, as the pre-generated ok_cert has too long of
102 // a validity period to be accepted by a publicly trusted root.
Hubert Chao71a14a02023-12-01 18:04:37103 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
Emily Stark25f01b82024-04-19 00:04:50104 // The test uses a certificate with a publicly resolvable name, since Chrome
105 // rejects certificates for non-unique names from publicly trusted CAs.
106 https_test_server.SetCertHostnames({"example.com"});
Matt Muellere6df72cb2023-04-12 22:08:37107 ASSERT_TRUE(https_test_server.Start());
108
109 // Clear test roots so that cert validation only happens with
110 // what's in the relevant root store.
111 net::TestRootCerts::GetInstance()->Clear();
112
113 {
114 // Create updated Chrome Root Store with just the test server root cert.
Alex Gougha67cd0b2024-04-17 17:17:31115 chrome_root_store::RootStore root_store;
116 root_store.set_version_major(net::CompiledChromeRootStoreVersion() + 1);
Matt Muellere6df72cb2023-04-12 22:08:37117
Alex Gougha67cd0b2024-04-17 17:17:31118 chrome_root_store::TrustAnchor* anchor = root_store.add_trust_anchors();
Matt Muellere6df72cb2023-04-12 22:08:37119 scoped_refptr<net::X509Certificate> root_cert =
120 net::ImportCertFromFile(net::EmbeddedTestServer::GetRootCertPemPath());
121 ASSERT_TRUE(root_cert);
122 anchor->set_der(std::string(
123 net::x509_util::CryptoBufferAsStringPiece(root_cert->cert_buffer())));
124
Matt Muellere6df72cb2023-04-12 22:08:37125 base::RunLoop update_run_loop;
126 content::GetCertVerifierServiceFactory()->UpdateChromeRootStore(
Alex Gougha67cd0b2024-04-17 17:17:31127 mojo_base::ProtoWrapper(root_store), update_run_loop.QuitClosure());
Matt Muellere6df72cb2023-04-12 22:08:37128 update_run_loop.Run();
129 }
130
Hubert Chao71a14a02023-12-01 18:04:37131 EXPECT_EQ(use_chrome_root_store(),
Emily Stark25f01b82024-04-19 00:04:50132 content::NavigateToURL(
133 GetActiveWebContents(),
134 https_test_server.GetURL("example.com", "/simple.html")));
Matt Muellere6df72cb2023-04-12 22:08:37135
136 // The navigation should show an interstitial if CRS was not in use, since
137 // the root was only trusted in the test CRS update and won't be trusted by
138 // the platform roots that are used when CRS is not used.
Hubert Chao71a14a02023-12-01 18:04:37139 EXPECT_NE(use_chrome_root_store(),
Matt Muellere6df72cb2023-04-12 22:08:37140 chrome_browser_interstitials::IsShowingInterstitial(
Hubert Chao71a14a02023-12-01 18:04:37141 GetActiveWebContents()));
Matt Mueller5a85dd42022-08-17 17:07:56142}
143
Hubert Chao71a14a02023-12-01 18:04:37144INSTANTIATE_TEST_SUITE_P(All,
145 CertVerifierServiceChromeRootStoreOptionalTest,
146 ::testing::Bool());
Matt Mueller8b02b1902023-03-07 00:06:36147#endif // BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL)
Matt Muellere06ddcc2024-06-15 00:32:26148
149#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
150class CertVerifierTestCrsConstraintsSwitchTest : public PlatformBrowserTest {
151 public:
152 void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
153 net::EmbeddedTestServer::ServerCertificateConfig test_cert_config;
154 test_cert_config.dns_names = {"example.com"};
155 test_cert_config.root = net::EmbeddedTestServer::RootType::kUniqueRoot;
156 test_server1_.SetSSLConfig(test_cert_config);
157 test_server2_.SetSSLConfig(test_cert_config);
158 ASSERT_TRUE(test_server1_.InitializeAndListen());
159 ASSERT_TRUE(test_server2_.InitializeAndListen());
160
161 scoped_test_root_ =
162 net::ScopedTestRoot({test_server1_.GetRoot(), test_server2_.GetRoot()});
163
164 const std::array<uint8_t, crypto::kSHA256Length> root2_hash =
165 crypto::SHA256Hash(test_server2_.GetRoot()->cert_span());
166 const std::string switch_value =
167 base::HexEncode(root2_hash) + ":maxversionexclusive=0";
168
169 PlatformBrowserTest::SetUpDefaultCommandLine(command_line);
170 command_line->AppendSwitchASCII(
171 net::TrustStoreChrome::kTestCrsConstraintsSwitch, switch_value);
172 }
173
174 void SetUpOnMainThread() override {
175 PlatformBrowserTest::SetUpOnMainThread();
176
177 test_server1_.ServeFilesFromSourceDirectory("chrome/test/data");
178 test_server2_.ServeFilesFromSourceDirectory("chrome/test/data");
179 test_server1_.StartAcceptingConnections();
180 test_server2_.StartAcceptingConnections();
181
182 host_resolver()->AddRule("*", "127.0.0.1");
183 }
184
185 protected:
186 content::WebContents* GetActiveWebContents() {
187 return chrome_test_utils::GetActiveWebContents(this);
188 }
189
190 net::EmbeddedTestServer test_server1_{net::EmbeddedTestServer::TYPE_HTTPS};
191 net::EmbeddedTestServer test_server2_{net::EmbeddedTestServer::TYPE_HTTPS};
192 net::ScopedTestRoot scoped_test_root_;
193};
194
195// End-to-end test to verify that the --test-crs-constraints switch is honored
196// when loading webpages in the browser. (More extensive testing of the various
197// features of the switch is handled by unittests.)
198IN_PROC_BROWSER_TEST_F(CertVerifierTestCrsConstraintsSwitchTest,
199 TestSwitchIsHonored) {
200 // First server does not have any test constraints set, and should load
201 // successfully.
202 EXPECT_TRUE(content::NavigateToURL(
203 GetActiveWebContents(),
204 test_server1_.GetURL("example.com", "/simple.html")));
205 EXPECT_FALSE(chrome_browser_interstitials::IsShowingInterstitial(
206 GetActiveWebContents()));
207
208 // Second server has test constraints set for its root with a
209 // max_version_exclusive of 0. The browser version should be greater than 0
210 // so this root will not be trusted.
211 EXPECT_FALSE(content::NavigateToURL(
212 GetActiveWebContents(),
213 test_server2_.GetURL("example.com", "/simple.html")));
214 EXPECT_TRUE(chrome_browser_interstitials::IsShowingInterstitial(
215 GetActiveWebContents()));
216}
217#endif // BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
Hubert Chao7299aa6b2024-10-03 18:20:22218
219#if BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)
220
221class CertVerifierUserSettingsTest : public PlatformBrowserTest {
222 public:
223 CertVerifierUserSettingsTest() {
224 feature_list_.InitWithFeatures({features::kEnableCertManagementUIV2,
225 features::kEnableCertManagementUIV2Write},
226 {});
227 }
228
Matt Muellerfc1bb39a2024-10-29 00:16:46229 testing::AssertionResult AddCertificateToDatabaseAndWaitForVerifierUpdate(
230 net::ServerCertificateDatabase::CertInformation cert_info) {
Hubert Chao93eefacc2024-10-23 01:07:38231 base::test::TestFuture<void> cert_verifier_service_update_waiter;
232 browser()
233 ->profile()
234 ->GetDefaultStoragePartition()
235 ->GetCertVerifierServiceUpdater()
236 ->WaitUntilNextUpdateForTesting(
237 cert_verifier_service_update_waiter.GetCallback());
Matt Muellerfc1bb39a2024-10-29 00:16:46238 base::test::TestFuture<bool> future;
Hubert Chaod4b21142024-11-22 17:00:37239 std::vector<net::ServerCertificateDatabase::CertInformation> cert_infos;
240 cert_infos.push_back(std::move(cert_info));
Matt Muellerfc1bb39a2024-10-29 00:16:46241 net::ServerCertificateDatabaseServiceFactory::GetForBrowserContext(
242 browser()->profile())
Hubert Chaod4b21142024-11-22 17:00:37243 ->AddOrUpdateUserCertificates(std::move(cert_infos),
244 future.GetCallback());
Matt Muellerfc1bb39a2024-10-29 00:16:46245 if (!future.Get()) {
246 return testing::AssertionFailure() << "database update failed";
247 }
248 if (!cert_verifier_service_update_waiter.Wait()) {
249 return testing::AssertionFailure() << "wait for verifier update failed";
250 }
251 return testing::AssertionSuccess();
Hubert Chao93eefacc2024-10-23 01:07:38252 }
253
Hubert Chao7299aa6b2024-10-03 18:20:22254 private:
255 base::test::ScopedFeatureList feature_list_;
256};
257
258IN_PROC_BROWSER_TEST_F(CertVerifierUserSettingsTest, TestUserSettingsUsed) {
259 net::EmbeddedTestServer https_test_server{
260 net::EmbeddedTestServer::TYPE_HTTPS};
261 net::EmbeddedTestServer::ServerCertificateConfig test_cert_config;
262 test_cert_config.intermediate =
263 net::EmbeddedTestServer::IntermediateType::kMissing;
264 test_cert_config.root = net::EmbeddedTestServer::RootType::kUniqueRoot;
265 https_test_server.SetSSLConfig(test_cert_config);
266
267 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
268 ASSERT_TRUE(https_test_server.Start());
269
Hubert Chao7299aa6b2024-10-03 18:20:22270 {
271 scoped_refptr<net::X509Certificate> root_cert = https_test_server.GetRoot();
Matt Mueller778dfcb2024-12-10 19:02:14272 net::ServerCertificateDatabase::CertInformation user_root_info(
273 root_cert->cert_span());
Hubert Chao7299aa6b2024-10-03 18:20:22274 user_root_info.cert_metadata.mutable_trust()->set_trust_type(
275 chrome_browser_server_certificate_database::CertificateTrust::
276 CERTIFICATE_TRUST_TYPE_TRUSTED);
Hubert Chao7299aa6b2024-10-03 18:20:22277
Matt Muellerfc1bb39a2024-10-29 00:16:46278 ASSERT_TRUE(AddCertificateToDatabaseAndWaitForVerifierUpdate(
279 std::move(user_root_info)));
Hubert Chao7299aa6b2024-10-03 18:20:22280 }
281 {
282 scoped_refptr<net::X509Certificate> hint_cert =
283 https_test_server.GetGeneratedIntermediate();
Matt Mueller778dfcb2024-12-10 19:02:14284 net::ServerCertificateDatabase::CertInformation user_hint_info(
285 hint_cert->cert_span());
Hubert Chao7299aa6b2024-10-03 18:20:22286 user_hint_info.cert_metadata.mutable_trust()->set_trust_type(
287 chrome_browser_server_certificate_database::CertificateTrust::
288 CERTIFICATE_TRUST_TYPE_UNSPECIFIED);
Hubert Chao7299aa6b2024-10-03 18:20:22289
Matt Muellerfc1bb39a2024-10-29 00:16:46290 ASSERT_TRUE(AddCertificateToDatabaseAndWaitForVerifierUpdate(
291 std::move(user_hint_info)));
Hubert Chao7299aa6b2024-10-03 18:20:22292 }
293
Hubert Chao7299aa6b2024-10-03 18:20:22294 // Clear test roots so that cert validation only happens with
295 // what's in the relevant root store + user settings.
296 net::TestRootCerts::GetInstance()->Clear();
297 ASSERT_TRUE(ui_test_utils::NavigateToURL(
298 browser(), https_test_server.GetURL("/simple.html")));
299 EXPECT_FALSE(chrome_browser_interstitials::IsShowingInterstitial(
300 chrome_test_utils::GetActiveWebContents(this)));
301}
302
303IN_PROC_BROWSER_TEST_F(CertVerifierUserSettingsTest,
Hubert Chao28f5cfa2024-10-07 22:57:08304 TestUserSettingsUsedAnchorConstraints) {
305 net::EmbeddedTestServer https_test_server{
306 net::EmbeddedTestServer::TYPE_HTTPS};
307 // Use a certificate valid for the dns name localhost rather than an IP.
308 https_test_server.SetSSLConfig(
309 net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
310
311 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
312 ASSERT_TRUE(https_test_server.Start());
313
Hubert Chao28f5cfa2024-10-07 22:57:08314 {
315 scoped_refptr<net::X509Certificate> root_cert =
316 net::ImportCertFromFile(net::EmbeddedTestServer::GetRootCertPemPath());
317 ASSERT_TRUE(root_cert);
Matt Mueller778dfcb2024-12-10 19:02:14318 net::ServerCertificateDatabase::CertInformation user_root_info(
319 root_cert->cert_span());
Hubert Chao28f5cfa2024-10-07 22:57:08320 user_root_info.cert_metadata.mutable_trust()->set_trust_type(
321 chrome_browser_server_certificate_database::CertificateTrust::
322 CERTIFICATE_TRUST_TYPE_TRUSTED);
323 user_root_info.cert_metadata.mutable_constraints()->add_dns_names(
324 "localhost");
Hubert Chao28f5cfa2024-10-07 22:57:08325
Matt Muellerfc1bb39a2024-10-29 00:16:46326 ASSERT_TRUE(AddCertificateToDatabaseAndWaitForVerifierUpdate(
327 std::move(user_root_info)));
Hubert Chao28f5cfa2024-10-07 22:57:08328 }
329
Hubert Chao28f5cfa2024-10-07 22:57:08330 // Clear test roots so that cert validation only happens with
331 // what's in the relevant root store + user settings.
332 net::TestRootCerts::GetInstance()->Clear();
333 ASSERT_TRUE(ui_test_utils::NavigateToURL(
334 browser(), https_test_server.GetURL("/simple.html")));
335 EXPECT_FALSE(chrome_browser_interstitials::IsShowingInterstitial(
336 chrome_test_utils::GetActiveWebContents(this)));
337}
338
339IN_PROC_BROWSER_TEST_F(CertVerifierUserSettingsTest,
340 TestUserSettingsUsedAnchorConstraintsWrongConstraint) {
341 net::EmbeddedTestServer https_test_server{
342 net::EmbeddedTestServer::TYPE_HTTPS};
343 // Use a certificate valid for the dns name localhost rather than an IP.
344 https_test_server.SetSSLConfig(
345 net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
346
347 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
348 ASSERT_TRUE(https_test_server.Start());
349
Hubert Chao28f5cfa2024-10-07 22:57:08350 {
351 scoped_refptr<net::X509Certificate> root_cert =
352 net::ImportCertFromFile(net::EmbeddedTestServer::GetRootCertPemPath());
353 ASSERT_TRUE(root_cert);
Matt Mueller778dfcb2024-12-10 19:02:14354 net::ServerCertificateDatabase::CertInformation user_root_info(
355 root_cert->cert_span());
Hubert Chao28f5cfa2024-10-07 22:57:08356 user_root_info.cert_metadata.mutable_trust()->set_trust_type(
357 chrome_browser_server_certificate_database::CertificateTrust::
358 CERTIFICATE_TRUST_TYPE_TRUSTED);
359 user_root_info.cert_metadata.mutable_constraints()->add_dns_names(
360 "cruddyhost");
Hubert Chao28f5cfa2024-10-07 22:57:08361
Matt Muellerfc1bb39a2024-10-29 00:16:46362 ASSERT_TRUE(AddCertificateToDatabaseAndWaitForVerifierUpdate(
363 std::move(user_root_info)));
Hubert Chao28f5cfa2024-10-07 22:57:08364 }
365
Hubert Chao28f5cfa2024-10-07 22:57:08366 // Clear test roots so that cert validation only happens with
367 // what's in the relevant root store + user settings.
368 net::TestRootCerts::GetInstance()->Clear();
369 ASSERT_TRUE(ui_test_utils::NavigateToURL(
370 browser(), https_test_server.GetURL("/simple.html")));
371 EXPECT_TRUE(chrome_browser_interstitials::IsShowingInterstitial(
372 chrome_test_utils::GetActiveWebContents(this)));
373}
374
375IN_PROC_BROWSER_TEST_F(CertVerifierUserSettingsTest,
Hubert Chao7299aa6b2024-10-03 18:20:22376 TestUserSettingsUsedDistrusted) {
377 net::EmbeddedTestServer https_test_server(
378 net::EmbeddedTestServer::TYPE_HTTPS);
379 https_test_server.SetSSLConfig(
380 net::test_server::EmbeddedTestServer::CERT_AUTO);
381 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
382 ASSERT_TRUE(https_test_server.Start());
Hubert Chao7299aa6b2024-10-03 18:20:22383
384 scoped_refptr<net::X509Certificate> root_cert =
385 net::ImportCertFromFile(net::EmbeddedTestServer::GetRootCertPemPath());
386 ASSERT_TRUE(root_cert);
387
Matt Mueller778dfcb2024-12-10 19:02:14388 net::ServerCertificateDatabase::CertInformation cert_info(
389 root_cert->cert_span());
Hubert Chao7299aa6b2024-10-03 18:20:22390 cert_info.cert_metadata.mutable_trust()->set_trust_type(
391 chrome_browser_server_certificate_database::CertificateTrust::
392 CERTIFICATE_TRUST_TYPE_DISTRUSTED);
Hubert Chao7299aa6b2024-10-03 18:20:22393
Matt Muellerfc1bb39a2024-10-29 00:16:46394 ASSERT_TRUE(
395 AddCertificateToDatabaseAndWaitForVerifierUpdate(std::move(cert_info)));
Hubert Chao7299aa6b2024-10-03 18:20:22396
397 // We don't clear test roots; the distrusted addition in the user db should
398 // override the test root trust.
399 ASSERT_TRUE(ui_test_utils::NavigateToURL(
400 browser(), https_test_server.GetURL("/simple.html")));
401 EXPECT_TRUE(chrome_browser_interstitials::IsShowingInterstitial(
402 chrome_test_utils::GetActiveWebContents(this)));
403}
404
405IN_PROC_BROWSER_TEST_F(CertVerifierUserSettingsTest,
406 TestUserSettingsUsedDistrustedIncognito) {
407 net::EmbeddedTestServer https_test_server(
408 net::EmbeddedTestServer::TYPE_HTTPS);
409 https_test_server.SetSSLConfig(
410 net::test_server::EmbeddedTestServer::CERT_AUTO);
411 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
412 ASSERT_TRUE(https_test_server.Start());
Hubert Chao7299aa6b2024-10-03 18:20:22413
414 scoped_refptr<net::X509Certificate> root_cert =
415 net::ImportCertFromFile(net::EmbeddedTestServer::GetRootCertPemPath());
416 ASSERT_TRUE(root_cert);
417
Matt Mueller778dfcb2024-12-10 19:02:14418 net::ServerCertificateDatabase::CertInformation cert_info(
419 root_cert->cert_span());
Hubert Chao7299aa6b2024-10-03 18:20:22420 cert_info.cert_metadata.mutable_trust()->set_trust_type(
421 chrome_browser_server_certificate_database::CertificateTrust::
422 CERTIFICATE_TRUST_TYPE_DISTRUSTED);
Hubert Chao7299aa6b2024-10-03 18:20:22423
Matt Muellerfc1bb39a2024-10-29 00:16:46424 ASSERT_TRUE(
425 AddCertificateToDatabaseAndWaitForVerifierUpdate(std::move(cert_info)));
Hubert Chao7299aa6b2024-10-03 18:20:22426
427 Browser* incognito_browser = CreateIncognitoBrowser();
428
429 // We don't clear test roots; the distrusted addition in the user db should
430 // override the test root trust, even for incognito.
431 ASSERT_TRUE(ui_test_utils::NavigateToURL(
432 incognito_browser, https_test_server.GetURL("/simple.html")));
433 EXPECT_TRUE(chrome_browser_interstitials::IsShowingInterstitial(
434 incognito_browser->tab_strip_model()->GetActiveWebContents()));
435}
Hubert Chao28f5cfa2024-10-07 22:57:08436
437IN_PROC_BROWSER_TEST_F(CertVerifierUserSettingsTest,
438 TestUserSettingsTrustedLeaf) {
439 net::EmbeddedTestServer https_test_server(
440 net::EmbeddedTestServer::TYPE_HTTPS);
441 https_test_server.SetSSLConfig(
442 net::test_server::EmbeddedTestServer::CERT_AUTO);
443 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
444 ASSERT_TRUE(https_test_server.Start());
Hubert Chao28f5cfa2024-10-07 22:57:08445
446 scoped_refptr<net::X509Certificate> leaf_cert =
447 https_test_server.GetCertificate();
448 ASSERT_TRUE(leaf_cert);
449
Matt Mueller778dfcb2024-12-10 19:02:14450 net::ServerCertificateDatabase::CertInformation cert_info(
451 leaf_cert->cert_span());
Hubert Chao28f5cfa2024-10-07 22:57:08452 cert_info.cert_metadata.mutable_trust()->set_trust_type(
453 chrome_browser_server_certificate_database::CertificateTrust::
454 CERTIFICATE_TRUST_TYPE_TRUSTED);
Hubert Chao28f5cfa2024-10-07 22:57:08455
456 // Sanity check.
457 ASSERT_EQ(net::ServerCertificateDatabase::GetUserCertificateTrust(cert_info),
458 bssl::CertificateTrustType::TRUSTED_LEAF);
459
Matt Muellerfc1bb39a2024-10-29 00:16:46460 ASSERT_TRUE(
461 AddCertificateToDatabaseAndWaitForVerifierUpdate(std::move(cert_info)));
Hubert Chao28f5cfa2024-10-07 22:57:08462
463 // Clear test roots so that cert validation only happens with
464 // what's in the relevant root store + user settings.
465 net::TestRootCerts::GetInstance()->Clear();
466 ASSERT_TRUE(ui_test_utils::NavigateToURL(
467 browser(), https_test_server.GetURL("/simple.html")));
468 EXPECT_FALSE(chrome_browser_interstitials::IsShowingInterstitial(
469 chrome_test_utils::GetActiveWebContents(this)));
470}
471
Hubert Chao93eefacc2024-10-23 01:07:38472IN_PROC_BROWSER_TEST_F(CertVerifierUserSettingsTest,
473 TestUserSettingsTrustedLeafAnchorAsLeaf) {
474 net::EmbeddedTestServer https_test_server(
475 net::EmbeddedTestServer::TYPE_HTTPS);
476 net::EmbeddedTestServer::ServerCertificateConfig test_cert_config;
477 test_cert_config.leaf_is_ca = true;
478 test_cert_config.root = net::EmbeddedTestServer::RootType::kUniqueRoot;
479 https_test_server.SetSSLConfig(test_cert_config);
480 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
481 ASSERT_TRUE(https_test_server.Start());
Hubert Chao93eefacc2024-10-23 01:07:38482
483 scoped_refptr<net::X509Certificate> leaf_cert =
484 https_test_server.GetCertificate();
485 ASSERT_TRUE(leaf_cert);
486
Matt Mueller778dfcb2024-12-10 19:02:14487 net::ServerCertificateDatabase::CertInformation cert_info(
488 leaf_cert->cert_span());
Hubert Chao93eefacc2024-10-23 01:07:38489 cert_info.cert_metadata.mutable_trust()->set_trust_type(
490 chrome_browser_server_certificate_database::CertificateTrust::
491 CERTIFICATE_TRUST_TYPE_TRUSTED);
Hubert Chao93eefacc2024-10-23 01:07:38492
493 // Sanity check.
494 ASSERT_EQ(net::ServerCertificateDatabase::GetUserCertificateTrust(cert_info),
495 bssl::CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF);
496
Matt Muellerfc1bb39a2024-10-29 00:16:46497 ASSERT_TRUE(
498 AddCertificateToDatabaseAndWaitForVerifierUpdate(std::move(cert_info)));
Hubert Chao93eefacc2024-10-23 01:07:38499
500 // Clear test roots so that cert validation only happens with
501 // what's in the relevant root store + user settings.
502 net::TestRootCerts::GetInstance()->Clear();
503 ASSERT_TRUE(ui_test_utils::NavigateToURL(
504 browser(), https_test_server.GetURL("/simple.html")));
505 EXPECT_FALSE(chrome_browser_interstitials::IsShowingInterstitial(
506 chrome_test_utils::GetActiveWebContents(this)));
507}
508
509IN_PROC_BROWSER_TEST_F(CertVerifierUserSettingsTest,
510 TestUserSettingsTrustedLeafAnchorAsAnchor) {
511 net::EmbeddedTestServer https_test_server(
512 net::EmbeddedTestServer::TYPE_HTTPS);
513 net::EmbeddedTestServer::ServerCertificateConfig test_cert_config;
514 test_cert_config.root_dns_names = {"example.com"};
515 test_cert_config.root = net::EmbeddedTestServer::RootType::kUniqueRoot;
516 https_test_server.SetSSLConfig(test_cert_config);
517 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
518 ASSERT_TRUE(https_test_server.Start());
Hubert Chao93eefacc2024-10-23 01:07:38519
520 scoped_refptr<net::X509Certificate> root_cert = https_test_server.GetRoot();
521 ASSERT_TRUE(root_cert);
522
Matt Mueller778dfcb2024-12-10 19:02:14523 net::ServerCertificateDatabase::CertInformation cert_info(
524 root_cert->cert_span());
Hubert Chao93eefacc2024-10-23 01:07:38525 cert_info.cert_metadata.mutable_trust()->set_trust_type(
526 chrome_browser_server_certificate_database::CertificateTrust::
527 CERTIFICATE_TRUST_TYPE_TRUSTED);
Hubert Chao93eefacc2024-10-23 01:07:38528
529 // Sanity check.
530 ASSERT_EQ(net::ServerCertificateDatabase::GetUserCertificateTrust(cert_info),
531 bssl::CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF);
532
Matt Muellerfc1bb39a2024-10-29 00:16:46533 ASSERT_TRUE(
534 AddCertificateToDatabaseAndWaitForVerifierUpdate(std::move(cert_info)));
Hubert Chao93eefacc2024-10-23 01:07:38535
536 // Clear test roots so that cert validation only happens with
537 // what's in the relevant root store + user settings.
538 net::TestRootCerts::GetInstance()->Clear();
539 ASSERT_TRUE(ui_test_utils::NavigateToURL(
540 browser(), https_test_server.GetURL("example.com", "/simple.html")));
541 EXPECT_FALSE(chrome_browser_interstitials::IsShowingInterstitial(
542 chrome_test_utils::GetActiveWebContents(this)));
543}
Hubert Chao28f5cfa2024-10-07 22:57:08544
Matt Muellerdd3443572024-10-11 22:47:22545#if BUILDFLAG(IS_CHROMEOS)
546class CertVerifierNSSMigrationTest : public PlatformBrowserTest {
547 public:
548 CertVerifierNSSMigrationTest() {
549 const std::vector<base::test::FeatureRef> feature_flags = {
550 features::kEnableCertManagementUIV2,
551 features::kEnableCertManagementUIV2Write};
552 if (GetTestPreCount() == 2) {
553 feature_list_.InitWithFeatures(/*enabled_features=*/{},
554 /*disabled_features=*/feature_flags);
555 } else {
556 feature_list_.InitWithFeatures(/*enabled_features=*/feature_flags,
557 /*disabled_features=*/{});
558 }
559 }
560
561 protected:
562 base::HistogramTester histogram_tester_;
563
564 private:
565 base::test::ScopedFeatureList feature_list_;
566};
567
568// Setup the NSS database before doing migration. The PRE_PRE_ test is run with
569// the feature flag disabled so migration will not be attempted yet.
570IN_PROC_BROWSER_TEST_F(CertVerifierNSSMigrationTest,
571 PRE_PRE_TestNSSCertMigration) {
572 // PRE_ test and main test don't share state, so there isn't an easy way use a
573 // generated EmbeddedTestServer cert in the PRE_ test and then run an
574 // EmbeddedTestServer with the same generated cert in the main test. Therefore
575 // we test the migration by importing the static test root and disabling
576 // TestRootCerts.
577 // Import test root as trusted in the NSS database.
578 scoped_refptr<net::X509Certificate> test_root =
579 net::ImportCertFromFile(net::EmbeddedTestServer::GetRootCertPemPath());
580 ASSERT_TRUE(test_root);
581 base::test::TestFuture<net::NSSCertDatabase*> nss_waiter;
582 NssServiceFactory::GetForContext(browser()->profile())
583 ->UnsafelyGetNSSCertDatabaseForTesting(nss_waiter.GetCallback());
584 net::NSSCertDatabase* nss_db = nss_waiter.Get();
585 net::NSSCertDatabase::ImportCertFailureList not_imported;
586 EXPECT_TRUE(nss_db->ImportCACerts(
587 net::x509_util::CreateCERTCertificateListFromX509Certificate(
588 test_root.get()),
589 net::NSSCertDatabase::TRUSTED_SSL, &not_imported));
590 EXPECT_TRUE(not_imported.empty());
591
592 // Migration pref should be false.
593 EXPECT_EQ(browser()->profile()->GetPrefs()->GetInteger(
594 prefs::kNSSCertsMigratedToServerCertDb),
595 static_cast<int>(net::ServerCertificateDatabaseService::
596 NSSMigrationResultPref::kNotMigrated));
597 histogram_tester_.ExpectTotalCount("Net.CertVerifier.NSSCertMigrationResult",
598 0);
599 histogram_tester_.ExpectTotalCount(
600 "Net.CertVerifier.NSSCertMigrationQueuedRequestsWhenFinished", 0);
601}
602
603// Tests that when the feature flag is set, NSS cert migration is done on
604// initialization and that the verification is blocked on the migration
605// completing.
606IN_PROC_BROWSER_TEST_F(CertVerifierNSSMigrationTest, PRE_TestNSSCertMigration) {
607 net::EmbeddedTestServer https_test_server{
608 net::EmbeddedTestServer::TYPE_HTTPS};
609
610 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
611 ASSERT_TRUE(https_test_server.Start());
612
613 // Clear test roots so that cert validation only happens with
614 // what's in the relevant root store.
615 net::TestRootCerts::GetInstance()->Clear();
616 // Loading the page should succeed since the root was trusted through the
617 // server cert db.
618 ASSERT_TRUE(ui_test_utils::NavigateToURL(
619 browser(), https_test_server.GetURL("/simple.html")));
620 // TODO(https://crbug.com/40928765): This should not be
621 // SECURE_WITH_POLICY_INSTALLED_CERT, it should just be SECURE. The
622 // additional certs provided to the verifier need some additional flag to
623 // indicate which ones are policy provided and which are user added.
624 ssl_test_util::CheckSecurityState(
625 chrome_test_utils::GetActiveWebContents(this),
626 ssl_test_util::CertError::NONE,
627 security_state::SECURE_WITH_POLICY_INSTALLED_CERT,
628 ssl_test_util::AuthState::NONE);
629
630 // Migration pref should be true now.
631 EXPECT_EQ(
632 browser()->profile()->GetPrefs()->GetInteger(
633 prefs::kNSSCertsMigratedToServerCertDb),
634 static_cast<int>(net::ServerCertificateDatabaseService::
635 NSSMigrationResultPref::kMigratedSuccessfully));
636
637 // Migration histograms should have been recorded. ExpectUniqueSample is not
638 // used here as the ChromeOS browsertests seem to create multiple users so
639 // this histogram may be recorded multiple times (the other samples would be
640 // kEmpty).
641 histogram_tester_.ExpectBucketCount("Net.CertVerifier.NSSCertMigrationResult",
642 net::ServerCertificateDatabaseService::
643 NSSMigrationResultHistogram::kSuccess,
644 1);
645 // The Net.CertVerifier.NSSCertMigrationQueuedRequestsWhenFinished histogram
646 // should have been recorded too, but it may not be possible to predict what
647 // the buckets will be, so only verify that it was recorded at all.
648 EXPECT_GT(histogram_tester_.GetTotalSum(
649 "Net.CertVerifier.NSSCertMigrationQueuedRequestsWhenFinished"),
650 0);
651
652 // Set root cert in NSS to distrusted. This ensures that when the next phase
653 // of the test runs it's actually the trust from the server cert db causing
654 // the connection to succeed and not still using the NSS trust, and also
655 // tests that the migration is not run again.
656 scoped_refptr<net::X509Certificate> test_root =
657 net::ImportCertFromFile(net::EmbeddedTestServer::GetRootCertPemPath());
658 ASSERT_TRUE(test_root);
659 base::test::TestFuture<net::NSSCertDatabase*> nss_waiter;
660 NssServiceFactory::GetForContext(browser()->profile())
661 ->UnsafelyGetNSSCertDatabaseForTesting(nss_waiter.GetCallback());
662 net::NSSCertDatabase* nss_db = nss_waiter.Get();
663 nss_db->SetCertTrust(
664 net::x509_util::CreateCERTCertificateFromX509Certificate(test_root.get())
665 .get(),
666 net::CertType::CA_CERT, net::NSSCertDatabase::DISTRUSTED_SSL);
667}
668
669// Tests that after migration is done the NSS user db is no longer depended on.
670IN_PROC_BROWSER_TEST_F(CertVerifierNSSMigrationTest, TestNSSCertMigration) {
671 // Migration pref should already be true.
672 EXPECT_EQ(
673 browser()->profile()->GetPrefs()->GetInteger(
674 prefs::kNSSCertsMigratedToServerCertDb),
675 static_cast<int>(net::ServerCertificateDatabaseService::
676 NSSMigrationResultPref::kMigratedSuccessfully));
677
678 net::EmbeddedTestServer https_test_server{
679 net::EmbeddedTestServer::TYPE_HTTPS};
680 https_test_server.ServeFilesFromSourceDirectory("chrome/test/data");
681 ASSERT_TRUE(https_test_server.Start());
682
683 // Clear test roots so that cert validation only happens with
684 // what's in the relevant root store.
685 net::TestRootCerts::GetInstance()->Clear();
686 // Loading the page should succeed since the root was trusted through the
687 // server cert db. The distrust set in NSS should be ignored as NSS user db
688 // is no longer used.
689 ASSERT_TRUE(ui_test_utils::NavigateToURL(
690 browser(), https_test_server.GetURL("/simple.html")));
691 // TODO(https://crbug.com/40928765): This should not be
692 // SECURE_WITH_POLICY_INSTALLED_CERT, it should just be SECURE. The
693 // additional certs provided to the verifier need some additional flag to
694 // indicate which ones are policy provided and which are user added.
695 ssl_test_util::CheckSecurityState(
696 chrome_test_utils::GetActiveWebContents(this),
697 ssl_test_util::CertError::NONE,
698 security_state::SECURE_WITH_POLICY_INSTALLED_CERT,
699 ssl_test_util::AuthState::NONE);
700
701 histogram_tester_.ExpectTotalCount("Net.CertVerifier.NSSCertMigrationResult",
702 0);
703 histogram_tester_.ExpectTotalCount(
704 "Net.CertVerifier.NSSCertMigrationQueuedRequestsWhenFinished", 0);
705}
706#endif // BUILDFLAG(IS_CHROMEOS)
707
Hubert Chao7299aa6b2024-10-03 18:20:22708#endif // BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI)