aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-01-22 18:24:33 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-01-24 00:12:24 +0100
commitfc41f439f573fce3efdd37017f072f86cb7828ff (patch)
tree1889c42f4a4dc5190c88c87ec2a05d172a396459
parentembeddable-dll-service: add more robust example for .NET 5 (diff)
downloadwireguard-windows-fc41f439f573fce3efdd37017f072f86cb7828ff.tar.xz
wireguard-windows-fc41f439f573fce3efdd37017f072f86cb7828ff.zip
global: move certain win32 APIs to x/sys/windows
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--conf/dpapi/dpapi_windows.go59
-rw-r--r--conf/dpapi/mksyscall.go8
-rwxr-xr-xconf/dpapi/test.exebin0 -> 3622400 bytes
-rw-r--r--conf/dpapi/zdpapi_windows.go61
-rw-r--r--conf/storewatcher_windows.go24
-rw-r--r--conf/zsyscall_windows.go28
-rw-r--r--elevate/membership.go4
-rw-r--r--elevate/syscall_windows.go3
-rw-r--r--elevate/zsyscall_windows.go34
-rw-r--r--version/certificate_test.go (renamed from version/wintrust/certificate_test.go)6
-rw-r--r--version/certificate_windows.go115
-rw-r--r--version/official_windows.go29
-rw-r--r--version/wintrust/certificate_windows.go180
-rw-r--r--version/wintrust/mksyscall.go8
-rw-r--r--version/wintrust/wintrust_windows.go116
-rw-r--r--version/wintrust/zsyscall_windows.go85
16 files changed, 168 insertions, 592 deletions
diff --git a/conf/dpapi/dpapi_windows.go b/conf/dpapi/dpapi_windows.go
index 778605e9..45ad950e 100644
--- a/conf/dpapi/dpapi_windows.go
+++ b/conf/dpapi/dpapi_windows.go
@@ -9,78 +9,59 @@ import (
"errors"
"runtime"
"unsafe"
+ "fmt"
"golang.org/x/sys/windows"
)
-const (
- dpCRYPTPROTECT_UI_FORBIDDEN uint32 = 0x1
- dpCRYPTPROTECT_LOCAL_MACHINE uint32 = 0x4
- dpCRYPTPROTECT_CRED_SYNC uint32 = 0x8
- dpCRYPTPROTECT_AUDIT uint32 = 0x10
- dpCRYPTPROTECT_NO_RECOVERY uint32 = 0x20
- dpCRYPTPROTECT_VERIFY_PROTECTION uint32 = 0x40
- dpCRYPTPROTECT_CRED_REGENERATE uint32 = 0x80
-)
-
-type dpBlob struct {
- len uint32
- data uintptr
+func bytesToBlob(bytes []byte) *windows.DataBlob {
+ blob := &windows.DataBlob{Size: uint32(len(bytes))}
+ if len(bytes) > 0 {
+ blob.Data = &bytes[0]
+ }
+ return blob
}
-func bytesToBlob(bytes []byte) *dpBlob {
- blob := &dpBlob{}
- blob.len = uint32(len(bytes))
- if len(bytes) > 0 {
- blob.data = uintptr(unsafe.Pointer(&bytes[0]))
- }
- return blob
-}
-
-//sys cryptProtectData(dataIn *dpBlob, name *uint16, optionalEntropy *dpBlob, reserved uintptr, promptStruct uintptr, flags uint32, dataOut *dpBlob) (err error) = crypt32.CryptProtectData
-
func Encrypt(data []byte, name string) ([]byte, error) {
- out := dpBlob{}
- err := cryptProtectData(bytesToBlob(data), windows.StringToUTF16Ptr(name), nil, 0, 0, dpCRYPTPROTECT_UI_FORBIDDEN, &out)
+ out := windows.DataBlob{}
+ err := windows.CryptProtectData(bytesToBlob(data), windows.StringToUTF16Ptr(name), nil, 0, nil, windows.CRYPTPROTECT_UI_FORBIDDEN, &out)
if err != nil {
- return nil, errors.New("Unable to encrypt DPAPI protected data: " + err.Error())
+ return nil, fmt.Errorf("unable to encrypt DPAPI protected data: %w", err)
}
outSlice := *(*[]byte)(unsafe.Pointer(&(struct {
- addr uintptr
+ addr *byte
len int
cap int
- }{out.data, int(out.len), int(out.len)})))
+ }{out.Data, int(out.Size), int(out.Size)})))
ret := make([]byte, len(outSlice))
copy(ret, outSlice)
- windows.LocalFree(windows.Handle(out.data))
+ windows.LocalFree(windows.Handle(unsafe.Pointer(out.Data)))
return ret, nil
}
-//sys cryptUnprotectData(dataIn *dpBlob, name **uint16, optionalEntropy *dpBlob, reserved uintptr, promptStruct uintptr, flags uint32, dataOut *dpBlob) (err error) = crypt32.CryptUnprotectData
-
func Decrypt(data []byte, name string) ([]byte, error) {
- out := dpBlob{}
+ out := windows.DataBlob{}
var outName *uint16
utf16Name, err := windows.UTF16PtrFromString(name)
if err != nil {
return nil, err
}
- err = cryptUnprotectData(bytesToBlob(data), &outName, nil, 0, 0, dpCRYPTPROTECT_UI_FORBIDDEN, &out)
+ err = windows.CryptUnprotectData(bytesToBlob(data), &outName, nil, 0, nil, windows.CRYPTPROTECT_UI_FORBIDDEN, &out)
if err != nil {
- return nil, errors.New("Unable to decrypt DPAPI protected data: " + err.Error())
+ return nil, fmt.Errorf("unable to decrypt DPAPI protected data: %w", err)
}
outSlice := *(*[]byte)(unsafe.Pointer(&(struct {
- addr uintptr
+ addr *byte
len int
cap int
- }{out.data, int(out.len), int(out.len)})))
+ }{out.Data, int(out.Size), int(out.Size)})))
ret := make([]byte, len(outSlice))
copy(ret, outSlice)
- windows.LocalFree(windows.Handle(out.data))
+ windows.LocalFree(windows.Handle(unsafe.Pointer(out.Data)))
// Note: this ridiculous open-coded strcmp is not constant time.
different := false
@@ -101,7 +82,7 @@ func Decrypt(data []byte, name string) ([]byte, error) {
windows.LocalFree(windows.Handle(unsafe.Pointer(outName)))
if different {
- return nil, errors.New("The input name does not match the stored name")
+ return nil, errors.New("input name does not match the stored name")
}
return ret, nil
diff --git a/conf/dpapi/mksyscall.go b/conf/dpapi/mksyscall.go
deleted file mode 100644
index 7c27e2d9..00000000
--- a/conf/dpapi/mksyscall.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
- */
-
-package dpapi
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zdpapi_windows.go dpapi_windows.go
diff --git a/conf/dpapi/test.exe b/conf/dpapi/test.exe
new file mode 100755
index 00000000..9e5f23a7
--- /dev/null
+++ b/conf/dpapi/test.exe
Binary files differ
diff --git a/conf/dpapi/zdpapi_windows.go b/conf/dpapi/zdpapi_windows.go
deleted file mode 100644
index 43738a52..00000000
--- a/conf/dpapi/zdpapi_windows.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package dpapi
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
- errnoERROR_IO_PENDING = 997
-)
-
-var (
- errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
- errERROR_EINVAL error = syscall.EINVAL
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
- switch e {
- case 0:
- return errERROR_EINVAL
- case errnoERROR_IO_PENDING:
- return errERROR_IO_PENDING
- }
- // TODO: add more here, after collecting data on the common
- // error values see on Windows. (perhaps when running
- // all.bat?)
- return e
-}
-
-var (
- modcrypt32 = windows.NewLazySystemDLL("crypt32.dll")
-
- procCryptProtectData = modcrypt32.NewProc("CryptProtectData")
- procCryptUnprotectData = modcrypt32.NewProc("CryptUnprotectData")
-)
-
-func cryptProtectData(dataIn *dpBlob, name *uint16, optionalEntropy *dpBlob, reserved uintptr, promptStruct uintptr, flags uint32, dataOut *dpBlob) (err error) {
- r1, _, e1 := syscall.Syscall9(procCryptProtectData.Addr(), 7, uintptr(unsafe.Pointer(dataIn)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(optionalEntropy)), uintptr(reserved), uintptr(promptStruct), uintptr(flags), uintptr(unsafe.Pointer(dataOut)), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func cryptUnprotectData(dataIn *dpBlob, name **uint16, optionalEntropy *dpBlob, reserved uintptr, promptStruct uintptr, flags uint32, dataOut *dpBlob) (err error) {
- r1, _, e1 := syscall.Syscall9(procCryptUnprotectData.Addr(), 7, uintptr(unsafe.Pointer(dataIn)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(optionalEntropy)), uintptr(reserved), uintptr(promptStruct), uintptr(flags), uintptr(unsafe.Pointer(dataOut)), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
diff --git a/conf/storewatcher_windows.go b/conf/storewatcher_windows.go
index c5754558..44b4564e 100644
--- a/conf/storewatcher_windows.go
+++ b/conf/storewatcher_windows.go
@@ -11,20 +11,6 @@ import (
"golang.org/x/sys/windows"
)
-const (
- fncFILE_NAME uint32 = 0x00000001
- fncDIR_NAME uint32 = 0x00000002
- fncATTRIBUTES uint32 = 0x00000004
- fncSIZE uint32 = 0x00000008
- fncLAST_WRITE uint32 = 0x00000010
- fncLAST_ACCESS uint32 = 0x00000020
- fncCREATION uint32 = 0x00000040
- fncSECURITY uint32 = 0x00000100
-)
-
-//sys findFirstChangeNotification(path *uint16, watchSubtree bool, filter uint32) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = kernel32.FindFirstChangeNotificationW
-//sys findNextChangeNotification(handle windows.Handle) (err error) = kernel32.FindNextChangeNotification
-
var haveStartedWatchingConfigDir bool
func startWatchingConfigDir() {
@@ -36,7 +22,7 @@ func startWatchingConfigDir() {
h := windows.InvalidHandle
defer func() {
if h != windows.InvalidHandle {
- windows.CloseHandle(h)
+ windows.FindCloseChangeNotification(h)
}
haveStartedWatchingConfigDir = false
}()
@@ -45,7 +31,7 @@ func startWatchingConfigDir() {
if err != nil {
return
}
- h, err = findFirstChangeNotification(windows.StringToUTF16Ptr(configFileDir), true, fncFILE_NAME|fncDIR_NAME|fncATTRIBUTES|fncSIZE|fncLAST_WRITE|fncLAST_ACCESS|fncCREATION|fncSECURITY)
+ h, err = windows.FindFirstChangeNotification(configFileDir, true, windows.FILE_NOTIFY_CHANGE_FILE_NAME|windows.FILE_NOTIFY_CHANGE_DIR_NAME|windows.FILE_NOTIFY_CHANGE_ATTRIBUTES|windows.FILE_NOTIFY_CHANGE_SIZE|windows.FILE_NOTIFY_CHANGE_LAST_WRITE|windows.FILE_NOTIFY_CHANGE_LAST_ACCESS|windows.FILE_NOTIFY_CHANGE_CREATION|windows.FILE_NOTIFY_CHANGE_SECURITY)
if err != nil {
log.Printf("Unable to monitor config directory: %v", err)
return
@@ -54,7 +40,7 @@ func startWatchingConfigDir() {
s, err := windows.WaitForSingleObject(h, windows.INFINITE)
if err != nil || s == windows.WAIT_FAILED {
log.Printf("Unable to wait on config directory watcher: %v", err)
- windows.CloseHandle(h)
+ windows.FindCloseChangeNotification(h)
h = windows.InvalidHandle
goto startover
}
@@ -63,10 +49,10 @@ func startWatchingConfigDir() {
cb.cb()
}
- err = findNextChangeNotification(h)
+ err = windows.FindNextChangeNotification(h)
if err != nil {
log.Printf("Unable to monitor config directory again: %v", err)
- windows.CloseHandle(h)
+ windows.FindCloseChangeNotification(h)
h = windows.InvalidHandle
goto startover
}
diff --git a/conf/zsyscall_windows.go b/conf/zsyscall_windows.go
index c012abaa..783411f6 100644
--- a/conf/zsyscall_windows.go
+++ b/conf/zsyscall_windows.go
@@ -38,35 +38,11 @@ func errnoErr(e syscall.Errno) error {
}
var (
- modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
- modwininet = windows.NewLazySystemDLL("wininet.dll")
+ modwininet = windows.NewLazySystemDLL("wininet.dll")
- procFindFirstChangeNotificationW = modkernel32.NewProc("FindFirstChangeNotificationW")
- procFindNextChangeNotification = modkernel32.NewProc("FindNextChangeNotification")
- procInternetGetConnectedState = modwininet.NewProc("InternetGetConnectedState")
+ procInternetGetConnectedState = modwininet.NewProc("InternetGetConnectedState")
)
-func findFirstChangeNotification(path *uint16, watchSubtree bool, filter uint32) (handle windows.Handle, err error) {
- var _p0 uint32
- if watchSubtree {
- _p0 = 1
- }
- r0, _, e1 := syscall.Syscall(procFindFirstChangeNotificationW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(_p0), uintptr(filter))
- handle = windows.Handle(r0)
- if handle == windows.InvalidHandle {
- err = errnoErr(e1)
- }
- return
-}
-
-func findNextChangeNotification(handle windows.Handle) (err error) {
- r1, _, e1 := syscall.Syscall(procFindNextChangeNotification.Addr(), 1, uintptr(handle), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
func internetGetConnectedState(flags *uint32, reserved uint32) (connected bool) {
r0, _, _ := syscall.Syscall(procInternetGetConnectedState.Addr(), 2, uintptr(unsafe.Pointer(flags)), uintptr(reserved), 0)
connected = r0 != 0
diff --git a/elevate/membership.go b/elevate/membership.go
index d0fe6bfe..769652c1 100644
--- a/elevate/membership.go
+++ b/elevate/membership.go
@@ -37,12 +37,12 @@ func TokenIsElevatedOrElevatable(token windows.Token) bool {
}
func IsAdminDesktop() (bool, error) {
- hwnd := getShellWindow()
+ hwnd := windows.GetShellWindow()
if hwnd == 0 {
return false, windows.ERROR_INVALID_WINDOW_HANDLE
}
var pid uint32
- _, err := getWindowThreadProcessId(hwnd, &pid)
+ _, err := windows.GetWindowThreadProcessId(hwnd, &pid)
if err != nil {
return false, err
}
diff --git a/elevate/syscall_windows.go b/elevate/syscall_windows.go
index 4f114711..b854fe7e 100644
--- a/elevate/syscall_windows.go
+++ b/elevate/syscall_windows.go
@@ -84,6 +84,3 @@ const (
//sys coInitializeEx(reserved uintptr, coInit uint32) (ret error) = ole32.CoInitializeEx
//sys coUninitialize() = ole32.CoUninitialize
//sys coGetObject(name *uint16, bindOpts *cBIND_OPTS3, guid *windows.GUID, functionTable ***[0xffff]uintptr) (ret error) = ole32.CoGetObject
-
-//sys getWindowThreadProcessId(hwnd uintptr, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId
-//sys getShellWindow() (hwnd uintptr) = user32.GetShellWindow
diff --git a/elevate/zsyscall_windows.go b/elevate/zsyscall_windows.go
index bd22f6dc..c7f71819 100644
--- a/elevate/zsyscall_windows.go
+++ b/elevate/zsyscall_windows.go
@@ -38,17 +38,14 @@ func errnoErr(e syscall.Errno) error {
}
var (
- modntdll = windows.NewLazySystemDLL("ntdll.dll")
- modole32 = windows.NewLazySystemDLL("ole32.dll")
- moduser32 = windows.NewLazySystemDLL("user32.dll")
-
- procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb")
- procRtlInitUnicodeString = modntdll.NewProc("RtlInitUnicodeString")
- procCoGetObject = modole32.NewProc("CoGetObject")
- procCoInitializeEx = modole32.NewProc("CoInitializeEx")
- procCoUninitialize = modole32.NewProc("CoUninitialize")
- procGetShellWindow = moduser32.NewProc("GetShellWindow")
- procGetWindowThreadProcessId = moduser32.NewProc("GetWindowThreadProcessId")
+ modntdll = windows.NewLazySystemDLL("ntdll.dll")
+ modole32 = windows.NewLazySystemDLL("ole32.dll")
+
+ procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb")
+ procRtlInitUnicodeString = modntdll.NewProc("RtlInitUnicodeString")
+ procCoGetObject = modole32.NewProc("CoGetObject")
+ procCoInitializeEx = modole32.NewProc("CoInitializeEx")
+ procCoUninitialize = modole32.NewProc("CoUninitialize")
)
func rtlGetCurrentPeb() (peb *cPEB) {
@@ -82,18 +79,3 @@ func coUninitialize() {
syscall.Syscall(procCoUninitialize.Addr(), 0, 0, 0, 0)
return
}
-
-func getShellWindow() (hwnd uintptr) {
- r0, _, _ := syscall.Syscall(procGetShellWindow.Addr(), 0, 0, 0, 0)
- hwnd = uintptr(r0)
- return
-}
-
-func getWindowThreadProcessId(hwnd uintptr, pid *uint32) (tid uint32, err error) {
- r0, _, e1 := syscall.Syscall(procGetWindowThreadProcessId.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(pid)), 0)
- tid = uint32(r0)
- if tid == 0 {
- err = errnoErr(e1)
- }
- return
-}
diff --git a/version/wintrust/certificate_test.go b/version/certificate_test.go
index 86d90526..35c4ddb6 100644
--- a/version/wintrust/certificate_test.go
+++ b/version/certificate_test.go
@@ -3,7 +3,7 @@
* Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
*/
-package wintrust
+package version
import (
"fmt"
@@ -18,7 +18,7 @@ func TestExtractCertificateNames(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- names, err := ExtractCertificateNames(filepath.Join(system32, "ntoskrnl.exe"))
+ names, err := extractCertificateNames(filepath.Join(system32, "ntoskrnl.exe"))
if err != nil {
t.Fatal(err)
}
@@ -32,7 +32,7 @@ func TestExtractCertificateExtension(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- policies, err := ExtractCertificatePolicies(filepath.Join(system32, "ntoskrnl.exe"), "2.5.29.32")
+ policies, err := extractCertificatePolicies(filepath.Join(system32, "ntoskrnl.exe"), "2.5.29.32")
if err != nil {
t.Fatal(err)
}
diff --git a/version/certificate_windows.go b/version/certificate_windows.go
new file mode 100644
index 00000000..b5ae3764
--- /dev/null
+++ b/version/certificate_windows.go
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
+ */
+
+package version
+
+import (
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+func extractCertificateNames(path string) ([]string, error) {
+ path16, err := windows.UTF16PtrFromString(path)
+ if err != nil {
+ return nil, err
+ }
+ var certStore windows.Handle
+ err = windows.CryptQueryObject(windows.CERT_QUERY_OBJECT_FILE, unsafe.Pointer(path16), windows.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, windows.CERT_QUERY_FORMAT_FLAG_ALL, 0, nil, nil, nil, &certStore, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer windows.CertCloseStore(certStore, 0)
+ var cert *windows.CertContext
+ var names []string
+ for {
+ cert, err = windows.CertEnumCertificatesInStore(certStore, cert)
+ if err != nil {
+ if errno, ok := err.(syscall.Errno); ok {
+ if errno == syscall.Errno(windows.CRYPT_E_NOT_FOUND) {
+ break
+ }
+ }
+ return nil, err
+ }
+ if cert == nil {
+ break
+ }
+ nameLen := windows.CertGetNameString(cert, windows.CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, nil, 0)
+ if nameLen == 0 {
+ continue
+ }
+ name16 := make([]uint16, nameLen)
+ if windows.CertGetNameString(cert, windows.CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, &name16[0], nameLen) != nameLen {
+ continue
+ }
+ if name16[0] == 0 {
+ continue
+ }
+ names = append(names, windows.UTF16ToString(name16))
+ }
+ if names == nil {
+ return nil, syscall.Errno(windows.CRYPT_E_NOT_FOUND)
+ }
+ return names, nil
+}
+
+func extractCertificatePolicies(path string, oid string) ([]string, error) {
+ path16, err := windows.UTF16PtrFromString(path)
+ if err != nil {
+ return nil, err
+ }
+ oid8, err := windows.BytePtrFromString(oid)
+ if err != nil {
+ return nil, err
+ }
+ var certStore windows.Handle
+ err = windows.CryptQueryObject(windows.CERT_QUERY_OBJECT_FILE, unsafe.Pointer(path16), windows.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, windows.CERT_QUERY_FORMAT_FLAG_ALL, 0, nil, nil, nil, &certStore, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer windows.CertCloseStore(certStore, 0)
+ var cert *windows.CertContext
+ var policies []string
+ for {
+ cert, err = windows.CertEnumCertificatesInStore(certStore, cert)
+ if err != nil {
+ if errno, ok := err.(syscall.Errno); ok {
+ if errno == syscall.Errno(windows.CRYPT_E_NOT_FOUND) {
+ break
+ }
+ }
+ return nil, err
+ }
+ if cert == nil {
+ break
+ }
+ ci := (*windows.CertInfo)(unsafe.Pointer(cert.CertInfo))
+ ext := windows.CertFindExtension(oid8, ci.CountExtensions, ci.Extensions)
+ if ext == nil {
+ continue
+ }
+ var decodedLen uint32
+ err = windows.CryptDecodeObject(windows.X509_ASN_ENCODING|windows.PKCS_7_ASN_ENCODING, ext.ObjId, ext.Value.Data, ext.Value.Size, 0, nil, &decodedLen)
+ if err != nil {
+ return nil, err
+ }
+ bytes := make([]byte, decodedLen)
+ certPoliciesInfo := (*windows.CertPoliciesInfo)(unsafe.Pointer(&bytes[0]))
+ err = windows.CryptDecodeObject(windows.X509_ASN_ENCODING|windows.PKCS_7_ASN_ENCODING, ext.ObjId, ext.Value.Data, ext.Value.Size, 0, unsafe.Pointer(&bytes[0]), &decodedLen)
+ if err != nil {
+ return nil, err
+ }
+ for i := uintptr(0); i < uintptr(certPoliciesInfo.Count); i++ {
+ cp := (*windows.CertPolicy)(unsafe.Pointer(uintptr(unsafe.Pointer(certPoliciesInfo.PolicyInfos)) + i*unsafe.Sizeof(*certPoliciesInfo.PolicyInfos)))
+ policies = append(policies, windows.BytePtrToString(cp.Identifier))
+ }
+ }
+ if policies == nil {
+ return nil, syscall.Errno(windows.CRYPT_E_NOT_FOUND)
+ }
+ return policies, nil
+}
diff --git a/version/official_windows.go b/version/official_windows.go
index 12b95e3b..1bfcf90b 100644
--- a/version/official_windows.go
+++ b/version/official_windows.go
@@ -10,8 +10,6 @@ import (
"unsafe"
"golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/windows/version/wintrust"
)
const (
@@ -25,19 +23,18 @@ func VerifyAuthenticode(path string) bool {
if err != nil {
return false
}
- file := &wintrust.WinTrustFileInfo{
- CbStruct: uint32(unsafe.Sizeof(wintrust.WinTrustFileInfo{})),
- FilePath: path16,
- }
- data := &wintrust.WinTrustData{
- CbStruct: uint32(unsafe.Sizeof(wintrust.WinTrustData{})),
- UIChoice: wintrust.WTD_UI_NONE,
- RevocationChecks: wintrust.WTD_REVOKE_WHOLECHAIN, // Full revocation checking, as this is called with network connectivity.
- UnionChoice: wintrust.WTD_CHOICE_FILE,
- StateAction: wintrust.WTD_STATEACTION_VERIFY,
- FileOrCatalogOrBlobOrSgnrOrCert: uintptr(unsafe.Pointer(file)),
+ data := &windows.WinTrustData{
+ Size: uint32(unsafe.Sizeof(windows.WinTrustData{})),
+ UIChoice: windows.WTD_UI_NONE,
+ RevocationChecks: windows.WTD_REVOKE_WHOLECHAIN, // Full revocation checking, as this is called with network connectivity.
+ UnionChoice: windows.WTD_CHOICE_FILE,
+ StateAction: windows.WTD_STATEACTION_VERIFY,
+ FileOrCatalogOrBlobOrSgnrOrCert: unsafe.Pointer(&windows.WinTrustFileInfo{
+ Size: uint32(unsafe.Sizeof(windows.WinTrustFileInfo{})),
+ FilePath: path16,
+ }),
}
- return wintrust.WinVerifyTrust(windows.InvalidHandle, &wintrust.WINTRUST_ACTION_GENERIC_VERIFY_V2, data) == nil
+ return windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data) == nil
}
// These are easily by-passable checks, which do not serve serve security purposes. Do not place security-sensitive
@@ -49,7 +46,7 @@ func IsRunningOfficialVersion() bool {
return false
}
- names, err := wintrust.ExtractCertificateNames(path)
+ names, err := extractCertificateNames(path)
if err != nil {
return false
}
@@ -67,7 +64,7 @@ func IsRunningEVSigned() bool {
return false
}
- policies, err := wintrust.ExtractCertificatePolicies(path, policyExtensionOid)
+ policies, err := extractCertificatePolicies(path, policyExtensionOid)
if err != nil {
return false
}
diff --git a/version/wintrust/certificate_windows.go b/version/wintrust/certificate_windows.go
deleted file mode 100644
index 0ce905e9..00000000
--- a/version/wintrust/certificate_windows.go
+++ /dev/null
@@ -1,180 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
- */
-
-package wintrust
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-const (
- _CERT_QUERY_OBJECT_FILE = 1
- _CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED = 1024
- _CERT_QUERY_FORMAT_FLAG_ALL = 14
- _CERT_NAME_SIMPLE_DISPLAY_TYPE = 4
-)
-
-type blob struct {
- len uint32
- data *byte
-}
-
-type bitBlob struct {
- len uint32
- data *byte
- unusedBits uint32
-}
-
-type algoIdentifier struct {
- objId uintptr
- params blob
-}
-
-type pubkeyInfo struct {
- algo algoIdentifier
- publicKey bitBlob
-}
-
-type certExtension struct {
- objId *byte
- critical uint32
- value blob
-}
-
-type certInfo struct {
- version uint32
- serialNumber blob /* CRYPT_INTEGER_BLOB */
- signatureAlgorithm algoIdentifier /* CRYPT_ALGORITHM_IDENTIFIER */
- issuer blob /* CERT_NAME_BLOB */
- notbefore windows.Filetime
- notafter windows.Filetime
- subject blob /* CERT_NAME_BLOB */
- subjectPublicKeyInfo pubkeyInfo /* CERT_PUBLIC_KEY_INFO */
- issuerUniqueId bitBlob /* CRYPT_BIT_BLOB */
- subjectUniqueId bitBlob /* CRYPT_BIT_BLOB */
- countExtensions uint32
- extensions *certExtension /* *CERT_EXTENSION */
-}
-
-type certPolicy struct {
- identifier *byte
- countQualifiers uint32
- qualifiers uintptr /* CERT_POLICY_QUALIFIER_INFO */
-}
-
-type certPoliciesInfo struct {
- countPolicyInfos uint32
- policyInfos *certPolicy
-}
-
-//sys cryptQueryObject(objectType uint32, object uintptr, expectedContentTypeFlags uint32, expectedFormatTypeFlags uint32, flags uint32, msgAndCertEncodingType *uint32, contentType *uint32, formatType *uint32, certStore *windows.Handle, msg *windows.Handle, context *uintptr) (err error) = crypt32.CryptQueryObject
-//sys certGetNameString(certContext *windows.CertContext, nameType uint32, flags uint32, typePara unsafe.Pointer, name *uint16, size uint32) (chars uint32) = crypt32.CertGetNameStringW
-//sys certFindExtension(objId *byte, countExtensions uint32, extensions *certExtension) (ret *certExtension) = crypt32.CertFindExtension
-//sys cryptDecodeObject(encodingType uint32, structType *byte, encodedBytes *byte, lenEncodedBytes uint32, flags uint32, decoded unsafe.Pointer, decodedLen *uint32) (err error) = crypt32.CryptDecodeObject
-
-func ExtractCertificateNames(path string) ([]string, error) {
- path16, err := windows.UTF16PtrFromString(path)
- if err != nil {
- return nil, err
- }
- var certStore windows.Handle
- err = cryptQueryObject(_CERT_QUERY_OBJECT_FILE, uintptr(unsafe.Pointer(path16)), _CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, _CERT_QUERY_FORMAT_FLAG_ALL, 0, nil, nil, nil, &certStore, nil, nil)
- if err != nil {
- return nil, err
- }
- defer windows.CertCloseStore(certStore, 0)
- var cert *windows.CertContext
- var names []string
- for {
- cert, err = windows.CertEnumCertificatesInStore(certStore, cert)
- if err != nil {
- if errno, ok := err.(syscall.Errno); ok {
- if errno == syscall.Errno(windows.CRYPT_E_NOT_FOUND) {
- break
- }
- }
- return nil, err
- }
- if cert == nil {
- break
- }
- nameLen := certGetNameString(cert, _CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, nil, 0)
- if nameLen == 0 {
- continue
- }
- name16 := make([]uint16, nameLen)
- if certGetNameString(cert, _CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, &name16[0], nameLen) != nameLen {
- continue
- }
- if name16[0] == 0 {
- continue
- }
- names = append(names, windows.UTF16ToString(name16))
- }
- if names == nil {
- return nil, syscall.Errno(windows.CRYPT_E_NOT_FOUND)
- }
- return names, nil
-}
-
-func ExtractCertificatePolicies(path string, oid string) ([]string, error) {
- path16, err := windows.UTF16PtrFromString(path)
- if err != nil {
- return nil, err
- }
- oid8, err := windows.BytePtrFromString(oid)
- if err != nil {
- return nil, err
- }
- var certStore windows.Handle
- err = cryptQueryObject(_CERT_QUERY_OBJECT_FILE, uintptr(unsafe.Pointer(path16)), _CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, _CERT_QUERY_FORMAT_FLAG_ALL, 0, nil, nil, nil, &certStore, nil, nil)
- if err != nil {
- return nil, err
- }
- defer windows.CertCloseStore(certStore, 0)
- var cert *windows.CertContext
- var policies []string
- for {
- cert, err = windows.CertEnumCertificatesInStore(certStore, cert)
- if err != nil {
- if errno, ok := err.(syscall.Errno); ok {
- if errno == syscall.Errno(windows.CRYPT_E_NOT_FOUND) {
- break
- }
- }
- return nil, err
- }
- if cert == nil {
- break
- }
- ci := (*certInfo)(unsafe.Pointer(cert.CertInfo))
- ext := certFindExtension(oid8, ci.countExtensions, ci.extensions)
- if ext == nil {
- continue
- }
- var decodedLen uint32
- err = cryptDecodeObject(windows.X509_ASN_ENCODING|windows.PKCS_7_ASN_ENCODING, ext.objId, ext.value.data, ext.value.len, 0, nil, &decodedLen)
- if err != nil {
- return nil, err
- }
- bytes := make([]byte, decodedLen)
- certPoliciesInfo := (*certPoliciesInfo)(unsafe.Pointer(&bytes[0]))
- err = cryptDecodeObject(windows.X509_ASN_ENCODING|windows.PKCS_7_ASN_ENCODING, ext.objId, ext.value.data, ext.value.len, 0, unsafe.Pointer(&bytes[0]), &decodedLen)
- if err != nil {
- return nil, err
- }
- for i := uintptr(0); i < uintptr(certPoliciesInfo.countPolicyInfos); i++ {
- cp := (*certPolicy)(unsafe.Pointer(uintptr(unsafe.Pointer(certPoliciesInfo.policyInfos)) + i*unsafe.Sizeof(*certPoliciesInfo.policyInfos)))
- policies = append(policies, windows.BytePtrToString(cp.identifier))
- }
- }
- if policies == nil {
- return nil, syscall.Errno(windows.CRYPT_E_NOT_FOUND)
- }
- return policies, nil
-}
diff --git a/version/wintrust/mksyscall.go b/version/wintrust/mksyscall.go
deleted file mode 100644
index 7709a654..00000000
--- a/version/wintrust/mksyscall.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
- */
-
-package wintrust
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go wintrust_windows.go certificate_windows.go
diff --git a/version/wintrust/wintrust_windows.go b/version/wintrust/wintrust_windows.go
deleted file mode 100644
index e7c92606..00000000
--- a/version/wintrust/wintrust_windows.go
+++ /dev/null
@@ -1,116 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
- */
-
-package wintrust
-
-import (
- "syscall"
-
- "golang.org/x/sys/windows"
-)
-
-type WinTrustData struct {
- CbStruct uint32
- PolicyCallbackData uintptr
- SIPClientData uintptr
- UIChoice uint32
- RevocationChecks uint32
- UnionChoice uint32
- FileOrCatalogOrBlobOrSgnrOrCert uintptr
- StateAction uint32
- StateData syscall.Handle
- URLReference *uint16
- ProvFlags uint32
- UIContext uint32
- SignatureSettings *WintrustSignatureSettings
-}
-
-const (
- WTD_UI_ALL = 1
- WTD_UI_NONE = 2
- WTD_UI_NOBAD = 3
- WTD_UI_NOGOOD = 4
-)
-
-const (
- WTD_REVOKE_NONE = 0
- WTD_REVOKE_WHOLECHAIN = 1
-)
-
-const (
- WTD_CHOICE_FILE = 1
- WTD_CHOICE_CATALOG = 2
- WTD_CHOICE_BLOB = 3
- WTD_CHOICE_SIGNER = 4
- WTD_CHOICE_CERT = 5
-)
-
-const (
- WTD_STATEACTION_IGNORE = 0x00000000
- WTD_STATEACTION_VERIFY = 0x00000010
- WTD_STATEACTION_CLOSE = 0x00000002
- WTD_STATEACTION_AUTO_CACHE = 0x00000003
- WTD_STATEACTION_AUTO_CACHE_FLUSH = 0x00000004
-)
-
-const (
- WTD_USE_IE4_TRUST_FLAG = 0x1
- WTD_NO_IE4_CHAIN_FLAG = 0x2
- WTD_NO_POLICY_USAGE_FLAG = 0x4
- WTD_REVOCATION_CHECK_NONE = 0x10
- WTD_REVOCATION_CHECK_END_CERT = 0x20
- WTD_REVOCATION_CHECK_CHAIN = 0x40
- WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x80
- WTD_SAFER_FLAG = 0x100
- WTD_HASH_ONLY_FLAG = 0x200
- WTD_USE_DEFAULT_OSVER_CHECK = 0x400
- WTD_LIFETIME_SIGNING_FLAG = 0x800
- WTD_CACHE_ONLY_URL_RETRIEVAL = 0x1000
- WTD_DISABLE_MD2_MD4 = 0x2000
- WTD_MOTW = 0x4000
-)
-
-const (
- TRUST_E_NOSIGNATURE = 0x800B0100
- TRUST_E_EXPLICIT_DISTRUST = 0x800B0111
- TRUST_E_SUBJECT_NOT_TRUSTED = 0x800B0004
- CRYPT_E_SECURITY_SETTINGS = 0x80092026
-)
-
-const (
- WTD_UICONTEXT_EXECUTE = 0
- WTD_UICONTEXT_INSTALL = 1
-)
-
-var WINTRUST_ACTION_GENERIC_VERIFY_V2 = windows.GUID{
- Data1: 0xaac56b,
- Data2: 0xcd44,
- Data3: 0x11d0,
- Data4: [8]byte{0x8c, 0xc2, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee},
-}
-
-type WinTrustFileInfo struct {
- CbStruct uint32
- FilePath *uint16
- File windows.Handle
- KnownSubject *windows.GUID
-}
-
-type WintrustSignatureSettings struct {
- CbStruct uint32
- Index uint32
- Flags uint32
- SecondarySigs uint32
- VerifiedSigIndex uint32
- CryptoPolicy *CertStrongSignPara
-}
-
-type CertStrongSignPara struct {
- CbStruct uint32
- InfoChoice uint32
- InfoOrSerializedInfoOrOID uintptr
-}
-
-//sys WinVerifyTrust(hWnd windows.Handle, actionId *windows.GUID, data *WinTrustData) (err error) [r1 != 0] = wintrust.WinVerifyTrust
diff --git a/version/wintrust/zsyscall_windows.go b/version/wintrust/zsyscall_windows.go
deleted file mode 100644
index 67daccb1..00000000
--- a/version/wintrust/zsyscall_windows.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package wintrust
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
- errnoERROR_IO_PENDING = 997
-)
-
-var (
- errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
- errERROR_EINVAL error = syscall.EINVAL
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
- switch e {
- case 0:
- return errERROR_EINVAL
- case errnoERROR_IO_PENDING:
- return errERROR_IO_PENDING
- }
- // TODO: add more here, after collecting data on the common
- // error values see on Windows. (perhaps when running
- // all.bat?)
- return e
-}
-
-var (
- modcrypt32 = windows.NewLazySystemDLL("crypt32.dll")
- modwintrust = windows.NewLazySystemDLL("wintrust.dll")
-
- procCertFindExtension = modcrypt32.NewProc("CertFindExtension")
- procCertGetNameStringW = modcrypt32.NewProc("CertGetNameStringW")
- procCryptDecodeObject = modcrypt32.NewProc("CryptDecodeObject")
- procCryptQueryObject = modcrypt32.NewProc("CryptQueryObject")
- procWinVerifyTrust = modwintrust.NewProc("WinVerifyTrust")
-)
-
-func certFindExtension(objId *byte, countExtensions uint32, extensions *certExtension) (ret *certExtension) {
- r0, _, _ := syscall.Syscall(procCertFindExtension.Addr(), 3, uintptr(unsafe.Pointer(objId)), uintptr(countExtensions), uintptr(unsafe.Pointer(extensions)))
- ret = (*certExtension)(unsafe.Pointer(r0))
- return
-}
-
-func certGetNameString(certContext *windows.CertContext, nameType uint32, flags uint32, typePara unsafe.Pointer, name *uint16, size uint32) (chars uint32) {
- r0, _, _ := syscall.Syscall6(procCertGetNameStringW.Addr(), 6, uintptr(unsafe.Pointer(certContext)), uintptr(nameType), uintptr(flags), uintptr(typePara), uintptr(unsafe.Pointer(name)), uintptr(size))
- chars = uint32(r0)
- return
-}
-
-func cryptDecodeObject(encodingType uint32, structType *byte, encodedBytes *byte, lenEncodedBytes uint32, flags uint32, decoded unsafe.Pointer, decodedLen *uint32) (err error) {
- r1, _, e1 := syscall.Syscall9(procCryptDecodeObject.Addr(), 7, uintptr(encodingType), uintptr(unsafe.Pointer(structType)), uintptr(unsafe.Pointer(encodedBytes)), uintptr(lenEncodedBytes), uintptr(flags), uintptr(decoded), uintptr(unsafe.Pointer(decodedLen)), 0, 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func cryptQueryObject(objectType uint32, object uintptr, expectedContentTypeFlags uint32, expectedFormatTypeFlags uint32, flags uint32, msgAndCertEncodingType *uint32, contentType *uint32, formatType *uint32, certStore *windows.Handle, msg *windows.Handle, context *uintptr) (err error) {
- r1, _, e1 := syscall.Syscall12(procCryptQueryObject.Addr(), 11, uintptr(objectType), uintptr(object), uintptr(expectedContentTypeFlags), uintptr(expectedFormatTypeFlags), uintptr(flags), uintptr(unsafe.Pointer(msgAndCertEncodingType)), uintptr(unsafe.Pointer(contentType)), uintptr(unsafe.Pointer(formatType)), uintptr(unsafe.Pointer(certStore)), uintptr(unsafe.Pointer(msg)), uintptr(unsafe.Pointer(context)), 0)
- if r1 == 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func WinVerifyTrust(hWnd windows.Handle, actionId *windows.GUID, data *WinTrustData) (err error) {
- r1, _, e1 := syscall.Syscall(procWinVerifyTrust.Addr(), 3, uintptr(hWnd), uintptr(unsafe.Pointer(actionId)), uintptr(unsafe.Pointer(data)))
- if r1 != 0 {
- err = errnoErr(e1)
- }
- return
-}