Source file src/crypto/x509/internal/macos/security.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build darwin
     6  
     7  package macOS
     8  
     9  import (
    10  	"errors"
    11  	"internal/abi"
    12  	"strconv"
    13  	"unsafe"
    14  )
    15  
    16  // Security.framework linker flags for the external linker. See Issue 42459.
    17  //
    18  //go:cgo_ldflag "-framework"
    19  //go:cgo_ldflag "Security"
    20  
    21  // Based on https://opensource.apple.com/source/Security/Security-59306.41.2/base/Security.h
    22  
    23  type SecTrustSettingsResult int32
    24  
    25  const (
    26  	SecTrustSettingsResultInvalid SecTrustSettingsResult = iota
    27  	SecTrustSettingsResultTrustRoot
    28  	SecTrustSettingsResultTrustAsRoot
    29  	SecTrustSettingsResultDeny
    30  	SecTrustSettingsResultUnspecified
    31  )
    32  
    33  type SecTrustResultType int32
    34  
    35  const (
    36  	SecTrustResultInvalid SecTrustResultType = iota
    37  	SecTrustResultProceed
    38  	SecTrustResultConfirm // deprecated
    39  	SecTrustResultDeny
    40  	SecTrustResultUnspecified
    41  	SecTrustResultRecoverableTrustFailure
    42  	SecTrustResultFatalTrustFailure
    43  	SecTrustResultOtherError
    44  )
    45  
    46  type SecTrustSettingsDomain int32
    47  
    48  const (
    49  	SecTrustSettingsDomainUser SecTrustSettingsDomain = iota
    50  	SecTrustSettingsDomainAdmin
    51  	SecTrustSettingsDomainSystem
    52  )
    53  
    54  const (
    55  	// various macOS error codes that can be returned from
    56  	// SecTrustEvaluateWithError that we can map to Go cert
    57  	// verification error types.
    58  	ErrSecCertificateExpired = -67818
    59  	ErrSecHostNameMismatch   = -67602
    60  	ErrSecNotTrusted         = -67843
    61  )
    62  
    63  type OSStatus struct {
    64  	call   string
    65  	status int32
    66  }
    67  
    68  func (s OSStatus) Error() string {
    69  	return s.call + " error: " + strconv.Itoa(int(s.status))
    70  }
    71  
    72  // Dictionary keys are defined as build-time strings with CFSTR, but the Go
    73  // linker's internal linking mode can't handle CFSTR relocations. Create our
    74  // own dynamic strings instead and just never release them.
    75  //
    76  // Note that this might be the only thing that can break over time if
    77  // these values change, as the ABI arguably requires using the strings
    78  // pointed to by the symbols, not values that happen to be equal to them.
    79  
    80  var SecTrustSettingsResultKey = StringToCFString("kSecTrustSettingsResult")
    81  var SecTrustSettingsPolicy = StringToCFString("kSecTrustSettingsPolicy")
    82  var SecTrustSettingsPolicyString = StringToCFString("kSecTrustSettingsPolicyString")
    83  var SecPolicyOid = StringToCFString("SecPolicyOid")
    84  var SecPolicyAppleSSL = StringToCFString("1.2.840.113635.100.1.3") // defined by POLICYMACRO
    85  
    86  var ErrNoTrustSettings = errors.New("no trust settings found")
    87  
    88  const errSecNoTrustSettings = -25263
    89  
    90  //go:cgo_import_dynamic x509_SecTrustSettingsCopyCertificates SecTrustSettingsCopyCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security"
    91  
    92  func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {
    93  	ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyCertificates_trampoline), uintptr(domain),
    94  		uintptr(unsafe.Pointer(&certArray)), 0, 0, 0, 0)
    95  	if int32(ret) == errSecNoTrustSettings {
    96  		return 0, ErrNoTrustSettings
    97  	} else if ret != 0 {
    98  		return 0, OSStatus{"SecTrustSettingsCopyCertificates", int32(ret)}
    99  	}
   100  	return certArray, nil
   101  }
   102  func x509_SecTrustSettingsCopyCertificates_trampoline()
   103  
   104  const errSecItemNotFound = -25300
   105  
   106  //go:cgo_import_dynamic x509_SecTrustSettingsCopyTrustSettings SecTrustSettingsCopyTrustSettings "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   107  
   108  func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {
   109  	ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyTrustSettings_trampoline), uintptr(cert), uintptr(domain),
   110  		uintptr(unsafe.Pointer(&trustSettings)), 0, 0, 0)
   111  	if int32(ret) == errSecItemNotFound {
   112  		return 0, ErrNoTrustSettings
   113  	} else if ret != 0 {
   114  		return 0, OSStatus{"SecTrustSettingsCopyTrustSettings", int32(ret)}
   115  	}
   116  	return trustSettings, nil
   117  }
   118  func x509_SecTrustSettingsCopyTrustSettings_trampoline()
   119  
   120  //go:cgo_import_dynamic x509_SecTrustCreateWithCertificates SecTrustCreateWithCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   121  
   122  func SecTrustCreateWithCertificates(certs CFRef, policies CFRef) (CFRef, error) {
   123  	var trustObj CFRef
   124  	ret := syscall(abi.FuncPCABI0(x509_SecTrustCreateWithCertificates_trampoline), uintptr(certs), uintptr(policies),
   125  		uintptr(unsafe.Pointer(&trustObj)), 0, 0, 0)
   126  	if int32(ret) != 0 {
   127  		return 0, OSStatus{"SecTrustCreateWithCertificates", int32(ret)}
   128  	}
   129  	return trustObj, nil
   130  }
   131  func x509_SecTrustCreateWithCertificates_trampoline()
   132  
   133  //go:cgo_import_dynamic x509_SecCertificateCreateWithData SecCertificateCreateWithData "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   134  
   135  func SecCertificateCreateWithData(b []byte) (CFRef, error) {
   136  	data := BytesToCFData(b)
   137  	defer CFRelease(data)
   138  	ret := syscall(abi.FuncPCABI0(x509_SecCertificateCreateWithData_trampoline), kCFAllocatorDefault, uintptr(data), 0, 0, 0, 0)
   139  	// Returns NULL if the data passed in the data parameter is not a valid
   140  	// DER-encoded X.509 certificate.
   141  	if ret == 0 {
   142  		return 0, errors.New("SecCertificateCreateWithData: invalid certificate")
   143  	}
   144  	return CFRef(ret), nil
   145  }
   146  func x509_SecCertificateCreateWithData_trampoline()
   147  
   148  //go:cgo_import_dynamic x509_SecPolicyCreateSSL SecPolicyCreateSSL "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   149  
   150  func SecPolicyCreateSSL(name string) (CFRef, error) {
   151  	var hostname CFString
   152  	if name != "" {
   153  		hostname = StringToCFString(name)
   154  		defer CFRelease(CFRef(hostname))
   155  	}
   156  	ret := syscall(abi.FuncPCABI0(x509_SecPolicyCreateSSL_trampoline), 1 /* true */, uintptr(hostname), 0, 0, 0, 0)
   157  	if ret == 0 {
   158  		return 0, OSStatus{"SecPolicyCreateSSL", int32(ret)}
   159  	}
   160  	return CFRef(ret), nil
   161  }
   162  func x509_SecPolicyCreateSSL_trampoline()
   163  
   164  //go:cgo_import_dynamic x509_SecTrustSetVerifyDate SecTrustSetVerifyDate "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   165  
   166  func SecTrustSetVerifyDate(trustObj CFRef, dateRef CFRef) error {
   167  	ret := syscall(abi.FuncPCABI0(x509_SecTrustSetVerifyDate_trampoline), uintptr(trustObj), uintptr(dateRef), 0, 0, 0, 0)
   168  	if int32(ret) != 0 {
   169  		return OSStatus{"SecTrustSetVerifyDate", int32(ret)}
   170  	}
   171  	return nil
   172  }
   173  func x509_SecTrustSetVerifyDate_trampoline()
   174  
   175  //go:cgo_import_dynamic x509_SecTrustEvaluate SecTrustEvaluate "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   176  
   177  func SecTrustEvaluate(trustObj CFRef) (CFRef, error) {
   178  	var result CFRef
   179  	ret := syscall(abi.FuncPCABI0(x509_SecTrustEvaluate_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&result)), 0, 0, 0, 0)
   180  	if int32(ret) != 0 {
   181  		return 0, OSStatus{"SecTrustEvaluate", int32(ret)}
   182  	}
   183  	return CFRef(result), nil
   184  }
   185  func x509_SecTrustEvaluate_trampoline()
   186  
   187  //go:cgo_import_dynamic x509_SecTrustGetResult SecTrustGetResult "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   188  
   189  func SecTrustGetResult(trustObj CFRef, result CFRef) (CFRef, CFRef, error) {
   190  	var chain, info CFRef
   191  	ret := syscall(abi.FuncPCABI0(x509_SecTrustGetResult_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&result)),
   192  		uintptr(unsafe.Pointer(&chain)), uintptr(unsafe.Pointer(&info)), 0, 0)
   193  	if int32(ret) != 0 {
   194  		return 0, 0, OSStatus{"SecTrustGetResult", int32(ret)}
   195  	}
   196  	return chain, info, nil
   197  }
   198  func x509_SecTrustGetResult_trampoline()
   199  
   200  //go:cgo_import_dynamic x509_SecTrustEvaluateWithError SecTrustEvaluateWithError "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   201  
   202  func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
   203  	var errRef CFRef
   204  	ret := syscall(abi.FuncPCABI0(x509_SecTrustEvaluateWithError_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&errRef)), 0, 0, 0, 0)
   205  	if int32(ret) != 1 {
   206  		errStr := CFErrorCopyDescription(errRef)
   207  		err := errors.New(CFStringToString(errStr))
   208  		errCode := CFErrorGetCode(errRef)
   209  		CFRelease(errRef)
   210  		CFRelease(errStr)
   211  		return errCode, err
   212  	}
   213  	return 0, nil
   214  }
   215  func x509_SecTrustEvaluateWithError_trampoline()
   216  
   217  //go:cgo_import_dynamic x509_SecTrustGetCertificateCount SecTrustGetCertificateCount "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   218  
   219  func SecTrustGetCertificateCount(trustObj CFRef) int {
   220  	ret := syscall(abi.FuncPCABI0(x509_SecTrustGetCertificateCount_trampoline), uintptr(trustObj), 0, 0, 0, 0, 0)
   221  	return int(ret)
   222  }
   223  func x509_SecTrustGetCertificateCount_trampoline()
   224  
   225  //go:cgo_import_dynamic x509_SecTrustGetCertificateAtIndex SecTrustGetCertificateAtIndex "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   226  
   227  func SecTrustGetCertificateAtIndex(trustObj CFRef, i int) (CFRef, error) {
   228  	ret := syscall(abi.FuncPCABI0(x509_SecTrustGetCertificateAtIndex_trampoline), uintptr(trustObj), uintptr(i), 0, 0, 0, 0)
   229  	if ret == 0 {
   230  		return 0, OSStatus{"SecTrustGetCertificateAtIndex", int32(ret)}
   231  	}
   232  	return CFRef(ret), nil
   233  }
   234  func x509_SecTrustGetCertificateAtIndex_trampoline()
   235  
   236  //go:cgo_import_dynamic x509_SecCertificateCopyData SecCertificateCopyData "/System/Library/Frameworks/Security.framework/Versions/A/Security"
   237  
   238  func SecCertificateCopyData(cert CFRef) ([]byte, error) {
   239  	ret := syscall(abi.FuncPCABI0(x509_SecCertificateCopyData_trampoline), uintptr(cert), 0, 0, 0, 0, 0)
   240  	if ret == 0 {
   241  		return nil, errors.New("x509: invalid certificate object")
   242  	}
   243  	b := CFDataToSlice(CFRef(ret))
   244  	CFRelease(CFRef(ret))
   245  	return b, nil
   246  }
   247  func x509_SecCertificateCopyData_trampoline()
   248  

View as plain text