Upgrade ReadPixels to ES3 semantic in command buffer.
[chromium-blink-merge.git] / net / http / transport_security_state.cc
blobb343223430245fc9e3764cf770dba270e3c5b693
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 bool CheckPinsAndMaybeSendReport(
139 const HostPortPair& host_port_pair,
140 const TransportSecurityState::PKPState& pkp_state,
141 const HashValueVector& hashes,
142 const X509Certificate* served_certificate_chain,
143 const X509Certificate* validated_certificate_chain,
144 const TransportSecurityState::PublicKeyPinReportStatus report_status,
145 TransportSecurityState::ReportSender* report_sender,
146 std::string* failure_log) {
147 if (pkp_state.CheckPublicKeyPins(hashes, failure_log))
148 return true;
150 if (!report_sender ||
151 report_status != TransportSecurityState::ENABLE_PIN_REPORTS ||
152 pkp_state.report_uri.is_empty()) {
153 return false;
156 DCHECK(pkp_state.report_uri.is_valid());
158 std::string serialized_report;
160 if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain,
161 validated_certificate_chain, &serialized_report)) {
162 return false;
165 report_sender->Send(pkp_state.report_uri, serialized_report);
167 return false;
170 std::string HashesToBase64String(const HashValueVector& hashes) {
171 std::string str;
172 for (size_t i = 0; i != hashes.size(); ++i) {
173 if (i != 0)
174 str += ",";
175 str += hashes[i].ToString();
177 return str;
180 std::string HashHost(const std::string& canonicalized_host) {
181 char hashed[crypto::kSHA256Length];
182 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
183 return std::string(hashed, sizeof(hashed));
186 // Returns true if the intersection of |a| and |b| is not empty. If either
187 // |a| or |b| is empty, returns false.
188 bool HashesIntersect(const HashValueVector& a,
189 const HashValueVector& b) {
190 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
191 HashValueVector::const_iterator j =
192 std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
193 if (j != b.end())
194 return true;
196 return false;
199 bool AddHash(const char* sha1_hash,
200 HashValueVector* out) {
201 HashValue hash(HASH_VALUE_SHA1);
202 memcpy(hash.data(), sha1_hash, hash.size());
203 out->push_back(hash);
204 return true;
207 // Converts |hostname| from dotted form ("www.google.com") to the form
208 // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns
209 // the result.
210 std::string CanonicalizeHost(const std::string& host) {
211 // We cannot perform the operations as detailed in the spec here as |host|
212 // has already undergone IDN processing before it reached us. Thus, we check
213 // that there are no invalid characters in the host and lowercase the result.
214 std::string new_host;
215 if (!DNSDomainFromDot(host, &new_host)) {
216 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
217 // name is >255 bytes. However, search terms can have those properties.
218 return std::string();
221 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
222 const unsigned label_length = static_cast<unsigned>(new_host[i]);
223 if (!label_length)
224 break;
226 for (size_t j = 0; j < label_length; ++j) {
227 new_host[i + 1 + j] = static_cast<char>(tolower(new_host[i + 1 + j]));
231 return new_host;
234 // BitReader is a class that allows a bytestring to be read bit-by-bit.
235 class BitReader {
236 public:
237 BitReader(const uint8* bytes, size_t num_bits)
238 : bytes_(bytes),
239 num_bits_(num_bits),
240 num_bytes_((num_bits + 7) / 8),
241 current_byte_index_(0),
242 num_bits_used_(8) {}
244 // Next sets |*out| to the next bit from the input. It returns false if no
245 // more bits are available or true otherwise.
246 bool Next(bool* out) {
247 if (num_bits_used_ == 8) {
248 if (current_byte_index_ >= num_bytes_) {
249 return false;
251 current_byte_ = bytes_[current_byte_index_++];
252 num_bits_used_ = 0;
255 *out = 1 & (current_byte_ >> (7 - num_bits_used_));
256 num_bits_used_++;
257 return true;
260 // Read sets the |num_bits| least-significant bits of |*out| to the value of
261 // the next |num_bits| bits from the input. It returns false if there are
262 // insufficient bits in the input or true otherwise.
263 bool Read(unsigned num_bits, uint32* out) {
264 DCHECK_LE(num_bits, 32u);
266 uint32 ret = 0;
267 for (unsigned i = 0; i < num_bits; ++i) {
268 bool bit;
269 if (!Next(&bit)) {
270 return false;
272 ret |= static_cast<uint32>(bit) << (num_bits - 1 - i);
275 *out = ret;
276 return true;
279 // Unary sets |*out| to the result of decoding a unary value from the input.
280 // It returns false if there were insufficient bits in the input and true
281 // otherwise.
282 bool Unary(size_t* out) {
283 size_t ret = 0;
285 for (;;) {
286 bool bit;
287 if (!Next(&bit)) {
288 return false;
290 if (!bit) {
291 break;
293 ret++;
296 *out = ret;
297 return true;
300 // Seek sets the current offest in the input to bit number |offset|. It
301 // returns true if |offset| is within the range of the input and false
302 // otherwise.
303 bool Seek(size_t offset) {
304 if (offset >= num_bits_) {
305 return false;
307 current_byte_index_ = offset / 8;
308 current_byte_ = bytes_[current_byte_index_++];
309 num_bits_used_ = offset % 8;
310 return true;
313 private:
314 const uint8* const bytes_;
315 const size_t num_bits_;
316 const size_t num_bytes_;
317 // current_byte_index_ contains the current byte offset in |bytes_|.
318 size_t current_byte_index_;
319 // current_byte_ contains the current byte of the input.
320 uint8 current_byte_;
321 // num_bits_used_ contains the number of bits of |current_byte_| that have
322 // been read.
323 unsigned num_bits_used_;
326 // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
327 // simply encoded as a series of two-byte structures. The first byte determines
328 // the "0" pointer for that node and the second the "1" pointer. Each byte
329 // either has the MSB set, in which case the bottom 7 bits are the value for
330 // that position, or else the bottom seven bits contain the index of a node.
332 // The tree is decoded by walking rather than a table-driven approach.
333 class HuffmanDecoder {
334 public:
335 HuffmanDecoder(const uint8* tree, size_t tree_bytes)
336 : tree_(tree), tree_bytes_(tree_bytes) {}
338 bool Decode(BitReader* reader, char* out) {
339 const uint8* current = &tree_[tree_bytes_ - 2];
341 for (;;) {
342 bool bit;
343 if (!reader->Next(&bit)) {
344 return false;
347 uint8 b = current[bit];
348 if (b & 0x80) {
349 *out = static_cast<char>(b & 0x7f);
350 return true;
353 unsigned offset = static_cast<unsigned>(b) * 2;
354 DCHECK_LT(offset, tree_bytes_);
355 if (offset >= tree_bytes_) {
356 return false;
359 current = &tree_[offset];
363 private:
364 const uint8* const tree_;
365 const size_t tree_bytes_;
368 // PreloadResult is the result of resolving a specific name in the preloaded
369 // data.
370 struct PreloadResult {
371 uint32 pinset_id;
372 uint32 domain_id;
373 // hostname_offset contains the number of bytes from the start of the given
374 // hostname where the name of the matching entry starts.
375 size_t hostname_offset;
376 bool sts_include_subdomains;
377 bool pkp_include_subdomains;
378 bool force_https;
379 bool has_pins;
382 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns
383 // false on internal error and true otherwise. After a successful return,
384 // |*out_found| is true iff a relevant entry has been found. If so, |*out|
385 // contains the details.
387 // Don't call this function, call DecodeHSTSPreload, below.
389 // Although this code should be robust, it never processes attacker-controlled
390 // data -- it only operates on the preloaded data built into the binary.
392 // The preloaded data is represented as a trie and matches the hostname
393 // backwards. Each node in the trie starts with a number of characters, which
394 // must match exactly. After that is a dispatch table which maps the next
395 // character in the hostname to another node in the trie.
397 // In the dispatch table, the zero character represents the "end of string"
398 // (which is the *beginning* of a hostname since we process it backwards). The
399 // value in that case is special -- rather than an offset to another trie node,
400 // it contains the HSTS information: whether subdomains are included, pinsets
401 // etc. If an "end of string" matches a period in the hostname then the
402 // information is remembered because, if no more specific node is found, then
403 // that information applies to the hostname.
405 // Dispatch tables are always given in order, but the "end of string" (zero)
406 // value always comes before an entry for '.'.
407 bool DecodeHSTSPreloadRaw(const std::string& search_hostname,
408 bool* out_found,
409 PreloadResult* out) {
410 HuffmanDecoder huffman(kHSTSHuffmanTree, sizeof(kHSTSHuffmanTree));
411 BitReader reader(kPreloadedHSTSData, kPreloadedHSTSBits);
412 size_t bit_offset = kHSTSRootPosition;
413 static const char kEndOfString = 0;
414 static const char kEndOfTable = 127;
416 *out_found = false;
418 // Ensure that |search_hostname| is a valid hostname before
419 // processing.
420 if (CanonicalizeHost(search_hostname).empty()) {
421 return true;
424 // Normalize any trailing '.' used for DNS suffix searches.
425 std::string hostname = search_hostname;
426 size_t found = hostname.find_last_not_of('.');
427 if (found != std::string::npos) {
428 hostname.erase(found + 1);
429 } else {
430 hostname.clear();
433 // |hostname| has already undergone IDN conversion, so should be
434 // entirely A-Labels. The preload data is entirely normalized to
435 // lower case.
436 base::StringToLowerASCII(&hostname);
438 if (hostname.empty()) {
439 return true;
442 // hostname_offset contains one more than the index of the current character
443 // in the hostname that is being considered. It's one greater so that we can
444 // represent the position just before the beginning (with zero).
445 size_t hostname_offset = hostname.size();
447 for (;;) {
448 // Seek to the desired location.
449 if (!reader.Seek(bit_offset)) {
450 return false;
453 // Decode the unary length of the common prefix.
454 size_t prefix_length;
455 if (!reader.Unary(&prefix_length)) {
456 return false;
459 // Match each character in the prefix.
460 for (size_t i = 0; i < prefix_length; ++i) {
461 if (hostname_offset == 0) {
462 // We can't match the terminator with a prefix string.
463 return true;
466 char c;
467 if (!huffman.Decode(&reader, &c)) {
468 return false;
470 if (hostname[hostname_offset - 1] != c) {
471 return true;
473 hostname_offset--;
476 bool is_first_offset = true;
477 size_t current_offset = 0;
479 // Next is the dispatch table.
480 for (;;) {
481 char c;
482 if (!huffman.Decode(&reader, &c)) {
483 return false;
485 if (c == kEndOfTable) {
486 // No exact match.
487 return true;
490 if (c == kEndOfString) {
491 PreloadResult tmp;
492 if (!reader.Next(&tmp.sts_include_subdomains) ||
493 !reader.Next(&tmp.force_https) || !reader.Next(&tmp.has_pins)) {
494 return false;
497 tmp.pkp_include_subdomains = tmp.sts_include_subdomains;
499 if (tmp.has_pins) {
500 if (!reader.Read(4, &tmp.pinset_id) ||
501 !reader.Read(9, &tmp.domain_id) ||
502 (!tmp.sts_include_subdomains &&
503 !reader.Next(&tmp.pkp_include_subdomains))) {
504 return false;
508 tmp.hostname_offset = hostname_offset;
510 if (hostname_offset == 0 || hostname[hostname_offset - 1] == '.') {
511 *out_found = tmp.sts_include_subdomains || tmp.pkp_include_subdomains;
512 *out = tmp;
514 if (hostname_offset > 0) {
515 out->force_https &= tmp.sts_include_subdomains;
516 } else {
517 *out_found = true;
518 return true;
522 continue;
525 // The entries in a dispatch table are in order thus we can tell if there
526 // will be no match if the current character past the one that we want.
527 if (hostname_offset == 0 || hostname[hostname_offset - 1] < c) {
528 return true;
531 if (is_first_offset) {
532 // The first offset is backwards from the current position.
533 uint32 jump_delta_bits;
534 uint32 jump_delta;
535 if (!reader.Read(5, &jump_delta_bits) ||
536 !reader.Read(jump_delta_bits, &jump_delta)) {
537 return false;
540 if (bit_offset < jump_delta) {
541 return false;
544 current_offset = bit_offset - jump_delta;
545 is_first_offset = false;
546 } else {
547 // Subsequent offsets are forward from the target of the first offset.
548 uint32 is_long_jump;
549 if (!reader.Read(1, &is_long_jump)) {
550 return false;
553 uint32 jump_delta;
554 if (!is_long_jump) {
555 if (!reader.Read(7, &jump_delta)) {
556 return false;
558 } else {
559 uint32 jump_delta_bits;
560 if (!reader.Read(4, &jump_delta_bits) ||
561 !reader.Read(jump_delta_bits + 8, &jump_delta)) {
562 return false;
566 current_offset += jump_delta;
567 if (current_offset >= bit_offset) {
568 return false;
572 DCHECK_LT(0u, hostname_offset);
573 if (hostname[hostname_offset - 1] == c) {
574 bit_offset = current_offset;
575 hostname_offset--;
576 break;
582 bool DecodeHSTSPreload(const std::string& hostname, PreloadResult* out) {
583 bool found;
584 if (!DecodeHSTSPreloadRaw(hostname, &found, out)) {
585 DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
586 << hostname;
587 return false;
590 return found;
593 } // namespace
595 TransportSecurityState::TransportSecurityState()
596 : delegate_(nullptr), report_sender_(nullptr), enable_static_pins_(true) {
597 // Static pinning is only enabled for official builds to make sure that
598 // others don't end up with pins that cannot be easily updated.
599 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
600 enable_static_pins_ = false;
601 #endif
602 DCHECK(CalledOnValidThread());
605 // Both HSTS and HPKP cause fatal SSL errors, so return true if a
606 // host has either.
607 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host) {
608 STSState sts_state;
609 PKPState pkp_state;
610 if (GetStaticDomainState(host, &sts_state, &pkp_state))
611 return true;
612 if (GetDynamicSTSState(host, &sts_state))
613 return true;
614 return GetDynamicPKPState(host, &pkp_state);
617 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host) {
618 STSState dynamic_sts_state;
619 if (GetDynamicSTSState(host, &dynamic_sts_state))
620 return dynamic_sts_state.ShouldUpgradeToSSL();
622 STSState static_sts_state;
623 PKPState unused;
624 if (GetStaticDomainState(host, &static_sts_state, &unused) &&
625 static_sts_state.ShouldUpgradeToSSL()) {
626 return true;
629 return false;
632 bool TransportSecurityState::CheckPublicKeyPins(
633 const HostPortPair& host_port_pair,
634 bool is_issued_by_known_root,
635 const HashValueVector& public_key_hashes,
636 const X509Certificate* served_certificate_chain,
637 const X509Certificate* validated_certificate_chain,
638 const PublicKeyPinReportStatus report_status,
639 std::string* pinning_failure_log) {
640 // Perform pin validation if, and only if, all these conditions obtain:
642 // * the server's certificate chain chains up to a known root (i.e. not a
643 // user-installed trust anchor); and
644 // * the server actually has public key pins.
645 if (!is_issued_by_known_root || !HasPublicKeyPins(host_port_pair.host())) {
646 return true;
649 bool pins_are_valid = CheckPublicKeyPinsImpl(
650 host_port_pair, public_key_hashes, served_certificate_chain,
651 validated_certificate_chain, report_status, pinning_failure_log);
652 if (!pins_are_valid) {
653 LOG(ERROR) << *pinning_failure_log;
654 ReportUMAOnPinFailure(host_port_pair.host());
657 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
658 return pins_are_valid;
661 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
662 PKPState dynamic_state;
663 if (GetDynamicPKPState(host, &dynamic_state))
664 return dynamic_state.HasPublicKeyPins();
666 STSState unused;
667 PKPState static_pkp_state;
668 if (GetStaticDomainState(host, &unused, &static_pkp_state)) {
669 if (static_pkp_state.HasPublicKeyPins())
670 return true;
673 return false;
676 void TransportSecurityState::SetDelegate(
677 TransportSecurityState::Delegate* delegate) {
678 DCHECK(CalledOnValidThread());
679 delegate_ = delegate;
682 void TransportSecurityState::SetReportSender(
683 TransportSecurityState::ReportSender* report_sender) {
684 DCHECK(CalledOnValidThread());
685 report_sender_ = report_sender;
688 void TransportSecurityState::AddHSTSInternal(
689 const std::string& host,
690 TransportSecurityState::STSState::UpgradeMode upgrade_mode,
691 const base::Time& expiry,
692 bool include_subdomains) {
693 DCHECK(CalledOnValidThread());
695 STSState sts_state;
696 sts_state.last_observed = base::Time::Now();
697 sts_state.include_subdomains = include_subdomains;
698 sts_state.expiry = expiry;
699 sts_state.upgrade_mode = upgrade_mode;
701 EnableSTSHost(host, sts_state);
704 void TransportSecurityState::AddHPKPInternal(const std::string& host,
705 const base::Time& last_observed,
706 const base::Time& expiry,
707 bool include_subdomains,
708 const HashValueVector& hashes,
709 const GURL& report_uri) {
710 DCHECK(CalledOnValidThread());
712 PKPState pkp_state;
713 pkp_state.last_observed = last_observed;
714 pkp_state.expiry = expiry;
715 pkp_state.include_subdomains = include_subdomains;
716 pkp_state.spki_hashes = hashes;
717 pkp_state.report_uri = report_uri;
719 EnablePKPHost(host, pkp_state);
722 void TransportSecurityState::EnableSTSHost(const std::string& host,
723 const STSState& state) {
724 DCHECK(CalledOnValidThread());
726 const std::string canonicalized_host = CanonicalizeHost(host);
727 if (canonicalized_host.empty())
728 return;
730 // Only store new state when HSTS is explicitly enabled. If it is
731 // disabled, remove the state from the enabled hosts.
732 if (state.ShouldUpgradeToSSL()) {
733 STSState sts_state(state);
734 // No need to store this value since it is redundant. (|canonicalized_host|
735 // is the map key.)
736 sts_state.domain.clear();
738 enabled_sts_hosts_[HashHost(canonicalized_host)] = sts_state;
739 } else {
740 const std::string hashed_host = HashHost(canonicalized_host);
741 enabled_sts_hosts_.erase(hashed_host);
744 DirtyNotify();
747 void TransportSecurityState::EnablePKPHost(const std::string& host,
748 const PKPState& state) {
749 DCHECK(CalledOnValidThread());
751 const std::string canonicalized_host = CanonicalizeHost(host);
752 if (canonicalized_host.empty())
753 return;
755 // Only store new state when HPKP is explicitly enabled. If it is
756 // disabled, remove the state from the enabled hosts.
757 if (state.HasPublicKeyPins()) {
758 PKPState pkp_state(state);
759 // No need to store this value since it is redundant. (|canonicalized_host|
760 // is the map key.)
761 pkp_state.domain.clear();
763 enabled_pkp_hosts_[HashHost(canonicalized_host)] = pkp_state;
764 } else {
765 const std::string hashed_host = HashHost(canonicalized_host);
766 enabled_pkp_hosts_.erase(hashed_host);
769 DirtyNotify();
772 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
773 DCHECK(CalledOnValidThread());
775 const std::string canonicalized_host = CanonicalizeHost(host);
776 if (canonicalized_host.empty())
777 return false;
779 const std::string hashed_host = HashHost(canonicalized_host);
780 bool deleted = false;
781 STSStateMap::iterator sts_interator = enabled_sts_hosts_.find(hashed_host);
782 if (sts_interator != enabled_sts_hosts_.end()) {
783 enabled_sts_hosts_.erase(sts_interator);
784 deleted = true;
787 PKPStateMap::iterator pkp_iterator = enabled_pkp_hosts_.find(hashed_host);
788 if (pkp_iterator != enabled_pkp_hosts_.end()) {
789 enabled_pkp_hosts_.erase(pkp_iterator);
790 deleted = true;
793 if (deleted)
794 DirtyNotify();
795 return deleted;
798 void TransportSecurityState::ClearDynamicData() {
799 DCHECK(CalledOnValidThread());
800 enabled_sts_hosts_.clear();
801 enabled_pkp_hosts_.clear();
804 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
805 DCHECK(CalledOnValidThread());
807 bool dirtied = false;
808 STSStateMap::iterator sts_iterator = enabled_sts_hosts_.begin();
809 while (sts_iterator != enabled_sts_hosts_.end()) {
810 if (sts_iterator->second.last_observed >= time) {
811 dirtied = true;
812 enabled_sts_hosts_.erase(sts_iterator++);
813 continue;
816 ++sts_iterator;
819 PKPStateMap::iterator pkp_iterator = enabled_pkp_hosts_.begin();
820 while (pkp_iterator != enabled_pkp_hosts_.end()) {
821 if (pkp_iterator->second.last_observed >= time) {
822 dirtied = true;
823 enabled_pkp_hosts_.erase(pkp_iterator++);
824 continue;
827 ++pkp_iterator;
830 if (dirtied)
831 DirtyNotify();
834 TransportSecurityState::~TransportSecurityState() {
835 DCHECK(CalledOnValidThread());
838 void TransportSecurityState::DirtyNotify() {
839 DCHECK(CalledOnValidThread());
841 if (delegate_)
842 delegate_->StateIsDirty(this);
845 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
846 const std::string& value) {
847 DCHECK(CalledOnValidThread());
849 base::Time now = base::Time::Now();
850 base::TimeDelta max_age;
851 bool include_subdomains;
852 if (!ParseHSTSHeader(value, &max_age, &include_subdomains)) {
853 return false;
856 // Handle max-age == 0.
857 STSState::UpgradeMode upgrade_mode;
858 if (max_age.InSeconds() == 0) {
859 upgrade_mode = STSState::MODE_DEFAULT;
860 } else {
861 upgrade_mode = STSState::MODE_FORCE_HTTPS;
864 AddHSTSInternal(host, upgrade_mode, now + max_age, include_subdomains);
865 return true;
868 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
869 const std::string& value,
870 const SSLInfo& ssl_info) {
871 DCHECK(CalledOnValidThread());
873 base::Time now = base::Time::Now();
874 base::TimeDelta max_age;
875 bool include_subdomains;
876 HashValueVector spki_hashes;
877 GURL report_uri;
879 if (!ParseHPKPHeader(value, ssl_info.public_key_hashes, &max_age,
880 &include_subdomains, &spki_hashes, &report_uri)) {
881 return false;
883 // Handle max-age == 0.
884 if (max_age.InSeconds() == 0)
885 spki_hashes.clear();
886 AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes,
887 report_uri);
888 return true;
891 void TransportSecurityState::AddHSTS(const std::string& host,
892 const base::Time& expiry,
893 bool include_subdomains) {
894 DCHECK(CalledOnValidThread());
895 AddHSTSInternal(host, STSState::MODE_FORCE_HTTPS, expiry, include_subdomains);
898 void TransportSecurityState::AddHPKP(const std::string& host,
899 const base::Time& expiry,
900 bool include_subdomains,
901 const HashValueVector& hashes,
902 const GURL& report_uri) {
903 DCHECK(CalledOnValidThread());
904 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes,
905 report_uri);
908 bool TransportSecurityState::ProcessHPKPReportOnlyHeader(
909 const std::string& value,
910 const HostPortPair& host_port_pair,
911 const SSLInfo& ssl_info) {
912 DCHECK(CalledOnValidThread());
914 base::Time now = base::Time::Now();
915 bool include_subdomains;
916 HashValueVector spki_hashes;
917 GURL report_uri;
918 std::string unused_failure_log;
920 if (!ParseHPKPReportOnlyHeader(value, &include_subdomains, &spki_hashes,
921 &report_uri) ||
922 !report_uri.is_valid() || report_uri.is_empty())
923 return false;
925 PKPState pkp_state;
926 pkp_state.last_observed = now;
927 pkp_state.expiry = now;
928 pkp_state.include_subdomains = include_subdomains;
929 pkp_state.spki_hashes = spki_hashes;
930 pkp_state.report_uri = report_uri;
931 pkp_state.domain = DNSDomainToString(CanonicalizeHost(host_port_pair.host()));
933 // Only perform pin validation if the cert chains up to a known root.
934 if (!ssl_info.is_issued_by_known_root)
935 return true;
937 CheckPinsAndMaybeSendReport(
938 host_port_pair, pkp_state, ssl_info.public_key_hashes,
939 ssl_info.unverified_cert.get(), ssl_info.cert.get(), ENABLE_PIN_REPORTS,
940 report_sender_, &unused_failure_log);
941 return true;
944 // static
945 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) {
946 PreloadResult result;
947 return DecodeHSTSPreload(host, &result) && result.has_pins &&
948 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts;
951 // static
952 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
953 PreloadResult result;
954 if (!DecodeHSTSPreload(host, &result) ||
955 !result.has_pins) {
956 return;
959 DCHECK(result.domain_id != DOMAIN_NOT_PINNED);
961 UMA_HISTOGRAM_SPARSE_SLOWLY(
962 "Net.PublicKeyPinFailureDomain", result.domain_id);
965 // static
966 bool TransportSecurityState::IsBuildTimely() {
967 // If the build metadata aren't embedded in the binary then we can't use the
968 // build time to determine if the build is timely, return true by default. If
969 // we're building an official build then keep using the build time, even if
970 // it's invalid it'd be a date in the past and this function will return
971 // false.
972 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
973 return true;
974 #else
975 const base::Time build_time = base::GetBuildTime();
976 // We consider built-in information to be timely for 10 weeks.
977 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
978 #endif
981 bool TransportSecurityState::CheckPublicKeyPinsImpl(
982 const HostPortPair& host_port_pair,
983 const HashValueVector& hashes,
984 const X509Certificate* served_certificate_chain,
985 const X509Certificate* validated_certificate_chain,
986 const PublicKeyPinReportStatus report_status,
987 std::string* failure_log) {
988 PKPState pkp_state;
989 STSState unused;
991 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) &&
992 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) {
993 // HasPublicKeyPins should have returned true in order for this method
994 // to have been called, so if we fall through to here, it's an error.
995 return false;
998 return CheckPinsAndMaybeSendReport(
999 host_port_pair, pkp_state, hashes, served_certificate_chain,
1000 validated_certificate_chain, report_status, report_sender_, failure_log);
1003 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
1004 STSState* sts_state,
1005 PKPState* pkp_state) const {
1006 DCHECK(CalledOnValidThread());
1008 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
1009 sts_state->include_subdomains = false;
1010 pkp_state->include_subdomains = false;
1012 if (!IsBuildTimely())
1013 return false;
1015 PreloadResult result;
1016 if (!DecodeHSTSPreload(host, &result))
1017 return false;
1019 sts_state->domain = host.substr(result.hostname_offset);
1020 pkp_state->domain = sts_state->domain;
1021 sts_state->include_subdomains = result.sts_include_subdomains;
1022 sts_state->last_observed = base::GetBuildTime();
1023 sts_state->upgrade_mode = STSState::MODE_DEFAULT;
1024 if (result.force_https) {
1025 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
1028 if (enable_static_pins_ && result.has_pins) {
1029 pkp_state->include_subdomains = result.pkp_include_subdomains;
1030 pkp_state->last_observed = base::GetBuildTime();
1032 if (result.pinset_id >= arraysize(kPinsets))
1033 return false;
1034 const Pinset *pinset = &kPinsets[result.pinset_id];
1036 if (pinset->accepted_pins) {
1037 const char* const* sha1_hash = pinset->accepted_pins;
1038 while (*sha1_hash) {
1039 AddHash(*sha1_hash, &pkp_state->spki_hashes);
1040 sha1_hash++;
1043 if (pinset->rejected_pins) {
1044 const char* const* sha1_hash = pinset->rejected_pins;
1045 while (*sha1_hash) {
1046 AddHash(*sha1_hash, &pkp_state->bad_spki_hashes);
1047 sha1_hash++;
1052 return true;
1055 bool TransportSecurityState::GetDynamicSTSState(const std::string& host,
1056 STSState* result) {
1057 DCHECK(CalledOnValidThread());
1059 const std::string canonicalized_host = CanonicalizeHost(host);
1060 if (canonicalized_host.empty())
1061 return false;
1063 base::Time current_time(base::Time::Now());
1065 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
1066 std::string host_sub_chunk(&canonicalized_host[i],
1067 canonicalized_host.size() - i);
1068 STSStateMap::iterator j = enabled_sts_hosts_.find(HashHost(host_sub_chunk));
1069 if (j == enabled_sts_hosts_.end())
1070 continue;
1072 // If the entry is invalid, drop it.
1073 if (current_time > j->second.expiry) {
1074 enabled_sts_hosts_.erase(j);
1075 DirtyNotify();
1076 continue;
1079 // If this is the most specific STS match, add it to the result. Note: a STS
1080 // entry at a more specific domain overrides a less specific domain whether
1081 // or not |include_subdomains| is set.
1082 if (current_time <= j->second.expiry) {
1083 if (i == 0 || j->second.include_subdomains) {
1084 *result = j->second;
1085 result->domain = DNSDomainToString(host_sub_chunk);
1086 return true;
1089 break;
1093 return false;
1096 bool TransportSecurityState::GetDynamicPKPState(const std::string& host,
1097 PKPState* result) {
1098 DCHECK(CalledOnValidThread());
1100 const std::string canonicalized_host = CanonicalizeHost(host);
1101 if (canonicalized_host.empty())
1102 return false;
1104 base::Time current_time(base::Time::Now());
1106 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
1107 std::string host_sub_chunk(&canonicalized_host[i],
1108 canonicalized_host.size() - i);
1109 PKPStateMap::iterator j = enabled_pkp_hosts_.find(HashHost(host_sub_chunk));
1110 if (j == enabled_pkp_hosts_.end())
1111 continue;
1113 // If the entry is invalid, drop it.
1114 if (current_time > j->second.expiry) {
1115 enabled_pkp_hosts_.erase(j);
1116 DirtyNotify();
1117 continue;
1120 // If this is the most specific PKP match, add it to the result. Note: a PKP
1121 // entry at a more specific domain overrides a less specific domain whether
1122 // or not |include_subdomains| is set.
1123 if (current_time <= j->second.expiry) {
1124 if (i == 0 || j->second.include_subdomains) {
1125 *result = j->second;
1126 result->domain = DNSDomainToString(host_sub_chunk);
1127 return true;
1130 break;
1134 return false;
1137 void TransportSecurityState::AddOrUpdateEnabledSTSHosts(
1138 const std::string& hashed_host,
1139 const STSState& state) {
1140 DCHECK(CalledOnValidThread());
1141 DCHECK(state.ShouldUpgradeToSSL());
1142 enabled_sts_hosts_[hashed_host] = state;
1145 void TransportSecurityState::AddOrUpdateEnabledPKPHosts(
1146 const std::string& hashed_host,
1147 const PKPState& state) {
1148 DCHECK(CalledOnValidThread());
1149 DCHECK(state.HasPublicKeyPins());
1150 enabled_pkp_hosts_[hashed_host] = state;
1153 TransportSecurityState::STSState::STSState()
1154 : upgrade_mode(MODE_DEFAULT), include_subdomains(false) {
1157 TransportSecurityState::STSState::~STSState() {
1160 bool TransportSecurityState::STSState::ShouldUpgradeToSSL() const {
1161 return upgrade_mode == MODE_FORCE_HTTPS;
1164 bool TransportSecurityState::STSState::ShouldSSLErrorsBeFatal() const {
1165 return true;
1168 TransportSecurityState::STSStateIterator::STSStateIterator(
1169 const TransportSecurityState& state)
1170 : iterator_(state.enabled_sts_hosts_.begin()),
1171 end_(state.enabled_sts_hosts_.end()) {
1174 TransportSecurityState::STSStateIterator::~STSStateIterator() {
1177 TransportSecurityState::PKPState::PKPState() : include_subdomains(false) {
1180 TransportSecurityState::PKPState::~PKPState() {
1183 bool TransportSecurityState::PKPState::CheckPublicKeyPins(
1184 const HashValueVector& hashes,
1185 std::string* failure_log) const {
1186 // Validate that hashes is not empty. By the time this code is called (in
1187 // production), that should never happen, but it's good to be defensive.
1188 // And, hashes *can* be empty in some test scenarios.
1189 if (hashes.empty()) {
1190 failure_log->append(
1191 "Rejecting empty public key chain for public-key-pinned domains: " +
1192 domain);
1193 return false;
1196 if (HashesIntersect(bad_spki_hashes, hashes)) {
1197 failure_log->append("Rejecting public key chain for domain " + domain +
1198 ". Validated chain: " + HashesToBase64String(hashes) +
1199 ", matches one or more bad hashes: " +
1200 HashesToBase64String(bad_spki_hashes));
1201 return false;
1204 // If there are no pins, then any valid chain is acceptable.
1205 if (spki_hashes.empty())
1206 return true;
1208 if (HashesIntersect(spki_hashes, hashes)) {
1209 return true;
1212 failure_log->append("Rejecting public key chain for domain " + domain +
1213 ". Validated chain: " + HashesToBase64String(hashes) +
1214 ", expected: " + HashesToBase64String(spki_hashes));
1215 return false;
1218 bool TransportSecurityState::PKPState::HasPublicKeyPins() const {
1219 return spki_hashes.size() > 0 || bad_spki_hashes.size() > 0;
1222 bool TransportSecurityState::PKPState::ShouldSSLErrorsBeFatal() const {
1223 return true;
1226 TransportSecurityState::PKPStateIterator::PKPStateIterator(
1227 const TransportSecurityState& state)
1228 : iterator_(state.enabled_pkp_hosts_.begin()),
1229 end_(state.enabled_pkp_hosts_.end()) {
1232 TransportSecurityState::PKPStateIterator::~PKPStateIterator() {
1235 } // namespace