In READ_RANDOM_UIOAt a basic level, add a fast path to vslock() user pages of typicalremove assumptions about the underlying algorithm (such as
single-segment requests and generate intooutput block size and reseeding requirements) from them directly, instead of algorithm-independent
generating a single page at a time and copying out with uiomove().
Retain the old code as a fallback slow path if vslock() fails or the requeslogic in randomdev.c. Chacha20 does not have many of the restrictions that
isn't a single segment.
AddiAES-ICM does as a PRF (Pseudo-Random Functionally), adapt randomdev to take advantage of some of the benefits ofbecause it has a cipher
Chacha20 over the historical AES PRF implementationblock size of 256 bits. In the READ_RANDOM_UIOThe motivation is that by generalizing the API,
fast pathChacha is not penalized by the limitations of AES.
In READ_RANDOM_UIO, eliminate the arbitrary restriction of individual ra_read()first attempt to NOWAIT allocate a large enough buffer
invocations to PAGE_SIZE. Insteadfor the entire user request, limit ra_read() calls with the arbitraryor the maximal input we'll accept between
sigchk_period (16 MB)signal checking, whichever is left unchanged in this commit, to continuesmaller. The idea is that the implementation
allowing large /dev/random or getrandom(2) reads to be interruptedof any randomdev algorithm is then free to divide up large requests in
whatever fashion it sees fit.
As part of this, two responsibilities from the "algorithm-generic" randomdev
code are pushed down into the Fortuna ra_read implementation (and any other
future or out-of-tree ra_read implementations):
1. If an algorithm needs to rekey every N bytes, it is responsible for
handling that in ra_read(). (I.e., Fortuna's 1MB rekey interval for AES
block generation.)
2. If an algorithm uses a block cipher that doesn't tolerate partial-block
requests (again, e.g., AES), it is also responsible for handling that in
ra_read().
Several APIs are changed from u_int buffer length to the more canonical
size_t. Several APIs are changed from taking a blockcount to a bytecount,
to permit PRFs like Chacha20 to directly generate quantities of output that
are not multiples of RANDOM_BLOCKSIZE (AES block size).
The Fortuna algorithm is changed to NOT rekey every 1MiB when in Chacha20
mode (kern.random.use_chacha20_cipher="1"). This is explicitly supported by
the math in FS&K §9.4 (Ferguson, Schneier, and Kohno; "Cryptography
Engineering"), as well as by their conclusion: "If we had a block cipher
with a 256-bit block size, then the collisions would not have been an issue
at all."