github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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 "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 }