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