Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / http / transport_security_state.cc
blob8ad73581e85a2670ac48fcd5c43e3f7dd2161ba3
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/transport_security_state.h"
7 #if defined(USE_OPENSSL)
8 #include <openssl/ecdsa.h>
9 #include <openssl/ssl.h>
10 #else // !defined(USE_OPENSSL)
11 #include <cryptohi.h>
12 #include <hasht.h>
13 #include <keyhi.h>
14 #include <nspr.h>
15 #include <pk11pub.h>
16 #endif
18 #include <algorithm>
20 #include "base/base64.h"
21 #include "base/build_time.h"
22 #include "base/logging.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/metrics/histogram_macros.h"
25 #include "base/metrics/sparse_histogram.h"
26 #include "base/sha1.h"
27 #include "base/strings/string_number_conversions.h"
28 #include "base/strings/string_util.h"
29 #include "base/strings/utf_string_conversions.h"
30 #include "base/time/time.h"
31 #include "base/values.h"
32 #include "crypto/sha2.h"
33 #include "net/base/dns_util.h"
34 #include "net/cert/x509_cert_types.h"
35 #include "net/cert/x509_certificate.h"
36 #include "net/http/http_security_headers.h"
37 #include "net/ssl/ssl_info.h"
38 #include "url/gurl.h"
40 #if defined(USE_OPENSSL)
41 #include "crypto/openssl_util.h"
42 #endif
44 namespace net {
46 namespace {
48 #include "net/http/transport_security_state_static.h"
50 std::string HashesToBase64String(const HashValueVector& hashes) {
51 std::string str;
52 for (size_t i = 0; i != hashes.size(); ++i) {
53 if (i != 0)
54 str += ",";
55 str += hashes[i].ToString();
57 return str;
60 std::string HashHost(const std::string& canonicalized_host) {
61 char hashed[crypto::kSHA256Length];
62 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
63 return std::string(hashed, sizeof(hashed));
66 // Returns true if the intersection of |a| and |b| is not empty. If either
67 // |a| or |b| is empty, returns false.
68 bool HashesIntersect(const HashValueVector& a,
69 const HashValueVector& b) {
70 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
71 HashValueVector::const_iterator j =
72 std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
73 if (j != b.end())
74 return true;
76 return false;
79 bool AddHash(const char* sha1_hash,
80 HashValueVector* out) {
81 HashValue hash(HASH_VALUE_SHA1);
82 memcpy(hash.data(), sha1_hash, hash.size());
83 out->push_back(hash);
84 return true;
87 // Converts |hostname| from dotted form ("www.google.com") to the form
88 // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns
89 // the result.
90 std::string CanonicalizeHost(const std::string& host) {
91 // We cannot perform the operations as detailed in the spec here as |host|
92 // has already undergone IDN processing before it reached us. Thus, we check
93 // that there are no invalid characters in the host and lowercase the result.
94 std::string new_host;
95 if (!DNSDomainFromDot(host, &new_host)) {
96 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
97 // name is >255 bytes. However, search terms can have those properties.
98 return std::string();
101 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
102 const unsigned label_length = static_cast<unsigned>(new_host[i]);
103 if (!label_length)
104 break;
106 for (size_t j = 0; j < label_length; ++j) {
107 new_host[i + 1 + j] = static_cast<char>(tolower(new_host[i + 1 + j]));
111 return new_host;
114 // BitReader is a class that allows a bytestring to be read bit-by-bit.
115 class BitReader {
116 public:
117 BitReader(const uint8* bytes, size_t num_bits)
118 : bytes_(bytes),
119 num_bits_(num_bits),
120 num_bytes_((num_bits + 7) / 8),
121 current_byte_index_(0),
122 num_bits_used_(8) {}
124 // Next sets |*out| to the next bit from the input. It returns false if no
125 // more bits are available or true otherwise.
126 bool Next(bool* out) {
127 if (num_bits_used_ == 8) {
128 if (current_byte_index_ >= num_bytes_) {
129 return false;
131 current_byte_ = bytes_[current_byte_index_++];
132 num_bits_used_ = 0;
135 *out = 1 & (current_byte_ >> (7 - num_bits_used_));
136 num_bits_used_++;
137 return true;
140 // Read sets the |num_bits| least-significant bits of |*out| to the value of
141 // the next |num_bits| bits from the input. It returns false if there are
142 // insufficient bits in the input or true otherwise.
143 bool Read(unsigned num_bits, uint32* out) {
144 DCHECK_LE(num_bits, 32u);
146 uint32 ret = 0;
147 for (unsigned i = 0; i < num_bits; ++i) {
148 bool bit;
149 if (!Next(&bit)) {
150 return false;
152 ret |= static_cast<uint32>(bit) << (num_bits - 1 - i);
155 *out = ret;
156 return true;
159 // Unary sets |*out| to the result of decoding a unary value from the input.
160 // It returns false if there were insufficient bits in the input and true
161 // otherwise.
162 bool Unary(size_t* out) {
163 size_t ret = 0;
165 for (;;) {
166 bool bit;
167 if (!Next(&bit)) {
168 return false;
170 if (!bit) {
171 break;
173 ret++;
176 *out = ret;
177 return true;
180 // Seek sets the current offest in the input to bit number |offset|. It
181 // returns true if |offset| is within the range of the input and false
182 // otherwise.
183 bool Seek(size_t offset) {
184 if (offset >= num_bits_) {
185 return false;
187 current_byte_index_ = offset / 8;
188 current_byte_ = bytes_[current_byte_index_++];
189 num_bits_used_ = offset % 8;
190 return true;
193 private:
194 const uint8* const bytes_;
195 const size_t num_bits_;
196 const size_t num_bytes_;
197 // current_byte_index_ contains the current byte offset in |bytes_|.
198 size_t current_byte_index_;
199 // current_byte_ contains the current byte of the input.
200 uint8 current_byte_;
201 // num_bits_used_ contains the number of bits of |current_byte_| that have
202 // been read.
203 unsigned num_bits_used_;
206 // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
207 // simply encoded as a series of two-byte structures. The first byte determines
208 // the "0" pointer for that node and the second the "1" pointer. Each byte
209 // either has the MSB set, in which case the bottom 7 bits are the value for
210 // that position, or else the bottom seven bits contain the index of a node.
212 // The tree is decoded by walking rather than a table-driven approach.
213 class HuffmanDecoder {
214 public:
215 HuffmanDecoder(const uint8* tree, size_t tree_bytes)
216 : tree_(tree), tree_bytes_(tree_bytes) {}
218 bool Decode(BitReader* reader, char* out) {
219 const uint8* current = &tree_[tree_bytes_ - 2];
221 for (;;) {
222 bool bit;
223 if (!reader->Next(&bit)) {
224 return false;
227 uint8 b = current[bit];
228 if (b & 0x80) {
229 *out = static_cast<char>(b & 0x7f);
230 return true;
233 unsigned offset = static_cast<unsigned>(b) * 2;
234 DCHECK_LT(offset, tree_bytes_);
235 if (offset >= tree_bytes_) {
236 return false;
239 current = &tree_[offset];
243 private:
244 const uint8* const tree_;
245 const size_t tree_bytes_;
248 // PreloadResult is the result of resolving a specific name in the preloaded
249 // data.
250 struct PreloadResult {
251 uint32 pinset_id;
252 uint32 domain_id;
253 // hostname_offset contains the number of bytes from the start of the given
254 // hostname where the name of the matching entry starts.
255 size_t hostname_offset;
256 bool sts_include_subdomains;
257 bool pkp_include_subdomains;
258 bool force_https;
259 bool has_pins;
262 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns
263 // false on internal error and true otherwise. After a successful return,
264 // |*out_found| is true iff a relevant entry has been found. If so, |*out|
265 // contains the details.
267 // Don't call this function, call DecodeHSTSPreload, below.
269 // Although this code should be robust, it never processes attacker-controlled
270 // data -- it only operates on the preloaded data built into the binary.
272 // The preloaded data is represented as a trie and matches the hostname
273 // backwards. Each node in the trie starts with a number of characters, which
274 // must match exactly. After that is a dispatch table which maps the next
275 // character in the hostname to another node in the trie.
277 // In the dispatch table, the zero character represents the "end of string"
278 // (which is the *beginning* of a hostname since we process it backwards). The
279 // value in that case is special -- rather than an offset to another trie node,
280 // it contains the HSTS information: whether subdomains are included, pinsets
281 // etc. If an "end of string" matches a period in the hostname then the
282 // information is remembered because, if no more specific node is found, then
283 // that information applies to the hostname.
285 // Dispatch tables are always given in order, but the "end of string" (zero)
286 // value always comes before an entry for '.'.
287 bool DecodeHSTSPreloadRaw(const std::string& search_hostname,
288 bool* out_found,
289 PreloadResult* out) {
290 HuffmanDecoder huffman(kHSTSHuffmanTree, sizeof(kHSTSHuffmanTree));
291 BitReader reader(kPreloadedHSTSData, kPreloadedHSTSBits);
292 size_t bit_offset = kHSTSRootPosition;
293 static const char kEndOfString = 0;
294 static const char kEndOfTable = 127;
296 *out_found = false;
298 // Ensure that |search_hostname| is a valid hostname before
299 // processing.
300 if (CanonicalizeHost(search_hostname).empty()) {
301 return true;
304 // Normalize any trailing '.' used for DNS suffix searches.
305 std::string hostname = search_hostname;
306 size_t found = hostname.find_last_not_of('.');
307 if (found != std::string::npos) {
308 hostname.erase(found + 1);
309 } else {
310 hostname.clear();
313 // |hostname| has already undergone IDN conversion, so should be
314 // entirely A-Labels. The preload data is entirely normalized to
315 // lower case.
316 base::StringToLowerASCII(&hostname);
318 if (hostname.empty()) {
319 return true;
322 // hostname_offset contains one more than the index of the current character
323 // in the hostname that is being considered. It's one greater so that we can
324 // represent the position just before the beginning (with zero).
325 size_t hostname_offset = hostname.size();
327 for (;;) {
328 // Seek to the desired location.
329 if (!reader.Seek(bit_offset)) {
330 return false;
333 // Decode the unary length of the common prefix.
334 size_t prefix_length;
335 if (!reader.Unary(&prefix_length)) {
336 return false;
339 // Match each character in the prefix.
340 for (size_t i = 0; i < prefix_length; ++i) {
341 if (hostname_offset == 0) {
342 // We can't match the terminator with a prefix string.
343 return true;
346 char c;
347 if (!huffman.Decode(&reader, &c)) {
348 return false;
350 if (hostname[hostname_offset - 1] != c) {
351 return true;
353 hostname_offset--;
356 bool is_first_offset = true;
357 size_t current_offset = 0;
359 // Next is the dispatch table.
360 for (;;) {
361 char c;
362 if (!huffman.Decode(&reader, &c)) {
363 return false;
365 if (c == kEndOfTable) {
366 // No exact match.
367 return true;
370 if (c == kEndOfString) {
371 PreloadResult tmp;
372 if (!reader.Next(&tmp.sts_include_subdomains) ||
373 !reader.Next(&tmp.force_https) || !reader.Next(&tmp.has_pins)) {
374 return false;
377 tmp.pkp_include_subdomains = tmp.sts_include_subdomains;
379 if (tmp.has_pins) {
380 if (!reader.Read(4, &tmp.pinset_id) ||
381 !reader.Read(9, &tmp.domain_id) ||
382 (!tmp.sts_include_subdomains &&
383 !reader.Next(&tmp.pkp_include_subdomains))) {
384 return false;
388 tmp.hostname_offset = hostname_offset;
390 if (hostname_offset == 0 || hostname[hostname_offset - 1] == '.') {
391 *out_found = tmp.sts_include_subdomains || tmp.pkp_include_subdomains;
392 *out = tmp;
394 if (hostname_offset > 0) {
395 out->force_https &= tmp.sts_include_subdomains;
396 } else {
397 *out_found = true;
398 return true;
402 continue;
405 // The entries in a dispatch table are in order thus we can tell if there
406 // will be no match if the current character past the one that we want.
407 if (hostname_offset == 0 || hostname[hostname_offset - 1] < c) {
408 return true;
411 if (is_first_offset) {
412 // The first offset is backwards from the current position.
413 uint32 jump_delta_bits;
414 uint32 jump_delta;
415 if (!reader.Read(5, &jump_delta_bits) ||
416 !reader.Read(jump_delta_bits, &jump_delta)) {
417 return false;
420 if (bit_offset < jump_delta) {
421 return false;
424 current_offset = bit_offset - jump_delta;
425 is_first_offset = false;
426 } else {
427 // Subsequent offsets are forward from the target of the first offset.
428 uint32 is_long_jump;
429 if (!reader.Read(1, &is_long_jump)) {
430 return false;
433 uint32 jump_delta;
434 if (!is_long_jump) {
435 if (!reader.Read(7, &jump_delta)) {
436 return false;
438 } else {
439 uint32 jump_delta_bits;
440 if (!reader.Read(4, &jump_delta_bits) ||
441 !reader.Read(jump_delta_bits + 8, &jump_delta)) {
442 return false;
446 current_offset += jump_delta;
447 if (current_offset >= bit_offset) {
448 return false;
452 DCHECK_LT(0u, hostname_offset);
453 if (hostname[hostname_offset - 1] == c) {
454 bit_offset = current_offset;
455 hostname_offset--;
456 break;
462 bool DecodeHSTSPreload(const std::string& hostname, PreloadResult* out) {
463 bool found;
464 if (!DecodeHSTSPreloadRaw(hostname, &found, out)) {
465 DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
466 << hostname;
467 return false;
470 return found;
473 } // namespace
475 TransportSecurityState::TransportSecurityState()
476 : delegate_(NULL), enable_static_pins_(true) {
477 // Static pinning is only enabled for official builds to make sure that
478 // others don't end up with pins that cannot be easily updated.
479 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
480 enable_static_pins_ = false;
481 #endif
482 DCHECK(CalledOnValidThread());
485 // Both HSTS and HPKP cause fatal SSL errors, so return true if a
486 // host has either.
487 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host) {
488 STSState sts_state;
489 PKPState pkp_state;
490 if (GetStaticDomainState(host, &sts_state, &pkp_state))
491 return true;
492 if (GetDynamicSTSState(host, &sts_state))
493 return true;
494 return GetDynamicPKPState(host, &pkp_state);
497 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host) {
498 STSState dynamic_sts_state;
499 if (GetDynamicSTSState(host, &dynamic_sts_state))
500 return dynamic_sts_state.ShouldUpgradeToSSL();
502 STSState static_sts_state;
503 PKPState unused;
504 if (GetStaticDomainState(host, &static_sts_state, &unused) &&
505 static_sts_state.ShouldUpgradeToSSL()) {
506 return true;
509 return false;
512 bool TransportSecurityState::CheckPublicKeyPins(
513 const std::string& host,
514 bool is_issued_by_known_root,
515 const HashValueVector& public_key_hashes,
516 std::string* pinning_failure_log) {
517 // Perform pin validation if, and only if, all these conditions obtain:
519 // * the server's certificate chain chains up to a known root (i.e. not a
520 // user-installed trust anchor); and
521 // * the server actually has public key pins.
522 if (!is_issued_by_known_root || !HasPublicKeyPins(host)) {
523 return true;
526 bool pins_are_valid =
527 CheckPublicKeyPinsImpl(host, public_key_hashes, pinning_failure_log);
528 if (!pins_are_valid) {
529 LOG(ERROR) << *pinning_failure_log;
530 ReportUMAOnPinFailure(host);
533 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
534 return pins_are_valid;
537 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
538 PKPState dynamic_state;
539 if (GetDynamicPKPState(host, &dynamic_state))
540 return dynamic_state.HasPublicKeyPins();
542 STSState unused;
543 PKPState static_pkp_state;
544 if (GetStaticDomainState(host, &unused, &static_pkp_state)) {
545 if (static_pkp_state.HasPublicKeyPins())
546 return true;
549 return false;
552 void TransportSecurityState::SetDelegate(
553 TransportSecurityState::Delegate* delegate) {
554 DCHECK(CalledOnValidThread());
555 delegate_ = delegate;
558 void TransportSecurityState::AddHSTSInternal(
559 const std::string& host,
560 TransportSecurityState::STSState::UpgradeMode upgrade_mode,
561 const base::Time& expiry,
562 bool include_subdomains) {
563 DCHECK(CalledOnValidThread());
565 STSState sts_state;
566 sts_state.last_observed = base::Time::Now();
567 sts_state.include_subdomains = include_subdomains;
568 sts_state.expiry = expiry;
569 sts_state.upgrade_mode = upgrade_mode;
571 EnableSTSHost(host, sts_state);
574 void TransportSecurityState::AddHPKPInternal(const std::string& host,
575 const base::Time& last_observed,
576 const base::Time& expiry,
577 bool include_subdomains,
578 const HashValueVector& hashes,
579 const GURL& report_uri) {
580 DCHECK(CalledOnValidThread());
582 PKPState pkp_state;
583 pkp_state.last_observed = last_observed;
584 pkp_state.expiry = expiry;
585 pkp_state.include_subdomains = include_subdomains;
586 pkp_state.spki_hashes = hashes;
587 pkp_state.report_uri = report_uri;
589 EnablePKPHost(host, pkp_state);
592 void TransportSecurityState::EnableSTSHost(const std::string& host,
593 const STSState& state) {
594 DCHECK(CalledOnValidThread());
596 const std::string canonicalized_host = CanonicalizeHost(host);
597 if (canonicalized_host.empty())
598 return;
600 // Only store new state when HSTS is explicitly enabled. If it is
601 // disabled, remove the state from the enabled hosts.
602 if (state.ShouldUpgradeToSSL()) {
603 STSState sts_state(state);
604 // No need to store this value since it is redundant. (|canonicalized_host|
605 // is the map key.)
606 sts_state.domain.clear();
608 enabled_sts_hosts_[HashHost(canonicalized_host)] = sts_state;
609 } else {
610 const std::string hashed_host = HashHost(canonicalized_host);
611 enabled_sts_hosts_.erase(hashed_host);
614 DirtyNotify();
617 void TransportSecurityState::EnablePKPHost(const std::string& host,
618 const PKPState& state) {
619 DCHECK(CalledOnValidThread());
621 const std::string canonicalized_host = CanonicalizeHost(host);
622 if (canonicalized_host.empty())
623 return;
625 // Only store new state when HPKP is explicitly enabled. If it is
626 // disabled, remove the state from the enabled hosts.
627 if (state.HasPublicKeyPins()) {
628 PKPState pkp_state(state);
629 // No need to store this value since it is redundant. (|canonicalized_host|
630 // is the map key.)
631 pkp_state.domain.clear();
633 enabled_pkp_hosts_[HashHost(canonicalized_host)] = pkp_state;
634 } else {
635 const std::string hashed_host = HashHost(canonicalized_host);
636 enabled_pkp_hosts_.erase(hashed_host);
639 DirtyNotify();
642 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
643 DCHECK(CalledOnValidThread());
645 const std::string canonicalized_host = CanonicalizeHost(host);
646 if (canonicalized_host.empty())
647 return false;
649 const std::string hashed_host = HashHost(canonicalized_host);
650 bool deleted = false;
651 STSStateMap::iterator sts_interator = enabled_sts_hosts_.find(hashed_host);
652 if (sts_interator != enabled_sts_hosts_.end()) {
653 enabled_sts_hosts_.erase(sts_interator);
654 deleted = true;
657 PKPStateMap::iterator pkp_iterator = enabled_pkp_hosts_.find(hashed_host);
658 if (pkp_iterator != enabled_pkp_hosts_.end()) {
659 enabled_pkp_hosts_.erase(pkp_iterator);
660 deleted = true;
663 if (deleted)
664 DirtyNotify();
665 return deleted;
668 void TransportSecurityState::ClearDynamicData() {
669 DCHECK(CalledOnValidThread());
670 enabled_sts_hosts_.clear();
671 enabled_pkp_hosts_.clear();
674 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
675 DCHECK(CalledOnValidThread());
677 bool dirtied = false;
678 STSStateMap::iterator sts_iterator = enabled_sts_hosts_.begin();
679 while (sts_iterator != enabled_sts_hosts_.end()) {
680 if (sts_iterator->second.last_observed >= time) {
681 dirtied = true;
682 enabled_sts_hosts_.erase(sts_iterator++);
683 continue;
686 ++sts_iterator;
689 PKPStateMap::iterator pkp_iterator = enabled_pkp_hosts_.begin();
690 while (pkp_iterator != enabled_pkp_hosts_.end()) {
691 if (pkp_iterator->second.last_observed >= time) {
692 dirtied = true;
693 enabled_pkp_hosts_.erase(pkp_iterator++);
694 continue;
697 ++pkp_iterator;
700 if (dirtied)
701 DirtyNotify();
704 TransportSecurityState::~TransportSecurityState() {
705 DCHECK(CalledOnValidThread());
708 void TransportSecurityState::DirtyNotify() {
709 DCHECK(CalledOnValidThread());
711 if (delegate_)
712 delegate_->StateIsDirty(this);
715 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
716 const std::string& value) {
717 DCHECK(CalledOnValidThread());
719 base::Time now = base::Time::Now();
720 base::TimeDelta max_age;
721 bool include_subdomains;
722 if (!ParseHSTSHeader(value, &max_age, &include_subdomains)) {
723 return false;
726 // Handle max-age == 0.
727 STSState::UpgradeMode upgrade_mode;
728 if (max_age.InSeconds() == 0) {
729 upgrade_mode = STSState::MODE_DEFAULT;
730 } else {
731 upgrade_mode = STSState::MODE_FORCE_HTTPS;
734 AddHSTSInternal(host, upgrade_mode, now + max_age, include_subdomains);
735 return true;
738 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
739 const std::string& value,
740 const SSLInfo& ssl_info) {
741 DCHECK(CalledOnValidThread());
743 base::Time now = base::Time::Now();
744 base::TimeDelta max_age;
745 bool include_subdomains;
746 HashValueVector spki_hashes;
747 GURL report_uri;
749 if (!ParseHPKPHeader(value, ssl_info.public_key_hashes, &max_age,
750 &include_subdomains, &spki_hashes, &report_uri)) {
751 return false;
753 // Handle max-age == 0.
754 if (max_age.InSeconds() == 0)
755 spki_hashes.clear();
756 AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes,
757 report_uri);
758 return true;
761 void TransportSecurityState::AddHSTS(const std::string& host,
762 const base::Time& expiry,
763 bool include_subdomains) {
764 DCHECK(CalledOnValidThread());
765 AddHSTSInternal(host, STSState::MODE_FORCE_HTTPS, expiry, include_subdomains);
768 void TransportSecurityState::AddHPKP(const std::string& host,
769 const base::Time& expiry,
770 bool include_subdomains,
771 const HashValueVector& hashes,
772 const GURL& report_uri) {
773 DCHECK(CalledOnValidThread());
774 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes,
775 report_uri);
778 // static
779 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) {
780 PreloadResult result;
781 return DecodeHSTSPreload(host, &result) && result.has_pins &&
782 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts;
785 // static
786 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
787 PreloadResult result;
788 if (!DecodeHSTSPreload(host, &result) ||
789 !result.has_pins) {
790 return;
793 DCHECK(result.domain_id != DOMAIN_NOT_PINNED);
795 UMA_HISTOGRAM_SPARSE_SLOWLY(
796 "Net.PublicKeyPinFailureDomain", result.domain_id);
799 // static
800 bool TransportSecurityState::IsBuildTimely() {
801 // If the build metadata aren't embedded in the binary then we can't use the
802 // build time to determine if the build is timely, return true by default. If
803 // we're building an official build then keep using the build time, even if
804 // it's invalid it'd be a date in the past and this function will return
805 // false.
806 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
807 return true;
808 #else
809 const base::Time build_time = base::GetBuildTime();
810 // We consider built-in information to be timely for 10 weeks.
811 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
812 #endif
815 bool TransportSecurityState::CheckPublicKeyPinsImpl(
816 const std::string& host,
817 const HashValueVector& hashes,
818 std::string* failure_log) {
819 PKPState dynamic_state;
820 if (GetDynamicPKPState(host, &dynamic_state))
821 return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
823 PKPState static_pkp_state;
824 STSState unused;
825 if (GetStaticDomainState(host, &unused, &static_pkp_state))
826 return static_pkp_state.CheckPublicKeyPins(hashes, failure_log);
828 // HasPublicKeyPins should have returned true in order for this method
829 // to have been called, so if we fall through to here, it's an error.
830 return false;
833 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
834 STSState* sts_state,
835 PKPState* pkp_state) const {
836 DCHECK(CalledOnValidThread());
838 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
839 sts_state->include_subdomains = false;
840 pkp_state->include_subdomains = false;
842 if (!IsBuildTimely())
843 return false;
845 PreloadResult result;
846 if (!DecodeHSTSPreload(host, &result))
847 return false;
849 sts_state->domain = host.substr(result.hostname_offset);
850 pkp_state->domain = sts_state->domain;
851 sts_state->include_subdomains = result.sts_include_subdomains;
852 sts_state->last_observed = base::GetBuildTime();
853 sts_state->upgrade_mode = STSState::MODE_DEFAULT;
854 if (result.force_https) {
855 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
858 if (enable_static_pins_ && result.has_pins) {
859 pkp_state->include_subdomains = result.pkp_include_subdomains;
860 pkp_state->last_observed = base::GetBuildTime();
862 if (result.pinset_id >= arraysize(kPinsets))
863 return false;
864 const Pinset *pinset = &kPinsets[result.pinset_id];
866 if (pinset->accepted_pins) {
867 const char* const* sha1_hash = pinset->accepted_pins;
868 while (*sha1_hash) {
869 AddHash(*sha1_hash, &pkp_state->spki_hashes);
870 sha1_hash++;
873 if (pinset->rejected_pins) {
874 const char* const* sha1_hash = pinset->rejected_pins;
875 while (*sha1_hash) {
876 AddHash(*sha1_hash, &pkp_state->bad_spki_hashes);
877 sha1_hash++;
882 return true;
885 bool TransportSecurityState::GetDynamicSTSState(const std::string& host,
886 STSState* result) {
887 DCHECK(CalledOnValidThread());
889 const std::string canonicalized_host = CanonicalizeHost(host);
890 if (canonicalized_host.empty())
891 return false;
893 base::Time current_time(base::Time::Now());
895 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
896 std::string host_sub_chunk(&canonicalized_host[i],
897 canonicalized_host.size() - i);
898 STSStateMap::iterator j = enabled_sts_hosts_.find(HashHost(host_sub_chunk));
899 if (j == enabled_sts_hosts_.end())
900 continue;
902 // If the entry is invalid, drop it.
903 if (current_time > j->second.expiry) {
904 enabled_sts_hosts_.erase(j);
905 DirtyNotify();
906 continue;
909 // If this is the most specific STS match, add it to the result. Note: a STS
910 // entry at a more specific domain overrides a less specific domain whether
911 // or not |include_subdomains| is set.
912 if (current_time <= j->second.expiry) {
913 if (i == 0 || j->second.include_subdomains) {
914 *result = j->second;
915 result->domain = DNSDomainToString(host_sub_chunk);
916 return true;
919 break;
923 return false;
926 bool TransportSecurityState::GetDynamicPKPState(const std::string& host,
927 PKPState* result) {
928 DCHECK(CalledOnValidThread());
930 const std::string canonicalized_host = CanonicalizeHost(host);
931 if (canonicalized_host.empty())
932 return false;
934 base::Time current_time(base::Time::Now());
936 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
937 std::string host_sub_chunk(&canonicalized_host[i],
938 canonicalized_host.size() - i);
939 PKPStateMap::iterator j = enabled_pkp_hosts_.find(HashHost(host_sub_chunk));
940 if (j == enabled_pkp_hosts_.end())
941 continue;
943 // If the entry is invalid, drop it.
944 if (current_time > j->second.expiry) {
945 enabled_pkp_hosts_.erase(j);
946 DirtyNotify();
947 continue;
950 // If this is the most specific PKP match, add it to the result. Note: a PKP
951 // entry at a more specific domain overrides a less specific domain whether
952 // or not |include_subdomains| is set.
953 if (current_time <= j->second.expiry) {
954 if (i == 0 || j->second.include_subdomains) {
955 *result = j->second;
956 result->domain = DNSDomainToString(host_sub_chunk);
957 return true;
960 break;
964 return false;
967 void TransportSecurityState::AddOrUpdateEnabledSTSHosts(
968 const std::string& hashed_host,
969 const STSState& state) {
970 DCHECK(CalledOnValidThread());
971 DCHECK(state.ShouldUpgradeToSSL());
972 enabled_sts_hosts_[hashed_host] = state;
975 void TransportSecurityState::AddOrUpdateEnabledPKPHosts(
976 const std::string& hashed_host,
977 const PKPState& state) {
978 DCHECK(CalledOnValidThread());
979 DCHECK(state.HasPublicKeyPins());
980 enabled_pkp_hosts_[hashed_host] = state;
983 TransportSecurityState::STSState::STSState()
984 : upgrade_mode(MODE_DEFAULT), include_subdomains(false) {
987 TransportSecurityState::STSState::~STSState() {
990 bool TransportSecurityState::STSState::ShouldUpgradeToSSL() const {
991 return upgrade_mode == MODE_FORCE_HTTPS;
994 bool TransportSecurityState::STSState::ShouldSSLErrorsBeFatal() const {
995 return true;
998 TransportSecurityState::STSStateIterator::STSStateIterator(
999 const TransportSecurityState& state)
1000 : iterator_(state.enabled_sts_hosts_.begin()),
1001 end_(state.enabled_sts_hosts_.end()) {
1004 TransportSecurityState::STSStateIterator::~STSStateIterator() {
1007 TransportSecurityState::PKPState::PKPState() : include_subdomains(false) {
1010 TransportSecurityState::PKPState::~PKPState() {
1013 bool TransportSecurityState::PKPState::CheckPublicKeyPins(
1014 const HashValueVector& hashes,
1015 std::string* failure_log) const {
1016 // Validate that hashes is not empty. By the time this code is called (in
1017 // production), that should never happen, but it's good to be defensive.
1018 // And, hashes *can* be empty in some test scenarios.
1019 if (hashes.empty()) {
1020 failure_log->append(
1021 "Rejecting empty public key chain for public-key-pinned domains: " +
1022 domain);
1023 return false;
1026 if (HashesIntersect(bad_spki_hashes, hashes)) {
1027 failure_log->append("Rejecting public key chain for domain " + domain +
1028 ". Validated chain: " + HashesToBase64String(hashes) +
1029 ", matches one or more bad hashes: " +
1030 HashesToBase64String(bad_spki_hashes));
1031 return false;
1034 // If there are no pins, then any valid chain is acceptable.
1035 if (spki_hashes.empty())
1036 return true;
1038 if (HashesIntersect(spki_hashes, hashes)) {
1039 return true;
1042 failure_log->append("Rejecting public key chain for domain " + domain +
1043 ". Validated chain: " + HashesToBase64String(hashes) +
1044 ", expected: " + HashesToBase64String(spki_hashes));
1045 return false;
1048 bool TransportSecurityState::PKPState::HasPublicKeyPins() const {
1049 return spki_hashes.size() > 0 || bad_spki_hashes.size() > 0;
1052 bool TransportSecurityState::PKPState::ShouldSSLErrorsBeFatal() const {
1053 return true;
1056 TransportSecurityState::PKPStateIterator::PKPStateIterator(
1057 const TransportSecurityState& state)
1058 : iterator_(state.enabled_pkp_hosts_.begin()),
1059 end_(state.enabled_pkp_hosts_.end()) {
1062 TransportSecurityState::PKPStateIterator::~PKPStateIterator() {
1065 } // namespace