diff mbox series

[v1,1/3] random: Make crng state queryable

Message ID 20180731191102.2434-2-Jason@zx2c4.com
State New
Headers show
Series WireGuard: Secure Network Tunnel | expand

Commit Message

Jason A. Donenfeld July 31, 2018, 7:11 p.m. UTC
It is very useful to be able to know whether or not get_random_bytes_wait
/ wait_for_random_bytes is going to block or not, or whether plain
get_random_bytes is going to return good randomness or bad randomness.

The particular use case is for mitigating certain attacks in WireGuard.
A handshake packet arrives and is queued up. Elsewhere a worker thread
takes items from the queue and processes them. In replying to these
items, it needs to use some random data, and it has to be good random
data. If we simply block until we can have good randomness, then it's
possible for an attacker to fill the queue up with packets waiting to be
processed. Upon realizing the queue is full, WireGuard will detect that
it's under a denial of service attack, and behave accordingly. A better
approach is just to drop incoming handshake packets if the crng is not
yet initialized.

This patch, therefore, makes that information directly accessible.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>

Signed-off-by: Theodore Ts'o <tytso@mit.edu>

---
 drivers/char/random.c  | 15 +++++++++++++++
 include/linux/random.h |  1 +
 2 files changed, 16 insertions(+)

-- 
2.18.0

Comments

Theodore Ts'o Aug. 2, 2018, 9:35 p.m. UTC | #1
On Tue, Jul 31, 2018 at 09:11:00PM +0200, Jason A. Donenfeld wrote:
> It is very useful to be able to know whether or not get_random_bytes_wait

> / wait_for_random_bytes is going to block or not, or whether plain

> get_random_bytes is going to return good randomness or bad randomness.

> 

> The particular use case is for mitigating certain attacks in WireGuard.

> A handshake packet arrives and is queued up. Elsewhere a worker thread

> takes items from the queue and processes them. In replying to these

> items, it needs to use some random data, and it has to be good random

> data. If we simply block until we can have good randomness, then it's

> possible for an attacker to fill the queue up with packets waiting to be

> processed. Upon realizing the queue is full, WireGuard will detect that

> it's under a denial of service attack, and behave accordingly. A better

> approach is just to drop incoming handshake packets if the crng is not

> yet initialized.

> 

> This patch, therefore, makes that information directly accessible.

> 

> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>

> Signed-off-by: Theodore Ts'o <tytso@mit.edu>


Applied to the random.git tree.

					- Ted
diff mbox series

Patch

diff --git a/drivers/char/random.c b/drivers/char/random.c
index cd888d4ee605..4efd16f6e0e1 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1658,6 +1658,21 @@  int wait_for_random_bytes(void)
 }
 EXPORT_SYMBOL(wait_for_random_bytes);
 
+/*
+ * Returns whether or not the urandom pool has been seeded and thus guaranteed
+ * to supply cryptographically secure random numbers. This applies to: the
+ * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
+ * ,u64,int,long} family of functions.
+ *
+ * Returns: true if the urandom pool has been seeded.
+ *          false if the urandom pool has not been seeded.
+ */
+bool rng_is_initialized(void)
+{
+	return crng_ready();
+}
+EXPORT_SYMBOL(rng_is_initialized);
+
 /*
  * Add a callback function that will be invoked when the nonblocking
  * pool is initialised.
diff --git a/include/linux/random.h b/include/linux/random.h
index 2ddf13b4281e..c8208e0ff227 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -36,6 +36,7 @@  extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy;
 
 extern void get_random_bytes(void *buf, int nbytes);
 extern int wait_for_random_bytes(void);
+extern bool rng_is_initialized(void);
 extern int add_random_ready_callback(struct random_ready_callback *rdy);
 extern void del_random_ready_callback(struct random_ready_callback *rdy);
 extern void get_random_bytes_arch(void *buf, int nbytes);