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