Copyright 2020 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+build !ios

package x509

import (
	
	macOS 
	
	
	
)

var debugDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "x509roots=1")

func ( *Certificate) ( *VerifyOptions) ( [][]*Certificate,  error) {
	return nil, nil
}

func () (*CertPool, error) {
	var  []*Certificate
	 := make(map[string]bool)
macOS has three trust domains: one for CAs added by users to their "login" keychain, one for CAs added by Admins to the "System" keychain, and one for the CAs that ship with the OS.
	for ,  := range []macOS.SecTrustSettingsDomain{
		macOS.SecTrustSettingsDomainUser,
		macOS.SecTrustSettingsDomainAdmin,
		macOS.SecTrustSettingsDomainSystem,
	} {
		,  := macOS.SecTrustSettingsCopyCertificates()
		if  == macOS.ErrNoTrustSettings {
			continue
		} else if  != nil {
			return nil, 
		}
		defer macOS.CFRelease()

		for  := 0;  < macOS.CFArrayGetCount(); ++ {
			 := macOS.CFArrayGetValueAtIndex(, )
			,  := exportCertificate()
			if  != nil {
				if debugDarwinRoots {
					fmt.Fprintf(os.Stderr, "crypto/x509: domain %d, certificate #%d: %v\n", , , )
				}
				continue
			}

			var  macOS.SecTrustSettingsResult
Certs found in the system domain are always trusted. If the user configures "Never Trust" on such a cert, it will also be found in the admin or user domain, causing it to be added to untrustedRoots.
				 = macOS.SecTrustSettingsResultTrustRoot
			} else {
				,  = sslTrustSettingsResult()
				if  != nil {
					if debugDarwinRoots {
						fmt.Fprintf(os.Stderr, "crypto/x509: trust settings for %v: %v\n", .Subject, )
					}
					continue
				}
				if debugDarwinRoots {
					fmt.Fprintf(os.Stderr, "crypto/x509: trust settings for %v: %d\n", .Subject, )
				}
			}

"Note the distinction between the results kSecTrustSettingsResultTrustRoot and kSecTrustSettingsResultTrustAsRoot: The former can only be applied to root (self-signed) certificates; the latter can only be applied to non-root certificates."
			case macOS.SecTrustSettingsResultTrustRoot:
				if isRootCertificate() {
					 = append(, )
				}
			case macOS.SecTrustSettingsResultTrustAsRoot:
				if !isRootCertificate() {
					 = append(, )
				}

Add this certificate to untrustedRoots, which are subtracted from trustedRoots, so that we don't have to evaluate policies for every root in the system domain, but still apply user and admin policies that override system roots.
				[string(.Raw)] = true

Certificates with unspecified trust should be added to a pool of intermediates for chain building, but we don't support it at the moment. This is Issue 35631.

			default:
				if debugDarwinRoots {
					fmt.Fprintf(os.Stderr, "crypto/x509: unknown trust setting for %v: %d\n", .Subject, )
				}
			}
		}
	}

	 := NewCertPool()
	for ,  := range  {
		if ![string(.Raw)] {
			.AddCert()
		}
	}
	return , nil
}
exportCertificate returns a *Certificate for a SecCertificateRef.
func ( macOS.CFRef) (*Certificate, error) {
	,  := macOS.SecItemExport()
	if  != nil {
		return nil, 
	}
	defer macOS.CFRelease()
	 := macOS.CFDataToSlice()

	return ParseCertificate()
}
isRootCertificate reports whether Subject and Issuer match.
func ( *Certificate) bool {
	return bytes.Equal(.RawSubject, .RawIssuer)
}
sslTrustSettingsResult obtains the final kSecTrustSettingsResult value for a certificate in the user or admin domain, combining usage constraints for the SSL SecTrustSettingsPolicy, It ignores SecTrustSettingsKeyUsage and kSecTrustSettingsAllowedError, and doesn't support kSecTrustSettingsDefaultRootCertSetting. https://developer.apple.com/documentation/security/1400261-sectrustsettingscopytrustsetting
In Apple's implementation user trust settings override admin trust settings (which themselves override system trust settings). If SecTrustSettingsCopyTrustSettings fails, or returns a NULL trust settings, when looking for the user trust settings then fallback to checking the admin trust settings. See Security-59306.41.2/trust/headers/SecTrustSettings.h for a description of the trust settings overrides, and SecLegacyAnchorSourceCopyUsageConstraints in Security-59306.41.2/trust/trustd/SecCertificateSource.c for a concrete example of how Apple applies the override in the case of NULL trust settings, or non success errors.
	,  := macOS.SecTrustSettingsCopyTrustSettings(, macOS.SecTrustSettingsDomainUser)
	if  != nil ||  == 0 {
		if debugDarwinRoots &&  != macOS.ErrNoTrustSettings {
			fmt.Fprintf(os.Stderr, "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainUser failed: %s\n", )
		}
		,  = macOS.SecTrustSettingsCopyTrustSettings(, macOS.SecTrustSettingsDomainAdmin)
	}
If there are neither user nor admin trust settings for a certificate returned from SecTrustSettingsCopyCertificates Apple returns kSecTrustSettingsResultInvalid, as this method is intended to return certificates _which have trust settings_. The most likely case for this being triggered is that the existing trust settings are invalid and cannot be properly parsed. In this case SecTrustSettingsCopyTrustSettings returns errSecInvalidTrustSettings. The existing cgo implementation returns kSecTrustSettingsResultUnspecified in this case, which mostly matches the Apple implementation because we don't do anything with certificates marked with this result. See SecPVCGetTrustSettingsResult in Security-59306.41.2/trust/trustd/SecPolicyServer.c
		if debugDarwinRoots &&  != macOS.ErrNoTrustSettings {
			fmt.Fprintf(os.Stderr, "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainAdmin failed: %s\n", )
		}
		return macOS.SecTrustSettingsResultUnspecified, nil
	}
	defer macOS.CFRelease()
"An empty trust settings array means 'always trust this certificate' with an overall trust setting for the certificate of kSecTrustSettingsResultTrustRoot."
	if macOS.CFArrayGetCount() == 0 {
		return macOS.SecTrustSettingsResultTrustRoot, nil
	}

	 := func( macOS.CFRef) bool {
		 := macOS.SecPolicyCopyProperties()
		defer macOS.CFRelease()
		if ,  := macOS.CFDictionaryGetValueIfPresent(, macOS.SecPolicyOid);  {
			return macOS.CFEqual(, macOS.CFRef(macOS.SecPolicyAppleSSL))
		}
		return false
	}

	for  := 0;  < macOS.CFArrayGetCount(); ++ {
		 := macOS.CFArrayGetValueAtIndex(, )
First, check if this trust setting is constrained to a non-SSL policy.
		if ,  := macOS.CFDictionaryGetValueIfPresent(, macOS.SecTrustSettingsPolicy);  {
			if !() {
				continue
			}
		}
Then check if it is restricted to a hostname, so not a root.
		if ,  := macOS.CFDictionaryGetValueIfPresent(, macOS.SecTrustSettingsPolicyString);  {
			continue
		}

"If this key is not present, a default value of kSecTrustSettingsResultTrustRoot is assumed."
		if ! {
			return macOS.SecTrustSettingsResultTrustRoot, nil
		}
		,  := macOS.CFNumberGetValue()
		if  != nil {
			return 0, 
		}
If multiple dictionaries match, we are supposed to "OR" them, the semantics of which are not clear. Since TrustRoot and TrustAsRoot are mutually exclusive, Deny should probably override, and Invalid and Unspecified be overridden, approximate this by stopping at the first TrustRoot, TrustAsRoot or Deny.
If trust settings are present, but none of them match the policy... the docs don't tell us what to do. "Trust settings for a given use apply if any of the dictionaries in the certificate’s trust settings array satisfies the specified use." suggests that it's as if there were no trust settings at all, so we should maybe fallback to the admin trust settings? TODO(golang.org/issue/38888).