OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |