Black Lives Matter. Support the Equal Justice Initiative.

Source file src/crypto/rand/rand_batched.go

Documentation: crypto/rand

     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 linux || freebsd || dragonfly || solaris
     6  // +build linux freebsd dragonfly solaris
     7  
     8  package rand
     9  
    10  import (
    11  	"internal/syscall/unix"
    12  )
    13  
    14  // maxGetRandomRead is platform dependent.
    15  func init() {
    16  	altGetRandom = batched(getRandomBatch, maxGetRandomRead)
    17  }
    18  
    19  // batched returns a function that calls f to populate a []byte by chunking it
    20  // into subslices of, at most, readMax bytes.
    21  func batched(f func([]byte) bool, readMax int) func([]byte) bool {
    22  	return func(buf []byte) bool {
    23  		for len(buf) > readMax {
    24  			if !f(buf[:readMax]) {
    25  				return false
    26  			}
    27  			buf = buf[readMax:]
    28  		}
    29  		return len(buf) == 0 || f(buf)
    30  	}
    31  }
    32  
    33  // If the kernel is too old to support the getrandom syscall(),
    34  // unix.GetRandom will immediately return ENOSYS and we will then fall back to
    35  // reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS
    36  // result so we only suffer the syscall overhead once in this case.
    37  // If the kernel supports the getrandom() syscall, unix.GetRandom will block
    38  // until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK).
    39  // In this case, unix.GetRandom will not return an error.
    40  func getRandomBatch(p []byte) (ok bool) {
    41  	n, err := unix.GetRandom(p, 0)
    42  	return n == len(p) && err == nil
    43  }
    44  

View as plain text