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

Side by Side Diff: components/certificate_transparency/single_tree_tracker.cc

Issue 2017563002: Add Certificate Transparency logs auditing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove templated function from tests Created 3 years, 11 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "components/certificate_transparency/single_tree_tracker.h" 5 #include "components/certificate_transparency/single_tree_tracker.h"
6 6
7 #include <algorithm>
8 #include <iterator>
9 #include <list>
7 #include <utility> 10 #include <utility>
8 11
12 #include "base/bind.h"
9 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "components/certificate_transparency/log_dns_client.h"
15 #include "crypto/sha2.h"
16 #include "net/base/hash_value.h"
17 #include "net/base/net_errors.h"
10 #include "net/cert/ct_log_verifier.h" 18 #include "net/cert/ct_log_verifier.h"
19 #include "net/cert/merkle_audit_proof.h"
20 #include "net/cert/merkle_tree_leaf.h"
11 #include "net/cert/signed_certificate_timestamp.h" 21 #include "net/cert/signed_certificate_timestamp.h"
12 #include "net/cert/x509_certificate.h" 22 #include "net/cert/x509_certificate.h"
13 23
24 using net::SHA256HashValue;
25 using net::ct::LogEntry;
26 using net::ct::MerkleAuditProof;
27 using net::ct::MerkleTreeLeaf;
28 using net::ct::SignedCertificateTimestamp;
14 using net::ct::SignedTreeHead; 29 using net::ct::SignedTreeHead;
15 30
31 // Overview of the process for auditing CT log entries
32 //
33 // A CT log entry, represented by net::ct::LogEntry, is made up of the
34 // end-entity certificate and the Signed Certificate Timestamp associated with
35 // it.
36 //
37 // In this file, obsered CT log entries are audited for inclusion in the CT log.
38 // A pre-requirement for auditing a log entry is having a Signed Tree Head (STH)
39 // from that log that is 24 hours (MMD period) after the timestamp in the SCT.
40 // Log entries observed while the client has no STH from that log or an STH that
41 // is too old start in the PENDING_NEWER_STH state.
42 //
43 // Once a fresh-enough STH is obtained, all entries that can be audited using
44 // this STH move to the PENDING_INCLUSION_PROOF_REQUEST state.
45 //
46 // Requests for the entry index and inclusion proof are obtained using a
47 // LogDnsClient instance - when an inclusion proof for an entry has been
48 // successfully requested (e.g. it has not been throttled), it moves to the
49 // INCLUSION_PROOF_REQUESTED state.
50 //
51 // Once the inclusion check is done, the entry is removed from
52 // |pending_entries_|. If the inclusion check has been successful, the entry
53 // is added to |checked_entries_|.
54
55 namespace certificate_transparency {
56
16 namespace { 57 namespace {
17 58
18 // Enum indicating whether an SCT can be checked for inclusion and if not, 59 // Enum indicating whether an SCT can be checked for inclusion and if not,
19 // the reason it cannot. 60 // the reason it cannot.
20 // 61 //
21 // Note: The numeric values are used within a histogram and should not change 62 // Note: The numeric values are used within a histogram and should not change
22 // or be re-assigned. 63 // or be re-assigned.
23 enum SCTCanBeCheckedForInclusion { 64 enum SCTCanBeCheckedForInclusion {
24 // If the SingleTreeTracker does not have a valid STH, then a valid STH is 65 // If the SingleTreeTracker does not have a valid STH, then a valid STH is
25 // first required to evaluate whether the SCT can be checked for inclusion 66 // first required to evaluate whether the SCT can be checked for inclusion
26 // or not. 67 // or not.
27 VALID_STH_REQUIRED = 0, 68 VALID_STH_REQUIRED = 0,
69
28 // If the STH does not cover the SCT (the timestamp in the SCT is greater than 70 // If the STH does not cover the SCT (the timestamp in the SCT is greater than
29 // MMD + timestamp in the STH), then a newer STH is needed. 71 // MMD + timestamp in the STH), then a newer STH is needed.
30 NEWER_STH_REQUIRED = 1, 72 NEWER_STH_REQUIRED = 1,
73
31 // When an SCT is observed, if the SingleTreeTracker instance has a valid STH 74 // When an SCT is observed, if the SingleTreeTracker instance has a valid STH
32 // and the STH covers the SCT (the timestamp in the SCT is less than MMD + 75 // and the STH covers the SCT (the timestamp in the SCT is less than MMD +
33 // timestamp in the STH), then it can be checked for inclusion. 76 // timestamp in the STH), then it can be checked for inclusion.
34 CAN_BE_CHECKED = 2, 77 CAN_BE_CHECKED = 2,
78
79 // This SCT was not audited because the queue of pending entries was
80 // full.
81 NOT_AUDITED_QUEUE_FULL = 3,
82
35 SCT_CAN_BE_CHECKED_MAX 83 SCT_CAN_BE_CHECKED_MAX
36 }; 84 };
37 85
38 // Measure how often clients encounter very new SCTs, by measuring whether an 86 // Measure how often clients encounter very new SCTs, by measuring whether an
39 // SCT can be checked for inclusion upon first observation. 87 // SCT can be checked for inclusion upon first observation.
40 void LogCanBeCheckedForInclusionToUMA( 88 void LogCanBeCheckedForInclusionToUMA(
41 SCTCanBeCheckedForInclusion can_be_checked) { 89 SCTCanBeCheckedForInclusion can_be_checked) {
42 UMA_HISTOGRAM_ENUMERATION("Net.CertificateTransparency.CanInclusionCheckSCT", 90 UMA_HISTOGRAM_ENUMERATION("Net.CertificateTransparency.CanInclusionCheckSCT",
43 can_be_checked, SCT_CAN_BE_CHECKED_MAX); 91 can_be_checked, SCT_CAN_BE_CHECKED_MAX);
44 } 92 }
45 93
94 // Enum indicating the outcome of an inclusion check for a particular log
95 // entry.
96 //
97 // Note: The numeric values are used within a histogram and should not change
98 // or be re-assigned.
99 enum LogEntryInclusionCheckResult {
100 // Inclusion check succeeded: Proof obtained and validated successfully.
101 GOT_VALID_INCLUSION_PROOF = 0,
102
103 // Could not get an inclusion proof.
104 FAILED_GETTING_INCLUSION_PROOF = 1,
105
106 // An inclusion proof was obtained but it is invalid.
107 GOT_INVALID_INCLUSION_PROOF = 2,
108
109 // The SCT could not be audited because the client's DNS configuration
110 // is faulty.
111 DNS_QUERY_NOT_POSSIBLE = 3,
112
113 LOG_ENTRY_INCLUSION_CHECK_RESULT_MAX
114 };
115
116 void LogInclusionCheckResult(LogEntryInclusionCheckResult result) {
117 UMA_HISTOGRAM_ENUMERATION("Net.CertificateTransparency.InclusionCheckResult",
118 result, LOG_ENTRY_INCLUSION_CHECK_RESULT_MAX);
119 }
120
121 // Calculate the leaf hash of the the entry in the log represented by
122 // the given |cert| and |sct|. If leaf hash calculation succeeds returns
123 // true, false otherwise.
124 bool GetLogEntryLeafHash(const net::X509Certificate* cert,
125 const SignedCertificateTimestamp* sct,
126 SHA256HashValue* leaf_hash) {
127 MerkleTreeLeaf leaf;
128 if (!GetMerkleTreeLeaf(cert, sct, &leaf))
129 return false;
130
131 std::string leaf_hash_str;
132 if (!HashMerkleTreeLeaf(leaf, &leaf_hash_str))
133 return false;
134
135 memcpy(leaf_hash->data, leaf_hash_str.data(), crypto::kSHA256Length);
136 return true;
137 }
138
139 // Audit state of a log entry.
140 enum AuditState {
141 // Entry cannot be audited because a newer STH is needed.
142 PENDING_NEWER_STH,
143 // A leaf index has been obtained and the entry is now pending request
144 // of an inclusion proof.
145 PENDING_INCLUSION_PROOF_REQUEST,
146 // An inclusion proof for this entry has been requested from the log.
147 INCLUSION_PROOF_REQUESTED
148 };
149
150 // Maximal size of the checked entries cache.
151 size_t kCheckedEntriesCacheSize = 100;
152
153 // Maximal size of the pending entries queue.
154 size_t kPendingEntriesQueueSize = 100;
155
156 // Maximum Merge Delay - logs can have individual MMD, but all known logs
157 // currently have 24 hours MMD and Chrome's CT policy requires an MMD
158 // that's no greater than that. For simplicity, use 24 hours for all logs.
159 constexpr base::TimeDelta kMaximumMergeDelay = base::TimeDelta::FromHours(24);
160
161 // The log MUST incorporate the a certificate in the tree within the Maximum
162 // Merge Delay, so an entry can be audited once the timestamp from the SCT +
163 // MMD has passed.
164 // Returns true if the timestamp from the STH is newer than SCT timestamp + MMD.
165 bool IsSCTReadyForAudit(base::Time sth_timestamp, base::Time sct_timestamp) {
166 return sct_timestamp + kMaximumMergeDelay < sth_timestamp;
167 }
168
46 } // namespace 169 } // namespace
47 170
48 namespace certificate_transparency { 171 // The entry that is being audited.
172 struct SingleTreeTracker::EntryToAudit {
173 base::Time sct_timestamp;
174 SHA256HashValue leaf_hash;
175
176 explicit EntryToAudit(base::Time timestamp) : sct_timestamp(timestamp) {}
177 };
178
179 // State of a log entry: its audit state and information necessary to
180 // validate an inclusion proof. Gets updated as the entry transitions
181 // between the different audit states.
182 struct SingleTreeTracker::EntryAuditState {
183 // Current phase of inclusion check.
184 AuditState state;
185
186 // The proof to be filled in by the LogDnsClient
187 MerkleAuditProof proof;
188
189 // The root hash of the tree for which an inclusion proof was requested.
190 // The root hash is needed after the inclusion proof is fetched for validating
191 // the inclusion proof (each inclusion proof is valid for one particular leaf,
192 // denoted by the leaf index, in exactly one particular tree, denoted by the
193 // tree size in the proof).
194 // To avoid having to re-fetch the inclusion proof if a newer STH is provided
195 // to the SingleTreeTracker, the size of the original tree for which the
196 // inclusion proof was requested is stored in |proof| and the root hash
197 // in |root_hash|.
198 std::string root_hash;
199
200 explicit EntryAuditState(AuditState state) : state(state) {}
201 };
202
203 // Orders entries by the SCT timestamp. In case of tie, which is very unlikely
204 // as it requires two SCTs issued from a log at exactly the same time, order
205 // by leaf hash.
206 bool SingleTreeTracker::OrderByTimestamp::operator()(
207 const EntryToAudit& lhs,
208 const EntryToAudit& rhs) const {
209 if (lhs.sct_timestamp != rhs.sct_timestamp)
210 return lhs.sct_timestamp < rhs.sct_timestamp;
211
212 return net::SHA256HashValueLessThan()(lhs.leaf_hash, rhs.leaf_hash);
213 }
49 214
50 SingleTreeTracker::SingleTreeTracker( 215 SingleTreeTracker::SingleTreeTracker(
51 scoped_refptr<const net::CTLogVerifier> ct_log) 216 scoped_refptr<const net::CTLogVerifier> ct_log,
52 : ct_log_(std::move(ct_log)) {} 217 LogDnsClient* dns_client)
218 : ct_log_(std::move(ct_log)),
219 checked_entries_(kCheckedEntriesCacheSize),
220 dns_client_(dns_client),
221 weak_factory_(this) {
222 memory_pressure_listener_.reset(new base::MemoryPressureListener(base::Bind(
223 &SingleTreeTracker::OnMemoryPressure, base::Unretained(this))));
224 }
53 225
54 SingleTreeTracker::~SingleTreeTracker() {} 226 SingleTreeTracker::~SingleTreeTracker() {}
55 227
56 void SingleTreeTracker::OnSCTVerified( 228 void SingleTreeTracker::OnSCTVerified(net::X509Certificate* cert,
57 net::X509Certificate* cert, 229 const SignedCertificateTimestamp* sct) {
58 const net::ct::SignedCertificateTimestamp* sct) {
59 DCHECK_EQ(ct_log_->key_id(), sct->log_id); 230 DCHECK_EQ(ct_log_->key_id(), sct->log_id);
60 231
61 // SCT was previously observed, so its status should not be changed. 232 EntryToAudit entry(sct->timestamp);
62 if (entries_status_.find(sct->timestamp) != entries_status_.end()) 233 if (!GetLogEntryLeafHash(cert, sct, &entry.leaf_hash))
63 return; 234 return;
64 235
236 // Avoid queueing multiple instances of the same entry.
237 if (GetAuditedEntryInclusionStatus(entry) != SCT_NOT_OBSERVED)
238 return;
239
240 if (pending_entries_.size() >= kPendingEntriesQueueSize) {
241 // Queue is full - cannot audit SCT.
242 LogCanBeCheckedForInclusionToUMA(NOT_AUDITED_QUEUE_FULL);
243 return;
244 }
245
65 // If there isn't a valid STH or the STH is not fresh enough to check 246 // If there isn't a valid STH or the STH is not fresh enough to check
66 // inclusion against, store the SCT for future checking and return. 247 // inclusion against, store the SCT for future checking and return.
67 if (verified_sth_.timestamp.is_null() || 248 if (verified_sth_.timestamp.is_null() ||
68 (verified_sth_.timestamp < 249 !IsSCTReadyForAudit(verified_sth_.timestamp, entry.sct_timestamp)) {
69 (sct->timestamp + base::TimeDelta::FromHours(24)))) { 250 pending_entries_.insert(
70 entries_status_.insert( 251 std::make_pair(std::move(entry), EntryAuditState(PENDING_NEWER_STH)));
71 std::make_pair(sct->timestamp, SCT_PENDING_NEWER_STH));
72 252
73 if (!verified_sth_.timestamp.is_null()) { 253 if (verified_sth_.timestamp.is_null()) {
254 LogCanBeCheckedForInclusionToUMA(VALID_STH_REQUIRED);
255 } else {
74 LogCanBeCheckedForInclusionToUMA(NEWER_STH_REQUIRED); 256 LogCanBeCheckedForInclusionToUMA(NEWER_STH_REQUIRED);
75 } else {
76 LogCanBeCheckedForInclusionToUMA(VALID_STH_REQUIRED);
77 } 257 }
78 258
79 return; 259 return;
80 } 260 }
81 261
82 LogCanBeCheckedForInclusionToUMA(CAN_BE_CHECKED); 262 LogCanBeCheckedForInclusionToUMA(CAN_BE_CHECKED);
83 // TODO(eranm): Check inclusion here. 263 pending_entries_.insert(std::make_pair(
84 entries_status_.insert( 264 std::move(entry), EntryAuditState(PENDING_INCLUSION_PROOF_REQUEST)));
85 std::make_pair(sct->timestamp, SCT_PENDING_INCLUSION_CHECK)); 265
266 ProcessPendingEntries();
86 } 267 }
87 268
88 void SingleTreeTracker::NewSTHObserved(const SignedTreeHead& sth) { 269 void SingleTreeTracker::NewSTHObserved(const SignedTreeHead& sth) {
89 DCHECK_EQ(ct_log_->key_id(), sth.log_id); 270 DCHECK_EQ(ct_log_->key_id(), sth.log_id);
90 271
91 if (!ct_log_->VerifySignedTreeHead(sth)) { 272 if (!ct_log_->VerifySignedTreeHead(sth)) {
92 // Sanity check the STH; the caller should have done this 273 // Sanity check the STH; the caller should have done this
93 // already, but being paranoid here. 274 // already, but being paranoid here.
94 // NOTE(eranm): Right now there's no way to get rid of this check here 275 // NOTE(eranm): Right now there's no way to get rid of this check here
95 // as this is the first object in the chain that has an instance of 276 // as this is the first object in the chain that has an instance of
96 // a CTLogVerifier to verify the STH. 277 // a CTLogVerifier to verify the STH.
97 return; 278 return;
98 } 279 }
99 280
100 // In order to avoid updating |verified_sth_| to an older STH in case 281 // In order to avoid updating |verified_sth_| to an older STH in case
101 // an older STH is observed, check that either the observed STH is for 282 // an older STH is observed, check that either the observed STH is for
102 // a larger tree size or that it is for the same tree size but has 283 // a larger tree size or that it is for the same tree size but has
103 // a newer timestamp. 284 // a newer timestamp.
104 const bool sths_for_same_tree = verified_sth_.tree_size == sth.tree_size; 285 const bool sths_for_same_tree = verified_sth_.tree_size == sth.tree_size;
105 const bool received_sth_is_for_larger_tree = 286 const bool received_sth_is_for_larger_tree =
106 (verified_sth_.tree_size > sth.tree_size); 287 (verified_sth_.tree_size < sth.tree_size);
107 const bool received_sth_is_newer = (sth.timestamp > verified_sth_.timestamp); 288 const bool received_sth_is_newer = (sth.timestamp > verified_sth_.timestamp);
108 289
109 if (verified_sth_.timestamp.is_null() || received_sth_is_for_larger_tree || 290 if (!verified_sth_.timestamp.is_null() && !received_sth_is_for_larger_tree &&
110 (sths_for_same_tree && received_sth_is_newer)) { 291 !(sths_for_same_tree && received_sth_is_newer)) {
111 verified_sth_ = sth; 292 // Observed an old STH - do nothing.
293 return;
112 } 294 }
113 295
114 // Find out which SCTs can now be checked for inclusion. 296 verified_sth_ = sth;
115 // TODO(eranm): Keep two maps of MerkleTreeLeaf instances, one for leaves 297
116 // pending inclusion checks and one for leaves pending a new STH. 298 // Find the first entry in the PENDING_NEWER_STH state - entries
117 // The comparison function between MerkleTreeLeaf instances should use the 299 // before that should be pending leaf index / inclusion proof, no
118 // timestamp to determine sorting order, so that bulk moving from one 300 // reason to inspect them.
119 // map to the other can happen. 301 auto auditable_entries_begin = std::find_if(
120 auto entry = entries_status_.begin(); 302 pending_entries_.begin(), pending_entries_.end(),
121 while (entry != entries_status_.end() && 303 [](std::pair<const EntryToAudit&, const EntryAuditState&> value) {
122 entry->first < verified_sth_.timestamp) { 304 return value.second.state == PENDING_NEWER_STH;
123 entry->second = SCT_PENDING_INCLUSION_CHECK; 305 });
124 ++entry; 306
125 // TODO(eranm): Check inclusion here. 307 // Find where to stop - this is the first entry whose timestamp + MMD
308 // is greater than the STH's timestamp.
309 auto auditable_entries_end = std::lower_bound(
310 auditable_entries_begin, pending_entries_.end(), sth.timestamp,
311 [](std::pair<const EntryToAudit&, const EntryAuditState&> value,
312 base::Time sth_timestamp) {
313 return IsSCTReadyForAudit(sth_timestamp, value.first.sct_timestamp);
314 });
315
316 // Update the state of all entries that can now be checked for inclusion.
317 for (auto curr_entry = auditable_entries_begin;
318 curr_entry != auditable_entries_end; ++curr_entry) {
319 DCHECK_EQ(curr_entry->second.state, PENDING_NEWER_STH);
320 curr_entry->second.state = PENDING_INCLUSION_PROOF_REQUEST;
321 }
322
323 if (auditable_entries_begin != auditable_entries_end) {
Ryan Sleevi 2017/01/23 17:37:31 nit: (only because you mentioned it's not your def
Eran Messeri 2017/01/23 20:51:57 Done.
324 ProcessPendingEntries();
126 } 325 }
127 } 326 }
128 327
129 SingleTreeTracker::SCTInclusionStatus 328 SingleTreeTracker::SCTInclusionStatus
130 SingleTreeTracker::GetLogEntryInclusionStatus( 329 SingleTreeTracker::GetLogEntryInclusionStatus(
131 net::X509Certificate* cert, 330 net::X509Certificate* cert,
132 const net::ct::SignedCertificateTimestamp* sct) { 331 const SignedCertificateTimestamp* sct) {
133 auto it = entries_status_.find(sct->timestamp); 332 EntryToAudit entry(sct->timestamp);
333 if (!GetLogEntryLeafHash(cert, sct, &entry.leaf_hash))
334 return SCT_NOT_OBSERVED;
335 return GetAuditedEntryInclusionStatus(entry);
336 }
134 337
135 return it == entries_status_.end() ? SCT_NOT_OBSERVED : it->second; 338 void SingleTreeTracker::ProcessPendingEntries() {
339 for (auto it = pending_entries_.begin(); it != pending_entries_.end(); ++it) {
340 if (it->second.state != PENDING_INCLUSION_PROOF_REQUEST) {
341 continue;
342 }
343
344 it->second.root_hash =
345 std::string(verified_sth_.sha256_root_hash, crypto::kSHA256Length);
346
347 std::string leaf_hash(
348 reinterpret_cast<const char*>(it->first.leaf_hash.data),
349 crypto::kSHA256Length);
350 net::Error result = dns_client_->QueryAuditProof(
351 ct_log_->dns_domain(), leaf_hash, verified_sth_.tree_size,
352 &(it->second.proof),
353 base::Bind(&SingleTreeTracker::OnAuditProofObtained,
354 weak_factory_.GetWeakPtr(), it->first));
355 // Handling proofs returned synchronously is not implemeted.
356 DCHECK_NE(result, net::OK);
357 if (result == net::ERR_IO_PENDING) {
358 // Successfully requested an inclusion proof - change entry state
359 // and continue to the next one.
360 it->second.state = INCLUSION_PROOF_REQUESTED;
361 } else if (result == net::ERR_TEMPORARILY_THROTTLED) {
362 dns_client_->NotifyWhenNotThrottled(
363 base::Bind(&SingleTreeTracker::ProcessPendingEntries,
364 weak_factory_.GetWeakPtr()));
365 // Exit the loop since all subsequent calls to QueryAuditProof
366 // will be throttled.
367 break;
368 } else if (result == net::ERR_NAME_RESOLUTION_FAILED) {
369 LogInclusionCheckResult(DNS_QUERY_NOT_POSSIBLE);
370 // Lookup failed due to bad DNS configuration, erase the entry and
371 // continue to the next one.
372 it = pending_entries_.erase(it);
373 // Break here if it's the last entry to avoid |it| being incremented
374 // by the for loop.
375 if (it == pending_entries_.end())
376 break;
377 } else {
378 // BUG: an invalid argument was provided or an unexpected error
379 // was returned from LogDnsClient.
380 DCHECK_EQ(result, net::ERR_INVALID_ARGUMENT);
381 NOTREACHED();
382 }
383 }
384 }
385
386 SingleTreeTracker::SCTInclusionStatus
387 SingleTreeTracker::GetAuditedEntryInclusionStatus(const EntryToAudit& entry) {
388 const auto checked_entries_iterator = checked_entries_.Get(entry.leaf_hash);
389 if (checked_entries_iterator != checked_entries_.end()) {
390 return SCT_INCLUDED_IN_LOG;
391 }
392
393 auto pending_iterator = pending_entries_.find(entry);
394 if (pending_iterator == pending_entries_.end()) {
395 return SCT_NOT_OBSERVED;
396 }
397
398 switch (pending_iterator->second.state) {
399 case PENDING_NEWER_STH:
400 return SCT_PENDING_NEWER_STH;
401 case PENDING_INCLUSION_PROOF_REQUEST:
402 case INCLUSION_PROOF_REQUESTED:
403 return SCT_PENDING_INCLUSION_CHECK;
404 }
405
406 NOTREACHED();
407 return SCT_NOT_OBSERVED;
408 }
409
410 void SingleTreeTracker::OnAuditProofObtained(const EntryToAudit& entry,
411 int net_error) {
412 auto it = pending_entries_.find(entry);
413 // The entry may not be present if it was evacuated due to low memory
414 // pressure.
415 if (it == pending_entries_.end())
416 return;
417
418 DCHECK_EQ(it->second.state, INCLUSION_PROOF_REQUESTED);
419
420 if (net_error != net::OK) {
421 // XXX(eranm): Should failures be cached? For now, they are not.
422 LogInclusionCheckResult(FAILED_GETTING_INCLUSION_PROOF);
423 pending_entries_.erase(it);
424 return;
425 }
426
427 std::string leaf_hash(reinterpret_cast<const char*>(entry.leaf_hash.data),
428 crypto::kSHA256Length);
429
430 bool verified = ct_log_->VerifyAuditProof(it->second.proof,
431 it->second.root_hash, leaf_hash);
432
433 if (!verified) {
434 LogInclusionCheckResult(GOT_INVALID_INCLUSION_PROOF);
435 } else {
436 LogInclusionCheckResult(GOT_VALID_INCLUSION_PROOF);
437 checked_entries_.Put(entry.leaf_hash, EntryAuditResult());
438 }
439
440 pending_entries_.erase(it);
441 }
442
443 void SingleTreeTracker::OnMemoryPressure(
444 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
445 switch (memory_pressure_level) {
446 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
447 break;
448 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
449 pending_entries_.clear();
450 // Fall through to clearing the other cache.
451 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
452 checked_entries_.Clear();
453 break;
454 }
136 } 455 }
137 456
138 } // namespace certificate_transparency 457 } // namespace certificate_transparency
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698