Rework the read routines to keep the PRNG sources happy. These work

in units of crypto blocks, so must have adequate space to write.
This means needing to be careful about buffers and keeping track
of external read request length.

Approved by:	so (/dev/random blanket)
This commit is contained in:
markm 2015-07-13 08:38:21 +00:00
parent 610f9926f9
commit 054d3d8bb0

View File

@ -153,8 +153,8 @@ static int
randomdev_read(struct cdev *dev __unused, struct uio *uio, int flags)
{
uint8_t *random_buf;
int c, error;
ssize_t nbytes;
int error;
ssize_t read_len, total_read, c;
random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
random_alg_context.ra_pre_read();
@ -175,14 +175,24 @@ randomdev_read(struct cdev *dev __unused, struct uio *uio, int flags)
/* XXX: FIX!! Next line as an atomic operation? */
read_rate += (uio->uio_resid + sizeof(uint32_t))/sizeof(uint32_t);
#endif
nbytes = uio->uio_resid;
total_read = 0;
while (uio->uio_resid && !error) {
c = MIN(uio->uio_resid, PAGE_SIZE);
/* See the random_buf size requirements in the Yarrow/Fortuna code */
random_alg_context.ra_read(random_buf, c);
read_len = uio->uio_resid;
/*
* Belt-and-braces.
* Round up the read length to a crypto block size multiple,
* which is what the underlying generator is expecting.
* See the random_buf size requirements in the Yarrow/Fortuna code.
*/
read_len += RANDOM_BLOCKSIZE;
read_len -= read_len % RANDOM_BLOCKSIZE;
read_len = MIN(read_len, PAGE_SIZE);
random_alg_context.ra_read(random_buf, read_len);
c = MIN(uio->uio_resid, read_len);
error = uiomove(random_buf, c, uio);
total_read += c;
}
if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR) )
if (total_read != uio->uio_resid && (error == ERESTART || error == EINTR) )
/* Return partial read, not error. */
error = 0;
}
@ -212,6 +222,13 @@ read_random(void *random_buf, u_int len)
read_rate += (len + sizeof(uint32_t))/sizeof(uint32_t);
#endif
read_len = len;
/*
* Belt-and-braces.
* Round up the read length to a crypto block size multiple,
* which is what the underlying generator is expecting.
*/
read_len += RANDOM_BLOCKSIZE;
read_len -= read_len % RANDOM_BLOCKSIZE;
total_read = 0;
while (read_len) {
c = MIN(read_len, PAGE_SIZE);