Update V8 to version 4.7.47.
[chromium-blink-merge.git] / net / http / transport_security_state.cc
blob53dc43c3444c39365d9a123eb8aa35f965fa42bc
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/json/json_writer.h"
23 #include "base/logging.h"
24 #include "base/memory/scoped_ptr.h"
25 #include "base/metrics/histogram_macros.h"
26 #include "base/metrics/sparse_histogram.h"
27 #include "base/sha1.h"
28 #include "base/strings/string_number_conversions.h"
29 #include "base/strings/string_util.h"
30 #include "base/strings/stringprintf.h"
31 #include "base/strings/utf_string_conversions.h"
32 #include "base/time/time.h"
33 #include "base/values.h"
34 #include "crypto/sha2.h"
35 #include "net/base/dns_util.h"
36 #include "net/base/host_port_pair.h"
37 #include "net/cert/x509_cert_types.h"
38 #include "net/cert/x509_certificate.h"
39 #include "net/http/http_security_headers.h"
40 #include "net/ssl/ssl_info.h"
41 #include "url/gurl.h"
43 #if defined(USE_OPENSSL)
44 #include "crypto/openssl_util.h"
45 #endif
47 namespace net {
49 namespace {
51 #include "net/http/transport_security_state_static.h"
53 std::string TimeToISO8601(const base::Time& t) {
54 base::Time::Exploded exploded;
55 t.UTCExplode(&exploded);
56 return base::StringPrintf(
57 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month,
58 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
59 exploded.millisecond);
62 scoped_ptr<base::ListValue> GetPEMEncodedChainAsList(
63 const net::X509Certificate* cert_chain) {
64 if (!cert_chain)
65 return make_scoped_ptr(new base::ListValue());
67 scoped_ptr<base::ListValue> result(new base::ListValue());
68 std::vector<std::string> pem_encoded_chain;
69 cert_chain->GetPEMEncodedChain(&pem_encoded_chain);
70 for (const std::string& cert : pem_encoded_chain)
71 result->Append(make_scoped_ptr(new base::StringValue(cert)));
73 return result.Pass();
76 bool GetHPKPReport(const HostPortPair& host_port_pair,
77 const TransportSecurityState::PKPState& pkp_state,
78 const X509Certificate* served_certificate_chain,
79 const X509Certificate* validated_certificate_chain,
80 std::string* serialized_report) {
81 // TODO(estark): keep track of reports already sent and rate-limit,
82 // break loops
83 if (pkp_state.report_uri.is_empty())
84 return false;
86 base::DictionaryValue report;
87 base::Time now = base::Time::Now();
88 report.SetString("date-time", TimeToISO8601(now));
89 report.SetString("hostname", host_port_pair.host());
90 report.SetInteger("port", host_port_pair.port());
91 report.SetString("effective-expiration-date",
92 TimeToISO8601(pkp_state.expiry));
93 report.SetBoolean("include-subdomains", pkp_state.include_subdomains);
94 report.SetString("noted-hostname", pkp_state.domain);
96 scoped_ptr<base::ListValue> served_certificate_chain_list =
97 GetPEMEncodedChainAsList(served_certificate_chain);
98 scoped_ptr<base::ListValue> validated_certificate_chain_list =
99 GetPEMEncodedChainAsList(validated_certificate_chain);
100 report.Set("served-certificate-chain", served_certificate_chain_list.Pass());
101 report.Set("validated-certificate-chain",
102 validated_certificate_chain_list.Pass());
104 scoped_ptr<base::ListValue> known_pin_list(new base::ListValue());
105 for (const auto& hash_value : pkp_state.spki_hashes) {
106 std::string known_pin;
108 switch (hash_value.tag) {
109 case HASH_VALUE_SHA1:
110 known_pin += "pin-sha1=";
111 break;
112 case HASH_VALUE_SHA256:
113 known_pin += "pin-sha256=";
114 break;
117 std::string base64_value;
118 base::Base64Encode(
119 base::StringPiece(reinterpret_cast<const char*>(hash_value.data()),
120 hash_value.size()),
121 &base64_value);
122 known_pin += "\"" + base64_value + "\"";
124 known_pin_list->Append(
125 scoped_ptr<base::Value>(new base::StringValue(known_pin)));
128 report.Set("known-pins", known_pin_list.Pass());
130 if (!base::JSONWriter::Write(report, serialized_report)) {
131 LOG(ERROR) << "Failed to serialize HPKP violation report.";
132 return false;
135 return true;
138 // Do not send a report over HTTPS to the same host that set the
139 // pin. Such report URIs will result in loops. (A.com has a pinning
140 // violation which results in a report being sent to A.com, which
141 // results in a pinning violation which results in a report being sent
142 // to A.com, etc.)
143 bool IsReportUriValidForHost(const GURL& report_uri, const std::string& host) {
144 return (report_uri.host() != host || !report_uri.SchemeIsCryptographic());
147 bool CheckPinsAndMaybeSendReport(
148 const HostPortPair& host_port_pair,
149 const TransportSecurityState::PKPState& pkp_state,
150 const HashValueVector& hashes,
151 const X509Certificate* served_certificate_chain,
152 const X509Certificate* validated_certificate_chain,
153 const TransportSecurityState::PublicKeyPinReportStatus report_status,
154 TransportSecurityState::ReportSender* report_sender,
155 std::string* failure_log) {
156 if (pkp_state.CheckPublicKeyPins(hashes, failure_log))
157 return true;
159 if (!report_sender ||
160 report_status != TransportSecurityState::ENABLE_PIN_REPORTS ||
161 pkp_state.report_uri.is_empty()) {
162 return false;
165 DCHECK(pkp_state.report_uri.is_valid());
166 // Report URIs should not be used if they are the same host as the pin
167 // and are HTTPS, to avoid going into a report-sending loop.
168 if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host()))
169 return false;
171 std::string serialized_report;
173 if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain,
174 validated_certificate_chain, &serialized_report)) {
175 return false;
178 report_sender->Send(pkp_state.report_uri, serialized_report);
180 return false;
183 std::string HashesToBase64String(const HashValueVector& hashes) {
184 std::string str;
185 for (size_t i = 0; i != hashes.size(); ++i) {
186 if (i != 0)
187 str += ",";
188 str += hashes[i].ToString();
190 return str;
193 std::string HashHost(const std::string& canonicalized_host) {
194 char hashed[crypto::kSHA256Length];
195 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
196 return std::string(hashed, sizeof(hashed));
199 // Returns true if the intersection of |a| and |b| is not empty. If either
200 // |a| or |b| is empty, returns false.
201 bool HashesIntersect(const HashValueVector& a,
202 const HashValueVector& b) {
203 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
204 HashValueVector::const_iterator j =
205 std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
206 if (j != b.end())
207 return true;
209 return false;
212 bool AddHash(const char* sha1_hash,
213 HashValueVector* out) {
214 HashValue hash(HASH_VALUE_SHA1);
215 memcpy(hash.data(), sha1_hash, hash.size());
216 out->push_back(hash);
217 return true;
220 // Converts |hostname| from dotted form ("www.google.com") to the form
221 // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns
222 // the result.
223 std::string CanonicalizeHost(const std::string& host) {
224 // We cannot perform the operations as detailed in the spec here as |host|
225 // has already undergone IDN processing before it reached us. Thus, we check
226 // that there are no invalid characters in the host and lowercase the result.
227 std::string new_host;
228 if (!DNSDomainFromDot(host, &new_host)) {
229 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
230 // name is >255 bytes. However, search terms can have those properties.
231 return std::string();
234 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
235 const unsigned label_length = static_cast<unsigned>(new_host[i]);
236 if (!label_length)
237 break;
239 for (size_t j = 0; j < label_length; ++j) {
240 new_host[i + 1 + j] = static_cast<char>(tolower(new_host[i + 1 + j]));
244 return new_host;
247 // BitReader is a class that allows a bytestring to be read bit-by-bit.
248 class BitReader {
249 public:
250 BitReader(const uint8* bytes, size_t num_bits)
251 : bytes_(bytes),
252 num_bits_(num_bits),
253 num_bytes_((num_bits + 7) / 8),
254 current_byte_index_(0),
255 num_bits_used_(8) {}
257 // Next sets |*out| to the next bit from the input. It returns false if no
258 // more bits are available or true otherwise.
259 bool Next(bool* out) {
260 if (num_bits_used_ == 8) {
261 if (current_byte_index_ >= num_bytes_) {
262 return false;
264 current_byte_ = bytes_[current_byte_index_++];
265 num_bits_used_ = 0;
268 *out = 1 & (current_byte_ >> (7 - num_bits_used_));
269 num_bits_used_++;
270 return true;
273 // Read sets the |num_bits| least-significant bits of |*out| to the value of
274 // the next |num_bits| bits from the input. It returns false if there are
275 // insufficient bits in the input or true otherwise.
276 bool Read(unsigned num_bits, uint32* out) {
277 DCHECK_LE(num_bits, 32u);
279 uint32 ret = 0;
280 for (unsigned i = 0; i < num_bits; ++i) {
281 bool bit;
282 if (!Next(&bit)) {
283 return false;
285 ret |= static_cast<uint32>(bit) << (num_bits - 1 - i);
288 *out = ret;
289 return true;
292 // Unary sets |*out| to the result of decoding a unary value from the input.
293 // It returns false if there were insufficient bits in the input and true
294 // otherwise.
295 bool Unary(size_t* out) {
296 size_t ret = 0;
298 for (;;) {
299 bool bit;
300 if (!Next(&bit)) {
301 return false;
303 if (!bit) {
304 break;
306 ret++;
309 *out = ret;
310 return true;
313 // Seek sets the current offest in the input to bit number |offset|. It
314 // returns true if |offset| is within the range of the input and false
315 // otherwise.
316 bool Seek(size_t offset) {
317 if (offset >= num_bits_) {
318 return false;
320 current_byte_index_ = offset / 8;
321 current_byte_ = bytes_[current_byte_index_++];
322 num_bits_used_ = offset % 8;
323 return true;
326 private:
327 const uint8* const bytes_;
328 const size_t num_bits_;
329 const size_t num_bytes_;
330 // current_byte_index_ contains the current byte offset in |bytes_|.
331 size_t current_byte_index_;
332 // current_byte_ contains the current byte of the input.
333 uint8 current_byte_;
334 // num_bits_used_ contains the number of bits of |current_byte_| that have
335 // been read.
336 unsigned num_bits_used_;
339 // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
340 // simply encoded as a series of two-byte structures. The first byte determines
341 // the "0" pointer for that node and the second the "1" pointer. Each byte
342 // either has the MSB set, in which case the bottom 7 bits are the value for
343 // that position, or else the bottom seven bits contain the index of a node.
345 // The tree is decoded by walking rather than a table-driven approach.
346 class HuffmanDecoder {
347 public:
348 HuffmanDecoder(const uint8* tree, size_t tree_bytes)
349 : tree_(tree), tree_bytes_(tree_bytes) {}
351 bool Decode(BitReader* reader, char* out) {
352 const uint8* current = &tree_[tree_bytes_ - 2];
354 for (;;) {
355 bool bit;
356 if (!reader->Next(&bit)) {
357 return false;
360 uint8 b = current[bit];
361 if (b & 0x80) {
362 *out = static_cast<char>(b & 0x7f);
363 return true;
366 unsigned offset = static_cast<unsigned>(b) * 2;
367 DCHECK_LT(offset, tree_bytes_);
368 if (offset >= tree_bytes_) {
369 return false;
372 current = &tree_[offset];
376 private:
377 const uint8* const tree_;
378 const size_t tree_bytes_;
381 // PreloadResult is the result of resolving a specific name in the preloaded
382 // data.
383 struct PreloadResult {
384 uint32 pinset_id;
385 uint32 domain_id;
386 // hostname_offset contains the number of bytes from the start of the given
387 // hostname where the name of the matching entry starts.
388 size_t hostname_offset;
389 bool sts_include_subdomains;
390 bool pkp_include_subdomains;
391 bool force_https;
392 bool has_pins;
395 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns
396 // false on internal error and true otherwise. After a successful return,
397 // |*out_found| is true iff a relevant entry has been found. If so, |*out|
398 // contains the details.
400 // Don't call this function, call DecodeHSTSPreload, below.
402 // Although this code should be robust, it never processes attacker-controlled
403 // data -- it only operates on the preloaded data built into the binary.
405 // The preloaded data is represented as a trie and matches the hostname
406 // backwards. Each node in the trie starts with a number of characters, which
407 // must match exactly. After that is a dispatch table which maps the next
408 // character in the hostname to another node in the trie.
410 // In the dispatch table, the zero character represents the "end of string"
411 // (which is the *beginning* of a hostname since we process it backwards). The
412 // value in that case is special -- rather than an offset to another trie node,
413 // it contains the HSTS information: whether subdomains are included, pinsets
414 // etc. If an "end of string" matches a period in the hostname then the
415 // information is remembered because, if no more specific node is found, then
416 // that information applies to the hostname.
418 // Dispatch tables are always given in order, but the "end of string" (zero)
419 // value always comes before an entry for '.'.
420 bool DecodeHSTSPreloadRaw(const std::string& search_hostname,
421 bool* out_found,
422 PreloadResult* out) {
423 HuffmanDecoder huffman(kHSTSHuffmanTree, sizeof(kHSTSHuffmanTree));
424 BitReader reader(kPreloadedHSTSData, kPreloadedHSTSBits);
425 size_t bit_offset = kHSTSRootPosition;
426 static const char kEndOfString = 0;
427 static const char kEndOfTable = 127;
429 *out_found = false;
431 // Ensure that |search_hostname| is a valid hostname before
432 // processing.
433 if (CanonicalizeHost(search_hostname).empty()) {
434 return true;
437 // Normalize any trailing '.' used for DNS suffix searches.
438 std::string hostname = search_hostname;
439 size_t found = hostname.find_last_not_of('.');
440 if (found != std::string::npos) {
441 hostname.erase(found + 1);
442 } else {
443 hostname.clear();
446 // |hostname| has already undergone IDN conversion, so should be
447 // entirely A-Labels. The preload data is entirely normalized to
448 // lower case.
449 hostname = base::ToLowerASCII(hostname);
450 if (hostname.empty()) {
451 return true;
454 // hostname_offset contains one more than the index of the current character
455 // in the hostname that is being considered. It's one greater so that we can
456 // represent the position just before the beginning (with zero).
457 size_t hostname_offset = hostname.size();
459 for (;;) {
460 // Seek to the desired location.
461 if (!reader.Seek(bit_offset)) {
462 return false;
465 // Decode the unary length of the common prefix.
466 size_t prefix_length;
467 if (!reader.Unary(&prefix_length)) {
468 return false;
471 // Match each character in the prefix.
472 for (size_t i = 0; i < prefix_length; ++i) {
473 if (hostname_offset == 0) {
474 // We can't match the terminator with a prefix string.
475 return true;
478 char c;
479 if (!huffman.Decode(&reader, &c)) {
480 return false;
482 if (hostname[hostname_offset - 1] != c) {
483 return true;
485 hostname_offset--;
488 bool is_first_offset = true;
489 size_t current_offset = 0;
491 // Next is the dispatch table.
492 for (;;) {
493 char c;
494 if (!huffman.Decode(&reader, &c)) {
495 return false;
497 if (c == kEndOfTable) {
498 // No exact match.
499 return true;
502 if (c == kEndOfString) {
503 PreloadResult tmp;
504 if (!reader.Next(&tmp.sts_include_subdomains) ||
505 !reader.Next(&tmp.force_https) || !reader.Next(&tmp.has_pins)) {
506 return false;
509 tmp.pkp_include_subdomains = tmp.sts_include_subdomains;
511 if (tmp.has_pins) {
512 if (!reader.Read(4, &tmp.pinset_id) ||
513 !reader.Read(9, &tmp.domain_id) ||
514 (!tmp.sts_include_subdomains &&
515 !reader.Next(&tmp.pkp_include_subdomains))) {
516 return false;
520 tmp.hostname_offset = hostname_offset;
522 if (hostname_offset == 0 || hostname[hostname_offset - 1] == '.') {
523 *out_found = tmp.sts_include_subdomains || tmp.pkp_include_subdomains;
524 *out = tmp;
526 if (hostname_offset > 0) {
527 out->force_https &= tmp.sts_include_subdomains;
528 } else {
529 *out_found = true;
530 return true;
534 continue;
537 // The entries in a dispatch table are in order thus we can tell if there
538 // will be no match if the current character past the one that we want.
539 if (hostname_offset == 0 || hostname[hostname_offset - 1] < c) {
540 return true;
543 if (is_first_offset) {
544 // The first offset is backwards from the current position.
545 uint32 jump_delta_bits;
546 uint32 jump_delta;
547 if (!reader.Read(5, &jump_delta_bits) ||
548 !reader.Read(jump_delta_bits, &jump_delta)) {
549 return false;
552 if (bit_offset < jump_delta) {
553 return false;
556 current_offset = bit_offset - jump_delta;
557 is_first_offset = false;
558 } else {
559 // Subsequent offsets are forward from the target of the first offset.
560 uint32 is_long_jump;
561 if (!reader.Read(1, &is_long_jump)) {
562 return false;
565 uint32 jump_delta;
566 if (!is_long_jump) {
567 if (!reader.Read(7, &jump_delta)) {
568 return false;
570 } else {
571 uint32 jump_delta_bits;
572 if (!reader.Read(4, &jump_delta_bits) ||
573 !reader.Read(jump_delta_bits + 8, &jump_delta)) {
574 return false;
578 current_offset += jump_delta;
579 if (current_offset >= bit_offset) {
580 return false;
584 DCHECK_LT(0u, hostname_offset);
585 if (hostname[hostname_offset - 1] == c) {
586 bit_offset = current_offset;
587 hostname_offset--;
588 break;
594 bool DecodeHSTSPreload(const std::string& hostname, PreloadResult* out) {
595 bool found;
596 if (!DecodeHSTSPreloadRaw(hostname, &found, out)) {
597 DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
598 << hostname;
599 return false;
602 return found;
605 } // namespace
607 TransportSecurityState::TransportSecurityState()
608 : delegate_(nullptr), report_sender_(nullptr), enable_static_pins_(true) {
609 // Static pinning is only enabled for official builds to make sure that
610 // others don't end up with pins that cannot be easily updated.
611 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
612 enable_static_pins_ = false;
613 #endif
614 DCHECK(CalledOnValidThread());
617 // Both HSTS and HPKP cause fatal SSL errors, so return true if a
618 // host has either.
619 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host) {
620 STSState sts_state;
621 PKPState pkp_state;
622 if (GetStaticDomainState(host, &sts_state, &pkp_state))
623 return true;
624 if (GetDynamicSTSState(host, &sts_state))
625 return true;
626 return GetDynamicPKPState(host, &pkp_state);
629 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host) {
630 STSState dynamic_sts_state;
631 if (GetDynamicSTSState(host, &dynamic_sts_state))
632 return dynamic_sts_state.ShouldUpgradeToSSL();
634 STSState static_sts_state;
635 PKPState unused;
636 if (GetStaticDomainState(host, &static_sts_state, &unused) &&
637 static_sts_state.ShouldUpgradeToSSL()) {
638 return true;
641 return false;
644 bool TransportSecurityState::CheckPublicKeyPins(
645 const HostPortPair& host_port_pair,
646 bool is_issued_by_known_root,
647 const HashValueVector& public_key_hashes,
648 const X509Certificate* served_certificate_chain,
649 const X509Certificate* validated_certificate_chain,
650 const PublicKeyPinReportStatus report_status,
651 std::string* pinning_failure_log) {
652 // Perform pin validation if, and only if, all these conditions obtain:
654 // * the server's certificate chain chains up to a known root (i.e. not a
655 // user-installed trust anchor); and
656 // * the server actually has public key pins.
657 if (!is_issued_by_known_root || !HasPublicKeyPins(host_port_pair.host())) {
658 return true;
661 bool pins_are_valid = CheckPublicKeyPinsImpl(
662 host_port_pair, public_key_hashes, served_certificate_chain,
663 validated_certificate_chain, report_status, pinning_failure_log);
664 if (!pins_are_valid) {
665 LOG(ERROR) << *pinning_failure_log;
666 ReportUMAOnPinFailure(host_port_pair.host());
669 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
670 return pins_are_valid;
673 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
674 PKPState dynamic_state;
675 if (GetDynamicPKPState(host, &dynamic_state))
676 return dynamic_state.HasPublicKeyPins();
678 STSState unused;
679 PKPState static_pkp_state;
680 if (GetStaticDomainState(host, &unused, &static_pkp_state)) {
681 if (static_pkp_state.HasPublicKeyPins())
682 return true;
685 return false;
688 void TransportSecurityState::SetDelegate(
689 TransportSecurityState::Delegate* delegate) {
690 DCHECK(CalledOnValidThread());
691 delegate_ = delegate;
694 void TransportSecurityState::SetReportSender(
695 TransportSecurityState::ReportSender* report_sender) {
696 DCHECK(CalledOnValidThread());
697 report_sender_ = report_sender;
700 void TransportSecurityState::AddHSTSInternal(
701 const std::string& host,
702 TransportSecurityState::STSState::UpgradeMode upgrade_mode,
703 const base::Time& expiry,
704 bool include_subdomains) {
705 DCHECK(CalledOnValidThread());
707 STSState sts_state;
708 sts_state.last_observed = base::Time::Now();
709 sts_state.include_subdomains = include_subdomains;
710 sts_state.expiry = expiry;
711 sts_state.upgrade_mode = upgrade_mode;
713 EnableSTSHost(host, sts_state);
716 void TransportSecurityState::AddHPKPInternal(const std::string& host,
717 const base::Time& last_observed,
718 const base::Time& expiry,
719 bool include_subdomains,
720 const HashValueVector& hashes,
721 const GURL& report_uri) {
722 DCHECK(CalledOnValidThread());
724 PKPState pkp_state;
725 pkp_state.last_observed = last_observed;
726 pkp_state.expiry = expiry;
727 pkp_state.include_subdomains = include_subdomains;
728 pkp_state.spki_hashes = hashes;
729 pkp_state.report_uri = report_uri;
731 EnablePKPHost(host, pkp_state);
734 void TransportSecurityState::EnableSTSHost(const std::string& host,
735 const STSState& state) {
736 DCHECK(CalledOnValidThread());
738 const std::string canonicalized_host = CanonicalizeHost(host);
739 if (canonicalized_host.empty())
740 return;
742 // Only store new state when HSTS is explicitly enabled. If it is
743 // disabled, remove the state from the enabled hosts.
744 if (state.ShouldUpgradeToSSL()) {
745 STSState sts_state(state);
746 // No need to store this value since it is redundant. (|canonicalized_host|
747 // is the map key.)
748 sts_state.domain.clear();
750 enabled_sts_hosts_[HashHost(canonicalized_host)] = sts_state;
751 } else {
752 const std::string hashed_host = HashHost(canonicalized_host);
753 enabled_sts_hosts_.erase(hashed_host);
756 DirtyNotify();
759 void TransportSecurityState::EnablePKPHost(const std::string& host,
760 const PKPState& state) {
761 DCHECK(CalledOnValidThread());
763 const std::string canonicalized_host = CanonicalizeHost(host);
764 if (canonicalized_host.empty())
765 return;
767 // Only store new state when HPKP is explicitly enabled. If it is
768 // disabled, remove the state from the enabled hosts.
769 if (state.HasPublicKeyPins()) {
770 PKPState pkp_state(state);
771 // No need to store this value since it is redundant. (|canonicalized_host|
772 // is the map key.)
773 pkp_state.domain.clear();
775 enabled_pkp_hosts_[HashHost(canonicalized_host)] = pkp_state;
776 } else {
777 const std::string hashed_host = HashHost(canonicalized_host);
778 enabled_pkp_hosts_.erase(hashed_host);
781 DirtyNotify();
784 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
785 DCHECK(CalledOnValidThread());
787 const std::string canonicalized_host = CanonicalizeHost(host);
788 if (canonicalized_host.empty())
789 return false;
791 const std::string hashed_host = HashHost(canonicalized_host);
792 bool deleted = false;
793 STSStateMap::iterator sts_interator = enabled_sts_hosts_.find(hashed_host);
794 if (sts_interator != enabled_sts_hosts_.end()) {
795 enabled_sts_hosts_.erase(sts_interator);
796 deleted = true;
799 PKPStateMap::iterator pkp_iterator = enabled_pkp_hosts_.find(hashed_host);
800 if (pkp_iterator != enabled_pkp_hosts_.end()) {
801 enabled_pkp_hosts_.erase(pkp_iterator);
802 deleted = true;
805 if (deleted)
806 DirtyNotify();
807 return deleted;
810 void TransportSecurityState::ClearDynamicData() {
811 DCHECK(CalledOnValidThread());
812 enabled_sts_hosts_.clear();
813 enabled_pkp_hosts_.clear();
816 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
817 DCHECK(CalledOnValidThread());
819 bool dirtied = false;
820 STSStateMap::iterator sts_iterator = enabled_sts_hosts_.begin();
821 while (sts_iterator != enabled_sts_hosts_.end()) {
822 if (sts_iterator->second.last_observed >= time) {
823 dirtied = true;
824 enabled_sts_hosts_.erase(sts_iterator++);
825 continue;
828 ++sts_iterator;
831 PKPStateMap::iterator pkp_iterator = enabled_pkp_hosts_.begin();
832 while (pkp_iterator != enabled_pkp_hosts_.end()) {
833 if (pkp_iterator->second.last_observed >= time) {
834 dirtied = true;
835 enabled_pkp_hosts_.erase(pkp_iterator++);
836 continue;
839 ++pkp_iterator;
842 if (dirtied)
843 DirtyNotify();
846 TransportSecurityState::~TransportSecurityState() {
847 DCHECK(CalledOnValidThread());
850 void TransportSecurityState::DirtyNotify() {
851 DCHECK(CalledOnValidThread());
853 if (delegate_)
854 delegate_->StateIsDirty(this);
857 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
858 const std::string& value) {
859 DCHECK(CalledOnValidThread());
861 base::Time now = base::Time::Now();
862 base::TimeDelta max_age;
863 bool include_subdomains;
864 if (!ParseHSTSHeader(value, &max_age, &include_subdomains)) {
865 return false;
868 // Handle max-age == 0.
869 STSState::UpgradeMode upgrade_mode;
870 if (max_age.InSeconds() == 0) {
871 upgrade_mode = STSState::MODE_DEFAULT;
872 } else {
873 upgrade_mode = STSState::MODE_FORCE_HTTPS;
876 AddHSTSInternal(host, upgrade_mode, now + max_age, include_subdomains);
877 return true;
880 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
881 const std::string& value,
882 const SSLInfo& ssl_info) {
883 DCHECK(CalledOnValidThread());
885 base::Time now = base::Time::Now();
886 base::TimeDelta max_age;
887 bool include_subdomains;
888 HashValueVector spki_hashes;
889 GURL report_uri;
891 if (!ParseHPKPHeader(value, ssl_info.public_key_hashes, &max_age,
892 &include_subdomains, &spki_hashes, &report_uri)) {
893 return false;
895 // Handle max-age == 0.
896 if (max_age.InSeconds() == 0)
897 spki_hashes.clear();
898 AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes,
899 report_uri);
900 return true;
903 void TransportSecurityState::AddHSTS(const std::string& host,
904 const base::Time& expiry,
905 bool include_subdomains) {
906 DCHECK(CalledOnValidThread());
907 AddHSTSInternal(host, STSState::MODE_FORCE_HTTPS, expiry, include_subdomains);
910 void TransportSecurityState::AddHPKP(const std::string& host,
911 const base::Time& expiry,
912 bool include_subdomains,
913 const HashValueVector& hashes,
914 const GURL& report_uri) {
915 DCHECK(CalledOnValidThread());
916 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes,
917 report_uri);
920 bool TransportSecurityState::ProcessHPKPReportOnlyHeader(
921 const std::string& value,
922 const HostPortPair& host_port_pair,
923 const SSLInfo& ssl_info) {
924 DCHECK(CalledOnValidThread());
926 base::Time now = base::Time::Now();
927 bool include_subdomains;
928 HashValueVector spki_hashes;
929 GURL report_uri;
930 std::string unused_failure_log;
932 if (!ParseHPKPReportOnlyHeader(value, &include_subdomains, &spki_hashes,
933 &report_uri) ||
934 !report_uri.is_valid() || report_uri.is_empty()) {
935 return false;
938 PKPState pkp_state;
939 pkp_state.last_observed = now;
940 pkp_state.expiry = now;
941 pkp_state.include_subdomains = include_subdomains;
942 pkp_state.spki_hashes = spki_hashes;
943 pkp_state.report_uri = report_uri;
944 pkp_state.domain = DNSDomainToString(CanonicalizeHost(host_port_pair.host()));
946 // Only perform pin validation if the cert chains up to a known root.
947 if (!ssl_info.is_issued_by_known_root)
948 return true;
950 CheckPinsAndMaybeSendReport(
951 host_port_pair, pkp_state, ssl_info.public_key_hashes,
952 ssl_info.unverified_cert.get(), ssl_info.cert.get(), ENABLE_PIN_REPORTS,
953 report_sender_, &unused_failure_log);
954 return true;
957 // static
958 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) {
959 PreloadResult result;
960 return DecodeHSTSPreload(host, &result) && result.has_pins &&
961 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts;
964 // static
965 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
966 PreloadResult result;
967 if (!DecodeHSTSPreload(host, &result) ||
968 !result.has_pins) {
969 return;
972 DCHECK(result.domain_id != DOMAIN_NOT_PINNED);
974 UMA_HISTOGRAM_SPARSE_SLOWLY(
975 "Net.PublicKeyPinFailureDomain", result.domain_id);
978 // static
979 bool TransportSecurityState::IsBuildTimely() {
980 // If the build metadata aren't embedded in the binary then we can't use the
981 // build time to determine if the build is timely, return true by default. If
982 // we're building an official build then keep using the build time, even if
983 // it's invalid it'd be a date in the past and this function will return
984 // false.
985 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
986 return true;
987 #else
988 const base::Time build_time = base::GetBuildTime();
989 // We consider built-in information to be timely for 10 weeks.
990 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
991 #endif
994 bool TransportSecurityState::CheckPublicKeyPinsImpl(
995 const HostPortPair& host_port_pair,
996 const HashValueVector& hashes,
997 const X509Certificate* served_certificate_chain,
998 const X509Certificate* validated_certificate_chain,
999 const PublicKeyPinReportStatus report_status,
1000 std::string* failure_log) {
1001 PKPState pkp_state;
1002 STSState unused;
1004 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) &&
1005 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) {
1006 // HasPublicKeyPins should have returned true in order for this method
1007 // to have been called, so if we fall through to here, it's an error.
1008 return false;
1011 return CheckPinsAndMaybeSendReport(
1012 host_port_pair, pkp_state, hashes, served_certificate_chain,
1013 validated_certificate_chain, report_status, report_sender_, failure_log);
1016 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
1017 STSState* sts_state,
1018 PKPState* pkp_state) const {
1019 DCHECK(CalledOnValidThread());
1021 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
1022 sts_state->include_subdomains = false;
1023 pkp_state->include_subdomains = false;
1025 if (!IsBuildTimely())
1026 return false;
1028 PreloadResult result;
1029 if (!DecodeHSTSPreload(host, &result))
1030 return false;
1032 sts_state->domain = host.substr(result.hostname_offset);
1033 pkp_state->domain = sts_state->domain;
1034 sts_state->include_subdomains = result.sts_include_subdomains;
1035 sts_state->last_observed = base::GetBuildTime();
1036 sts_state->upgrade_mode = STSState::MODE_DEFAULT;
1037 if (result.force_https) {
1038 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
1041 if (enable_static_pins_ && result.has_pins) {
1042 pkp_state->include_subdomains = result.pkp_include_subdomains;
1043 pkp_state->last_observed = base::GetBuildTime();
1045 if (result.pinset_id >= arraysize(kPinsets))
1046 return false;
1047 const Pinset *pinset = &kPinsets[result.pinset_id];
1049 if (pinset->report_uri != kNoReportURI)
1050 pkp_state->report_uri = GURL(pinset->report_uri);
1052 if (pinset->accepted_pins) {
1053 const char* const* sha1_hash = pinset->accepted_pins;
1054 while (*sha1_hash) {
1055 AddHash(*sha1_hash, &pkp_state->spki_hashes);
1056 sha1_hash++;
1059 if (pinset->rejected_pins) {
1060 const char* const* sha1_hash = pinset->rejected_pins;
1061 while (*sha1_hash) {
1062 AddHash(*sha1_hash, &pkp_state->bad_spki_hashes);
1063 sha1_hash++;
1068 return true;
1071 bool TransportSecurityState::GetDynamicSTSState(const std::string& host,
1072 STSState* result) {
1073 DCHECK(CalledOnValidThread());
1075 const std::string canonicalized_host = CanonicalizeHost(host);
1076 if (canonicalized_host.empty())
1077 return false;
1079 base::Time current_time(base::Time::Now());
1081 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
1082 std::string host_sub_chunk(&canonicalized_host[i],
1083 canonicalized_host.size() - i);
1084 STSStateMap::iterator j = enabled_sts_hosts_.find(HashHost(host_sub_chunk));
1085 if (j == enabled_sts_hosts_.end())
1086 continue;
1088 // If the entry is invalid, drop it.
1089 if (current_time > j->second.expiry) {
1090 enabled_sts_hosts_.erase(j);
1091 DirtyNotify();
1092 continue;
1095 // If this is the most specific STS match, add it to the result. Note: a STS
1096 // entry at a more specific domain overrides a less specific domain whether
1097 // or not |include_subdomains| is set.
1098 if (current_time <= j->second.expiry) {
1099 if (i == 0 || j->second.include_subdomains) {
1100 *result = j->second;
1101 result->domain = DNSDomainToString(host_sub_chunk);
1102 return true;
1105 break;
1109 return false;
1112 bool TransportSecurityState::GetDynamicPKPState(const std::string& host,
1113 PKPState* result) {
1114 DCHECK(CalledOnValidThread());
1116 const std::string canonicalized_host = CanonicalizeHost(host);
1117 if (canonicalized_host.empty())
1118 return false;
1120 base::Time current_time(base::Time::Now());
1122 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
1123 std::string host_sub_chunk(&canonicalized_host[i],
1124 canonicalized_host.size() - i);
1125 PKPStateMap::iterator j = enabled_pkp_hosts_.find(HashHost(host_sub_chunk));
1126 if (j == enabled_pkp_hosts_.end())
1127 continue;
1129 // If the entry is invalid, drop it.
1130 if (current_time > j->second.expiry) {
1131 enabled_pkp_hosts_.erase(j);
1132 DirtyNotify();
1133 continue;
1136 // If this is the most specific PKP match, add it to the result. Note: a PKP
1137 // entry at a more specific domain overrides a less specific domain whether
1138 // or not |include_subdomains| is set.
1139 if (current_time <= j->second.expiry) {
1140 if (i == 0 || j->second.include_subdomains) {
1141 *result = j->second;
1142 result->domain = DNSDomainToString(host_sub_chunk);
1143 return true;
1146 break;
1150 return false;
1153 void TransportSecurityState::AddOrUpdateEnabledSTSHosts(
1154 const std::string& hashed_host,
1155 const STSState& state) {
1156 DCHECK(CalledOnValidThread());
1157 DCHECK(state.ShouldUpgradeToSSL());
1158 enabled_sts_hosts_[hashed_host] = state;
1161 void TransportSecurityState::AddOrUpdateEnabledPKPHosts(
1162 const std::string& hashed_host,
1163 const PKPState& state) {
1164 DCHECK(CalledOnValidThread());
1165 DCHECK(state.HasPublicKeyPins());
1166 enabled_pkp_hosts_[hashed_host] = state;
1169 TransportSecurityState::STSState::STSState()
1170 : upgrade_mode(MODE_DEFAULT), include_subdomains(false) {
1173 TransportSecurityState::STSState::~STSState() {
1176 bool TransportSecurityState::STSState::ShouldUpgradeToSSL() const {
1177 return upgrade_mode == MODE_FORCE_HTTPS;
1180 bool TransportSecurityState::STSState::ShouldSSLErrorsBeFatal() const {
1181 return true;
1184 TransportSecurityState::STSStateIterator::STSStateIterator(
1185 const TransportSecurityState& state)
1186 : iterator_(state.enabled_sts_hosts_.begin()),
1187 end_(state.enabled_sts_hosts_.end()) {
1190 TransportSecurityState::STSStateIterator::~STSStateIterator() {
1193 TransportSecurityState::PKPState::PKPState() : include_subdomains(false) {
1196 TransportSecurityState::PKPState::~PKPState() {
1199 bool TransportSecurityState::PKPState::CheckPublicKeyPins(
1200 const HashValueVector& hashes,
1201 std::string* failure_log) const {
1202 // Validate that hashes is not empty. By the time this code is called (in
1203 // production), that should never happen, but it's good to be defensive.
1204 // And, hashes *can* be empty in some test scenarios.
1205 if (hashes.empty()) {
1206 failure_log->append(
1207 "Rejecting empty public key chain for public-key-pinned domains: " +
1208 domain);
1209 return false;
1212 if (HashesIntersect(bad_spki_hashes, hashes)) {
1213 failure_log->append("Rejecting public key chain for domain " + domain +
1214 ". Validated chain: " + HashesToBase64String(hashes) +
1215 ", matches one or more bad hashes: " +
1216 HashesToBase64String(bad_spki_hashes));
1217 return false;
1220 // If there are no pins, then any valid chain is acceptable.
1221 if (spki_hashes.empty())
1222 return true;
1224 if (HashesIntersect(spki_hashes, hashes)) {
1225 return true;
1228 failure_log->append("Rejecting public key chain for domain " + domain +
1229 ". Validated chain: " + HashesToBase64String(hashes) +
1230 ", expected: " + HashesToBase64String(spki_hashes));
1231 return false;
1234 bool TransportSecurityState::PKPState::HasPublicKeyPins() const {
1235 return spki_hashes.size() > 0 || bad_spki_hashes.size() > 0;
1238 bool TransportSecurityState::PKPState::ShouldSSLErrorsBeFatal() const {
1239 return true;
1242 TransportSecurityState::PKPStateIterator::PKPStateIterator(
1243 const TransportSecurityState& state)
1244 : iterator_(state.enabled_pkp_hosts_.begin()),
1245 end_(state.enabled_pkp_hosts_.end()) {
1248 TransportSecurityState::PKPStateIterator::~PKPStateIterator() {
1251 } // namespace