windows: add support for DPAPI
DPAPI allows machine or user-based blob encryption, using APIs from
crypt32:
https://docs.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptunprotectdata
https://docs.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectdata
Change-Id: I57fb4f1877a5fb7629809e79111cbfa02b11cca3
Reviewed-on: https://go-review.googlesource.com/c/sys/+/285716
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go
index 13d7425..0197df8 100644
--- a/windows/syscall_windows.go
+++ b/windows/syscall_windows.go
@@ -285,6 +285,8 @@
//sys CertFindExtension(objId *byte, countExtensions uint32, extensions *CertExtension) (ret *CertExtension) = crypt32.CertFindExtension
//sys CryptQueryObject(objectType uint32, object unsafe.Pointer, expectedContentTypeFlags uint32, expectedFormatTypeFlags uint32, flags uint32, msgAndCertEncodingType *uint32, contentType *uint32, formatType *uint32, certStore *Handle, msg *Handle, context *unsafe.Pointer) (err error) = crypt32.CryptQueryObject
//sys CryptDecodeObject(encodingType uint32, structType *byte, encodedBytes *byte, lenEncodedBytes uint32, flags uint32, decoded unsafe.Pointer, decodedLen *uint32) (err error) = crypt32.CryptDecodeObject
+//sys CryptProtectData(dataIn *DataBlob, name *uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) = crypt32.CryptProtectData
+//sys CryptUnprotectData(dataIn *DataBlob, name **uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) = crypt32.CryptUnprotectData
//sys WinVerifyTrustEx(hwnd HWND, actionId *GUID, data *WinTrustData) (ret error) = wintrust.WinVerifyTrustEx
//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW
//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey
diff --git a/windows/types_windows.go b/windows/types_windows.go
index 453f56f..1f51bb8 100644
--- a/windows/types_windows.go
+++ b/windows/types_windows.go
@@ -498,6 +498,22 @@
SECURITY_FLAG_IGNORE_WRONG_USAGE = 0x00000200
SECURITY_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000
+
+ /* Flags for Crypt[Un]ProtectData */
+ CRYPTPROTECT_UI_FORBIDDEN = 0x1
+ CRYPTPROTECT_LOCAL_MACHINE = 0x4
+ CRYPTPROTECT_CRED_SYNC = 0x8
+ CRYPTPROTECT_AUDIT = 0x10
+ CRYPTPROTECT_NO_RECOVERY = 0x20
+ CRYPTPROTECT_VERIFY_PROTECTION = 0x40
+ CRYPTPROTECT_CRED_REGENERATE = 0x80
+
+ /* Flags for CryptProtectPromptStruct */
+ CRYPTPROTECT_PROMPT_ON_UNPROTECT = 1
+ CRYPTPROTECT_PROMPT_ON_PROTECT = 2
+ CRYPTPROTECT_PROMPT_RESERVED = 4
+ CRYPTPROTECT_PROMPT_STRONG = 8
+ CRYPTPROTECT_PROMPT_REQUIRE_STRONG = 16
)
const (
@@ -1337,6 +1353,13 @@
InfoOrSerializedInfoOrOID unsafe.Pointer
}
+type CryptProtectPromptStruct struct {
+ Size uint32
+ PromptFlags uint32
+ App HWND
+ Prompt *uint16
+}
+
type WinTrustData struct {
Size uint32
PolicyCallbackData uintptr
diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go
index b28a193..c38c59d 100644
--- a/windows/zsyscall_windows.go
+++ b/windows/zsyscall_windows.go
@@ -155,7 +155,9 @@
procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW")
procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy")
procCryptDecodeObject = modcrypt32.NewProc("CryptDecodeObject")
+ procCryptProtectData = modcrypt32.NewProc("CryptProtectData")
procCryptQueryObject = modcrypt32.NewProc("CryptQueryObject")
+ procCryptUnprotectData = modcrypt32.NewProc("CryptUnprotectData")
procPFXImportCertStore = modcrypt32.NewProc("PFXImportCertStore")
procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W")
procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W")
@@ -1275,6 +1277,14 @@
return
}
+func CryptProtectData(dataIn *DataBlob, name *uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) {
+ r1, _, e1 := syscall.Syscall9(procCryptProtectData.Addr(), 7, uintptr(unsafe.Pointer(dataIn)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(optionalEntropy)), uintptr(reserved), uintptr(unsafe.Pointer(promptStruct)), uintptr(flags), uintptr(unsafe.Pointer(dataOut)), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func CryptQueryObject(objectType uint32, object unsafe.Pointer, expectedContentTypeFlags uint32, expectedFormatTypeFlags uint32, flags uint32, msgAndCertEncodingType *uint32, contentType *uint32, formatType *uint32, certStore *Handle, msg *Handle, context *unsafe.Pointer) (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 {
@@ -1283,6 +1293,14 @@
return
}
+func CryptUnprotectData(dataIn *DataBlob, name **uint16, optionalEntropy *DataBlob, reserved uintptr, promptStruct *CryptProtectPromptStruct, flags uint32, dataOut *DataBlob) (err error) {
+ r1, _, e1 := syscall.Syscall9(procCryptUnprotectData.Addr(), 7, uintptr(unsafe.Pointer(dataIn)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(optionalEntropy)), uintptr(reserved), uintptr(unsafe.Pointer(promptStruct)), uintptr(flags), uintptr(unsafe.Pointer(dataOut)), 0, 0)
+ if r1 == 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
func PFXImportCertStore(pfx *CryptDataBlob, password *uint16, flags uint32) (store Handle, err error) {
r0, _, e1 := syscall.Syscall(procPFXImportCertStore.Addr(), 3, uintptr(unsafe.Pointer(pfx)), uintptr(unsafe.Pointer(password)), uintptr(flags))
store = Handle(r0)