1 // Copyright 2017 The Chromium Authors
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 "net/cert/internal/system_trust_store.h"
6
7 #include <memory>
8 #include <optional>
9 #include <vector>
10
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/no_destructor.h"
16 #include "base/task/task_traits.h"
17 #include "base/task/thread_pool.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "build/build_config.h"
20 #include "crypto/crypto_buildflags.h"
21 #include "net/cert/x509_certificate.h"
22 #include "net/cert/x509_util.h"
23 #include "third_party/boringssl/src/pki/cert_errors.h"
24 #include "third_party/boringssl/src/pki/parsed_certificate.h"
25 #include "third_party/boringssl/src/pki/trust_store_collection.h"
26 #include "third_party/boringssl/src/pki/trust_store_in_memory.h"
27
28 #if BUILDFLAG(USE_NSS_CERTS)
29 #include "net/cert/internal/system_trust_store_nss.h"
30 #include "net/cert/internal/trust_store_nss.h"
31 #elif BUILDFLAG(IS_MAC)
32 #include <Security/Security.h>
33
34 #include "net/base/features.h"
35 #include "net/cert/internal/trust_store_mac.h"
36 #include "net/cert/x509_util_apple.h"
37 #elif BUILDFLAG(IS_FUCHSIA)
38 #include "base/lazy_instance.h"
39 #include "third_party/boringssl/src/include/openssl/pool.h"
40 #elif BUILDFLAG(IS_WIN)
41 #include "net/cert/internal/trust_store_win.h"
42 #elif BUILDFLAG(IS_ANDROID)
43 #include "net/cert/internal/trust_store_android.h"
44 #endif
45
46 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
47 #include "net/cert/internal/trust_store_chrome.h"
48 #endif // CHROME_ROOT_STORE_SUPPORTED
49
50 #if BUILDFLAG(IS_CHROMEOS)
51 #include "base/system/sys_info.h"
52 #endif
53
54 namespace net {
55
56 #if BUILDFLAG(IS_CHROMEOS)
57 namespace internal {
58 class PemFileCertStore {
59 public:
PemFileCertStore(std::string_view file_name)60 explicit PemFileCertStore(std::string_view file_name) {
61 // This will block on the cert verifier service thread, so the effect will
62 // just be to block any cert verifications (interactions with the cert
63 // verifier service are async mojo calls, so it shouldn't block the browser
64 // UI). There would be no benefit to moving this to a worker thread, since
65 // all cert verifications would still need to block on loading of the roots
66 // to complete.
67 base::ScopedAllowBlocking allow_blocking;
68 std::optional<std::vector<uint8_t>> certs_file =
69 base::ReadFileToBytes(base::FilePath(file_name));
70 if (!certs_file) {
71 return;
72 }
73
74 trust_store_ = std::make_unique<bssl::TrustStoreInMemory>();
75
76 CertificateList certs = X509Certificate::CreateCertificateListFromBytes(
77 *certs_file, X509Certificate::FORMAT_AUTO);
78
79 for (const auto& cert : certs) {
80 bssl::CertErrors errors;
81 auto parsed = bssl::ParsedCertificate::Create(
82 bssl::UpRef(cert->cert_buffer()),
83 x509_util::DefaultParseCertificateOptions(), &errors);
84 if (!parsed) {
85 LOG(ERROR) << file_name << ": " << errors.ToDebugString();
86 continue;
87 }
88 trust_store_->AddTrustAnchor(std::move(parsed));
89 }
90 }
91
trust_store()92 bssl::TrustStoreInMemory* trust_store() { return trust_store_.get(); }
93
94 private:
95 std::unique_ptr<bssl::TrustStoreInMemory> trust_store_;
96 };
97 } // namespace internal
98
99 namespace {
100
101 // On ChromeOS look for a PEM file of root CA certs to trust which may be
102 // present on test images.
GetChromeOSTestTrustStore()103 bssl::TrustStoreInMemory* GetChromeOSTestTrustStore() {
104 constexpr char kCrosTestRootCertsFile[] = "/etc/fake_root_ca_certs.pem";
105 static base::NoDestructor<internal::PemFileCertStore> cros_test_roots{
106 kCrosTestRootCertsFile};
107 return cros_test_roots->trust_store();
108 }
109
110 } // namespace
111 #endif
112
113 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
114 class SystemTrustStoreChromeWithUnOwnedSystemStore : public SystemTrustStore {
115 public:
116 // Creates a SystemTrustStore that gets publicly trusted roots from
117 // |trust_store_chrome| and local trust settings from |trust_store_system|,
118 // if non-null. Does not take ownership of |trust_store_system|, which must
119 // outlive this object.
SystemTrustStoreChromeWithUnOwnedSystemStore(std::unique_ptr<TrustStoreChrome> trust_store_chrome,net::PlatformTrustStore * trust_store_system)120 explicit SystemTrustStoreChromeWithUnOwnedSystemStore(
121 std::unique_ptr<TrustStoreChrome> trust_store_chrome,
122 net::PlatformTrustStore* trust_store_system)
123 : trust_store_chrome_(std::move(trust_store_chrome)),
124 platform_trust_store_(trust_store_system) {
125 #if BUILDFLAG(IS_CHROMEOS)
126 if (GetChromeOSTestTrustStore()) {
127 // The fake_root_ca_certs.pem file is only intended for testing purposes,
128 // crash if it is present on a ChromeOS device in a non-test image.
129 base::SysInfo::CrashIfChromeOSNonTestImage();
130
131 trust_store_collection_.AddTrustStore(GetChromeOSTestTrustStore());
132 non_crs_trust_store_collection_.AddTrustStore(
133 GetChromeOSTestTrustStore());
134 }
135 #endif
136 if (trust_store_system) {
137 trust_store_collection_.AddTrustStore(trust_store_system);
138 non_crs_trust_store_collection_.AddTrustStore(trust_store_system);
139 }
140
141 trust_store_collection_.AddTrustStore(trust_store_chrome_.get());
142 }
143
GetTrustStore()144 bssl::TrustStore* GetTrustStore() override {
145 return &trust_store_collection_;
146 }
147
148 // IsKnownRoot returns true if the given trust anchor is a standard one (as
149 // opposed to a user-installed root)
IsKnownRoot(const bssl::ParsedCertificate * trust_anchor) const150 bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const override {
151 return trust_store_chrome_->Contains(trust_anchor);
152 }
153
IsLocallyTrustedRoot(const bssl::ParsedCertificate * trust_anchor)154 bool IsLocallyTrustedRoot(
155 const bssl::ParsedCertificate* trust_anchor) override {
156 return non_crs_trust_store_collection_.GetTrust(trust_anchor)
157 .IsTrustAnchor();
158 }
159
chrome_root_store_version() const160 int64_t chrome_root_store_version() const override {
161 return trust_store_chrome_->version();
162 }
163
GetChromeRootConstraints(const bssl::ParsedCertificate * cert) const164 base::span<const ChromeRootCertConstraints> GetChromeRootConstraints(
165 const bssl::ParsedCertificate* cert) const override {
166 return trust_store_chrome_->GetConstraintsForCert(cert);
167 }
168
GetPlatformTrustStore()169 net::PlatformTrustStore* GetPlatformTrustStore() override {
170 return platform_trust_store_;
171 }
172
173 private:
174 std::unique_ptr<TrustStoreChrome> trust_store_chrome_;
175 bssl::TrustStoreCollection trust_store_collection_;
176 bssl::TrustStoreCollection non_crs_trust_store_collection_;
177 net::PlatformTrustStore* platform_trust_store_;
178 };
179
CreateChromeOnlySystemTrustStore(std::unique_ptr<TrustStoreChrome> chrome_root)180 std::unique_ptr<SystemTrustStore> CreateChromeOnlySystemTrustStore(
181 std::unique_ptr<TrustStoreChrome> chrome_root) {
182 return std::make_unique<SystemTrustStoreChromeWithUnOwnedSystemStore>(
183 std::move(chrome_root), /*trust_store_system=*/nullptr);
184 }
185
186 class SystemTrustStoreChrome
187 : public SystemTrustStoreChromeWithUnOwnedSystemStore {
188 public:
189 // Creates a SystemTrustStore that gets publicly trusted roots from
190 // |trust_store_chrome| and local trust settings from |trust_store_system|.
SystemTrustStoreChrome(std::unique_ptr<TrustStoreChrome> trust_store_chrome,std::unique_ptr<net::PlatformTrustStore> trust_store_system)191 explicit SystemTrustStoreChrome(
192 std::unique_ptr<TrustStoreChrome> trust_store_chrome,
193 std::unique_ptr<net::PlatformTrustStore> trust_store_system)
194 : SystemTrustStoreChromeWithUnOwnedSystemStore(
195 std::move(trust_store_chrome),
196 trust_store_system.get()),
197 trust_store_system_(std::move(trust_store_system)) {}
198
199 private:
200 std::unique_ptr<net::PlatformTrustStore> trust_store_system_;
201 };
202
CreateSystemTrustStoreChromeForTesting(std::unique_ptr<TrustStoreChrome> trust_store_chrome,std::unique_ptr<net::PlatformTrustStore> trust_store_system)203 std::unique_ptr<SystemTrustStore> CreateSystemTrustStoreChromeForTesting(
204 std::unique_ptr<TrustStoreChrome> trust_store_chrome,
205 std::unique_ptr<net::PlatformTrustStore> trust_store_system) {
206 return std::make_unique<SystemTrustStoreChrome>(
207 std::move(trust_store_chrome), std::move(trust_store_system));
208 }
209 #endif // CHROME_ROOT_STORE_SUPPORTED
210
211 #if BUILDFLAG(USE_NSS_CERTS)
212
CreateSslSystemTrustStoreChromeRoot(std::unique_ptr<TrustStoreChrome> chrome_root)213 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot(
214 std::unique_ptr<TrustStoreChrome> chrome_root) {
215 return std::make_unique<SystemTrustStoreChrome>(
216 std::move(chrome_root), std::make_unique<TrustStoreNSS>(
217 TrustStoreNSS::UseTrustFromAllUserSlots()));
218 }
219
220 std::unique_ptr<SystemTrustStore>
CreateSslSystemTrustStoreChromeRootWithUserSlotRestriction(std::unique_ptr<TrustStoreChrome> chrome_root,crypto::ScopedPK11Slot user_slot_restriction)221 CreateSslSystemTrustStoreChromeRootWithUserSlotRestriction(
222 std::unique_ptr<TrustStoreChrome> chrome_root,
223 crypto::ScopedPK11Slot user_slot_restriction) {
224 return std::make_unique<SystemTrustStoreChrome>(
225 std::move(chrome_root),
226 std::make_unique<TrustStoreNSS>(std::move(user_slot_restriction)));
227 }
228
229 #elif BUILDFLAG(IS_MAC)
230
231 namespace {
232
GetGlobalTrustStoreMacForCRS()233 TrustStoreMac* GetGlobalTrustStoreMacForCRS() {
234 constexpr TrustStoreMac::TrustImplType kDefaultMacTrustImplForCRS =
235 TrustStoreMac::TrustImplType::kDomainCacheFullCerts;
236 static base::NoDestructor<TrustStoreMac> static_trust_store_mac(
237 kSecPolicyAppleSSL, kDefaultMacTrustImplForCRS);
238 return static_trust_store_mac.get();
239 }
240
InitializeTrustCacheForCRSOnWorkerThread()241 void InitializeTrustCacheForCRSOnWorkerThread() {
242 GetGlobalTrustStoreMacForCRS()->InitializeTrustCache();
243 }
244
245 } // namespace
246
CreateSslSystemTrustStoreChromeRoot(std::unique_ptr<TrustStoreChrome> chrome_root)247 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot(
248 std::unique_ptr<TrustStoreChrome> chrome_root) {
249 return std::make_unique<SystemTrustStoreChromeWithUnOwnedSystemStore>(
250 std::move(chrome_root), GetGlobalTrustStoreMacForCRS());
251 }
252
InitializeTrustStoreMacCache()253 void InitializeTrustStoreMacCache() {
254 base::ThreadPool::PostTask(
255 FROM_HERE,
256 {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
257 base::BindOnce(&InitializeTrustCacheForCRSOnWorkerThread));
258 }
259
260 #elif BUILDFLAG(IS_FUCHSIA)
261
262 namespace {
263
264 constexpr char kRootCertsFileFuchsia[] = "/config/ssl/cert.pem";
265
266 class FuchsiaSystemCerts {
267 public:
FuchsiaSystemCerts()268 FuchsiaSystemCerts() {
269 base::FilePath filename(kRootCertsFileFuchsia);
270 std::string certs_file;
271 if (!base::ReadFileToString(filename, &certs_file)) {
272 LOG(ERROR) << "Can't load root certificates from " << filename;
273 return;
274 }
275
276 CertificateList certs = X509Certificate::CreateCertificateListFromBytes(
277 base::as_byte_span(certs_file), X509Certificate::FORMAT_AUTO);
278
279 for (const auto& cert : certs) {
280 bssl::CertErrors errors;
281 auto parsed = bssl::ParsedCertificate::Create(
282 bssl::UpRef(cert->cert_buffer()),
283 x509_util::DefaultParseCertificateOptions(), &errors);
284 CHECK(parsed) << errors.ToDebugString();
285 system_trust_store_.AddTrustAnchor(std::move(parsed));
286 }
287 }
288
system_trust_store()289 bssl::TrustStoreInMemory* system_trust_store() {
290 return &system_trust_store_;
291 }
292
293 private:
294 bssl::TrustStoreInMemory system_trust_store_;
295 };
296
297 base::LazyInstance<FuchsiaSystemCerts>::Leaky g_root_certs_fuchsia =
298 LAZY_INSTANCE_INITIALIZER;
299
300 } // namespace
301
302 class SystemTrustStoreFuchsia : public SystemTrustStore {
303 public:
304 SystemTrustStoreFuchsia() = default;
305
GetTrustStore()306 bssl::TrustStore* GetTrustStore() override {
307 return g_root_certs_fuchsia.Get().system_trust_store();
308 }
309
IsKnownRoot(const bssl::ParsedCertificate * trust_anchor) const310 bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const override {
311 return g_root_certs_fuchsia.Get().system_trust_store()->Contains(
312 trust_anchor);
313 }
314 };
315
CreateSslSystemTrustStore()316 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
317 return std::make_unique<SystemTrustStoreFuchsia>();
318 }
319
320 #elif BUILDFLAG(IS_WIN)
321
322 namespace {
GetGlobalTrustStoreWinForCRS()323 TrustStoreWin* GetGlobalTrustStoreWinForCRS() {
324 static base::NoDestructor<TrustStoreWin> static_trust_store_win;
325 return static_trust_store_win.get();
326 }
327
InitializeTrustStoreForCRSOnWorkerThread()328 void InitializeTrustStoreForCRSOnWorkerThread() {
329 GetGlobalTrustStoreWinForCRS()->InitializeStores();
330 }
331 } // namespace
332
CreateSslSystemTrustStoreChromeRoot(std::unique_ptr<TrustStoreChrome> chrome_root)333 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot(
334 std::unique_ptr<TrustStoreChrome> chrome_root) {
335 return std::make_unique<SystemTrustStoreChromeWithUnOwnedSystemStore>(
336 std::move(chrome_root), GetGlobalTrustStoreWinForCRS());
337 }
338
339 // We do this in a separate thread as loading the Windows Cert Stores can cause
340 // quite a bit of I/O. See crbug.com/1399974 for more context.
InitializeTrustStoreWinSystem()341 void InitializeTrustStoreWinSystem() {
342 base::ThreadPool::PostTask(
343 FROM_HERE,
344 {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
345 base::BindOnce(&InitializeTrustStoreForCRSOnWorkerThread));
346 }
347
348 #elif BUILDFLAG(IS_ANDROID)
349
350 #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
351
352 namespace {
GetGlobalTrustStoreAndroidForCRS()353 TrustStoreAndroid* GetGlobalTrustStoreAndroidForCRS() {
354 static base::NoDestructor<TrustStoreAndroid> static_trust_store_android;
355 return static_trust_store_android.get();
356 }
357
InitializeTrustStoreForCRSOnWorkerThread()358 void InitializeTrustStoreForCRSOnWorkerThread() {
359 GetGlobalTrustStoreAndroidForCRS()->Initialize();
360 }
361 } // namespace
362
CreateSslSystemTrustStoreChromeRoot(std::unique_ptr<TrustStoreChrome> chrome_root)363 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot(
364 std::unique_ptr<TrustStoreChrome> chrome_root) {
365 return std::make_unique<SystemTrustStoreChromeWithUnOwnedSystemStore>(
366 std::move(chrome_root), GetGlobalTrustStoreAndroidForCRS());
367 }
368
InitializeTrustStoreAndroid()369 void InitializeTrustStoreAndroid() {
370 // Start observing DB change before the Trust Store is initialized so we don't
371 // accidentally miss any changes. See https://crrev.com/c/4226436 for context.
372 //
373 // This call is safe here because we're the only callers of
374 // ObserveCertDBChanges on the singleton TrustStoreAndroid.
375 GetGlobalTrustStoreAndroidForCRS()->ObserveCertDBChanges();
376
377 base::ThreadPool::PostTask(
378 FROM_HERE,
379 {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
380 base::BindOnce(&InitializeTrustStoreForCRSOnWorkerThread));
381 }
382
383 #else
384
InitializeTrustStoreAndroid()385 void InitializeTrustStoreAndroid() {}
386
387 #endif // CHROME_ROOT_STORE_SUPPORTED
388
389 #endif
390
391 } // namespace net
392