| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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> |
| 11 | 11 |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/mac/mac_logging.h" | 16 #include "base/mac/mac_logging.h" |
| 17 #include "base/mac/scoped_cftyperef.h" | 17 #include "base/mac/scoped_cftyperef.h" |
| 18 #include "base/memory/singleton.h" | 18 #include "base/memory/singleton.h" |
| 19 #include "base/pickle.h" | 19 #include "base/pickle.h" |
| 20 #include "base/sha1.h" | 20 #include "base/sha1.h" |
| 21 #include "base/synchronization/lock.h" |
| 21 #include "base/sys_string_conversions.h" | 22 #include "base/sys_string_conversions.h" |
| 22 #include "crypto/cssm_init.h" | 23 #include "crypto/cssm_init.h" |
| 24 #include "crypto/mac_security_services_lock.h" |
| 23 #include "crypto/nss_util.h" | 25 #include "crypto/nss_util.h" |
| 24 #include "crypto/rsa_private_key.h" | 26 #include "crypto/rsa_private_key.h" |
| 25 #include "net/base/x509_util_mac.h" | 27 #include "net/base/x509_util_mac.h" |
| 26 #include "third_party/nss/mozilla/security/nss/lib/certdb/cert.h" | 28 #include "third_party/nss/mozilla/security/nss/lib/certdb/cert.h" |
| 27 | 29 |
| 28 using base::mac::ScopedCFTypeRef; | 30 using base::mac::ScopedCFTypeRef; |
| 29 using base::Time; | 31 using base::Time; |
| 30 | 32 |
| 31 namespace net { | 33 namespace net { |
| 32 | 34 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 | 88 |
| 87 // Gets the issuer for a given cert, starting with the cert itself and | 89 // Gets the issuer for a given cert, starting with the cert itself and |
| 88 // including the intermediate and finally root certificates (if any). | 90 // including the intermediate and finally root certificates (if any). |
| 89 // This function calls SecTrust but doesn't actually pay attention to the trust | 91 // This function calls SecTrust but doesn't actually pay attention to the trust |
| 90 // result: it shouldn't be used to determine trust, just to traverse the chain. | 92 // result: it shouldn't be used to determine trust, just to traverse the chain. |
| 91 // Caller is responsible for releasing the value stored into *out_cert_chain. | 93 // Caller is responsible for releasing the value stored into *out_cert_chain. |
| 92 OSStatus CopyCertChain(SecCertificateRef cert_handle, | 94 OSStatus CopyCertChain(SecCertificateRef cert_handle, |
| 93 CFArrayRef* out_cert_chain) { | 95 CFArrayRef* out_cert_chain) { |
| 94 DCHECK(cert_handle); | 96 DCHECK(cert_handle); |
| 95 DCHECK(out_cert_chain); | 97 DCHECK(out_cert_chain); |
| 98 |
| 96 // Create an SSL policy ref configured for client cert evaluation. | 99 // Create an SSL policy ref configured for client cert evaluation. |
| 97 SecPolicyRef ssl_policy; | 100 SecPolicyRef ssl_policy; |
| 98 OSStatus result = x509_util::CreateSSLClientPolicy(&ssl_policy); | 101 OSStatus result = x509_util::CreateSSLClientPolicy(&ssl_policy); |
| 99 if (result) | 102 if (result) |
| 100 return result; | 103 return result; |
| 101 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); | 104 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); |
| 102 | 105 |
| 103 // Create a SecTrustRef. | 106 // Create a SecTrustRef. |
| 104 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( | 107 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( |
| 105 NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), | 108 NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), |
| 106 1, &kCFTypeArrayCallBacks)); | 109 1, &kCFTypeArrayCallBacks)); |
| 107 SecTrustRef trust_ref = NULL; | 110 SecTrustRef trust_ref = NULL; |
| 108 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref); | 111 { |
| 112 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 113 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, |
| 114 &trust_ref); |
| 115 } |
| 109 if (result) | 116 if (result) |
| 110 return result; | 117 return result; |
| 111 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); | 118 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); |
| 112 | 119 |
| 113 // Evaluate trust, which creates the cert chain. | 120 // Evaluate trust, which creates the cert chain. |
| 114 SecTrustResultType status; | 121 SecTrustResultType status; |
| 115 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; | 122 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; |
| 116 result = SecTrustEvaluate(trust, &status); | 123 { |
| 124 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 125 result = SecTrustEvaluate(trust, &status); |
| 126 } |
| 117 if (result) | 127 if (result) |
| 118 return result; | 128 return result; |
| 119 return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); | 129 { |
| 130 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 131 result = SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); |
| 132 } |
| 133 return result; |
| 120 } | 134 } |
| 121 | 135 |
| 122 // Returns true if |purpose| is listed as allowed in |usage|. This | 136 // Returns true if |purpose| is listed as allowed in |usage|. This |
| 123 // function also considers the "Any" purpose. If the attribute is | 137 // function also considers the "Any" purpose. If the attribute is |
| 124 // present and empty, we return false. | 138 // present and empty, we return false. |
| 125 bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, | 139 bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, |
| 126 const CSSM_OID* purpose) { | 140 const CSSM_OID* purpose) { |
| 127 for (unsigned p = 0; p < usage->numPurposes; ++p) { | 141 for (unsigned p = 0; p < usage->numPurposes; ++p) { |
| 128 if (CSSMOIDEqual(&usage->purposes[p], purpose)) | 142 if (CSSMOIDEqual(&usage->purposes[p], purpose)) |
| 129 return true; | 143 return true; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 155 // within are stored into |output|. | 169 // within are stored into |output|. |
| 156 void AddCertificatesFromBytes(const char* data, size_t length, | 170 void AddCertificatesFromBytes(const char* data, size_t length, |
| 157 SecExternalFormat format, | 171 SecExternalFormat format, |
| 158 X509Certificate::OSCertHandles* output) { | 172 X509Certificate::OSCertHandles* output) { |
| 159 SecExternalFormat input_format = format; | 173 SecExternalFormat input_format = format; |
| 160 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( | 174 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( |
| 161 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, | 175 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, |
| 162 kCFAllocatorNull)); | 176 kCFAllocatorNull)); |
| 163 | 177 |
| 164 CFArrayRef items = NULL; | 178 CFArrayRef items = NULL; |
| 165 OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format, | 179 OSStatus status; |
| 166 NULL, 0, NULL, NULL, &items); | 180 { |
| 181 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 182 status = SecKeychainItemImport(local_data, NULL, &input_format, |
| 183 NULL, 0, NULL, NULL, &items); |
| 184 } |
| 185 |
| 167 if (status) { | 186 if (status) { |
| 168 OSSTATUS_DLOG(WARNING, status) | 187 OSSTATUS_DLOG(WARNING, status) |
| 169 << "Unable to import items from data of length " << length; | 188 << "Unable to import items from data of length " << length; |
| 170 return; | 189 return; |
| 171 } | 190 } |
| 172 | 191 |
| 173 ScopedCFTypeRef<CFArrayRef> scoped_items(items); | 192 ScopedCFTypeRef<CFArrayRef> scoped_items(items); |
| 174 CFTypeID cert_type_id = SecCertificateGetTypeID(); | 193 CFTypeID cert_type_id = SecCertificateGetTypeID(); |
| 175 | 194 |
| 176 for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { | 195 for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 if (!server_domain.empty()) { | 705 if (!server_domain.empty()) { |
| 687 // See if there's an identity preference for this domain: | 706 // See if there's an identity preference for this domain: |
| 688 ScopedCFTypeRef<CFStringRef> domain_str( | 707 ScopedCFTypeRef<CFStringRef> domain_str( |
| 689 base::SysUTF8ToCFStringRef("https://" + server_domain)); | 708 base::SysUTF8ToCFStringRef("https://" + server_domain)); |
| 690 SecIdentityRef identity = NULL; | 709 SecIdentityRef identity = NULL; |
| 691 // While SecIdentityCopyPreferences appears to take a list of CA issuers | 710 // While SecIdentityCopyPreferences appears to take a list of CA issuers |
| 692 // to restrict the identity search to, within Security.framework the | 711 // to restrict the identity search to, within Security.framework the |
| 693 // argument is ignored and filtering unimplemented. See | 712 // argument is ignored and filtering unimplemented. See |
| 694 // SecIdentity.cpp in libsecurity_keychain, specifically | 713 // SecIdentity.cpp in libsecurity_keychain, specifically |
| 695 // _SecIdentityCopyPreferenceMatchingName(). | 714 // _SecIdentityCopyPreferenceMatchingName(). |
| 696 if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr) | 715 { |
| 697 preferred_identity.reset(identity); | 716 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 717 if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr) |
| 718 preferred_identity.reset(identity); |
| 719 } |
| 698 } | 720 } |
| 699 | 721 |
| 700 // Now enumerate the identities in the available keychains. | 722 // Now enumerate the identities in the available keychains. |
| 701 SecIdentitySearchRef search = nil; | 723 SecIdentitySearchRef search = NULL; |
| 702 OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); | 724 OSStatus err; |
| 725 { |
| 726 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 727 err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); |
| 728 } |
| 729 if (err) |
| 730 return false; |
| 703 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search); | 731 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search); |
| 704 while (!err) { | 732 while (!err) { |
| 705 SecIdentityRef identity = NULL; | 733 SecIdentityRef identity = NULL; |
| 706 err = SecIdentitySearchCopyNext(search, &identity); | 734 { |
| 735 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 736 err = SecIdentitySearchCopyNext(search, &identity); |
| 737 } |
| 707 if (err) | 738 if (err) |
| 708 break; | 739 break; |
| 709 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); | 740 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); |
| 710 | 741 |
| 711 SecCertificateRef cert_handle; | 742 SecCertificateRef cert_handle; |
| 712 err = SecIdentityCopyCertificate(identity, &cert_handle); | 743 err = SecIdentityCopyCertificate(identity, &cert_handle); |
| 713 if (err != noErr) | 744 if (err != noErr) |
| 714 continue; | 745 continue; |
| 715 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle); | 746 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle); |
| 716 | 747 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 if (err != errSecItemNotFound) { | 779 if (err != errSecItemNotFound) { |
| 749 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error"; | 780 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error"; |
| 750 return false; | 781 return false; |
| 751 } | 782 } |
| 752 return true; | 783 return true; |
| 753 } | 784 } |
| 754 | 785 |
| 755 CFArrayRef X509Certificate::CreateClientCertificateChain() const { | 786 CFArrayRef X509Certificate::CreateClientCertificateChain() const { |
| 756 // Initialize the result array with just the IdentityRef of the receiver: | 787 // Initialize the result array with just the IdentityRef of the receiver: |
| 757 SecIdentityRef identity; | 788 SecIdentityRef identity; |
| 758 OSStatus result = | 789 OSStatus result; |
| 759 SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); | 790 { |
| 791 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 792 result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); |
| 793 } |
| 760 if (result) { | 794 if (result) { |
| 761 OSSTATUS_LOG(ERROR, result) << "SecIdentityCreateWithCertificate error"; | 795 OSSTATUS_LOG(ERROR, result) << "SecIdentityCreateWithCertificate error"; |
| 762 return NULL; | 796 return NULL; |
| 763 } | 797 } |
| 764 ScopedCFTypeRef<CFMutableArrayRef> chain( | 798 ScopedCFTypeRef<CFMutableArrayRef> chain( |
| 765 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); | 799 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); |
| 766 CFArrayAppendValue(chain, identity); | 800 CFArrayAppendValue(chain, identity); |
| 767 | 801 |
| 768 CFArrayRef cert_chain = NULL; | 802 CFArrayRef cert_chain = NULL; |
| 769 result = CopyCertChain(cert_handle_, &cert_chain); | 803 result = CopyCertChain(cert_handle_, &cert_chain); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 *type = kPublicKeyTypeDH; | 896 *type = kPublicKeyTypeDH; |
| 863 break; | 897 break; |
| 864 default: | 898 default: |
| 865 *type = kPublicKeyTypeUnknown; | 899 *type = kPublicKeyTypeUnknown; |
| 866 *size_bits = 0; | 900 *size_bits = 0; |
| 867 break; | 901 break; |
| 868 } | 902 } |
| 869 } | 903 } |
| 870 | 904 |
| 871 } // namespace net | 905 } // namespace net |
| OLD | NEW |