1 // Copyright 2012 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_HTTP_TRANSPORT_SECURITY_STATE_H_ 6 #define NET_HTTP_TRANSPORT_SECURITY_STATE_H_ 7 8 #include <stdint.h> 9 10 #include <array> 11 #include <map> 12 #include <optional> 13 #include <set> 14 #include <string> 15 16 #include "base/feature_list.h" 17 #include "base/functional/callback.h" 18 #include "base/gtest_prod_util.h" 19 #include "base/memory/raw_ptr.h" 20 #include "base/strings/string_piece.h" 21 #include "base/threading/thread_checker.h" 22 #include "base/time/time.h" 23 #include "base/values.h" 24 #include "crypto/sha2.h" 25 #include "net/base/expiring_cache.h" 26 #include "net/base/hash_value.h" 27 #include "net/base/net_export.h" 28 #include "net/base/network_anonymization_key.h" 29 #include "net/cert/signed_certificate_timestamp_and_status.h" 30 #include "net/http/transport_security_state_source.h" 31 #include "net/log/net_log_with_source.h" 32 #include "url/gurl.h" 33 34 namespace net { 35 36 namespace ct { 37 enum class CTPolicyCompliance; 38 } 39 40 class HostPortPair; 41 class X509Certificate; 42 43 void NET_EXPORT_PRIVATE SetTransportSecurityStateSourceForTesting( 44 const TransportSecurityStateSource* source); 45 46 // Tracks which hosts have enabled strict transport security and/or public 47 // key pins. 48 // 49 // This object manages the in-memory store. Register a Delegate with 50 // |SetDelegate| to persist the state to disk. 51 // 52 // HTTP strict transport security (HSTS) is defined in 53 // http://tools.ietf.org/html/ietf-websec-strict-transport-sec. 54 class NET_EXPORT TransportSecurityState { 55 public: 56 using HashedHost = std::array<uint8_t, crypto::kSHA256Length>; 57 58 class NET_EXPORT Delegate { 59 public: 60 // This function may not block and may be called with internal locks held. 61 // Thus it must not reenter the TransportSecurityState object. 62 virtual void StateIsDirty(TransportSecurityState* state) = 0; 63 // Same as StateIsDirty but instructs the Delegate to persist the data 64 // immediately and call |callback| when done. 65 virtual void WriteNow(TransportSecurityState* state, 66 base::OnceClosure callback) = 0; 67 68 protected: 69 virtual ~Delegate() = default; 70 }; 71 72 class NET_EXPORT RequireCTDelegate { 73 public: 74 // Provides a capability for altering the default handling of Certificate 75 // Transparency information, allowing it to be always required for some 76 // hosts, for some hosts to be opted out of the default policy, or 77 // allowing the TransportSecurityState to apply the default security 78 // policies. 79 enum class CTRequirementLevel { 80 // The host is required to always supply Certificate Transparency 81 // information that complies with the CT policy. 82 REQUIRED, 83 84 // The host is explicitly not required to supply Certificate 85 // Transparency information that complies with the CT policy. 86 NOT_REQUIRED, 87 }; 88 89 // Called by the TransportSecurityState, allows the Delegate to override 90 // the default handling of Certificate Transparency requirements, if 91 // desired. 92 // |hostname| contains the host being contacted, serving the certificate 93 // |chain|, with the set of hashesh |hashes|. Note that |hashes| and 94 // |chain| are not guaranteed to be in the same order - that is, the first 95 // hash in |hashes| is NOT guaranteed to be for the leaf cert in |chain|. 96 virtual CTRequirementLevel IsCTRequiredForHost( 97 const std::string& hostname, 98 const X509Certificate* chain, 99 const HashValueVector& hashes) = 0; 100 101 protected: 102 virtual ~RequireCTDelegate() = default; 103 }; 104 105 // A STSState describes the strict transport security state (required 106 // upgrade to HTTPS). 107 class NET_EXPORT STSState { 108 public: 109 enum UpgradeMode { 110 // These numbers must match those in hsts_view.js, function modeToString. 111 MODE_FORCE_HTTPS = 0, 112 MODE_DEFAULT = 1, 113 }; 114 115 STSState(); 116 ~STSState(); 117 118 // The absolute time (UTC) when the |upgrade_mode| (and other state) was 119 // observed. 120 base::Time last_observed; 121 122 // The absolute time (UTC) when |upgrade_mode| (and other state) 123 // expires. 124 base::Time expiry; 125 126 UpgradeMode upgrade_mode = MODE_DEFAULT; 127 128 // Are subdomains subject to this policy state? 129 bool include_subdomains = false; 130 131 // The domain which matched during a search for this STSState entry. 132 // Updated by |GetDynamicSTSState| and |GetStaticDomainState|. 133 std::string domain; 134 135 // ShouldUpgradeToSSL returns true iff HTTP requests should be internally 136 // redirected to HTTPS (also if WS should be upgraded to WSS). 137 bool ShouldUpgradeToSSL() const; 138 }; 139 140 class NET_EXPORT STSStateIterator { 141 public: 142 explicit STSStateIterator(const TransportSecurityState& state); 143 ~STSStateIterator(); 144 HasNext()145 bool HasNext() const { return iterator_ != end_; } Advance()146 void Advance() { ++iterator_; } hostname()147 const HashedHost& hostname() const { return iterator_->first; } domain_state()148 const STSState& domain_state() const { return iterator_->second; } 149 150 private: 151 std::map<HashedHost, STSState>::const_iterator iterator_; 152 std::map<HashedHost, STSState>::const_iterator end_; 153 }; 154 155 // PKPStatus describes the result of a pinning check. 156 enum class PKPStatus { 157 // Pinning was enabled and the necessary pins were not present. 158 VIOLATED, 159 160 // Pinning was not enabled, or pinning was enabled and the certificate 161 // satisfied the pins. 162 OK, 163 164 // Pinning was enabled and the certificate did not satisfy the pins, but the 165 // violation was ignored due to local policy, such as a local trust anchor. 166 BYPASSED, 167 }; 168 169 // A PKPState describes the public key pinning state. 170 class NET_EXPORT PKPState { 171 public: 172 PKPState(); 173 PKPState(const PKPState& other); 174 ~PKPState(); 175 176 // The absolute time (UTC) when the |spki_hashes| (and other state) were 177 // observed. 178 base::Time last_observed; 179 180 // The absolute time (UTC) when the |spki_hashes| expire. 181 base::Time expiry; 182 183 // Optional; hashes of pinned SubjectPublicKeyInfos. 184 HashValueVector spki_hashes; 185 186 // Optional; hashes of static known-bad SubjectPublicKeyInfos which MUST 187 // NOT intersect with the set of SPKIs in the TLS server's certificate 188 // chain. 189 HashValueVector bad_spki_hashes; 190 191 // Are subdomains subject to this policy state? 192 bool include_subdomains = false; 193 194 // The domain which matched during a search for this DomainState entry. 195 // Updated by |GetDynamicPKPState| and |GetStaticDomainState|. 196 std::string domain; 197 198 // Takes a set of SubjectPublicKeyInfo |hashes| and returns true if: 199 // 1) |bad_static_spki_hashes| does not intersect |hashes|; AND 200 // 2) Both |static_spki_hashes| and |dynamic_spki_hashes| are empty 201 // or at least one of them intersects |hashes|. 202 // 203 // |{dynamic,static}_spki_hashes| contain trustworthy public key hashes, 204 // any one of which is sufficient to validate the certificate chain in 205 // question. The public keys could be of a root CA, intermediate CA, or 206 // leaf certificate, depending on the security vs. disaster recovery 207 // tradeoff selected. (Pinning only to leaf certifiates increases 208 // security because you no longer trust any CAs, but it hampers disaster 209 // recovery because you can't just get a new certificate signed by the 210 // CA.) 211 // 212 // |bad_static_spki_hashes| contains public keys that we don't want to 213 // trust. 214 bool CheckPublicKeyPins(const HashValueVector& hashes) const; 215 216 // Returns true if any of the HashValueVectors |static_spki_hashes|, 217 // |bad_static_spki_hashes|, or |dynamic_spki_hashes| contains any 218 // items. 219 bool HasPublicKeyPins() const; 220 }; 221 222 class NET_EXPORT PinSet { 223 public: 224 PinSet(std::string name, 225 std::vector<std::vector<uint8_t>> static_spki_hashes, 226 std::vector<std::vector<uint8_t>> bad_static_spki_hashes); 227 PinSet(const PinSet& other); 228 ~PinSet(); 229 name()230 const std::string& name() const { return name_; } static_spki_hashes()231 const std::vector<std::vector<uint8_t>>& static_spki_hashes() const { 232 return static_spki_hashes_; 233 } bad_static_spki_hashes()234 const std::vector<std::vector<uint8_t>>& bad_static_spki_hashes() const { 235 return bad_static_spki_hashes_; 236 } 237 238 private: 239 std::string name_; 240 std::vector<std::vector<uint8_t>> static_spki_hashes_; 241 std::vector<std::vector<uint8_t>> bad_static_spki_hashes_; 242 }; 243 244 struct NET_EXPORT PinSetInfo { 245 std::string hostname_; 246 std::string pinset_name_; 247 bool include_subdomains_; 248 249 PinSetInfo(std::string hostname, 250 std::string pinset_name, 251 bool include_subdomains); 252 }; 253 254 // Indicates whether a connection met CT requirements. 255 enum CTRequirementsStatus { 256 // CT was not required for the connection. 257 CT_NOT_REQUIRED, 258 // CT was required for the connection and valid Certificate Transparency 259 // information was provided. 260 CT_REQUIREMENTS_MET, 261 // CT was required for the connection but valid CT info was not provided. 262 CT_REQUIREMENTS_NOT_MET, 263 }; 264 265 TransportSecurityState(); 266 267 // Creates a TransportSecurityState object that will skip the check to force 268 // HTTPS from static entries for the given set of hosts. All hostnames in the 269 // bypass list must consist of a single label, i.e. they must be a TLD. 270 explicit TransportSecurityState( 271 std::vector<std::string> hsts_host_bypass_list); 272 273 TransportSecurityState(const TransportSecurityState&) = delete; 274 TransportSecurityState& operator=(const TransportSecurityState&) = delete; 275 276 ~TransportSecurityState(); 277 278 // These functions search for static and dynamic STS and PKP states, and 279 // invoke the functions of the same name on them. These functions are the 280 // primary public interface; direct access to STS and PKP states is best 281 // left to tests. The caller needs to handle the optional pinning override 282 // when is_issued_by_known_root is false. 283 bool ShouldSSLErrorsBeFatal(const std::string& host); 284 bool ShouldUpgradeToSSL(const std::string& host, 285 const NetLogWithSource& net_log = NetLogWithSource()); 286 PKPStatus CheckPublicKeyPins(const HostPortPair& host_port_pair, 287 bool is_issued_by_known_root, 288 const HashValueVector& hashes); 289 bool HasPublicKeyPins(const std::string& host); 290 291 // Returns CT_REQUIREMENTS_NOT_MET if a connection violates CT policy 292 // requirements: that is, if a connection to |host|, using the validated 293 // certificate |validated_certificate_chain|, is expected to be accompanied 294 // with valid Certificate Transparency information that complies with the 295 // connection's CTPolicyEnforcer and |policy_compliance| indicates that 296 // the connection does not comply. 297 // 298 // The behavior may be further be altered by setting a RequireCTDelegate 299 // via |SetRequireCTDelegate()|. 300 CTRequirementsStatus CheckCTRequirements( 301 const net::HostPortPair& host_port_pair, 302 bool is_issued_by_known_root, 303 const HashValueVector& public_key_hashes, 304 const X509Certificate* validated_certificate_chain, 305 ct::CTPolicyCompliance policy_compliance); 306 307 // Assign a |Delegate| for persisting the transport security state. If 308 // |NULL|, state will not be persisted. The caller retains 309 // ownership of |delegate|. 310 // Note: This is only used for serializing/deserializing the 311 // TransportSecurityState. 312 void SetDelegate(Delegate* delegate); 313 314 // Assigns a delegate responsible for determining whether or not a 315 // connection to a given host should require Certificate Transparency 316 // information that complies with the CT policy provided by a 317 // CTPolicyEnforcer. 318 // If nullptr, no delegate will be consulted. 319 // The caller retains ownership of the |delegate|, and must persist for 320 // the lifetime of this object or until called with nullptr, whichever 321 // occurs first. 322 void SetRequireCTDelegate(RequireCTDelegate* delegate); 323 324 // If |emergency_disable| is set to true, will stop requiring CT 325 // compliance on any further requests regardless of host or certificate 326 // status. SetCTEmergencyDisabled(bool emergency_disable)327 void SetCTEmergencyDisabled(bool emergency_disable) { 328 ct_emergency_disable_ = emergency_disable; 329 } 330 is_ct_emergency_disabled_for_testing()331 bool is_ct_emergency_disabled_for_testing() const { 332 return ct_emergency_disable_; 333 } 334 335 // |pinsets| should include all known pinsets, |host_pins| the information 336 // related to each hostname's pin, and |update_time| the time at which this 337 // list was known to be up to date. 338 void UpdatePinList(const std::vector<PinSet>& pinsets, 339 const std::vector<PinSetInfo>& host_pins, 340 base::Time update_time); 341 342 // Clears all dynamic data (e.g. HSTS and HPKP data). 343 // 344 // Does NOT persist changes using the Delegate, as this function is only 345 // used to clear any dynamic data prior to re-loading it from a file. 346 // Note: This is only used for serializing/deserializing the 347 // TransportSecurityState. 348 void ClearDynamicData(); 349 350 // Inserts |state| into |enabled_sts_hosts_| under the key |hashed_host|. 351 // |hashed_host| is already in the internal representation. 352 // Note: This is only used for serializing/deserializing the 353 // TransportSecurityState. 354 void AddOrUpdateEnabledSTSHosts(const HashedHost& hashed_host, 355 const STSState& state); 356 357 // Deletes all dynamic data (e.g. HSTS or HPKP data) created between a time 358 // period [|start_time|, |end_time|). 359 // 360 // If any entries are deleted, the new state will be persisted through 361 // the Delegate (if any). Calls |callback| when data is persisted to disk. 362 void DeleteAllDynamicDataBetween(base::Time start_time, 363 base::Time end_time, 364 base::OnceClosure callback); 365 366 // Deletes any dynamic data stored for |host| (e.g. HSTS or HPKP data). 367 // If |host| doesn't have an exact entry then no action is taken. Does 368 // not delete static (i.e. preloaded) data. Returns true iff an entry 369 // was deleted. 370 // 371 // If an entry is deleted, the new state will be persisted through 372 // the Delegate (if any). 373 bool DeleteDynamicDataForHost(const std::string& host); 374 375 // Returns true and updates |*result| if |host| has dynamic or static 376 // HSTS/HPKP (respectively) state. If multiple entries match |host|, dynamic 377 // state is preferred over static state and other than that the most specific 378 // match determines the return value (both is in deviation of RFC6797, cf. 379 // https://crbug.com/821811). 380 // 381 // Note that these methods are not const because they opportunistically remove 382 // entries that have expired. 383 bool GetSTSState(const std::string& host, STSState* sts_result); 384 bool GetPKPState(const std::string& host, PKPState* pkp_result); 385 386 // Returns true and updates |*result| iff |host| has static HSTS/HPKP 387 // (respectively) state. If multiple entries match |host|, the most specific 388 // match determines the return value. 389 bool GetStaticSTSState(const std::string& host, STSState* sts_result) const; 390 bool GetStaticPKPState(const std::string& host, PKPState* pkp_result) const; 391 392 // Returns true and updates |*result| iff |host| has dynamic 393 // HSTS/HPKP (respectively) state. If multiple entries match |host|, 394 // the most specific match determines the return value. 395 // 396 // Note that these methods are not const because they opportunistically remove 397 // entries that have expired. 398 bool GetDynamicSTSState(const std::string& host, STSState* result); 399 bool GetDynamicPKPState(const std::string& host, PKPState* result); 400 401 // Processes an HSTS header value from the host, adding entries to 402 // dynamic state if necessary. 403 bool AddHSTSHeader(const std::string& host, const std::string& value); 404 405 // Adds explicitly-specified data as if it was processed from an 406 // HSTS header (used for net-internals and unit tests). 407 void AddHSTS(const std::string& host, 408 const base::Time& expiry, 409 bool include_subdomains); 410 411 // Adds explicitly-specified data as if it was processed from an HPKP header. 412 // Note: dynamic PKP data is not persisted. 413 void AddHPKP(const std::string& host, 414 const base::Time& expiry, 415 bool include_subdomains, 416 const HashValueVector& hashes); 417 418 // Enables or disables public key pinning bypass for local trust anchors. 419 // Disabling the bypass for local trust anchors is highly discouraged. 420 // This method is used by Cronet only and *** MUST NOT *** be used by any 421 // other consumer. For more information see "How does key pinning interact 422 // with local proxies and filters?" at 423 // https://www.chromium.org/Home/chromium-security/security-faq 424 void SetEnablePublicKeyPinningBypassForLocalTrustAnchors(bool value); 425 AssertCalledOnValidThread()426 void AssertCalledOnValidThread() const { 427 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); 428 } 429 430 // For unit tests only. EnableStaticPinsForTesting()431 void EnableStaticPinsForTesting() { enable_static_pins_ = true; } has_dynamic_pkp_state()432 bool has_dynamic_pkp_state() const { return !enabled_pkp_hosts_.empty(); } 433 434 // Sets whether pinning list timestamp freshness should be ignored for 435 // testing. SetPinningListAlwaysTimelyForTesting(bool always_timely)436 void SetPinningListAlwaysTimelyForTesting(bool always_timely) { 437 pins_list_always_timely_for_testing_ = always_timely; 438 } 439 440 // The number of cached STSState entries. 441 size_t num_sts_entries() const; 442 443 private: 444 friend class TransportSecurityStateTest; 445 friend class TransportSecurityStateStaticFuzzer; 446 FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, NoClobberPins); 447 448 typedef std::map<HashedHost, STSState> STSStateMap; 449 typedef std::map<HashedHost, PKPState> PKPStateMap; 450 451 base::Value::Dict NetLogUpgradeToSSLParam(const std::string& host); 452 453 // IsBuildTimely returns true if the current build is new enough ensure that 454 // built in security information (i.e. HSTS preloading and pinning 455 // information) is timely. 456 static bool IsBuildTimely(); 457 458 // Helper method for actually checking pins. 459 PKPStatus CheckPublicKeyPinsImpl(const HostPortPair& host_port_pair, 460 bool is_issued_by_known_root, 461 const HashValueVector& hashes); 462 463 // If a Delegate is present, notify it that the internal state has 464 // changed. 465 void DirtyNotify(); 466 467 // Adds HSTS and HPKP state for |host|. The new state supercedes 468 // any previous state for the |host|, including static entries. 469 // 470 // The new state for |host| is persisted using the Delegate (if any). 471 void AddHSTSInternal(const std::string& host, 472 STSState::UpgradeMode upgrade_mode, 473 const base::Time& expiry, 474 bool include_subdomains); 475 void AddHPKPInternal(const std::string& host, 476 const base::Time& last_observed, 477 const base::Time& expiry, 478 bool include_subdomains, 479 const HashValueVector& hashes); 480 481 // Returns true if a request to |host_port_pair| with the given 482 // SubjectPublicKeyInfo |hashes| satisfies the pins in |pkp_state|, 483 // and false otherwise. 484 PKPStatus CheckPins(const HostPortPair& host_port_pair, 485 bool is_issued_by_known_root, 486 const TransportSecurityState::PKPState& pkp_state, 487 const HashValueVector& hashes); 488 489 // Returns true if the static key pinning list has been updated in the last 10 490 // weeks. 491 bool IsStaticPKPListTimely() const; 492 493 // The sets of hosts that have enabled TransportSecurity. |domain| will always 494 // be empty for a STSState or PKPState in these maps; the domain comes from 495 // the map keys instead. In addition, |upgrade_mode| in the STSState is never 496 // MODE_DEFAULT and |HasPublicKeyPins| in the PKPState always returns true. 497 STSStateMap enabled_sts_hosts_; 498 PKPStateMap enabled_pkp_hosts_; 499 500 raw_ptr<Delegate> delegate_ = nullptr; 501 502 // True if static pins should be used. 503 bool enable_static_pins_ = true; 504 505 // True if public key pinning bypass is enabled for local trust anchors. 506 bool enable_pkp_bypass_for_local_trust_anchors_ = true; 507 508 raw_ptr<RequireCTDelegate> require_ct_delegate_ = nullptr; 509 510 std::set<std::string> hsts_host_bypass_list_; 511 512 bool ct_emergency_disable_ = false; 513 514 // The values in host_pins_ maps are references to PinSet objects in the 515 // pinsets_ vector. 516 std::optional< 517 std::map<std::string, std::pair<const PinSet*, bool>, std::less<>>> 518 host_pins_; 519 base::Time key_pins_list_last_update_time_; 520 std::vector<PinSet> pinsets_; 521 522 bool pins_list_always_timely_for_testing_ = false; 523 524 THREAD_CHECKER(thread_checker_); 525 }; 526 527 } // namespace net 528 529 #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_H_ 530