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

View as plain text