Switch ProcessPrng back to RtlGenRandom (revert 693def1)

This commit is contained in:
Vorapol Rinsatitnon
2024-09-21 23:56:11 +10:00
parent 17cd57a668
commit f1f146d453
5 changed files with 29 additions and 19 deletions

View File

@@ -16,7 +16,7 @@ import "io"
// - On macOS and iOS, Reader uses arc4random_buf(3). // - On macOS and iOS, Reader uses arc4random_buf(3).
// - On OpenBSD and NetBSD, Reader uses getentropy(2). // - On OpenBSD and NetBSD, Reader uses getentropy(2).
// - On other Unix-like systems, Reader reads from /dev/urandom. // - On other Unix-like systems, Reader reads from /dev/urandom.
// - On Windows, Reader uses the ProcessPrng API. // - On Windows, Reader uses the RtlGenRandom API.
// - On js/wasm, Reader uses the Web Crypto API. // - On js/wasm, Reader uses the Web Crypto API.
// - On wasip1/wasm, Reader uses random_get from wasi_snapshot_preview1. // - On wasip1/wasm, Reader uses random_get from wasi_snapshot_preview1.
var Reader io.Reader var Reader io.Reader

View File

@@ -15,8 +15,11 @@ func init() { Reader = &rngReader{} }
type rngReader struct{} type rngReader struct{}
func (r *rngReader) Read(b []byte) (int, error) { func (r *rngReader) Read(b []byte) (n int, err error) {
if err := windows.ProcessPrng(b); err != nil { // 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 0, err
} }
return len(b), nil return len(b), nil

View File

@@ -414,7 +414,7 @@ func ErrorLoadingGetTempPath2() error {
//sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock //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 CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW
//sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng //sys RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036
type FILE_ID_BOTH_DIR_INFO struct { type FILE_ID_BOTH_DIR_INFO struct {
NextEntryOffset uint32 NextEntryOffset uint32

View File

@@ -38,7 +38,6 @@ func errnoErr(e syscall.Errno) error {
var ( var (
modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
modbcryptprimitives = syscall.NewLazyDLL(sysdll.Add("bcryptprimitives.dll"))
modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll")) modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
@@ -57,7 +56,7 @@ var (
procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus")
procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation")
procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng") procSystemFunction036 = modadvapi32.NewProc("SystemFunction036")
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
procCreateEventW = modkernel32.NewProc("CreateEventW") procCreateEventW = modkernel32.NewProc("CreateEventW")
procGetACP = modkernel32.NewProc("GetACP") procGetACP = modkernel32.NewProc("GetACP")
@@ -183,12 +182,12 @@ func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32
return return
} }
func ProcessPrng(buf []byte) (err error) { func RtlGenRandom(buf []byte) (err error) {
var _p0 *byte var _p0 *byte
if len(buf) > 0 { if len(buf) > 0 {
_p0 = &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 { if r1 == 0 {
err = errnoErr(e1) err = errnoErr(e1)
} }

View File

@@ -127,8 +127,15 @@ var (
_WriteFile, _WriteFile,
_ stdFunction _ stdFunction
// Use ProcessPrng to generate cryptographically random data. // Use RtlGenRandom to generate cryptographically random data.
_ProcessPrng stdFunction // 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 // Load ntdll.dll manually during startup, otherwise Mingw
// links wrong printf function to cgo executable (see issue // links wrong printf function to cgo executable (see issue
@@ -146,10 +153,11 @@ var (
) )
var ( var (
bcryptprimitivesdll = [...]uint16{'b', 'c', 'r', 'y', 'p', 't', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 's', '.', 'd', 'l', 'l', 0} advapi32dll = [...]uint16{'a', 'd', 'v', 'a', 'p', 'i', '3', '2', '.', 'd', 'l', 'l', 0}
ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', '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} 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} 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 // Function to be called by windows CreateThread
@@ -263,11 +271,11 @@ func windows_QueryPerformanceFrequency() int64 {
} }
func loadOptionalSyscalls() { func loadOptionalSyscalls() {
bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll[:]) a32 := windowsLoadSystemLib(advapi32dll[:])
if bcryptPrimitives == 0 { if a32 == 0 {
throw("bcryptprimitives.dll not found") throw("advapi32.dll not found")
} }
_ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000")) _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000"))
n32 := windowsLoadSystemLib(ntdlldll[:]) n32 := windowsLoadSystemLib(ntdlldll[:])
if n32 == 0 { if n32 == 0 {
@@ -500,7 +508,7 @@ func osinit() {
//go:nosplit //go:nosplit
func readRandom(r []byte) int { func readRandom(r []byte) int {
n := 0 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) n = len(r)
} }
return n return n