crypto/rand for Windows

R=rsc, brainman
CC=golang-dev
https://golang.org/cl/1773041
diff --git a/src/pkg/crypto/rand/Makefile b/src/pkg/crypto/rand/Makefile
index 0e7a553..2181259 100644
--- a/src/pkg/crypto/rand/Makefile
+++ b/src/pkg/crypto/rand/Makefile
@@ -9,4 +9,21 @@
 GOFILES=\
 	rand.go\
 
+GOFILES_freebsd=\
+	rand_unix.go\
+
+GOFILES_darwin=\
+	rand_unix.go\
+
+GOFILES_linux=\
+	rand_unix.go\
+
+GOFILES_nacl=\
+	rand_unix.go\
+
+GOFILES_windows=\
+	rand_windows.go\
+
+GOFILES+=$(GOFILES_$(GOOS))
+
 include ../../../Make.pkg
diff --git a/src/pkg/crypto/rand/rand.go b/src/pkg/crypto/rand/rand.go
index 01c3031..42d9da0 100644
--- a/src/pkg/crypto/rand/rand.go
+++ b/src/pkg/crypto/rand/rand.go
@@ -7,124 +7,15 @@
 package rand
 
 import (
-	"crypto/aes"
 	"io"
 	"os"
-	"sync"
-	"time"
 )
 
 // Reader is a global, shared instance of a cryptographically
 // strong pseudo-random generator.
+// On Unix-like systems, Reader reads from /dev/urandom.
+// On Windows systems, Reader uses the CryptGenRandom API.
 var Reader io.Reader
 
 // Read is a helper function that calls Reader.Read.
 func Read(b []byte) (n int, err os.Error) { return Reader.Read(b) }
-
-// Easy implementation: read from /dev/urandom.
-// This is sufficient on Linux, OS X, and FreeBSD.
-
-func init() { Reader = &devReader{name: "/dev/urandom"} }
-
-// A devReader satisfies reads by reading the file named name.
-type devReader struct {
-	name string
-	f    *os.File
-	mu   sync.Mutex
-}
-
-func (r *devReader) Read(b []byte) (n int, err os.Error) {
-	r.mu.Lock()
-	if r.f == nil {
-		f, err := os.Open(r.name, os.O_RDONLY, 0)
-		if f == nil {
-			return 0, err
-		}
-		r.f = f
-	}
-	r.mu.Unlock()
-	return r.f.Read(b)
-}
-
-// Alternate pseudo-random implementation for use on
-// systems without a reliable /dev/urandom.  So far we
-// haven't needed it.
-
-// newReader returns a new pseudorandom generator that
-// seeds itself by reading from entropy.  If entropy == nil,
-// the generator seeds itself by reading from the system's
-// random number generator, typically /dev/random.
-// The Read method on the returned reader always returns
-// the full amount asked for, or else it returns an error.
-//
-// The generator uses the X9.31 algorithm with AES-128,
-// reseeding after every 1 MB of generated data.
-func newReader(entropy io.Reader) io.Reader {
-	if entropy == nil {
-		entropy = &devReader{name: "/dev/random"}
-	}
-	return &reader{entropy: entropy}
-}
-
-type reader struct {
-	mu                   sync.Mutex
-	budget               int // number of bytes that can be generated
-	cipher               *aes.Cipher
-	entropy              io.Reader
-	time, seed, dst, key [aes.BlockSize]byte
-}
-
-func (r *reader) Read(b []byte) (n int, err os.Error) {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-	n = len(b)
-
-	for len(b) > 0 {
-		if r.budget == 0 {
-			_, err := io.ReadFull(r.entropy, r.seed[0:])
-			if err != nil {
-				return n - len(b), err
-			}
-			_, err = io.ReadFull(r.entropy, r.key[0:])
-			if err != nil {
-				return n - len(b), err
-			}
-			r.cipher, err = aes.NewCipher(r.key[0:])
-			if err != nil {
-				return n - len(b), err
-			}
-			r.budget = 1 << 20 // reseed after generating 1MB
-		}
-		r.budget -= aes.BlockSize
-
-		// ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES.
-		//
-		// single block:
-		// t = encrypt(time)
-		// dst = encrypt(t^seed)
-		// seed = encrypt(t^dst)
-		ns := time.Nanoseconds()
-		r.time[0] = byte(ns >> 56)
-		r.time[1] = byte(ns >> 48)
-		r.time[2] = byte(ns >> 40)
-		r.time[3] = byte(ns >> 32)
-		r.time[4] = byte(ns >> 24)
-		r.time[5] = byte(ns >> 16)
-		r.time[6] = byte(ns >> 8)
-		r.time[7] = byte(ns)
-		r.cipher.Encrypt(r.time[0:], r.time[0:])
-		for i := 0; i < aes.BlockSize; i++ {
-			r.dst[i] = r.time[i] ^ r.seed[i]
-		}
-		r.cipher.Encrypt(r.dst[0:], r.dst[0:])
-		for i := 0; i < aes.BlockSize; i++ {
-			r.seed[i] = r.time[i] ^ r.dst[i]
-		}
-		r.cipher.Encrypt(r.seed[0:], r.seed[0:])
-
-		m := copy(b, r.dst[0:])
-		b = b[m:]
-	}
-
-	return n, nil
-}
diff --git a/src/pkg/crypto/rand/rand_unix.go b/src/pkg/crypto/rand/rand_unix.go
new file mode 100644
index 0000000..d8db6f2
--- /dev/null
+++ b/src/pkg/crypto/rand/rand_unix.go
@@ -0,0 +1,124 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Unix cryptographically secure pseudorandom number
+// generator.
+
+package rand
+
+import (
+	"crypto/aes"
+	"io"
+	"os"
+	"sync"
+	"time"
+)
+
+// Easy implementation: read from /dev/urandom.
+// This is sufficient on Linux, OS X, and FreeBSD.
+
+func init() { Reader = &devReader{name: "/dev/urandom"} }
+
+// A devReader satisfies reads by reading the file named name.
+type devReader struct {
+	name string
+	f    *os.File
+	mu   sync.Mutex
+}
+
+func (r *devReader) Read(b []byte) (n int, err os.Error) {
+	r.mu.Lock()
+	if r.f == nil {
+		f, err := os.Open(r.name, os.O_RDONLY, 0)
+		if f == nil {
+			return 0, err
+		}
+		r.f = f
+	}
+	r.mu.Unlock()
+	return r.f.Read(b)
+}
+
+// Alternate pseudo-random implementation for use on
+// systems without a reliable /dev/urandom.  So far we
+// haven't needed it.
+
+// newReader returns a new pseudorandom generator that
+// seeds itself by reading from entropy.  If entropy == nil,
+// the generator seeds itself by reading from the system's
+// random number generator, typically /dev/random.
+// The Read method on the returned reader always returns
+// the full amount asked for, or else it returns an error.
+//
+// The generator uses the X9.31 algorithm with AES-128,
+// reseeding after every 1 MB of generated data.
+func newReader(entropy io.Reader) io.Reader {
+	if entropy == nil {
+		entropy = &devReader{name: "/dev/random"}
+	}
+	return &reader{entropy: entropy}
+}
+
+type reader struct {
+	mu                   sync.Mutex
+	budget               int // number of bytes that can be generated
+	cipher               *aes.Cipher
+	entropy              io.Reader
+	time, seed, dst, key [aes.BlockSize]byte
+}
+
+func (r *reader) Read(b []byte) (n int, err os.Error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	n = len(b)
+
+	for len(b) > 0 {
+		if r.budget == 0 {
+			_, err := io.ReadFull(r.entropy, r.seed[0:])
+			if err != nil {
+				return n - len(b), err
+			}
+			_, err = io.ReadFull(r.entropy, r.key[0:])
+			if err != nil {
+				return n - len(b), err
+			}
+			r.cipher, err = aes.NewCipher(r.key[0:])
+			if err != nil {
+				return n - len(b), err
+			}
+			r.budget = 1 << 20 // reseed after generating 1MB
+		}
+		r.budget -= aes.BlockSize
+
+		// ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES.
+		//
+		// single block:
+		// t = encrypt(time)
+		// dst = encrypt(t^seed)
+		// seed = encrypt(t^dst)
+		ns := time.Nanoseconds()
+		r.time[0] = byte(ns >> 56)
+		r.time[1] = byte(ns >> 48)
+		r.time[2] = byte(ns >> 40)
+		r.time[3] = byte(ns >> 32)
+		r.time[4] = byte(ns >> 24)
+		r.time[5] = byte(ns >> 16)
+		r.time[6] = byte(ns >> 8)
+		r.time[7] = byte(ns)
+		r.cipher.Encrypt(r.time[0:], r.time[0:])
+		for i := 0; i < aes.BlockSize; i++ {
+			r.dst[i] = r.time[i] ^ r.seed[i]
+		}
+		r.cipher.Encrypt(r.dst[0:], r.dst[0:])
+		for i := 0; i < aes.BlockSize; i++ {
+			r.seed[i] = r.time[i] ^ r.dst[i]
+		}
+		r.cipher.Encrypt(r.seed[0:], r.seed[0:])
+
+		m := copy(b, r.dst[0:])
+		b = b[m:]
+	}
+
+	return n, nil
+}
diff --git a/src/pkg/crypto/rand/rand_windows.go b/src/pkg/crypto/rand/rand_windows.go
new file mode 100755
index 0000000..9bab2cb
--- /dev/null
+++ b/src/pkg/crypto/rand/rand_windows.go
@@ -0,0 +1,42 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Windows cryptographically secure pseudorandom number
+// generator.
+
+package rand
+
+import (
+	"os"
+	"sync"
+	"syscall"
+)
+
+// Implemented by using Windows CryptoAPI 2.0.
+
+func init() { Reader = &rngReader{} }
+
+// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
+type rngReader struct {
+	prov uint32
+	mu   sync.Mutex
+}
+
+func (r *rngReader) Read(b []byte) (n int, err os.Error) {
+	r.mu.Lock()
+	if r.prov == 0 {
+		const provType = syscall.PROV_RSA_FULL
+		const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
+		ok, errno := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
+		if !ok {
+			return 0, os.NewSyscallError("CryptAcquireContext", errno)
+		}
+	}
+	r.mu.Unlock()
+	ok, errno := syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
+	if !ok {
+		return 0, os.NewSyscallError("CryptGenRandom", errno)
+	}
+	return len(b), nil
+}
diff --git a/src/pkg/crypto/rsa/pkcs1v15_test.go b/src/pkg/crypto/rsa/pkcs1v15_test.go
index bfc12be..9a4da23 100644
--- a/src/pkg/crypto/rsa/pkcs1v15_test.go
+++ b/src/pkg/crypto/rsa/pkcs1v15_test.go
@@ -7,10 +7,10 @@
 import (
 	"big"
 	"bytes"
+	"crypto/rand"
 	"crypto/sha1"
 	"encoding/base64"
 	"encoding/hex"
-	"os"
 	"io"
 	"testing"
 	"testing/quick"
@@ -63,10 +63,7 @@
 }
 
 func TestEncryptPKCS1v15(t *testing.T) {
-	urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0)
-	if err != nil {
-		t.Errorf("Failed to open /dev/urandom")
-	}
+	random := rand.Reader
 	k := (rsaPrivateKey.N.BitLen() + 7) / 8
 
 	tryEncryptDecrypt := func(in []byte, blind bool) bool {
@@ -74,7 +71,7 @@
 			in = in[0 : k-11]
 		}
 
-		ciphertext, err := EncryptPKCS1v15(urandom, &rsaPrivateKey.PublicKey, in)
+		ciphertext, err := EncryptPKCS1v15(random, &rsaPrivateKey.PublicKey, in)
 		if err != nil {
 			t.Errorf("error encrypting: %s", err)
 			return false
@@ -84,7 +81,7 @@
 		if !blind {
 			rand = nil
 		} else {
-			rand = urandom
+			rand = random
 		}
 		plaintext, err := DecryptPKCS1v15(rand, rsaPrivateKey, ciphertext)
 		if err != nil {
@@ -137,13 +134,10 @@
 }
 
 func TestNonZeroRandomBytes(t *testing.T) {
-	urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0)
-	if err != nil {
-		t.Errorf("Failed to open /dev/urandom")
-	}
+	random := rand.Reader
 
 	b := make([]byte, 512)
-	err = nonZeroRandomBytes(b, urandom)
+	err := nonZeroRandomBytes(b, random)
 	if err != nil {
 		t.Errorf("returned error: %s", err)
 	}
diff --git a/src/pkg/crypto/rsa/rsa_test.go b/src/pkg/crypto/rsa/rsa_test.go
index 1721739..66c2445 100644
--- a/src/pkg/crypto/rsa/rsa_test.go
+++ b/src/pkg/crypto/rsa/rsa_test.go
@@ -7,18 +7,15 @@
 import (
 	"big"
 	"bytes"
+	"crypto/rand"
 	"crypto/sha1"
-	"os"
 	"testing"
 )
 
 func TestKeyGeneration(t *testing.T) {
-	urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0)
-	if err != nil {
-		t.Errorf("failed to open /dev/urandom")
-	}
+	random := rand.Reader
 
-	priv, err := GenerateKey(urandom, 1024)
+	priv, err := GenerateKey(random, 1024)
 	if err != nil {
 		t.Errorf("failed to generate key")
 	}
@@ -33,7 +30,7 @@
 		t.Errorf("got:%v, want:%v (%s)", m2, m, priv)
 	}
 
-	m3, err := decrypt(urandom, priv, c)
+	m3, err := decrypt(random, priv, c)
 	if err != nil {
 		t.Errorf("error while decrypting (blind): %s", err)
 	}
@@ -76,10 +73,7 @@
 }
 
 func TestDecryptOAEP(t *testing.T) {
-	urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0)
-	if err != nil {
-		t.Errorf("Failed to open /dev/urandom")
-	}
+	random := rand.Reader
 
 	sha1 := sha1.New()
 	n := new(big.Int)
@@ -98,7 +92,7 @@
 			}
 
 			// Decrypt with blinding.
-			out, err = DecryptOAEP(sha1, urandom, &private, message.out, nil)
+			out, err = DecryptOAEP(sha1, random, &private, message.out, nil)
 			if err != nil {
 				t.Errorf("#%d,%d (blind) error: %s", i, j, err)
 			} else if bytes.Compare(out, message.in) != 0 {
diff --git a/src/pkg/crypto/x509/x509_test.go b/src/pkg/crypto/x509/x509_test.go
index 23ce1ad..fa87fe2 100644
--- a/src/pkg/crypto/x509/x509_test.go
+++ b/src/pkg/crypto/x509/x509_test.go
@@ -6,10 +6,10 @@
 
 import (
 	"big"
+	"crypto/rand"
 	"crypto/rsa"
 	"encoding/hex"
 	"encoding/pem"
-	"os"
 	"reflect"
 	"testing"
 	"time"
@@ -145,10 +145,7 @@
 	"36dcd585d6ace53f546f961e05af"
 
 func TestCreateSelfSignedCertificate(t *testing.T) {
-	urandom, err := os.Open("/dev/urandom", os.O_RDONLY, 0)
-	if err != nil {
-		t.Errorf("failed to open /dev/urandom")
-	}
+	random := rand.Reader
 
 	block, _ := pem.Decode([]byte(pemPrivateKey))
 	priv, err := ParsePKCS1PrivateKey(block.Bytes)
@@ -174,7 +171,7 @@
 		DNSNames:              []string{"test.example.com"},
 	}
 
-	derBytes, err := CreateCertificate(urandom, &template, &template, &priv.PublicKey, priv)
+	derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
 	if err != nil {
 		t.Errorf("Failed to create certificate: %s", err)
 		return
diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go
index 86badb8..a7f03ad 100644
--- a/src/pkg/syscall/syscall_windows.go
+++ b/src/pkg/syscall/syscall_windows.go
@@ -132,6 +132,9 @@
 //sys	CreateIoCompletionPort(filehandle int32, cphandle int32, key uint32, threadcnt uint32) (handle int32, errno int)
 //sys	GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (ok bool, errno int)
 //sys	GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) = GetTempPathW
+//sys	CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) = advapi32.CryptAcquireContextW
+//sys	CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) = advapi32.CryptReleaseContext
+//sys	CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno int) = advapi32.CryptGenRandom
 
 // syscall interface implementation for other packages
 
diff --git a/src/pkg/syscall/zsyscall_windows_386.go b/src/pkg/syscall/zsyscall_windows_386.go
index be5dd03..55f2673 100644
--- a/src/pkg/syscall/zsyscall_windows_386.go
+++ b/src/pkg/syscall/zsyscall_windows_386.go
@@ -7,6 +7,7 @@
 
 var (
 	modkernel32 = loadDll("kernel32.dll")
+	modadvapi32 = loadDll("advapi32.dll")
 	modwsock32  = loadDll("wsock32.dll")
 	modws2_32   = loadDll("ws2_32.dll")
 
@@ -41,6 +42,9 @@
 	procCreateIoCompletionPort     = getSysProcAddr(modkernel32, "CreateIoCompletionPort")
 	procGetQueuedCompletionStatus  = getSysProcAddr(modkernel32, "GetQueuedCompletionStatus")
 	procGetTempPathW               = getSysProcAddr(modkernel32, "GetTempPathW")
+	procCryptAcquireContextW       = getSysProcAddr(modadvapi32, "CryptAcquireContextW")
+	procCryptReleaseContext        = getSysProcAddr(modadvapi32, "CryptReleaseContext")
+	procCryptGenRandom             = getSysProcAddr(modadvapi32, "CryptGenRandom")
 	procWSAStartup                 = getSysProcAddr(modwsock32, "WSAStartup")
 	procWSACleanup                 = getSysProcAddr(modwsock32, "WSACleanup")
 	procsocket                     = getSysProcAddr(modwsock32, "socket")
@@ -387,6 +391,39 @@
 	return
 }
 
+func CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) {
+	r0, _, e1 := Syscall6(procCryptAcquireContextW, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0)
+	ok = bool(r0 != 0)
+	if !ok {
+		errno = int(e1)
+	} else {
+		errno = 0
+	}
+	return
+}
+
+func CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) {
+	r0, _, e1 := Syscall(procCryptReleaseContext, uintptr(provhandle), uintptr(flags), 0)
+	ok = bool(r0 != 0)
+	if !ok {
+		errno = int(e1)
+	} else {
+		errno = 0
+	}
+	return
+}
+
+func CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno int) {
+	r0, _, e1 := Syscall(procCryptGenRandom, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf)))
+	ok = bool(r0 != 0)
+	if !ok {
+		errno = int(e1)
+	} else {
+		errno = 0
+	}
+	return
+}
+
 func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) {
 	r0, _, _ := Syscall(procWSAStartup, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
 	sockerrno = int(r0)
diff --git a/src/pkg/syscall/ztypes_windows_386.go b/src/pkg/syscall/ztypes_windows_386.go
index 315a8ac..4d35078 100644
--- a/src/pkg/syscall/ztypes_windows_386.go
+++ b/src/pkg/syscall/ztypes_windows_386.go
@@ -88,6 +88,34 @@
 	WAIT_TIMEOUT = 258
 )
 
+const (
+	// wincrypt.h
+	PROV_RSA_FULL                    = 1
+	PROV_RSA_SIG                     = 2
+	PROV_DSS                         = 3
+	PROV_FORTEZZA                    = 4
+	PROV_MS_EXCHANGE                 = 5
+	PROV_SSL                         = 6
+	PROV_RSA_SCHANNEL                = 12
+	PROV_DSS_DH                      = 13
+	PROV_EC_ECDSA_SIG                = 14
+	PROV_EC_ECNRA_SIG                = 15
+	PROV_EC_ECDSA_FULL               = 16
+	PROV_EC_ECNRA_FULL               = 17
+	PROV_DH_SCHANNEL                 = 18
+	PROV_SPYRUS_LYNKS                = 20
+	PROV_RNG                         = 21
+	PROV_INTEL_SEC                   = 22
+	PROV_REPLACE_OWF                 = 23
+	PROV_RSA_AES                     = 24
+	CRYPT_VERIFYCONTEXT              = 0xF0000000
+	CRYPT_NEWKEYSET                  = 0x00000008
+	CRYPT_DELETEKEYSET               = 0x00000010
+	CRYPT_MACHINE_KEYSET             = 0x00000020
+	CRYPT_SILENT                     = 0x00000040
+	CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x00000080
+)
+
 // Types
 
 type _C_short int16