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

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

Issue 2225493003: Don't treat trust anchors as certificates during path building. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix components_unittests compile (hopefully) 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
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/logging.h"
11 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
12 #include "net/base/net_errors.h" 13 #include "net/base/net_errors.h"
13 #include "net/cert/internal/cert_issuer_source.h" 14 #include "net/cert/internal/cert_issuer_source.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"
18 #include "net/cert/internal/verify_certificate_chain.h" 19 #include "net/cert/internal/verify_certificate_chain.h"
19 #include "net/cert/internal/verify_name_match.h" 20 #include "net/cert/internal/verify_name_match.h"
20 #include "net/der/parser.h" 21 #include "net/der/parser.h"
(...skipping 12 matching lines...) Expand all
33 if (!ParseName(cert->tbs().subject_tlv, &subject) || 34 if (!ParseName(cert->tbs().subject_tlv, &subject) ||
34 !ConvertToRFC2253(subject, &subject_str)) 35 !ConvertToRFC2253(subject, &subject_str))
35 subject_str = "???"; 36 subject_str = "???";
36 if (!ParseName(cert->tbs().issuer_tlv, &issuer) || 37 if (!ParseName(cert->tbs().issuer_tlv, &issuer) ||
37 !ConvertToRFC2253(issuer, &issuer_str)) 38 !ConvertToRFC2253(issuer, &issuer_str))
38 issuer_str = "???"; 39 issuer_str = "???";
39 40
40 return subject_str + "(" + issuer_str + ")"; 41 return subject_str + "(" + issuer_str + ")";
41 } 42 }
42 43
44 // This structure contains either a ParsedCertificate or a TrustAnchor. It is
45 // used to describe the result of getting a certificate's issuer, which may
46 // either be another certificate, or a trust anchor.
47 struct CertificateOrTrustAnchor {
48 CertificateOrTrustAnchor() {}
49
50 explicit CertificateOrTrustAnchor(scoped_refptr<ParsedCertificate> cert)
51 : cert(std::move(cert)) {}
52
53 explicit CertificateOrTrustAnchor(scoped_refptr<TrustAnchor> anchor)
54 : anchor(std::move(anchor)) {}
55
56 bool IsTrustAnchor() const { return anchor.get() != nullptr; }
57 bool IsCertificate() const { return cert.get() != nullptr; }
58 bool IsEmpty() const { return !IsTrustAnchor() && !IsCertificate(); }
59
60 scoped_refptr<ParsedCertificate> cert;
61 scoped_refptr<TrustAnchor> anchor;
62 };
63
43 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources| 64 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources|
44 // which may be issuers of |cert|. 65 // which may be issuers of |cert|.
45 class CertIssuersIter { 66 class CertIssuersIter {
46 public: 67 public:
47 // Constructs the CertIssuersIter. |*cert_issuer_sources| must be valid for 68 // Constructs the CertIssuersIter. |*cert_issuer_sources| must be valid for
48 // the lifetime of the CertIssuersIter. 69 // the lifetime of the CertIssuersIter.
49 CertIssuersIter(scoped_refptr<ParsedCertificate> cert, 70 CertIssuersIter(scoped_refptr<ParsedCertificate> cert,
50 CertIssuerSources* cert_issuer_sources, 71 CertIssuerSources* cert_issuer_sources,
51 const TrustStore& trust_store); 72 const TrustStore& trust_store);
52 73
53 // Gets the next candidate issuer. If an issuer is ready synchronously, SYNC 74 // 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 75 // is returned and the cert is stored in |*cert|. If an issuer is not
55 // ready, ASYNC is returned and |callback| will be called once |*out_cert| has 76 // ready, ASYNC is returned and |callback| will be called once |*out_cert| has
56 // been set. If |callback| is null, always completes synchronously. 77 // been set. If |callback| is null, always completes synchronously.
57 // 78 //
58 // In either case, if all issuers have been exhausted, |*out_cert| is cleared. 79 // In either case, if all issuers have been exhausted, |*out| is cleared.
59 CompletionStatus GetNextIssuer(scoped_refptr<ParsedCertificate>* out_cert, 80 CompletionStatus GetNextIssuer(CertificateOrTrustAnchor* out,
60 const base::Closure& callback); 81 const base::Closure& callback);
61 82
62 // Returns the |cert| for which issuers are being retrieved. 83 // Returns the |cert| for which issuers are being retrieved.
63 const ParsedCertificate* cert() const { return cert_.get(); } 84 const ParsedCertificate* cert() const { return cert_.get(); }
64 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; } 85 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; }
65 86
66 private: 87 private:
67 void GotAsyncCerts(CertIssuerSource::Request* request); 88 void GotAsyncCerts(CertIssuerSource::Request* request);
68 89
69 scoped_refptr<ParsedCertificate> cert_; 90 scoped_refptr<ParsedCertificate> cert_;
70 CertIssuerSources* cert_issuer_sources_; 91 CertIssuerSources* cert_issuer_sources_;
71 92
93 // The list of trust anchors that match the issuer name for |cert_|.
94 TrustAnchors anchors_;
95 // The index of the next trust anchor in |anchors_| to return.
96 size_t cur_anchor_ = 0;
97
72 // The list of issuers for |cert_|. This is added to incrementally (first 98 // The list of issuers for |cert_|. This is added to incrementally (first
73 // synchronous results, then possibly multiple times as asynchronous results 99 // synchronous results, then possibly multiple times as asynchronous results
74 // arrive.) The issuers may be re-sorted each time new issuers are added, but 100 // 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 101 // only the results from |cur_| onwards should be sorted, since the earlier
76 // results were already returned. 102 // results were already returned.
77 // Elements should not be removed from |issuers_| once added, since 103 // Elements should not be removed from |issuers_| once added, since
78 // |present_issuers_| will point to data owned by the certs. 104 // |present_issuers_| will point to data owned by the certs.
79 ParsedCertificateList issuers_; 105 ParsedCertificateList issuers_;
80 // The index of the next cert in |issuers_| to return. 106 // The index of the next cert in |issuers_| to return.
81 size_t cur_ = 0; 107 size_t cur_issuer_ = 0;
108
82 // Set of DER-encoded values for the certs in |issuers_|. Used to prevent 109 // 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 110 // 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. 111 // versions of the same certificate to be tried in different candidate paths.
85 // This points to data owned by |issuers_|. 112 // This points to data owned by |issuers_|.
86 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_; 113 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_;
87 114
88 // Tracks whether asynchronous requests have been made yet. 115 // Tracks whether asynchronous requests have been made yet.
89 bool did_async_query_ = false; 116 bool did_async_query_ = false;
90 // If asynchronous requests were made, how many of them are still outstanding? 117 // If asynchronous requests were made, how many of them are still outstanding?
91 size_t pending_async_results_; 118 size_t pending_async_results_;
92 // Owns the Request objects for any asynchronous requests so that they will be 119 // Owns the Request objects for any asynchronous requests so that they will be
93 // cancelled if CertIssuersIter is destroyed. 120 // cancelled if CertIssuersIter is destroyed.
94 std::vector<std::unique_ptr<CertIssuerSource::Request>> 121 std::vector<std::unique_ptr<CertIssuerSource::Request>>
95 pending_async_requests_; 122 pending_async_requests_;
96 123
97 // When GetNextIssuer was called and returned asynchronously, |*out_cert_| is 124 // When GetNextIssuer was called and returned asynchronously, |*out_| is
98 // where the result will be stored, and |callback_| will be run when the 125 // where the result will be stored, and |callback_| will be run when the
99 // result is ready. 126 // result is ready.
100 scoped_refptr<ParsedCertificate>* out_cert_; 127 CertificateOrTrustAnchor* out_;
101 base::Closure callback_; 128 base::Closure callback_;
102 129
103 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter); 130 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter);
104 }; 131 };
105 132
106 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert, 133 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert,
107 CertIssuerSources* cert_issuer_sources, 134 CertIssuerSources* cert_issuer_sources,
108 const TrustStore& trust_store) 135 const TrustStore& trust_store)
109 : cert_(in_cert), cert_issuer_sources_(cert_issuer_sources) { 136 : cert_(in_cert), cert_issuer_sources_(cert_issuer_sources) {
110 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created"; 137 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created";
111 trust_store.FindTrustAnchorsByNormalizedName(in_cert->normalized_issuer(), 138 trust_store.FindTrustAnchorsByNormalizedName(in_cert->normalized_issuer(),
112 &issuers_); 139 &anchors_);
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());
mattm 2016/08/09 00:59:21 Since this is removed there would be the possibili
eroman 2016/08/09 01:37:20 I am not sure that limiting is needed for correctn
mattm 2016/08/09 19:51:04 Yeah, I was thinking of avoiding unnecessary work
eroman 2016/08/09 23:42:07 Thanks, I have added that as a test. I have some
118 140
119 for (auto* cert_issuer_source : *cert_issuer_sources_) { 141 for (auto* cert_issuer_source : *cert_issuer_sources_) {
120 ParsedCertificateList new_issuers; 142 ParsedCertificateList new_issuers;
121 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers); 143 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
122 for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) { 144 for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) {
123 if (present_issuers_.find(issuer->der_cert().AsStringPiece()) != 145 if (present_issuers_.find(issuer->der_cert().AsStringPiece()) !=
124 present_issuers_.end()) 146 present_issuers_.end())
125 continue; 147 continue;
126 present_issuers_.insert(issuer->der_cert().AsStringPiece()); 148 present_issuers_.insert(issuer->der_cert().AsStringPiece());
127 issuers_.push_back(std::move(issuer)); 149 issuers_.push_back(std::move(issuer));
128 } 150 }
129 } 151 }
130 // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust 152 // 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. 153 // anchor subject (or is a trust anchor), that should be sorted higher too.
132 // See big list of possible sorting hints in RFC 4158.) 154 // See big list of possible sorting hints in RFC 4158.)
133 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that 155 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that
134 // is done) 156 // is done)
135 } 157 }
136 158
137 CompletionStatus CertIssuersIter::GetNextIssuer( 159 CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out,
138 scoped_refptr<ParsedCertificate>* out_cert, 160 const base::Closure& callback) {
139 const base::Closure& callback) {
140 // Should not be called again while already waiting for an async result. 161 // Should not be called again while already waiting for an async result.
141 DCHECK(callback_.is_null()); 162 DCHECK(callback_.is_null());
142 163
143 if (cur_ < issuers_.size()) { 164 // Return possible trust anchors first.
165 if (cur_anchor_ < anchors_.size()) {
144 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 166 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
145 << "): returning item " << cur_ << " of " << issuers_.size(); 167 << "): returning anchor " << cur_anchor_ << " of "
168 << anchors_.size();
169 // Still have anchors that haven't been returned yet, return one of them.
170 *out = CertificateOrTrustAnchor(anchors_[cur_anchor_++]);
171 return CompletionStatus::SYNC;
172 }
173
174 if (cur_issuer_ < issuers_.size()) {
175 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
176 << "): returning issuer " << cur_issuer_ << " of "
177 << issuers_.size();
146 // Still have issuers that haven't been returned yet, return one of them. 178 // 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_| 179 // A reference to the returned issuer is retained, since |present_issuers_|
148 // points to data owned by it. 180 // points to data owned by it.
149 *out_cert = issuers_[cur_++]; 181 *out = CertificateOrTrustAnchor(issuers_[cur_issuer_++]);
150 return CompletionStatus::SYNC; 182 return CompletionStatus::SYNC;
151 } 183 }
152 if (did_async_query_) { 184 if (did_async_query_) {
153 if (pending_async_results_ == 0) { 185 if (pending_async_results_ == 0) {
154 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 186 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
155 << ") Reached the end of all available issuers."; 187 << ") Reached the end of all available issuers.";
156 // Reached the end of all available issuers. 188 // Reached the end of all available issuers.
157 *out_cert = nullptr; 189 *out = CertificateOrTrustAnchor();
158 return CompletionStatus::SYNC; 190 return CompletionStatus::SYNC;
159 } 191 }
160 192
161 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 193 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
162 << ") Still waiting for async results from other " 194 << ") Still waiting for async results from other "
163 "CertIssuerSources."; 195 "CertIssuerSources.";
164 // Still waiting for async results from other CertIssuerSources. 196 // Still waiting for async results from other CertIssuerSources.
165 out_cert_ = out_cert; 197 out_ = out;
166 callback_ = callback; 198 callback_ = callback;
167 return CompletionStatus::ASYNC; 199 return CompletionStatus::ASYNC;
168 } 200 }
169 // Reached the end of synchronously gathered issuers. 201 // Reached the end of synchronously gathered issuers.
170 202
171 if (callback.is_null()) { 203 if (callback.is_null()) {
172 // Synchronous-only mode, don't try to query async sources. 204 // Synchronous-only mode, don't try to query async sources.
173 *out_cert = nullptr; 205 *out = CertificateOrTrustAnchor();
174 return CompletionStatus::SYNC; 206 return CompletionStatus::SYNC;
175 } 207 }
176 208
177 // Now issue request(s) for async ones (AIA, etc). 209 // Now issue request(s) for async ones (AIA, etc).
178 did_async_query_ = true; 210 did_async_query_ = true;
179 pending_async_results_ = 0; 211 pending_async_results_ = 0;
180 for (auto* cert_issuer_source : *cert_issuer_sources_) { 212 for (auto* cert_issuer_source : *cert_issuer_sources_) {
181 std::unique_ptr<CertIssuerSource::Request> request; 213 std::unique_ptr<CertIssuerSource::Request> request;
182 cert_issuer_source->AsyncGetIssuersOf( 214 cert_issuer_source->AsyncGetIssuersOf(
183 cert(), 215 cert(),
184 base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)), 216 base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)),
185 &request); 217 &request);
186 if (request) { 218 if (request) {
187 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert()) 219 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert())
188 << ") pending..."; 220 << ") pending...";
189 pending_async_results_++; 221 pending_async_results_++;
190 pending_async_requests_.push_back(std::move(request)); 222 pending_async_requests_.push_back(std::move(request));
191 } 223 }
192 } 224 }
193 225
194 if (pending_async_results_ == 0) { 226 if (pending_async_results_ == 0) {
195 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 227 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
196 << ") No cert sources have async results."; 228 << ") No cert sources have async results.";
197 // No cert sources have async results. 229 // No cert sources have async results.
198 *out_cert = nullptr; 230 *out = CertificateOrTrustAnchor();
199 return CompletionStatus::SYNC; 231 return CompletionStatus::SYNC;
200 } 232 }
201 233
202 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 234 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
203 << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_ 235 << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_
204 << ")"; 236 << ")";
205 out_cert_ = out_cert; 237 out_ = out;
206 callback_ = callback; 238 callback_ = callback;
207 return CompletionStatus::ASYNC; 239 return CompletionStatus::ASYNC;
208 } 240 }
209 241
210 void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) { 242 void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) {
211 DVLOG(1) << "CertIssuersIter::GotAsyncCerts(" << CertDebugString(cert()) 243 DVLOG(1) << "CertIssuersIter::GotAsyncCerts(" << CertDebugString(cert())
212 << ")"; 244 << ")";
213 while (true) { 245 while (true) {
214 scoped_refptr<ParsedCertificate> cert; 246 scoped_refptr<ParsedCertificate> cert;
215 CompletionStatus status = request->GetNext(&cert); 247 CompletionStatus status = request->GetNext(&cert);
(...skipping 12 matching lines...) Expand all
228 continue; 260 continue;
229 present_issuers_.insert(cert->der_cert().AsStringPiece()); 261 present_issuers_.insert(cert->der_cert().AsStringPiece());
230 issuers_.push_back(std::move(cert)); 262 issuers_.push_back(std::move(cert));
231 } 263 }
232 264
233 // TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may 265 // TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may
234 // be more than the ones just inserted, depending on |cur_| value). 266 // be more than the ones just inserted, depending on |cur_| value).
235 267
236 // Notify that more results are available, if necessary. 268 // Notify that more results are available, if necessary.
237 if (!callback_.is_null()) { 269 if (!callback_.is_null()) {
238 if (cur_ < issuers_.size()) { 270 DCHECK_GE(cur_anchor_, anchors_.size());
271 if (cur_issuer_ < issuers_.size()) {
239 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 272 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
240 << "): async returning item " << cur_ << " of " 273 << "): async returning item " << cur_issuer_ << " of "
241 << issuers_.size(); 274 << issuers_.size();
242 *out_cert_ = std::move(issuers_[cur_++]); 275 *out_ = CertificateOrTrustAnchor(std::move(issuers_[cur_issuer_++]));
243 base::ResetAndReturn(&callback_).Run(); 276 base::ResetAndReturn(&callback_).Run();
244 } else if (pending_async_results_ == 0) { 277 } else if (pending_async_results_ == 0) {
245 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 278 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
246 << "): async returning empty result"; 279 << "): async returning empty result";
247 *out_cert_ = nullptr; 280 *out_ = CertificateOrTrustAnchor();
248 base::ResetAndReturn(&callback_).Run(); 281 base::ResetAndReturn(&callback_).Run();
249 } else { 282 } else {
250 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 283 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
251 << "): empty result, but other async results " 284 << "): empty result, but other async results "
252 "pending, waiting.."; 285 "pending, waiting..";
253 } 286 }
254 } 287 }
255 } 288 }
256 289
257 // CertIssuerIterPath tracks which certs are present in the path and prevents 290 // CertIssuerIterPath tracks which certs are present in the path and prevents
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 354
322 std::vector<std::unique_ptr<CertIssuersIter>> cur_path_; 355 std::vector<std::unique_ptr<CertIssuersIter>> cur_path_;
323 356
324 // This refers to data owned by |cur_path_|. 357 // This refers to data owned by |cur_path_|.
325 // TODO(mattm): use unordered_set. Requires making a hash function for Key. 358 // TODO(mattm): use unordered_set. Requires making a hash function for Key.
326 std::set<Key> present_certs_; 359 std::set<Key> present_certs_;
327 }; 360 };
328 361
329 } // namespace 362 } // namespace
330 363
364 CertPath::CertPath() = default;
365 CertPath::~CertPath() = default;
366
367 void CertPath::Clear() {
368 trust_anchor = nullptr;
369 certs.clear();
370 }
371
372 bool CertPath::IsEmpty() const {
373 return certs.empty();
374 }
375
331 // CertPathIter generates possible paths from |cert| to a trust anchor in 376 // CertPathIter generates possible paths from |cert| to a trust anchor in
332 // |trust_store|, using intermediates from the |cert_issuer_source| objects if 377 // |trust_store|, using intermediates from the |cert_issuer_source| objects if
333 // necessary. 378 // necessary.
334 class CertPathIter { 379 class CertPathIter {
335 public: 380 public:
336 CertPathIter(scoped_refptr<ParsedCertificate> cert, 381 CertPathIter(scoped_refptr<ParsedCertificate> cert,
337 const TrustStore* trust_store); 382 const TrustStore* trust_store);
338 383
339 // Adds a CertIssuerSource to provide intermediates for use in path building. 384 // Adds a CertIssuerSource to provide intermediates for use in path building.
340 // The |*cert_issuer_source| must remain valid for the lifetime of the 385 // The |*cert_issuer_source| must remain valid for the lifetime of the
341 // CertPathIter. 386 // CertPathIter.
342 void AddCertIssuerSource(CertIssuerSource* cert_issuer_source); 387 void AddCertIssuerSource(CertIssuerSource* cert_issuer_source);
343 388
344 // Gets the next candidate path. If a path is ready synchronously, SYNC is 389 // 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, 390 // 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. 391 // 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. 392 // In either case, if all paths have been exhausted, |*path| is cleared.
348 CompletionStatus GetNextPath(ParsedCertificateList* path, 393 CompletionStatus GetNextPath(CertPath* path, const base::Closure& callback);
349 const base::Closure& callback);
350 394
351 private: 395 private:
352 enum State { 396 enum State {
353 STATE_NONE, 397 STATE_NONE,
354 STATE_GET_NEXT_ISSUER, 398 STATE_GET_NEXT_ISSUER,
355 STATE_GET_NEXT_ISSUER_COMPLETE, 399 STATE_GET_NEXT_ISSUER_COMPLETE,
356 STATE_RETURN_A_PATH, 400 STATE_RETURN_A_PATH,
357 STATE_BACKTRACK, 401 STATE_BACKTRACK,
358 }; 402 };
359 403
360 CompletionStatus DoLoop(bool allow_async); 404 CompletionStatus DoLoop(bool allow_async);
361 405
362 CompletionStatus DoGetNextIssuer(bool allow_async); 406 CompletionStatus DoGetNextIssuer(bool allow_async);
363 CompletionStatus DoGetNextIssuerComplete(); 407 CompletionStatus DoGetNextIssuerComplete();
364 CompletionStatus DoBackTrack(); 408 CompletionStatus DoBackTrack();
365 409
366 void HandleGotNextIssuer(void); 410 void HandleGotNextIssuer(void);
367 411
368 // Stores the next candidate issuer certificate, until it is used during the 412 // Stores the next candidate issuer, until it is used during the
369 // STATE_GET_NEXT_ISSUER_COMPLETE step. 413 // STATE_GET_NEXT_ISSUER_COMPLETE step.
370 scoped_refptr<ParsedCertificate> next_cert_; 414 CertificateOrTrustAnchor next_issuer_;
371 // The current path being explored, made up of CertIssuerIters. Each node 415 // 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 416 // 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. 417 // when backtracking it can resume the search where it left off.
374 CertIssuerIterPath cur_path_; 418 CertIssuerIterPath cur_path_;
375 // The CertIssuerSources for retrieving candidate issuers. 419 // The CertIssuerSources for retrieving candidate issuers.
376 CertIssuerSources cert_issuer_sources_; 420 CertIssuerSources cert_issuer_sources_;
377 // The TrustStore for checking if a path ends in a trust anchor. 421 // The TrustStore for checking if a path ends in a trust anchor.
422 // TODO: is this comment correct anymore?
378 const TrustStore* trust_store_; 423 const TrustStore* trust_store_;
379 // The output variable for storing the next candidate path, which the client 424 // The output variable for storing the next candidate path, which the client
380 // passes in to GetNextPath. Only used for a single path output. 425 // passes in to GetNextPath. Only used for a single path output.
381 ParsedCertificateList* out_path_; 426 CertPath* out_path_;
382 // The callback to be called if an async lookup generated a candidate path. 427 // The callback to be called if an async lookup generated a candidate path.
383 base::Closure callback_; 428 base::Closure callback_;
384 // Current state of the state machine. 429 // Current state of the state machine.
385 State next_state_; 430 State next_state_;
386 431
387 DISALLOW_COPY_AND_ASSIGN(CertPathIter); 432 DISALLOW_COPY_AND_ASSIGN(CertPathIter);
388 }; 433 };
389 434
390 CertPathIter::CertPathIter(scoped_refptr<ParsedCertificate> cert, 435 CertPathIter::CertPathIter(scoped_refptr<ParsedCertificate> cert,
391 const TrustStore* trust_store) 436 const TrustStore* trust_store)
392 : next_cert_(std::move(cert)), 437 : next_issuer_(std::move(cert)),
393 trust_store_(trust_store), 438 trust_store_(trust_store),
394 next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {} 439 next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {}
395 440
396 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) { 441 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) {
397 cert_issuer_sources_.push_back(cert_issuer_source); 442 cert_issuer_sources_.push_back(cert_issuer_source);
398 } 443 }
399 444
400 CompletionStatus CertPathIter::GetNextPath(ParsedCertificateList* path, 445 CompletionStatus CertPathIter::GetNextPath(CertPath* path,
401 const base::Closure& callback) { 446 const base::Closure& callback) {
402 out_path_ = path; 447 out_path_ = path;
403 out_path_->clear(); 448 out_path_->Clear();
404 CompletionStatus rv = DoLoop(!callback.is_null()); 449 CompletionStatus rv = DoLoop(!callback.is_null());
405 if (rv == CompletionStatus::ASYNC) { 450 if (rv == CompletionStatus::ASYNC) {
406 callback_ = callback; 451 callback_ = callback;
407 } else { 452 } else {
408 // Clear the reference to the output parameter as a precaution. 453 // Clear the reference to the output parameter as a precaution.
409 out_path_ = nullptr; 454 out_path_ = nullptr;
410 } 455 }
411 return rv; 456 return rv;
412 } 457 }
413 458
(...skipping 25 matching lines...) Expand all
439 } 484 }
440 } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE && 485 } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE &&
441 next_state_ != STATE_RETURN_A_PATH); 486 next_state_ != STATE_RETURN_A_PATH);
442 487
443 return result; 488 return result;
444 } 489 }
445 490
446 CompletionStatus CertPathIter::DoGetNextIssuer(bool allow_async) { 491 CompletionStatus CertPathIter::DoGetNextIssuer(bool allow_async) {
447 next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE; 492 next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE;
448 CompletionStatus rv = cur_path_.back()->GetNextIssuer( 493 CompletionStatus rv = cur_path_.back()->GetNextIssuer(
449 &next_cert_, allow_async ? base::Bind(&CertPathIter::HandleGotNextIssuer, 494 &next_issuer_, allow_async
450 base::Unretained(this)) 495 ? base::Bind(&CertPathIter::HandleGotNextIssuer,
451 : base::Closure()); 496 base::Unretained(this))
497 : base::Closure());
452 return rv; 498 return rv;
453 } 499 }
454 500
455 CompletionStatus CertPathIter::DoGetNextIssuerComplete() { 501 CompletionStatus CertPathIter::DoGetNextIssuerComplete() {
456 if (next_cert_) { 502 // If the issuer is a trust anchor signal readiness.
503 if (next_issuer_.IsTrustAnchor()) {
504 DVLOG(1) << "CertPathIter got anchor("
505 << CertDebugString(next_issuer_.anchor->cert().get());
506 next_state_ = STATE_RETURN_A_PATH;
507 cur_path_.CopyPath(&out_path_->certs);
508 out_path_->trust_anchor = std::move(next_issuer_.anchor);
509 next_issuer_ = CertificateOrTrustAnchor();
510 return CompletionStatus::SYNC;
511 }
512
513 if (next_issuer_.IsCertificate()) {
457 // Skip this cert if it is already in the chain. 514 // Skip this cert if it is already in the chain.
458 if (cur_path_.IsPresent(next_cert_.get())) { 515 if (cur_path_.IsPresent(next_issuer_.cert.get())) {
459 next_state_ = STATE_GET_NEXT_ISSUER; 516 next_state_ = STATE_GET_NEXT_ISSUER;
460 return CompletionStatus::SYNC; 517 return CompletionStatus::SYNC;
461 } 518 }
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 519
475 cur_path_.Append(base::WrapUnique(new CertIssuersIter( 520 cur_path_.Append(base::WrapUnique(new CertIssuersIter(
476 std::move(next_cert_), &cert_issuer_sources_, *trust_store_))); 521 std::move(next_issuer_.cert), &cert_issuer_sources_, *trust_store_)));
477 next_cert_ = nullptr; 522 next_issuer_ = CertificateOrTrustAnchor();
478 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString(); 523 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString();
479 // Continue descending the tree. 524 // Continue descending the tree.
480 next_state_ = STATE_GET_NEXT_ISSUER; 525 next_state_ = STATE_GET_NEXT_ISSUER;
481 } else { 526 } else {
482 // TODO(mattm): should also include such paths in CertPathBuilder::Result, 527 // 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 528 // 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. 529 // 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 530 // No more issuers for current chain, go back up and see if there are any
486 // more for the previous cert. 531 // more for the previous cert.
487 next_state_ = STATE_BACKTRACK; 532 next_state_ = STATE_BACKTRACK;
(...skipping 28 matching lines...) Expand all
516 CertPathBuilder::ResultPath::~ResultPath() = default; 561 CertPathBuilder::ResultPath::~ResultPath() = default;
517 CertPathBuilder::Result::Result() = default; 562 CertPathBuilder::Result::Result() = default;
518 CertPathBuilder::Result::~Result() = default; 563 CertPathBuilder::Result::~Result() = default;
519 564
520 CertPathBuilder::CertPathBuilder(scoped_refptr<ParsedCertificate> cert, 565 CertPathBuilder::CertPathBuilder(scoped_refptr<ParsedCertificate> cert,
521 const TrustStore* trust_store, 566 const TrustStore* trust_store,
522 const SignaturePolicy* signature_policy, 567 const SignaturePolicy* signature_policy,
523 const der::GeneralizedTime& time, 568 const der::GeneralizedTime& time,
524 Result* result) 569 Result* result)
525 : cert_path_iter_(new CertPathIter(std::move(cert), trust_store)), 570 : cert_path_iter_(new CertPathIter(std::move(cert), trust_store)),
526 trust_store_(trust_store),
527 signature_policy_(signature_policy), 571 signature_policy_(signature_policy),
528 time_(time), 572 time_(time),
529 next_state_(STATE_NONE), 573 next_state_(STATE_NONE),
530 out_result_(result) {} 574 out_result_(result) {}
531 575
532 CertPathBuilder::~CertPathBuilder() {} 576 CertPathBuilder::~CertPathBuilder() {}
533 577
534 void CertPathBuilder::AddCertIssuerSource( 578 void CertPathBuilder::AddCertIssuerSource(
535 CertIssuerSource* cert_issuer_source) { 579 CertIssuerSource* cert_issuer_source) {
536 cert_path_iter_->AddCertIssuerSource(cert_issuer_source); 580 cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 } 623 }
580 624
581 void CertPathBuilder::HandleGotNextPath() { 625 void CertPathBuilder::HandleGotNextPath() {
582 DCHECK(!callback_.is_null()); 626 DCHECK(!callback_.is_null());
583 CompletionStatus rv = DoLoop(true /* allow_async */); 627 CompletionStatus rv = DoLoop(true /* allow_async */);
584 if (rv == CompletionStatus::SYNC) 628 if (rv == CompletionStatus::SYNC)
585 base::ResetAndReturn(&callback_).Run(); 629 base::ResetAndReturn(&callback_).Run();
586 } 630 }
587 631
588 CompletionStatus CertPathBuilder::DoGetNextPathComplete() { 632 CompletionStatus CertPathBuilder::DoGetNextPathComplete() {
589 if (next_path_.empty()) { 633 if (next_path_.IsEmpty()) {
590 // No more paths to check, signal completion. 634 // No more paths to check, signal completion.
591 next_state_ = STATE_NONE; 635 next_state_ = STATE_NONE;
592 return CompletionStatus::SYNC; 636 return CompletionStatus::SYNC;
593 } 637 }
594 638
595 bool verify_result = VerifyCertificateChainAssumingTrustedRoot( 639 bool verify_result =
596 next_path_, *trust_store_, signature_policy_, time_); 640 next_path_.trust_anchor.get() &&
641 VerifyCertificateChain(next_path_.certs, next_path_.trust_anchor.get(),
642 signature_policy_, time_);
597 DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = " 643 DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = "
598 << verify_result; 644 << verify_result;
599 AddResultPath(next_path_, verify_result); 645 AddResultPath(next_path_, verify_result);
600 646
601 if (verify_result) { 647 if (verify_result) {
602 // Found a valid path, return immediately. 648 // Found a valid path, return immediately.
603 // TODO(mattm): add debug/test mode that tries all possible paths. 649 // TODO(mattm): add debug/test mode that tries all possible paths.
604 next_state_ = STATE_NONE; 650 next_state_ = STATE_NONE;
605 return CompletionStatus::SYNC; 651 return CompletionStatus::SYNC;
606 } 652 }
607 653
608 // Path did not verify. Try more paths. If there are no more paths, the result 654 // 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_ 655 // will be returned next time DoGetNextPathComplete is called with next_path_
610 // empty. 656 // empty.
611 next_state_ = STATE_GET_NEXT_PATH; 657 next_state_ = STATE_GET_NEXT_PATH;
612 return CompletionStatus::SYNC; 658 return CompletionStatus::SYNC;
613 } 659 }
614 660
615 void CertPathBuilder::AddResultPath(const ParsedCertificateList& path, 661 void CertPathBuilder::AddResultPath(const CertPath& path, bool is_success) {
616 bool is_success) {
617 std::unique_ptr<ResultPath> result_path(new ResultPath()); 662 std::unique_ptr<ResultPath> result_path(new ResultPath());
618 // TODO(mattm): better error reporting. 663 // TODO(mattm): better error reporting.
619 result_path->error = is_success ? OK : ERR_CERT_AUTHORITY_INVALID; 664 result_path->error = is_success ? OK : ERR_CERT_AUTHORITY_INVALID;
620 // TODO(mattm): set best_result_index based on number or severity of errors. 665 // TODO(mattm): set best_result_index based on number or severity of errors.
621 if (result_path->error == OK) 666 if (result_path->error == OK)
622 out_result_->best_result_index = out_result_->paths.size(); 667 out_result_->best_result_index = out_result_->paths.size();
623 // TODO(mattm): add flag to only return a single path or all attempted paths? 668 // TODO(mattm): add flag to only return a single path or all attempted paths?
624 result_path->path = path; 669 result_path->path = path;
625 out_result_->paths.push_back(std::move(result_path)); 670 out_result_->paths.push_back(std::move(result_path));
626 } 671 }
627 672
628 } // namespace net 673 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698