• 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 #ifndef NET_CERT_INTERNAL_TRUST_STORE_CHROME_H_
6 #define NET_CERT_INTERNAL_TRUST_STORE_CHROME_H_
7 
8 #include <optional>
9 #include <vector>
10 
11 #include "base/containers/flat_map.h"
12 #include "base/containers/span.h"
13 #include "base/time/time.h"
14 #include "base/version.h"
15 #include "crypto/sha2.h"
16 #include "net/base/net_export.h"
17 #include "net/cert/root_store_proto_lite/root_store.pb.h"
18 #include "third_party/boringssl/src/pki/trust_store.h"
19 #include "third_party/boringssl/src/pki/trust_store_in_memory.h"
20 
21 namespace net {
22 
23 // Represents a ConstraintSet for compiled-in version of the root store.
24 // This is a separate struct from ChromeRootCertConstraints since the in-memory
25 // representation parses the version constraints into a base::Version.
26 // (base::Version can't be used in the compiled-in version since it isn't
27 // constexpr.)
28 struct StaticChromeRootCertConstraints {
29   std::optional<base::Time> sct_not_after;
30   std::optional<base::Time> sct_all_after;
31 
32   std::optional<std::string_view> min_version;
33   std::optional<std::string_view> max_version_exclusive;
34 
35   base::span<const std::string_view> permitted_dns_names;
36 };
37 
38 struct ChromeRootCertInfo {
39   base::span<const uint8_t> root_cert_der;
40   base::span<const StaticChromeRootCertConstraints> constraints;
41 };
42 
43 struct NET_EXPORT ChromeRootCertConstraints {
44   ChromeRootCertConstraints();
45   ChromeRootCertConstraints(std::optional<base::Time> sct_not_after,
46                             std::optional<base::Time> sct_all_after,
47                             std::optional<base::Version> min_version,
48                             std::optional<base::Version> max_version_exclusive,
49                             std::vector<std::string> permitted_dns_names);
50   explicit ChromeRootCertConstraints(
51       const StaticChromeRootCertConstraints& constraints);
52   ~ChromeRootCertConstraints();
53   ChromeRootCertConstraints(const ChromeRootCertConstraints& other);
54   ChromeRootCertConstraints(ChromeRootCertConstraints&& other);
55   ChromeRootCertConstraints& operator=(const ChromeRootCertConstraints& other);
56   ChromeRootCertConstraints& operator=(ChromeRootCertConstraints&& other);
57 
58   std::optional<base::Time> sct_not_after;
59   std::optional<base::Time> sct_all_after;
60 
61   std::optional<base::Version> min_version;
62   std::optional<base::Version> max_version_exclusive;
63 
64   std::vector<std::string> permitted_dns_names;
65 };
66 
67 // ChromeRootStoreData is a container class that stores all of the Chrome Root
68 // Store data in a single class.
69 class NET_EXPORT ChromeRootStoreData {
70  public:
71   struct NET_EXPORT Anchor {
72     Anchor(std::shared_ptr<const bssl::ParsedCertificate> certificate,
73            std::vector<ChromeRootCertConstraints> constraints);
74     ~Anchor();
75 
76     Anchor(const Anchor& other);
77     Anchor(Anchor&& other);
78     Anchor& operator=(const Anchor& other);
79     Anchor& operator=(Anchor&& other);
80 
81     std::shared_ptr<const bssl::ParsedCertificate> certificate;
82     std::vector<ChromeRootCertConstraints> constraints;
83   };
84   // CreateChromeRootStoreData converts |proto| into a usable
85   // ChromeRootStoreData object. Returns std::nullopt if the passed in
86   // proto has errors in it (e.g. an unparsable DER-encoded certificate).
87   static std::optional<ChromeRootStoreData> CreateChromeRootStoreData(
88       const chrome_root_store::RootStore& proto);
89   ~ChromeRootStoreData();
90 
91   ChromeRootStoreData(const ChromeRootStoreData& other);
92   ChromeRootStoreData(ChromeRootStoreData&& other);
93   ChromeRootStoreData& operator=(const ChromeRootStoreData& other);
94   ChromeRootStoreData& operator=(ChromeRootStoreData&& other);
95 
anchors()96   const std::vector<Anchor>& anchors() const { return anchors_; }
version()97   int64_t version() const { return version_; }
98 
99  private:
100   ChromeRootStoreData();
101 
102   std::vector<Anchor> anchors_;
103   int64_t version_;
104 };
105 
106 // TrustStoreChrome contains the Chrome Root Store, as described at
107 // https://g.co/chrome/root-policy
108 class NET_EXPORT TrustStoreChrome : public bssl::TrustStore {
109  public:
110   using ConstraintOverrideMap =
111       base::flat_map<std::array<uint8_t, crypto::kSHA256Length>,
112                      std::vector<ChromeRootCertConstraints>>;
113 
114   // Commandline switch that can be used to specify constraints for testing
115   // purposes.
116   //
117   // The base unit of the switch is a root constraint specification:
118   //   `${comma_separated_root_sha256_hashes}:${comma_separated_constraints}`
119   // Multiple such specifications can be separated by `+` characters:
120   //   `${hashes}:${constraints}+${morehashes}:${moreconstraints}`
121   //
122   // Recognized constraints:
123   //   `sctnotafter=${seconds_since_epoch}`
124   //   `sctallafter=${seconds_since_epoch}`
125   //   `minversion=${dotted_version_string}`
126   //   `maxversionexclusive=${dotted_version_string}`
127   //   `dns=${permitted_dns_name}` (can be specified multiple times)
128   //
129   // If the same root hash is specified multiple times in separate constraint
130   // specifications, each time will create a new constraintset for that root,
131   // which can be used to test the handling of multiple constraintsets on one
132   // root.
133   static constexpr char kTestCrsConstraintsSwitch[] = "test-crs-constraints";
134 
135   // Creates a TrustStoreChrome that uses a copy of `certs`, instead of the
136   // default Chrome Root Store.
137   static std::unique_ptr<TrustStoreChrome> CreateTrustStoreForTesting(
138       base::span<const ChromeRootCertInfo> certs,
139       int64_t version,
140       ConstraintOverrideMap override_constraints = {});
141 
142   // Creates a TrustStoreChrome that uses the compiled in Chrome Root Store.
143   TrustStoreChrome();
144 
145   // Creates a TrustStoreChrome that uses the passed in anchors as
146   // the contents of the Chrome Root Store.
147   explicit TrustStoreChrome(const ChromeRootStoreData& anchors);
148   ~TrustStoreChrome() override;
149 
150   TrustStoreChrome(const TrustStoreChrome& other) = delete;
151   TrustStoreChrome& operator=(const TrustStoreChrome& other) = delete;
152 
153   // bssl::TrustStore implementation:
154   void SyncGetIssuersOf(const bssl::ParsedCertificate* cert,
155                         bssl::ParsedCertificateList* issuers) override;
156   bssl::CertificateTrust GetTrust(const bssl::ParsedCertificate* cert) override;
157 
158   // Returns true if the trust store contains the given bssl::ParsedCertificate
159   // (matches by DER).
160   bool Contains(const bssl::ParsedCertificate* cert) const;
161 
162   // Returns the root store constraints for `cert`, or an empty span if the
163   // certificate is not constrained.
164   base::span<const ChromeRootCertConstraints> GetConstraintsForCert(
165       const bssl::ParsedCertificate* cert) const;
166 
version()167   int64_t version() const { return version_; }
168 
169   // Parses a string specifying constraint overrides, in the format expected by
170   // the `kTestCrsConstraintsSwitch` command line switch.
171   static ConstraintOverrideMap ParseCrsConstraintsSwitch(
172       std::string_view switch_value);
173 
174  private:
175   TrustStoreChrome(base::span<const ChromeRootCertInfo> certs,
176                    bool certs_are_static,
177                    int64_t version,
178                    ConstraintOverrideMap override_constraints);
179 
180   static ConstraintOverrideMap InitializeConstraintsOverrides();
181 
182   bssl::TrustStoreInMemory trust_store_;
183 
184   // Map from certificate DER bytes to additional constraints (if any) for that
185   // certificate. The DER bytes of the key are owned by the ParsedCertificate
186   // stored in `trust_store_`, so this must be below `trust_store_` in the
187   // member list.
188   base::flat_map<std::string_view, std::vector<ChromeRootCertConstraints>>
189       constraints_;
190 
191   // Map from certificate SHA256 hash to constraints. If a certificate has an
192   // entry in this map, it will override the entry in `constraints_` (if any).
193   const ConstraintOverrideMap override_constraints_;
194 
195   int64_t version_;
196 };
197 
198 // Returns the version # of the Chrome Root Store that was compiled into the
199 // binary.
200 NET_EXPORT int64_t CompiledChromeRootStoreVersion();
201 
202 // Returns the anchors of the Chrome Root Store that were compiled into the
203 // binary.
204 NET_EXPORT std::vector<ChromeRootStoreData::Anchor>
205 CompiledChromeRootStoreAnchors();
206 
207 }  // namespace net
208 
209 #endif  // NET_CERT_INTERNAL_TRUST_STORE_CHROME_H_
210