Home | History | Annotate | Download | only in rand
      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 	"syscall"
     14 )
     15 
     16 // Implemented by using Windows CryptoAPI 2.0.
     17 
     18 func init() { Reader = &rngReader{} }
     19 
     20 // A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
     21 type rngReader struct {
     22 	prov syscall.Handle
     23 	mu   sync.Mutex
     24 }
     25 
     26 func (r *rngReader) Read(b []byte) (n int, err error) {
     27 	r.mu.Lock()
     28 	if r.prov == 0 {
     29 		const provType = syscall.PROV_RSA_FULL
     30 		const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
     31 		err := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
     32 		if err != nil {
     33 			r.mu.Unlock()
     34 			return 0, os.NewSyscallError("CryptAcquireContext", err)
     35 		}
     36 	}
     37 	r.mu.Unlock()
     38 
     39 	if len(b) == 0 {
     40 		return 0, nil
     41 	}
     42 	err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
     43 	if err != nil {
     44 		return 0, os.NewSyscallError("CryptGenRandom", err)
     45 	}
     46 	return len(b), nil
     47 }
     48