Optimise the buffer-size calculation. It was possible to get one block too many.

Approved by:	so (/dev/random blanket)
This commit is contained in:
Mark Murray 2015-07-19 16:05:23 +00:00
parent a612bbfa12
commit 95b184a048
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285690

View File

@ -64,6 +64,9 @@ __FBSDID("$FreeBSD$");
#define RANDOM_UNIT 0
/* Return the largest number >= x that is a multiple of m */
#define CEIL_TO_MULTIPLE(x, m) ((((x) + (m) - 1)/(m))*(m))
static d_read_t randomdev_read;
static d_write_t randomdev_write;
static d_poll_t randomdev_poll;
@ -191,15 +194,15 @@ read_random_uio(struct uio *uio, bool nonblock)
* 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 = CEIL_TO_MULTIPLE(read_len, RANDOM_BLOCKSIZE);
/* Work in chunks page-sized or less */
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 (total_read != uio->uio_resid && (error == ERESTART || error == EINTR) )
if (total_read != uio->uio_resid && (error == ERESTART || error == EINTR))
/* Return partial read, not error. */
error = 0;
}
@ -217,7 +220,7 @@ read_random_uio(struct uio *uio, bool nonblock)
u_int
read_random(void *random_buf, u_int len)
{
u_int read_len, total_read, c;
u_int read_len;
uint8_t local_buf[len + RANDOM_BLOCKSIZE];
KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__));
@ -228,22 +231,16 @@ read_random(void *random_buf, u_int len)
/* XXX: FIX!! Next line as an atomic operation? */
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);
random_alg_context.ra_read(&local_buf[total_read], c);
read_len -= c;
total_read += c;
if (len > 0) {
/*
* Belt-and-braces.
* Round up the read length to a crypto block size multiple,
* which is what the underlying generator is expecting.
*/
read_len = CEIL_TO_MULTIPLE(len, RANDOM_BLOCKSIZE);
random_alg_context.ra_read(local_buf, read_len);
memcpy(random_buf, local_buf, len);
}
memcpy(random_buf, local_buf, len);
} else
len = 0;
return (len);