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  

View as plain text