| 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..d2119c185539c86e16fe1318db916c336bd2a6c9 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 defined(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 defined(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 defined(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);
|
|
|