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

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

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