lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Fri, 20 Mar 2020 19:38:09 -0400
From:   George Spelvin <lkml@....org>
To:     linux-kernel@...r.kernel.org, lkml@....org
Cc:     "Theodore Ts'o" <tytso@....edu>,
        "Jason A. Donenfeld" <Jason@...c4.com>
Subject: [RFC PATCH v1 50/50] random: add get_random_nonce()

This is like get_random_bytes(), but uses the same batched entropy
buffer as get_random_u32().

Many kernel users of get_random_bytes could be switched to this.
E.g. eth_random_addr().

But before doing that, we should decide if it wouldn't be better
to rename this function to get_random_bytes, and let the smaller
number of sites which really need strongly secure random numbers
use a different name like "get_secret_bytes()".

Code size +731 bytes (x86-64)

Signed-off-by: George Spelvin <lkml@....org>
Cc: Theodore Ts'o <tytso@....edu>
Cc: Jason A. Donenfeld <Jason@...c4.com>
---
 drivers/char/random.c  | 77 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/random.h |  1 +
 2 files changed, 78 insertions(+)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 67bdfb51eb25c..02e80000310ce 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -342,6 +342,7 @@
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/io.h>
+#include <asm/unaligned.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/random.h>
@@ -2569,6 +2570,82 @@ u32 get_random_u32(void)
 }
 EXPORT_SYMBOL(get_random_u32);
 
+/**
+ * get_random_nonce - Generate a random string of bytes
+ * @buf:	The buffer to fill
+ * @nbytes:	The size of the buffer
+ *
+ * This generates cryptographically strong bytes, at less cost than
+ * get_random_bytes.  In particular, anti-backtracking is not
+ * provided.  It is suitable for public values (random cookies or
+ * MAC addresses which are supposed to be unguessable), and for
+ * secret values which are stored in the kernel as long as they
+ * are valuable, such as SipHash keys or stack canaries.
+ *
+ * In general, if the calling code does not use memzero_explicit(), it
+ * is safe to use this function rather than get_random_bytes.
+ *
+ * TODO: Perhaps get_random_bytes should be renamed to get_secret_bytes
+ * and this function should be renamed to get_random_bytes?
+ */
+void get_random_nonce(void *buf, size_t nbytes)
+{
+	unsigned long ret;
+	size_t pos;
+	unsigned long flags;
+	struct batched_entropy *batch;
+	static void *previous;
+
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+	while (nbytes >= sizeof(ret)) {
+		if (!arch_get_random_long(buf))
+			goto software;
+		buf += sizeof(ret);
+		nbytes -= sizeof(ret);
+	}
+	if (nbytes) {
+		if (!arch_get_random_long(&ret))
+			goto software;
+		memcpy(buf, &ret, nbytes);
+	}
+	return;
+software:
+#else
+	while (arch_get_random_long(&ret)) {
+		if (nbytes > sizeof(ret)) {
+			put_unaligned(ret, (unsigned long *)buf);
+			buf += sizeof(ret);
+			nbytes -= sizeof(ret);
+		} else {
+			memcpy(buf, &ret, nbytes);
+			return;
+		}
+	}
+#endif
+
+	warn_unseeded_randomness(&previous);
+
+	local_irq_save(flags);
+	batch = this_cpu_ptr(&batched_entropy);
+	pos = batch->position + 1;
+	if (unlikely(crng_init != batch->crng_init)) {
+		batch->crng_init = crng_init;
+		pos = CHACHA_BLOCK_SIZE;
+	}
+
+	while (nbytes > CHACHA_BLOCK_SIZE - pos) {
+		memcpy(buf, batch->entropy8 + pos, CHACHA_BLOCK_SIZE - pos);
+		buf += CHACHA_BLOCK_SIZE - pos;
+		nbytes -= CHACHA_BLOCK_SIZE - pos;
+		extract_crng(batch->entropy32);
+		pos = 0;
+	}
+	batch->position = pos + nbytes - 1;
+	memcpy(buf, batch->entropy8 + pos, nbytes);
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(get_random_nonce);
+
 /**
  * __get_random_max32 - Generate a uniform random number 0 <= x < range < 2^32
  * @range:	Modulus for random number; must not be zero!
diff --git a/include/linux/random.h b/include/linux/random.h
index 97d3469f3aad8..de9eae20b69af 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -50,6 +50,7 @@ extern const struct file_operations random_fops, urandom_fops;
 
 u32 get_random_u32(void);
 u64 get_random_u64(void);
+void get_random_nonce(void *buf, size_t nbytes);
 static inline unsigned int get_random_int(void)
 {
 	return get_random_u32();
-- 
2.26.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ