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

Side by Side Diff: net/cert/internal/path_builder.cc

Issue 1923433002: Certificate path builder for new certificate verification library (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: changes for review comment #20 Created 4 years, 5 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
« no previous file with comments | « net/cert/internal/path_builder.h ('k') | net/cert/internal/path_builder_pkits_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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/cert/internal/path_builder.h"
6
7 #include <set>
8 #include <unordered_set>
9
10 #include "base/callback_helpers.h"
11 #include "base/memory/ptr_util.h"
12 #include "net/base/net_errors.h"
13 #include "net/cert/internal/cert_issuer_source.h"
14 #include "net/cert/internal/parse_certificate.h"
15 #include "net/cert/internal/parse_name.h" // For CertDebugString.
16 #include "net/cert/internal/signature_policy.h"
17 #include "net/cert/internal/trust_store.h"
18 #include "net/cert/internal/verify_certificate_chain.h"
19 #include "net/cert/internal/verify_name_match.h"
20 #include "net/der/parser.h"
21 #include "net/der/tag.h"
22
23 namespace net {
24
25 namespace {
26
27 using CertIssuerSources = std::vector<CertIssuerSource*>;
28
29 // TODO(mattm): decide how much debug logging to keep.
30 std::string CertDebugString(const ParsedCertificate* cert) {
31 RDNSequence subject, issuer;
32 std::string subject_str, issuer_str;
33 if (!ParseName(cert->tbs().subject_tlv, &subject) ||
34 !ConvertToRFC2253(subject, &subject_str))
35 subject_str = "???";
36 if (!ParseName(cert->tbs().issuer_tlv, &issuer) ||
37 !ConvertToRFC2253(issuer, &issuer_str))
38 issuer_str = "???";
39
40 return subject_str + "(" + issuer_str + ")";
41 }
42
43 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources|
44 // which may be issuers of |cert|.
45 class CertIssuersIter {
46 public:
47 // Constructs the CertIssuersIter. |*cert_issuer_sources| must be valid for
48 // the lifetime of the CertIssuersIter.
49 CertIssuersIter(scoped_refptr<ParsedCertificate> cert,
50 CertIssuerSources* cert_issuer_sources,
51 const TrustStore& trust_store);
52
53 // Gets the next candidate issuer. If an issuer is ready synchronously, SYNC
54 // is returned and the cert is stored in |*out_cert|. If an issuer is not
55 // ready, ASYNC is returned and |callback| will be called once |*out_cert| has
56 // been set. If |callback| is null, always completes synchronously.
57 //
58 // In either case, if all issuers have been exhausted, |*out_cert| is cleared.
59 CompletionStatus GetNextIssuer(scoped_refptr<ParsedCertificate>* out_cert,
60 const base::Closure& callback);
61
62 // Returns the |cert| for which issuers are being retrieved.
63 const ParsedCertificate* cert() const { return cert_.get(); }
64 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; }
65
66 private:
67 void GotAsyncCerts(CertIssuerSource::Request* request);
68
69 scoped_refptr<ParsedCertificate> cert_;
70 CertIssuerSources* cert_issuer_sources_;
71
72 // The list of issuers for |cert_|. This is added to incrementally (first
73 // synchronous results, then possibly multiple times as asynchronous results
74 // arrive.) The issuers may be re-sorted each time new issuers are added, but
75 // only the results from |cur_| onwards should be sorted, since the earlier
76 // results were already returned.
77 // Elements should not be removed from |issuers_| once added, since
78 // |present_issuers_| will point to data owned by the certs.
79 ParsedCertificateList issuers_;
80 // The index of the next cert in |issuers_| to return.
81 size_t cur_ = 0;
82 // Set of DER-encoded values for the certs in |issuers_|. Used to prevent
83 // duplicates. This is based on the full DER of the cert to allow different
84 // versions of the same certificate to be tried in different candidate paths.
85 // This points to data owned by |issuers_|.
86 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_;
87
88 // Tracks whether asynchronous requests have been made yet.
89 bool did_async_query_ = false;
90 // If asynchronous requests were made, how many of them are still outstanding?
91 size_t pending_async_results_;
92 // Owns the Request objects for any asynchronous requests so that they will be
93 // cancelled if CertIssuersIter is destroyed.
94 std::vector<std::unique_ptr<CertIssuerSource::Request>>
95 pending_async_requests_;
96
97 // When GetNextIssuer was called and returned asynchronously, |*out_cert_| is
98 // where the result will be stored, and |callback_| will be run when the
99 // result is ready.
100 scoped_refptr<ParsedCertificate>* out_cert_;
101 base::Closure callback_;
102
103 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter);
104 };
105
106 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert,
107 CertIssuerSources* cert_issuer_sources,
108 const TrustStore& trust_store)
109 : cert_(in_cert), cert_issuer_sources_(cert_issuer_sources) {
110 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created";
111 trust_store.FindTrustAnchorsByNormalizedName(in_cert->normalized_issuer(),
112 &issuers_);
113 // Insert matching roots into |present_issuers_| in case they also are
114 // returned by a CertIssuerSource. It is assumed
115 // FindTrustAnchorsByNormalizedName does not itself return dupes.
116 for (const auto& root : issuers_)
117 present_issuers_.insert(root->der_cert().AsStringPiece());
118
119 for (auto* cert_issuer_source : *cert_issuer_sources_) {
120 ParsedCertificateList new_issuers;
121 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
122 for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) {
123 if (present_issuers_.find(issuer->der_cert().AsStringPiece()) !=
124 present_issuers_.end())
125 continue;
126 present_issuers_.insert(issuer->der_cert().AsStringPiece());
127 issuers_.push_back(std::move(issuer));
128 }
129 }
130 // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust
131 // anchor subject (or is a trust anchor), that should be sorted higher too.
132 // See big list of possible sorting hints in RFC 4158.)
133 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that
134 // is done)
135 }
136
137 CompletionStatus CertIssuersIter::GetNextIssuer(
138 scoped_refptr<ParsedCertificate>* out_cert,
139 const base::Closure& callback) {
140 // Should not be called again while already waiting for an async result.
141 DCHECK(callback_.is_null());
142
143 if (cur_ < issuers_.size()) {
144 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
145 << "): returning item " << cur_ << " of " << issuers_.size();
146 // Still have issuers that haven't been returned yet, return one of them.
147 // A reference to the returned issuer is retained, since |present_issuers_|
148 // points to data owned by it.
149 *out_cert = issuers_[cur_++];
150 return CompletionStatus::SYNC;
151 }
152 if (did_async_query_) {
153 if (pending_async_results_ == 0) {
154 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
155 << ") Reached the end of all available issuers.";
156 // Reached the end of all available issuers.
157 *out_cert = nullptr;
158 return CompletionStatus::SYNC;
159 }
160
161 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
162 << ") Still waiting for async results from other "
163 "CertIssuerSources.";
164 // Still waiting for async results from other CertIssuerSources.
165 out_cert_ = out_cert;
166 callback_ = callback;
167 return CompletionStatus::ASYNC;
168 }
169 // Reached the end of synchronously gathered issuers.
170
171 if (callback.is_null()) {
172 // Synchronous-only mode, don't try to query async sources.
173 *out_cert = nullptr;
174 return CompletionStatus::SYNC;
175 }
176
177 // Now issue request(s) for async ones (AIA, etc).
178 did_async_query_ = true;
179 pending_async_results_ = 0;
180 for (auto* cert_issuer_source : *cert_issuer_sources_) {
181 std::unique_ptr<CertIssuerSource::Request> request;
182 cert_issuer_source->AsyncGetIssuersOf(
183 cert(),
184 base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)),
185 &request);
186 if (request) {
187 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert())
188 << ") pending...";
189 pending_async_results_++;
190 pending_async_requests_.push_back(std::move(request));
191 }
192 }
193
194 if (pending_async_results_ == 0) {
195 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
196 << ") No cert sources have async results.";
197 // No cert sources have async results.
198 *out_cert = nullptr;
199 return CompletionStatus::SYNC;
200 }
201
202 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
203 << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_
204 << ")";
205 out_cert_ = out_cert;
206 callback_ = callback;
207 return CompletionStatus::ASYNC;
208 }
209
210 void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) {
211 DVLOG(1) << "CertIssuersIter::GotAsyncCerts(" << CertDebugString(cert())
212 << ")";
213 while (true) {
214 scoped_refptr<ParsedCertificate> cert;
215 CompletionStatus status = request->GetNext(&cert);
216 if (!cert) {
217 if (status == CompletionStatus::SYNC) {
218 // Request is exhausted, no more results pending from that
219 // CertIssuerSource.
220 DCHECK_GT(pending_async_results_, 0U);
221 pending_async_results_--;
222 }
223 break;
224 }
225 DCHECK_EQ(status, CompletionStatus::SYNC);
226 if (present_issuers_.find(cert->der_cert().AsStringPiece()) !=
227 present_issuers_.end())
228 continue;
229 present_issuers_.insert(cert->der_cert().AsStringPiece());
230 issuers_.push_back(std::move(cert));
231 }
232
233 // TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may
234 // be more than the ones just inserted, depending on |cur_| value).
235
236 // Notify that more results are available, if necessary.
237 if (!callback_.is_null()) {
238 if (cur_ < issuers_.size()) {
239 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
240 << "): async returning item " << cur_ << " of "
241 << issuers_.size();
242 *out_cert_ = std::move(issuers_[cur_++]);
243 base::ResetAndReturn(&callback_).Run();
244 } else if (pending_async_results_ == 0) {
245 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
246 << "): async returning empty result";
247 *out_cert_ = nullptr;
248 base::ResetAndReturn(&callback_).Run();
249 } else {
250 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
251 << "): empty result, but other async results "
252 "pending, waiting..";
253 }
254 }
255 }
256
257 // CertIssuerIterPath tracks which certs are present in the path and prevents
258 // paths from being built which repeat any certs (including different versions
259 // of the same cert, based on Subject+SubjectAltName+SPKI).
260 class CertIssuerIterPath {
261 public:
262 // Returns true if |cert| is already present in the path.
263 bool IsPresent(const ParsedCertificate* cert) const {
264 return present_certs_.find(GetKey(cert)) != present_certs_.end();
265 }
266
267 // Appends |cert_issuers_iter| to the path. The cert referred to by
268 // |cert_issuers_iter| must not be present in the path already.
269 void Append(std::unique_ptr<CertIssuersIter> cert_issuers_iter) {
270 bool added =
271 present_certs_.insert(GetKey(cert_issuers_iter->cert())).second;
272 DCHECK(added);
273 cur_path_.push_back(std::move(cert_issuers_iter));
274 }
275
276 // Pops the last CertIssuersIter off the path.
277 void Pop() {
278 size_t num_erased = present_certs_.erase(GetKey(cur_path_.back()->cert()));
279 DCHECK_EQ(num_erased, 1U);
280 cur_path_.pop_back();
281 }
282
283 // Copies the ParsedCertificate elements of the current path to |*out_path|.
284 void CopyPath(ParsedCertificateList* out_path) {
285 out_path->clear();
286 for (const auto& node : cur_path_)
287 out_path->push_back(node->reference_cert());
288 }
289
290 // Returns true if the path is empty.
291 bool Empty() const { return cur_path_.empty(); }
292
293 // Returns the last CertIssuersIter in the path.
294 CertIssuersIter* back() { return cur_path_.back().get(); }
295
296 std::string PathDebugString() {
297 std::string s;
298 for (const auto& node : cur_path_) {
299 if (!s.empty())
300 s += " <- ";
301 s += CertDebugString(node->cert());
302 }
303 return s;
304 }
305
306 private:
307 using Key =
308 std::tuple<base::StringPiece, base::StringPiece, base::StringPiece>;
309
310 static Key GetKey(const ParsedCertificate* cert) {
311 // TODO(mattm): ideally this would use a normalized version of
312 // SubjectAltName, but it's not that important just for LoopChecker.
313 //
314 // Note that subject_alt_names_extension().value will be empty if the cert
315 // had no SubjectAltName extension, so there is no need for a condition on
316 // has_subject_alt_names().
317 return Key(cert->normalized_subject().AsStringPiece(),
318 cert->subject_alt_names_extension().value.AsStringPiece(),
319 cert->tbs().spki_tlv.AsStringPiece());
320 }
321
322 std::vector<std::unique_ptr<CertIssuersIter>> cur_path_;
323
324 // This refers to data owned by |cur_path_|.
325 // TODO(mattm): use unordered_set. Requires making a hash function for Key.
326 std::set<Key> present_certs_;
327 };
328
329 } // namespace
330
331 // CertPathIter generates possible paths from |cert| to a trust anchor in
332 // |trust_store|, using intermediates from the |cert_issuer_source| objects if
333 // necessary.
334 class CertPathIter {
335 public:
336 CertPathIter(scoped_refptr<ParsedCertificate> cert,
337 const TrustStore* trust_store);
338
339 // Adds a CertIssuerSource to provide intermediates for use in path building.
340 // The |*cert_issuer_source| must remain valid for the lifetime of the
341 // CertPathIter.
342 void AddCertIssuerSource(CertIssuerSource* cert_issuer_source);
343
344 // Gets the next candidate path. If a path is ready synchronously, SYNC is
345 // returned and the path is stored in |*path|. If a path is not ready,
346 // ASYNC is returned and |callback| will be called once |*path| has been set.
347 // In either case, if all paths have been exhausted, |*path| is cleared.
348 CompletionStatus GetNextPath(ParsedCertificateList* path,
349 const base::Closure& callback);
350
351 private:
352 enum State {
353 STATE_NONE,
354 STATE_GET_NEXT_ISSUER,
355 STATE_GET_NEXT_ISSUER_COMPLETE,
356 STATE_RETURN_A_PATH,
357 STATE_BACKTRACK,
358 };
359
360 CompletionStatus DoLoop(bool allow_async);
361
362 CompletionStatus DoGetNextIssuer(bool allow_async);
363 CompletionStatus DoGetNextIssuerComplete();
364 CompletionStatus DoBackTrack();
365
366 void HandleGotNextIssuer(void);
367
368 // Stores the next candidate issuer certificate, until it is used during the
369 // STATE_GET_NEXT_ISSUER_COMPLETE step.
370 scoped_refptr<ParsedCertificate> next_cert_;
371 // The current path being explored, made up of CertIssuerIters. Each node
372 // keeps track of the state of searching for issuers of that cert, so that
373 // when backtracking it can resume the search where it left off.
374 CertIssuerIterPath cur_path_;
375 // The CertIssuerSources for retrieving candidate issuers.
376 CertIssuerSources cert_issuer_sources_;
377 // The TrustStore for checking if a path ends in a trust anchor.
378 const TrustStore* trust_store_;
379 // The output variable for storing the next candidate path, which the client
380 // passes in to GetNextPath. Only used for a single path output.
381 ParsedCertificateList* out_path_;
382 // The callback to be called if an async lookup generated a candidate path.
383 base::Closure callback_;
384 // Current state of the state machine.
385 State next_state_;
386
387 DISALLOW_COPY_AND_ASSIGN(CertPathIter);
388 };
389
390 CertPathIter::CertPathIter(scoped_refptr<ParsedCertificate> cert,
391 const TrustStore* trust_store)
392 : next_cert_(std::move(cert)),
393 trust_store_(trust_store),
394 next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {}
395
396 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) {
397 cert_issuer_sources_.push_back(cert_issuer_source);
398 }
399
400 CompletionStatus CertPathIter::GetNextPath(ParsedCertificateList* path,
401 const base::Closure& callback) {
402 out_path_ = path;
403 out_path_->clear();
404 CompletionStatus rv = DoLoop(!callback.is_null());
405 if (rv == CompletionStatus::ASYNC) {
406 callback_ = callback;
407 } else {
408 // Clear the reference to the output parameter as a precaution.
409 out_path_ = nullptr;
410 }
411 return rv;
412 }
413
414 CompletionStatus CertPathIter::DoLoop(bool allow_async) {
415 CompletionStatus result = CompletionStatus::SYNC;
416 do {
417 State state = next_state_;
418 next_state_ = STATE_NONE;
419 switch (state) {
420 case STATE_NONE:
421 NOTREACHED();
422 break;
423 case STATE_GET_NEXT_ISSUER:
424 result = DoGetNextIssuer(allow_async);
425 break;
426 case STATE_GET_NEXT_ISSUER_COMPLETE:
427 result = DoGetNextIssuerComplete();
428 break;
429 case STATE_RETURN_A_PATH:
430 // If the returned path did not verify, keep looking for other paths
431 // (the trust root is not part of cur_path_, so don't need to
432 // backtrack).
433 next_state_ = STATE_GET_NEXT_ISSUER;
434 result = CompletionStatus::SYNC;
435 break;
436 case STATE_BACKTRACK:
437 result = DoBackTrack();
438 break;
439 }
440 } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE &&
441 next_state_ != STATE_RETURN_A_PATH);
442
443 return result;
444 }
445
446 CompletionStatus CertPathIter::DoGetNextIssuer(bool allow_async) {
447 next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE;
448 CompletionStatus rv = cur_path_.back()->GetNextIssuer(
449 &next_cert_, allow_async ? base::Bind(&CertPathIter::HandleGotNextIssuer,
450 base::Unretained(this))
451 : base::Closure());
452 return rv;
453 }
454
455 CompletionStatus CertPathIter::DoGetNextIssuerComplete() {
456 if (next_cert_) {
457 // Skip this cert if it is already in the chain.
458 if (cur_path_.IsPresent(next_cert_.get())) {
459 next_state_ = STATE_GET_NEXT_ISSUER;
460 return CompletionStatus::SYNC;
461 }
462 // If the cert matches a trust root, this is a (possibly) complete path.
463 // Signal readiness. Don't add it to cur_path_, since that would cause an
464 // unnecessary lookup of issuers of the trust root.
465 if (trust_store_->IsTrustedCertificate(next_cert_.get())) {
466 DVLOG(1) << "CertPathIter IsTrustedCertificate("
467 << CertDebugString(next_cert_.get()) << ") = true";
468 next_state_ = STATE_RETURN_A_PATH;
469 cur_path_.CopyPath(out_path_);
470 out_path_->push_back(std::move(next_cert_));
471 next_cert_ = nullptr;
472 return CompletionStatus::SYNC;
473 }
474
475 cur_path_.Append(base::WrapUnique(new CertIssuersIter(
476 std::move(next_cert_), &cert_issuer_sources_, *trust_store_)));
477 next_cert_ = nullptr;
478 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString();
479 // Continue descending the tree.
480 next_state_ = STATE_GET_NEXT_ISSUER;
481 } else {
482 // TODO(mattm): should also include such paths in CertPathBuilder::Result,
483 // maybe with a flag to enable it. Or use a visitor pattern so the caller
484 // can decide what to do with any failed paths.
485 // No more issuers for current chain, go back up and see if there are any
486 // more for the previous cert.
487 next_state_ = STATE_BACKTRACK;
488 }
489 return CompletionStatus::SYNC;
490 }
491
492 CompletionStatus CertPathIter::DoBackTrack() {
493 DVLOG(1) << "CertPathIter backtracking...";
494 cur_path_.Pop();
495 if (cur_path_.Empty()) {
496 // Exhausted all paths.
497 next_state_ = STATE_NONE;
498 } else {
499 // Continue exploring issuers of the previous path.
500 next_state_ = STATE_GET_NEXT_ISSUER;
501 }
502 return CompletionStatus::SYNC;
503 }
504
505 void CertPathIter::HandleGotNextIssuer(void) {
506 DCHECK(!callback_.is_null());
507 CompletionStatus rv = DoLoop(true /* allow_async */);
508 if (rv == CompletionStatus::SYNC) {
509 // Clear the reference to the output parameter as a precaution.
510 out_path_ = nullptr;
511 base::ResetAndReturn(&callback_).Run();
512 }
513 }
514
515 CertPathBuilder::ResultPath::ResultPath() = default;
516 CertPathBuilder::ResultPath::~ResultPath() = default;
517 CertPathBuilder::Result::Result() = default;
518 CertPathBuilder::Result::~Result() = default;
519
520 CertPathBuilder::CertPathBuilder(scoped_refptr<ParsedCertificate> cert,
521 const TrustStore* trust_store,
522 const SignaturePolicy* signature_policy,
523 const der::GeneralizedTime& time,
524 Result* result)
525 : cert_path_iter_(new CertPathIter(std::move(cert), trust_store)),
526 trust_store_(trust_store),
527 signature_policy_(signature_policy),
528 time_(time),
529 next_state_(STATE_NONE),
530 out_result_(result) {}
531
532 CertPathBuilder::~CertPathBuilder() {}
533
534 void CertPathBuilder::AddCertIssuerSource(
535 CertIssuerSource* cert_issuer_source) {
536 cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
537 }
538
539 CompletionStatus CertPathBuilder::Run(const base::Closure& callback) {
540 DCHECK_EQ(STATE_NONE, next_state_);
541 next_state_ = STATE_GET_NEXT_PATH;
542 CompletionStatus rv = DoLoop(!callback.is_null());
543
544 if (rv == CompletionStatus::ASYNC)
545 callback_ = callback;
546
547 return rv;
548 }
549
550 CompletionStatus CertPathBuilder::DoLoop(bool allow_async) {
551 CompletionStatus result = CompletionStatus::SYNC;
552
553 do {
554 State state = next_state_;
555 next_state_ = STATE_NONE;
556 switch (state) {
557 case STATE_NONE:
558 NOTREACHED();
559 break;
560 case STATE_GET_NEXT_PATH:
561 result = DoGetNextPath(allow_async);
562 break;
563 case STATE_GET_NEXT_PATH_COMPLETE:
564 result = DoGetNextPathComplete();
565 break;
566 }
567 } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE);
568
569 return result;
570 }
571
572 CompletionStatus CertPathBuilder::DoGetNextPath(bool allow_async) {
573 next_state_ = STATE_GET_NEXT_PATH_COMPLETE;
574 CompletionStatus rv = cert_path_iter_->GetNextPath(
575 &next_path_, allow_async ? base::Bind(&CertPathBuilder::HandleGotNextPath,
576 base::Unretained(this))
577 : base::Closure());
578 return rv;
579 }
580
581 void CertPathBuilder::HandleGotNextPath() {
582 DCHECK(!callback_.is_null());
583 CompletionStatus rv = DoLoop(true /* allow_async */);
584 if (rv == CompletionStatus::SYNC)
585 base::ResetAndReturn(&callback_).Run();
586 }
587
588 CompletionStatus CertPathBuilder::DoGetNextPathComplete() {
589 if (next_path_.empty()) {
590 // No more paths to check, signal completion.
591 next_state_ = STATE_NONE;
592 return CompletionStatus::SYNC;
593 }
594
595 bool verify_result = VerifyCertificateChainAssumingTrustedRoot(
596 next_path_, *trust_store_, signature_policy_, time_);
597 DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = "
598 << verify_result;
599 AddResultPath(next_path_, verify_result);
600
601 if (verify_result) {
602 // Found a valid path, return immediately.
603 // TODO(mattm): add debug/test mode that tries all possible paths.
604 next_state_ = STATE_NONE;
605 return CompletionStatus::SYNC;
606 }
607
608 // Path did not verify. Try more paths. If there are no more paths, the result
609 // will be returned next time DoGetNextPathComplete is called with next_path_
610 // empty.
611 next_state_ = STATE_GET_NEXT_PATH;
612 return CompletionStatus::SYNC;
613 }
614
615 void CertPathBuilder::AddResultPath(const ParsedCertificateList& path,
616 bool is_success) {
617 std::unique_ptr<ResultPath> result_path(new ResultPath());
618 // TODO(mattm): better error reporting.
619 result_path->error = is_success ? OK : ERR_CERT_AUTHORITY_INVALID;
620 // TODO(mattm): set best_result_index based on number or severity of errors.
621 if (result_path->error == OK)
622 out_result_->best_result_index = out_result_->paths.size();
623 // TODO(mattm): add flag to only return a single path or all attempted paths?
624 result_path->path = path;
625 out_result_->paths.push_back(std::move(result_path));
626 }
627
628 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/internal/path_builder.h ('k') | net/cert/internal/path_builder_pkits_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698