Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/cert/multi_threaded_cert_verifier.h" | 5 #include "net/cert/multi_threaded_cert_verifier.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 ++it) { | 110 ++it) { |
| 111 hashes->AppendString(it->ToString()); | 111 hashes->AppendString(it->ToString()); |
| 112 } | 112 } |
| 113 results->Set("public_key_hashes", std::move(hashes)); | 113 results->Set("public_key_hashes", std::move(hashes)); |
| 114 | 114 |
| 115 return std::move(results); | 115 return std::move(results); |
| 116 } | 116 } |
| 117 | 117 |
| 118 } // namespace | 118 } // namespace |
| 119 | 119 |
| 120 MultiThreadedCertVerifier::RequestParams::RequestParams( | |
| 121 const SHA1HashValue& cert_fingerprint_arg, | |
| 122 const SHA1HashValue& ca_fingerprint_arg, | |
| 123 const std::string& hostname_arg, | |
| 124 const std::string& ocsp_response_arg, | |
| 125 int flags_arg, | |
| 126 const CertificateList& additional_trust_anchors) | |
| 127 : hostname(hostname_arg), flags(flags_arg), start_time(base::Time::Now()) { | |
| 128 hash_values.reserve(3 + additional_trust_anchors.size()); | |
| 129 SHA1HashValue ocsp_hash; | |
| 130 base::SHA1HashBytes( | |
| 131 reinterpret_cast<const unsigned char*>(ocsp_response_arg.data()), | |
| 132 ocsp_response_arg.size(), ocsp_hash.data); | |
| 133 hash_values.push_back(ocsp_hash); | |
| 134 hash_values.push_back(cert_fingerprint_arg); | |
| 135 hash_values.push_back(ca_fingerprint_arg); | |
| 136 for (size_t i = 0; i < additional_trust_anchors.size(); ++i) | |
| 137 hash_values.push_back(additional_trust_anchors[i]->fingerprint()); | |
| 138 } | |
| 139 | |
| 140 MultiThreadedCertVerifier::RequestParams::RequestParams( | |
| 141 const RequestParams& other) = default; | |
| 142 | |
| 143 MultiThreadedCertVerifier::RequestParams::RequestParams( | |
| 144 const std::string& hostname_arg, | |
| 145 int flags_arg, | |
| 146 const std::vector<SHA1HashValue>& hash_values_arg, | |
| 147 const base::Time& start_time_arg) { | |
| 148 hostname = hostname_arg; | |
| 149 flags = flags_arg; | |
| 150 hash_values = std::move(hash_values_arg); | |
| 151 start_time = start_time_arg; | |
| 152 } | |
| 153 | |
| 154 MultiThreadedCertVerifier::RequestParams::~RequestParams() {} | |
| 155 | |
| 156 bool MultiThreadedCertVerifier::RequestParams::operator<( | |
| 157 const RequestParams& other) const { | |
| 158 // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, | |
| 159 // |hostname|, and |ocsp_response|, under assumption that integer comparisons | |
| 160 // are faster than memory and string comparisons. | |
| 161 if (flags != other.flags) | |
| 162 return flags < other.flags; | |
| 163 if (hostname != other.hostname) | |
| 164 return hostname < other.hostname; | |
| 165 return std::lexicographical_compare( | |
| 166 hash_values.begin(), hash_values.end(), other.hash_values.begin(), | |
| 167 other.hash_values.end(), SHA1HashValueLessThan()); | |
| 168 } | |
| 169 | |
| 120 MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} | 170 MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} |
| 121 | 171 |
| 172 MultiThreadedCertVerifier::CachedResult::CachedResult( | |
| 173 int error_arg, | |
| 174 CertVerifyResult result_arg) | |
| 175 : error(error_arg) { | |
| 176 result.CopyFrom(result_arg); | |
| 177 } | |
| 178 | |
| 122 MultiThreadedCertVerifier::CachedResult::~CachedResult() {} | 179 MultiThreadedCertVerifier::CachedResult::~CachedResult() {} |
| 123 | 180 |
| 124 MultiThreadedCertVerifier::CacheValidityPeriod::CacheValidityPeriod( | 181 MultiThreadedCertVerifier::CacheValidityPeriod::CacheValidityPeriod( |
| 125 const base::Time& now) | 182 const base::Time& now) |
| 126 : verification_time(now), | 183 : verification_time(now), |
| 127 expiration_time(now) { | 184 expiration_time(now) { |
| 128 } | 185 } |
| 129 | 186 |
| 130 MultiThreadedCertVerifier::CacheValidityPeriod::CacheValidityPeriod( | 187 MultiThreadedCertVerifier::CacheValidityPeriod::CacheValidityPeriod( |
| 131 const base::Time& now, | 188 const base::Time& now, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 162 // This algorithm is only problematic if the user consistently keeps | 219 // This algorithm is only problematic if the user consistently keeps |
| 163 // adjusting their clock backwards in increments smaller than the expiration | 220 // adjusting their clock backwards in increments smaller than the expiration |
| 164 // TTL, in which case, cached elements continue to be added. However, | 221 // TTL, in which case, cached elements continue to be added. However, |
| 165 // because the cache has a fixed upper bound, if no entries are expired, a | 222 // because the cache has a fixed upper bound, if no entries are expired, a |
| 166 // 'random' entry will be, thus keeping the memory constraints bounded over | 223 // 'random' entry will be, thus keeping the memory constraints bounded over |
| 167 // time. | 224 // time. |
| 168 return now.verification_time >= expiration.verification_time && | 225 return now.verification_time >= expiration.verification_time && |
| 169 now.verification_time < expiration.expiration_time; | 226 now.verification_time < expiration.expiration_time; |
| 170 }; | 227 }; |
| 171 | 228 |
| 229 MultiThreadedCertVerifier::Iterator::Iterator( | |
| 230 const MultiThreadedCertVerifier& verifier) | |
| 231 : iterator_(verifier.cache_) {} | |
| 232 | |
| 233 MultiThreadedCertVerifier::Iterator::~Iterator() {} | |
| 234 | |
| 172 // Represents the output and result callback of a request. The | 235 // Represents the output and result callback of a request. The |
| 173 // CertVerifierRequest is owned by the caller that initiated the call to | 236 // CertVerifierRequest is owned by the caller that initiated the call to |
| 174 // CertVerifier::Verify(). | 237 // CertVerifier::Verify(). |
| 175 class CertVerifierRequest : public base::LinkNode<CertVerifierRequest>, | 238 class CertVerifierRequest : public base::LinkNode<CertVerifierRequest>, |
| 176 public CertVerifier::Request { | 239 public CertVerifier::Request { |
| 177 public: | 240 public: |
| 178 CertVerifierRequest(CertVerifierJob* job, | 241 CertVerifierRequest(CertVerifierJob* job, |
| 179 const CompletionCallback& callback, | 242 const CompletionCallback& callback, |
| 180 CertVerifyResult* verify_result, | 243 CertVerifyResult* verify_result, |
| 181 const BoundNetLog& net_log) | 244 const BoundNetLog& net_log) |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 std::unique_ptr<CertVerifierRequest> request = | 539 std::unique_ptr<CertVerifierRequest> request = |
| 477 job->CreateRequest(callback, verify_result, net_log); | 540 job->CreateRequest(callback, verify_result, net_log); |
| 478 *out_req = std::move(request); | 541 *out_req = std::move(request); |
| 479 return ERR_IO_PENDING; | 542 return ERR_IO_PENDING; |
| 480 } | 543 } |
| 481 | 544 |
| 482 bool MultiThreadedCertVerifier::SupportsOCSPStapling() { | 545 bool MultiThreadedCertVerifier::SupportsOCSPStapling() { |
| 483 return verify_proc_->SupportsOCSPStapling(); | 546 return verify_proc_->SupportsOCSPStapling(); |
| 484 } | 547 } |
| 485 | 548 |
| 486 MultiThreadedCertVerifier::RequestParams::RequestParams( | 549 bool MultiThreadedCertVerifier::AddCertResult( |
| 487 const SHA1HashValue& cert_fingerprint_arg, | 550 const std::string& hostname, |
| 488 const SHA1HashValue& ca_fingerprint_arg, | 551 int flags, |
| 489 const std::string& hostname_arg, | 552 const std::vector<SHA1HashValue>& hash_values, |
| 490 const std::string& ocsp_response_arg, | 553 const base::Time& start_time, |
| 491 int flags_arg, | 554 int error, |
| 492 const CertificateList& additional_trust_anchors) | 555 const CertVerifyResult& result, |
| 493 : hostname(hostname_arg), flags(flags_arg), start_time(base::Time::Now()) { | 556 const base::Time& verification_time, |
| 494 hash_values.reserve(3 + additional_trust_anchors.size()); | 557 const base::Time& expiration_time) { |
| 495 SHA1HashValue ocsp_hash; | 558 base::Time now = base::Time::Now(); |
| 496 base::SHA1HashBytes( | 559 if (hostname.empty() || hash_values.size() == 0 || |
|
Ryan Sleevi
2016/05/13 20:18:12
.empty()
| |
| 497 reinterpret_cast<const unsigned char*>(ocsp_response_arg.data()), | 560 start_time != verification_time || start_time >= now || |
| 498 ocsp_response_arg.size(), ocsp_hash.data); | 561 expiration_time <= now || |
| 499 hash_values.push_back(ocsp_hash); | 562 (expiration_time != |
| 500 hash_values.push_back(cert_fingerprint_arg); | 563 start_time + base::TimeDelta::FromSeconds(kTTLSecs))) { |
| 501 hash_values.push_back(ca_fingerprint_arg); | 564 DVLOG(1) << "Invalid data for: " << hostname; |
|
Ryan Sleevi
2016/05/13 20:18:13
Why DVLOG? Is it a programmer error? If so, why no
| |
| 502 for (size_t i = 0; i < additional_trust_anchors.size(); ++i) | 565 return false; |
| 503 hash_values.push_back(additional_trust_anchors[i]->fingerprint()); | 566 } |
| 504 } | |
| 505 | 567 |
| 506 MultiThreadedCertVerifier::RequestParams::RequestParams( | 568 // If cache is already full, then don't replace the current entries. |
| 507 const RequestParams& other) = default; | 569 if (cache_.size() >= kMaxCacheEntries) { |
| 570 DVLOG(1) << "Cache is full"; | |
|
Ryan Sleevi
2016/05/13 20:18:12
Necessary?
| |
| 571 return false; | |
| 572 } | |
| 508 | 573 |
| 509 MultiThreadedCertVerifier::RequestParams::~RequestParams() {} | 574 // Don't overwrite existing entry. |
| 575 RequestParams key(hostname, flags, hash_values, start_time); | |
| 576 CacheValidityPeriod expiration(now); | |
| 577 if (cache_.Get(key, expiration)) { | |
| 578 DVLOG(1) << "Already exists in the cache for " << key.hostname; | |
|
Ryan Sleevi
2016/05/13 20:18:13
Necessary?
| |
| 579 return false; | |
| 580 } | |
| 510 | 581 |
| 511 bool MultiThreadedCertVerifier::RequestParams::operator<( | 582 // Add a new entry. |
| 512 const RequestParams& other) const { | 583 CachedResult value(error, result); |
| 513 // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, | 584 cache_.Put(key, value, CacheValidityPeriod(verification_time), |
| 514 // |hostname|, and |ocsp_response|, under assumption that integer comparisons | 585 CacheValidityPeriod(verification_time, expiration_time)); |
| 515 // are faster than memory and string comparisons. | 586 return true; |
| 516 if (flags != other.flags) | |
| 517 return flags < other.flags; | |
| 518 if (hostname != other.hostname) | |
| 519 return hostname < other.hostname; | |
| 520 return std::lexicographical_compare( | |
| 521 hash_values.begin(), hash_values.end(), other.hash_values.begin(), | |
| 522 other.hash_values.end(), SHA1HashValueLessThan()); | |
| 523 } | 587 } |
| 524 | 588 |
| 525 bool MultiThreadedCertVerifier::JobComparator::operator()( | 589 bool MultiThreadedCertVerifier::JobComparator::operator()( |
| 526 const CertVerifierJob* job1, | 590 const CertVerifierJob* job1, |
| 527 const CertVerifierJob* job2) const { | 591 const CertVerifierJob* job2) const { |
| 528 return job1->key() < job2->key(); | 592 return job1->key() < job2->key(); |
| 529 } | 593 } |
| 530 | 594 |
| 531 void MultiThreadedCertVerifier::SaveResultToCache(const RequestParams& key, | 595 void MultiThreadedCertVerifier::SaveResultToCache(const RequestParams& key, |
| 532 const CachedResult& result) { | 596 const CachedResult& result) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 // The JobSet is kept in sorted order so items can be found using binary | 654 // The JobSet is kept in sorted order so items can be found using binary |
| 591 // search. | 655 // search. |
| 592 auto it = std::lower_bound(inflight_.begin(), inflight_.end(), key, | 656 auto it = std::lower_bound(inflight_.begin(), inflight_.end(), key, |
| 593 JobToRequestParamsComparator()); | 657 JobToRequestParamsComparator()); |
| 594 if (it != inflight_.end() && !(key < (*it)->key())) | 658 if (it != inflight_.end() && !(key < (*it)->key())) |
| 595 return *it; | 659 return *it; |
| 596 return nullptr; | 660 return nullptr; |
| 597 } | 661 } |
| 598 | 662 |
| 599 } // namespace net | 663 } // namespace net |
| OLD | NEW |