Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / http / transport_security_state.cc
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.
4
5 #include "net/http/transport_security_state.h"
6
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
17
18 #include <algorithm>
19
20 #include "base/base64.h"
21 #include "base/build_time.h"
22 #include "base/logging.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/metrics/histogram.h"
25 #include "base/sha1.h"
26 #include "base/strings/string_number_conversions.h"
27 #include "base/strings/string_util.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "base/time/time.h"
30 #include "base/values.h"
31 #include "crypto/sha2.h"
32 #include "net/base/dns_util.h"
33 #include "net/cert/x509_cert_types.h"
34 #include "net/cert/x509_certificate.h"
35 #include "net/http/http_security_headers.h"
36 #include "net/ssl/ssl_info.h"
37 #include "url/gurl.h"
38
39 #if defined(USE_OPENSSL)
40 #include "crypto/openssl_util.h"
41 #endif
42
43 namespace net {
44
45 namespace {
46
47 std::string HashesToBase64String(const HashValueVector& hashes) {
48   std::string str;
49   for (size_t i = 0; i != hashes.size(); ++i) {
50     if (i != 0)
51       str += ",";
52     str += hashes[i].ToString();
53   }
54   return str;
55 }
56
57 std::string HashHost(const std::string& canonicalized_host) {
58   char hashed[crypto::kSHA256Length];
59   crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
60   return std::string(hashed, sizeof(hashed));
61 }
62
63 // Returns true if the intersection of |a| and |b| is not empty. If either
64 // |a| or |b| is empty, returns false.
65 bool HashesIntersect(const HashValueVector& a,
66                      const HashValueVector& b) {
67   for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
68     HashValueVector::const_iterator j =
69         std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
70     if (j != b.end())
71       return true;
72   }
73   return false;
74 }
75
76 bool AddHash(const char* sha1_hash,
77              HashValueVector* out) {
78   HashValue hash(HASH_VALUE_SHA1);
79   memcpy(hash.data(), sha1_hash, hash.size());
80   out->push_back(hash);
81   return true;
82 }
83
84 }  // namespace
85
86 TransportSecurityState::TransportSecurityState()
87     : delegate_(NULL), enable_static_pins_(true) {
88 // Static pinning is only enabled for official builds to make sure that
89 // others don't end up with pins that cannot be easily updated.
90 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
91   enable_static_pins_ = false;
92 #endif
93   DCHECK(CalledOnValidThread());
94 }
95
96 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
97     : iterator_(state.enabled_hosts_.begin()),
98       end_(state.enabled_hosts_.end()) {
99 }
100
101 TransportSecurityState::Iterator::~Iterator() {}
102
103 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host) {
104   DomainState state;
105   if (GetStaticDomainState(host, &state))
106     return true;
107   return GetDynamicDomainState(host, &state);
108 }
109
110 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host) {
111   DomainState dynamic_state;
112   if (GetDynamicDomainState(host, &dynamic_state))
113     return dynamic_state.ShouldUpgradeToSSL();
114
115   DomainState static_state;
116   if (GetStaticDomainState(host, &static_state) &&
117       static_state.ShouldUpgradeToSSL()) {
118       return true;
119   }
120
121   return false;
122 }
123
124 bool TransportSecurityState::CheckPublicKeyPins(
125     const std::string& host,
126     bool is_issued_by_known_root,
127     const HashValueVector& public_key_hashes,
128     std::string* pinning_failure_log) {
129   // Perform pin validation if, and only if, all these conditions obtain:
130   //
131   // * the server's certificate chain chains up to a known root (i.e. not a
132   //   user-installed trust anchor); and
133   // * the server actually has public key pins.
134   if (!is_issued_by_known_root || !HasPublicKeyPins(host)) {
135     return true;
136   }
137
138   bool pins_are_valid = CheckPublicKeyPinsImpl(
139       host, public_key_hashes, pinning_failure_log);
140   if (!pins_are_valid) {
141     LOG(ERROR) << *pinning_failure_log;
142     ReportUMAOnPinFailure(host);
143   }
144
145   UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
146   return pins_are_valid;
147 }
148
149 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
150   DomainState dynamic_state;
151   if (GetDynamicDomainState(host, &dynamic_state))
152     return dynamic_state.HasPublicKeyPins();
153
154   DomainState static_state;
155   if (GetStaticDomainState(host, &static_state)) {
156     if (static_state.HasPublicKeyPins())
157       return true;
158   }
159
160   return false;
161 }
162
163 void TransportSecurityState::SetDelegate(
164     TransportSecurityState::Delegate* delegate) {
165   DCHECK(CalledOnValidThread());
166   delegate_ = delegate;
167 }
168
169 void TransportSecurityState::EnableHost(const std::string& host,
170                                         const DomainState& state) {
171   DCHECK(CalledOnValidThread());
172
173   const std::string canonicalized_host = CanonicalizeHost(host);
174   if (canonicalized_host.empty())
175     return;
176
177   DomainState state_copy(state);
178   // No need to store this value since it is redundant. (|canonicalized_host|
179   // is the map key.)
180   state_copy.domain.clear();
181
182   enabled_hosts_[HashHost(canonicalized_host)] = state_copy;
183   DirtyNotify();
184 }
185
186 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
187   DCHECK(CalledOnValidThread());
188
189   const std::string canonicalized_host = CanonicalizeHost(host);
190   if (canonicalized_host.empty())
191     return false;
192
193   DomainStateMap::iterator i = enabled_hosts_.find(
194       HashHost(canonicalized_host));
195   if (i != enabled_hosts_.end()) {
196     enabled_hosts_.erase(i);
197     DirtyNotify();
198     return true;
199   }
200   return false;
201 }
202
203 void TransportSecurityState::ClearDynamicData() {
204   DCHECK(CalledOnValidThread());
205   enabled_hosts_.clear();
206 }
207
208 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
209   DCHECK(CalledOnValidThread());
210
211   bool dirtied = false;
212   DomainStateMap::iterator i = enabled_hosts_.begin();
213   while (i != enabled_hosts_.end()) {
214     if (i->second.sts.last_observed >= time &&
215         i->second.pkp.last_observed >= time) {
216       dirtied = true;
217       enabled_hosts_.erase(i++);
218       continue;
219     }
220
221     if (i->second.sts.last_observed >= time) {
222       dirtied = true;
223       i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT;
224     } else if (i->second.pkp.last_observed >= time) {
225       dirtied = true;
226       i->second.pkp.spki_hashes.clear();
227       i->second.pkp.expiry = base::Time();
228     }
229     ++i;
230   }
231
232   if (dirtied)
233     DirtyNotify();
234 }
235
236 TransportSecurityState::~TransportSecurityState() {
237   DCHECK(CalledOnValidThread());
238 }
239
240 void TransportSecurityState::DirtyNotify() {
241   DCHECK(CalledOnValidThread());
242
243   if (delegate_)
244     delegate_->StateIsDirty(this);
245 }
246
247 // static
248 std::string TransportSecurityState::CanonicalizeHost(const std::string& host) {
249   // We cannot perform the operations as detailed in the spec here as |host|
250   // has already undergone IDN processing before it reached us. Thus, we check
251   // that there are no invalid characters in the host and lowercase the result.
252
253   std::string new_host;
254   if (!DNSDomainFromDot(host, &new_host)) {
255     // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
256     // name is >255 bytes. However, search terms can have those properties.
257     return std::string();
258   }
259
260   for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
261     const unsigned label_length = static_cast<unsigned>(new_host[i]);
262     if (!label_length)
263       break;
264
265     for (size_t j = 0; j < label_length; ++j) {
266       new_host[i + 1 + j] = tolower(new_host[i + 1 + j]);
267     }
268   }
269
270   return new_host;
271 }
272
273 // BitReader is a class that allows a bytestring to be read bit-by-bit.
274 class BitReader {
275  public:
276   BitReader(const uint8* bytes, size_t num_bits)
277       : bytes_(bytes),
278         num_bits_(num_bits),
279         num_bytes_((num_bits + 7) / 8),
280         current_byte_index_(0),
281         num_bits_used_(8) {}
282
283   // Next sets |*out| to the next bit from the input. It returns false if no
284   // more bits are available or true otherwise.
285   bool Next(bool* out) {
286     if (num_bits_used_ == 8) {
287       if (current_byte_index_ >= num_bytes_) {
288         return false;
289       }
290       current_byte_ = bytes_[current_byte_index_++];
291       num_bits_used_ = 0;
292     }
293
294     *out = 1 & (current_byte_ >> (7 - num_bits_used_));
295     num_bits_used_++;
296     return true;
297   }
298
299   // Read sets the |num_bits| least-significant bits of |*out| to the value of
300   // the next |num_bits| bits from the input. It returns false if there are
301   // insufficient bits in the input or true otherwise.
302   bool Read(unsigned num_bits, uint32* out) {
303     DCHECK_LE(num_bits, 32u);
304
305     uint32 ret = 0;
306     for (unsigned i = 0; i < num_bits; ++i) {
307       bool bit;
308       if (!Next(&bit)) {
309         return false;
310       }
311       ret |= static_cast<uint32>(bit) << (num_bits - 1 - i);
312     }
313
314     *out = ret;
315     return true;
316   }
317
318   // Unary sets |*out| to the result of decoding a unary value from the input.
319   // It returns false if there were insufficient bits in the input and true
320   // otherwise.
321   bool Unary(size_t* out) {
322     size_t ret = 0;
323
324     for (;;) {
325       bool bit;
326       if (!Next(&bit)) {
327         return false;
328       }
329       if (!bit) {
330         break;
331       }
332       ret++;
333     }
334
335     *out = ret;
336     return true;
337   }
338
339   // Seek sets the current offest in the input to bit number |offset|. It
340   // returns true if |offset| is within the range of the input and false
341   // otherwise.
342   bool Seek(size_t offset) {
343     if (offset >= num_bits_) {
344       return false;
345     }
346     current_byte_index_ = offset / 8;
347     current_byte_ = bytes_[current_byte_index_++];
348     num_bits_used_ = offset % 8;
349     return true;
350   }
351
352  private:
353   const uint8* const bytes_;
354   const size_t num_bits_;
355   const size_t num_bytes_;
356   // current_byte_index_ contains the current byte offset in |bytes_|.
357   size_t current_byte_index_;
358   // current_byte_ contains the current byte of the input.
359   uint8 current_byte_;
360   // num_bits_used_ contains the number of bits of |current_byte_| that have
361   // been read.
362   unsigned num_bits_used_;
363 };
364
365 // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
366 // simply encoded as a series of two-byte structures. The first byte determines
367 // the "0" pointer for that node and the second the "1" pointer. Each byte
368 // either has the MSB set, in which case the bottom 7 bits are the value for
369 // that position, or else the bottom seven bits contain the index of a node.
370 //
371 // The tree is decoded by walking rather than a table-driven approach.
372 class HuffmanDecoder {
373  public:
374   HuffmanDecoder(const uint8* tree, size_t tree_bytes)
375       : tree_(tree),
376         tree_bytes_(tree_bytes) {}
377
378   bool Decode(BitReader* reader, char* out) {
379     const uint8* current = &tree_[tree_bytes_-2];
380
381     for (;;) {
382       bool bit;
383       if (!reader->Next(&bit)) {
384         return false;
385       }
386
387       uint8 b = current[bit];
388       if (b & 0x80) {
389         *out = static_cast<char>(b & 0x7f);
390         return true;
391       }
392
393       unsigned offset = static_cast<unsigned>(b) * 2;
394       DCHECK_LT(offset, tree_bytes_);
395       if (offset >= tree_bytes_) {
396         return false;
397       }
398
399       current = &tree_[offset];
400     }
401   }
402
403  private:
404   const uint8* const tree_;
405   const size_t tree_bytes_;
406 };
407
408 #include "net/http/transport_security_state_static.h"
409
410 // PreloadResult is the result of resolving a specific name in the preloaded
411 // data.
412 struct PreloadResult {
413   uint32 pinset_id;
414   uint32 domain_id;
415   // hostname_offset contains the number of bytes from the start of the given
416   // hostname where the name of the matching entry starts.
417   size_t hostname_offset;
418   bool include_subdomains;
419   bool force_https;
420   bool has_pins;
421 };
422
423 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns
424 // false on internal error and true otherwise. After a successful return,
425 // |*out_found| is true iff a relevant entry has been found. If so, |*out|
426 // contains the details.
427 //
428 // Don't call this function, call DecodeHSTSPreload, below.
429 //
430 // Although this code should be robust, it never processes attacker-controlled
431 // data -- it only operates on the preloaded data built into the binary.
432 //
433 // The preloaded data is represented as a trie and matches the hostname
434 // backwards. Each node in the trie starts with a number of characters, which
435 // must match exactly. After that is a dispatch table which maps the next
436 // character in the hostname to another node in the trie.
437 //
438 // In the dispatch table, the zero character represents the "end of string"
439 // (which is the *beginning* of a hostname since we process it backwards). The
440 // value in that case is special -- rather than an offset to another trie node,
441 // it contains the HSTS information: whether subdomains are included, pinsets
442 // etc. If an "end of string" matches a period in the hostname then the
443 // information is remembered because, if no more specific node is found, then
444 // that information applies to the hostname.
445 //
446 // Dispatch tables are always given in order, but the "end of string" (zero)
447 // value always comes before an entry for '.'.
448 bool DecodeHSTSPreloadRaw(const std::string& hostname,
449                           bool* out_found,
450                           PreloadResult* out) {
451   HuffmanDecoder huffman(kHSTSHuffmanTree, sizeof(kHSTSHuffmanTree));
452   BitReader reader(kPreloadedHSTSData, kPreloadedHSTSBits);
453   size_t bit_offset = kHSTSRootPosition;
454   static const char kEndOfString = 0;
455   static const char kEndOfTable = 127;
456
457   *out_found = false;
458
459   if (hostname.empty()) {
460     return true;
461   }
462   // hostname_offset contains one more than the index of the current character
463   // in the hostname that is being considered. It's one greater so that we can
464   // represent the position just before the beginning (with zero).
465   size_t hostname_offset = hostname.size();
466
467   for (;;) {
468     // Seek to the desired location.
469     if (!reader.Seek(bit_offset)) {
470       return false;
471     }
472
473     // Decode the unary length of the common prefix.
474     size_t prefix_length;
475     if (!reader.Unary(&prefix_length)) {
476       return false;
477     }
478
479     // Match each character in the prefix.
480     for (size_t i = 0; i < prefix_length; ++i) {
481       if (hostname_offset == 0) {
482         // We can't match the terminator with a prefix string.
483         return true;
484       }
485
486       char c;
487       if (!huffman.Decode(&reader, &c)) {
488         return false;
489       }
490       if (hostname[hostname_offset - 1] != c) {
491         return true;
492       }
493       hostname_offset--;
494     }
495
496     bool is_first_offset = true;
497     size_t current_offset = 0;
498
499     // Next is the dispatch table.
500     for (;;) {
501       char c;
502       if (!huffman.Decode(&reader, &c)) {
503         return false;
504       }
505       if (c == kEndOfTable) {
506         // No exact match.
507         return true;
508       }
509
510       if (c == kEndOfString) {
511         PreloadResult tmp;
512         if (!reader.Next(&tmp.include_subdomains) ||
513             !reader.Next(&tmp.force_https) ||
514             !reader.Next(&tmp.has_pins)) {
515           return false;
516         }
517
518         if (tmp.has_pins) {
519           if (!reader.Read(4, &tmp.pinset_id) ||
520               !reader.Read(9, &tmp.domain_id)) {
521             return false;
522           }
523         }
524
525         tmp.hostname_offset = hostname_offset;
526
527         if (hostname_offset == 0 || hostname[hostname_offset - 1] == '.') {
528           *out_found = tmp.include_subdomains;
529           *out = tmp;
530         }
531
532         if (hostname_offset == 0) {
533           *out_found = true;
534           return true;
535         }
536
537         continue;
538       }
539
540       // The entries in a dispatch table are in order thus we can tell if there
541       // will be no match if the current character past the one that we want.
542       if (hostname_offset == 0 || hostname[hostname_offset-1] < c) {
543         return true;
544       }
545
546       if (is_first_offset) {
547         // The first offset is backwards from the current position.
548         uint32 jump_delta_bits;
549         uint32 jump_delta;
550         if (!reader.Read(5, &jump_delta_bits) ||
551             !reader.Read(jump_delta_bits, &jump_delta)) {
552           return false;
553         }
554
555         if (bit_offset < jump_delta) {
556           return false;
557         }
558
559         current_offset = bit_offset - jump_delta;
560         is_first_offset = false;
561       } else {
562         // Subsequent offsets are forward from the target of the first offset.
563         uint32 is_long_jump;
564         if (!reader.Read(1, &is_long_jump)) {
565           return false;
566         }
567
568         uint32 jump_delta;
569         if (!is_long_jump) {
570           if (!reader.Read(7, &jump_delta)) {
571             return false;
572           }
573         } else {
574           uint32 jump_delta_bits;
575           if (!reader.Read(4, &jump_delta_bits) ||
576               !reader.Read(jump_delta_bits + 8, &jump_delta)) {
577             return false;
578           }
579         }
580
581         current_offset += jump_delta;
582         if (current_offset >= bit_offset) {
583           return false;
584         }
585       }
586
587       DCHECK_LT(0u, hostname_offset);
588       if (hostname[hostname_offset - 1] == c) {
589         bit_offset = current_offset;
590         hostname_offset--;
591         break;
592       }
593     }
594   }
595 }
596
597 bool DecodeHSTSPreload(const std::string& hostname,
598                        PreloadResult* out) {
599   bool found;
600   if (!DecodeHSTSPreloadRaw(hostname, &found, out)) {
601     DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
602                   << hostname;
603     return false;
604   }
605
606   return found;
607 }
608
609 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
610                                            const std::string& value) {
611   DCHECK(CalledOnValidThread());
612
613   base::Time now = base::Time::Now();
614   base::TimeDelta max_age;
615   TransportSecurityState::DomainState domain_state;
616   GetDynamicDomainState(host, &domain_state);
617   if (ParseHSTSHeader(value, &max_age, &domain_state.sts.include_subdomains)) {
618     // Handle max-age == 0.
619     if (max_age.InSeconds() == 0)
620       domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT;
621     else
622       domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
623     domain_state.sts.last_observed = now;
624     domain_state.sts.expiry = now + max_age;
625     EnableHost(host, domain_state);
626     return true;
627   }
628   return false;
629 }
630
631 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
632                                            const std::string& value,
633                                            const SSLInfo& ssl_info) {
634   DCHECK(CalledOnValidThread());
635
636   base::Time now = base::Time::Now();
637   base::TimeDelta max_age;
638   TransportSecurityState::DomainState domain_state;
639   GetDynamicDomainState(host, &domain_state);
640   if (ParseHPKPHeader(value,
641                       ssl_info.public_key_hashes,
642                       &max_age,
643                       &domain_state.pkp.include_subdomains,
644                       &domain_state.pkp.spki_hashes)) {
645     // Handle max-age == 0.
646     if (max_age.InSeconds() == 0)
647       domain_state.pkp.spki_hashes.clear();
648     domain_state.pkp.last_observed = now;
649     domain_state.pkp.expiry = now + max_age;
650     EnableHost(host, domain_state);
651     return true;
652   }
653   return false;
654 }
655
656 bool TransportSecurityState::AddHSTS(const std::string& host,
657                                      const base::Time& expiry,
658                                      bool include_subdomains) {
659   DCHECK(CalledOnValidThread());
660
661   // Copy-and-modify the existing DomainState for this host (if any).
662   TransportSecurityState::DomainState domain_state;
663   const std::string canonicalized_host = CanonicalizeHost(host);
664   const std::string hashed_host = HashHost(canonicalized_host);
665   DomainStateMap::const_iterator i = enabled_hosts_.find(
666       hashed_host);
667   if (i != enabled_hosts_.end())
668     domain_state = i->second;
669
670   domain_state.sts.last_observed = base::Time::Now();
671   domain_state.sts.include_subdomains = include_subdomains;
672   domain_state.sts.expiry = expiry;
673   domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
674   EnableHost(host, domain_state);
675   return true;
676 }
677
678 bool TransportSecurityState::AddHPKP(const std::string& host,
679                                      const base::Time& expiry,
680                                      bool include_subdomains,
681                                      const HashValueVector& hashes) {
682   DCHECK(CalledOnValidThread());
683
684   // Copy-and-modify the existing DomainState for this host (if any).
685   TransportSecurityState::DomainState domain_state;
686   const std::string canonicalized_host = CanonicalizeHost(host);
687   const std::string hashed_host = HashHost(canonicalized_host);
688   DomainStateMap::const_iterator i = enabled_hosts_.find(
689       hashed_host);
690   if (i != enabled_hosts_.end())
691     domain_state = i->second;
692
693   domain_state.pkp.last_observed = base::Time::Now();
694   domain_state.pkp.include_subdomains = include_subdomains;
695   domain_state.pkp.expiry = expiry;
696   domain_state.pkp.spki_hashes = hashes;
697   EnableHost(host, domain_state);
698   return true;
699 }
700
701 // static
702 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) {
703   PreloadResult result;
704   return DecodeHSTSPreload(host, &result) && result.has_pins &&
705          kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts;
706 }
707
708 // static
709 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
710   PreloadResult result;
711   if (!DecodeHSTSPreload(host, &result) ||
712       !result.has_pins) {
713     return;
714   }
715
716   DCHECK(result.domain_id != DOMAIN_NOT_PINNED);
717
718   UMA_HISTOGRAM_ENUMERATION(
719       "Net.PublicKeyPinFailureDomain", result.domain_id, DOMAIN_NUM_EVENTS);
720 }
721
722 // static
723 bool TransportSecurityState::IsBuildTimely() {
724   // If the build metadata aren't embedded in the binary then we can't use the
725   // build time to determine if the build is timely, return true by default. If
726   // we're building an official build then keep using the build time, even if
727   // it's invalid it'd be a date in the past and this function will return
728   // false.
729 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
730   return true;
731 #else
732   const base::Time build_time = base::GetBuildTime();
733   // We consider built-in information to be timely for 10 weeks.
734   return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
735 #endif
736 }
737
738 bool TransportSecurityState::CheckPublicKeyPinsImpl(
739     const std::string& host,
740     const HashValueVector& hashes,
741     std::string* failure_log) {
742   DomainState dynamic_state;
743   if (GetDynamicDomainState(host, &dynamic_state))
744     return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
745
746   DomainState static_state;
747   if (GetStaticDomainState(host, &static_state))
748     return static_state.CheckPublicKeyPins(hashes, failure_log);
749
750   // HasPublicKeyPins should have returned true in order for this method
751   // to have been called, so if we fall through to here, it's an error.
752   return false;
753 }
754
755 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
756                                                   DomainState* out) const {
757   DCHECK(CalledOnValidThread());
758
759   out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
760   out->sts.include_subdomains = false;
761   out->pkp.include_subdomains = false;
762
763   if (!IsBuildTimely())
764     return false;
765
766   PreloadResult result;
767   if (!DecodeHSTSPreload(host, &result))
768     return false;
769
770   out->domain = host.substr(result.hostname_offset);
771   out->sts.include_subdomains = result.include_subdomains;
772   out->sts.last_observed = base::GetBuildTime();
773   out->sts.upgrade_mode =
774       TransportSecurityState::DomainState::MODE_DEFAULT;
775   if (result.force_https) {
776     out->sts.upgrade_mode =
777         TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
778   }
779
780   if (enable_static_pins_ && result.has_pins) {
781     out->pkp.include_subdomains = result.include_subdomains;
782     out->pkp.last_observed = base::GetBuildTime();
783
784     if (result.pinset_id >= arraysize(kPinsets))
785       return false;
786     const Pinset *pinset = &kPinsets[result.pinset_id];
787
788     if (pinset->accepted_pins) {
789       const char* const* sha1_hash = pinset->accepted_pins;
790       while (*sha1_hash) {
791         AddHash(*sha1_hash, &out->pkp.spki_hashes);
792         sha1_hash++;
793       }
794     }
795     if (pinset->rejected_pins) {
796       const char* const* sha1_hash = pinset->rejected_pins;
797       while (*sha1_hash) {
798         AddHash(*sha1_hash, &out->pkp.bad_spki_hashes);
799         sha1_hash++;
800       }
801     }
802   }
803
804   return true;
805 }
806
807 bool TransportSecurityState::GetDynamicDomainState(const std::string& host,
808                                                    DomainState* result) {
809   DCHECK(CalledOnValidThread());
810
811   DomainState state;
812   const std::string canonicalized_host = CanonicalizeHost(host);
813   if (canonicalized_host.empty())
814     return false;
815
816   base::Time current_time(base::Time::Now());
817
818   for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
819     std::string host_sub_chunk(&canonicalized_host[i],
820                                canonicalized_host.size() - i);
821     DomainStateMap::iterator j =
822         enabled_hosts_.find(HashHost(host_sub_chunk));
823     if (j == enabled_hosts_.end())
824       continue;
825
826     if (current_time > j->second.sts.expiry &&
827         current_time > j->second.pkp.expiry) {
828       enabled_hosts_.erase(j);
829       DirtyNotify();
830       continue;
831     }
832
833     state = j->second;
834     state.domain = DNSDomainToString(host_sub_chunk);
835
836     // Succeed if we matched the domain exactly or if subdomain matches are
837     // allowed.
838     if (i == 0 || j->second.sts.include_subdomains ||
839         j->second.pkp.include_subdomains) {
840       *result = state;
841       return true;
842     }
843
844     return false;
845   }
846
847   return false;
848 }
849
850 void TransportSecurityState::AddOrUpdateEnabledHosts(
851     const std::string& hashed_host, const DomainState& state) {
852   DCHECK(CalledOnValidThread());
853   enabled_hosts_[hashed_host] = state;
854 }
855
856 TransportSecurityState::DomainState::DomainState() {
857   sts.upgrade_mode = MODE_DEFAULT;
858   sts.include_subdomains = false;
859   pkp.include_subdomains = false;
860 }
861
862 TransportSecurityState::DomainState::~DomainState() {
863 }
864
865 bool TransportSecurityState::DomainState::CheckPublicKeyPins(
866     const HashValueVector& hashes, std::string* failure_log) const {
867   // Validate that hashes is not empty. By the time this code is called (in
868   // production), that should never happen, but it's good to be defensive.
869   // And, hashes *can* be empty in some test scenarios.
870   if (hashes.empty()) {
871     failure_log->append(
872         "Rejecting empty public key chain for public-key-pinned domains: " +
873         domain);
874     return false;
875   }
876
877   if (HashesIntersect(pkp.bad_spki_hashes, hashes)) {
878     failure_log->append("Rejecting public key chain for domain " + domain +
879                         ". Validated chain: " + HashesToBase64String(hashes) +
880                         ", matches one or more bad hashes: " +
881                         HashesToBase64String(pkp.bad_spki_hashes));
882     return false;
883   }
884
885   // If there are no pins, then any valid chain is acceptable.
886   if (pkp.spki_hashes.empty())
887     return true;
888
889   if (HashesIntersect(pkp.spki_hashes, hashes)) {
890     return true;
891   }
892
893   failure_log->append("Rejecting public key chain for domain " + domain +
894                       ". Validated chain: " + HashesToBase64String(hashes) +
895                       ", expected: " + HashesToBase64String(pkp.spki_hashes));
896   return false;
897 }
898
899 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
900   return sts.upgrade_mode == MODE_FORCE_HTTPS;
901 }
902
903 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
904   return true;
905 }
906
907 bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
908   return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0;
909 }
910
911 TransportSecurityState::DomainState::PKPState::PKPState() {
912 }
913
914 TransportSecurityState::DomainState::PKPState::~PKPState() {
915 }
916
917 }  // namespace