// Copyright 2013 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/ssl/client_cert_store_mac.h"

#include <CommonCrypto/CommonDigest.h>
#include <CoreFoundation/CFArray.h>
#include <CoreServices/CoreServices.h>
#include <Security/SecBase.h>
#include <Security/Security.h>

#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/task_runner_util.h"
#include "crypto/mac_security_services_lock.h"
#include "net/base/host_port_pair.h"
#include "net/cert/x509_util.h"
#include "net/cert/x509_util_ios_and_mac.h"
#include "net/cert/x509_util_mac.h"
#include "net/ssl/client_cert_identity_mac.h"
#include "net/ssl/ssl_platform_key_util.h"

using base::ScopedCFTypeRef;

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 {

// Gets the issuer for a given cert, starting with the cert itself and
// including the intermediate and finally root certificates (if any).
// This function calls SecTrust but doesn't actually pay attention to the trust
// result: it shouldn't be used to determine trust, just to traverse the chain.
// Caller is responsible for releasing the value stored into *out_cert_chain.
OSStatus CopyCertChain(SecCertificateRef cert_handle,
                       CFArrayRef* out_cert_chain) {
  DCHECK(cert_handle);
  DCHECK(out_cert_chain);

  // Create an SSL policy ref configured for client cert evaluation.
  SecPolicyRef ssl_policy;
  OSStatus result = x509_util::CreateSSLClientPolicy(&ssl_policy);
  if (result)
    return result;
  ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy);

  // Create a SecTrustRef.
  ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate(
      NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)),
      1, &kCFTypeArrayCallBacks));
  SecTrustRef trust_ref = NULL;
  {
    base::AutoLock lock(crypto::GetMacSecurityServicesLock());
    result = SecTrustCreateWithCertificates(input_certs, ssl_policy,
                                            &trust_ref);
  }
  if (result)
    return result;
  ScopedCFTypeRef<SecTrustRef> trust(trust_ref);

  // Evaluate trust, which creates the cert chain.
  SecTrustResultType status;
  CSSM_TP_APPLE_EVIDENCE_INFO* status_chain;
  {
    base::AutoLock lock(crypto::GetMacSecurityServicesLock());
    result = SecTrustEvaluate(trust, &status);
  }
  if (result)
    return result;
  {
    base::AutoLock lock(crypto::GetMacSecurityServicesLock());
    result = SecTrustGetResult(trust, &status, out_cert_chain, &status_chain);
  }
  return result;
}

// Returns true if |*identity| is issued by an authority in |valid_issuers|
// according to Keychain Services, rather than using |identity|'s intermediate
// certificates. If it is, |*identity| is updated to include the intermediates.
bool IsIssuedByInKeychain(const std::vector<std::string>& valid_issuers,
                          ClientCertIdentity* identity) {
  DCHECK(identity);
  DCHECK(identity->sec_identity_ref());

  ScopedCFTypeRef<SecCertificateRef> os_cert;
  int err = SecIdentityCopyCertificate(identity->sec_identity_ref(),
                                       os_cert.InitializeInto());
  if (err != noErr)
    return false;
  CFArrayRef cert_chain = NULL;
  OSStatus result = CopyCertChain(os_cert.get(), &cert_chain);
  if (result) {
    OSSTATUS_LOG(ERROR, result) << "CopyCertChain error";
    return false;
  }

  if (!cert_chain)
    return false;

  std::vector<SecCertificateRef> intermediates;
  for (CFIndex i = 1, chain_count = CFArrayGetCount(cert_chain);
       i < chain_count; ++i) {
    SecCertificateRef sec_cert = reinterpret_cast<SecCertificateRef>(
        const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
    intermediates.push_back(sec_cert);
  }

  // Allow UTF-8 inside PrintableStrings in client certificates. See
  // crbug.com/770323.
  X509Certificate::UnsafeCreateOptions options;
  options.printable_string_is_utf8 = true;
  scoped_refptr<X509Certificate> new_cert(
      x509_util::CreateX509CertificateFromSecCertificate(
          os_cert.get(), intermediates, options));
  CFRelease(cert_chain);  // Also frees |intermediates|.

  if (!new_cert || !new_cert->IsIssuedByEncoded(valid_issuers))
    return false;

  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediate_buffers;
  intermediate_buffers.reserve(new_cert->intermediate_buffers().size());
  for (const auto& intermediate : new_cert->intermediate_buffers()) {
    intermediate_buffers.push_back(bssl::UpRef(intermediate.get()));
  }
  identity->SetIntermediates(std::move(intermediate_buffers));
  return true;
}

// Returns true if |purpose| is listed as allowed in |usage|. This
// function also considers the "Any" purpose. If the attribute is
// present and empty, we return false.
bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage,
                            const CSSM_OID* purpose) {
  for (unsigned p = 0; p < usage->numPurposes; ++p) {
    if (x509_util::CSSMOIDEqual(&usage->purposes[p], purpose))
      return true;
    if (x509_util::CSSMOIDEqual(&usage->purposes[p],
                                &CSSMOID_ExtendedKeyUsageAny))
      return true;
  }
  return false;
}

// Does |cert|'s usage allow SSL client authentication?
bool SupportsSSLClientAuth(SecCertificateRef cert) {
  x509_util::CSSMCachedCertificate cached_cert;
  OSStatus status = cached_cert.Init(cert);
  if (status)
    return false;

  // RFC5280 says to take the intersection of the two extensions.
  //
  // Our underlying crypto libraries don't expose
  // ClientCertificateType, so for now we will not support fixed
  // Diffie-Hellman mechanisms. For rsa_sign, we need the
  // digitalSignature bit.
  //
  // In particular, if a key has the nonRepudiation bit and not the
  // digitalSignature one, we will not offer it to the user.
  x509_util::CSSMFieldValue key_usage;
  status = cached_cert.GetField(&CSSMOID_KeyUsage, &key_usage);
  if (status == CSSM_OK && key_usage.field()) {
    const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>();
    const CE_KeyUsage* key_usage_value =
        reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue);
    if (!((*key_usage_value) & CE_KU_DigitalSignature))
      return false;
  }

  status = cached_cert.GetField(&CSSMOID_ExtendedKeyUsage, &key_usage);
  if (status == CSSM_OK && key_usage.field()) {
    const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>();
    const CE_ExtendedKeyUsage* ext_key_usage =
        reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue);
    if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth))
      return false;
  }
  return true;
}

// Examines the certificates in |preferred_identity| and |regular_identities| to
// find all certificates that match the client certificate request in |request|,
// storing the matching certificates in |selected_identities|.
// If |query_keychain| is true, Keychain Services will be queried to construct
// full certificate chains. If it is false, only the the certificates and their
// intermediates (available via X509Certificate::intermediate_buffers())
// will be considered.
void GetClientCertsImpl(std::unique_ptr<ClientCertIdentity> preferred_identity,
                        ClientCertIdentityList regular_identities,
                        const SSLCertRequestInfo& request,
                        bool query_keychain,
                        ClientCertIdentityList* selected_identities) {
  scoped_refptr<X509Certificate> preferred_cert_orig;
  ClientCertIdentityList preliminary_list(std::move(regular_identities));
  if (preferred_identity) {
    preferred_cert_orig = preferred_identity->certificate();
    preliminary_list.insert(preliminary_list.begin(),
                            std::move(preferred_identity));
  }

  selected_identities->clear();
  for (size_t i = 0; i < preliminary_list.size(); ++i) {
    std::unique_ptr<ClientCertIdentity>& cert = preliminary_list[i];
    if (cert->certificate()->HasExpired())
      continue;

    // Skip duplicates (a cert may be in multiple keychains).
    auto cert_iter = std::find_if(
        selected_identities->begin(), selected_identities->end(),
        [&cert](
            const std::unique_ptr<ClientCertIdentity>& other_cert_identity) {
          return x509_util::CryptoBufferEqual(
              cert->certificate()->cert_buffer(),
              other_cert_identity->certificate()->cert_buffer());
        });
    if (cert_iter != selected_identities->end())
      continue;

    // Check if the certificate issuer is allowed by the server.
    if (request.cert_authorities.empty() ||
        cert->certificate()->IsIssuedByEncoded(request.cert_authorities) ||
        (query_keychain &&
         IsIssuedByInKeychain(request.cert_authorities, cert.get()))) {
      selected_identities->push_back(std::move(cert));
    }
  }

  // Preferred cert should appear first in the ui, so exclude it from the
  // sorting.  Compare the cert_buffer since the X509Certificate object may
  // have changed if intermediates were added.
  ClientCertIdentityList::iterator sort_begin = selected_identities->begin();
  ClientCertIdentityList::iterator sort_end = selected_identities->end();
  if (preferred_cert_orig && sort_begin != sort_end &&
      x509_util::CryptoBufferEqual(
          sort_begin->get()->certificate()->cert_buffer(),
          preferred_cert_orig->cert_buffer())) {
    ++sort_begin;
  }
  sort(sort_begin, sort_end, ClientCertIdentitySorter());
}

// Given a |sec_identity|, identifies its corresponding certificate, and either
// adds it to |regular_identities| or assigns it to |preferred_identity|, if the
// |sec_identity| matches the |preferred_sec_identity|.
void AddIdentity(ScopedCFTypeRef<SecIdentityRef> sec_identity,
                 SecIdentityRef preferred_sec_identity,
                 ClientCertIdentityList* regular_identities,
                 std::unique_ptr<ClientCertIdentity>* preferred_identity) {
  OSStatus err;
  ScopedCFTypeRef<SecCertificateRef> cert_handle;
  err = SecIdentityCopyCertificate(sec_identity.get(),
                                   cert_handle.InitializeInto());
  if (err != noErr)
    return;

  if (!SupportsSSLClientAuth(cert_handle.get()))
    return;

  // Allow UTF-8 inside PrintableStrings in client certificates. See
  // crbug.com/770323.
  X509Certificate::UnsafeCreateOptions options;
  options.printable_string_is_utf8 = true;
  scoped_refptr<X509Certificate> cert(
      x509_util::CreateX509CertificateFromSecCertificate(cert_handle.get(), {},
                                                         options));
  if (!cert)
    return;

  if (preferred_sec_identity &&
      CFEqual(preferred_sec_identity, sec_identity.get())) {
    *preferred_identity = std::make_unique<ClientCertIdentityMac>(
        std::move(cert), std::move(sec_identity));
  } else {
    regular_identities->push_back(std::make_unique<ClientCertIdentityMac>(
        std::move(cert), std::move(sec_identity)));
  }
}

ClientCertIdentityList GetClientCertsOnBackgroundThread(
    const SSLCertRequestInfo& request) {
  std::string server_domain = request.host_and_port.host();

  ScopedCFTypeRef<SecIdentityRef> preferred_sec_identity;
  if (!server_domain.empty()) {
    // See if there's an identity preference for this domain:
    ScopedCFTypeRef<CFStringRef> domain_str(
        base::SysUTF8ToCFStringRef("https://" + server_domain));
    SecIdentityRef sec_identity = NULL;
    // While SecIdentityCopyPreferences appears to take a list of CA issuers
    // to restrict the identity search to, within Security.framework the
    // argument is ignored and filtering unimplemented. See
    // SecIdentity.cpp in libsecurity_keychain, specifically
    // _SecIdentityCopyPreferenceMatchingName().
    {
      base::AutoLock lock(crypto::GetMacSecurityServicesLock());
      if (SecIdentityCopyPreference(domain_str, 0, NULL, &sec_identity) ==
          noErr)
        preferred_sec_identity.reset(sec_identity);
    }
  }

  // Now enumerate the identities in the available keychains.
  std::unique_ptr<ClientCertIdentity> preferred_identity;
  ClientCertIdentityList regular_identities;

  SecIdentitySearchRef search = NULL;
  OSStatus err;
  {
    base::AutoLock lock(crypto::GetMacSecurityServicesLock());
    err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search);
  }
  if (err)
    return ClientCertIdentityList();
  ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search);
  while (!err) {
    ScopedCFTypeRef<SecIdentityRef> sec_identity;
    {
      base::AutoLock lock(crypto::GetMacSecurityServicesLock());
      err = SecIdentitySearchCopyNext(search, sec_identity.InitializeInto());
    }
    if (err)
      break;
    AddIdentity(std::move(sec_identity), preferred_sec_identity.get(),
                &regular_identities, &preferred_identity);
  }

  if (err != errSecItemNotFound) {
    OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error";
    return ClientCertIdentityList();
  }

  // macOS provides two ways to search for identities. SecIdentitySearchCreate()
  // is deprecated, as it relies on CSSM_KEYUSE_SIGN (part of the deprecated
  // CDSM/CSSA implementation), but is necessary to return some certificates
  // that would otherwise not be returned by SecItemCopyMatching(), which is the
  // non-deprecated way. However, SecIdentitySearchCreate() will not return all
  // items, particularly smart-card based identities, so it's necessary to call
  // both functions.
  static const void* kKeys[] = {
      kSecClass, kSecMatchLimit, kSecReturnRef, kSecAttrCanSign,
  };
  static const void* kValues[] = {
      kSecClassIdentity, kSecMatchLimitAll, kCFBooleanTrue, kCFBooleanTrue,
  };
  ScopedCFTypeRef<CFDictionaryRef> query(CFDictionaryCreate(
      kCFAllocatorDefault, kKeys, kValues, base::size(kValues),
      &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
  ScopedCFTypeRef<CFArrayRef> result;
  {
    base::AutoLock lock(crypto::GetMacSecurityServicesLock());
    err = SecItemCopyMatching(
        query, reinterpret_cast<CFTypeRef*>(result.InitializeInto()));
  }
  if (!err) {
    for (CFIndex i = 0; i < CFArrayGetCount(result); i++) {
      SecIdentityRef item = reinterpret_cast<SecIdentityRef>(
          const_cast<void*>(CFArrayGetValueAtIndex(result, i)));
      AddIdentity(
          ScopedCFTypeRef<SecIdentityRef>(item, base::scoped_policy::RETAIN),
          preferred_sec_identity.get(), &regular_identities,
          &preferred_identity);
    }
  }

  ClientCertIdentityList selected_identities;
  GetClientCertsImpl(std::move(preferred_identity),
                     std::move(regular_identities), request, true,
                     &selected_identities);
  return selected_identities;
}

}  // namespace

ClientCertStoreMac::ClientCertStoreMac() {}

ClientCertStoreMac::~ClientCertStoreMac() {}

void ClientCertStoreMac::GetClientCerts(
    const SSLCertRequestInfo& request,
    const ClientCertListCallback& callback) {
  if (base::PostTaskAndReplyWithResult(
          GetSSLPlatformKeyTaskRunner().get(), FROM_HERE,
          // Caller is responsible for keeping the |request| alive
          // until the callback is run, so ConstRef is safe.
          base::Bind(&GetClientCertsOnBackgroundThread,
                     base::ConstRef(request)),
          callback)) {
    return;
  }

  // If the task could not be posted, behave as if there were no certificates.
  callback.Run(ClientCertIdentityList());
}

bool ClientCertStoreMac::SelectClientCertsForTesting(
    ClientCertIdentityList input_identities,
    const SSLCertRequestInfo& request,
    ClientCertIdentityList* selected_identities) {
  GetClientCertsImpl(NULL, std::move(input_identities), request, false,
                     selected_identities);
  return true;
}

bool ClientCertStoreMac::SelectClientCertsGivenPreferredForTesting(
    std::unique_ptr<ClientCertIdentity> preferred_identity,
    ClientCertIdentityList regular_identities,
    const SSLCertRequestInfo& request,
    ClientCertIdentityList* selected_identities) {
  GetClientCertsImpl(std::move(preferred_identity),
                     std::move(regular_identities), request, false,
                     selected_identities);
  return true;
}

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

}  // namespace net
