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

Powered by Google App Engine
This is Rietveld 408576698