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 "errors" 11 "internal/syscall/unix" 12 "math" 13 "runtime" 14 "syscall" 15 ) 16 17 func read(b []byte) error { 18 // Linux, DragonFly, and illumos don't have a limit on the buffer size. 19 // FreeBSD has a limit of IOSIZE_MAX, which seems to be either INT_MAX or 20 // SSIZE_MAX. 2^31-1 is a safe and high enough value to use for all of them. 21 // 22 // Note that Linux returns "a maximum of 32Mi-1 bytes", but that will only 23 // result in a short read, not an error. Short reads can also happen above 24 // 256 bytes due to signals. Reads up to 256 bytes are guaranteed not to 25 // return short (and not to return an error IF THE POOL IS INITIALIZED) on 26 // at least Linux, FreeBSD, DragonFly, and Oracle Solaris, but we don't make 27 // use of that. 28 maxSize := math.MaxInt32 29 30 // Oracle Solaris has a limit of 133120 bytes. Very specific. 31 // 32 // The getrandom() and getentropy() functions fail if: [...] 33 // 34 // - bufsz is <= 0 or > 133120, when GRND_RANDOM is not set 35 // 36 // https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html 37 if runtime.GOOS == "solaris" { 38 maxSize = 133120 39 } 40 41 for len(b) > 0 { 42 size := len(b) 43 if size > maxSize { 44 size = maxSize 45 } 46 n, err := unix.GetRandom(b[:size], 0) 47 if errors.Is(err, syscall.ENOSYS) { 48 // If getrandom(2) is not available, presumably on Linux versions 49 // earlier than 3.17, fall back to reading from /dev/urandom. 50 return urandomRead(b) 51 } 52 if errors.Is(err, syscall.EINTR) { 53 // If getrandom(2) is blocking, either because it is waiting for the 54 // entropy pool to become initialized or because we requested more 55 // than 256 bytes, it might get interrupted by a signal. 56 continue 57 } 58 if err != nil { 59 return err 60 } 61 b = b[n:] 62 } 63 return nil 64 } 65