summaryrefslogtreecommitdiffstats
path: root/sys/dev/random/randomdev.c
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2015-07-19 16:05:23 +0000
committermarkm <markm@FreeBSD.org>2015-07-19 16:05:23 +0000
commit3ed54293a28be84e3e5841a06f90394843e9b52d (patch)
tree808d52d87730a039d4790819cd20e8c656ebae58 /sys/dev/random/randomdev.c
parent8672831bb490f98611d0eafad6252403cd7b5618 (diff)
downloadFreeBSD-src-3ed54293a28be84e3e5841a06f90394843e9b52d.zip
FreeBSD-src-3ed54293a28be84e3e5841a06f90394843e9b52d.tar.gz
Optimise the buffer-size calculation. It was possible to get one block too many.
Approved by: so (/dev/random blanket)
Diffstat (limited to 'sys/dev/random/randomdev.c')
-rw-r--r--sys/dev/random/randomdev.c35
1 files changed, 16 insertions, 19 deletions
diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c
index 43f905e..8a12777 100644
--- a/sys/dev/random/randomdev.c
+++ b/sys/dev/random/randomdev.c
@@ -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);
OpenPOWER on IntegriCloud