Index: net/cert/x509_util_mac.cc |
diff --git a/net/cert/x509_util_mac.cc b/net/cert/x509_util_mac.cc |
index f2ce0f3b4b4f521255adf0944787ff6ff7559b0c..0e12a64702a787bb7e754066a3b6d5aaa168da0b 100644 |
--- a/net/cert/x509_util_mac.cc |
+++ b/net/cert/x509_util_mac.cc |
@@ -4,11 +4,14 @@ |
#include "net/cert/x509_util_mac.h" |
+#include <CommonCrypto/CommonDigest.h> |
+ |
#include "base/logging.h" |
#include "base/mac/mac_util.h" |
-#include "base/mac/scoped_cftyperef.h" |
#include "base/strings/sys_string_conversions.h" |
+#include "net/cert/x509_certificate.h" |
#include "third_party/apple_apsl/cssmapplePriv.h" |
+#include "third_party/boringssl/src/include/openssl/pool.h" |
namespace net { |
@@ -52,6 +55,161 @@ OSStatus CreatePolicy(const CSSM_OID* policy_oid, |
} // namespace |
+bool IsValidSecCertificate(SecCertificateRef cert_handle) { |
+ const CSSM_X509_NAME* sanity_check = NULL; |
+ OSStatus status = SecCertificateGetSubject(cert_handle, &sanity_check); |
+ return status == noErr && sanity_check; |
+} |
+ |
+base::ScopedCFTypeRef<SecCertificateRef> CreateSecCertificateFromBytes( |
+ const uint8_t* data, |
+ size_t length) { |
+ CSSM_DATA cert_data; |
+ cert_data.Data = const_cast<uint8_t*>(data); |
+ cert_data.Length = length; |
+ |
+ base::ScopedCFTypeRef<SecCertificateRef> cert_handle; |
+ OSStatus status = SecCertificateCreateFromData(&cert_data, CSSM_CERT_X_509v3, |
+ CSSM_CERT_ENCODING_DER, |
+ cert_handle.InitializeInto()); |
+ if (status != noErr) |
+ return base::ScopedCFTypeRef<SecCertificateRef>(); |
+ if (!IsValidSecCertificate(cert_handle.get())) |
+ return base::ScopedCFTypeRef<SecCertificateRef>(); |
+ return cert_handle; |
+} |
+ |
+base::ScopedCFTypeRef<SecCertificateRef> |
+CreateSecCertificateFromX509Certificate(const X509Certificate* cert) { |
+#if BUILDFLAG(USE_BYTE_CERTS) |
+ return CreateSecCertificateFromBytes( |
+ CRYPTO_BUFFER_data(cert->os_cert_handle()), |
+ CRYPTO_BUFFER_len(cert->os_cert_handle())); |
+#else |
+ return base::ScopedCFTypeRef<SecCertificateRef>( |
+ reinterpret_cast<SecCertificateRef>( |
+ const_cast<void*>(CFRetain(cert->os_cert_handle())))); |
+#endif |
+} |
+ |
+base::ScopedCFTypeRef<CFMutableArrayRef> |
+CreateSecCertificateArrayForX509Certificate(X509Certificate* cert) { |
+ base::ScopedCFTypeRef<CFMutableArrayRef> cert_list( |
+ CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); |
+ if (!cert_list) |
+ return base::ScopedCFTypeRef<CFMutableArrayRef>(); |
+#if BUILDFLAG(USE_BYTE_CERTS) |
+ std::string bytes; |
+ base::ScopedCFTypeRef<SecCertificateRef> sec_cert( |
+ CreateSecCertificateFromBytes(CRYPTO_BUFFER_data(cert->os_cert_handle()), |
+ CRYPTO_BUFFER_len(cert->os_cert_handle()))); |
+ if (!sec_cert) |
+ return base::ScopedCFTypeRef<CFMutableArrayRef>(); |
+ CFArrayAppendValue(cert_list, sec_cert); |
+ for (X509Certificate::OSCertHandle intermediate : |
+ cert->GetIntermediateCertificates()) { |
+ base::ScopedCFTypeRef<SecCertificateRef> sec_cert( |
+ CreateSecCertificateFromBytes(CRYPTO_BUFFER_data(intermediate), |
+ CRYPTO_BUFFER_len(intermediate))); |
+ CFArrayAppendValue(cert_list, sec_cert); |
+ } |
+#else |
+ X509Certificate::OSCertHandles intermediate_ca_certs = |
+ cert->GetIntermediateCertificates(); |
+ CFArrayAppendValue(cert_list, cert->os_cert_handle()); |
+ for (size_t i = 0; i < intermediate_ca_certs.size(); ++i) |
+ CFArrayAppendValue(cert_list, intermediate_ca_certs[i]); |
+#endif |
+ return cert_list; |
+} |
+ |
+scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate( |
+ SecCertificateRef sec_cert, |
+ const std::vector<SecCertificateRef>& sec_chain) { |
+#if BUILDFLAG(USE_BYTE_CERTS) |
+ CSSM_DATA der_data; |
+ if (!sec_cert || SecCertificateGetData(sec_cert, &der_data) != noErr) |
+ return nullptr; |
+ bssl::UniquePtr<CRYPTO_BUFFER> cert_handle( |
+ X509Certificate::CreateOSCertHandleFromBytes( |
+ reinterpret_cast<const char*>(der_data.Data), der_data.Length)); |
+ if (!cert_handle) |
+ return nullptr; |
+ std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates; |
+ X509Certificate::OSCertHandles intermediates_raw; |
+ for (const SecCertificateRef& sec_intermediate : sec_chain) { |
+ if (!sec_intermediate || |
+ SecCertificateGetData(sec_intermediate, &der_data) != noErr) { |
+ return nullptr; |
+ } |
+ bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle( |
+ X509Certificate::CreateOSCertHandleFromBytes( |
+ reinterpret_cast<const char*>(der_data.Data), der_data.Length)); |
+ if (!intermediate_cert_handle) |
+ return nullptr; |
+ intermediates_raw.push_back(intermediate_cert_handle.get()); |
+ intermediates.push_back(std::move(intermediate_cert_handle)); |
+ } |
+ scoped_refptr<X509Certificate> result( |
+ X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw)); |
+ return result; |
+#else |
+ return X509Certificate::CreateFromHandle(sec_cert, sec_chain); |
+#endif |
+} |
+ |
+bool IsSelfSigned(SecCertificateRef cert_handle) { |
+ CSSMCachedCertificate cached_cert; |
+ OSStatus status = cached_cert.Init(cert_handle); |
+ if (status != noErr) |
+ return false; |
+ |
+ CSSMFieldValue subject; |
+ status = cached_cert.GetField(&CSSMOID_X509V1SubjectNameStd, &subject); |
+ if (status != CSSM_OK || !subject.field()) |
+ return false; |
+ |
+ CSSMFieldValue issuer; |
+ status = cached_cert.GetField(&CSSMOID_X509V1IssuerNameStd, &issuer); |
+ if (status != CSSM_OK || !issuer.field()) |
+ return false; |
+ |
+ if (subject.field()->Length != issuer.field()->Length || |
+ memcmp(subject.field()->Data, issuer.field()->Data, |
+ issuer.field()->Length) != 0) { |
+ return false; |
+ } |
+ |
+ CSSM_CL_HANDLE cl_handle = CSSM_INVALID_HANDLE; |
+ status = SecCertificateGetCLHandle(cert_handle, &cl_handle); |
+ if (status) |
+ return false; |
+ CSSM_DATA cert_data; |
+ status = SecCertificateGetData(cert_handle, &cert_data); |
+ if (status) |
+ return false; |
+ |
+ if (CSSM_CL_CertVerify(cl_handle, 0, &cert_data, &cert_data, NULL, 0)) |
+ return false; |
+ return true; |
+} |
+ |
+SHA256HashValue CalculateFingerprint256(SecCertificateRef cert) { |
+ SHA256HashValue sha256; |
+ memset(sha256.data, 0, sizeof(sha256.data)); |
+ |
+ CSSM_DATA cert_data; |
+ OSStatus status = SecCertificateGetData(cert, &cert_data); |
+ if (status) |
+ return sha256; |
+ |
+ DCHECK(cert_data.Data); |
+ DCHECK_NE(cert_data.Length, 0U); |
+ |
+ CC_SHA256(cert_data.Data, cert_data.Length, sha256.data); |
+ |
+ return sha256; |
+} |
OSStatus CreateSSLClientPolicy(SecPolicyRef* policy) { |
*policy = SecPolicyCreateSSL(false /* server */, nullptr); |