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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to