• 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 #include "net/http/transport_security_state.h"
6 
7 #include <algorithm>
8 #include <cstdint>
9 #include <memory>
10 #include <tuple>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/base64.h"
15 #include "base/build_time.h"
16 #include "base/containers/contains.h"
17 #include "base/containers/span.h"
18 #include "base/feature_list.h"
19 #include "base/functional/bind.h"
20 #include "base/json/json_writer.h"
21 #include "base/logging.h"
22 #include "base/metrics/field_trial.h"
23 #include "base/metrics/field_trial_params.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_util.h"
26 #include "base/strings/stringprintf.h"
27 #include "base/strings/utf_string_conversions.h"
28 #include "base/time/time.h"
29 #include "base/values.h"
30 #include "build/branding_buildflags.h"
31 #include "build/build_config.h"
32 #include "crypto/sha2.h"
33 #include "net/base/features.h"
34 #include "net/base/hash_value.h"
35 #include "net/base/host_port_pair.h"
36 #include "net/cert/ct_policy_status.h"
37 #include "net/cert/x509_certificate.h"
38 #include "net/dns/dns_names_util.h"
39 #include "net/extras/preload_data/decoder.h"
40 #include "net/http/http_security_headers.h"
41 #include "net/net_buildflags.h"
42 #include "net/ssl/ssl_info.h"
43 #include "third_party/abseil-cpp/absl/types/optional.h"
44 
45 namespace net {
46 
47 namespace {
48 
49 #if BUILDFLAG(INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST)
50 #include "net/http/transport_security_state_static.h"  // nogncheck
51 // Points to the active transport security state source.
52 const TransportSecurityStateSource* const kDefaultHSTSSource = &kHSTSSource;
53 #else
54 const TransportSecurityStateSource* const kDefaultHSTSSource = nullptr;
55 #endif
56 
57 const TransportSecurityStateSource* g_hsts_source = kDefaultHSTSSource;
58 
59 // Parameters for remembering sent HPKP reports.
60 const size_t kMaxReportCacheEntries = 50;
61 const int kTimeToRememberReportsMins = 60;
62 const size_t kReportCacheKeyLength = 16;
63 
64 // Override for CheckCTRequirements() for unit tests. Possible values:
65 //   false: Use the default implementation (e.g. production)
66 //   true: Unless a delegate says otherwise, require CT.
67 bool g_ct_required_for_testing = false;
68 
GetPEMEncodedChainAsList(const net::X509Certificate * cert_chain)69 base::Value GetPEMEncodedChainAsList(const net::X509Certificate* cert_chain) {
70   if (!cert_chain)
71     return base::Value(base::Value::Type::LIST);
72 
73   base::Value::List result;
74   std::vector<std::string> pem_encoded_chain;
75   cert_chain->GetPEMEncodedChain(&pem_encoded_chain);
76   for (const std::string& cert : pem_encoded_chain)
77     result.Append(cert);
78 
79   return base::Value(std::move(result));
80 }
81 
HashReportForCache(const base::Value::Dict & report,const GURL & report_uri,std::string * cache_key)82 bool HashReportForCache(const base::Value::Dict& report,
83                         const GURL& report_uri,
84                         std::string* cache_key) {
85   char hashed[crypto::kSHA256Length];
86   std::string to_hash;
87   if (!base::JSONWriter::Write(report, &to_hash))
88     return false;
89   to_hash += "," + report_uri.spec();
90   crypto::SHA256HashString(to_hash, hashed, sizeof(hashed));
91   static_assert(kReportCacheKeyLength <= sizeof(hashed),
92                 "HPKP report cache key size is larger than hash size.");
93   *cache_key = std::string(hashed, kReportCacheKeyLength);
94   return true;
95 }
96 
97 // Formats a time compliant to ISO 8601 in UTC, e.g. "2020-12-31T23:59:59.999Z".
98 //
99 // This behaves identically to the function in base/i18n/time_formatting.h. It
100 // is reimplemented here since net/ cannot depend on base/i18n/.
TimeFormatAsIso8601(const base::Time & time)101 std::string TimeFormatAsIso8601(const base::Time& time) {
102   base::Time::Exploded exploded;
103   time.UTCExplode(&exploded);
104   return base::StringPrintf(
105       "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month,
106       exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
107       exploded.millisecond);
108 }
109 
GetHPKPReport(const HostPortPair & host_port_pair,const TransportSecurityState::PKPState & pkp_state,const X509Certificate * served_certificate_chain,const X509Certificate * validated_certificate_chain,std::string * serialized_report,std::string * cache_key)110 bool GetHPKPReport(const HostPortPair& host_port_pair,
111                    const TransportSecurityState::PKPState& pkp_state,
112                    const X509Certificate* served_certificate_chain,
113                    const X509Certificate* validated_certificate_chain,
114                    std::string* serialized_report,
115                    std::string* cache_key) {
116   if (pkp_state.report_uri.is_empty())
117     return false;
118 
119   base::Value::Dict report;
120   base::Time now = base::Time::Now();
121   report.Set("hostname", host_port_pair.host());
122   report.Set("port", host_port_pair.port());
123   report.Set("include-subdomains", pkp_state.include_subdomains);
124   report.Set("noted-hostname", pkp_state.domain);
125 
126   auto served_certificate_chain_list =
127       GetPEMEncodedChainAsList(served_certificate_chain);
128   auto validated_certificate_chain_list =
129       GetPEMEncodedChainAsList(validated_certificate_chain);
130   report.Set("served-certificate-chain",
131              std::move(served_certificate_chain_list));
132   report.Set("validated-certificate-chain",
133              std::move(validated_certificate_chain_list));
134 
135   base::Value::List known_pin_list;
136   for (const auto& hash_value : pkp_state.spki_hashes) {
137     std::string known_pin;
138 
139     switch (hash_value.tag()) {
140       case HASH_VALUE_SHA256:
141         known_pin += "pin-sha256=";
142         break;
143       default:
144         // Don't bother reporting about hash types we don't support. SHA-256 is
145         // the only standardized hash function for HPKP anyway.
146         continue;
147     }
148 
149     std::string base64_value;
150     base::Base64Encode(
151         base::StringPiece(reinterpret_cast<const char*>(hash_value.data()),
152                           hash_value.size()),
153         &base64_value);
154     known_pin += "\"" + base64_value + "\"";
155 
156     known_pin_list.Append(known_pin);
157   }
158 
159   report.Set("known-pins", std::move(known_pin_list));
160 
161   // For the sent reports cache, do not include the effective expiration
162   // date. The expiration date will likely change every time the user
163   // visits the site, so it would prevent reports from being effectively
164   // deduplicated.
165   if (!HashReportForCache(report, pkp_state.report_uri, cache_key)) {
166     LOG(ERROR) << "Failed to compute cache key for HPKP violation report.";
167     return false;
168   }
169 
170   report.Set("date-time", TimeFormatAsIso8601(now));
171   report.Set("effective-expiration-date",
172              TimeFormatAsIso8601(pkp_state.expiry));
173   if (!base::JSONWriter::Write(report, serialized_report)) {
174     LOG(ERROR) << "Failed to serialize HPKP violation report.";
175     return false;
176   }
177 
178   return true;
179 }
180 
181 // Do not send a report over HTTPS to the same host that set the
182 // pin. Such report URIs will result in loops. (A.com has a pinning
183 // violation which results in a report being sent to A.com, which
184 // results in a pinning violation which results in a report being sent
185 // to A.com, etc.)
IsReportUriValidForHost(const GURL & report_uri,const std::string & host)186 bool IsReportUriValidForHost(const GURL& report_uri, const std::string& host) {
187   return (report_uri.host_piece() != host ||
188           !report_uri.SchemeIsCryptographic());
189 }
190 
HashesToBase64String(const HashValueVector & hashes)191 std::string HashesToBase64String(const HashValueVector& hashes) {
192   std::string str;
193   for (size_t i = 0; i != hashes.size(); ++i) {
194     if (i != 0)
195       str += ",";
196     str += hashes[i].ToString();
197   }
198   return str;
199 }
200 
HashHost(base::span<const uint8_t> canonicalized_host)201 TransportSecurityState::HashedHost HashHost(
202     base::span<const uint8_t> canonicalized_host) {
203   return crypto::SHA256Hash(canonicalized_host);
204 }
205 
206 // Returns true if the intersection of |a| and |b| is not empty. If either
207 // |a| or |b| is empty, returns false.
HashesIntersect(const HashValueVector & a,const HashValueVector & b)208 bool HashesIntersect(const HashValueVector& a, const HashValueVector& b) {
209   for (const auto& hash : a) {
210     if (base::Contains(b, hash))
211       return true;
212   }
213   return false;
214 }
215 
AddHash(const char * sha256_hash,HashValueVector * out)216 bool AddHash(const char* sha256_hash, HashValueVector* out) {
217   HashValue hash(HASH_VALUE_SHA256);
218   memcpy(hash.data(), sha256_hash, hash.size());
219   out->push_back(hash);
220   return true;
221 }
222 
223 // Converts |hostname| from dotted form ("www.google.com") to the form
224 // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns
225 // the result.
CanonicalizeHost(const std::string & host)226 std::vector<uint8_t> CanonicalizeHost(const std::string& host) {
227   // We cannot perform the operations as detailed in the spec here as `host`
228   // has already undergone IDN processing before it reached us. Thus, we
229   // lowercase the input (probably redudnant since most input here has been
230   // lowercased through URL canonicalization) and check that there are no
231   // invalid characters in the host (via DNSDomainFromDot()).
232   std::string lowered_host = base::ToLowerASCII(host);
233 
234   absl::optional<std::vector<uint8_t>> new_host =
235       dns_names_util::DottedNameToNetwork(
236           lowered_host,
237           /*require_valid_internet_hostname=*/true);
238   if (!new_host.has_value()) {
239     // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
240     // name is >255 bytes. However, search terms can have those properties.
241     return std::vector<uint8_t>();
242   }
243 
244   return new_host.value();
245 }
246 
247 // PreloadResult is the result of resolving a specific name in the preloaded
248 // data.
249 struct PreloadResult {
250   uint32_t pinset_id = 0;
251   // hostname_offset contains the number of bytes from the start of the given
252   // hostname where the name of the matching entry starts.
253   size_t hostname_offset = 0;
254   bool sts_include_subdomains = false;
255   bool pkp_include_subdomains = false;
256   bool force_https = false;
257   bool has_pins = false;
258 };
259 
260 using net::extras::PreloadDecoder;
261 
262 // Extracts the current PreloadResult entry from the given Huffman encoded trie.
263 // If an "end of string" matches a period in the hostname then the information
264 // is remembered because, if no more specific node is found, then that
265 // information applies to the hostname.
266 class HSTSPreloadDecoder : public net::extras::PreloadDecoder {
267  public:
268   using net::extras::PreloadDecoder::PreloadDecoder;
269 
270   // net::extras::PreloadDecoder:
ReadEntry(net::extras::PreloadDecoder::BitReader * reader,const std::string & search,size_t current_search_offset,bool * out_found)271   bool ReadEntry(net::extras::PreloadDecoder::BitReader* reader,
272                  const std::string& search,
273                  size_t current_search_offset,
274                  bool* out_found) override {
275     bool is_simple_entry;
276     if (!reader->Next(&is_simple_entry)) {
277       return false;
278     }
279     PreloadResult tmp;
280     // Simple entries only configure HSTS with IncludeSubdomains and use a
281     // compact serialization format where the other policy flags are
282     // omitted. The omitted flags are assumed to be 0 and the associated
283     // policies are disabled.
284     if (is_simple_entry) {
285       tmp.force_https = true;
286       tmp.sts_include_subdomains = true;
287     } else {
288       if (!reader->Next(&tmp.sts_include_subdomains) ||
289           !reader->Next(&tmp.force_https) || !reader->Next(&tmp.has_pins)) {
290         return false;
291       }
292 
293       tmp.pkp_include_subdomains = tmp.sts_include_subdomains;
294 
295       if (tmp.has_pins) {
296         if (!reader->Read(4, &tmp.pinset_id) ||
297             (!tmp.sts_include_subdomains &&
298              !reader->Next(&tmp.pkp_include_subdomains))) {
299           return false;
300         }
301       }
302     }
303 
304     tmp.hostname_offset = current_search_offset;
305 
306     if (current_search_offset == 0 ||
307         search[current_search_offset - 1] == '.') {
308       *out_found = tmp.sts_include_subdomains || tmp.pkp_include_subdomains;
309 
310       result_ = tmp;
311 
312       if (current_search_offset > 0) {
313         result_.force_https &= tmp.sts_include_subdomains;
314       } else {
315         *out_found = true;
316         return true;
317       }
318     }
319     return true;
320   }
321 
result() const322   PreloadResult result() const { return result_; }
323 
324  private:
325   PreloadResult result_;
326 };
327 
DecodeHSTSPreload(const std::string & search_hostname,PreloadResult * out)328 bool DecodeHSTSPreload(const std::string& search_hostname, PreloadResult* out) {
329 #if !BUILDFLAG(INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST)
330   if (g_hsts_source == nullptr)
331     return false;
332 #endif
333   bool found = false;
334 
335   // Ensure that |search_hostname| is a valid hostname before
336   // processing.
337   if (CanonicalizeHost(search_hostname).empty()) {
338     return false;
339   }
340   // Normalize any trailing '.' used for DNS suffix searches.
341   std::string hostname = search_hostname;
342   size_t trailing_dot_found = hostname.find_last_not_of('.');
343   if (trailing_dot_found != std::string::npos) {
344     hostname.erase(trailing_dot_found + 1);
345   } else {
346     hostname.clear();
347   }
348 
349   // |hostname| has already undergone IDN conversion, so should be
350   // entirely A-Labels. The preload data is entirely normalized to
351   // lower case.
352   hostname = base::ToLowerASCII(hostname);
353   if (hostname.empty()) {
354     return false;
355   }
356 
357   HSTSPreloadDecoder decoder(
358       g_hsts_source->huffman_tree, g_hsts_source->huffman_tree_size,
359       g_hsts_source->preloaded_data, g_hsts_source->preloaded_bits,
360       g_hsts_source->root_position);
361   if (!decoder.Decode(hostname, &found)) {
362     DCHECK(false) << "Internal error in DecodeHSTSPreload for hostname "
363                   << hostname;
364     return false;
365   }
366   if (found)
367     *out = decoder.result();
368   return found;
369 }
370 
371 }  // namespace
372 
373 // static
374 BASE_FEATURE(kCertificateTransparencyEnforcement,
375              "CertificateTransparencyEnforcement",
376              base::FEATURE_ENABLED_BY_DEFAULT);
377 
SetTransportSecurityStateSourceForTesting(const TransportSecurityStateSource * source)378 void SetTransportSecurityStateSourceForTesting(
379     const TransportSecurityStateSource* source) {
380   g_hsts_source = source ? source : kDefaultHSTSSource;
381 }
382 
TransportSecurityState()383 TransportSecurityState::TransportSecurityState()
384     : TransportSecurityState(std::vector<std::string>()) {}
385 
TransportSecurityState(std::vector<std::string> hsts_host_bypass_list)386 TransportSecurityState::TransportSecurityState(
387     std::vector<std::string> hsts_host_bypass_list)
388     : sent_hpkp_reports_cache_(kMaxReportCacheEntries) {
389 // Static pinning is only enabled for official builds to make sure that
390 // others don't end up with pins that cannot be easily updated.
391 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING) || BUILDFLAG(IS_IOS)
392   enable_static_pins_ = false;
393 #endif
394   // Check that there no invalid entries in the static HSTS bypass list.
395   for (auto& host : hsts_host_bypass_list) {
396     DCHECK(host.find('.') == std::string::npos);
397     hsts_host_bypass_list_.insert(host);
398   }
399   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
400 }
401 
402 // Both HSTS and HPKP cause fatal SSL errors, so return true if a
403 // host has either.
ShouldSSLErrorsBeFatal(const std::string & host)404 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host) {
405   STSState unused_sts;
406   PKPState unused_pkp;
407   return GetSTSState(host, &unused_sts) || GetPKPState(host, &unused_pkp);
408 }
409 
NetLogUpgradeToSSLParam(const std::string & host)410 base::Value::Dict TransportSecurityState::NetLogUpgradeToSSLParam(
411     const std::string& host) {
412   STSState sts_state;
413   base::Value::Dict dict;
414   dict.Set("host", host);
415   dict.Set("get_sts_state_result", GetSTSState(host, &sts_state));
416   dict.Set("should_upgrade_to_ssl", sts_state.ShouldUpgradeToSSL());
417   dict.Set("host_found_in_hsts_bypass_list",
418            hsts_host_bypass_list_.find(host) != hsts_host_bypass_list_.end());
419   return dict;
420 }
421 
ShouldUpgradeToSSL(const std::string & host,const NetLogWithSource & net_log)422 bool TransportSecurityState::ShouldUpgradeToSSL(
423     const std::string& host,
424     const NetLogWithSource& net_log) {
425   STSState sts_state;
426   net_log.AddEvent(
427       NetLogEventType::TRANSPORT_SECURITY_STATE_SHOULD_UPGRADE_TO_SSL,
428       [&] { return NetLogUpgradeToSSLParam(host); });
429   return GetSTSState(host, &sts_state) && sts_state.ShouldUpgradeToSSL();
430 }
431 
CheckPublicKeyPins(const HostPortPair & host_port_pair,bool is_issued_by_known_root,const HashValueVector & public_key_hashes,const X509Certificate * served_certificate_chain,const X509Certificate * validated_certificate_chain,const PublicKeyPinReportStatus report_status,const NetworkAnonymizationKey & network_anonymization_key,std::string * pinning_failure_log)432 TransportSecurityState::PKPStatus TransportSecurityState::CheckPublicKeyPins(
433     const HostPortPair& host_port_pair,
434     bool is_issued_by_known_root,
435     const HashValueVector& public_key_hashes,
436     const X509Certificate* served_certificate_chain,
437     const X509Certificate* validated_certificate_chain,
438     const PublicKeyPinReportStatus report_status,
439     const NetworkAnonymizationKey& network_anonymization_key,
440     std::string* pinning_failure_log) {
441   // Perform pin validation only if the server actually has public key pins.
442   if (!HasPublicKeyPins(host_port_pair.host())) {
443     return PKPStatus::OK;
444   }
445 
446   return CheckPublicKeyPinsImpl(host_port_pair, is_issued_by_known_root,
447                                 public_key_hashes, served_certificate_chain,
448                                 validated_certificate_chain, report_status,
449                                 network_anonymization_key, pinning_failure_log);
450 }
451 
HasPublicKeyPins(const std::string & host)452 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
453   PKPState pkp_state;
454   return GetPKPState(host, &pkp_state) && pkp_state.HasPublicKeyPins();
455 }
456 
457 TransportSecurityState::CTRequirementsStatus
CheckCTRequirements(const net::HostPortPair & host_port_pair,bool is_issued_by_known_root,const HashValueVector & public_key_hashes,const X509Certificate * validated_certificate_chain,const X509Certificate * served_certificate_chain,const SignedCertificateTimestampAndStatusList & signed_certificate_timestamps,ct::CTPolicyCompliance policy_compliance)458 TransportSecurityState::CheckCTRequirements(
459     const net::HostPortPair& host_port_pair,
460     bool is_issued_by_known_root,
461     const HashValueVector& public_key_hashes,
462     const X509Certificate* validated_certificate_chain,
463     const X509Certificate* served_certificate_chain,
464     const SignedCertificateTimestampAndStatusList&
465         signed_certificate_timestamps,
466     ct::CTPolicyCompliance policy_compliance) {
467   using CTRequirementLevel = RequireCTDelegate::CTRequirementLevel;
468   std::string hostname = host_port_pair.host();
469 
470   // If CT is emergency disabled, either through a component updater set flag or
471   // through the feature flag, we don't require CT for any host.
472   if (ct_emergency_disable_ ||
473       !base::FeatureList::IsEnabled(kCertificateTransparencyEnforcement)) {
474     return CT_NOT_REQUIRED;
475   }
476 
477   // CT is not required if the certificate does not chain to a publicly
478   // trusted root certificate. Testing can override this, as certain tests
479   // rely on using a non-publicly-trusted root.
480   if (!is_issued_by_known_root && !g_ct_required_for_testing)
481     return CT_NOT_REQUIRED;
482 
483   // A connection is considered compliant if it has sufficient SCTs or if the
484   // build is outdated. Other statuses are not considered compliant; this
485   // includes COMPLIANCE_DETAILS_NOT_AVAILABLE because compliance must have been
486   // evaluated in order to determine that the connection is compliant.
487   bool complies =
488       (policy_compliance ==
489            ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS ||
490        policy_compliance == ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY);
491 
492   CTRequirementLevel ct_required = g_ct_required_for_testing
493                                        ? CTRequirementLevel::REQUIRED
494                                        : CTRequirementLevel::NOT_REQUIRED;
495   if (require_ct_delegate_) {
496     // Allow the delegate to override the CT requirement state.
497     ct_required = require_ct_delegate_->IsCTRequiredForHost(
498         hostname, validated_certificate_chain, public_key_hashes);
499   }
500   switch (ct_required) {
501     case CTRequirementLevel::REQUIRED:
502       return complies ? CT_REQUIREMENTS_MET : CT_REQUIREMENTS_NOT_MET;
503     case CTRequirementLevel::NOT_REQUIRED:
504       return CT_NOT_REQUIRED;
505   }
506 }
507 
SetDelegate(TransportSecurityState::Delegate * delegate)508 void TransportSecurityState::SetDelegate(
509     TransportSecurityState::Delegate* delegate) {
510   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
511   delegate_ = delegate;
512 }
513 
SetReportSender(TransportSecurityState::ReportSenderInterface * report_sender)514 void TransportSecurityState::SetReportSender(
515     TransportSecurityState::ReportSenderInterface* report_sender) {
516   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
517   report_sender_ = report_sender;
518 }
519 
SetRequireCTDelegate(RequireCTDelegate * delegate)520 void TransportSecurityState::SetRequireCTDelegate(RequireCTDelegate* delegate) {
521   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
522   require_ct_delegate_ = delegate;
523 }
524 
UpdatePinList(const std::vector<PinSet> & pinsets,const std::vector<PinSetInfo> & host_pins,base::Time update_time)525 void TransportSecurityState::UpdatePinList(
526     const std::vector<PinSet>& pinsets,
527     const std::vector<PinSetInfo>& host_pins,
528     base::Time update_time) {
529   pinsets_ = pinsets;
530   key_pins_list_last_update_time_ = update_time;
531   host_pins_.emplace();
532   std::map<std::string, PinSet const*> pinset_names_map;
533   for (const auto& pinset : pinsets_) {
534     pinset_names_map[pinset.name()] = &pinset;
535   }
536   for (const auto& pin : host_pins) {
537     if (!base::Contains(pinset_names_map, pin.pinset_name_)) {
538       // This should never happen, but if the component is bad and missing an
539       // entry, we will ignore that particular pin.
540       continue;
541     }
542     host_pins_.value()[pin.hostname_] = std::make_pair(
543         pinset_names_map[pin.pinset_name_], pin.include_subdomains_);
544   }
545 }
546 
AddHSTSInternal(const std::string & host,TransportSecurityState::STSState::UpgradeMode upgrade_mode,const base::Time & expiry,bool include_subdomains)547 void TransportSecurityState::AddHSTSInternal(
548     const std::string& host,
549     TransportSecurityState::STSState::UpgradeMode upgrade_mode,
550     const base::Time& expiry,
551     bool include_subdomains) {
552   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
553   const std::vector<uint8_t> canonicalized_host = CanonicalizeHost(host);
554   if (canonicalized_host.empty())
555     return;
556 
557   STSState sts_state;
558   // No need to store |sts_state.domain| since it is redundant.
559   // (|canonicalized_host| is the map key.)
560   sts_state.last_observed = base::Time::Now();
561   sts_state.include_subdomains = include_subdomains;
562   sts_state.expiry = expiry;
563   sts_state.upgrade_mode = upgrade_mode;
564 
565   // Only store new state when HSTS is explicitly enabled. If it is
566   // disabled, remove the state from the enabled hosts.
567   if (sts_state.ShouldUpgradeToSSL()) {
568     enabled_sts_hosts_[HashHost(canonicalized_host)] = sts_state;
569   } else {
570     const HashedHost hashed_host = HashHost(canonicalized_host);
571     enabled_sts_hosts_.erase(hashed_host);
572   }
573 
574   DirtyNotify();
575 }
576 
AddHPKPInternal(const std::string & host,const base::Time & last_observed,const base::Time & expiry,bool include_subdomains,const HashValueVector & hashes,const GURL & report_uri)577 void TransportSecurityState::AddHPKPInternal(const std::string& host,
578                                              const base::Time& last_observed,
579                                              const base::Time& expiry,
580                                              bool include_subdomains,
581                                              const HashValueVector& hashes,
582                                              const GURL& report_uri) {
583   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
584   const std::vector<uint8_t> canonicalized_host = CanonicalizeHost(host);
585   if (canonicalized_host.empty())
586     return;
587 
588   PKPState pkp_state;
589   // No need to store |pkp_state.domain| since it is redundant.
590   // (|canonicalized_host| is the map key.)
591   pkp_state.last_observed = last_observed;
592   pkp_state.expiry = expiry;
593   pkp_state.include_subdomains = include_subdomains;
594   pkp_state.spki_hashes = hashes;
595   pkp_state.report_uri = report_uri;
596 
597   // Only store new state when HPKP is explicitly enabled. If it is
598   // disabled, remove the state from the enabled hosts.
599   if (pkp_state.HasPublicKeyPins()) {
600     enabled_pkp_hosts_[HashHost(canonicalized_host)] = pkp_state;
601   } else {
602     const HashedHost hashed_host = HashHost(canonicalized_host);
603     enabled_pkp_hosts_.erase(hashed_host);
604   }
605 
606   DirtyNotify();
607 }
608 
609 void TransportSecurityState::
SetEnablePublicKeyPinningBypassForLocalTrustAnchors(bool value)610     SetEnablePublicKeyPinningBypassForLocalTrustAnchors(bool value) {
611   enable_pkp_bypass_for_local_trust_anchors_ = value;
612 }
613 
614 TransportSecurityState::PKPStatus
CheckPinsAndMaybeSendReport(const HostPortPair & host_port_pair,bool is_issued_by_known_root,const TransportSecurityState::PKPState & pkp_state,const HashValueVector & hashes,const X509Certificate * served_certificate_chain,const X509Certificate * validated_certificate_chain,const TransportSecurityState::PublicKeyPinReportStatus report_status,const net::NetworkAnonymizationKey & network_anonymization_key,std::string * failure_log)615 TransportSecurityState::CheckPinsAndMaybeSendReport(
616     const HostPortPair& host_port_pair,
617     bool is_issued_by_known_root,
618     const TransportSecurityState::PKPState& pkp_state,
619     const HashValueVector& hashes,
620     const X509Certificate* served_certificate_chain,
621     const X509Certificate* validated_certificate_chain,
622     const TransportSecurityState::PublicKeyPinReportStatus report_status,
623     const net::NetworkAnonymizationKey& network_anonymization_key,
624     std::string* failure_log) {
625   if (pkp_state.CheckPublicKeyPins(hashes, failure_log))
626     return PKPStatus::OK;
627 
628   // Don't report violations for certificates that chain to local roots.
629   if (!is_issued_by_known_root && enable_pkp_bypass_for_local_trust_anchors_)
630     return PKPStatus::BYPASSED;
631 
632   if (!report_sender_ ||
633       report_status != TransportSecurityState::ENABLE_PIN_REPORTS ||
634       pkp_state.report_uri.is_empty()) {
635     return PKPStatus::VIOLATED;
636   }
637 
638   DCHECK(pkp_state.report_uri.is_valid());
639   // Report URIs should not be used if they are the same host as the pin
640   // and are HTTPS, to avoid going into a report-sending loop.
641   if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host()))
642     return PKPStatus::VIOLATED;
643 
644   std::string serialized_report;
645   std::string report_cache_key;
646   if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain,
647                      validated_certificate_chain, &serialized_report,
648                      &report_cache_key)) {
649     return PKPStatus::VIOLATED;
650   }
651 
652   // Limit the rate at which duplicate reports are sent to the same
653   // report URI. The same report will not be sent within
654   // |kTimeToRememberReportsMins|, which reduces load on servers and
655   // also prevents accidental loops (a.com triggers a report to b.com
656   // which triggers a report to a.com). See section 2.1.4 of RFC 7469.
657   if (sent_hpkp_reports_cache_.Get(report_cache_key, base::TimeTicks::Now()))
658     return PKPStatus::VIOLATED;
659   sent_hpkp_reports_cache_.Put(
660       report_cache_key, true, base::TimeTicks::Now(),
661       base::TimeTicks::Now() + base::Minutes(kTimeToRememberReportsMins));
662 
663   report_sender_->Send(pkp_state.report_uri, "application/json; charset=utf-8",
664                        serialized_report, network_anonymization_key,
665                        base::OnceCallback<void()>(),
666                        base::OnceCallback<void(const GURL&, int, int)>());
667   return PKPStatus::VIOLATED;
668 }
669 
DeleteDynamicDataForHost(const std::string & host)670 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
671   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
672 
673   const std::vector<uint8_t> canonicalized_host = CanonicalizeHost(host);
674   if (canonicalized_host.empty())
675     return false;
676 
677   const HashedHost hashed_host = HashHost(canonicalized_host);
678   bool deleted = false;
679   auto sts_interator = enabled_sts_hosts_.find(hashed_host);
680   if (sts_interator != enabled_sts_hosts_.end()) {
681     enabled_sts_hosts_.erase(sts_interator);
682     deleted = true;
683   }
684 
685   auto pkp_iterator = enabled_pkp_hosts_.find(hashed_host);
686   if (pkp_iterator != enabled_pkp_hosts_.end()) {
687     enabled_pkp_hosts_.erase(pkp_iterator);
688     deleted = true;
689   }
690 
691   if (deleted)
692     DirtyNotify();
693   return deleted;
694 }
695 
ClearDynamicData()696 void TransportSecurityState::ClearDynamicData() {
697   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
698   enabled_sts_hosts_.clear();
699   enabled_pkp_hosts_.clear();
700 }
701 
DeleteAllDynamicDataBetween(base::Time start_time,base::Time end_time,base::OnceClosure callback)702 void TransportSecurityState::DeleteAllDynamicDataBetween(
703     base::Time start_time,
704     base::Time end_time,
705     base::OnceClosure callback) {
706   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
707 
708   bool dirtied = false;
709   auto sts_iterator = enabled_sts_hosts_.begin();
710   while (sts_iterator != enabled_sts_hosts_.end()) {
711     if (sts_iterator->second.last_observed >= start_time &&
712         sts_iterator->second.last_observed < end_time) {
713       dirtied = true;
714       enabled_sts_hosts_.erase(sts_iterator++);
715       continue;
716     }
717 
718     ++sts_iterator;
719   }
720 
721   auto pkp_iterator = enabled_pkp_hosts_.begin();
722   while (pkp_iterator != enabled_pkp_hosts_.end()) {
723     if (pkp_iterator->second.last_observed >= start_time &&
724         pkp_iterator->second.last_observed < end_time) {
725       dirtied = true;
726       enabled_pkp_hosts_.erase(pkp_iterator++);
727       continue;
728     }
729 
730     ++pkp_iterator;
731   }
732 
733   if (dirtied && delegate_)
734     delegate_->WriteNow(this, std::move(callback));
735   else
736     std::move(callback).Run();
737 }
738 
~TransportSecurityState()739 TransportSecurityState::~TransportSecurityState() {
740   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
741 }
742 
DirtyNotify()743 void TransportSecurityState::DirtyNotify() {
744   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
745 
746   if (delegate_)
747     delegate_->StateIsDirty(this);
748 }
749 
AddHSTSHeader(const std::string & host,const std::string & value)750 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
751                                            const std::string& value) {
752   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
753 
754   base::Time now = base::Time::Now();
755   base::TimeDelta max_age;
756   bool include_subdomains;
757   if (!ParseHSTSHeader(value, &max_age, &include_subdomains)) {
758     return false;
759   }
760 
761   // Handle max-age == 0.
762   STSState::UpgradeMode upgrade_mode;
763   if (max_age.InSeconds() == 0) {
764     upgrade_mode = STSState::MODE_DEFAULT;
765   } else {
766     upgrade_mode = STSState::MODE_FORCE_HTTPS;
767   }
768 
769   AddHSTSInternal(host, upgrade_mode, now + max_age, include_subdomains);
770   return true;
771 }
772 
AddHSTS(const std::string & host,const base::Time & expiry,bool include_subdomains)773 void TransportSecurityState::AddHSTS(const std::string& host,
774                                      const base::Time& expiry,
775                                      bool include_subdomains) {
776   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
777   AddHSTSInternal(host, STSState::MODE_FORCE_HTTPS, expiry, include_subdomains);
778 }
779 
AddHPKP(const std::string & host,const base::Time & expiry,bool include_subdomains,const HashValueVector & hashes,const GURL & report_uri)780 void TransportSecurityState::AddHPKP(const std::string& host,
781                                      const base::Time& expiry,
782                                      bool include_subdomains,
783                                      const HashValueVector& hashes,
784                                      const GURL& report_uri) {
785   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
786   AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes,
787                   report_uri);
788 }
789 
790 // static
SetRequireCTForTesting(bool required)791 void TransportSecurityState::SetRequireCTForTesting(bool required) {
792   g_ct_required_for_testing = required;
793 }
794 
ClearReportCachesForTesting()795 void TransportSecurityState::ClearReportCachesForTesting() {
796   sent_hpkp_reports_cache_.Clear();
797 }
798 
num_sts_entries() const799 size_t TransportSecurityState::num_sts_entries() const {
800   return enabled_sts_hosts_.size();
801 }
802 
803 // static
IsBuildTimely()804 bool TransportSecurityState::IsBuildTimely() {
805   const base::Time build_time = base::GetBuildTime();
806   // We consider built-in information to be timely for 10 weeks.
807   return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
808 }
809 
810 TransportSecurityState::PKPStatus
CheckPublicKeyPinsImpl(const HostPortPair & host_port_pair,bool is_issued_by_known_root,const HashValueVector & hashes,const X509Certificate * served_certificate_chain,const X509Certificate * validated_certificate_chain,const PublicKeyPinReportStatus report_status,const NetworkAnonymizationKey & network_anonymization_key,std::string * failure_log)811 TransportSecurityState::CheckPublicKeyPinsImpl(
812     const HostPortPair& host_port_pair,
813     bool is_issued_by_known_root,
814     const HashValueVector& hashes,
815     const X509Certificate* served_certificate_chain,
816     const X509Certificate* validated_certificate_chain,
817     const PublicKeyPinReportStatus report_status,
818     const NetworkAnonymizationKey& network_anonymization_key,
819     std::string* failure_log) {
820   PKPState pkp_state;
821   bool found_state = GetPKPState(host_port_pair.host(), &pkp_state);
822 
823   // HasPublicKeyPins should have returned true in order for this method to have
824   // been called.
825   DCHECK(found_state);
826   return CheckPinsAndMaybeSendReport(
827       host_port_pair, is_issued_by_known_root, pkp_state, hashes,
828       served_certificate_chain, validated_certificate_chain, report_status,
829       network_anonymization_key, failure_log);
830 }
831 
GetStaticSTSState(const std::string & host,STSState * sts_result) const832 bool TransportSecurityState::GetStaticSTSState(const std::string& host,
833                                                STSState* sts_result) const {
834   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
835 
836   if (!IsBuildTimely())
837     return false;
838 
839   PreloadResult result;
840   if (DecodeHSTSPreload(host, &result) &&
841       hsts_host_bypass_list_.find(host) == hsts_host_bypass_list_.end() &&
842       result.force_https) {
843     sts_result->domain = host.substr(result.hostname_offset);
844     sts_result->include_subdomains = result.sts_include_subdomains;
845     sts_result->last_observed = base::GetBuildTime();
846     sts_result->upgrade_mode = STSState::MODE_FORCE_HTTPS;
847     return true;
848   }
849 
850   return false;
851 }
852 
GetStaticPKPState(const std::string & host,PKPState * pkp_result) const853 bool TransportSecurityState::GetStaticPKPState(const std::string& host,
854                                                PKPState* pkp_result) const {
855   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
856 
857   if (!enable_static_pins_ || !IsStaticPKPListTimely() ||
858       !base::FeatureList::IsEnabled(features::kStaticKeyPinningEnforcement)) {
859     return false;
860   }
861 
862   PreloadResult result;
863   if (host_pins_.has_value()) {
864     // Ensure that |host| is a valid hostname before processing.
865     if (CanonicalizeHost(host).empty()) {
866       return false;
867     }
868     // Normalize any trailing '.' used for DNS suffix searches.
869     std::string normalized_host = host;
870     size_t trailing_dot_found = normalized_host.find_last_not_of('.');
871     if (trailing_dot_found == std::string::npos) {
872       // Hostname is either empty or all dots
873       return false;
874     }
875     normalized_host.erase(trailing_dot_found + 1);
876     normalized_host = base::ToLowerASCII(normalized_host);
877 
878     base::StringPiece search_hostname = normalized_host;
879     while (true) {
880       auto iter = host_pins_->find(search_hostname);
881       // Only consider this a match if either include_subdomains is set, or
882       // this is an exact match of the full hostname.
883       if (iter != host_pins_->end() &&
884           (iter->second.second || search_hostname == normalized_host)) {
885         pkp_result->domain = std::string(search_hostname);
886         pkp_result->last_observed = key_pins_list_last_update_time_;
887         pkp_result->include_subdomains = iter->second.second;
888         const PinSet* pinset = iter->second.first;
889         if (!pinset->report_uri().empty()) {
890           pkp_result->report_uri = GURL(pinset->report_uri());
891         }
892         for (auto hash : pinset->static_spki_hashes()) {
893           // If the update is malformed, it's preferable to skip the hash than
894           // crash.
895           if (hash.size() == 32) {
896             AddHash(reinterpret_cast<const char*>(hash.data()),
897                     &pkp_result->spki_hashes);
898           }
899         }
900         for (auto hash : pinset->bad_static_spki_hashes()) {
901           // If the update is malformed, it's preferable to skip the hash than
902           // crash.
903           if (hash.size() == 32) {
904             AddHash(reinterpret_cast<const char*>(hash.data()),
905                     &pkp_result->bad_spki_hashes);
906           }
907         }
908         return true;
909       }
910       auto dot_pos = search_hostname.find(".");
911       if (dot_pos == std::string::npos) {
912         // If this was not a match, and there are no more dots in the string,
913         // there are no more domains to try.
914         return false;
915       }
916       // Try again in case this is a subdomain of a pinned domain that includes
917       // subdomains.
918       search_hostname = search_hostname.substr(dot_pos + 1);
919     }
920   } else if (DecodeHSTSPreload(host, &result) && result.has_pins) {
921     if (result.pinset_id >= g_hsts_source->pinsets_count)
922       return false;
923 
924     pkp_result->domain = host.substr(result.hostname_offset);
925     pkp_result->include_subdomains = result.pkp_include_subdomains;
926     pkp_result->last_observed = base::GetBuildTime();
927 
928     const TransportSecurityStateSource::Pinset* pinset =
929         &g_hsts_source->pinsets[result.pinset_id];
930     if (pinset->report_uri != kNoReportURI)
931       pkp_result->report_uri = GURL(pinset->report_uri);
932 
933     if (pinset->accepted_pins) {
934       const char* const* sha256_hash = pinset->accepted_pins;
935       while (*sha256_hash) {
936         AddHash(*sha256_hash, &pkp_result->spki_hashes);
937         sha256_hash++;
938       }
939     }
940     if (pinset->rejected_pins) {
941       const char* const* sha256_hash = pinset->rejected_pins;
942       while (*sha256_hash) {
943         AddHash(*sha256_hash, &pkp_result->bad_spki_hashes);
944         sha256_hash++;
945       }
946     }
947     return true;
948   }
949 
950   return false;
951 }
952 
GetSTSState(const std::string & host,STSState * result)953 bool TransportSecurityState::GetSTSState(const std::string& host,
954                                          STSState* result) {
955   return GetDynamicSTSState(host, result) || GetStaticSTSState(host, result);
956 }
957 
GetPKPState(const std::string & host,PKPState * result)958 bool TransportSecurityState::GetPKPState(const std::string& host,
959                                          PKPState* result) {
960   return GetDynamicPKPState(host, result) || GetStaticPKPState(host, result);
961 }
962 
GetDynamicSTSState(const std::string & host,STSState * result)963 bool TransportSecurityState::GetDynamicSTSState(const std::string& host,
964                                                 STSState* result) {
965   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
966 
967   const std::vector<uint8_t> canonicalized_host = CanonicalizeHost(host);
968   if (canonicalized_host.empty())
969     return false;
970 
971   base::Time current_time(base::Time::Now());
972 
973   for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
974     base::span<const uint8_t> host_sub_chunk =
975         base::make_span(canonicalized_host).subspan(i);
976     auto j = enabled_sts_hosts_.find(HashHost(host_sub_chunk));
977     if (j == enabled_sts_hosts_.end())
978       continue;
979 
980     // If the entry is invalid, drop it.
981     if (current_time > j->second.expiry) {
982       enabled_sts_hosts_.erase(j);
983       DirtyNotify();
984       continue;
985     }
986 
987     // An entry matches if it is either an exact match, or if it is a prefix
988     // match and the includeSubDomains directive was included.
989     if (i == 0 || j->second.include_subdomains) {
990       absl::optional<std::string> dotted_name =
991           dns_names_util::NetworkToDottedName(host_sub_chunk);
992       if (!dotted_name)
993         return false;
994 
995       *result = j->second;
996       result->domain = std::move(dotted_name).value();
997       return true;
998     }
999   }
1000 
1001   return false;
1002 }
1003 
GetDynamicPKPState(const std::string & host,PKPState * result)1004 bool TransportSecurityState::GetDynamicPKPState(const std::string& host,
1005                                                 PKPState* result) {
1006   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1007 
1008   const std::vector<uint8_t> canonicalized_host = CanonicalizeHost(host);
1009   if (canonicalized_host.empty())
1010     return false;
1011 
1012   base::Time current_time(base::Time::Now());
1013 
1014   for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
1015     base::span<const uint8_t> host_sub_chunk =
1016         base::make_span(canonicalized_host).subspan(i);
1017     auto j = enabled_pkp_hosts_.find(HashHost(host_sub_chunk));
1018     if (j == enabled_pkp_hosts_.end())
1019       continue;
1020 
1021     // If the entry is invalid, drop it.
1022     if (current_time > j->second.expiry) {
1023       enabled_pkp_hosts_.erase(j);
1024       DirtyNotify();
1025       continue;
1026     }
1027 
1028     // If this is the most specific PKP match, add it to the result. Note: a PKP
1029     // entry at a more specific domain overrides a less specific domain whether
1030     // or not |include_subdomains| is set.
1031     //
1032     // TODO(davidben): This does not match the HSTS behavior. We no longer
1033     // implement HPKP, so this logic is only used via AddHPKP(), reachable from
1034     // Cronet.
1035     if (i == 0 || j->second.include_subdomains) {
1036       absl::optional<std::string> dotted_name =
1037           dns_names_util::NetworkToDottedName(host_sub_chunk);
1038       if (!dotted_name)
1039         return false;
1040 
1041       *result = j->second;
1042       result->domain = std::move(dotted_name).value();
1043       return true;
1044     }
1045 
1046     break;
1047   }
1048 
1049   return false;
1050 }
1051 
AddOrUpdateEnabledSTSHosts(const HashedHost & hashed_host,const STSState & state)1052 void TransportSecurityState::AddOrUpdateEnabledSTSHosts(
1053     const HashedHost& hashed_host,
1054     const STSState& state) {
1055   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1056   DCHECK(state.ShouldUpgradeToSSL());
1057   enabled_sts_hosts_[hashed_host] = state;
1058 }
1059 
1060 TransportSecurityState::STSState::STSState() = default;
1061 
1062 TransportSecurityState::STSState::~STSState() = default;
1063 
ShouldUpgradeToSSL() const1064 bool TransportSecurityState::STSState::ShouldUpgradeToSSL() const {
1065   return upgrade_mode == MODE_FORCE_HTTPS;
1066 }
1067 
STSStateIterator(const TransportSecurityState & state)1068 TransportSecurityState::STSStateIterator::STSStateIterator(
1069     const TransportSecurityState& state)
1070     : iterator_(state.enabled_sts_hosts_.begin()),
1071       end_(state.enabled_sts_hosts_.end()) {}
1072 
1073 TransportSecurityState::STSStateIterator::~STSStateIterator() = default;
1074 
1075 TransportSecurityState::PKPState::PKPState() = default;
1076 
1077 TransportSecurityState::PKPState::PKPState(const PKPState& other) = default;
1078 
1079 TransportSecurityState::PKPState::~PKPState() = default;
1080 
PinSet(std::string name,std::vector<std::vector<uint8_t>> static_spki_hashes,std::vector<std::vector<uint8_t>> bad_static_spki_hashes,std::string report_uri)1081 TransportSecurityState::PinSet::PinSet(
1082     std::string name,
1083     std::vector<std::vector<uint8_t>> static_spki_hashes,
1084     std::vector<std::vector<uint8_t>> bad_static_spki_hashes,
1085     std::string report_uri)
1086     : name_(std::move(name)),
1087       static_spki_hashes_(std::move(static_spki_hashes)),
1088       bad_static_spki_hashes_(std::move(bad_static_spki_hashes)),
1089       report_uri_(std::move(report_uri)) {}
1090 
1091 TransportSecurityState::PinSet::PinSet(const PinSet& other) = default;
1092 TransportSecurityState::PinSet::~PinSet() = default;
1093 
PinSetInfo(std::string hostname,std::string pinset_name,bool include_subdomains)1094 TransportSecurityState::PinSetInfo::PinSetInfo(std::string hostname,
1095                                                std::string pinset_name,
1096                                                bool include_subdomains)
1097     : hostname_(std::move(hostname)),
1098       pinset_name_(std::move(pinset_name)),
1099       include_subdomains_(std::move(include_subdomains)) {}
1100 
CheckPublicKeyPins(const HashValueVector & hashes,std::string * failure_log) const1101 bool TransportSecurityState::PKPState::CheckPublicKeyPins(
1102     const HashValueVector& hashes,
1103     std::string* failure_log) const {
1104   // Validate that hashes is not empty. By the time this code is called (in
1105   // production), that should never happen, but it's good to be defensive.
1106   // And, hashes *can* be empty in some test scenarios.
1107   if (hashes.empty()) {
1108     failure_log->append(
1109         "Rejecting empty public key chain for public-key-pinned domains: " +
1110         domain);
1111     return false;
1112   }
1113 
1114   if (HashesIntersect(bad_spki_hashes, hashes)) {
1115     failure_log->append("Rejecting public key chain for domain " + domain +
1116                         ". Validated chain: " + HashesToBase64String(hashes) +
1117                         ", matches one or more bad hashes: " +
1118                         HashesToBase64String(bad_spki_hashes));
1119     return false;
1120   }
1121 
1122   // If there are no pins, then any valid chain is acceptable.
1123   if (spki_hashes.empty())
1124     return true;
1125 
1126   if (HashesIntersect(spki_hashes, hashes)) {
1127     return true;
1128   }
1129 
1130   failure_log->append("Rejecting public key chain for domain " + domain +
1131                       ". Validated chain: " + HashesToBase64String(hashes) +
1132                       ", expected: " + HashesToBase64String(spki_hashes));
1133   return false;
1134 }
1135 
HasPublicKeyPins() const1136 bool TransportSecurityState::PKPState::HasPublicKeyPins() const {
1137   return spki_hashes.size() > 0 || bad_spki_hashes.size() > 0;
1138 }
1139 
IsStaticPKPListTimely() const1140 bool TransportSecurityState::IsStaticPKPListTimely() const {
1141   if (pins_list_always_timely_for_testing_) {
1142     return true;
1143   }
1144 
1145   // If the list has not been updated via component updater, freshness depends
1146   // on the compiled-in list freshness.
1147   if (!host_pins_.has_value()) {
1148 #if BUILDFLAG(INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST)
1149     return (base::Time::Now() - kPinsListTimestamp).InDays() < 70;
1150 #else
1151     return false;
1152 #endif
1153   }
1154   DCHECK(!key_pins_list_last_update_time_.is_null());
1155   // Else, we use the last update time.
1156   return (base::Time::Now() - key_pins_list_last_update_time_).InDays() <
1157          70 /* 10 weeks */;
1158 }
1159 
1160 }  // namespace net
1161