...
Source file src/pkg/crypto/rand/rand_windows.go
1
2
3
4
5
6
7
8 package rand
9
10 import (
11 "os"
12 "sync"
13 "sync/atomic"
14 "syscall"
15 "time"
16 )
17
18
19
20 func init() { Reader = &rngReader{} }
21
22
23 type rngReader struct {
24 used int32
25 prov syscall.Handle
26 mu sync.Mutex
27 }
28
29 func (r *rngReader) Read(b []byte) (n int, err error) {
30 if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
31
32
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])
52 if err != nil {
53 return 0, os.NewSyscallError("CryptGenRandom", err)
54 }
55 return len(b), nil
56 }
57
View as plain text