// Copyright 2017 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/internal/trust_store_mac.h"

#include <Security/Security.h>

#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/mac_logging.h"
#include "base/synchronization/lock.h"
#include "crypto/mac_security_services_lock.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/internal/parse_name.h"
#include "net/cert/internal/parsed_certificate.h"
#include "net/cert/test_keychain_search_list_mac.h"
#include "net/cert/x509_util.h"
#include "net/cert/x509_util_mac.h"
#include "starboard/types.h"

namespace net {

namespace {

// The rules for interpreting trust settings are documented at:
// https://developer.apple.com/reference/security/1400261-sectrustsettingscopytrustsetting?language=objc

// Indicates the trust status of a certificate.
enum class TrustStatus {
  // Certificate inherits trust value from its issuer. If the certificate is the
  // root of the chain, this implies distrust.
  UNSPECIFIED,
  // Certificate is a trust anchor.
  TRUSTED,
  // Certificate is blacklisted / explicitly distrusted.
  DISTRUSTED
};

// Returns trust status of usage constraints dictionary |trust_dict| for a
// certificate that |is_self_signed|.
TrustStatus IsTrustDictionaryTrustedForPolicy(
    CFDictionaryRef trust_dict,
    bool is_self_signed,
    const CFStringRef target_policy_oid) {
  // An empty trust dict should be interpreted as
  // kSecTrustSettingsResultTrustRoot. This is handled by falling through all
  // the conditions below with the default value of |trust_settings_result|.

  // Trust settings may be scoped to a single application, by checking that the
  // code signing identity of the current application matches the serialized
  // code signing identity in the kSecTrustSettingsApplication key.
  // As this is not presently supported, skip any trust settings scoped to the
  // application.
  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsApplication))
    return TrustStatus::UNSPECIFIED;

  // Trust settings may be scoped using policy-specific constraints. For
  // example, SSL trust settings might be scoped to a single hostname, or EAP
  // settings specific to a particular WiFi network.
  // As this is not presently supported, skip any policy-specific trust
  // settings.
  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsPolicyString))
    return TrustStatus::UNSPECIFIED;

  // Ignoring kSecTrustSettingsKeyUsage for now; it does not seem relevant to
  // the TLS case.

  // If the trust settings are scoped to a specific policy (via
  // kSecTrustSettingsPolicy), ensure that the policy is the same policy as
  // |target_policy_oid|. If there is no kSecTrustSettingsPolicy key, it's
  // considered a match for all policies.
  SecPolicyRef policy_ref = base::mac::GetValueFromDictionary<SecPolicyRef>(
      trust_dict, kSecTrustSettingsPolicy);
  if (policy_ref) {
    base::ScopedCFTypeRef<CFDictionaryRef> policy_dict;
    {
      base::AutoLock lock(crypto::GetMacSecurityServicesLock());
      policy_dict.reset(SecPolicyCopyProperties(policy_ref));
    }

    // kSecPolicyOid is guaranteed to be present in the policy dictionary.
    //
    // TODO(mattm): remove the CFCastStrict below once Chromium builds against
    // the 10.11 SDK.
    CFStringRef policy_oid = base::mac::GetValueFromDictionary<CFStringRef>(
        policy_dict, base::mac::CFCastStrict<CFStringRef>(kSecPolicyOid));

    if (!CFEqual(policy_oid, target_policy_oid))
      return TrustStatus::UNSPECIFIED;
  }

  // If kSecTrustSettingsResult is not present in the trust dict,
  // kSecTrustSettingsResultTrustRoot is assumed.
  int trust_settings_result = kSecTrustSettingsResultTrustRoot;
  CFNumberRef trust_settings_result_ref =
      base::mac::GetValueFromDictionary<CFNumberRef>(trust_dict,
                                                     kSecTrustSettingsResult);
  if (trust_settings_result_ref &&
      !CFNumberGetValue(trust_settings_result_ref, kCFNumberIntType,
                        &trust_settings_result)) {
    return TrustStatus::UNSPECIFIED;
  }

  if (trust_settings_result == kSecTrustSettingsResultDeny)
    return TrustStatus::DISTRUSTED;

  // kSecTrustSettingsResultTrustRoot can only be applied to root(self-signed)
  // certs.
  if (is_self_signed)
    return (trust_settings_result == kSecTrustSettingsResultTrustRoot)
               ? TrustStatus::TRUSTED
               : TrustStatus::UNSPECIFIED;

  // kSecTrustSettingsResultTrustAsRoot can only be applied to non-root certs.
  return (trust_settings_result == kSecTrustSettingsResultTrustAsRoot)
             ? TrustStatus::TRUSTED
             : TrustStatus::UNSPECIFIED;
}

// Returns true if the trust settings array |trust_settings| for a certificate
// that |is_self_signed| should be treated as a trust anchor.
TrustStatus IsTrustSettingsTrustedForPolicy(CFArrayRef trust_settings,
                                            bool is_self_signed,
                                            const CFStringRef policy_oid) {
  // An empty trust settings array (that is, the trust_settings parameter
  // returns a valid but empty CFArray) means "always trust this certificate"
  // with an overall trust setting for the certificate of
  // kSecTrustSettingsResultTrustRoot.
  if (CFArrayGetCount(trust_settings) == 0 && is_self_signed)
    return TrustStatus::TRUSTED;

  for (CFIndex i = 0, settings_count = CFArrayGetCount(trust_settings);
       i < settings_count; ++i) {
    CFDictionaryRef trust_dict = reinterpret_cast<CFDictionaryRef>(
        const_cast<void*>(CFArrayGetValueAtIndex(trust_settings, i)));
    TrustStatus trust = IsTrustDictionaryTrustedForPolicy(
        trust_dict, is_self_signed, policy_oid);
    if (trust != TrustStatus::UNSPECIFIED)
      return trust;
  }
  return TrustStatus::UNSPECIFIED;
}

// Returns true if the certificate |cert_handle| is trusted for the policy
// |policy_oid|.
TrustStatus IsSecCertificateTrustedForPolicy(SecCertificateRef cert_handle,
                                             const CFStringRef policy_oid) {
  const bool is_self_signed = x509_util::IsSelfSigned(cert_handle);
  // Evaluate trust domains in user, admin, system order. Admin settings can
  // override system ones, and user settings can override both admin and system.
  for (const auto& trust_domain :
       {kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin,
        kSecTrustSettingsDomainSystem}) {
    base::ScopedCFTypeRef<CFArrayRef> trust_settings;
    OSStatus err;
    {
      base::AutoLock lock(crypto::GetMacSecurityServicesLock());
      err = SecTrustSettingsCopyTrustSettings(cert_handle, trust_domain,
                                              trust_settings.InitializeInto());
    }
    if (err == errSecItemNotFound) {
      // No trust settings for that domain.. try the next.
      continue;
    }
    if (err) {
      OSSTATUS_LOG(ERROR, err) << "SecTrustSettingsCopyTrustSettings error";
      continue;
    }
    TrustStatus trust = IsTrustSettingsTrustedForPolicy(
        trust_settings, is_self_signed, policy_oid);
    if (trust != TrustStatus::UNSPECIFIED)
      return trust;
  }

  // No trust settings, or none of the settings were for the correct policy, or
  // had the correct trust result.
  return TrustStatus::UNSPECIFIED;
}

}  // namespace

TrustStoreMac::TrustStoreMac(CFTypeRef policy_oid)
    : policy_oid_(base::mac::CFCastStrict<CFStringRef>(policy_oid)) {
  DCHECK(policy_oid_);
}

TrustStoreMac::~TrustStoreMac() = default;

void TrustStoreMac::SyncGetIssuersOf(const ParsedCertificate* cert,
                                     ParsedCertificateList* issuers) {
  base::ScopedCFTypeRef<CFDataRef> name_data = GetMacNormalizedIssuer(cert);
  if (!name_data)
    return;

  base::ScopedCFTypeRef<CFArrayRef> matching_items =
      FindMatchingCertificatesForMacNormalizedSubject(name_data);
  if (!matching_items)
    return;

  // Convert to ParsedCertificate.
  for (CFIndex i = 0, item_count = CFArrayGetCount(matching_items);
       i < item_count; ++i) {
    SecCertificateRef match_cert_handle = reinterpret_cast<SecCertificateRef>(
        const_cast<void*>(CFArrayGetValueAtIndex(matching_items, i)));

    base::ScopedCFTypeRef<CFDataRef> der_data(
        SecCertificateCopyData(match_cert_handle));
    if (!der_data) {
      LOG(ERROR) << "SecCertificateCopyData error";
      continue;
    }

    CertErrors errors;
    ParseCertificateOptions options;
    options.allow_invalid_serial_numbers = true;
    scoped_refptr<ParsedCertificate> anchor_cert = ParsedCertificate::Create(
        x509_util::CreateCryptoBuffer(CFDataGetBytePtr(der_data.get()),
                                      CFDataGetLength(der_data.get())),
        options, &errors);
    if (!anchor_cert) {
      // TODO(crbug.com/634443): return errors better.
      LOG(ERROR) << "Error parsing issuer certificate:\n"
                 << errors.ToDebugString();
      continue;
    }

    issuers->push_back(std::move(anchor_cert));
  }
}

void TrustStoreMac::GetTrust(const scoped_refptr<ParsedCertificate>& cert,
                             CertificateTrust* trust) const {
  // TODO(eroman): Inefficient -- path building will convert between
  // SecCertificateRef and ParsedCertificate representations multiple times
  // (when getting the issuers, and again here).
  base::ScopedCFTypeRef<SecCertificateRef> cert_handle =
      x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(),
                                               cert->der_cert().Length());
  if (!cert_handle) {
    *trust = CertificateTrust::ForUnspecified();
    return;
  }

  TrustStatus trust_status =
      IsSecCertificateTrustedForPolicy(cert_handle, policy_oid_);
  switch (trust_status) {
    case TrustStatus::TRUSTED:
      *trust = CertificateTrust::ForTrustAnchor();
      return;
    case TrustStatus::DISTRUSTED:
      *trust = CertificateTrust::ForDistrusted();
      return;
    case TrustStatus::UNSPECIFIED:
      *trust = CertificateTrust::ForUnspecified();
      return;
  }

  *trust = CertificateTrust::ForUnspecified();
  return;
}

// static
base::ScopedCFTypeRef<CFArrayRef>
TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject(
    CFDataRef name_data) {
  base::ScopedCFTypeRef<CFArrayRef> matching_items;
  base::ScopedCFTypeRef<CFMutableDictionaryRef> query(
      CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks,
                                &kCFTypeDictionaryValueCallBacks));

  CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
  CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
  CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
  CFDictionarySetValue(query, kSecAttrSubject, name_data);

  base::ScopedCFTypeRef<CFArrayRef> scoped_alternate_keychain_search_list;
  if (TestKeychainSearchList::HasInstance()) {
    OSStatus status = TestKeychainSearchList::GetInstance()->CopySearchList(
        scoped_alternate_keychain_search_list.InitializeInto());
    if (status) {
      OSSTATUS_LOG(ERROR, status)
          << "TestKeychainSearchList::CopySearchList error";
      return matching_items;
    }
  }

  base::AutoLock lock(crypto::GetMacSecurityServicesLock());

  // If a TestKeychainSearchList is present, it will have already set
  // |scoped_alternate_keychain_search_list|, which will be used as the
  // basis for reordering the keychain. Otherwise, get the current keychain
  // search list and use that.
  if (!scoped_alternate_keychain_search_list) {
    OSStatus status = SecKeychainCopySearchList(
        scoped_alternate_keychain_search_list.InitializeInto());
    if (status) {
      OSSTATUS_LOG(ERROR, status) << "SecKeychainCopySearchList error";
      return matching_items;
    }
  }

  CFMutableArrayRef mutable_keychain_search_list = CFArrayCreateMutableCopy(
      kCFAllocatorDefault,
      CFArrayGetCount(scoped_alternate_keychain_search_list.get()) + 1,
      scoped_alternate_keychain_search_list.get());
  if (!mutable_keychain_search_list) {
    LOG(ERROR) << "CFArrayCreateMutableCopy";
    return matching_items;
  }
  scoped_alternate_keychain_search_list.reset(mutable_keychain_search_list);

  base::ScopedCFTypeRef<SecKeychainRef> roots_keychain;
  // The System Roots keychain is not normally searched by SecItemCopyMatching.
  // Get a reference to it and include in the keychain search list.
  OSStatus status = SecKeychainOpen(
      "/System/Library/Keychains/SystemRootCertificates.keychain",
      roots_keychain.InitializeInto());
  if (status) {
    OSSTATUS_LOG(ERROR, status) << "SecKeychainOpen error";
    return matching_items;
  }
  CFArrayAppendValue(mutable_keychain_search_list, roots_keychain);

  CFDictionarySetValue(query, kSecMatchSearchList,
                       scoped_alternate_keychain_search_list.get());

  OSStatus err = SecItemCopyMatching(
      query, reinterpret_cast<CFTypeRef*>(matching_items.InitializeInto()));
  if (err == errSecItemNotFound) {
    // No matches found.
    return matching_items;
  }
  if (err) {
    OSSTATUS_LOG(ERROR, err) << "SecItemCopyMatching error";
    return matching_items;
  }
  return matching_items;
}

// static
base::ScopedCFTypeRef<CFDataRef> TrustStoreMac::GetMacNormalizedIssuer(
    const ParsedCertificate* cert) {
  base::ScopedCFTypeRef<CFDataRef> name_data;
  // There does not appear to be any public API to get the normalized version
  // of a Name without creating a SecCertificate.
  base::ScopedCFTypeRef<SecCertificateRef> cert_handle(
      x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(),
                                               cert->der_cert().Length()));
  if (!cert_handle) {
    LOG(ERROR) << "CreateCertBufferFromBytes";
    return name_data;
  }
  {
    base::AutoLock lock(crypto::GetMacSecurityServicesLock());
    name_data.reset(
        SecCertificateCopyNormalizedIssuerContent(cert_handle, nullptr));
  }
  if (!name_data)
    LOG(ERROR) << "SecCertificateCopyNormalizedIssuerContent";
  return name_data;
}

}  // namespace net
