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