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

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

Issue 2832703002: Allow the TrustStore interface to return matching intermediates, and identify distrusted certs. (Closed)
Patch Set: address comments Created 3 years, 7 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/logging.h" 10 #include "base/logging.h"
(...skipping 22 matching lines...) Expand all
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 // This structure contains either a ParsedCertificate or a TrustAnchor. It is 43 // This structure describes a certificate and its trust level. Note that |cert|
44 // used to describe the result of getting a certificate's issuer, which may 44 // may be null to indicate an "empty" entry.
45 // either be another certificate, or a trust anchor. 45 struct IssuerEntry {
46 struct CertificateOrTrustAnchor { 46 scoped_refptr<ParsedCertificate> cert;
47 CertificateOrTrustAnchor() {} 47 CertificateTrust trust;
48 };
48 49
49 explicit CertificateOrTrustAnchor(scoped_refptr<ParsedCertificate> cert) 50 // Simple comparator of IssuerEntry that defines the order in which issuers
50 : cert(std::move(cert)) {} 51 // should be explored. It puts trust anchors ahead of unknown or distrusted
52 // ones.
53 struct IssuerEntryComparator {
54 bool operator()(const IssuerEntry& issuer1, const IssuerEntry& issuer2) {
55 return CertificateTrustToOrder(issuer1.trust) <
56 CertificateTrustToOrder(issuer2.trust);
57 }
51 58
52 explicit CertificateOrTrustAnchor(scoped_refptr<TrustAnchor> anchor) 59 static int CertificateTrustToOrder(const CertificateTrust& trust) {
53 : anchor(std::move(anchor)) {} 60 switch (trust.type) {
61 case CertificateTrustType::TRUSTED_ANCHOR:
62 case CertificateTrustType::TRUSTED_ANCHOR_WITH_CONSTRAINTS:
63 return 1;
64 case CertificateTrustType::UNSPECIFIED:
65 return 2;
66 case CertificateTrustType::DISTRUSTED:
67 return 4;
68 }
54 69
55 bool IsTrustAnchor() const { return anchor.get() != nullptr; } 70 NOTREACHED();
56 bool IsCertificate() const { return cert.get() != nullptr; } 71 return 5;
57 bool IsEmpty() const { return !IsTrustAnchor() && !IsCertificate(); } 72 }
58
59 scoped_refptr<ParsedCertificate> cert;
60 scoped_refptr<TrustAnchor> anchor;
61 }; 73 };
62 74
63 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources| 75 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources|
64 // which may be issuers of |cert|. 76 // which may be issuers of |cert|.
65 class CertIssuersIter { 77 class CertIssuersIter {
66 public: 78 public:
67 // Constructs the CertIssuersIter. |*cert_issuer_sources| and |*trust_store| 79 // Constructs the CertIssuersIter. |*cert_issuer_sources| and |*trust_store|
68 // must be valid for the lifetime of the CertIssuersIter. 80 // must be valid for the lifetime of the CertIssuersIter.
69 CertIssuersIter(scoped_refptr<ParsedCertificate> cert, 81 CertIssuersIter(scoped_refptr<ParsedCertificate> cert,
70 CertIssuerSources* cert_issuer_sources, 82 CertIssuerSources* cert_issuer_sources,
71 const TrustStore* trust_store); 83 const TrustStore* trust_store);
72 84
73 // Gets the next candidate issuer, or clears |*out| when all issuers have been 85 // Gets the next candidate issuer, or clears |*out| when all issuers have been
74 // exhausted. 86 // exhausted.
75 void GetNextIssuer(CertificateOrTrustAnchor* out); 87 void GetNextIssuer(IssuerEntry* out);
76 88
77 // Returns the |cert| for which issuers are being retrieved. 89 // Returns the |cert| for which issuers are being retrieved.
78 const ParsedCertificate* cert() const { return cert_.get(); } 90 const ParsedCertificate* cert() const { return cert_.get(); }
79 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; } 91 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; }
80 92
81 private: 93 private:
82 void AddIssuers(ParsedCertificateList issuers); 94 void AddIssuers(ParsedCertificateList issuers);
83 void DoAsyncIssuerQuery(); 95 void DoAsyncIssuerQuery();
84 96
85 // Returns true if |issuers_| contains unconsumed certificates. 97 // Returns true if |issuers_| contains unconsumed certificates.
86 bool HasCurrentIssuer() const { return cur_issuer_ < issuers_.size(); } 98 bool HasCurrentIssuer() const { return cur_issuer_ < issuers_.size(); }
87 99
100 // Sorts the remaining entries in |issuers_| in the preferred order to
101 // explore. Does not change the ordering for indices before cur_issuer_.
102 void SortRemainingIssuers();
103
88 scoped_refptr<ParsedCertificate> cert_; 104 scoped_refptr<ParsedCertificate> cert_;
89 CertIssuerSources* cert_issuer_sources_; 105 CertIssuerSources* cert_issuer_sources_;
90 const TrustStore* trust_store_; 106 const TrustStore* trust_store_;
91 107
92 // The list of trust anchors that match the issuer name for |cert_|.
93 TrustAnchors anchors_;
94 // The index of the next trust anchor in |anchors_| to return.
95 size_t cur_anchor_ = 0;
96
97 // The list of issuers for |cert_|. This is added to incrementally (first 108 // The list of issuers for |cert_|. This is added to incrementally (first
98 // synchronous results, then possibly multiple times as asynchronous results 109 // synchronous results, then possibly multiple times as asynchronous results
99 // arrive.) The issuers may be re-sorted each time new issuers are added, but 110 // arrive.) The issuers may be re-sorted each time new issuers are added, but
100 // only the results from |cur_| onwards should be sorted, since the earlier 111 // only the results from |cur_| onwards should be sorted, since the earlier
101 // results were already returned. 112 // results were already returned.
102 // Elements should not be removed from |issuers_| once added, since 113 // Elements should not be removed from |issuers_| once added, since
103 // |present_issuers_| will point to data owned by the certs. 114 // |present_issuers_| will point to data owned by the certs.
104 ParsedCertificateList issuers_; 115 std::vector<IssuerEntry> issuers_;
105 // The index of the next cert in |issuers_| to return. 116 // The index of the next cert in |issuers_| to return.
106 size_t cur_issuer_ = 0; 117 size_t cur_issuer_ = 0;
118 // Set to true whenever new issuers are appended at the end, to indicate the
119 // ordering needs to be checked.
120 bool issuers_needs_sort_ = false;
107 121
108 // Set of DER-encoded values for the certs in |issuers_|. Used to prevent 122 // Set of DER-encoded values for the certs in |issuers_|. Used to prevent
109 // duplicates. This is based on the full DER of the cert to allow different 123 // duplicates. This is based on the full DER of the cert to allow different
110 // versions of the same certificate to be tried in different candidate paths. 124 // versions of the same certificate to be tried in different candidate paths.
111 // This points to data owned by |issuers_|. 125 // This points to data owned by |issuers_|.
112 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_; 126 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_;
113 127
114 // Tracks which requests have been made yet. 128 // Tracks which requests have been made yet.
115 bool did_initial_query_ = false; 129 bool did_initial_query_ = false;
116 bool did_async_issuer_query_ = false; 130 bool did_async_issuer_query_ = false;
117 // Index into pending_async_requests_ that is the next one to process. 131 // Index into pending_async_requests_ that is the next one to process.
118 size_t cur_async_request_ = 0; 132 size_t cur_async_request_ = 0;
119 // Owns the Request objects for any asynchronous requests so that they will be 133 // Owns the Request objects for any asynchronous requests so that they will be
120 // cancelled if CertIssuersIter is destroyed. 134 // cancelled if CertIssuersIter is destroyed.
121 std::vector<std::unique_ptr<CertIssuerSource::Request>> 135 std::vector<std::unique_ptr<CertIssuerSource::Request>>
122 pending_async_requests_; 136 pending_async_requests_;
123 137
124 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter); 138 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter);
125 }; 139 };
126 140
127 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert, 141 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert,
128 CertIssuerSources* cert_issuer_sources, 142 CertIssuerSources* cert_issuer_sources,
129 const TrustStore* trust_store) 143 const TrustStore* trust_store)
130 : cert_(in_cert), 144 : cert_(in_cert),
131 cert_issuer_sources_(cert_issuer_sources), 145 cert_issuer_sources_(cert_issuer_sources),
132 trust_store_(trust_store) { 146 trust_store_(trust_store) {
133 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created"; 147 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created";
134 } 148 }
135 149
136 void CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out) { 150 void CertIssuersIter::GetNextIssuer(IssuerEntry* out) {
137 if (!did_initial_query_) { 151 if (!did_initial_query_) {
138 did_initial_query_ = true; 152 did_initial_query_ = true;
139 trust_store_->FindTrustAnchorsForCert(cert_, &anchors_);
140
141 for (auto* cert_issuer_source : *cert_issuer_sources_) { 153 for (auto* cert_issuer_source : *cert_issuer_sources_) {
142 ParsedCertificateList new_issuers; 154 ParsedCertificateList new_issuers;
143 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers); 155 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
144 AddIssuers(std::move(new_issuers)); 156 AddIssuers(std::move(new_issuers));
145 } 157 }
146 DVLOG(1) << anchors_.size() << " sync anchors, " << issuers_.size()
147 << " sync issuers";
148 // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust
149 // anchor subject (or is a trust anchor), that should be sorted higher too.
150 // See big list of possible sorting hints in RFC 4158.)
151 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that
152 // is done)
153 } 158 }
154 159
155 // Return possible trust anchors first. 160 // If there aren't any issuers, block until async results are ready.
156 if (cur_anchor_ < anchors_.size()) {
157 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
158 << "): returning anchor " << cur_anchor_ << " of "
159 << anchors_.size();
160 // Still have anchors that haven't been returned yet, return one of them.
161 *out = CertificateOrTrustAnchor(anchors_[cur_anchor_++]);
162 return;
163 }
164
165 // If there aren't any issuers left, block until async results are ready.
166 if (!HasCurrentIssuer()) { 161 if (!HasCurrentIssuer()) {
167 if (!did_async_issuer_query_) { 162 if (!did_async_issuer_query_) {
168 // Now issue request(s) for async ones (AIA, etc). 163 // Now issue request(s) for async ones (AIA, etc).
169 DoAsyncIssuerQuery(); 164 DoAsyncIssuerQuery();
170 } 165 }
171 166
172 // TODO(eroman): Rather than blocking on the async requests in FIFO order, 167 // TODO(eroman): Rather than blocking on the async requests in FIFO order,
173 // consume in the order they become ready. 168 // consume in the order they become ready.
174 while (!HasCurrentIssuer() && 169 while (!HasCurrentIssuer() &&
175 cur_async_request_ < pending_async_requests_.size()) { 170 cur_async_request_ < pending_async_requests_.size()) {
176 ParsedCertificateList new_issuers; 171 ParsedCertificateList new_issuers;
177 pending_async_requests_[cur_async_request_]->GetNext(&new_issuers); 172 pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
178 if (new_issuers.empty()) { 173 if (new_issuers.empty()) {
179 // Request is exhausted, no more results pending from that 174 // Request is exhausted, no more results pending from that
180 // CertIssuerSource. 175 // CertIssuerSource.
181 pending_async_requests_[cur_async_request_++].reset(); 176 pending_async_requests_[cur_async_request_++].reset();
182 } else { 177 } else {
183 AddIssuers(std::move(new_issuers)); 178 AddIssuers(std::move(new_issuers));
184 } 179 }
185 } 180 }
186 } 181 }
187 182
188 if (HasCurrentIssuer()) { 183 if (HasCurrentIssuer()) {
184 SortRemainingIssuers();
185
189 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 186 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
190 << "): returning issuer " << cur_issuer_ << " of " 187 << "): returning issuer " << cur_issuer_ << " of "
191 << issuers_.size(); 188 << issuers_.size();
192 // Still have issuers that haven't been returned yet, return one of them. 189 // Still have issuers that haven't been returned yet, return the highest
193 // A reference to the returned issuer is retained, since |present_issuers_| 190 // priority one (head of remaining list). A reference to the returned issuer
194 // points to data owned by it. 191 // is retained, since |present_issuers_| points to data owned by it.
195 *out = CertificateOrTrustAnchor(issuers_[cur_issuer_++]); 192 *out = issuers_[cur_issuer_++];
196 return; 193 return;
197 } 194 }
198 195
199 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 196 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
200 << ") Reached the end of all available issuers."; 197 << ") Reached the end of all available issuers.";
201 // Reached the end of all available issuers. 198 // Reached the end of all available issuers.
202 *out = CertificateOrTrustAnchor(); 199 *out = IssuerEntry();
203 } 200 }
204 201
205 void CertIssuersIter::AddIssuers(ParsedCertificateList new_issuers) { 202 void CertIssuersIter::AddIssuers(ParsedCertificateList new_issuers) {
206 for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) { 203 for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) {
207 if (present_issuers_.find(issuer->der_cert().AsStringPiece()) != 204 if (present_issuers_.find(issuer->der_cert().AsStringPiece()) !=
208 present_issuers_.end()) 205 present_issuers_.end())
209 continue; 206 continue;
210 present_issuers_.insert(issuer->der_cert().AsStringPiece()); 207 present_issuers_.insert(issuer->der_cert().AsStringPiece());
211 issuers_.push_back(std::move(issuer)); 208
209 // Look up the trust for this issuer.
210 IssuerEntry entry;
211 entry.cert = std::move(issuer);
212 trust_store_->GetTrust(entry.cert, &entry.trust);
213
214 issuers_.push_back(std::move(entry));
215 issuers_needs_sort_ = true;
212 } 216 }
213 } 217 }
214 218
215 void CertIssuersIter::DoAsyncIssuerQuery() { 219 void CertIssuersIter::DoAsyncIssuerQuery() {
216 DCHECK(!did_async_issuer_query_); 220 DCHECK(!did_async_issuer_query_);
217 did_async_issuer_query_ = true; 221 did_async_issuer_query_ = true;
218 cur_async_request_ = 0; 222 cur_async_request_ = 0;
219 for (auto* cert_issuer_source : *cert_issuer_sources_) { 223 for (auto* cert_issuer_source : *cert_issuer_sources_) {
220 std::unique_ptr<CertIssuerSource::Request> request; 224 std::unique_ptr<CertIssuerSource::Request> request;
221 cert_issuer_source->AsyncGetIssuersOf(cert(), &request); 225 cert_issuer_source->AsyncGetIssuersOf(cert(), &request);
222 if (request) { 226 if (request) {
223 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert()) 227 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert())
224 << ") pending..."; 228 << ") pending...";
225 pending_async_requests_.push_back(std::move(request)); 229 pending_async_requests_.push_back(std::move(request));
226 } 230 }
227 } 231 }
228 } 232 }
229 233
234 void CertIssuersIter::SortRemainingIssuers() {
235 // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust
236 // anchor subject (or is a trust anchor), that should be sorted higher too.
237 // See big list of possible sorting hints in RFC 4158.)
238 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that
239 // is done)
240 if (!issuers_needs_sort_)
241 return;
242
243 std::stable_sort(issuers_.begin() + cur_issuer_, issuers_.end(),
244 IssuerEntryComparator());
245
246 issuers_needs_sort_ = false;
247 }
248
230 // CertIssuerIterPath tracks which certs are present in the path and prevents 249 // CertIssuerIterPath tracks which certs are present in the path and prevents
231 // paths from being built which repeat any certs (including different versions 250 // paths from being built which repeat any certs (including different versions
232 // of the same cert, based on Subject+SubjectAltName+SPKI). 251 // of the same cert, based on Subject+SubjectAltName+SPKI).
233 class CertIssuerIterPath { 252 class CertIssuerIterPath {
234 public: 253 public:
235 // Returns true if |cert| is already present in the path. 254 // Returns true if |cert| is already present in the path.
236 bool IsPresent(const ParsedCertificate* cert) const { 255 bool IsPresent(const ParsedCertificate* cert) const {
237 return present_certs_.find(GetKey(cert)) != present_certs_.end(); 256 return present_certs_.find(GetKey(cert)) != present_certs_.end();
238 } 257 }
239 258
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 // TODO(mattm): use unordered_set. Requires making a hash function for Key. 317 // TODO(mattm): use unordered_set. Requires making a hash function for Key.
299 std::set<Key> present_certs_; 318 std::set<Key> present_certs_;
300 }; 319 };
301 320
302 } // namespace 321 } // namespace
303 322
304 CertPath::CertPath() = default; 323 CertPath::CertPath() = default;
305 CertPath::~CertPath() = default; 324 CertPath::~CertPath() = default;
306 325
307 void CertPath::Clear() { 326 void CertPath::Clear() {
308 trust_anchor = nullptr; 327 last_cert_trust = CertificateTrust::ForUnspecified();
309 certs.clear(); 328 certs.clear();
310 } 329 }
311 330
312 bool CertPath::IsEmpty() const { 331 bool CertPath::IsEmpty() const {
313 return certs.empty(); 332 return certs.empty();
314 } 333 }
315 334
335 const ParsedCertificate* CertPath::GetTrustedCert() const {
336 if (certs.empty())
337 return nullptr;
338
339 switch (last_cert_trust.type) {
340 case CertificateTrustType::TRUSTED_ANCHOR:
341 case CertificateTrustType::TRUSTED_ANCHOR_WITH_CONSTRAINTS:
342 return certs.back().get();
343 case CertificateTrustType::UNSPECIFIED:
344 case CertificateTrustType::DISTRUSTED:
345 return nullptr;
346 }
347
348 NOTREACHED();
349 return nullptr;
350 }
351
316 // CertPathIter generates possible paths from |cert| to a trust anchor in 352 // CertPathIter generates possible paths from |cert| to a trust anchor in
317 // |trust_store|, using intermediates from the |cert_issuer_source| objects if 353 // |trust_store|, using intermediates from the |cert_issuer_source| objects if
318 // necessary. 354 // necessary.
319 class CertPathIter { 355 class CertPathIter {
320 public: 356 public:
321 CertPathIter(scoped_refptr<ParsedCertificate> cert, 357 CertPathIter(scoped_refptr<ParsedCertificate> cert,
322 const TrustStore* trust_store); 358 const TrustStore* trust_store);
323 359
324 // Adds a CertIssuerSource to provide intermediates for use in path building. 360 // Adds a CertIssuerSource to provide intermediates for use in path building.
325 // The |*cert_issuer_source| must remain valid for the lifetime of the 361 // The |*cert_issuer_source| must remain valid for the lifetime of the
(...skipping 12 matching lines...) Expand all
338 STATE_RETURN_A_PATH, 374 STATE_RETURN_A_PATH,
339 STATE_BACKTRACK, 375 STATE_BACKTRACK,
340 }; 376 };
341 377
342 void DoGetNextIssuer(); 378 void DoGetNextIssuer();
343 void DoGetNextIssuerComplete(); 379 void DoGetNextIssuerComplete();
344 void DoBackTrack(); 380 void DoBackTrack();
345 381
346 // Stores the next candidate issuer, until it is used during the 382 // Stores the next candidate issuer, until it is used during the
347 // STATE_GET_NEXT_ISSUER_COMPLETE step. 383 // STATE_GET_NEXT_ISSUER_COMPLETE step.
348 CertificateOrTrustAnchor next_issuer_; 384 IssuerEntry next_issuer_;
349 // The current path being explored, made up of CertIssuerIters. Each node 385 // The current path being explored, made up of CertIssuerIters. Each node
350 // keeps track of the state of searching for issuers of that cert, so that 386 // keeps track of the state of searching for issuers of that cert, so that
351 // when backtracking it can resume the search where it left off. 387 // when backtracking it can resume the search where it left off.
352 CertIssuerIterPath cur_path_; 388 CertIssuerIterPath cur_path_;
353 // The CertIssuerSources for retrieving candidate issuers. 389 // The CertIssuerSources for retrieving candidate issuers.
354 CertIssuerSources cert_issuer_sources_; 390 CertIssuerSources cert_issuer_sources_;
355 // The TrustStore for checking if a path ends in a trust anchor. 391 // The TrustStore for checking if a path ends in a trust anchor.
356 const TrustStore* trust_store_; 392 const TrustStore* trust_store_;
357 // The output variable for storing the next candidate path, which the client 393 // The output variable for storing the next candidate path, which the client
358 // passes in to GetNextPath. Only used for a single path output. 394 // passes in to GetNextPath. Only used for a single path output.
359 CertPath* out_path_; 395 CertPath* out_path_;
360 // Current state of the state machine. 396 // Current state of the state machine.
361 State next_state_; 397 State next_state_;
362 398
363 DISALLOW_COPY_AND_ASSIGN(CertPathIter); 399 DISALLOW_COPY_AND_ASSIGN(CertPathIter);
364 }; 400 };
365 401
366 CertPathIter::CertPathIter(scoped_refptr<ParsedCertificate> cert, 402 CertPathIter::CertPathIter(scoped_refptr<ParsedCertificate> cert,
367 const TrustStore* trust_store) 403 const TrustStore* trust_store)
368 : next_issuer_(std::move(cert)), 404 : trust_store_(trust_store), next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {
369 trust_store_(trust_store), 405 // Initialize |next_issuer_| to the target certificate.
370 next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {} 406 next_issuer_.cert = std::move(cert);
407 trust_store_->GetTrust(next_issuer_.cert, &next_issuer_.trust);
408 }
371 409
372 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) { 410 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) {
373 cert_issuer_sources_.push_back(cert_issuer_source); 411 cert_issuer_sources_.push_back(cert_issuer_source);
374 } 412 }
375 413
376 // TODO(eroman): Simplify (doesn't need to use the "DoLoop" pattern). 414 // TODO(eroman): Simplify (doesn't need to use the "DoLoop" pattern).
377 void CertPathIter::GetNextPath(CertPath* path) { 415 void CertPathIter::GetNextPath(CertPath* path) {
378 out_path_ = path; 416 out_path_ = path;
379 out_path_->Clear(); 417 out_path_->Clear();
380 do { 418 do {
(...skipping 18 matching lines...) Expand all
399 case STATE_BACKTRACK: 437 case STATE_BACKTRACK:
400 DoBackTrack(); 438 DoBackTrack();
401 break; 439 break;
402 } 440 }
403 } while (next_state_ != STATE_NONE && next_state_ != STATE_RETURN_A_PATH); 441 } while (next_state_ != STATE_NONE && next_state_ != STATE_RETURN_A_PATH);
404 442
405 out_path_ = nullptr; 443 out_path_ = nullptr;
406 } 444 }
407 445
408 void CertPathIter::DoGetNextIssuer() { 446 void CertPathIter::DoGetNextIssuer() {
409 next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE; 447 if (cur_path_.Empty()) {
410 cur_path_.back()->GetNextIssuer(&next_issuer_); 448 // Exhausted all paths.
449 next_state_ = STATE_NONE;
450 } else {
451 next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE;
452 cur_path_.back()->GetNextIssuer(&next_issuer_);
453 }
411 } 454 }
412 455
413 void CertPathIter::DoGetNextIssuerComplete() { 456 void CertPathIter::DoGetNextIssuerComplete() {
414 // If the issuer is a trust anchor signal readiness. 457 if (!next_issuer_.cert) {
415 if (next_issuer_.IsTrustAnchor()) {
416 DVLOG(1) << "CertPathIter got anchor("
417 << CertDebugString(next_issuer_.anchor->cert().get());
418 next_state_ = STATE_RETURN_A_PATH;
419 cur_path_.CopyPath(&out_path_->certs);
420 out_path_->trust_anchor = std::move(next_issuer_.anchor);
421 next_issuer_ = CertificateOrTrustAnchor();
422 return;
423 }
424
425 if (next_issuer_.IsCertificate()) {
426 // Skip this cert if it is already in the chain.
427 if (cur_path_.IsPresent(next_issuer_.cert.get())) {
428 next_state_ = STATE_GET_NEXT_ISSUER;
429 return;
430 }
431
432 cur_path_.Append(base::MakeUnique<CertIssuersIter>(
433 std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_));
434 next_issuer_ = CertificateOrTrustAnchor();
435 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString();
436 // Continue descending the tree.
437 next_state_ = STATE_GET_NEXT_ISSUER;
438 } else {
439 // TODO(mattm): should also include such paths in CertPathBuilder::Result, 458 // TODO(mattm): should also include such paths in CertPathBuilder::Result,
440 // maybe with a flag to enable it. Or use a visitor pattern so the caller 459 // maybe with a flag to enable it. Or use a visitor pattern so the caller
441 // can decide what to do with any failed paths. 460 // can decide what to do with any failed paths.
442 // No more issuers for current chain, go back up and see if there are any 461 // No more issuers for current chain, go back up and see if there are any
443 // more for the previous cert. 462 // more for the previous cert.
444 next_state_ = STATE_BACKTRACK; 463 next_state_ = STATE_BACKTRACK;
464 return;
465 }
466
467 switch (next_issuer_.trust.type) {
468 // If the trust for this issuer is "known" (either becuase it is distrusted,
469 // or because it is trusted) then stop building and return the path.
470 case CertificateTrustType::DISTRUSTED:
471 case CertificateTrustType::TRUSTED_ANCHOR:
472 case CertificateTrustType::TRUSTED_ANCHOR_WITH_CONSTRAINTS: {
473 // If the issuer has a known trust level, can stop building the path.
474 DVLOG(1) << "CertPathIter got anchor: "
475 << CertDebugString(next_issuer_.cert.get());
476 next_state_ = STATE_RETURN_A_PATH;
477 cur_path_.CopyPath(&out_path_->certs);
478 out_path_->certs.push_back(std::move(next_issuer_.cert));
479 out_path_->last_cert_trust = next_issuer_.trust;
480 next_issuer_ = IssuerEntry();
481 break;
482 }
483 case CertificateTrustType::UNSPECIFIED: {
484 // Skip this cert if it is already in the chain.
485 if (cur_path_.IsPresent(next_issuer_.cert.get())) {
486 next_state_ = STATE_GET_NEXT_ISSUER;
487 break;
488 }
489
490 cur_path_.Append(base::MakeUnique<CertIssuersIter>(
491 std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_));
492 next_issuer_ = IssuerEntry();
493 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString();
494 // Continue descending the tree.
495 next_state_ = STATE_GET_NEXT_ISSUER;
496 break;
497 }
445 } 498 }
446 } 499 }
447 500
448 void CertPathIter::DoBackTrack() { 501 void CertPathIter::DoBackTrack() {
449 DVLOG(1) << "CertPathIter backtracking..."; 502 DVLOG(1) << "CertPathIter backtracking...";
450 cur_path_.Pop(); 503 cur_path_.Pop();
451 if (cur_path_.Empty()) { 504 if (cur_path_.Empty()) {
452 // Exhausted all paths. 505 // Exhausted all paths.
453 next_state_ = STATE_NONE; 506 next_state_ = STATE_NONE;
454 } else { 507 } else {
455 // Continue exploring issuers of the previous path. 508 // Continue exploring issuers of the previous path.
456 next_state_ = STATE_GET_NEXT_ISSUER; 509 next_state_ = STATE_GET_NEXT_ISSUER;
457 } 510 }
458 } 511 }
459 512
460 CertPathBuilder::ResultPath::ResultPath() = default; 513 CertPathBuilder::ResultPath::ResultPath() = default;
461 CertPathBuilder::ResultPath::~ResultPath() = default; 514 CertPathBuilder::ResultPath::~ResultPath() = default;
462 515
463 bool CertPathBuilder::ResultPath::IsValid() const { 516 bool CertPathBuilder::ResultPath::IsValid() const {
464 return !path.certs.empty() && path.trust_anchor && 517 return path.GetTrustedCert() && !errors.ContainsHighSeverityErrors();
465 !errors.ContainsHighSeverityErrors();
466 } 518 }
467 519
468 CertPathBuilder::Result::Result() = default; 520 CertPathBuilder::Result::Result() = default;
469 CertPathBuilder::Result::~Result() = default; 521 CertPathBuilder::Result::~Result() = default;
470 522
471 const CertPathBuilder::ResultPath* CertPathBuilder::Result::GetBestValidPath() 523 const CertPathBuilder::ResultPath* CertPathBuilder::Result::GetBestValidPath()
472 const { 524 const {
473 DCHECK((paths.empty() && best_result_index == 0) || 525 DCHECK((paths.empty() && best_result_index == 0) ||
474 best_result_index < paths.size()); 526 best_result_index < paths.size());
475 527
476 if (best_result_index >= paths.size()) 528 if (best_result_index >= paths.size())
477 return nullptr; 529 return nullptr;
478 530
479 const ResultPath* result_path = paths[best_result_index].get(); 531 const ResultPath* result_path = paths[best_result_index].get();
480 if (result_path->IsValid()) 532 if (result_path->IsValid())
481 return result_path; 533 return result_path;
482 534
483 return nullptr; 535 return nullptr;
484 } 536 }
485 537
486 bool CertPathBuilder::Result::HasValidPath() const { 538 bool CertPathBuilder::Result::HasValidPath() const {
487 return GetBestValidPath() != nullptr; 539 return GetBestValidPath() != nullptr;
488 } 540 }
489 541
490 CertPathBuilder::CertPathBuilder(scoped_refptr<ParsedCertificate> cert, 542 CertPathBuilder::CertPathBuilder(scoped_refptr<ParsedCertificate> cert,
491 const TrustStore* trust_store, 543 TrustStore* trust_store,
492 const SignaturePolicy* signature_policy, 544 const SignaturePolicy* signature_policy,
493 const der::GeneralizedTime& time, 545 const der::GeneralizedTime& time,
494 KeyPurpose key_purpose, 546 KeyPurpose key_purpose,
495 Result* result) 547 Result* result)
496 : cert_path_iter_(new CertPathIter(std::move(cert), trust_store)), 548 : cert_path_iter_(new CertPathIter(std::move(cert), trust_store)),
497 signature_policy_(signature_policy), 549 signature_policy_(signature_policy),
498 time_(time), 550 time_(time),
499 key_purpose_(key_purpose), 551 key_purpose_(key_purpose),
500 next_state_(STATE_NONE), 552 next_state_(STATE_NONE),
501 out_result_(result) {} 553 out_result_(result) {
554 // The TrustStore also implements the CertIssuerSource interface.
555 AddCertIssuerSource(trust_store);
556 }
502 557
503 CertPathBuilder::~CertPathBuilder() {} 558 CertPathBuilder::~CertPathBuilder() {}
504 559
505 void CertPathBuilder::AddCertIssuerSource( 560 void CertPathBuilder::AddCertIssuerSource(
506 CertIssuerSource* cert_issuer_source) { 561 CertIssuerSource* cert_issuer_source) {
507 cert_path_iter_->AddCertIssuerSource(cert_issuer_source); 562 cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
508 } 563 }
509 564
510 // TODO(eroman): Simplify (doesn't need to use the "DoLoop" pattern). 565 // TODO(eroman): Simplify (doesn't need to use the "DoLoop" pattern).
511 void CertPathBuilder::Run() { 566 void CertPathBuilder::Run() {
(...skipping 24 matching lines...) Expand all
536 591
537 void CertPathBuilder::DoGetNextPathComplete() { 592 void CertPathBuilder::DoGetNextPathComplete() {
538 if (next_path_.IsEmpty()) { 593 if (next_path_.IsEmpty()) {
539 // No more paths to check, signal completion. 594 // No more paths to check, signal completion.
540 next_state_ = STATE_NONE; 595 next_state_ = STATE_NONE;
541 return; 596 return;
542 } 597 }
543 598
544 // Verify the entire certificate chain. 599 // Verify the entire certificate chain.
545 auto result_path = base::MakeUnique<ResultPath>(); 600 auto result_path = base::MakeUnique<ResultPath>();
546 bool verify_result = VerifyCertificateChain( 601 VerifyCertificateChain(next_path_.certs, next_path_.last_cert_trust,
547 next_path_.certs, next_path_.trust_anchor.get(), signature_policy_, time_, 602 signature_policy_, time_, key_purpose_,
548 key_purpose_, &result_path->errors); 603 &result_path->errors);
604 bool verify_result = !result_path->errors.ContainsHighSeverityErrors();
605
549 DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = " 606 DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = "
550 << verify_result; 607 << verify_result << "\n"
608 << result_path->errors.ToDebugString(next_path_.certs);
551 result_path->path = next_path_; 609 result_path->path = next_path_;
552 DCHECK_EQ(verify_result, !result_path->errors.ContainsHighSeverityErrors());
553 AddResultPath(std::move(result_path)); 610 AddResultPath(std::move(result_path));
554 611
555 if (verify_result) { 612 if (verify_result) {
556 // Found a valid path, return immediately. 613 // Found a valid path, return immediately.
557 // TODO(mattm): add debug/test mode that tries all possible paths. 614 // TODO(mattm): add debug/test mode that tries all possible paths.
558 next_state_ = STATE_NONE; 615 next_state_ = STATE_NONE;
559 return; 616 return;
560 } 617 }
561 618
562 // Path did not verify. Try more paths. If there are no more paths, the result 619 // Path did not verify. Try more paths. If there are no more paths, the result
563 // will be returned next time DoGetNextPathComplete is called with next_path_ 620 // will be returned next time DoGetNextPathComplete is called with next_path_
564 // empty. 621 // empty.
565 next_state_ = STATE_GET_NEXT_PATH; 622 next_state_ = STATE_GET_NEXT_PATH;
566 } 623 }
567 624
568 void CertPathBuilder::AddResultPath(std::unique_ptr<ResultPath> result_path) { 625 void CertPathBuilder::AddResultPath(std::unique_ptr<ResultPath> result_path) {
569 // TODO(mattm): set best_result_index based on number or severity of errors. 626 // TODO(mattm): set best_result_index based on number or severity of errors.
570 if (result_path->IsValid()) 627 if (result_path->IsValid())
571 out_result_->best_result_index = out_result_->paths.size(); 628 out_result_->best_result_index = out_result_->paths.size();
572 // TODO(mattm): add flag to only return a single path or all attempted paths? 629 // TODO(mattm): add flag to only return a single path or all attempted paths?
573 out_result_->paths.push_back(std::move(result_path)); 630 out_result_->paths.push_back(std::move(result_path));
574 } 631 }
575 632
576 } // namespace net 633 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698