• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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