1 // Copyright 2017 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 
5 #include "net/cert/internal/system_trust_store.h"
6 
7 #if defined(USE_NSS_CERTS)
8 #include "net/cert/internal/system_trust_store_nss.h"
9 #endif  // defined(USE_NSS_CERTS)
10 
11 #if defined(USE_NSS_CERTS)
12 #include <cert.h>
13 #include <pk11pub.h>
14 #elif defined(OS_MAC)
15 #include <Security/Security.h>
16 #endif
17 
18 #include <memory>
19 
20 #include "base/files/file_path.h"
21 #include "base/files/file_util.h"
22 #include "base/logging.h"
23 #include "base/no_destructor.h"
24 #include "base/task/task_traits.h"
25 #include "base/task/thread_pool.h"
26 #include "build/build_config.h"
27 #include "net/cert/internal/cert_errors.h"
28 #include "net/cert/internal/parsed_certificate.h"
29 #include "net/cert/internal/trust_store_collection.h"
30 #include "net/cert/internal/trust_store_in_memory.h"
31 #include "net/cert/test_root_certs.h"
32 #include "net/cert/x509_certificate.h"
33 #include "net/cert/x509_util.h"
34 
35 #if defined(USE_NSS_CERTS)
36 #include "crypto/nss_util.h"
37 #include "net/cert/internal/trust_store_nss.h"
38 #include "net/cert/known_roots_nss.h"
39 #include "net/cert/scoped_nss_types.h"
40 #elif defined(OS_MAC)
41 #include "net/cert/internal/trust_store_mac.h"
42 #include "net/cert/x509_util_mac.h"
43 #elif defined(OS_FUCHSIA)
44 #include "third_party/boringssl/src/include/openssl/pool.h"
45 #endif
46 
47 namespace net {
48 
49 namespace {
50 
51 // Abstract implementation of SystemTrustStore to be used as a base class.
52 // Handles the addition of additional trust anchors.
53 class BaseSystemTrustStore : public SystemTrustStore {
54  public:
BaseSystemTrustStore()55   BaseSystemTrustStore() {
56     trust_store_.AddTrustStore(&additional_trust_store_);
57   }
58 
AddTrustAnchor(const scoped_refptr<ParsedCertificate> & trust_anchor)59   void AddTrustAnchor(
60       const scoped_refptr<ParsedCertificate>& trust_anchor) override {
61     additional_trust_store_.AddTrustAnchor(trust_anchor);
62   }
63 
GetTrustStore()64   TrustStore* GetTrustStore() override { return &trust_store_; }
65 
IsAdditionalTrustAnchor(const ParsedCertificate * trust_anchor) const66   bool IsAdditionalTrustAnchor(
67       const ParsedCertificate* trust_anchor) const override {
68     return additional_trust_store_.Contains(trust_anchor);
69   }
70 
71  protected:
72   TrustStoreCollection trust_store_;
73   TrustStoreInMemory additional_trust_store_;
74 };
75 
76 class DummySystemTrustStore : public BaseSystemTrustStore {
77  public:
UsesSystemTrustStore() const78   bool UsesSystemTrustStore() const override { return false; }
79 
IsKnownRoot(const ParsedCertificate * trust_anchor) const80   bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override {
81     return false;
82   }
83 };
84 
85 }  // namespace
86 
87 #if defined(USE_NSS_CERTS)
88 namespace {
89 
90 class SystemTrustStoreNSS : public BaseSystemTrustStore {
91  public:
SystemTrustStoreNSS(std::unique_ptr<TrustStoreNSS> trust_store_nss)92   explicit SystemTrustStoreNSS(std::unique_ptr<TrustStoreNSS> trust_store_nss)
93       : trust_store_nss_(std::move(trust_store_nss)) {
94     trust_store_.AddTrustStore(trust_store_nss_.get());
95 
96     // When running in test mode, also layer in the test-only root certificates.
97     //
98     // Note that this integration requires TestRootCerts::HasInstance() to be
99     // true by the time SystemTrustStoreNSS is created - a limitation which is
100     // acceptable for the test-only code that consumes this.
101     if (TestRootCerts::HasInstance()) {
102       trust_store_.AddTrustStore(
103           TestRootCerts::GetInstance()->test_trust_store());
104     }
105   }
106 
UsesSystemTrustStore() const107   bool UsesSystemTrustStore() const override { return true; }
108 
109   // IsKnownRoot returns true if the given trust anchor is a standard one (as
110   // opposed to a user-installed root)
IsKnownRoot(const ParsedCertificate * trust_anchor) const111   bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override {
112     // TODO(eroman): The overall approach of IsKnownRoot() is inefficient -- it
113     // requires searching for the trust anchor by DER in NSS, however path
114     // building already had a handle to it.
115     SECItem der_cert;
116     der_cert.data = const_cast<uint8_t*>(trust_anchor->der_cert().UnsafeData());
117     der_cert.len = trust_anchor->der_cert().Length();
118     der_cert.type = siDERCertBuffer;
119     ScopedCERTCertificate nss_cert(
120         CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &der_cert));
121     if (!nss_cert)
122       return false;
123 
124     if (!net::IsKnownRoot(nss_cert.get()))
125       return false;
126 
127     return trust_anchor->der_cert() ==
128            der::Input(nss_cert->derCert.data, nss_cert->derCert.len);
129   }
130 
131  private:
132   std::unique_ptr<TrustStoreNSS> trust_store_nss_;
133 };
134 
135 }  // namespace
136 
CreateSslSystemTrustStore()137 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
138   return std::make_unique<SystemTrustStoreNSS>(
139       std::make_unique<TrustStoreNSS>(trustSSL));
140 }
141 
142 std::unique_ptr<SystemTrustStore>
CreateSslSystemTrustStoreNSSWithUserSlotRestriction(crypto::ScopedPK11Slot user_slot)143 CreateSslSystemTrustStoreNSSWithUserSlotRestriction(
144     crypto::ScopedPK11Slot user_slot) {
145   return std::make_unique<SystemTrustStoreNSS>(
146       std::make_unique<TrustStoreNSS>(trustSSL, std::move(user_slot)));
147 }
148 
149 std::unique_ptr<SystemTrustStore>
CreateSslSystemTrustStoreNSSWithNoUserSlots()150 CreateSslSystemTrustStoreNSSWithNoUserSlots() {
151   return std::make_unique<SystemTrustStoreNSS>(std::make_unique<TrustStoreNSS>(
152       trustSSL, TrustStoreNSS::DisallowTrustForCertsOnUserSlots()));
153 }
154 
155 #elif defined(OS_MAC)
156 
157 class SystemTrustStoreMac : public BaseSystemTrustStore {
158  public:
SystemTrustStoreMac()159   SystemTrustStoreMac() {
160     trust_store_.AddTrustStore(GetGlobalTrustStoreMac());
161 
162     // When running in test mode, also layer in the test-only root certificates.
163     //
164     // Note that this integration requires TestRootCerts::HasInstance() to be
165     // true by the time SystemTrustStoreMac is created - a limitation which is
166     // acceptable for the test-only code that consumes this.
167     if (TestRootCerts::HasInstance()) {
168       trust_store_.AddTrustStore(
169           TestRootCerts::GetInstance()->test_trust_store());
170     }
171   }
172 
UsesSystemTrustStore() const173   bool UsesSystemTrustStore() const override { return true; }
174 
175   // IsKnownRoot returns true if the given trust anchor is a standard one (as
176   // opposed to a user-installed root)
IsKnownRoot(const ParsedCertificate * trust_anchor) const177   bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override {
178     return GetGlobalTrustStoreMac()->IsKnownRoot(trust_anchor);
179   }
180 
InitializeTrustCacheOnWorkerThread()181   static void InitializeTrustCacheOnWorkerThread() {
182     GetGlobalTrustStoreMac()->InitializeTrustCache();
183   }
184 
185  private:
GetGlobalTrustStoreMac()186   static TrustStoreMac* GetGlobalTrustStoreMac() {
187     static base::NoDestructor<TrustStoreMac> static_trust_store_mac(
188         kSecPolicyAppleSSL);
189     return static_trust_store_mac.get();
190   }
191 };
192 
CreateSslSystemTrustStore()193 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
194   return std::make_unique<SystemTrustStoreMac>();
195 }
196 
InitializeTrustStoreMacCache()197 void InitializeTrustStoreMacCache() {
198   base::ThreadPool::PostTask(
199       FROM_HERE,
200       {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
201       base::BindOnce(&SystemTrustStoreMac::InitializeTrustCacheOnWorkerThread));
202 }
203 
204 #elif defined(OS_FUCHSIA)
205 
206 namespace {
207 
208 constexpr char kRootCertsFileFuchsia[] = "/config/ssl/cert.pem";
209 
210 class FuchsiaSystemCerts {
211  public:
FuchsiaSystemCerts()212   FuchsiaSystemCerts() {
213     base::FilePath filename(kRootCertsFileFuchsia);
214     std::string certs_file;
215     if (!base::ReadFileToString(filename, &certs_file)) {
216       LOG(ERROR) << "Can't load root certificates from " << filename;
217       return;
218     }
219 
220     CertificateList certs = X509Certificate::CreateCertificateListFromBytes(
221         certs_file.data(), certs_file.length(), X509Certificate::FORMAT_AUTO);
222 
223     for (const auto& cert : certs) {
224       CertErrors errors;
225       auto parsed = ParsedCertificate::Create(
226           bssl::UpRef(cert->cert_buffer()),
227           x509_util::DefaultParseCertificateOptions(), &errors);
228       CHECK(parsed) << errors.ToDebugString();
229       system_trust_store_.AddTrustAnchor(parsed);
230     }
231   }
232 
system_trust_store()233   TrustStoreInMemory* system_trust_store() { return &system_trust_store_; }
234 
235  private:
236   TrustStoreInMemory system_trust_store_;
237 };
238 
239 base::LazyInstance<FuchsiaSystemCerts>::Leaky g_root_certs_fuchsia =
240     LAZY_INSTANCE_INITIALIZER;
241 
242 }  // namespace
243 
244 class SystemTrustStoreFuchsia : public BaseSystemTrustStore {
245  public:
SystemTrustStoreFuchsia()246   SystemTrustStoreFuchsia() {
247     trust_store_.AddTrustStore(g_root_certs_fuchsia.Get().system_trust_store());
248     if (TestRootCerts::HasInstance()) {
249       trust_store_.AddTrustStore(
250           TestRootCerts::GetInstance()->test_trust_store());
251     }
252   }
253 
UsesSystemTrustStore() const254   bool UsesSystemTrustStore() const override { return true; }
255 
IsKnownRoot(const ParsedCertificate * trust_anchor) const256   bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override {
257     return g_root_certs_fuchsia.Get().system_trust_store()->Contains(
258         trust_anchor);
259   }
260 };
261 
CreateSslSystemTrustStore()262 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
263   return std::make_unique<SystemTrustStoreFuchsia>();
264 }
265 
266 #else
267 
CreateSslSystemTrustStore()268 std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
269   return std::make_unique<DummySystemTrustStore>();
270 }
271 
272 #endif
273 
CreateEmptySystemTrustStore()274 std::unique_ptr<SystemTrustStore> CreateEmptySystemTrustStore() {
275   return std::make_unique<DummySystemTrustStore>();
276 }
277 
278 }  // namespace net
279