1// Copyright 2014 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//go:build dragonfly || freebsd || linux || solaris 6 7package rand 8 9import ( 10 "internal/syscall/unix" 11 "runtime" 12 "syscall" 13) 14 15func init() { 16 var maxGetRandomRead int 17 switch runtime.GOOS { 18 case "linux", "android": 19 // Per the manpage: 20 // When reading from the urandom source, a maximum of 33554431 bytes 21 // is returned by a single call to getrandom() on systems where int 22 // has a size of 32 bits. 23 maxGetRandomRead = (1 << 25) - 1 24 case "dragonfly", "freebsd", "illumos", "solaris": 25 maxGetRandomRead = 1 << 8 26 default: 27 panic("no maximum specified for GetRandom") 28 } 29 altGetRandom = batched(getRandom, maxGetRandomRead) 30} 31 32// If the kernel is too old to support the getrandom syscall(), 33// unix.GetRandom will immediately return ENOSYS and we will then fall back to 34// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS 35// result so we only suffer the syscall overhead once in this case. 36// If the kernel supports the getrandom() syscall, unix.GetRandom will block 37// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK). 38// In this case, unix.GetRandom will not return an error. 39func getRandom(p []byte) error { 40 n, err := unix.GetRandom(p, 0) 41 if err != nil { 42 return err 43 } 44 if n != len(p) { 45 return syscall.EIO 46 } 47 return nil 48} 49