OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/base/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
6 | 6 |
7 #include <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
8 #include <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
9 #include <Security/Security.h> | 9 #include <Security/Security.h> |
10 #include <time.h> | 10 #include <time.h> |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 status = X509Certificate::CreateRevocationPolicies( | 279 status = X509Certificate::CreateRevocationPolicies( |
280 (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED), | 280 (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED), |
281 local_policies); | 281 local_policies); |
282 if (status) | 282 if (status) |
283 return status; | 283 return status; |
284 | 284 |
285 policies->reset(local_policies.release()); | 285 policies->reset(local_policies.release()); |
286 return noErr; | 286 return noErr; |
287 } | 287 } |
288 | 288 |
289 // Saves some information about the certificate chain |cert_chain| in | |
290 // |*verify_result|. The caller MUST initialize |*verify_result| before | |
291 // calling this function. | |
292 void GetCertChainInfo(CFArrayRef cert_chain, | |
293 CSSM_TP_APPLE_EVIDENCE_INFO* chain_info, | |
294 CertVerifyResult* verify_result) { | |
295 SecCertificateRef verified_cert = NULL; | |
296 std::vector<SecCertificateRef> verified_chain; | |
297 for (CFIndex i = 0, count = CFArrayGetCount(cert_chain); i < count; ++i) { | |
298 SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>( | |
299 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); | |
300 if (i == 0) { | |
301 verified_cert = chain_cert; | |
302 } else { | |
303 verified_chain.push_back(chain_cert); | |
304 } | |
305 | |
306 if ((chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_IN_ANCHORS) || | |
307 (chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_ROOT)) { | |
308 // The current certificate is either in the user's trusted store or is | |
309 // a root (self-signed) certificate. Ignore the signature algorithm for | |
310 // these certificates, as it is meaningless for security. We allow | |
311 // self-signed certificates (i == 0 & IS_ROOT), since we accept that | |
312 // any security assertions by such a cert are inherently meaningless. | |
313 continue; | |
314 } | |
315 | |
316 CSSMFields cssm_fields; | |
317 OSStatus status = GetCertFields(chain_cert, &cssm_fields); | |
318 if (status) | |
319 continue; | |
320 CSSM_FIELD_PTR fields = cssm_fields.fields; | |
321 for (size_t field = 0; field < cssm_fields.num_of_fields; ++field) { | |
322 if (!CSSMOIDEqual(&fields[field].FieldOid, | |
323 &CSSMOID_X509V1SignatureAlgorithm)) { | |
324 continue; | |
325 } | |
326 | |
327 CSSM_X509_ALGORITHM_IDENTIFIER* signature_algorithm = | |
328 reinterpret_cast<CSSM_X509_ALGORITHM_IDENTIFIER*>( | |
329 fields[field].FieldValue.Data); | |
330 // Match the behaviour of OS X system tools and defensively check that | |
wtc
2011/11/02 00:28:43
Do OS X system tools really do these defensive che
Ryan Sleevi
2011/11/02 02:35:16
http://www.opensource.apple.com/source/libsecurity
wtc
2011/11/02 19:26:57
Thank you for the reference. You're still more de
| |
331 // sizes are appropriate. This would indicate a critical failure of the | |
332 // OS X certificate library, but based on history, it is best to play it | |
333 // safe. | |
334 if (!signature_algorithm || (fields[field].FieldValue.Length != | |
335 sizeof(CSSM_X509_ALGORITHM_IDENTIFIER))) { | |
336 break; | |
337 } | |
338 CSSM_OID_PTR alg_oid = &signature_algorithm->algorithm; | |
339 if (CSSMOIDEqual(alg_oid, &CSSMOID_MD2) || | |
340 CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA)) { | |
341 verify_result->has_md2 = true; | |
342 if (i != 0) | |
343 verify_result->has_md2_ca = true; | |
344 } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD4) || | |
345 CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA)) { | |
346 verify_result->has_md4 = true; | |
347 } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD5) || | |
348 CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA)) { | |
wtc
2011/11/02 00:28:43
I'm not convinced that we need to allow CSSMOID_MD
Ryan Sleevi
2011/11/02 02:35:16
The concern was if Apple's TP maps them under the
wtc
2011/11/02 19:26:57
Thank you for checking.
If Apple's TP allows such
| |
349 verify_result->has_md5 = true; | |
350 if (i != 0) | |
351 verify_result->has_md5_ca = true; | |
352 } | |
353 break; | |
354 } | |
355 } | |
356 if (!verified_cert) | |
357 return; | |
358 | |
359 verify_result->verified_cert = | |
360 X509Certificate::CreateFromHandle(verified_cert, verified_chain); | |
361 } | |
362 | |
289 // Gets the issuer for a given cert, starting with the cert itself and | 363 // Gets the issuer for a given cert, starting with the cert itself and |
290 // including the intermediate and finally root certificates (if any). | 364 // including the intermediate and finally root certificates (if any). |
291 // This function calls SecTrust but doesn't actually pay attention to the trust | 365 // This function calls SecTrust but doesn't actually pay attention to the trust |
292 // result: it shouldn't be used to determine trust, just to traverse the chain. | 366 // result: it shouldn't be used to determine trust, just to traverse the chain. |
293 // Caller is responsible for releasing the value stored into *out_cert_chain. | 367 // Caller is responsible for releasing the value stored into *out_cert_chain. |
294 OSStatus CopyCertChain(SecCertificateRef cert_handle, | 368 OSStatus CopyCertChain(SecCertificateRef cert_handle, |
295 CFArrayRef* out_cert_chain) { | 369 CFArrayRef* out_cert_chain) { |
296 DCHECK(cert_handle); | 370 DCHECK(cert_handle); |
297 DCHECK(out_cert_chain); | 371 DCHECK(out_cert_chain); |
298 // Create an SSL policy ref configured for client cert evaluation. | 372 // Create an SSL policy ref configured for client cert evaluation. |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
823 if (status) | 897 if (status) |
824 return NetErrorFromOSStatus(status); | 898 return NetErrorFromOSStatus(status); |
825 CFArrayRef completed_chain = NULL; | 899 CFArrayRef completed_chain = NULL; |
826 CSSM_TP_APPLE_EVIDENCE_INFO* chain_info; | 900 CSSM_TP_APPLE_EVIDENCE_INFO* chain_info; |
827 status = SecTrustGetResult(trust_ref, &trust_result, &completed_chain, | 901 status = SecTrustGetResult(trust_ref, &trust_result, &completed_chain, |
828 &chain_info); | 902 &chain_info); |
829 if (status) | 903 if (status) |
830 return NetErrorFromOSStatus(status); | 904 return NetErrorFromOSStatus(status); |
831 ScopedCFTypeRef<CFArrayRef> scoped_completed_chain(completed_chain); | 905 ScopedCFTypeRef<CFArrayRef> scoped_completed_chain(completed_chain); |
832 | 906 |
833 SecCertificateRef verified_cert = NULL; | 907 GetCertChainInfo(scoped_completed_chain.get(), chain_info, verify_result); |
834 std::vector<SecCertificateRef> verified_chain; | |
835 for (CFIndex i = 0, count = CFArrayGetCount(completed_chain); | |
836 i < count; ++i) { | |
837 SecCertificateRef chain_cert = reinterpret_cast<SecCertificateRef>( | |
838 const_cast<void*>(CFArrayGetValueAtIndex(completed_chain, i))); | |
839 if (i == 0) { | |
840 verified_cert = chain_cert; | |
841 } else { | |
842 verified_chain.push_back(chain_cert); | |
843 } | |
844 } | |
845 if (verified_cert) { | |
846 verify_result->verified_cert = CreateFromHandle(verified_cert, | |
847 verified_chain); | |
848 } | |
849 | 908 |
850 // Evaluate the results | 909 // Evaluate the results |
851 OSStatus cssm_result; | 910 OSStatus cssm_result; |
852 switch (trust_result) { | 911 switch (trust_result) { |
853 case kSecTrustResultUnspecified: | 912 case kSecTrustResultUnspecified: |
854 case kSecTrustResultProceed: | 913 case kSecTrustResultProceed: |
855 // Certificate chain is valid and trusted ("unspecified" indicates that | 914 // Certificate chain is valid and trusted ("unspecified" indicates that |
856 // the user has not explicitly set a trust setting) | 915 // the user has not explicitly set a trust setting) |
857 break; | 916 break; |
858 | 917 |
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1368 CSSM_DATA cert_data; | 1427 CSSM_DATA cert_data; |
1369 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); | 1428 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); |
1370 if (status) | 1429 if (status) |
1371 return false; | 1430 return false; |
1372 | 1431 |
1373 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), | 1432 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), |
1374 cert_data.Length); | 1433 cert_data.Length); |
1375 } | 1434 } |
1376 | 1435 |
1377 } // namespace net | 1436 } // namespace net |
OLD | NEW |