From: "H. Peter Anvin" <hpa@zytor.com>
To: Linus Torvalds <torvalds@linux-foundation.org>,
"H. Peter Anvin" <hpa@zytor.com>, Ingo Molnar <mingo@elte.hu>,
Thomas Gleixner <tglx@linutronix.de>,
Fenghua Yu <fenghua.yu@intel.com>, Matt Mackall <mpm@selenic.com>,
Herbert Xu <herbert@gondor.hengli.com.au>,
"Theodore Ts'o" <tytso@mit.edu>, Jeff Garzik <jgarzik@pobox.com>,
linux-kernel@vger.kernel.org
Cc: Arjan van de Ven <arjan@infradead.org>,
"H. Peter Anvin" <hpa@linux.intel.com>,
Herbert Xu <herbert@gondor.hengli.com.au>
Subject: [PATCH v2 1/2] random: Add support for architectural random hooks
Date: Sat, 30 Jul 2011 15:26:22 -0700 [thread overview]
Message-ID: <1312064783-9033-2-git-send-email-hpa@zytor.com> (raw)
In-Reply-To: <1312064783-9033-1-git-send-email-hpa@zytor.com>
From: "H. Peter Anvin" <hpa@zytor.com>
Add support for architecture-specific hooks into either the blocking
or the nonblocking random pools. These hooks are defined to produce a
single random "unsigned long" and return true (nonzero) on success.
They could also potentialy be used to inject randomness on demand
while continuing to use the pool system, by calling a suitable
injection interface and returning 0.
Note: the "blocking" hook is not actually allowed to block; the
semantic difference is that it is required to produce
/dev/random-quality entropy if available.
Changes in version 2:
- Have a single hook per pool (blocking, nonblocking) that returns an
unsigned long. The loops to fill an arbitrary buffer has moved to
generic code.
- Invoke the nonblocking hook to service get_random_int() if it is
available. (Note: we could in theory do this for random32() as
well, however, the assumption is that random32() is used when speed
is the only thing that matters, and the current random32()
implementation is extremely fast.)
- Correct the use of the nonblocking hook to preinitialize the pool
data buffers. Version 1 would incorrectly initialize the input pool
three times.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Matt Mackall <mpm@selenic.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "Theodore Ts'o" <tytso@mit.edu>
---
drivers/char/random.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/random.h | 14 +++++
2 files changed, 147 insertions(+), 1 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index d4ddeba..f2ddc6a 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -416,6 +416,7 @@ struct entropy_store {
const char *name;
struct entropy_store *pull;
int limit;
+ arch_random_func_t arch_func; /* Arch-specific shortcut */
/* read-write data: */
spinlock_t lock;
@@ -724,6 +725,104 @@ void add_disk_randomness(struct gendisk *disk)
/*********************************************************************
*
+ * Helper functions to fill a block from an arch-specific function
+ *
+ *********************************************************************/
+
+/* Clear a variable and make sure it is actually zeroed in memory */
+#define ZERO_VAR(x) do { \
+ (x) = 0; \
+ asm volatile("" : : "m" (x)); \
+} while (0)
+
+#ifdef CONFIG_ARCH_RANDOM
+
+static ssize_t func_to_kern(arch_random_func_t func,
+ void *buf, size_t size)
+{
+ unsigned long *p1 = (unsigned long *)buf;
+ unsigned long rnd;
+ ssize_t ret = 0;
+ int ok;
+
+ while (size >= sizeof *p1) {
+ ok = func(p1);
+ if (unlikely(!ok))
+ goto out;
+ p1++;
+ size -= sizeof *p1;
+ ret += sizeof *p1;
+ }
+
+ if (size) {
+ ok = func(&rnd);
+ if (unlikely(!ok))
+ goto out;
+ memcpy(p1, &rnd, size);
+ ret += size;
+ }
+
+out:
+ ZERO_VAR(rnd);
+ return ret;
+}
+
+static ssize_t func_to_user(arch_random_func_t func,
+ void __user *buf, size_t size)
+{
+ char __user *p1 = (char __user *)buf;
+ unsigned long rnd;
+ size_t chunk;
+ ssize_t ret = 0;
+ int ok, err;
+
+ while (size >= sizeof rnd) {
+ ok = func(&rnd);
+ if (unlikely(!ok))
+ goto out;
+ err = copy_to_user(p1, &rnd, sizeof rnd);
+ chunk = sizeof rnd - err;
+ p1 += chunk;
+ ret += chunk;
+ size -= chunk;
+ if (err)
+ goto out;
+ }
+
+ if (size) {
+ ok = func(&rnd);
+ if (unlikely(!ok))
+ goto out;
+ err = copy_to_user(p1, &rnd, size);
+ chunk = size - err;
+ p1 += chunk;
+ ret += chunk;
+ size -= chunk;
+ }
+
+out:
+ ZERO_VAR(rnd);
+ return ret;
+}
+
+#else
+
+static inline ssize_t func_to_kern(arch_random_func_t func,
+ void *buf, size_t size)
+{
+ return 0;
+}
+
+static inline ssize_t func_to_user(arch_random_func_t func,
+ void __user *buf, size_t size)
+{
+ return 0;
+}
+
+#endif
+
+/*********************************************************************
+ *
* Entropy extraction routines
*
*********************************************************************/
@@ -862,6 +961,15 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
__u8 tmp[EXTRACT_SIZE];
unsigned long flags;
+ if (r->arch_func) {
+ ret = func_to_kern(r->arch_func, buf, nbytes);
+ buf += ret;
+ nbytes -= ret;
+ }
+
+ if (!nbytes)
+ return ret;
+
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, min, reserved);
@@ -894,6 +1002,15 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
+ if (r->arch_func) {
+ ret = func_to_user(r->arch_func, buf, nbytes);
+ buf += ret;
+ nbytes -= ret;
+ }
+
+ if (!nbytes)
+ return ret;
+
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
@@ -954,6 +1071,11 @@ static void init_std_data(struct entropy_store *r)
r->entropy_count = 0;
spin_unlock_irqrestore(&r->lock, flags);
+ if (nonblocking_pool.arch_func) {
+ func_to_kern(nonblocking_pool.arch_func,
+ r->pool, r->poolinfo->POOLBYTES);
+ }
+
now = ktime_get_real();
mix_pool_bytes(r, &now, sizeof(now));
mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
@@ -961,6 +1083,8 @@ static void init_std_data(struct entropy_store *r)
static int rand_initialize(void)
{
+ arch_setup_random_funcs(&nonblocking_pool.arch_func,
+ &blocking_pool.arch_func);
init_std_data(&input_pool);
init_std_data(&blocking_pool);
init_std_data(&nonblocking_pool);
@@ -1635,8 +1759,16 @@ DEFINE_PER_CPU(__u32 [4], get_random_int_hash);
unsigned int get_random_int(void)
{
struct keydata *keyptr;
- __u32 *hash = get_cpu_var(get_random_int_hash);
+ __u32 *hash;
int ret;
+ unsigned long tmp;
+
+ if (nonblocking_pool.arch_func) {
+ if (nonblocking_pool.arch_func(&tmp))
+ return tmp;
+ }
+
+ hash = get_cpu_var(get_random_int_hash);
keyptr = get_keyptr();
hash[0] += current->pid + jiffies + get_cycles();
diff --git a/include/linux/random.h b/include/linux/random.h
index fb7ab9d..65a1752 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/irqnr.h>
+#include <linux/errno.h>
/* ioctl()'s for the random number generator */
@@ -75,7 +76,20 @@ extern const struct file_operations random_fops, urandom_fops;
unsigned int get_random_int(void);
unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
+typedef int (*arch_random_func_t)(unsigned long *);
+#ifdef CONFIG_ARCH_RANDOM
+void arch_setup_random_funcs(arch_random_func_t *nonblocking,
+ arch_random_func_t *blocking);
+#else
+static inline void arch_setup_random_funcs(arch_random_func_t *nonblocking,
+ arch_random_func_t *blocking)
+{
+ /* Nothing to do */
+}
+#endif
+
u32 random32(void);
+
void srandom32(u32 seed);
u32 prandom32(struct rnd_state *);
--
1.7.6
next prev parent reply other threads:[~2011-07-30 22:34 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-29 20:37 [RFD] Direct support for the x86 RDRAND instruction H. Peter Anvin
2011-07-29 20:37 ` [PATCH 1/2] random: Add support for architectural random hooks H. Peter Anvin
2011-07-29 21:16 ` Matt Mackall
2011-07-30 6:20 ` Linus Torvalds
2011-07-30 16:34 ` Arjan van de Ven
2011-07-30 17:45 ` Matt Mackall
2011-07-30 18:20 ` Linus Torvalds
2011-07-30 19:13 ` Matt Mackall
2011-07-30 19:29 ` Linus Torvalds
2011-07-30 22:25 ` Ted Ts'o
2011-07-31 1:13 ` Linus Torvalds
2011-07-31 1:32 ` H. Peter Anvin
2011-07-31 1:43 ` Linus Torvalds
2011-07-31 21:26 ` [PATCH v3 0/3] Add support for architectural random number generator H. Peter Anvin
2011-07-31 21:26 ` [PATCH v3 1/3] random: Add support for architectural random hooks H. Peter Anvin
2011-07-31 21:26 ` [PATCH v3 2/3] x86, random: Architectural inlines to get random integers with RDRAND H. Peter Anvin
2011-07-31 21:26 ` [PATCH v3 3/3] x86, random: Verify RDRAND functionality and allow it to be disabled H. Peter Anvin
2011-08-05 12:00 ` [PATCH v3 0/3] Add support for architectural random number generator Herbert Xu
2011-08-05 16:28 ` H. Peter Anvin
2011-08-06 0:09 ` Herbert Xu
2011-07-29 20:37 ` [PATCH 2/2] x86, random: " H. Peter Anvin
2011-07-29 21:05 ` [RFD] Direct support for the x86 RDRAND instruction Jeff Garzik
2011-07-29 21:17 ` H. Peter Anvin
2011-07-30 6:03 ` Linus Torvalds
2011-07-30 22:26 ` [PATCH v2 0/2] Add support for architectural random number generator H. Peter Anvin
2011-07-30 22:26 ` H. Peter Anvin [this message]
2011-07-30 22:26 ` [PATCH v2 2/2] x86, random: " H. Peter Anvin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1312064783-9033-2-git-send-email-hpa@zytor.com \
--to=hpa@zytor.com \
--cc=arjan@infradead.org \
--cc=fenghua.yu@intel.com \
--cc=herbert@gondor.hengli.com.au \
--cc=hpa@linux.intel.com \
--cc=jgarzik@pobox.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=mpm@selenic.com \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®