1 // Copyright 2021 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/trust_store_chrome.h"
6 #include "base/containers/span.h"
7 #include "base/logging.h"
8 #include "base/memory/ptr_util.h"
9 #include "net/cert/pki/cert_errors.h"
10 #include "net/cert/pki/parsed_certificate.h"
11 #include "net/cert/root_store_proto_lite/root_store.pb.h"
12 #include "net/cert/x509_certificate.h"
13 #include "net/cert/x509_util.h"
14 #include "third_party/abseil-cpp/absl/types/optional.h"
15 #include "third_party/boringssl/src/include/openssl/pool.h"
16
17 namespace net {
18
19 namespace {
20 #include "net/data/ssl/chrome_root_store/chrome-root-store-inc.cc"
21 } // namespace
22
23 ChromeRootStoreData::ChromeRootStoreData() = default;
24
25 ChromeRootStoreData::~ChromeRootStoreData() = default;
26
27 ChromeRootStoreData::ChromeRootStoreData(const ChromeRootStoreData& other) =
28 default;
29 ChromeRootStoreData::ChromeRootStoreData(ChromeRootStoreData&& other) = default;
30 ChromeRootStoreData& ChromeRootStoreData::operator=(
31 const ChromeRootStoreData& other) = default;
32 ChromeRootStoreData& ChromeRootStoreData::operator=(
33 ChromeRootStoreData&& other) = default;
34
35 absl::optional<ChromeRootStoreData>
CreateChromeRootStoreData(const chrome_root_store::RootStore & proto)36 ChromeRootStoreData::CreateChromeRootStoreData(
37 const chrome_root_store::RootStore& proto) {
38 ChromeRootStoreData root_store_data;
39
40 for (auto& anchor : proto.trust_anchors()) {
41 if (anchor.der().empty()) {
42 LOG(ERROR) << "Error anchor with empty DER in update";
43 return absl::nullopt;
44 }
45
46 auto parsed = net::ParsedCertificate::Create(
47 net::x509_util::CreateCryptoBuffer(anchor.der()),
48 net::x509_util::DefaultParseCertificateOptions(), nullptr);
49 if (!parsed) {
50 LOG(ERROR) << "Error parsing cert for update";
51 return absl::nullopt;
52 }
53 root_store_data.anchors_.push_back(std::move(parsed));
54 }
55
56 root_store_data.version_ = proto.version_major();
57
58 return root_store_data;
59 }
60
TrustStoreChrome()61 TrustStoreChrome::TrustStoreChrome()
62 : TrustStoreChrome(kChromeRootCertList,
63 /*certs_are_static=*/true,
64 /*version=*/CompiledChromeRootStoreVersion()) {}
65
TrustStoreChrome(base::span<const ChromeRootCertInfo> certs,bool certs_are_static,int64_t version)66 TrustStoreChrome::TrustStoreChrome(base::span<const ChromeRootCertInfo> certs,
67 bool certs_are_static,
68 int64_t version) {
69 // TODO(hchao, sleevi): Explore keeping a CRYPTO_BUFFER of just the DER
70 // certificate and subject name. This would hopefully save memory compared
71 // to keeping the full parsed representation in memory, especially when
72 // there are multiple instances of TrustStoreChrome.
73 for (const auto& cert_info : certs) {
74 bssl::UniquePtr<CRYPTO_BUFFER> cert;
75 if (certs_are_static) {
76 // TODO(mattm,hchao): Ensure the static data crypto_buffers for the
77 // compiled-in roots are kept alive, so that roots from the component
78 // updater data will de-dupe against them. This currently works if the
79 // new components roots are the same as the compiled in roots, but
80 // fails if a component update drops a root and then the next component
81 // update readds the root without a restart.
82 cert = x509_util::CreateCryptoBufferFromStaticDataUnsafe(
83 cert_info.root_cert_der);
84 } else {
85 cert = x509_util::CreateCryptoBuffer(cert_info.root_cert_der);
86 }
87 CertErrors errors;
88 auto parsed = ParsedCertificate::Create(
89 std::move(cert), x509_util::DefaultParseCertificateOptions(), &errors);
90 DCHECK(parsed);
91 trust_store_.AddTrustAnchor(parsed);
92 }
93 version_ = version;
94 }
95
TrustStoreChrome(const ChromeRootStoreData & root_store_data)96 TrustStoreChrome::TrustStoreChrome(const ChromeRootStoreData& root_store_data) {
97 for (const auto& anchor : root_store_data.anchors()) {
98 trust_store_.AddTrustAnchor(anchor);
99 }
100 version_ = root_store_data.version();
101 }
102
103 TrustStoreChrome::~TrustStoreChrome() = default;
104
SyncGetIssuersOf(const ParsedCertificate * cert,ParsedCertificateList * issuers)105 void TrustStoreChrome::SyncGetIssuersOf(const ParsedCertificate* cert,
106 ParsedCertificateList* issuers) {
107 trust_store_.SyncGetIssuersOf(cert, issuers);
108 }
109
GetTrust(const ParsedCertificate * cert,base::SupportsUserData * debug_data)110 CertificateTrust TrustStoreChrome::GetTrust(
111 const ParsedCertificate* cert,
112 base::SupportsUserData* debug_data) {
113 return trust_store_.GetTrust(cert, debug_data);
114 }
115
Contains(const ParsedCertificate * cert) const116 bool TrustStoreChrome::Contains(const ParsedCertificate* cert) const {
117 return trust_store_.Contains(cert);
118 }
119
120 // static
CreateTrustStoreForTesting(base::span<const ChromeRootCertInfo> certs,int64_t version)121 std::unique_ptr<TrustStoreChrome> TrustStoreChrome::CreateTrustStoreForTesting(
122 base::span<const ChromeRootCertInfo> certs,
123 int64_t version) {
124 // Note: wrap_unique is used because the constructor is private.
125 return base::WrapUnique(new TrustStoreChrome(
126 certs, /*certs_are_static=*/false, /*version=*/version));
127 }
128
CompiledChromeRootStoreVersion()129 int64_t CompiledChromeRootStoreVersion() {
130 return kRootStoreVersion;
131 }
132
CompiledChromeRootStoreAnchors()133 ParsedCertificateList CompiledChromeRootStoreAnchors() {
134 ParsedCertificateList parsed_cert_list;
135 for (const auto& cert_info : kChromeRootCertList) {
136 bssl::UniquePtr<CRYPTO_BUFFER> cert =
137 x509_util::CreateCryptoBufferFromStaticDataUnsafe(
138 cert_info.root_cert_der);
139 CertErrors errors;
140 auto parsed = ParsedCertificate::Create(
141 std::move(cert), x509_util::DefaultParseCertificateOptions(), &errors);
142 DCHECK(parsed);
143 parsed_cert_list.push_back(parsed);
144 }
145
146 return parsed_cert_list;
147 }
148
149 } // namespace net
150