Skip to content

Commit 7c840d4

Browse files
committed
crypto/rand: use BCryptGenRandom instead of CryptGenRandom on Windows
The existing function that is used is CryptGenRandom. This function and the whole underling API is deprecated. Use the function BCryptGenRandom from the new recommended API called "Cryptography API: Next Generation (CNG)". Fixes #33542
1 parent 4fda7dc commit 7c840d4

File tree

5 files changed

+35
-45
lines changed

5 files changed

+35
-45
lines changed

src/crypto/rand/rand.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import "io"
1414
// On Linux and FreeBSD, Reader uses getrandom(2) if available, /dev/urandom otherwise.
1515
// On OpenBSD, Reader uses getentropy(2).
1616
// On other Unix-like systems, Reader reads from /dev/urandom.
17-
// On Windows systems, Reader uses the CryptGenRandom API.
17+
// On Windows systems, Reader uses the BCryptGenRandom API.
1818
// On Wasm, Reader uses the Web Crypto API.
1919
var Reader io.Reader
2020

src/crypto/rand/rand_windows.go

+5-33
Original file line numberDiff line numberDiff line change
@@ -10,47 +10,19 @@ package rand
1010
import (
1111
"os"
1212
"sync"
13-
"sync/atomic"
1413
"syscall"
15-
"time"
1614
)
1715

18-
// Implemented by using Windows CryptoAPI 2.0.
16+
// Implemented by using the Cryptography Next Generation (CNG) API.
1917

2018
func init() { Reader = &rngReader{} }
2119

22-
// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
23-
type rngReader struct {
24-
used int32 // atomic; whether this rngReader has been used
25-
prov syscall.Handle
26-
mu sync.Mutex
27-
}
20+
type rngReader struct{}
2821

2922
func (r *rngReader) Read(b []byte) (n int, err error) {
30-
if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
31-
// First use of randomness. Start timer to warn about
32-
// being blocked on entropy not being available.
33-
t := time.AfterFunc(60*time.Second, warnBlocked)
34-
defer t.Stop()
35-
}
36-
r.mu.Lock()
37-
if r.prov == 0 {
38-
const provType = syscall.PROV_RSA_FULL
39-
const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
40-
err := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
41-
if err != nil {
42-
r.mu.Unlock()
43-
return 0, os.NewSyscallError("CryptAcquireContext", err)
44-
}
45-
}
46-
r.mu.Unlock()
47-
48-
if len(b) == 0 {
49-
return 0, nil
50-
}
51-
err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
23+
err = syscall.BCryptGenRandom(nil, &b[0], uint32(len(b)), syscall.BCRYPT_USE_SYSTEM_PREFERRED_RNG)
5224
if err != nil {
53-
return 0, os.NewSyscallError("CryptGenRandom", err)
25+
return 0, os.NewSyscallError("BCryptGenRandom", err)
5426
}
55-
return len(b), nil
27+
return int(uint32(len(b))), nil
5628
}

src/syscall/syscall_windows.go

+1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
234234
//sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW
235235
//sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext
236236
//sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom
237+
//sys BCryptGenRandom(algorithmhandle Handle, buf *uint16, buflen uint32, flags uint32) (err error) = bcrypt.BCryptGenRandom
237238
//sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW
238239
//sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW
239240
//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW

src/syscall/types_windows.go

+3
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ const (
241241
CRYPT_SILENT = 0x00000040
242242
CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x00000080
243243

244+
// bcrypt.h
245+
BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002
246+
244247
USAGE_MATCH_TYPE_AND = 0
245248
USAGE_MATCH_TYPE_OR = 1
246249

src/syscall/zsyscall_windows.go

+25-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)