github.com/remobjects/goldbaselibrary@v0.0.0-20230924164425-d458680a936b/Source/Gold/crypto/rand/rand_windows.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Windows cryptographically secure pseudorandom number 6 // generator. 7 8 package rand 9 10 import ( 11 "os" 12 "sync" 13 "sync/atomic" 14 "syscall" 15 "time" 16 ) 17 18 // Implemented by using Windows CryptoAPI 2.0. 19 20 func init() { Reader = &rngReader{} } 21 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 } 28 29 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]) 52 if err != nil { 53 return 0, os.NewSyscallError("CryptGenRandom", err) 54 } 55 return len(b), nil 56 }