// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/cert/x509_util_mac.h"

#include <CommonCrypto/CommonDigest.h>

#include "base/logging.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 {

// CSSM functions are deprecated as of OSX 10.7, but have no replacement.
// https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

namespace x509_util {

namespace {

// Creates a SecPolicyRef for the given OID, with optional value.
OSStatus CreatePolicy(const CSSM_OID* policy_oid,
                      void* option_data,
                      size_t option_length,
                      SecPolicyRef* policy) {
  SecPolicySearchRef search;
  OSStatus err = SecPolicySearchCreate(CSSM_CERT_X_509v3, policy_oid, NULL,
                                       &search);
  if (err)
    return err;
  err = SecPolicySearchCopyNext(search, policy);
  CFRelease(search);
  if (err)
    return err;

  if (option_data) {
    CSSM_DATA options_data = {
      option_length,
      reinterpret_cast<uint8_t*>(option_data)
    };
    err = SecPolicySetValue(*policy, &options_data);
    if (err) {
      CFRelease(*policy);
      return err;
    }
  }
  return noErr;
}

}  // 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) {
  return CreateSecCertificateFromBytes(CRYPTO_BUFFER_data(cert->cert_buffer()),
                                       CRYPTO_BUFFER_len(cert->cert_buffer()));
}

scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate(
    SecCertificateRef sec_cert,
    const std::vector<SecCertificateRef>& sec_chain) {
  return CreateX509CertificateFromSecCertificate(sec_cert, sec_chain, {});
}

scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate(
    SecCertificateRef sec_cert,
    const std::vector<SecCertificateRef>& sec_chain,
    X509Certificate::UnsafeCreateOptions options) {
  CSSM_DATA der_data;
  if (!sec_cert || SecCertificateGetData(sec_cert, &der_data) != noErr)
    return nullptr;
  bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
      X509Certificate::CreateCertBufferFromBytes(
          reinterpret_cast<const char*>(der_data.Data), der_data.Length));
  if (!cert_handle)
    return nullptr;
  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
  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::CreateCertBufferFromBytes(
            reinterpret_cast<const char*>(der_data.Data), der_data.Length));
    if (!intermediate_cert_handle)
      return nullptr;
    intermediates.push_back(std::move(intermediate_cert_handle));
  }
  scoped_refptr<X509Certificate> result(
      X509Certificate::CreateFromBufferUnsafeOptions(
          std::move(cert_handle), std::move(intermediates), options));
  return result;
}

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);
  return *policy ? noErr : errSecNoPolicyModule;
}

OSStatus CreateSSLServerPolicy(const std::string& hostname,
                               SecPolicyRef* policy) {
  base::ScopedCFTypeRef<CFStringRef> hostname_cfstring;
  if (!hostname.empty()) {
    hostname_cfstring.reset(base::SysUTF8ToCFStringRef(hostname));
    if (!hostname_cfstring)
      return errSecNoPolicyModule;
  }

  *policy = SecPolicyCreateSSL(true /* server */, hostname_cfstring.get());
  return *policy ? noErr : errSecNoPolicyModule;
}

OSStatus CreateBasicX509Policy(SecPolicyRef* policy) {
  *policy = SecPolicyCreateBasicX509();
  return *policy ? noErr : errSecNoPolicyModule;
}

OSStatus CreateRevocationPolicies(bool enable_revocation_checking,
                                  CFMutableArrayRef policies) {
  if (__builtin_available(macos 10.12, *)) {
    // On Sierra, it's not possible to disable network revocation checking
    // without also breaking AIA. If revocation checking isn't explicitly
    // enabled, just don't add a revocation policy.
    if (!enable_revocation_checking)
      return noErr;

    // If revocation checking is requested, enable checking and require positive
    // results. Note that this will fail if there are certs with no
    // CRLDistributionPoints or OCSP AIA urls, which differs from the behavior
    // of |enable_revocation_checking| on pre-10.12. There does not appear to be
    // a way around this, but it shouldn't matter much in practice since
    // revocation checking is generally used with EV certs, where it is expected
    // that all certs include revocation mechanisms.
    SecPolicyRef revocation_policy =
        SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod |
                                  kSecRevocationRequirePositiveResponse);

    if (!revocation_policy)
      return errSecNoPolicyModule;
    CFArrayAppendValue(policies, revocation_policy);
    CFRelease(revocation_policy);
    return noErr;
  }
  OSStatus status = noErr;

  // In order to bypass the system revocation checking settings, the
  // SecTrustRef must have at least one revocation policy associated with it.
  // Since it is not known prior to verification whether the Apple TP will
  // consider a certificate as an EV candidate, the default policy used is a
  // CRL policy, since it does not communicate over the network.
  // If the TP believes the leaf is an EV cert, it will explicitly add an
  // OCSP policy to perform the online checking, and if it doesn't believe
  // that the leaf is EV, then the default CRL policy will effectively no-op.
  // This behaviour is used to implement EV-only revocation checking.
  if (enable_revocation_checking) {
    CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options;
    memset(&tp_crl_options, 0, sizeof(tp_crl_options));
    tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
    // Only allow network CRL fetches if the caller explicitly requests
    // online revocation checking. Note that, as of OS X 10.7.2, the system
    // will set force this flag on according to system policies, so
    // online revocation checks cannot be completely disabled.
    // Starting with OS X 10.12, if a CRL policy is added without the
    // FETCH_CRL_FROM_NET flag, AIA fetching is disabled.
    tp_crl_options.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET;

    SecPolicyRef crl_policy;
    status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options,
                          sizeof(tp_crl_options), &crl_policy);
    if (status)
      return status;
    CFArrayAppendValue(policies, crl_policy);
    CFRelease(crl_policy);
  }

  // If revocation checking is explicitly enabled, then add an OCSP policy
  // and allow network access. If both revocation checking is
  // disabled, then the added OCSP policy will be prevented from
  // accessing the network. This is done because the TP will force an OCSP
  // policy to be present when it believes the certificate is EV.
  CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options;
  memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options));
  tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;

  if (enable_revocation_checking) {
    // The default for the OCSP policy is to fetch responses via the network,
    // unlike the CRL policy default. The policy is further modified to
    // prefer OCSP over CRLs, if both are specified on the certificate. This
    // is because an OCSP response is both sufficient and typically
    // significantly smaller than the CRL counterpart.
    tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT;
  } else {
    // Effectively disable OCSP checking by making it impossible to get an
    // OCSP response. Even if the Apple TP forces OCSP, no checking will
    // be able to succeed. If this happens, the Apple TP will report an error
    // that OCSP was unavailable, but this will be handled and suppressed in
    // X509Certificate::Verify().
    tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET |
                            CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE;
  }

  SecPolicyRef ocsp_policy;
  status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, &tp_ocsp_options,
                        sizeof(tp_ocsp_options), &ocsp_policy);
  if (status)
    return status;
  CFArrayAppendValue(policies, ocsp_policy);
  CFRelease(ocsp_policy);

  return status;
}

CSSMFieldValue::CSSMFieldValue()
    : cl_handle_(CSSM_INVALID_HANDLE),
      oid_(NULL),
      field_(NULL) {
}
CSSMFieldValue::CSSMFieldValue(CSSM_CL_HANDLE cl_handle,
                               const CSSM_OID* oid,
                               CSSM_DATA_PTR field)
    : cl_handle_(cl_handle),
      oid_(const_cast<CSSM_OID_PTR>(oid)),
      field_(field) {
}

CSSMFieldValue::~CSSMFieldValue() {
  Reset(CSSM_INVALID_HANDLE, NULL, NULL);
}

void CSSMFieldValue::Reset(CSSM_CL_HANDLE cl_handle,
                           CSSM_OID_PTR oid,
                           CSSM_DATA_PTR field) {
  if (cl_handle_ && oid_ && field_)
    CSSM_CL_FreeFieldValue(cl_handle_, oid_, field_);
  cl_handle_ = cl_handle;
  oid_ = oid;
  field_ = field;
}

CSSMCachedCertificate::CSSMCachedCertificate()
    : cl_handle_(CSSM_INVALID_HANDLE),
      cached_cert_handle_(CSSM_INVALID_HANDLE) {
}
CSSMCachedCertificate::~CSSMCachedCertificate() {
  if (cl_handle_ && cached_cert_handle_)
    CSSM_CL_CertAbortCache(cl_handle_, cached_cert_handle_);
}

OSStatus CSSMCachedCertificate::Init(SecCertificateRef os_cert_handle) {
  DCHECK(!cl_handle_ && !cached_cert_handle_);
  DCHECK(os_cert_handle);
  CSSM_DATA cert_data;
  OSStatus status = SecCertificateGetData(os_cert_handle, &cert_data);
  if (status)
    return status;
  status = SecCertificateGetCLHandle(os_cert_handle, &cl_handle_);
  if (status) {
    DCHECK(!cl_handle_);
    return status;
  }

  status = CSSM_CL_CertCache(cl_handle_, &cert_data, &cached_cert_handle_);
  if (status)
    DCHECK(!cached_cert_handle_);
  return status;
}

OSStatus CSSMCachedCertificate::GetField(const CSSM_OID* field_oid,
                                         CSSMFieldValue* field) const {
  DCHECK(cl_handle_);
  DCHECK(cached_cert_handle_);

  CSSM_OID_PTR oid = const_cast<CSSM_OID_PTR>(field_oid);
  CSSM_DATA_PTR field_ptr = NULL;
  CSSM_HANDLE results_handle = CSSM_INVALID_HANDLE;
  uint32_t field_value_count = 0;
  CSSM_RETURN status = CSSM_CL_CertGetFirstCachedFieldValue(
      cl_handle_, cached_cert_handle_, oid, &results_handle,
      &field_value_count, &field_ptr);
  if (status)
    return status;

  // Note: |field_value_count| may be > 1, indicating that more than one
  // value is present. This may happen with extensions, but for current
  // usages, only the first value is returned.
  CSSM_CL_CertAbortQuery(cl_handle_, results_handle);
  field->Reset(cl_handle_, oid, field_ptr);
  return CSSM_OK;
}

}  // namespace x509_util

#pragma clang diagnostic pop  // "-Wdeprecated-declarations"

}  // namespace net
