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 }