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/cert/x509_certificate.h" | 5 #include "net/cert/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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, | 106 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, |
107 &serial_number); | 107 &serial_number); |
108 if (status || !serial_number.field()) | 108 if (status || !serial_number.field()) |
109 return std::string(); | 109 return std::string(); |
110 | 110 |
111 return std::string( | 111 return std::string( |
112 reinterpret_cast<const char*>(serial_number.field()->Data), | 112 reinterpret_cast<const char*>(serial_number.field()->Data), |
113 serial_number.field()->Length); | 113 serial_number.field()->Length); |
114 } | 114 } |
115 | 115 |
116 // Gets the issuer for a given cert, starting with the cert itself and | |
117 // including the intermediate and finally root certificates (if any). | |
118 // This function calls SecTrust but doesn't actually pay attention to the trust | |
119 // result: it shouldn't be used to determine trust, just to traverse the chain. | |
120 // Caller is responsible for releasing the value stored into *out_cert_chain. | |
121 OSStatus CopyCertChain(SecCertificateRef cert_handle, | |
122 CFArrayRef* out_cert_chain) { | |
123 DCHECK(cert_handle); | |
124 DCHECK(out_cert_chain); | |
125 | |
126 // Create an SSL policy ref configured for client cert evaluation. | |
127 SecPolicyRef ssl_policy; | |
128 OSStatus result = x509_util::CreateSSLClientPolicy(&ssl_policy); | |
129 if (result) | |
130 return result; | |
131 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); | |
132 | |
133 // Create a SecTrustRef. | |
134 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( | |
135 NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), | |
136 1, &kCFTypeArrayCallBacks)); | |
137 SecTrustRef trust_ref = NULL; | |
138 { | |
139 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | |
140 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, | |
141 &trust_ref); | |
142 } | |
143 if (result) | |
144 return result; | |
145 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); | |
146 | |
147 // Evaluate trust, which creates the cert chain. | |
148 SecTrustResultType status; | |
149 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; | |
150 { | |
151 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | |
152 result = SecTrustEvaluate(trust, &status); | |
153 } | |
154 if (result) | |
155 return result; | |
156 { | |
157 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | |
158 result = SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); | |
159 } | |
160 return result; | |
161 } | |
162 | |
163 // Returns true if |purpose| is listed as allowed in |usage|. This | 116 // Returns true if |purpose| is listed as allowed in |usage|. This |
164 // function also considers the "Any" purpose. If the attribute is | 117 // function also considers the "Any" purpose. If the attribute is |
165 // present and empty, we return false. | 118 // present and empty, we return false. |
166 bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, | 119 bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, |
167 const CSSM_OID* purpose) { | 120 const CSSM_OID* purpose) { |
168 for (unsigned p = 0; p < usage->numPurposes; ++p) { | 121 for (unsigned p = 0; p < usage->numPurposes; ++p) { |
169 if (CSSMOIDEqual(&usage->purposes[p], purpose)) | 122 if (CSSMOIDEqual(&usage->purposes[p], purpose)) |
170 return true; | 123 return true; |
171 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) | 124 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) |
172 return true; | 125 return true; |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 if (status == CSSM_OK && key_usage.field()) { | 658 if (status == CSSM_OK && key_usage.field()) { |
706 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); | 659 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); |
707 const CE_ExtendedKeyUsage* ext_key_usage = | 660 const CE_ExtendedKeyUsage* ext_key_usage = |
708 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); | 661 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); |
709 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth)) | 662 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth)) |
710 return false; | 663 return false; |
711 } | 664 } |
712 return true; | 665 return true; |
713 } | 666 } |
714 | 667 |
715 CFArrayRef X509Certificate::CreateClientCertificateChain() const { | |
716 // Initialize the result array with just the IdentityRef of the receiver: | |
717 SecIdentityRef identity; | |
718 OSStatus result; | |
719 { | |
720 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | |
721 result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); | |
722 } | |
723 if (result) { | |
724 OSSTATUS_LOG(ERROR, result) << "SecIdentityCreateWithCertificate error"; | |
725 return NULL; | |
726 } | |
727 ScopedCFTypeRef<CFMutableArrayRef> chain( | |
728 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); | |
729 CFArrayAppendValue(chain, identity); | |
730 | |
731 CFArrayRef cert_chain = NULL; | |
732 result = CopyCertChain(cert_handle_, &cert_chain); | |
733 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); | |
734 if (result) { | |
735 OSSTATUS_LOG(ERROR, result) << "CreateIdentityCertificateChain error"; | |
736 return chain.release(); | |
737 } | |
738 | |
739 // Append the intermediate certs from SecTrust to the result array: | |
740 if (cert_chain) { | |
741 int chain_count = CFArrayGetCount(cert_chain); | |
742 if (chain_count > 1) { | |
743 CFArrayAppendArray(chain, | |
744 cert_chain, | |
745 CFRangeMake(1, chain_count - 1)); | |
746 } | |
747 } | |
748 | |
749 return chain.release(); | |
750 } | |
751 | |
752 CFArrayRef X509Certificate::CreateOSCertChainForCert() const { | 668 CFArrayRef X509Certificate::CreateOSCertChainForCert() const { |
753 CFMutableArrayRef cert_list = | 669 CFMutableArrayRef cert_list = |
754 CFArrayCreateMutable(kCFAllocatorDefault, 0, | 670 CFArrayCreateMutable(kCFAllocatorDefault, 0, |
755 &kCFTypeArrayCallBacks); | 671 &kCFTypeArrayCallBacks); |
756 if (!cert_list) | 672 if (!cert_list) |
757 return NULL; | 673 return NULL; |
758 | 674 |
759 CFArrayAppendValue(cert_list, os_cert_handle()); | 675 CFArrayAppendValue(cert_list, os_cert_handle()); |
760 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) | 676 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) |
761 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); | 677 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 *type = kPublicKeyTypeDH; | 741 *type = kPublicKeyTypeDH; |
826 break; | 742 break; |
827 default: | 743 default: |
828 *type = kPublicKeyTypeUnknown; | 744 *type = kPublicKeyTypeUnknown; |
829 *size_bits = 0; | 745 *size_bits = 0; |
830 break; | 746 break; |
831 } | 747 } |
832 } | 748 } |
833 | 749 |
834 } // namespace net | 750 } // namespace net |
OLD | NEW |