From 77397ffcb2acff0dff7ecd860af1496f34e0bc04 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 29 Nov 2023 20:01:24 +0000 Subject: [release-branch.go1.20] crypto/rand,runtime: revert "switch RtlGenRandom for ProcessPrng" This reverts CL 545356. Reason for revert: 1.20 still supports Windows versions before ProcessPrng was introduced. Change-Id: I224b8c4e7d0ca9ad5e733819b24dd92d14e61ab8 Reviewed-on: https://go-review.googlesource.com/c/go/+/545995 Reviewed-by: Dmitri Shuralyov TryBot-Bypass: Dmitri Shuralyov TryBot-Result: Gopher Robot Run-TryBot: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov Auto-Submit: Dmitri Shuralyov --- src/crypto/rand/rand.go | 2 +- src/crypto/rand/rand_windows.go | 7 +++++-- src/internal/syscall/windows/syscall_windows.go | 2 +- src/internal/syscall/windows/zsyscall_windows.go | 21 ++++++++++----------- src/runtime/os_windows.go | 23 +++++++++++++++-------- 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go index 0f3dca4e0e..af85b966df 100644 --- a/src/crypto/rand/rand.go +++ b/src/crypto/rand/rand.go @@ -15,7 +15,7 @@ import "io" // available, /dev/urandom otherwise. // On OpenBSD and macOS, Reader uses getentropy(2). // On other Unix-like systems, Reader reads from /dev/urandom. -// On Windows systems, Reader uses the ProcessPrng API. +// On Windows systems, Reader uses the RtlGenRandom API. // On Wasm, Reader uses the Web Crypto API. var Reader io.Reader diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go index 7380f1f0f1..6c0655c72b 100644 --- a/src/crypto/rand/rand_windows.go +++ b/src/crypto/rand/rand_windows.go @@ -15,8 +15,11 @@ func init() { Reader = &rngReader{} } type rngReader struct{} -func (r *rngReader) Read(b []byte) (int, error) { - if err := windows.ProcessPrng(b); err != nil { +func (r *rngReader) Read(b []byte) (n int, err error) { + // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at + // most 1<<31-1 bytes at a time so that this works the same on 32-bit + // and 64-bit systems. + if err := batched(windows.RtlGenRandom, 1<<31-1)(b); err != nil { return 0, err } return len(b), nil diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go index b7bf886f38..8ace2a27e7 100644 --- a/src/internal/syscall/windows/syscall_windows.go +++ b/src/internal/syscall/windows/syscall_windows.go @@ -366,4 +366,4 @@ func LoadGetFinalPathNameByHandle() error { //sys CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock -//sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng +//sys RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036 diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go index 7ed6234451..afd64e318e 100644 --- a/src/internal/syscall/windows/zsyscall_windows.go +++ b/src/internal/syscall/windows/zsyscall_windows.go @@ -37,14 +37,13 @@ func errnoErr(e syscall.Errno) error { } var ( - modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) - modbcryptprimitives = syscall.NewLazyDLL(sysdll.Add("bcryptprimitives.dll")) - modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll")) - modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) - modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) - modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll")) - moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll")) - modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll")) + modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) + modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll")) + modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) + modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) + modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll")) + moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll")) + modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll")) procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") @@ -53,7 +52,7 @@ var ( procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") - procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng") + procSystemFunction036 = modadvapi32.NewProc("SystemFunction036") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procGetACP = modkernel32.NewProc("GetACP") procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") @@ -145,12 +144,12 @@ func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32 return } -func ProcessPrng(buf []byte) (err error) { +func RtlGenRandom(buf []byte) (err error) { var _p0 *byte if len(buf) > 0 { _p0 = &buf[0] } - r1, _, e1 := syscall.Syscall(procProcessPrng.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0) + r1, _, e1 := syscall.Syscall(procSystemFunction036.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0) if r1 == 0 { err = errnoErr(e1) } diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index a88d3a8ac6..44718f1d21 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -122,8 +122,15 @@ var ( _LoadLibraryExW, _ stdFunction - // Use ProcessPrng to generate cryptographically random data. - _ProcessPrng stdFunction + // Use RtlGenRandom to generate cryptographically random data. + // This approach has been recommended by Microsoft (see issue + // 15589 for details). + // The RtlGenRandom is not listed in advapi32.dll, instead + // RtlGenRandom function can be found by searching for SystemFunction036. + // Also some versions of Mingw cannot link to SystemFunction036 + // when building executable as Cgo. So load SystemFunction036 + // manually during runtime startup. + _RtlGenRandom stdFunction // Load ntdll.dll manually during startup, otherwise Mingw // links wrong printf function to cgo executable (see issue @@ -249,12 +256,12 @@ func loadOptionalSyscalls() { _LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000")) useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil) - var bcryptprimitivesdll = []byte("bcryptprimitives.dll\000") - bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll) - if bcryptPrimitives == 0 { - throw("bcryptprimitives.dll not found") + var advapi32dll = []byte("advapi32.dll\000") + a32 := windowsLoadSystemLib(advapi32dll) + if a32 == 0 { + throw("advapi32.dll not found") } - _ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000")) + _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000")) var ntdll = []byte("ntdll.dll\000") n32 := windowsLoadSystemLib(ntdll) @@ -637,7 +644,7 @@ func initWine(k32 uintptr) { //go:nosplit func getRandomData(r []byte) { n := 0 - if stdcall2(_ProcessPrng, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { + if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { n = len(r) } extendRandom(r, n) -- cgit v1.2.3-54-g00ecf