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 | 33 +++++++++++++-------------------- diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go index 62738e2cb1a7df8a8cf3e3ec48d5a772ef91d4ae..d0dcc7cc71fc0c9b35c12fd25a2a551e7253044b 100644 --- a/src/crypto/rand/rand.go +++ b/src/crypto/rand/rand.go @@ -15,7 +15,7 @@ // On Linux, FreeBSD, Dragonfly, NetBSD and Solaris, Reader uses getrandom(2) if // 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 RtlGenRandom API. +// On Windows systems, Reader uses the ProcessPrng API. // On JS/Wasm, Reader uses the Web Crypto API. // On WASIP1/Wasm, Reader uses random_get from wasi_snapshot_preview1. var Reader io.Reader diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go index 6c0655c72b692ae444a85025ecc3d27d65107404..7380f1f0f1e6e6ee21a912318fdefdf1655e1a0c 100644 --- a/src/crypto/rand/rand_windows.go +++ b/src/crypto/rand/rand_windows.go @@ -15,11 +15,8 @@ func init() { Reader = &rngReader{} } type rngReader struct{} -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 { +func (r *rngReader) Read(b []byte) (int, error) { + if err := windows.ProcessPrng(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 892b878d165dd5dda249c47cf2633a5970b5c0de..e9390b07cd40a1c3a8957783c9d34b93a0a7bd33 100644 --- a/src/internal/syscall/windows/syscall_windows.go +++ b/src/internal/syscall/windows/syscall_windows.go @@ -373,7 +373,7 @@ //sys CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock //sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW -//sys RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036 +//sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng //sys RtlLookupFunctionEntry(pc uintptr, baseAddress *uintptr, table *byte) (ret uintptr) = kernel32.RtlLookupFunctionEntry //sys RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry uintptr, ctxt uintptr, data *uintptr, frame *uintptr, ctxptrs *byte) (ret uintptr) = kernel32.RtlVirtualUnwind diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go index a5c246b773d398b3c8a4ab81d529b4b303b5b9e5..26ec290e026c1a010b55acad874715782cf44c11 100644 --- a/src/internal/syscall/windows/zsyscall_windows.go +++ b/src/internal/syscall/windows/zsyscall_windows.go @@ -37,13 +37,14 @@ return e } var ( - 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")) + 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")) procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") @@ -52,7 +53,7 @@ procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") - procSystemFunction036 = modadvapi32.NewProc("SystemFunction036") + procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procCreateEventW = modkernel32.NewProc("CreateEventW") procGetACP = modkernel32.NewProc("GetACP") @@ -148,12 +149,12 @@ } return } -func RtlGenRandom(buf []byte) (err error) { +func ProcessPrng(buf []byte) (err error) { var _p0 *byte if len(buf) > 0 { _p0 = &buf[0] } - r1, _, e1 := syscall.Syscall(procSystemFunction036.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0) + r1, _, e1 := syscall.Syscall(procProcessPrng.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 f5c2429a05d1460fc01072e3687001af9e79b7a0..735a905b6161ac05ff5a17650720d1589a4d7b07 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -127,15 +127,8 @@ // We will load syscalls, if available, before using them. _AddVectoredContinueHandler, _ 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 + // Use ProcessPrng to generate cryptographically random data. + _ProcessPrng stdFunction // Load ntdll.dll manually during startup, otherwise Mingw // links wrong printf function to cgo executable (see issue @@ -152,12 +145,12 @@ _ stdFunction ) var ( - advapi32dll = [...]uint16{'a', 'd', 'v', 'a', 'p', 'i', '3', '2', '.', 'd', 'l', 'l', 0} - kernel32dll = [...]uint16{'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0} - ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0} - powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0} - winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0} - ws2_32dll = [...]uint16{'w', 's', '2', '_', '3', '2', '.', 'd', 'l', 'l', 0} + bcryptprimitivesdll = [...]uint16{'b', 'c', 'r', 'y', 'p', 't', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 's', '.', 'd', 'l', 'l', 0} + kernel32dll = [...]uint16{'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0} + ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0} + powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0} + winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0} + ws2_32dll = [...]uint16{'w', 's', '2', '_', '3', '2', '.', 'd', 'l', 'l', 0} ) // Function to be called by windows CreateThread @@ -256,11 +249,11 @@ throw("kernel32.dll not found") } _AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000")) - a32 := windowsLoadSystemLib(advapi32dll[:]) - if a32 == 0 { - throw("advapi32.dll not found") + bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll[:]) + if bcryptPrimitives == 0 { + throw("bcryptprimitives.dll not found") } - _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000")) + _ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000")) n32 := windowsLoadSystemLib(ntdlldll[:]) if n32 == 0 { @@ -617,7 +610,7 @@ //go:nosplit func getRandomData(r []byte) { n := 0 - if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { + if stdcall2(_ProcessPrng, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { n = len(r) } extendRandom(r, n)