• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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