| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 <Security/Security.h> | 8 #include <Security/Security.h> |
| 9 #include <time.h> | 9 #include <time.h> |
| 10 | 10 |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 | 351 |
| 352 // Evaluate trust, which creates the cert chain. | 352 // Evaluate trust, which creates the cert chain. |
| 353 SecTrustResultType status; | 353 SecTrustResultType status; |
| 354 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; | 354 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; |
| 355 result = SecTrustEvaluate(trust, &status); | 355 result = SecTrustEvaluate(trust, &status); |
| 356 if (result) | 356 if (result) |
| 357 return result; | 357 return result; |
| 358 return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); | 358 return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); |
| 359 } | 359 } |
| 360 | 360 |
| 361 // Returns true if |purpose| is listed as allowed in |usage|. This |
| 362 // function also considers the "Any" purpose. If the attribute is |
| 363 // present and empty, we return false. |
| 364 bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, |
| 365 const CSSM_OID* purpose) { |
| 366 for (unsigned p = 0; p < usage->numPurposes; ++p) { |
| 367 if (CSSMOIDEqual(&usage->purposes[p], purpose)) |
| 368 return true; |
| 369 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) |
| 370 return true; |
| 371 } |
| 372 return false; |
| 373 } |
| 374 |
| 361 } // namespace | 375 } // namespace |
| 362 | 376 |
| 363 void X509Certificate::Initialize() { | 377 void X509Certificate::Initialize() { |
| 364 const CSSM_X509_NAME* name; | 378 const CSSM_X509_NAME* name; |
| 365 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); | 379 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); |
| 366 if (!status) { | 380 if (!status) { |
| 367 subject_.Parse(name); | 381 subject_.Parse(name); |
| 368 } | 382 } |
| 369 status = SecCertificateGetIssuer(cert_handle_, &name); | 383 status = SecCertificateGetIssuer(cert_handle_, &name); |
| 370 if (!status) { | 384 if (!status) { |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 | 706 |
| 693 CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); | 707 CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); |
| 694 | 708 |
| 695 return sha1; | 709 return sha1; |
| 696 } | 710 } |
| 697 | 711 |
| 698 bool X509Certificate::SupportsSSLClientAuth() const { | 712 bool X509Certificate::SupportsSSLClientAuth() const { |
| 699 CSSMFields fields; | 713 CSSMFields fields; |
| 700 if (GetCertFields(cert_handle_, &fields) != noErr) | 714 if (GetCertFields(cert_handle_, &fields) != noErr) |
| 701 return false; | 715 return false; |
| 716 |
| 717 // Gather the extensions we care about. We do not support |
| 718 // CSSMOID_NetscapeCertType on OS X. |
| 719 const CE_ExtendedKeyUsage* ext_key_usage = NULL; |
| 720 const CE_KeyUsage* key_usage = NULL; |
| 702 for (unsigned f = 0; f < fields.num_of_fields; ++f) { | 721 for (unsigned f = 0; f < fields.num_of_fields; ++f) { |
| 703 const CSSM_FIELD& field = fields.fields[f]; | 722 const CSSM_FIELD& field = fields.fields[f]; |
| 704 const CSSM_X509_EXTENSION* ext = | 723 const CSSM_X509_EXTENSION* ext = |
| 705 reinterpret_cast<const CSSM_X509_EXTENSION*>(field.FieldValue.Data); | 724 reinterpret_cast<const CSSM_X509_EXTENSION*>(field.FieldValue.Data); |
| 706 if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) { | 725 if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_KeyUsage)) { |
| 707 const CE_ExtendedKeyUsage* usage = | 726 key_usage = reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue); |
| 727 } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) { |
| 728 ext_key_usage = |
| 708 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); | 729 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); |
| 709 for (unsigned p = 0; p < usage->numPurposes; ++p) { | |
| 710 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ClientAuth)) | |
| 711 return true; | |
| 712 } | |
| 713 } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_NetscapeCertType)) { | |
| 714 uint16_t flags = | |
| 715 *reinterpret_cast<const uint16_t*>(ext->value.parsedValue); | |
| 716 if (flags & CE_NCT_SSL_Client) | |
| 717 return true; | |
| 718 } | 730 } |
| 719 } | 731 } |
| 720 return false; | 732 |
| 733 // RFC5280 says to take the intersection of the two extensions. |
| 734 // |
| 735 // Our underlying crypto libraries don't expose |
| 736 // ClientCertificateType, so for now we will not support fixed |
| 737 // Diffie-Hellman mechanisms. For rsa_sign, we need the |
| 738 // digitalSignature bit. |
| 739 // |
| 740 // In particular, if a key has the nonRepudiation bit and not the |
| 741 // digitalSignature one, we will not offer it to the user. |
| 742 if (key_usage && !((*key_usage) & CE_KU_DigitalSignature)) |
| 743 return false; |
| 744 if (ext_key_usage && !ExtendedKeyUsageAllows(ext_key_usage, |
| 745 &CSSMOID_ClientAuth)) |
| 746 return false; |
| 747 return true; |
| 721 } | 748 } |
| 722 | 749 |
| 723 bool X509Certificate::IsIssuedBy( | 750 bool X509Certificate::IsIssuedBy( |
| 724 const std::vector<CertPrincipal>& valid_issuers) { | 751 const std::vector<CertPrincipal>& valid_issuers) { |
| 725 // Get the cert's issuer chain. | 752 // Get the cert's issuer chain. |
| 726 CFArrayRef cert_chain = NULL; | 753 CFArrayRef cert_chain = NULL; |
| 727 OSStatus result; | 754 OSStatus result; |
| 728 result = CopyCertChain(os_cert_handle(), &cert_chain); | 755 result = CopyCertChain(os_cert_handle(), &cert_chain); |
| 729 if (result != noErr) | 756 if (result != noErr) |
| 730 return false; | 757 return false; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 } | 894 } |
| 868 CFRelease(cert_chain); | 895 CFRelease(cert_chain); |
| 869 } | 896 } |
| 870 exit: | 897 exit: |
| 871 if (result) | 898 if (result) |
| 872 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; | 899 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; |
| 873 return chain.release(); | 900 return chain.release(); |
| 874 } | 901 } |
| 875 | 902 |
| 876 } // namespace net | 903 } // namespace net |
| OLD | NEW |