]> Pileus Git - ~andy/linux/blobdiff - drivers/char/random.c
Merge remote-tracking branch 'regmap/topic/no-bus' into regmap-next
[~andy/linux] / drivers / char / random.c
index b86eae9b77dfaeb04dd2d4efefd6ebc01b9e0a93..85e81ec1451e38accca94d8dee9d4703ff614063 100644 (file)
@@ -399,7 +399,6 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 static struct fasync_struct *fasync;
 
-#if 0
 static bool debug;
 module_param(debug, bool, 0644);
 #define DEBUG_ENT(fmt, arg...) do { \
@@ -410,9 +409,6 @@ module_param(debug, bool, 0644);
                blocking_pool.entropy_count,\
                nonblocking_pool.entropy_count,\
                ## arg); } while (0)
-#else
-#define DEBUG_ENT(fmt, arg...) do {} while (0)
-#endif
 
 /**********************************************************************
  *
@@ -437,6 +433,7 @@ struct entropy_store {
        int entropy_count;
        int entropy_total;
        unsigned int initialized:1;
+       bool last_data_init;
        __u8 last_data[EXTRACT_SIZE];
 };
 
@@ -829,7 +826,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
                bytes = min_t(int, bytes, sizeof(tmp));
 
                DEBUG_ENT("going to reseed %s with %d bits "
-                         "(%d of %d requested)\n",
+                         "(%zu of %d requested)\n",
                          r->name, bytes * 8, nbytes * 8, r->entropy_count);
 
                bytes = extract_entropy(r->pull, tmp, bytes,
@@ -860,7 +857,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
        spin_lock_irqsave(&r->lock, flags);
 
        BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
-       DEBUG_ENT("trying to extract %d bits from %s\n",
+       DEBUG_ENT("trying to extract %zu bits from %s\n",
                  nbytes * 8, r->name);
 
        /* Can we pull enough? */
@@ -882,7 +879,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
                }
        }
 
-       DEBUG_ENT("debiting %d entropy credits from %s%s\n",
+       DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
                  nbytes * 8, r->name, r->limit ? "" : " (unlimited)");
 
        spin_unlock_irqrestore(&r->lock, flags);
@@ -957,6 +954,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
        ssize_t ret = 0, i;
        __u8 tmp[EXTRACT_SIZE];
 
+       /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */
+       if (fips_enabled && !r->last_data_init)
+               nbytes += EXTRACT_SIZE;
+
        trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
        xfer_secondary_pool(r, nbytes);
        nbytes = account(r, nbytes, min, reserved);
@@ -967,6 +968,17 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
                if (fips_enabled) {
                        unsigned long flags;
 
+
+                       /* prime last_data value if need be, per fips 140-2 */
+                       if (!r->last_data_init) {
+                               spin_lock_irqsave(&r->lock, flags);
+                               memcpy(r->last_data, tmp, EXTRACT_SIZE);
+                               r->last_data_init = true;
+                               nbytes -= EXTRACT_SIZE;
+                               spin_unlock_irqrestore(&r->lock, flags);
+                               extract_buf(r, tmp);
+                       }
+
                        spin_lock_irqsave(&r->lock, flags);
                        if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
                                panic("Hardware RNG duplicated output!\n");
@@ -1086,6 +1098,7 @@ static void init_std_data(struct entropy_store *r)
 
        r->entropy_count = 0;
        r->entropy_total = 0;
+       r->last_data_init = false;
        mix_pool_bytes(r, &now, sizeof(now), NULL);
        for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
                if (!arch_get_random_long(&rv))
@@ -1142,11 +1155,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
                if (n > SEC_XFER_SIZE)
                        n = SEC_XFER_SIZE;
 
-               DEBUG_ENT("reading %d bits\n", n*8);
+               DEBUG_ENT("reading %zu bits\n", n*8);
 
                n = extract_entropy_user(&blocking_pool, buf, n);
 
-               DEBUG_ENT("read got %d bits (%d still needed)\n",
+               if (n < 0) {
+                       retval = n;
+                       break;
+               }
+
+               DEBUG_ENT("read got %zd bits (%zd still needed)\n",
                          n*8, (nbytes-n)*8);
 
                if (n == 0) {
@@ -1171,10 +1189,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
                        continue;
                }
 
-               if (n < 0) {
-                       retval = n;
-                       break;
-               }
                count += n;
                buf += n;
                nbytes -= n;