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)
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"
43 #if defined(USE_OPENSSL)
44 #include "crypto/openssl_util.h"
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
) {
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
)));
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,
83 if (pkp_state
.report_uri
.is_empty())
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=";
112 case HASH_VALUE_SHA256
:
113 known_pin
+= "pin-sha256=";
117 std::string base64_value
;
119 base::StringPiece(reinterpret_cast<const char*>(hash_value
.data()),
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.";
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
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
))
159 if (!report_sender
||
160 report_status
!= TransportSecurityState::ENABLE_PIN_REPORTS
||
161 pkp_state
.report_uri
.is_empty()) {
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()))
171 std::string serialized_report
;
173 if (!GetHPKPReport(host_port_pair
, pkp_state
, served_certificate_chain
,
174 validated_certificate_chain
, &serialized_report
)) {
178 report_sender
->Send(pkp_state
.report_uri
, serialized_report
);
183 std::string
HashesToBase64String(const HashValueVector
& hashes
) {
185 for (size_t i
= 0; i
!= hashes
.size(); ++i
) {
188 str
+= hashes
[i
].ToString();
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
));
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
);
220 // Converts |hostname| from dotted form ("www.google.com") to the form
221 // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns
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
]);
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
]));
247 // BitReader is a class that allows a bytestring to be read bit-by-bit.
250 BitReader(const uint8
* bytes
, size_t num_bits
)
253 num_bytes_((num_bits
+ 7) / 8),
254 current_byte_index_(0),
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_
) {
264 current_byte_
= bytes_
[current_byte_index_
++];
268 *out
= 1 & (current_byte_
>> (7 - num_bits_used_
));
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);
280 for (unsigned i
= 0; i
< num_bits
; ++i
) {
285 ret
|= static_cast<uint32
>(bit
) << (num_bits
- 1 - i
);
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
295 bool Unary(size_t* out
) {
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
316 bool Seek(size_t offset
) {
317 if (offset
>= num_bits_
) {
320 current_byte_index_
= offset
/ 8;
321 current_byte_
= bytes_
[current_byte_index_
++];
322 num_bits_used_
= offset
% 8;
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.
334 // num_bits_used_ contains the number of bits of |current_byte_| that have
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
{
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];
356 if (!reader
->Next(&bit
)) {
360 uint8 b
= current
[bit
];
362 *out
= static_cast<char>(b
& 0x7f);
366 unsigned offset
= static_cast<unsigned>(b
) * 2;
367 DCHECK_LT(offset
, tree_bytes_
);
368 if (offset
>= tree_bytes_
) {
372 current
= &tree_
[offset
];
377 const uint8
* const tree_
;
378 const size_t tree_bytes_
;
381 // PreloadResult is the result of resolving a specific name in the preloaded
383 struct PreloadResult
{
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
;
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
,
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;
431 // Ensure that |search_hostname| is a valid hostname before
433 if (CanonicalizeHost(search_hostname
).empty()) {
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);
446 // |hostname| has already undergone IDN conversion, so should be
447 // entirely A-Labels. The preload data is entirely normalized to
449 hostname
= base::ToLowerASCII(hostname
);
450 if (hostname
.empty()) {
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();
460 // Seek to the desired location.
461 if (!reader
.Seek(bit_offset
)) {
465 // Decode the unary length of the common prefix.
466 size_t prefix_length
;
467 if (!reader
.Unary(&prefix_length
)) {
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.
479 if (!huffman
.Decode(&reader
, &c
)) {
482 if (hostname
[hostname_offset
- 1] != c
) {
488 bool is_first_offset
= true;
489 size_t current_offset
= 0;
491 // Next is the dispatch table.
494 if (!huffman
.Decode(&reader
, &c
)) {
497 if (c
== kEndOfTable
) {
502 if (c
== kEndOfString
) {
504 if (!reader
.Next(&tmp
.sts_include_subdomains
) ||
505 !reader
.Next(&tmp
.force_https
) || !reader
.Next(&tmp
.has_pins
)) {
509 tmp
.pkp_include_subdomains
= tmp
.sts_include_subdomains
;
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
))) {
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
;
526 if (hostname_offset
> 0) {
527 out
->force_https
&= tmp
.sts_include_subdomains
;
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
) {
543 if (is_first_offset
) {
544 // The first offset is backwards from the current position.
545 uint32 jump_delta_bits
;
547 if (!reader
.Read(5, &jump_delta_bits
) ||
548 !reader
.Read(jump_delta_bits
, &jump_delta
)) {
552 if (bit_offset
< jump_delta
) {
556 current_offset
= bit_offset
- jump_delta
;
557 is_first_offset
= false;
559 // Subsequent offsets are forward from the target of the first offset.
561 if (!reader
.Read(1, &is_long_jump
)) {
567 if (!reader
.Read(7, &jump_delta
)) {
571 uint32 jump_delta_bits
;
572 if (!reader
.Read(4, &jump_delta_bits
) ||
573 !reader
.Read(jump_delta_bits
+ 8, &jump_delta
)) {
578 current_offset
+= jump_delta
;
579 if (current_offset
>= bit_offset
) {
584 DCHECK_LT(0u, hostname_offset
);
585 if (hostname
[hostname_offset
- 1] == c
) {
586 bit_offset
= current_offset
;
594 bool DecodeHSTSPreload(const std::string
& hostname
, PreloadResult
* out
) {
596 if (!DecodeHSTSPreloadRaw(hostname
, &found
, out
)) {
597 DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
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;
614 DCHECK(CalledOnValidThread());
617 // Both HSTS and HPKP cause fatal SSL errors, so return true if a
619 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string
& host
) {
622 if (GetStaticDomainState(host
, &sts_state
, &pkp_state
))
624 if (GetDynamicSTSState(host
, &sts_state
))
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
;
636 if (GetStaticDomainState(host
, &static_sts_state
, &unused
) &&
637 static_sts_state
.ShouldUpgradeToSSL()) {
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())) {
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();
679 PKPState static_pkp_state
;
680 if (GetStaticDomainState(host
, &unused
, &static_pkp_state
)) {
681 if (static_pkp_state
.HasPublicKeyPins())
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());
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());
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())
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|
748 sts_state
.domain
.clear();
750 enabled_sts_hosts_
[HashHost(canonicalized_host
)] = sts_state
;
752 const std::string hashed_host
= HashHost(canonicalized_host
);
753 enabled_sts_hosts_
.erase(hashed_host
);
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())
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|
773 pkp_state
.domain
.clear();
775 enabled_pkp_hosts_
[HashHost(canonicalized_host
)] = pkp_state
;
777 const std::string hashed_host
= HashHost(canonicalized_host
);
778 enabled_pkp_hosts_
.erase(hashed_host
);
784 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string
& host
) {
785 DCHECK(CalledOnValidThread());
787 const std::string canonicalized_host
= CanonicalizeHost(host
);
788 if (canonicalized_host
.empty())
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
);
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
);
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
) {
824 enabled_sts_hosts_
.erase(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
) {
835 enabled_pkp_hosts_
.erase(pkp_iterator
++);
846 TransportSecurityState::~TransportSecurityState() {
847 DCHECK(CalledOnValidThread());
850 void TransportSecurityState::DirtyNotify() {
851 DCHECK(CalledOnValidThread());
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
)) {
868 // Handle max-age == 0.
869 STSState::UpgradeMode upgrade_mode
;
870 if (max_age
.InSeconds() == 0) {
871 upgrade_mode
= STSState::MODE_DEFAULT
;
873 upgrade_mode
= STSState::MODE_FORCE_HTTPS
;
876 AddHSTSInternal(host
, upgrade_mode
, now
+ max_age
, include_subdomains
);
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
;
891 if (!ParseHPKPHeader(value
, ssl_info
.public_key_hashes
, &max_age
,
892 &include_subdomains
, &spki_hashes
, &report_uri
)) {
895 // Handle max-age == 0.
896 if (max_age
.InSeconds() == 0)
898 AddHPKPInternal(host
, now
, now
+ max_age
, include_subdomains
, spki_hashes
,
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
,
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
;
930 std::string unused_failure_log
;
932 if (!ParseHPKPReportOnlyHeader(value
, &include_subdomains
, &spki_hashes
,
934 !report_uri
.is_valid() || report_uri
.is_empty()) {
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
)
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
);
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
;
965 void TransportSecurityState::ReportUMAOnPinFailure(const std::string
& host
) {
966 PreloadResult result
;
967 if (!DecodeHSTSPreload(host
, &result
) ||
972 DCHECK(result
.domain_id
!= DOMAIN_NOT_PINNED
);
974 UMA_HISTOGRAM_SPARSE_SLOWLY(
975 "Net.PublicKeyPinFailureDomain", result
.domain_id
);
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
985 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
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 */;
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
) {
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.
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())
1028 PreloadResult result
;
1029 if (!DecodeHSTSPreload(host
, &result
))
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
))
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
);
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
);
1071 bool TransportSecurityState::GetDynamicSTSState(const std::string
& host
,
1073 DCHECK(CalledOnValidThread());
1075 const std::string canonicalized_host
= CanonicalizeHost(host
);
1076 if (canonicalized_host
.empty())
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())
1088 // If the entry is invalid, drop it.
1089 if (current_time
> j
->second
.expiry
) {
1090 enabled_sts_hosts_
.erase(j
);
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
);
1112 bool TransportSecurityState::GetDynamicPKPState(const std::string
& host
,
1114 DCHECK(CalledOnValidThread());
1116 const std::string canonicalized_host
= CanonicalizeHost(host
);
1117 if (canonicalized_host
.empty())
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())
1129 // If the entry is invalid, drop it.
1130 if (current_time
> j
->second
.expiry
) {
1131 enabled_pkp_hosts_
.erase(j
);
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
);
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 {
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: " +
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
));
1220 // If there are no pins, then any valid chain is acceptable.
1221 if (spki_hashes
.empty())
1224 if (HashesIntersect(spki_hashes
, hashes
)) {
1228 failure_log
->append("Rejecting public key chain for domain " + domain
+
1229 ". Validated chain: " + HashesToBase64String(hashes
) +
1230 ", expected: " + HashesToBase64String(spki_hashes
));
1234 bool TransportSecurityState::PKPState::HasPublicKeyPins() const {
1235 return spki_hashes
.size() > 0 || bad_spki_hashes
.size() > 0;
1238 bool TransportSecurityState::PKPState::ShouldSSLErrorsBeFatal() const {
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() {