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

Side by Side Diff: net/cert/cert_verify_proc_builtin.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 (c) 2017 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2017 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/cert_verify_proc_builtin.h" 5 #include "net/cert/cert_verify_proc_builtin.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 base::SHA1HashBytes(spki_bytes.UnsafeData(), spki_bytes.Length(), 96 base::SHA1HashBytes(spki_bytes.UnsafeData(), spki_bytes.Length(),
97 sha1.data()); 97 sha1.data());
98 hashes->push_back(sha1); 98 hashes->push_back(sha1);
99 99
100 HashValue sha256(HASH_VALUE_SHA256); 100 HashValue sha256(HASH_VALUE_SHA256);
101 crypto::SHA256HashString(spki_bytes.AsStringPiece(), sha256.data(), 101 crypto::SHA256HashString(spki_bytes.AsStringPiece(), sha256.data(),
102 crypto::kSHA256Length); 102 crypto::kSHA256Length);
103 hashes->push_back(sha256); 103 hashes->push_back(sha256);
104 } 104 }
105 105
106 // Appends the SubjectPublicKeyInfo hashes for all certificates (and trust 106 // Appends the SubjectPublicKeyInfo hashes for all certificates in
107 // anchor) in |partial_path| to |*hashes|. 107 // |partial_path| to |*hashes|.
108 void AppendPublicKeyHashes(const CertPathBuilder::ResultPath& partial_path, 108 void AppendPublicKeyHashes(const CertPathBuilder::ResultPath& partial_path,
109 HashValueVector* hashes) { 109 HashValueVector* hashes) {
110 for (const scoped_refptr<ParsedCertificate>& cert : partial_path.path.certs) 110 for (const scoped_refptr<ParsedCertificate>& cert : partial_path.path.certs)
111 AppendPublicKeyHashes(cert->tbs().spki_tlv, hashes); 111 AppendPublicKeyHashes(cert->tbs().spki_tlv, hashes);
112
113 if (partial_path.path.trust_anchor)
114 AppendPublicKeyHashes(partial_path.path.trust_anchor->spki(), hashes);
115 } 112 }
116 113
117 // Sets the bits on |cert_status| for all the errors present in |errors| (the 114 // Sets the bits on |cert_status| for all the errors present in |errors| (the
118 // errors for a particular path). 115 // errors for a particular path).
119 void MapPathBuilderErrorsToCertStatus(const CertPathErrors& errors, 116 void MapPathBuilderErrorsToCertStatus(const CertPathErrors& errors,
120 CertStatus* cert_status) { 117 CertStatus* cert_status) {
121 // If there were no errors, nothing to do. 118 // If there were no errors, nothing to do.
122 if (!errors.ContainsHighSeverityErrors()) 119 if (!errors.ContainsHighSeverityErrors())
123 return; 120 return;
124 121
(...skipping 27 matching lines...) Expand all
152 // * |path|: The result (possibly failed) from path building. 149 // * |path|: The result (possibly failed) from path building.
153 scoped_refptr<X509Certificate> CreateVerifiedCertChain( 150 scoped_refptr<X509Certificate> CreateVerifiedCertChain(
154 X509Certificate* target_cert, 151 X509Certificate* target_cert,
155 const CertPathBuilder::ResultPath& path) { 152 const CertPathBuilder::ResultPath& path) {
156 X509Certificate::OSCertHandles intermediates; 153 X509Certificate::OSCertHandles intermediates;
157 154
158 // Skip the first certificate in the path as that is the target certificate 155 // Skip the first certificate in the path as that is the target certificate
159 for (size_t i = 1; i < path.path.certs.size(); ++i) 156 for (size_t i = 1; i < path.path.certs.size(); ++i)
160 intermediates.push_back(CreateOSCertHandle(path.path.certs[i])); 157 intermediates.push_back(CreateOSCertHandle(path.path.certs[i]));
161 158
162 if (path.path.trust_anchor) {
163 // TODO(eroman): This assumes that TrustAnchor::cert() cannot be null,
164 // which disagrees with the documentation.
165 intermediates.push_back(CreateOSCertHandle(path.path.trust_anchor->cert()));
166 }
167
168 scoped_refptr<X509Certificate> result = X509Certificate::CreateFromHandle( 159 scoped_refptr<X509Certificate> result = X509Certificate::CreateFromHandle(
169 target_cert->os_cert_handle(), intermediates); 160 target_cert->os_cert_handle(), intermediates);
170 // |target_cert| was already successfully parsed, so this should never fail. 161 // |target_cert| was already successfully parsed, so this should never fail.
171 DCHECK(result); 162 DCHECK(result);
172 163
173 for (const X509Certificate::OSCertHandle handle : intermediates) 164 for (const X509Certificate::OSCertHandle handle : intermediates)
174 X509Certificate::FreeOSCertHandle(handle); 165 X509Certificate::FreeOSCertHandle(handle);
175 166
176 return result; 167 return result;
177 } 168 }
(...skipping 20 matching lines...) Expand all
198 verify_result->cert_status |= CERT_STATUS_INVALID; 189 verify_result->cert_status |= CERT_STATUS_INVALID;
199 return; 190 return;
200 } 191 }
201 192
202 std::unique_ptr<SystemTrustStore> ssl_trust_store = 193 std::unique_ptr<SystemTrustStore> ssl_trust_store =
203 CreateSslSystemTrustStore(); 194 CreateSslSystemTrustStore();
204 195
205 for (const auto& x509_cert : additional_trust_anchors) { 196 for (const auto& x509_cert : additional_trust_anchors) {
206 scoped_refptr<ParsedCertificate> cert = ParseCertificateFromOSHandle( 197 scoped_refptr<ParsedCertificate> cert = ParseCertificateFromOSHandle(
207 x509_cert->os_cert_handle(), &parsing_errors); 198 x509_cert->os_cert_handle(), &parsing_errors);
208 if (cert) { 199 if (cert)
209 ssl_trust_store->AddTrustAnchor( 200 ssl_trust_store->AddTrustAnchor(cert);
210 TrustAnchor::CreateFromCertificateNoConstraints(std::move(cert)));
211 }
212 // TODO(eroman): Surface parsing errors of additional trust anchor. 201 // TODO(eroman): Surface parsing errors of additional trust anchor.
213 } 202 }
214 203
215 // TODO(eroman): The path building code in this file enforces its idea of weak 204 // TODO(eroman): The path building code in this file enforces its idea of weak
216 // keys, and separately cert_verify_proc.cc also checks the chains with its 205 // keys, and separately cert_verify_proc.cc also checks the chains with its
217 // own policy. These policies should be aligned, to give path building the 206 // own policy. These policies should be aligned, to give path building the
218 // best chance of finding a good path. 207 // best chance of finding a good path.
219 // Another difference to resolve is the path building here does not check the 208 // Another difference to resolve is the path building here does not check the
220 // target certificate's key strength, whereas cert_verify_proc.cc does. 209 // target certificate's key strength, whereas cert_verify_proc.cc does.
221 SimpleSignaturePolicy signature_policy(1024); 210 SimpleSignaturePolicy signature_policy(1024);
222 211
223 // Use the current time. 212 // Use the current time.
224 der::GeneralizedTime verification_time; 213 der::GeneralizedTime verification_time;
225 if (!der::EncodeTimeAsGeneralizedTime(base::Time::Now(), 214 if (!der::EncodeTimeAsGeneralizedTime(base::Time::Now(),
226 &verification_time)) { 215 &verification_time)) {
227 // This really shouldn't be possible unless Time::Now() returned 216 // This really shouldn't be possible unless Time::Now() returned
228 // something crazy. 217 // something crazy.
229 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 218 verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
230 return; 219 return;
231 } 220 }
232 221
233 // Initialize the path builder. 222 // Initialize the path builder.
234 CertPathBuilder::Result result; 223 CertPathBuilder::Result result;
235 CertPathBuilder path_builder(target, ssl_trust_store->GetTrustStore(), 224 CertPathBuilder path_builder(target, ssl_trust_store->GetTrustStore(),
236 &signature_policy, verification_time, 225 &signature_policy, verification_time,
237 KeyPurpose::SERVER_AUTH, &result); 226 KeyPurpose::SERVER_AUTH, &result);
238 227
239 // Allow the path builder to discover intermediates from the trust store.
240 if (ssl_trust_store->GetCertIssuerSource())
241 path_builder.AddCertIssuerSource(ssl_trust_store->GetCertIssuerSource());
242
243 // Allow the path builder to discover the explicitly provided intermediates in 228 // Allow the path builder to discover the explicitly provided intermediates in
244 // |input_cert|. 229 // |input_cert|.
245 CertIssuerSourceStatic intermediates; 230 CertIssuerSourceStatic intermediates;
246 AddIntermediatesToIssuerSource(input_cert, &intermediates); 231 AddIntermediatesToIssuerSource(input_cert, &intermediates);
247 path_builder.AddCertIssuerSource(&intermediates); 232 path_builder.AddCertIssuerSource(&intermediates);
248 233
249 // TODO(crbug.com/649017): Allow the path builder to discover intermediates 234 // TODO(crbug.com/649017): Allow the path builder to discover intermediates
250 // through AIA fetching. 235 // through AIA fetching.
251 236
252 path_builder.Run(); 237 path_builder.Run();
253 238
254 if (result.best_result_index >= result.paths.size()) { 239 if (result.best_result_index >= result.paths.size()) {
255 // TODO(crbug.com/634443): What errors to communicate? Maybe the path 240 // TODO(crbug.com/634443): What errors to communicate? Maybe the path
256 // builder should always return some partial path (even if just containing 241 // builder should always return some partial path (even if just containing
257 // the target), then there is a CertErrors to test. 242 // the target), then there is a CertErrors to test.
258 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; 243 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
259 return; 244 return;
260 } 245 }
261 246
262 // Use the best path that was built. This could be a partial path, or it could 247 // Use the best path that was built. This could be a partial path, or it could
263 // be a valid complete path. 248 // be a valid complete path.
264 const CertPathBuilder::ResultPath& partial_path = 249 const CertPathBuilder::ResultPath& partial_path =
265 *result.paths[result.best_result_index].get(); 250 *result.paths[result.best_result_index].get();
266 251
267 if (partial_path.path.trust_anchor) { 252 const ParsedCertificate* trusted_cert = partial_path.path.GetTrustedCert();
253 if (trusted_cert) {
268 verify_result->is_issued_by_known_root = 254 verify_result->is_issued_by_known_root =
269 ssl_trust_store->IsKnownRoot(partial_path.path.trust_anchor); 255 ssl_trust_store->IsKnownRoot(trusted_cert);
270 256
271 verify_result->is_issued_by_additional_trust_anchor = 257 verify_result->is_issued_by_additional_trust_anchor =
272 ssl_trust_store->IsAdditionalTrustAnchor( 258 ssl_trust_store->IsAdditionalTrustAnchor(trusted_cert);
273 partial_path.path.trust_anchor);
274 } else {
275 // TODO(eroman): This shouldn't be necessary -- partial_path.errors should
276 // contain an error if it didn't chain to trust anchor.
277 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
278 } 259 }
279 260
280 verify_result->verified_cert = 261 verify_result->verified_cert =
281 CreateVerifiedCertChain(input_cert, partial_path); 262 CreateVerifiedCertChain(input_cert, partial_path);
282 263
283 AppendPublicKeyHashes(partial_path, &verify_result->public_key_hashes); 264 AppendPublicKeyHashes(partial_path, &verify_result->public_key_hashes);
284 MapPathBuilderErrorsToCertStatus(partial_path.errors, 265 MapPathBuilderErrorsToCertStatus(partial_path.errors,
285 &verify_result->cert_status); 266 &verify_result->cert_status);
286 267
287 // TODO(eroman): Is it possible that IsValid() fails but no errors were set in 268 // TODO(eroman): Is it possible that IsValid() fails but no errors were set in
(...skipping 23 matching lines...) Expand all
311 : OK; 292 : OK;
312 } 293 }
313 294
314 } // namespace 295 } // namespace
315 296
316 scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin() { 297 scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin() {
317 return scoped_refptr<CertVerifyProc>(new CertVerifyProcBuiltin()); 298 return scoped_refptr<CertVerifyProc>(new CertVerifyProcBuiltin());
318 } 299 }
319 300
320 } // namespace net 301 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698