svn commit: r285690 - head/sys/dev/random
Mark Murray
markm at FreeBSD.org
Sun Jul 19 16:05:24 UTC 2015
Author: markm
Date: Sun Jul 19 16:05:23 2015
New Revision: 285690
URL: https://svnweb.freebsd.org/changeset/base/285690
Log:
Optimise the buffer-size calculation. It was possible to get one block too many.
Approved by: so (/dev/random blanket)
Modified:
head/sys/dev/random/randomdev.c
Modified: head/sys/dev/random/randomdev.c
==============================================================================
--- head/sys/dev/random/randomdev.c Sun Jul 19 15:44:51 2015 (r285689)
+++ head/sys/dev/random/randomdev.c Sun Jul 19 16:05:23 2015 (r285690)
@@ -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 no
* 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 no
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);
More information about the svn-src-all
mailing list