• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/root_store_proto_lite/root_store.pb.h"
10 #include "net/cert/x509_certificate.h"
11 #include "net/cert/x509_util.h"
12 #include "third_party/abseil-cpp/absl/types/optional.h"
13 #include "third_party/boringssl/src/include/openssl/pool.h"
14 #include "third_party/boringssl/src/pki/cert_errors.h"
15 #include "third_party/boringssl/src/pki/parsed_certificate.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 = bssl::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     bssl::CertErrors errors;
88     auto parsed = bssl::ParsedCertificate::Create(
89         std::move(cert), x509_util::DefaultParseCertificateOptions(), &errors);
90     // There should always be a valid cert, because we should be parsing Chrome
91     // Root Store static data compiled in.
92     CHECK(parsed);
93     trust_store_.AddTrustAnchor(std::move(parsed));
94   }
95   version_ = version;
96 }
97 
TrustStoreChrome(const ChromeRootStoreData & root_store_data)98 TrustStoreChrome::TrustStoreChrome(const ChromeRootStoreData& root_store_data) {
99   for (const auto& anchor : root_store_data.anchors()) {
100     trust_store_.AddTrustAnchor(anchor);
101   }
102   version_ = root_store_data.version();
103 }
104 
105 TrustStoreChrome::~TrustStoreChrome() = default;
106 
SyncGetIssuersOf(const bssl::ParsedCertificate * cert,bssl::ParsedCertificateList * issuers)107 void TrustStoreChrome::SyncGetIssuersOf(const bssl::ParsedCertificate* cert,
108                                         bssl::ParsedCertificateList* issuers) {
109   trust_store_.SyncGetIssuersOf(cert, issuers);
110 }
111 
GetTrust(const bssl::ParsedCertificate * cert)112 bssl::CertificateTrust TrustStoreChrome::GetTrust(
113     const bssl::ParsedCertificate* cert) {
114   return trust_store_.GetTrust(cert);
115 }
116 
Contains(const bssl::ParsedCertificate * cert) const117 bool TrustStoreChrome::Contains(const bssl::ParsedCertificate* cert) const {
118   return trust_store_.Contains(cert);
119 }
120 
121 // static
CreateTrustStoreForTesting(base::span<const ChromeRootCertInfo> certs,int64_t version)122 std::unique_ptr<TrustStoreChrome> TrustStoreChrome::CreateTrustStoreForTesting(
123     base::span<const ChromeRootCertInfo> certs,
124     int64_t version) {
125   // Note: wrap_unique is used because the constructor is private.
126   return base::WrapUnique(new TrustStoreChrome(
127       certs, /*certs_are_static=*/false, /*version=*/version));
128 }
129 
CompiledChromeRootStoreVersion()130 int64_t CompiledChromeRootStoreVersion() {
131   return kRootStoreVersion;
132 }
133 
CompiledChromeRootStoreAnchors()134 bssl::ParsedCertificateList CompiledChromeRootStoreAnchors() {
135   bssl::ParsedCertificateList parsed_cert_list;
136   for (const auto& cert_info : kChromeRootCertList) {
137     bssl::UniquePtr<CRYPTO_BUFFER> cert =
138         x509_util::CreateCryptoBufferFromStaticDataUnsafe(
139             cert_info.root_cert_der);
140     bssl::CertErrors errors;
141     auto parsed = bssl::ParsedCertificate::Create(
142         std::move(cert), x509_util::DefaultParseCertificateOptions(), &errors);
143     DCHECK(parsed);
144     parsed_cert_list.push_back(std::move(parsed));
145   }
146 
147   return parsed_cert_list;
148 }
149 
150 }  // namespace net
151