github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/crypto/x509/internal/macos/corefoundation.go (about)

     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 provides cgo-less wrappers for Core Foundation and
     8  // Security.framework, similarly to how package syscall provides access to
     9  // libSystem.dylib.
    10  package macOS
    11  
    12  import (
    13  	"errors"
    14  	"internal/abi"
    15  	"reflect"
    16  	"runtime"
    17  	"time"
    18  	"unsafe"
    19  )
    20  
    21  // Core Foundation linker flags for the external linker. See Issue 42459.
    22  //go:cgo_ldflag "-framework"
    23  //go:cgo_ldflag "CoreFoundation"
    24  
    25  // CFRef is an opaque reference to a Core Foundation object. It is a pointer,
    26  // but to memory not owned by Go, so not an unsafe.Pointer.
    27  type CFRef uintptr
    28  
    29  // CFDataToSlice returns a copy of the contents of data as a bytes slice.
    30  func CFDataToSlice(data CFRef) []byte {
    31  	length := CFDataGetLength(data)
    32  	ptr := CFDataGetBytePtr(data)
    33  	src := (*[1 << 20]byte)(unsafe.Pointer(ptr))[:length:length]
    34  	out := make([]byte, length)
    35  	copy(out, src)
    36  	return out
    37  }
    38  
    39  // CFStringToString returns a Go string representation of the passed
    40  // in CFString.
    41  func CFStringToString(ref CFRef) string {
    42  	data := CFStringCreateExternalRepresentation(ref)
    43  	b := CFDataToSlice(data)
    44  	CFRelease(data)
    45  	return string(b)
    46  }
    47  
    48  // TimeToCFDateRef converts a time.Time into an apple CFDateRef
    49  func TimeToCFDateRef(t time.Time) CFRef {
    50  	secs := t.Sub(time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC)).Seconds()
    51  	ref := CFDateCreate(int(secs))
    52  	return ref
    53  }
    54  
    55  type CFString CFRef
    56  
    57  const kCFAllocatorDefault = 0
    58  const kCFStringEncodingUTF8 = 0x08000100
    59  
    60  //go:cgo_import_dynamic x509_CFDataCreate CFDataCreate "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    61  
    62  func BytesToCFData(b []byte) CFRef {
    63  	p := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data)
    64  	ret := syscall(abi.FuncPCABI0(x509_CFDataCreate_trampoline), kCFAllocatorDefault, uintptr(p), uintptr(len(b)), 0, 0, 0)
    65  	runtime.KeepAlive(p)
    66  	return CFRef(ret)
    67  }
    68  func x509_CFDataCreate_trampoline()
    69  
    70  //go:cgo_import_dynamic x509_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    71  
    72  // StringToCFString returns a copy of the UTF-8 contents of s as a new CFString.
    73  func StringToCFString(s string) CFString {
    74  	p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
    75  	ret := syscall(abi.FuncPCABI0(x509_CFStringCreateWithBytes_trampoline), kCFAllocatorDefault, uintptr(p),
    76  		uintptr(len(s)), uintptr(kCFStringEncodingUTF8), 0 /* isExternalRepresentation */, 0)
    77  	runtime.KeepAlive(p)
    78  	return CFString(ret)
    79  }
    80  func x509_CFStringCreateWithBytes_trampoline()
    81  
    82  //go:cgo_import_dynamic x509_CFDictionaryGetValueIfPresent CFDictionaryGetValueIfPresent "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    83  
    84  func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
    85  	ret := syscall(abi.FuncPCABI0(x509_CFDictionaryGetValueIfPresent_trampoline), uintptr(dict), uintptr(key),
    86  		uintptr(unsafe.Pointer(&value)), 0, 0, 0)
    87  	if ret == 0 {
    88  		return 0, false
    89  	}
    90  	return value, true
    91  }
    92  func x509_CFDictionaryGetValueIfPresent_trampoline()
    93  
    94  const kCFNumberSInt32Type = 3
    95  
    96  //go:cgo_import_dynamic x509_CFNumberGetValue CFNumberGetValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    97  
    98  func CFNumberGetValue(num CFRef) (int32, error) {
    99  	var value int32
   100  	ret := syscall(abi.FuncPCABI0(x509_CFNumberGetValue_trampoline), uintptr(num), uintptr(kCFNumberSInt32Type),
   101  		uintptr(unsafe.Pointer(&value)), 0, 0, 0)
   102  	if ret == 0 {
   103  		return 0, errors.New("CFNumberGetValue call failed")
   104  	}
   105  	return value, nil
   106  }
   107  func x509_CFNumberGetValue_trampoline()
   108  
   109  //go:cgo_import_dynamic x509_CFDataGetLength CFDataGetLength "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   110  
   111  func CFDataGetLength(data CFRef) int {
   112  	ret := syscall(abi.FuncPCABI0(x509_CFDataGetLength_trampoline), uintptr(data), 0, 0, 0, 0, 0)
   113  	return int(ret)
   114  }
   115  func x509_CFDataGetLength_trampoline()
   116  
   117  //go:cgo_import_dynamic x509_CFDataGetBytePtr CFDataGetBytePtr "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   118  
   119  func CFDataGetBytePtr(data CFRef) uintptr {
   120  	ret := syscall(abi.FuncPCABI0(x509_CFDataGetBytePtr_trampoline), uintptr(data), 0, 0, 0, 0, 0)
   121  	return ret
   122  }
   123  func x509_CFDataGetBytePtr_trampoline()
   124  
   125  //go:cgo_import_dynamic x509_CFArrayGetCount CFArrayGetCount "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   126  
   127  func CFArrayGetCount(array CFRef) int {
   128  	ret := syscall(abi.FuncPCABI0(x509_CFArrayGetCount_trampoline), uintptr(array), 0, 0, 0, 0, 0)
   129  	return int(ret)
   130  }
   131  func x509_CFArrayGetCount_trampoline()
   132  
   133  //go:cgo_import_dynamic x509_CFArrayGetValueAtIndex CFArrayGetValueAtIndex "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   134  
   135  func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
   136  	ret := syscall(abi.FuncPCABI0(x509_CFArrayGetValueAtIndex_trampoline), uintptr(array), uintptr(index), 0, 0, 0, 0)
   137  	return CFRef(ret)
   138  }
   139  func x509_CFArrayGetValueAtIndex_trampoline()
   140  
   141  //go:cgo_import_dynamic x509_CFEqual CFEqual "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   142  
   143  func CFEqual(a, b CFRef) bool {
   144  	ret := syscall(abi.FuncPCABI0(x509_CFEqual_trampoline), uintptr(a), uintptr(b), 0, 0, 0, 0)
   145  	return ret == 1
   146  }
   147  func x509_CFEqual_trampoline()
   148  
   149  //go:cgo_import_dynamic x509_CFRelease CFRelease "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   150  
   151  func CFRelease(ref CFRef) {
   152  	syscall(abi.FuncPCABI0(x509_CFRelease_trampoline), uintptr(ref), 0, 0, 0, 0, 0)
   153  }
   154  func x509_CFRelease_trampoline()
   155  
   156  //go:cgo_import_dynamic x509_CFArrayCreateMutable CFArrayCreateMutable "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   157  
   158  func CFArrayCreateMutable() CFRef {
   159  	ret := syscall(abi.FuncPCABI0(x509_CFArrayCreateMutable_trampoline), kCFAllocatorDefault, 0, 0 /* kCFTypeArrayCallBacks */, 0, 0, 0)
   160  	return CFRef(ret)
   161  }
   162  func x509_CFArrayCreateMutable_trampoline()
   163  
   164  //go:cgo_import_dynamic x509_CFArrayAppendValue CFArrayAppendValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   165  
   166  func CFArrayAppendValue(array CFRef, val CFRef) {
   167  	syscall(abi.FuncPCABI0(x509_CFArrayAppendValue_trampoline), uintptr(array), uintptr(val), 0, 0, 0, 0)
   168  }
   169  func x509_CFArrayAppendValue_trampoline()
   170  
   171  //go:cgo_import_dynamic x509_CFDateCreate CFDateCreate "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   172  
   173  func CFDateCreate(seconds int) CFRef {
   174  	ret := syscall(abi.FuncPCABI0(x509_CFDateCreate_trampoline), kCFAllocatorDefault, uintptr(seconds), 0, 0, 0, 0)
   175  	return CFRef(ret)
   176  }
   177  func x509_CFDateCreate_trampoline()
   178  
   179  //go:cgo_import_dynamic x509_CFErrorCopyDescription CFErrorCopyDescription "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   180  
   181  func CFErrorCopyDescription(errRef CFRef) CFRef {
   182  	ret := syscall(abi.FuncPCABI0(x509_CFErrorCopyDescription_trampoline), uintptr(errRef), 0, 0, 0, 0, 0)
   183  	return CFRef(ret)
   184  }
   185  func x509_CFErrorCopyDescription_trampoline()
   186  
   187  //go:cgo_import_dynamic x509_CFStringCreateExternalRepresentation CFStringCreateExternalRepresentation "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   188  
   189  func CFStringCreateExternalRepresentation(strRef CFRef) CFRef {
   190  	ret := syscall(abi.FuncPCABI0(x509_CFStringCreateExternalRepresentation_trampoline), kCFAllocatorDefault, uintptr(strRef), kCFStringEncodingUTF8, 0, 0, 0)
   191  	return CFRef(ret)
   192  }
   193  func x509_CFStringCreateExternalRepresentation_trampoline()
   194  
   195  // syscall is implemented in the runtime package (runtime/sys_darwin.go)
   196  func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
   197  
   198  // ReleaseCFArray iterates through an array, releasing its contents, and then
   199  // releases the array itself. This is necessary because we cannot, easily, set the
   200  // CFArrayCallBacks argument when creating CFArrays.
   201  func ReleaseCFArray(array CFRef) {
   202  	for i := 0; i < CFArrayGetCount(array); i++ {
   203  		ref := CFArrayGetValueAtIndex(array, i)
   204  		CFRelease(ref)
   205  	}
   206  	CFRelease(array)
   207  }