diff options
Diffstat (limited to 'version')
-rw-r--r-- | version/certificate_test.go | 42 | ||||
-rw-r--r-- | version/debugging_linux.go | 35 | ||||
-rw-r--r-- | version/official.go | 156 | ||||
-rw-r--r-- | version/official_windows.go | 105 | ||||
-rw-r--r-- | version/os.go (renamed from version/os_windows.go) | 2 | ||||
-rw-r--r-- | version/useragent.go | 18 | ||||
-rw-r--r-- | version/version.go | 10 | ||||
-rw-r--r-- | version/version.h | 2 | ||||
-rw-r--r-- | version/wintrust/certificate_windows.go | 59 | ||||
-rw-r--r-- | version/wintrust/mksyscall.go | 8 | ||||
-rw-r--r-- | version/wintrust/wintrust_windows.go | 116 | ||||
-rw-r--r-- | version/wintrust/zsyscall_windows.go | 69 |
12 files changed, 221 insertions, 401 deletions
diff --git a/version/certificate_test.go b/version/certificate_test.go new file mode 100644 index 00000000..724c524f --- /dev/null +++ b/version/certificate_test.go @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package version + +import ( + "fmt" + "path/filepath" + "testing" + + "golang.org/x/sys/windows" +) + +func TestExtractCertificateNames(t *testing.T) { + system32, err := windows.GetSystemDirectory() + if err != nil { + t.Fatal(err) + } + names, err := extractCertificateNames(filepath.Join(system32, "ntoskrnl.exe")) + if err != nil { + t.Fatal(err) + } + for i, name := range names { + fmt.Printf("%d: %s\n", i, name) + } +} + +func TestExtractCertificateExtension(t *testing.T) { + system32, err := windows.GetSystemDirectory() + if err != nil { + t.Fatal(err) + } + policies, err := extractCertificatePolicies(filepath.Join(system32, "ntoskrnl.exe"), "2.5.29.32") + if err != nil { + t.Fatal(err) + } + for i, policy := range policies { + fmt.Printf("%d: %s\n", i, policy) + } +} diff --git a/version/debugging_linux.go b/version/debugging_linux.go deleted file mode 100644 index ddea4242..00000000 --- a/version/debugging_linux.go +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: MIT - * - * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. - */ - -package version - -import ( - "bytes" - "fmt" - - "golang.org/x/sys/unix" -) - -// For testing the updater package from linux. Debug stuff only. - -func utsToStr(u [65]byte) string { - i := bytes.IndexByte(u[:], 0) - if i < 0 { - return string(u[:]) - } - return string(u[:i]) -} - -func OsName() string { - var utsname unix.Utsname - if unix.Uname(&utsname) != nil { - return "Unix Unknown" - } - return fmt.Sprintf("%s %s %s", utsToStr(utsname.Sysname), utsToStr(utsname.Release), utsToStr(utsname.Version)) -} - -func VerifyAuthenticode(path string) bool { - return true -} diff --git a/version/official.go b/version/official.go new file mode 100644 index 00000000..2951c893 --- /dev/null +++ b/version/official.go @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package version + +import ( + "errors" + "os" + "unsafe" + + "golang.org/x/sys/windows" +) + +const ( + officialCommonName = "WireGuard LLC" + evPolicyOid = "2.23.140.1.3" + policyExtensionOid = "2.5.29.32" +) + +// These are easily by-passable checks, which do not serve security purposes. +// DO NOT PLACE SECURITY-SENSITIVE FUNCTIONS IN THIS FILE + +func IsRunningOfficialVersion() bool { + path, err := os.Executable() + if err != nil { + return false + } + + names, err := extractCertificateNames(path) + if err != nil { + return false + } + for _, name := range names { + if name == officialCommonName { + return true + } + } + return false +} + +func IsRunningEVSigned() bool { + path, err := os.Executable() + if err != nil { + return false + } + + policies, err := extractCertificatePolicies(path, policyExtensionOid) + if err != nil { + return false + } + for _, policy := range policies { + if policy == evPolicyOid { + return true + } + } + return false +} + +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 errors.Is(err, windows.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, windows.Errno(windows.CRYPT_E_NOT_FOUND) + } + return names, nil +} + +func extractCertificatePolicies(path, 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 errors.Is(err, windows.Errno(windows.CRYPT_E_NOT_FOUND)) { + break + } + return nil, err + } + if cert == nil { + break + } + ext := windows.CertFindExtension(oid8, cert.CertInfo.CountExtensions, cert.CertInfo.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.CertPolicyInfo)(unsafe.Add(unsafe.Pointer(certPoliciesInfo.PolicyInfos), i*unsafe.Sizeof(*certPoliciesInfo.PolicyInfos))) + policies = append(policies, windows.BytePtrToString(cp.Identifier)) + } + } + if policies == nil { + return nil, windows.Errno(windows.CRYPT_E_NOT_FOUND) + } + return policies, nil +} diff --git a/version/official_windows.go b/version/official_windows.go deleted file mode 100644 index 5f8ea731..00000000 --- a/version/official_windows.go +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: MIT - * - * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. - */ - -package version - -import ( - "encoding/asn1" - "os" - "unsafe" - - "golang.org/x/sys/windows" - "golang.zx2c4.com/wireguard/windows/version/wintrust" -) - -const ( - officialCommonName = "WireGuard LLC" - evPolicyOid = "2.23.140.1.3" - policyExtensionOid = "2.5.29.32" -) - -type policyQualifierInfo struct { - PolicyQualifierId asn1.ObjectIdentifier - Qualifier asn1.RawValue -} - -type policyInformation struct { - Policy asn1.ObjectIdentifier - Qualifiers []policyQualifierInfo `asn1:"optional"` -} - -func VerifyAuthenticode(path string) bool { - path16, err := windows.UTF16PtrFromString(path) - 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)), - } - return wintrust.WinVerifyTrust(0, &wintrust.WINTRUST_ACTION_GENERIC_VERIFY_V2, data) == nil -} - -// This is an easily by-passable check, which doesn't serve a security purpose but mostly just a low-grade -// informational and semantic one. -func IsRunningOfficialVersion() bool { - path, err := os.Executable() - if err != nil { - return false - } - - // This is easily circumvented. We don't even verify the chain before hand with WinVerifyTrust. - // False certificates can be appended. But that's okay, as this isn't security related. - - certs, err := wintrust.ExtractCertificates(path) - if err != nil { - return false - } - for _, cert := range certs { - if cert.Subject.CommonName == officialCommonName { - return true - } - } - return false -} - -func IsRunningEVSigned() bool { - path, err := os.Executable() - if err != nil { - return false - } - - // This is easily circumvented. We don't even verify the chain before hand with WinVerifyTrust. - // False certificates can be appended. But that's okay, as this isn't security related. - - certs, err := wintrust.ExtractCertificates(path) - if err != nil { - return false - } - for _, cert := range certs { - for _, extension := range cert.Extensions { - if extension.Id.String() == policyExtensionOid { - var policies []policyInformation - if _, err = asn1.Unmarshal(extension.Value, &policies); err != nil { - continue - } - for _, policy := range policies { - if policy.Policy.String() == evPolicyOid { - return true - } - } - } - } - } - return false -} diff --git a/version/os_windows.go b/version/os.go index 670d3da7..ff9188bb 100644 --- a/version/os_windows.go +++ b/version/os.go @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: MIT * - * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. */ package version diff --git a/version/useragent.go b/version/useragent.go index 1c1adf55..3b5240c6 100644 --- a/version/useragent.go +++ b/version/useragent.go @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: MIT * - * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. */ package version @@ -10,11 +10,17 @@ import ( "runtime" ) -// #include "version.h" -import "C" - -const Number = C.WIREGUARD_WINDOWS_VERSION_STRING +func Arch() string { + switch runtime.GOARCH { + case "arm", "arm64", "amd64": + return runtime.GOARCH + case "386": + return "x86" + default: + panic("Unrecognized GOARCH") + } +} func UserAgent() string { - return fmt.Sprintf("WireGuard/%s (%s; %s)", Number, OsName(), runtime.GOARCH) + return fmt.Sprintf("WireGuard/%s (%s; %s)", Number, OsName(), Arch()) } diff --git a/version/version.go b/version/version.go new file mode 100644 index 00000000..a7f908e8 --- /dev/null +++ b/version/version.go @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. + */ + +package version + +const ( + Number = "0.5.3" +) diff --git a/version/version.h b/version/version.h deleted file mode 100644 index 0da08178..00000000 --- a/version/version.h +++ /dev/null @@ -1,2 +0,0 @@ -#define WIREGUARD_WINDOWS_VERSION_ARRAY 0,1,1 -#define WIREGUARD_WINDOWS_VERSION_STRING "0.1.1" diff --git a/version/wintrust/certificate_windows.go b/version/wintrust/certificate_windows.go deleted file mode 100644 index 1e145095..00000000 --- a/version/wintrust/certificate_windows.go +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: MIT - * - * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. - */ - -package wintrust - -import ( - "crypto/x509" - "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 -) - -//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 - -func ExtractCertificates(path string) ([]x509.Certificate, 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 certs []x509.Certificate - var cert *windows.CertContext - 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 - } - buf := make([]byte, cert.Length) - copy(buf, (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]) - if c, err := x509.ParseCertificate(buf); err == nil { - certs = append(certs, *c) - } else { - return nil, err - } - } - return certs, nil -} diff --git a/version/wintrust/mksyscall.go b/version/wintrust/mksyscall.go deleted file mode 100644 index 890b2668..00000000 --- a/version/wintrust/mksyscall.go +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: MIT - * - * Copyright (C) 2019 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 fa3b2f0b..00000000 --- a/version/wintrust/wintrust_windows.go +++ /dev/null @@ -1,116 +0,0 @@ -/* SPDX-License-Identifier: MIT - * - * Copyright (C) 2019 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 4d73cc5e..00000000 --- a/version/wintrust/zsyscall_windows.go +++ /dev/null @@ -1,69 +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) -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return nil - 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 ( - modwintrust = windows.NewLazySystemDLL("wintrust.dll") - modcrypt32 = windows.NewLazySystemDLL("crypt32.dll") - - procWinVerifyTrust = modwintrust.NewProc("WinVerifyTrust") - procCryptQueryObject = modcrypt32.NewProc("CryptQueryObject") -) - -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 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - 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 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} |