summaryrefslogtreecommitdiffstats
path: root/src/crypto/x509/internal
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/x509/internal')
-rw-r--r--src/crypto/x509/internal/macos/corefoundation.go131
-rw-r--r--src/crypto/x509/internal/macos/corefoundation.s30
-rw-r--r--src/crypto/x509/internal/macos/security.go118
-rw-r--r--src/crypto/x509/internal/macos/security.s20
4 files changed, 299 insertions, 0 deletions
diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go
new file mode 100644
index 0000000..fcfbc1e
--- /dev/null
+++ b/src/crypto/x509/internal/macos/corefoundation.go
@@ -0,0 +1,131 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build darwin && !ios
+// +build darwin,!ios
+
+// Package macOS provides cgo-less wrappers for Core Foundation and
+// Security.framework, similarly to how package syscall provides access to
+// libSystem.dylib.
+package macOS
+
+import (
+ "errors"
+ "internal/abi"
+ "reflect"
+ "runtime"
+ "unsafe"
+)
+
+// Core Foundation linker flags for the external linker. See Issue 42459.
+//go:cgo_ldflag "-framework"
+//go:cgo_ldflag "CoreFoundation"
+
+// CFRef is an opaque reference to a Core Foundation object. It is a pointer,
+// but to memory not owned by Go, so not an unsafe.Pointer.
+type CFRef uintptr
+
+// CFDataToSlice returns a copy of the contents of data as a bytes slice.
+func CFDataToSlice(data CFRef) []byte {
+ length := CFDataGetLength(data)
+ ptr := CFDataGetBytePtr(data)
+ src := (*[1 << 20]byte)(unsafe.Pointer(ptr))[:length:length]
+ out := make([]byte, length)
+ copy(out, src)
+ return out
+}
+
+type CFString CFRef
+
+const kCFAllocatorDefault = 0
+const kCFStringEncodingUTF8 = 0x08000100
+
+//go:cgo_import_dynamic x509_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+// StringToCFString returns a copy of the UTF-8 contents of s as a new CFString.
+func StringToCFString(s string) CFString {
+ p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
+ ret := syscall(abi.FuncPCABI0(x509_CFStringCreateWithBytes_trampoline), kCFAllocatorDefault, uintptr(p),
+ uintptr(len(s)), uintptr(kCFStringEncodingUTF8), 0 /* isExternalRepresentation */, 0)
+ runtime.KeepAlive(p)
+ return CFString(ret)
+}
+func x509_CFStringCreateWithBytes_trampoline()
+
+//go:cgo_import_dynamic x509_CFDictionaryGetValueIfPresent CFDictionaryGetValueIfPresent "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
+ ret := syscall(abi.FuncPCABI0(x509_CFDictionaryGetValueIfPresent_trampoline), uintptr(dict), uintptr(key),
+ uintptr(unsafe.Pointer(&value)), 0, 0, 0)
+ if ret == 0 {
+ return 0, false
+ }
+ return value, true
+}
+func x509_CFDictionaryGetValueIfPresent_trampoline()
+
+const kCFNumberSInt32Type = 3
+
+//go:cgo_import_dynamic x509_CFNumberGetValue CFNumberGetValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFNumberGetValue(num CFRef) (int32, error) {
+ var value int32
+ ret := syscall(abi.FuncPCABI0(x509_CFNumberGetValue_trampoline), uintptr(num), uintptr(kCFNumberSInt32Type),
+ uintptr(unsafe.Pointer(&value)), 0, 0, 0)
+ if ret == 0 {
+ return 0, errors.New("CFNumberGetValue call failed")
+ }
+ return value, nil
+}
+func x509_CFNumberGetValue_trampoline()
+
+//go:cgo_import_dynamic x509_CFDataGetLength CFDataGetLength "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFDataGetLength(data CFRef) int {
+ ret := syscall(abi.FuncPCABI0(x509_CFDataGetLength_trampoline), uintptr(data), 0, 0, 0, 0, 0)
+ return int(ret)
+}
+func x509_CFDataGetLength_trampoline()
+
+//go:cgo_import_dynamic x509_CFDataGetBytePtr CFDataGetBytePtr "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFDataGetBytePtr(data CFRef) uintptr {
+ ret := syscall(abi.FuncPCABI0(x509_CFDataGetBytePtr_trampoline), uintptr(data), 0, 0, 0, 0, 0)
+ return ret
+}
+func x509_CFDataGetBytePtr_trampoline()
+
+//go:cgo_import_dynamic x509_CFArrayGetCount CFArrayGetCount "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFArrayGetCount(array CFRef) int {
+ ret := syscall(abi.FuncPCABI0(x509_CFArrayGetCount_trampoline), uintptr(array), 0, 0, 0, 0, 0)
+ return int(ret)
+}
+func x509_CFArrayGetCount_trampoline()
+
+//go:cgo_import_dynamic x509_CFArrayGetValueAtIndex CFArrayGetValueAtIndex "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
+ ret := syscall(abi.FuncPCABI0(x509_CFArrayGetValueAtIndex_trampoline), uintptr(array), uintptr(index), 0, 0, 0, 0)
+ return CFRef(ret)
+}
+func x509_CFArrayGetValueAtIndex_trampoline()
+
+//go:cgo_import_dynamic x509_CFEqual CFEqual "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFEqual(a, b CFRef) bool {
+ ret := syscall(abi.FuncPCABI0(x509_CFEqual_trampoline), uintptr(a), uintptr(b), 0, 0, 0, 0)
+ return ret == 1
+}
+func x509_CFEqual_trampoline()
+
+//go:cgo_import_dynamic x509_CFRelease CFRelease "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFRelease(ref CFRef) {
+ syscall(abi.FuncPCABI0(x509_CFRelease_trampoline), uintptr(ref), 0, 0, 0, 0, 0)
+}
+func x509_CFRelease_trampoline()
+
+// syscall is implemented in the runtime package (runtime/sys_darwin.go)
+func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
diff --git a/src/crypto/x509/internal/macos/corefoundation.s b/src/crypto/x509/internal/macos/corefoundation.s
new file mode 100644
index 0000000..cda2336
--- /dev/null
+++ b/src/crypto/x509/internal/macos/corefoundation.s
@@ -0,0 +1,30 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build darwin && !ios
+// +build darwin,!ios
+
+#include "textflag.h"
+
+// The trampolines are ABIInternal as they are address-taken in
+// Go code.
+
+TEXT ·x509_CFArrayGetCount_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFArrayGetCount(SB)
+TEXT ·x509_CFArrayGetValueAtIndex_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFArrayGetValueAtIndex(SB)
+TEXT ·x509_CFDataGetBytePtr_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFDataGetBytePtr(SB)
+TEXT ·x509_CFDataGetLength_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFDataGetLength(SB)
+TEXT ·x509_CFStringCreateWithBytes_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFStringCreateWithBytes(SB)
+TEXT ·x509_CFRelease_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFRelease(SB)
+TEXT ·x509_CFDictionaryGetValueIfPresent_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFDictionaryGetValueIfPresent(SB)
+TEXT ·x509_CFNumberGetValue_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFNumberGetValue(SB)
+TEXT ·x509_CFEqual_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFEqual(SB)
diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go
new file mode 100644
index 0000000..0f6fa42
--- /dev/null
+++ b/src/crypto/x509/internal/macos/security.go
@@ -0,0 +1,118 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build darwin && !ios
+// +build darwin,!ios
+
+package macOS
+
+import (
+ "errors"
+ "internal/abi"
+ "strconv"
+ "unsafe"
+)
+
+// Security.framework linker flags for the external linker. See Issue 42459.
+//go:cgo_ldflag "-framework"
+//go:cgo_ldflag "Security"
+
+// Based on https://opensource.apple.com/source/Security/Security-59306.41.2/base/Security.h
+
+type SecTrustSettingsResult int32
+
+const (
+ SecTrustSettingsResultInvalid SecTrustSettingsResult = iota
+ SecTrustSettingsResultTrustRoot
+ SecTrustSettingsResultTrustAsRoot
+ SecTrustSettingsResultDeny
+ SecTrustSettingsResultUnspecified
+)
+
+type SecTrustSettingsDomain int32
+
+const (
+ SecTrustSettingsDomainUser SecTrustSettingsDomain = iota
+ SecTrustSettingsDomainAdmin
+ SecTrustSettingsDomainSystem
+)
+
+type OSStatus struct {
+ call string
+ status int32
+}
+
+func (s OSStatus) Error() string {
+ return s.call + " error: " + strconv.Itoa(int(s.status))
+}
+
+// Dictionary keys are defined as build-time strings with CFSTR, but the Go
+// linker's internal linking mode can't handle CFSTR relocations. Create our
+// own dynamic strings instead and just never release them.
+//
+// Note that this might be the only thing that can break over time if
+// these values change, as the ABI arguably requires using the strings
+// pointed to by the symbols, not values that happen to be equal to them.
+
+var SecTrustSettingsResultKey = StringToCFString("kSecTrustSettingsResult")
+var SecTrustSettingsPolicy = StringToCFString("kSecTrustSettingsPolicy")
+var SecTrustSettingsPolicyString = StringToCFString("kSecTrustSettingsPolicyString")
+var SecPolicyOid = StringToCFString("SecPolicyOid")
+var SecPolicyAppleSSL = StringToCFString("1.2.840.113635.100.1.3") // defined by POLICYMACRO
+
+var ErrNoTrustSettings = errors.New("no trust settings found")
+
+const errSecNoTrustSettings = -25263
+
+//go:cgo_import_dynamic x509_SecTrustSettingsCopyCertificates SecTrustSettingsCopyCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security"
+
+func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) {
+ ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyCertificates_trampoline), uintptr(domain),
+ uintptr(unsafe.Pointer(&certArray)), 0, 0, 0, 0)
+ if int32(ret) == errSecNoTrustSettings {
+ return 0, ErrNoTrustSettings
+ } else if ret != 0 {
+ return 0, OSStatus{"SecTrustSettingsCopyCertificates", int32(ret)}
+ }
+ return certArray, nil
+}
+func x509_SecTrustSettingsCopyCertificates_trampoline()
+
+const kSecFormatX509Cert int32 = 9
+
+//go:cgo_import_dynamic x509_SecItemExport SecItemExport "/System/Library/Frameworks/Security.framework/Versions/A/Security"
+
+func SecItemExport(cert CFRef) (data CFRef, err error) {
+ ret := syscall(abi.FuncPCABI0(x509_SecItemExport_trampoline), uintptr(cert), uintptr(kSecFormatX509Cert),
+ 0 /* flags */, 0 /* keyParams */, uintptr(unsafe.Pointer(&data)), 0)
+ if ret != 0 {
+ return 0, OSStatus{"SecItemExport", int32(ret)}
+ }
+ return data, nil
+}
+func x509_SecItemExport_trampoline()
+
+const errSecItemNotFound = -25300
+
+//go:cgo_import_dynamic x509_SecTrustSettingsCopyTrustSettings SecTrustSettingsCopyTrustSettings "/System/Library/Frameworks/Security.framework/Versions/A/Security"
+
+func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) {
+ ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyTrustSettings_trampoline), uintptr(cert), uintptr(domain),
+ uintptr(unsafe.Pointer(&trustSettings)), 0, 0, 0)
+ if int32(ret) == errSecItemNotFound {
+ return 0, ErrNoTrustSettings
+ } else if ret != 0 {
+ return 0, OSStatus{"SecTrustSettingsCopyTrustSettings", int32(ret)}
+ }
+ return trustSettings, nil
+}
+func x509_SecTrustSettingsCopyTrustSettings_trampoline()
+
+//go:cgo_import_dynamic x509_SecPolicyCopyProperties SecPolicyCopyProperties "/System/Library/Frameworks/Security.framework/Versions/A/Security"
+
+func SecPolicyCopyProperties(policy CFRef) CFRef {
+ ret := syscall(abi.FuncPCABI0(x509_SecPolicyCopyProperties_trampoline), uintptr(policy), 0, 0, 0, 0, 0)
+ return CFRef(ret)
+}
+func x509_SecPolicyCopyProperties_trampoline()
diff --git a/src/crypto/x509/internal/macos/security.s b/src/crypto/x509/internal/macos/security.s
new file mode 100644
index 0000000..0038f25
--- /dev/null
+++ b/src/crypto/x509/internal/macos/security.s
@@ -0,0 +1,20 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build darwin && !ios
+// +build darwin,!ios
+
+#include "textflag.h"
+
+// The trampolines are ABIInternal as they are address-taken in
+// Go code.
+
+TEXT ·x509_SecTrustSettingsCopyCertificates_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_SecTrustSettingsCopyCertificates(SB)
+TEXT ·x509_SecItemExport_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_SecItemExport(SB)
+TEXT ·x509_SecTrustSettingsCopyTrustSettings_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_SecTrustSettingsCopyTrustSettings(SB)
+TEXT ·x509_SecPolicyCopyProperties_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_SecPolicyCopyProperties(SB)