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