runtime: clean up & go-ify the hash function seeder
Change-Id: I0e95f8a5962c547da20e19a356ae1cf8375c9107
Reviewed-on: https://go-review.googlesource.com/1270
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/src/runtime/alg.go b/src/runtime/alg.go
index e367bc5..6e53f81 100644
--- a/src/runtime/alg.go
+++ b/src/runtime/alg.go
@@ -332,18 +332,6 @@
algarray[alg_MEM128].hash = aeshash
algarray[alg_STRING].hash = aeshashstr
// Initialize with random data so hash collisions will be hard to engineer.
- var rnd unsafe.Pointer
- var n int32
- get_random_data(&rnd, &n)
- if n > hashRandomBytes {
- n = hashRandomBytes
- }
- memmove(unsafe.Pointer(&aeskeysched[0]), rnd, uintptr(n))
- if n < hashRandomBytes {
- // Not very random, but better than nothing.
- for t := nanotime(); n < hashRandomBytes; n++ {
- aeskeysched[n] = byte(t >> uint(8*(n%8)))
- }
- }
+ getRandomData(aeskeysched[:])
}
}
diff --git a/src/runtime/os1_darwin.go b/src/runtime/os1_darwin.go
index 2fbf2ca..12642aa 100644
--- a/src/runtime/os1_darwin.go
+++ b/src/runtime/os1_darwin.go
@@ -45,20 +45,14 @@
}
}
-var urandom_data [_HashRandomBytes]byte
var urandom_dev = []byte("/dev/random\x00")
//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+func getRandomData(r []byte) {
fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
- if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
- *rnd = unsafe.Pointer(&urandom_data[0])
- *rnd_len = _HashRandomBytes
- } else {
- *rnd = nil
- *rnd_len = 0
- }
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
close(fd)
+ extendRandom(r, int(n))
}
func goenvs() {
diff --git a/src/runtime/os1_dragonfly.go b/src/runtime/os1_dragonfly.go
index 82bb45b..d02e925 100644
--- a/src/runtime/os1_dragonfly.go
+++ b/src/runtime/os1_dragonfly.go
@@ -97,20 +97,14 @@
ncpu = getncpu()
}
-var urandom_data [_HashRandomBytes]byte
var urandom_dev = []byte("/dev/urandom\x00")
//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+func getRandomData(r []byte) {
fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
- if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
- *rnd = unsafe.Pointer(&urandom_data[0])
- *rnd_len = _HashRandomBytes
- } else {
- *rnd = nil
- *rnd_len = 0
- }
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
close(fd)
+ extendRandom(r, int(n))
}
func goenvs() {
diff --git a/src/runtime/os1_freebsd.go b/src/runtime/os1_freebsd.go
index 2cacfba..80e4532 100644
--- a/src/runtime/os1_freebsd.go
+++ b/src/runtime/os1_freebsd.go
@@ -96,20 +96,14 @@
ncpu = getncpu()
}
-var urandom_data [_HashRandomBytes]byte
var urandom_dev = []byte("/dev/random\x00")
//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+func getRandomData(r []byte) {
fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
- if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
- *rnd = unsafe.Pointer(&urandom_data[0])
- *rnd_len = _HashRandomBytes
- } else {
- *rnd = nil
- *rnd_len = 0
- }
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
close(fd)
+ extendRandom(r, int(n))
}
func goenvs() {
diff --git a/src/runtime/os1_linux.go b/src/runtime/os1_linux.go
index 67fa639..2e12d74 100644
--- a/src/runtime/os1_linux.go
+++ b/src/runtime/os1_linux.go
@@ -145,30 +145,18 @@
ncpu = getproccount()
}
-// Random bytes initialized at startup. These come
-// from the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.c).
-// byte* runtime·startup_random_data;
-// uint32 runtime·startup_random_data_len;
-
-var urandom_data [_HashRandomBytes]byte
var urandom_dev = []byte("/dev/random\x00")
-//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
- if startup_random_data != nil {
- *rnd = unsafe.Pointer(startup_random_data)
- *rnd_len = int32(startup_random_data_len)
+func getRandomData(r []byte) {
+ if startupRandomData != nil {
+ n := copy(r, startupRandomData)
+ extendRandom(r, n)
return
}
fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
- if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
- *rnd = unsafe.Pointer(&urandom_data[0])
- *rnd_len = _HashRandomBytes
- } else {
- *rnd = nil
- *rnd_len = 0
- }
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
close(fd)
+ extendRandom(r, int(n))
}
func goenvs() {
diff --git a/src/runtime/os1_netbsd.go b/src/runtime/os1_netbsd.go
index 493be30..b506862 100644
--- a/src/runtime/os1_netbsd.go
+++ b/src/runtime/os1_netbsd.go
@@ -170,20 +170,14 @@
ncpu = getncpu()
}
-var urandom_data [_HashRandomBytes]byte
var urandom_dev = []byte("/dev/urandom\x00")
//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+func getRandomData(r []byte) {
fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
- if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
- *rnd = unsafe.Pointer(&urandom_data[0])
- *rnd_len = _HashRandomBytes
- } else {
- *rnd = nil
- *rnd_len = 0
- }
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
close(fd)
+ extendRandom(r, int(n))
}
func goenvs() {
diff --git a/src/runtime/os1_openbsd.go b/src/runtime/os1_openbsd.go
index d5ffe10..b1a16d5 100644
--- a/src/runtime/os1_openbsd.go
+++ b/src/runtime/os1_openbsd.go
@@ -138,20 +138,14 @@
ncpu = getncpu()
}
-var urandom_data [_HashRandomBytes]byte
var urandom_dev = []byte("/dev/urandom\x00")
//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+func getRandomData(r []byte) {
fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
- if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
- *rnd = unsafe.Pointer(&urandom_data[0])
- *rnd_len = _HashRandomBytes
- } else {
- *rnd = nil
- *rnd_len = 0
- }
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
close(fd)
+ extendRandom(r, int(n))
}
func goenvs() {
diff --git a/src/runtime/os1_plan9.go b/src/runtime/os1_plan9.go
index 0f8da03..9581f0c 100644
--- a/src/runtime/os1_plan9.go
+++ b/src/runtime/os1_plan9.go
@@ -85,20 +85,14 @@
*(*int)(nil) = 0
}
-var random_data [_HashRandomBytes]byte
var random_dev = []byte("/dev/random\x00")
//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+func getRandomData(r []byte) {
fd := open(&random_dev[0], 0 /* O_RDONLY */, 0)
- if read(fd, unsafe.Pointer(&random_data), _HashRandomBytes) == _HashRandomBytes {
- *rnd = unsafe.Pointer(&random_data[0])
- *rnd_len = _HashRandomBytes
- } else {
- *rnd = nil
- *rnd_len = 0
- }
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
close(fd)
+ extendRandom(r, int(n))
}
func goenvs() {
diff --git a/src/runtime/os1_windows.go b/src/runtime/os1_windows.go
index 57ea050..a78eeac 100644
--- a/src/runtime/os1_windows.go
+++ b/src/runtime/os1_windows.go
@@ -148,24 +148,21 @@
}
}
-var random_data [_HashRandomBytes]byte
-
//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+func getRandomData(r []byte) {
const (
prov_rsa_full = 1
crypt_verifycontext = 0xF0000000
)
var handle uintptr
- *rnd = nil
- *rnd_len = 0
+ n := 0
if stdcall5(_CryptAcquireContextW, uintptr(unsafe.Pointer(&handle)), 0, 0, prov_rsa_full, crypt_verifycontext) != 0 {
- if stdcall3(_CryptGenRandom, handle, _HashRandomBytes, uintptr(unsafe.Pointer(&random_data[0]))) != 0 {
- *rnd = unsafe.Pointer(&random_data[0])
- *rnd_len = _HashRandomBytes
+ if stdcall3(_CryptGenRandom, handle, uintptr(len(r)), uintptr(unsafe.Pointer(&r[0]))) != 0 {
+ n = len(r)
}
stdcall2(_CryptReleaseContext, handle, 0)
}
+ extendRandom(r, n)
}
func goenvs() {
diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go
index 1df74fa..6ccbbe2 100644
--- a/src/runtime/os3_solaris.go
+++ b/src/runtime/os3_solaris.go
@@ -165,20 +165,14 @@
}
}
-var urandom_data [_HashRandomBytes]byte
var urandom_dev = []byte("/dev/random\x00")
//go:nosplit
-func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+func getRandomData(r []byte) {
fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
- if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
- *rnd = unsafe.Pointer(&urandom_data[0])
- *rnd_len = _HashRandomBytes
- } else {
- *rnd = nil
- *rnd_len = 0
- }
+ n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
close(fd)
+ extendRandom(r, int(n))
}
func goenvs() {
diff --git a/src/runtime/os_linux_386.go b/src/runtime/os_linux_386.go
index adcd5a1..e2120da 100644
--- a/src/runtime/os_linux_386.go
+++ b/src/runtime/os_linux_386.go
@@ -29,8 +29,7 @@
_vdso = auxv[i+1]
case _AT_RANDOM:
- startup_random_data = (*byte)(unsafe.Pointer(uintptr(auxv[i+1])))
- startup_random_data_len = 16
+ startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))[:]
}
}
}
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index d18178d..e0d23e7 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -475,16 +475,33 @@
_Structrnd = regSize
)
-var startup_random_data *byte
-var startup_random_data_len uint32
+// startup_random_data holds random bytes initialized at startup. These come from
+// the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.go or os_linux_386.go).
+var startupRandomData []byte
+
+// extendRandom extends the random numbers in r[:n] to the whole slice r.
+// Treats n<0 as n==0.
+func extendRandom(r []byte, n int) {
+ if n < 0 {
+ n = 0
+ }
+ for n < len(r) {
+ // Extend random bits using hash function & time seed
+ w := n
+ if w > 16 {
+ w = 16
+ }
+ h := memhash(unsafe.Pointer(&r[n-w]), uintptr(w), uintptr(nanotime()))
+ for i := 0; i < ptrSize && n < len(r); i++ {
+ r[n] = byte(h)
+ n++
+ h >>= 8
+ }
+ }
+}
var invalidptr int32
-const (
- // hashinit wants this many random bytes
- _HashRandomBytes = 32
-)
-
/*
* deferred subroutine calls
*/
diff --git a/src/runtime/vdso_linux_amd64.go b/src/runtime/vdso_linux_amd64.go
index 7eb6988..2440015 100644
--- a/src/runtime/vdso_linux_amd64.go
+++ b/src/runtime/vdso_linux_amd64.go
@@ -321,8 +321,7 @@
vdso_parse_symbols(info1, vdso_find_version(info1, &linux26))
case _AT_RANDOM:
- startup_random_data = (*byte)(unsafe.Pointer(uintptr(av.a_val)))
- startup_random_data_len = 16
+ startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(av.a_val)))[:]
}
}
}