Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Side by Side Diff: net/base/transport_security_state.cc

Issue 10826257: Implement SHA-256 fingerprint support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/transport_security_state.h ('k') | net/base/transport_security_state_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/transport_security_state.h" 5 #include "net/base/transport_security_state.h"
6 6
7 #if defined(USE_OPENSSL) 7 #if defined(USE_OPENSSL)
8 #include <openssl/ecdsa.h> 8 #include <openssl/ecdsa.h>
9 #include <openssl/ssl.h> 9 #include <openssl/ssl.h>
10 #else // !defined(USE_OPENSSL) 10 #else // !defined(USE_OPENSSL)
11 #include <cryptohi.h> 11 #include <cryptohi.h>
12 #include <hasht.h> 12 #include <hasht.h>
13 #include <keyhi.h> 13 #include <keyhi.h>
14 #include <pk11pub.h> 14 #include <pk11pub.h>
15 #include <nspr.h> 15 #include <nspr.h>
16 #endif 16 #endif
17 17
18 #include <algorithm> 18 #include <algorithm>
19 #include <utility>
20 19
21 #include "base/base64.h" 20 #include "base/base64.h"
22 #include "base/logging.h" 21 #include "base/logging.h"
23 #include "base/memory/scoped_ptr.h" 22 #include "base/memory/scoped_ptr.h"
24 #include "base/metrics/histogram.h" 23 #include "base/metrics/histogram.h"
25 #include "base/sha1.h" 24 #include "base/sha1.h"
26 #include "base/string_number_conversions.h" 25 #include "base/string_number_conversions.h"
27 #include "base/string_tokenizer.h" 26 #include "base/string_tokenizer.h"
28 #include "base/string_util.h" 27 #include "base/string_util.h"
29 #include "base/time.h" 28 #include "base/time.h"
30 #include "base/utf_string_conversions.h" 29 #include "base/utf_string_conversions.h"
31 #include "base/values.h" 30 #include "base/values.h"
32 #include "crypto/sha2.h" 31 #include "crypto/sha2.h"
33 #include "googleurl/src/gurl.h" 32 #include "googleurl/src/gurl.h"
34 #include "net/base/dns_util.h" 33 #include "net/base/dns_util.h"
35 #include "net/base/ssl_info.h" 34 #include "net/base/ssl_info.h"
35 #include "net/base/x509_cert_types.h"
36 #include "net/base/x509_certificate.h" 36 #include "net/base/x509_certificate.h"
37 #include "net/http/http_util.h" 37 #include "net/http/http_util.h"
38 38
39 #if defined(USE_OPENSSL) 39 #if defined(USE_OPENSSL)
40 #include "crypto/openssl_util.h" 40 #include "crypto/openssl_util.h"
41 #endif 41 #endif
42 42
43 namespace net { 43 namespace net {
44 44
45 const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year 45 const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 StringPair pair; 218 StringPair pair;
219 size_t point = source.find(delimiter); 219 size_t point = source.find(delimiter);
220 220
221 pair.first = source.substr(0, point); 221 pair.first = source.substr(0, point);
222 if (std::string::npos != point) 222 if (std::string::npos != point)
223 pair.second = source.substr(point + 1); 223 pair.second = source.substr(point + 1);
224 224
225 return pair; 225 return pair;
226 } 226 }
227 227
228 // TODO(palmer): Support both sha256 and sha1. This will require additional
229 // infrastructure code changes and can come in a later patch.
230 //
231 // static 228 // static
232 bool TransportSecurityState::ParsePin(const std::string& value, 229 bool TransportSecurityState::ParsePin(const std::string& value,
233 SHA1Fingerprint* out) { 230 HashValue* out) {
234 StringPair slash = Split(Strip(value), '/'); 231 StringPair slash = Split(Strip(value), '/');
235 if (slash.first != "sha1") 232
233 if (slash.first == "sha1")
234 out->tag = HASH_VALUE_SHA1;
235 else if (slash.first == "sha256")
236 out->tag = HASH_VALUE_SHA256;
237 else
236 return false; 238 return false;
237 239
238 std::string decoded; 240 std::string decoded;
239 if (!base::Base64Decode(slash.second, &decoded) || 241 if (!base::Base64Decode(slash.second, &decoded) ||
240 decoded.size() != arraysize(out->data)) { 242 decoded.size() != out->size()) {
241 return false; 243 return false;
242 } 244 }
243 245
244 memcpy(out->data, decoded.data(), arraysize(out->data)); 246 memcpy(out->data(), decoded.data(), out->size());
245 return true; 247 return true;
246 } 248 }
247 249
248 static bool ParseAndAppendPin(const std::string& value, 250 static bool ParseAndAppendPin(const std::string& value,
249 FingerprintVector* fingerprints) { 251 HashValueTag tag,
250 // The base64'd fingerprint MUST be a quoted-string. 20 bytes base64'd is 28 252 HashValueVector* hashes) {
251 // characters; 32 bytes base64'd is 44 characters. TODO(palmer): Support 253 std::string unquoted = HttpUtil::Unquote(value);
252 // SHA256. 254 std::string decoded;
253 size_t size = value.size(); 255
254 if (size != 30 || value[0] != '"' || value[size - 1] != '"') 256 // This code has to assume that 32 bytes is SHA-256 and 20 bytes is SHA-1.
257 // Currently, those are the only two possibilities, so the assumption is
258 // valid.
259 if (!base::Base64Decode(unquoted, &decoded))
255 return false; 260 return false;
256 261
257 std::string unquoted = HttpUtil::Unquote(value); 262 HashValue hash(tag);
258 std::string decoded; 263 if (decoded.size() != hash.size())
259 SHA1Fingerprint fp; 264 return false;
260 265
261 if (!base::Base64Decode(unquoted, &decoded) || 266 memcpy(hash.data(), decoded.data(), hash.size());
262 decoded.size() != arraysize(fp.data)) { 267 hashes->push_back(hash);
263 return false;
264 }
265
266 memcpy(fp.data, decoded.data(), arraysize(fp.data));
267 fingerprints->push_back(fp);
268 return true; 268 return true;
269 } 269 }
270 270
271 struct FingerprintsEqualPredicate { 271 struct HashValuesEqualPredicate {
272 explicit FingerprintsEqualPredicate(const SHA1Fingerprint& fingerprint) : 272 explicit HashValuesEqualPredicate(const HashValue& fingerprint) :
273 fingerprint_(fingerprint) {} 273 fingerprint_(fingerprint) {}
274 274
275 bool operator()(const SHA1Fingerprint& other) const { 275 bool operator()(const HashValue& other) const {
276 return fingerprint_.Equals(other); 276 return fingerprint_.Equals(other);
277 } 277 }
278 278
279 const SHA1Fingerprint& fingerprint_; 279 const HashValue& fingerprint_;
280 }; 280 };
281 281
282 // Returns true iff there is an item in |pins| which is not present in 282 // Returns true iff there is an item in |pins| which is not present in
283 // |from_cert_chain|. Such an SPKI hash is called a "backup pin". 283 // |from_cert_chain|. Such an SPKI hash is called a "backup pin".
284 static bool IsBackupPinPresent(const FingerprintVector& pins, 284 static bool IsBackupPinPresent(const HashValueVector& pins,
285 const FingerprintVector& from_cert_chain) { 285 const HashValueVector& from_cert_chain) {
286 for (FingerprintVector::const_iterator 286 for (HashValueVector::const_iterator
287 i = pins.begin(); i != pins.end(); ++i) { 287 i = pins.begin(); i != pins.end(); ++i) {
288 FingerprintVector::const_iterator j = 288 HashValueVector::const_iterator j =
289 std::find_if(from_cert_chain.begin(), from_cert_chain.end(), 289 std::find_if(from_cert_chain.begin(), from_cert_chain.end(),
290 FingerprintsEqualPredicate(*i)); 290 HashValuesEqualPredicate(*i));
291 if (j == from_cert_chain.end()) 291 if (j == from_cert_chain.end())
292 return true; 292 return true;
293 } 293 }
294 294
295 return false; 295 return false;
296 } 296 }
297 297
298 static bool HashesIntersect(const FingerprintVector& a, 298 // Returns true if the intersection of |a| and |b| is not empty. If either
299 const FingerprintVector& b) { 299 // |a| or |b| is empty, returns false.
300 for (FingerprintVector::const_iterator 300 static bool HashesIntersect(const HashValueVector& a,
301 i = a.begin(); i != a.end(); ++i) { 301 const HashValueVector& b) {
302 FingerprintVector::const_iterator j = 302 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
303 std::find_if(b.begin(), b.end(), FingerprintsEqualPredicate(*i)); 303 HashValueVector::const_iterator j =
304 if (j != b.end()) 304 std::find_if(b.begin(), b.end(), HashValuesEqualPredicate(*i));
305 return true; 305 if (j != b.end())
306 return true;
306 } 307 }
307 308
308 return false; 309 return false;
309 } 310 }
310 311
311 // Returns true iff |pins| contains both a live and a backup pin. A live pin 312 // Returns true iff |pins| contains both a live and a backup pin. A live pin
312 // is a pin whose SPKI is present in the certificate chain in |ssl_info|. A 313 // is a pin whose SPKI is present in the certificate chain in |ssl_info|. A
313 // backup pin is a pin intended for disaster recovery, not day-to-day use, and 314 // backup pin is a pin intended for disaster recovery, not day-to-day use, and
314 // thus must be absent from the certificate chain. The Public-Key-Pins header 315 // thus must be absent from the certificate chain. The Public-Key-Pins header
315 // specification requires both. 316 // specification requires both.
316 static bool IsPinListValid(const FingerprintVector& pins, 317 static bool IsPinListValid(const HashValueVector& pins,
317 const SSLInfo& ssl_info) { 318 const SSLInfo& ssl_info) {
319 // Fast fail: 1 live + 1 backup = at least 2 pins. (Check for actual
320 // liveness and backupness below.)
318 if (pins.size() < 2) 321 if (pins.size() < 2)
319 return false; 322 return false;
320 323
321 const FingerprintVector& from_cert_chain = ssl_info.public_key_hashes; 324 const HashValueVector& from_cert_chain = ssl_info.public_key_hashes;
322 if (from_cert_chain.empty()) 325 if (from_cert_chain.empty())
323 return false; 326 return false;
324 327
325 return IsBackupPinPresent(pins, from_cert_chain) && 328 return IsBackupPinPresent(pins, from_cert_chain) &&
326 HashesIntersect(pins, from_cert_chain); 329 HashesIntersect(pins, from_cert_chain);
327 } 330 }
328 331
329 // "Public-Key-Pins" ":" 332 // "Public-Key-Pins" ":"
330 // "max-age" "=" delta-seconds ";" 333 // "max-age" "=" delta-seconds ";"
331 // "pin-" algo "=" base64 [ ";" ... ] 334 // "pin-" algo "=" base64 [ ";" ... ]
332 bool TransportSecurityState::DomainState::ParsePinsHeader( 335 bool TransportSecurityState::DomainState::ParsePinsHeader(
333 const base::Time& now, 336 const base::Time& now,
334 const std::string& value, 337 const std::string& value,
335 const SSLInfo& ssl_info) { 338 const SSLInfo& ssl_info) {
336 bool parsed_max_age = false; 339 bool parsed_max_age = false;
337 int max_age_candidate = 0; 340 int max_age_candidate = 0;
338 FingerprintVector pins; 341 HashValueVector pins;
339 342
340 std::string source = value; 343 std::string source = value;
341 344
342 while (!source.empty()) { 345 while (!source.empty()) {
343 StringPair semicolon = Split(source, ';'); 346 StringPair semicolon = Split(source, ';');
344 semicolon.first = Strip(semicolon.first); 347 semicolon.first = Strip(semicolon.first);
345 semicolon.second = Strip(semicolon.second); 348 semicolon.second = Strip(semicolon.second);
346 StringPair equals = Split(semicolon.first, '='); 349 StringPair equals = Split(semicolon.first, '=');
347 equals.first = Strip(equals.first); 350 equals.first = Strip(equals.first);
348 equals.second = Strip(equals.second); 351 equals.second = Strip(equals.second);
349 352
350 if (LowerCaseEqualsASCII(equals.first, "max-age")) { 353 if (LowerCaseEqualsASCII(equals.first, "max-age")) {
351 if (equals.second.empty() || 354 if (equals.second.empty() ||
352 !MaxAgeToInt(equals.second.begin(), equals.second.end(), 355 !MaxAgeToInt(equals.second.begin(), equals.second.end(),
353 &max_age_candidate)) { 356 &max_age_candidate)) {
354 return false; 357 return false;
355 } 358 }
356 if (max_age_candidate > kMaxHSTSAgeSecs) 359 if (max_age_candidate > kMaxHSTSAgeSecs)
357 max_age_candidate = kMaxHSTSAgeSecs; 360 max_age_candidate = kMaxHSTSAgeSecs;
358 parsed_max_age = true; 361 parsed_max_age = true;
359 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) { 362 } else if (StartsWithASCII(equals.first, "pin-", false)) {
360 if (!ParseAndAppendPin(equals.second, &pins)) 363 HashValueTag tag;
364 if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) {
365 tag = HASH_VALUE_SHA1;
366 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) {
367 tag = HASH_VALUE_SHA256;
368 } else {
369 LOG(WARNING) << "Ignoring pin of unknown type: " << equals.first;
361 return false; 370 return false;
362 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) { 371 }
363 // TODO(palmer) 372 if (!ParseAndAppendPin(equals.second, tag, &pins))
373 return false;
364 } else { 374 } else {
365 // Silently ignore unknown directives for forward compatibility. 375 // Silently ignore unknown directives for forward compatibility.
366 } 376 }
367 377
368 source = semicolon.second; 378 source = semicolon.second;
369 } 379 }
370 380
371 if (!parsed_max_age || !IsPinListValid(pins, ssl_info)) 381 if (!parsed_max_age || !IsPinListValid(pins, ssl_info))
372 return false; 382 return false;
373 383
374 dynamic_spki_hashes_expiry = 384 dynamic_spki_hashes_expiry =
375 now + base::TimeDelta::FromSeconds(max_age_candidate); 385 now + base::TimeDelta::FromSeconds(max_age_candidate);
376 386
377 dynamic_spki_hashes.clear(); 387 dynamic_spki_hashes.clear();
378 if (max_age_candidate > 0) { 388 if (max_age_candidate > 0) {
379 for (FingerprintVector::const_iterator i = pins.begin(); 389 for (HashValueVector::const_iterator i = pins.begin();
380 i != pins.end(); ++i) { 390 i != pins.end(); ++i) {
381 dynamic_spki_hashes.push_back(*i); 391 dynamic_spki_hashes.push_back(*i);
382 } 392 }
383 } 393 }
384 394
385 return true; 395 return true;
386 } 396 }
387 397
388 // "Strict-Transport-Security" ":" 398 // "Strict-Transport-Security" ":"
389 // "max-age" "=" delta-seconds [ ";" "includeSubDomains" ] 399 // "max-age" "=" delta-seconds [ ";" "includeSubDomains" ]
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 include_subdomains = true; 486 include_subdomains = true;
477 upgrade_mode = MODE_FORCE_HTTPS; 487 upgrade_mode = MODE_FORCE_HTTPS;
478 return true; 488 return true;
479 default: 489 default:
480 NOTREACHED(); 490 NOTREACHED();
481 return false; 491 return false;
482 } 492 }
483 } 493 }
484 494
485 static bool AddHash(const std::string& type_and_base64, 495 static bool AddHash(const std::string& type_and_base64,
486 FingerprintVector* out) { 496 HashValueVector* out) {
487 SHA1Fingerprint hash; 497 HashValue hash;
488 498
489 if (!TransportSecurityState::ParsePin(type_and_base64, &hash)) 499 if (!TransportSecurityState::ParsePin(type_and_base64, &hash))
490 return false; 500 return false;
491 501
492 out->push_back(hash); 502 out->push_back(hash);
493 return true; 503 return true;
494 } 504 }
495 505
496 TransportSecurityState::~TransportSecurityState() {} 506 TransportSecurityState::~TransportSecurityState() {}
497 507
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 } 708 }
699 709
700 DCHECK(entry); 710 DCHECK(entry);
701 DCHECK(entry->pins.required_hashes); 711 DCHECK(entry->pins.required_hashes);
702 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); 712 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED);
703 713
704 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", 714 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain",
705 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); 715 entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
706 } 716 }
707 717
718 // static
719 const char* TransportSecurityState::HashValueLabel(
720 const HashValue& hash_value) {
721 switch (hash_value.tag) {
722 case HASH_VALUE_SHA1:
723 return "sha1/";
724 case HASH_VALUE_SHA256:
725 return "sha256/";
726 default:
727 NOTREACHED();
728 LOG(WARNING) << "Invalid fingerprint of unknown type " << hash_value.tag;
729 return "unknown/";
730 }
731 }
732
708 bool TransportSecurityState::GetStaticDomainState( 733 bool TransportSecurityState::GetStaticDomainState(
709 const std::string& canonicalized_host, 734 const std::string& canonicalized_host,
710 bool sni_enabled, 735 bool sni_enabled,
711 DomainState* out) { 736 DomainState* out) {
712 DCHECK(CalledOnValidThread()); 737 DCHECK(CalledOnValidThread());
713 738
714 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; 739 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS;
715 out->include_subdomains = false; 740 out->include_subdomains = false;
716 741
717 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 742 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
(...skipping 25 matching lines...) Expand all
743 const std::string& hashed_host, const DomainState& state) { 768 const std::string& hashed_host, const DomainState& state) {
744 enabled_hosts_[hashed_host] = state; 769 enabled_hosts_[hashed_host] = state;
745 } 770 }
746 771
747 void TransportSecurityState::AddOrUpdateForcedHosts( 772 void TransportSecurityState::AddOrUpdateForcedHosts(
748 const std::string& hashed_host, const DomainState& state) { 773 const std::string& hashed_host, const DomainState& state) {
749 forced_hosts_[hashed_host] = state; 774 forced_hosts_[hashed_host] = state;
750 } 775 }
751 776
752 static std::string HashesToBase64String( 777 static std::string HashesToBase64String(
753 const FingerprintVector& hashes) { 778 const HashValueVector& hashes) {
754 std::vector<std::string> hashes_strs; 779 std::vector<std::string> hashes_strs;
755 for (FingerprintVector::const_iterator 780 for (HashValueVector::const_iterator
756 i = hashes.begin(); i != hashes.end(); i++) { 781 i = hashes.begin(); i != hashes.end(); i++) {
757 std::string s; 782 std::string s;
758 const std::string hash_str(reinterpret_cast<const char*>(i->data), 783 const std::string hash_str(reinterpret_cast<const char*>(i->data()),
759 sizeof(i->data)); 784 i->size());
760 base::Base64Encode(hash_str, &s); 785 base::Base64Encode(hash_str, &s);
761 hashes_strs.push_back(s); 786 hashes_strs.push_back(s);
762 } 787 }
763 788
764 return JoinString(hashes_strs, ','); 789 return JoinString(hashes_strs, ',');
765 } 790 }
766 791
767 TransportSecurityState::DomainState::DomainState() 792 TransportSecurityState::DomainState::DomainState()
768 : upgrade_mode(MODE_FORCE_HTTPS), 793 : upgrade_mode(MODE_FORCE_HTTPS),
769 created(base::Time::Now()), 794 created(base::Time::Now()),
770 include_subdomains(false) { 795 include_subdomains(false) {
771 } 796 }
772 797
773 TransportSecurityState::DomainState::~DomainState() { 798 TransportSecurityState::DomainState::~DomainState() {
774 } 799 }
775 800
776 bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted( 801 bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted(
777 const FingerprintVector& hashes) const { 802 const HashValueVector& hashes) const {
803 // Validate that hashes is not empty. By the time this code is called (in
804 // production), that should never happen, but it's good to be defensive.
805 // And, hashes *can* be empty in some test scenarios.
806 if (hashes.empty()) {
807 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned "
808 "domain " << domain;
809 return false;
810 }
811
778 if (HashesIntersect(bad_static_spki_hashes, hashes)) { 812 if (HashesIntersect(bad_static_spki_hashes, hashes)) {
779 LOG(ERROR) << "Rejecting public key chain for domain " << domain 813 LOG(ERROR) << "Rejecting public key chain for domain " << domain
780 << ". Validated chain: " << HashesToBase64String(hashes) 814 << ". Validated chain: " << HashesToBase64String(hashes)
781 << ", matches one or more bad hashes: " 815 << ", matches one or more bad hashes: "
782 << HashesToBase64String(bad_static_spki_hashes); 816 << HashesToBase64String(bad_static_spki_hashes);
783 return false; 817 return false;
784 } 818 }
785 819
786 if (!(dynamic_spki_hashes.empty() && static_spki_hashes.empty()) && 820 // If there are no pins, then any valid chain is acceptable.
787 !HashesIntersect(dynamic_spki_hashes, hashes) && 821 if (dynamic_spki_hashes.empty() && static_spki_hashes.empty())
788 !HashesIntersect(static_spki_hashes, hashes)) { 822 return true;
789 LOG(ERROR) << "Rejecting public key chain for domain " << domain
790 << ". Validated chain: " << HashesToBase64String(hashes)
791 << ", expected: " << HashesToBase64String(dynamic_spki_hashes)
792 << " or: " << HashesToBase64String(static_spki_hashes);
793 823
794 return false; 824 if (HashesIntersect(dynamic_spki_hashes, hashes) ||
825 HashesIntersect(static_spki_hashes, hashes)) {
826 return true;
795 } 827 }
796 828
797 return true; 829 LOG(ERROR) << "Rejecting public key chain for domain " << domain
830 << ". Validated chain: " << HashesToBase64String(hashes)
831 << ", expected: " << HashesToBase64String(dynamic_spki_hashes)
832 << " or: " << HashesToBase64String(static_spki_hashes);
833 return false;
798 } 834 }
799 835
800 bool TransportSecurityState::DomainState::ShouldRedirectHTTPToHTTPS() const { 836 bool TransportSecurityState::DomainState::ShouldRedirectHTTPToHTTPS() const {
801 return upgrade_mode == MODE_FORCE_HTTPS; 837 return upgrade_mode == MODE_FORCE_HTTPS;
802 } 838 }
803 839
804 bool TransportSecurityState::DomainState::Equals( 840 bool TransportSecurityState::DomainState::Equals(
805 const DomainState& other) const { 841 const DomainState& other) const {
806 // TODO(palmer): Implement this 842 // TODO(palmer): Implement this
807 (void) other; 843 (void) other;
808 return true; 844 return true;
809 } 845 }
810 846
811 bool TransportSecurityState::DomainState::HasPins() const { 847 bool TransportSecurityState::DomainState::HasPins() const {
812 return static_spki_hashes.size() > 0 || 848 return static_spki_hashes.size() > 0 ||
813 bad_static_spki_hashes.size() > 0 || 849 bad_static_spki_hashes.size() > 0 ||
814 dynamic_spki_hashes.size() > 0; 850 dynamic_spki_hashes.size() > 0;
815 } 851 }
816 852
817 } // namespace 853 } // namespace
OLDNEW
« no previous file with comments | « net/base/transport_security_state.h ('k') | net/base/transport_security_state_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698