1+ diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go
2+ index 62738e2cb1a7d..d0dcc7cc71fc0 100644
3+ --- a/src/crypto/rand/rand.go
4+ +++ b/src/crypto/rand/rand.go
5+ @@ -15,7 +15,7 @@ import "io"
6+ // available, /dev/urandom otherwise.
7+ // On OpenBSD and macOS, Reader uses getentropy(2).
8+ // On other Unix-like systems, Reader reads from /dev/urandom.
9+ - // On Windows systems, Reader uses the RtlGenRandom API.
10+ + // On Windows systems, Reader uses the ProcessPrng API.
11+ // On JS/Wasm, Reader uses the Web Crypto API.
12+ // On WASIP1/Wasm, Reader uses random_get from wasi_snapshot_preview1.
13+ var Reader io.Reader
14+ diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go
15+ index 6c0655c72b692..7380f1f0f1e6e 100644
16+ --- a/src/crypto/rand/rand_windows.go
17+ +++ b/src/crypto/rand/rand_windows.go
18+ @@ -15,11 +15,8 @@ func init() { Reader = &rngReader{} }
19+
20+ type rngReader struct{}
21+
22+ - func (r *rngReader) Read(b []byte) (n int, err error) {
23+ - // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at
24+ - // most 1<<31-1 bytes at a time so that this works the same on 32-bit
25+ - // and 64-bit systems.
26+ - if err := batched(windows.RtlGenRandom, 1<<31-1)(b); err != nil {
27+ + func (r *rngReader) Read(b []byte) (int, error) {
28+ + if err := windows.ProcessPrng(b); err != nil {
29+ return 0, err
30+ }
31+ return len(b), nil
32+ diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go
33+ index ab4ad2ec64108..5854ca60b5cef 100644
34+ --- a/src/internal/syscall/windows/syscall_windows.go
35+ +++ b/src/internal/syscall/windows/syscall_windows.go
36+ @@ -373,7 +373,7 @@ func ErrorLoadingGetTempPath2() error {
37+ //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
38+ //sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW
39+
40+ - //sys RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036
41+ + //sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng
42+
43+ type FILE_ID_BOTH_DIR_INFO struct {
44+ NextEntryOffset uint32
45+ diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go
46+ index e3f6d8d2a2208..5a587ad4f146c 100644
47+ --- a/src/internal/syscall/windows/zsyscall_windows.go
48+ +++ b/src/internal/syscall/windows/zsyscall_windows.go
49+ @@ -37,13 +37,14 @@ func errnoErr(e syscall.Errno) error {
50+ }
51+
52+ var (
53+ - modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
54+ - modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
55+ - modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
56+ - modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
57+ - modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll"))
58+ - moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll"))
59+ - modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll"))
60+ + modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
61+ + modbcryptprimitives = syscall.NewLazyDLL(sysdll.Add("bcryptprimitives.dll"))
62+ + modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
63+ + modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
64+ + modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
65+ + modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll"))
66+ + moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll"))
67+ + modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll"))
68+
69+ procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
70+ procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx")
71+ @@ -55,7 +56,7 @@ var (
72+ procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus")
73+ procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
74+ procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation")
75+ - procSystemFunction036 = modadvapi32.NewProc("SystemFunction036")
76+ + procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng")
77+ procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
78+ procCreateEventW = modkernel32.NewProc("CreateEventW")
79+ procGetACP = modkernel32.NewProc("GetACP")
80+ @@ -179,12 +180,12 @@ func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32
81+ return
82+ }
83+
84+ - func RtlGenRandom(buf []byte) (err error) {
85+ + func ProcessPrng(buf []byte) (err error) {
86+ var _p0 *byte
87+ if len(buf) > 0 {
88+ _p0 = &buf[0]
89+ }
90+ - r1, _, e1 := syscall.Syscall(procSystemFunction036.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0)
91+ + r1, _, e1 := syscall.Syscall(procProcessPrng.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0)
92+ if r1 == 0 {
93+ err = errnoErr(e1)
94+ }
95+ diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
96+ index 8ca8d7790909e..3772a864b2ff4 100644
97+ --- a/src/runtime/os_windows.go
98+ +++ b/src/runtime/os_windows.go
99+ @@ -127,15 +127,8 @@ var (
100+ _WriteFile,
101+ _ stdFunction
102+
103+ - // Use RtlGenRandom to generate cryptographically random data.
104+ - // This approach has been recommended by Microsoft (see issue
105+ - // 15589 for details).
106+ - // The RtlGenRandom is not listed in advapi32.dll, instead
107+ - // RtlGenRandom function can be found by searching for SystemFunction036.
108+ - // Also some versions of Mingw cannot link to SystemFunction036
109+ - // when building executable as Cgo. So load SystemFunction036
110+ - // manually during runtime startup.
111+ - _RtlGenRandom stdFunction
112+ + // Use ProcessPrng to generate cryptographically random data.
113+ + _ProcessPrng stdFunction
114+
115+ // Load ntdll.dll manually during startup, otherwise Mingw
116+ // links wrong printf function to cgo executable (see issue
117+ @@ -151,11 +144,11 @@ var (
118+ )
119+
120+ var (
121+ - advapi32dll = [...]uint16{'a', 'd', 'v', 'a', 'p', 'i', '3', '2', '.', 'd', 'l', 'l', 0}
122+ - ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0}
123+ - powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0}
124+ - winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0}
125+ - ws2_32dll = [...]uint16{'w', 's', '2', '_', '3', '2', '.', 'd', 'l', 'l', 0}
126+ + bcryptprimitivesdll = [...]uint16{'b', 'c', 'r', 'y', 'p', 't', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 's', '.', 'd', 'l', 'l', 0}
127+ + ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0}
128+ + powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0}
129+ + winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0}
130+ + ws2_32dll = [...]uint16{'w', 's', '2', '_', '3', '2', '.', 'd', 'l', 'l', 0}
131+ )
132+
133+ // Function to be called by windows CreateThread
134+ @@ -251,11 +244,11 @@ func windowsLoadSystemLib(name []uint16) uintptr {
135+ }
136+
137+ func loadOptionalSyscalls() {
138+ - a32 := windowsLoadSystemLib(advapi32dll[:])
139+ - if a32 == 0 {
140+ - throw("advapi32.dll not found")
141+ + bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll[:])
142+ + if bcryptPrimitives == 0 {
143+ + throw("bcryptprimitives.dll not found")
144+ }
145+ - _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000"))
146+ + _ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000"))
147+
148+ n32 := windowsLoadSystemLib(ntdlldll[:])
149+ if n32 == 0 {
150+ @@ -531,7 +524,7 @@ func osinit() {
151+ //go:nosplit
152+ func readRandom(r []byte) int {
153+ n := 0
154+ - if stdcall2(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
155+ + if stdcall2(_ProcessPrng, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
156+ n = len(r)
157+ }
158+ return n
0 commit comments