Source file src/crypto/rand/rand_getrandom.go
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 7 package rand 8 9 import ( 10 "internal/syscall/unix" 11 "runtime" 12 "syscall" 13 ) 14 15 func 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. 39 func 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