* [PATCH 0/3] RDSEED support for the Linux kernel
@ 2014-03-04 22:40 H. Peter Anvin
2014-03-04 22:40 ` [PATCH 1/3] x86, random: Enable the RDSEED instruction H. Peter Anvin
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: H. Peter Anvin @ 2014-03-04 22:40 UTC (permalink / raw)
To: Linus Torvalds, Ted Ts'o, H. Peter Anvin, Ingo Molnar,
Thomas Gleixner
Cc: Linux Kernel Mailing List, H. Peter Anvin
From: "H. Peter Anvin" <hpa@linux.intel.com>
Upcoming Intel silicon adds a new RDSEED instruction. Whereas RDRAND
returns output from a PRNG, the RDSEED instruction returns fully
conditioned entropy that is suitable for use as seeds to a PRNG.
This patchset adds support for RDSEED in the Linux kernel in three
places:
1. During bootup, use RDSEED to initialize the entropy pool if
available (we already use RDRAND for this). We don't add any
credit at this point, but it will give much better starting point.
2. In the slow path to add_interrupt_randomness, executed once per
second, we take a single RDSEED sample and mix it into the entropy
pool, crediting it at 50% of its rated entropy. This was suggested
by Linus.
3. If we are about to block on /dev/random due to lack of entropy,
attempt an "emergency pool refill" using RDSEED.
Comments are, of course, appreciated.
-hpa
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] x86, random: Enable the RDSEED instruction
2014-03-04 22:40 [PATCH 0/3] RDSEED support for the Linux kernel H. Peter Anvin
@ 2014-03-04 22:40 ` H. Peter Anvin
2014-03-05 8:43 ` Ingo Molnar
2014-03-04 22:40 ` [PATCH 2/3] random: Use arch_get_random_seed*() at init time and once a second H. Peter Anvin
2014-03-04 22:40 ` [PATCH 3/3] random: If we have arch_get_random_seed*(), try it before blocking H. Peter Anvin
2 siblings, 1 reply; 7+ messages in thread
From: H. Peter Anvin @ 2014-03-04 22:40 UTC (permalink / raw)
To: Linus Torvalds, Ted Ts'o, H. Peter Anvin, Ingo Molnar,
Thomas Gleixner
Cc: Linux Kernel Mailing List, H. Peter Anvin
From: "H. Peter Anvin" <hpa@linux.intel.com>
Upcoming Intel silicon adds a new RDSEED instruction. Whereas RDRAND
returns output from a PRNG, the RDSEED instruction returns fully
conditioned entropy that is suitable for use as seeds to a PRNG.
The RDSEED instruction takes the same time to execute as RDRAND, but
RDSEED unlike RDRAND can legitimately return failure (CF=0) due to
entropy exhaustion if too many threads on too many cores are hammering
the RDSEED instruction at the same time. Therefore, we have to be
more conservative and only use it in places where we can tolerate
failures.
This patch introduces the primitives arch_get_random_seed_{int,long}()
but does not use it yet.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
---
arch/x86/include/asm/archrandom.h | 34 +++++++++++++++++++++++++++++++++-
include/linux/random.h | 16 ++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/archrandom.h b/arch/x86/include/asm/archrandom.h
index e6a9245..6e97683 100644
--- a/arch/x86/include/asm/archrandom.h
+++ b/arch/x86/include/asm/archrandom.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Linux kernel.
*
- * Copyright (c) 2011, Intel Corporation
+ * Copyright (c) 2011-2014, Intel Corporation
* Authors: Fenghua Yu <fenghua.yu@intel.com>,
* H. Peter Anvin <hpa@linux.intel.com>
*
@@ -31,10 +31,13 @@
#define RDRAND_RETRY_LOOPS 10
#define RDRAND_INT ".byte 0x0f,0xc7,0xf0"
+#define RDSEED_INT ".byte 0x0f,0xc7,0xf8"
#ifdef CONFIG_X86_64
# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0"
+# define RDSEED_LONG ".byte 0x48,0x0f,0xc7,0xf8"
#else
# define RDRAND_LONG RDRAND_INT
+# define RDSEED_LONG RDSEED_INT
#endif
#ifdef CONFIG_ARCH_RANDOM
@@ -53,6 +56,16 @@ static inline int rdrand_long(unsigned long *v)
return ok;
}
+/* A single attempt at RDSEED */
+static inline bool rdseed_long(unsigned long *v)
+{
+ unsigned char ok;
+ asm volatile(RDSEED_LONG "\n\t"
+ "setc %0"
+ : "=qm" (ok), "=a" (*v));
+ return ok;
+}
+
#define GET_RANDOM(name, type, rdrand, nop) \
static inline int name(type *v) \
{ \
@@ -70,16 +83,35 @@ static inline int name(type *v) \
return ok; \
}
+#define GET_SEED(name, type, rdseed, nop) \
+static inline int name(type *v) \
+{ \
+ unsigned char ok; \
+ alternative_io("movb $0, %0\n\t" \
+ nop, \
+ rdseed "\n\t" \
+ "setc %0", \
+ X86_FEATURE_RDSEED, \
+ ASM_OUTPUT2("=q" (ok), "=a" (*v))); \
+ return ok; \
+}
+
#ifdef CONFIG_X86_64
GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5);
GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4);
+GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP5);
+GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4);
+
#else
GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3);
GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3);
+GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP4);
+GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4);
+
#endif /* CONFIG_X86_64 */
#else
diff --git a/include/linux/random.h b/include/linux/random.h
index 1cfce0e..4417693 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -88,6 +88,22 @@ static inline int arch_get_random_int(unsigned int *v)
{
return 0;
}
+static inline int arch_get_random_seed_long(unsigned long *v)
+{
+ return 0;
+}
+static inline int arch_get_random_seed_int(unsigned int *v)
+{
+ return 0;
+}
+static inline int arch_get_random_seed_long(unsigned long *v)
+{
+ return 0;
+}
+static inline int arch_get_random_seed_int(unsigned int *v)
+{
+ return 0;
+}
#endif
/* Pseudo random number generator from numerical recipes. */
--
1.8.3.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/3] random: Use arch_get_random_seed*() at init time and once a second
2014-03-04 22:40 [PATCH 0/3] RDSEED support for the Linux kernel H. Peter Anvin
2014-03-04 22:40 ` [PATCH 1/3] x86, random: Enable the RDSEED instruction H. Peter Anvin
@ 2014-03-04 22:40 ` H. Peter Anvin
2014-03-05 8:44 ` Ingo Molnar
2014-03-04 22:40 ` [PATCH 3/3] random: If we have arch_get_random_seed*(), try it before blocking H. Peter Anvin
2 siblings, 1 reply; 7+ messages in thread
From: H. Peter Anvin @ 2014-03-04 22:40 UTC (permalink / raw)
To: Linus Torvalds, Ted Ts'o, H. Peter Anvin, Ingo Molnar,
Thomas Gleixner
Cc: Linux Kernel Mailing List, H. Peter Anvin
From: "H. Peter Anvin" <hpa@linux.intel.com>
Use arch_get_random_seed*() in two places in the Linux random
driver (drivers/char/random.c):
1. During entropy pool initialization, use RDSEED in favor of RDRAND,
with a fallback to the latter. Entropy exhaustion is unlikely to
happen there on physical hardware as the machine is single-threaded
at that point, but could happen in a virtual machine. In that
case, the fallback to RDRAND will still provide more than adequate
entropy pool initialization.
2. Once a second, issue RDSEED and, if successful, feed it to the
entropy pool. To ensure an extra layer of security, only credit
half the entropy just in case.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
---
drivers/char/random.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 429b75b..b1d5ae2 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -844,6 +844,8 @@ void add_interrupt_randomness(int irq, int irq_flags)
cycles_t cycles = random_get_entropy();
__u32 input[4], c_high, j_high;
__u64 ip;
+ unsigned long seed;
+ int credit;
c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
j_high = (sizeof(now) > 4) ? now >> 32 : 0;
@@ -862,20 +864,33 @@ void add_interrupt_randomness(int irq, int irq_flags)
r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+
/*
* If we don't have a valid cycle counter, and we see
* back-to-back timer interrupts, then skip giving credit for
- * any entropy.
+ * any entropy, otherwise credit 1 bit.
*/
+ credit = 1;
if (cycles == 0) {
if (irq_flags & __IRQF_TIMER) {
if (fast_pool->last_timer_intr)
- return;
+ credit = 0;
fast_pool->last_timer_intr = 1;
} else
fast_pool->last_timer_intr = 0;
}
- credit_entropy_bits(r, 1);
+
+ /*
+ * If we have architectural seed generator, produce a seed and
+ * add it to the pool. For the sake of paranoia count it as
+ * 50% entropic.
+ */
+ if (arch_get_random_seed_long(&seed)) {
+ __mix_pool_bytes(r, &seed, sizeof(seed), NULL);
+ credit += sizeof(seed) * 4;
+ }
+
+ credit_entropy_bits(r, credit);
}
#ifdef CONFIG_BLOCK
@@ -1238,7 +1253,8 @@ static void init_std_data(struct entropy_store *r)
r->last_pulled = jiffies;
mix_pool_bytes(r, &now, sizeof(now), NULL);
for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
- if (!arch_get_random_long(&rv))
+ if (!arch_get_random_seed_long(&rv) &&
+ !arch_get_random_long(&rv))
rv = random_get_entropy();
mix_pool_bytes(r, &rv, sizeof(rv), NULL);
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] random: If we have arch_get_random_seed*(), try it before blocking
2014-03-04 22:40 [PATCH 0/3] RDSEED support for the Linux kernel H. Peter Anvin
2014-03-04 22:40 ` [PATCH 1/3] x86, random: Enable the RDSEED instruction H. Peter Anvin
2014-03-04 22:40 ` [PATCH 2/3] random: Use arch_get_random_seed*() at init time and once a second H. Peter Anvin
@ 2014-03-04 22:40 ` H. Peter Anvin
2014-03-05 8:45 ` Ingo Molnar
2 siblings, 1 reply; 7+ messages in thread
From: H. Peter Anvin @ 2014-03-04 22:40 UTC (permalink / raw)
To: Linus Torvalds, Ted Ts'o, H. Peter Anvin, Ingo Molnar,
Thomas Gleixner
Cc: Linux Kernel Mailing List, H. Peter Anvin
From: "H. Peter Anvin" <hpa@linux.intel.com>
If we have arch_get_random_seed*(), try to use it for emergency refill
of the entropy pool before giving up and blocking on /dev/random. It
may or may not work in the moment, but if it does work, it will give
the user better service than blocking will.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Acked-by: Ingo Molnar <mingo@kernel.org>
---
drivers/char/random.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index b1d5ae2..f13f04b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1297,6 +1297,34 @@ void rand_initialize_disk(struct gendisk *disk)
}
#endif
+/*
+ * Attempt an emergency refill using arch_get_random_seed_long().
+ *
+ * As with add_interrupt_randomness() be paranoid and only
+ * credit the output as 50% entropic.
+ */
+static int arch_random_refill(void)
+{
+ const unsigned int nlongs = 64; /* Arbitrary number */
+ unsigned int n = 0;
+ unsigned int i;
+ unsigned long buf[nlongs];
+
+ for (i = 0; i < nlongs; i++) {
+ if (arch_get_random_seed_long(&buf[n]))
+ n++;
+ }
+
+ if (n) {
+ unsigned int rand_bytes = n * sizeof(unsigned long);
+
+ mix_pool_bytes(&input_pool, buf, rand_bytes, NULL);
+ credit_entropy_bits(&input_pool, rand_bytes*4);
+ }
+
+ return n;
+}
+
static ssize_t
random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
@@ -1322,6 +1350,10 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
ENTROPY_BITS(&input_pool));
if (n == 0) {
+ /* Try an emergency refill */
+ if (arch_random_refill())
+ continue;
+
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] x86, random: Enable the RDSEED instruction
2014-03-04 22:40 ` [PATCH 1/3] x86, random: Enable the RDSEED instruction H. Peter Anvin
@ 2014-03-05 8:43 ` Ingo Molnar
0 siblings, 0 replies; 7+ messages in thread
From: Ingo Molnar @ 2014-03-05 8:43 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Linus Torvalds, Ted Ts'o, H. Peter Anvin, Thomas Gleixner,
Linux Kernel Mailing List
* H. Peter Anvin <hpa@linux.intel.com> wrote:
> From: "H. Peter Anvin" <hpa@linux.intel.com>
>
> Upcoming Intel silicon adds a new RDSEED instruction. Whereas RDRAND
> returns output from a PRNG, the RDSEED instruction returns fully
> conditioned entropy that is suitable for use as seeds to a PRNG.
>
> The RDSEED instruction takes the same time to execute as RDRAND, but
> RDSEED unlike RDRAND can legitimately return failure (CF=0) due to
> entropy exhaustion if too many threads on too many cores are hammering
> the RDSEED instruction at the same time. Therefore, we have to be
> more conservative and only use it in places where we can tolerate
> failures.
>
> This patch introduces the primitives arch_get_random_seed_{int,long}()
> but does not use it yet.
>
> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
> ---
> arch/x86/include/asm/archrandom.h | 34 +++++++++++++++++++++++++++++++++-
> include/linux/random.h | 16 ++++++++++++++++
> 2 files changed, 49 insertions(+), 1 deletion(-)
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Thanks,
Ingo
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] random: Use arch_get_random_seed*() at init time and once a second
2014-03-04 22:40 ` [PATCH 2/3] random: Use arch_get_random_seed*() at init time and once a second H. Peter Anvin
@ 2014-03-05 8:44 ` Ingo Molnar
0 siblings, 0 replies; 7+ messages in thread
From: Ingo Molnar @ 2014-03-05 8:44 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Linus Torvalds, Ted Ts'o, H. Peter Anvin, Thomas Gleixner,
Linux Kernel Mailing List
* H. Peter Anvin <hpa@linux.intel.com> wrote:
> From: "H. Peter Anvin" <hpa@linux.intel.com>
>
> Use arch_get_random_seed*() in two places in the Linux random
> driver (drivers/char/random.c):
>
> 1. During entropy pool initialization, use RDSEED in favor of RDRAND,
> with a fallback to the latter. Entropy exhaustion is unlikely to
> happen there on physical hardware as the machine is single-threaded
> at that point, but could happen in a virtual machine. In that
> case, the fallback to RDRAND will still provide more than adequate
> entropy pool initialization.
>
> 2. Once a second, issue RDSEED and, if successful, feed it to the
> entropy pool. To ensure an extra layer of security, only credit
> half the entropy just in case.
>
> Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
> ---
> drivers/char/random.c | 24 ++++++++++++++++++++----
> 1 file changed, 20 insertions(+), 4 deletions(-)
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Thanks,
Ingo
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] random: If we have arch_get_random_seed*(), try it before blocking
2014-03-04 22:40 ` [PATCH 3/3] random: If we have arch_get_random_seed*(), try it before blocking H. Peter Anvin
@ 2014-03-05 8:45 ` Ingo Molnar
0 siblings, 0 replies; 7+ messages in thread
From: Ingo Molnar @ 2014-03-05 8:45 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Linus Torvalds, Ted Ts'o, H. Peter Anvin, Thomas Gleixner,
Linux Kernel Mailing List
* H. Peter Anvin <hpa@linux.intel.com> wrote:
> From: "H. Peter Anvin" <hpa@linux.intel.com>
>
> If we have arch_get_random_seed*(), try to use it for emergency refill
> of the entropy pool before giving up and blocking on /dev/random. It
> may or may not work in the moment, but if it does work, it will give
> the user better service than blocking will.
>
> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
> Acked-by: Ingo Molnar <mingo@kernel.org>
> ---
> drivers/char/random.c | 32 ++++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Thanks,
Ingo
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-03-05 8:45 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-04 22:40 [PATCH 0/3] RDSEED support for the Linux kernel H. Peter Anvin
2014-03-04 22:40 ` [PATCH 1/3] x86, random: Enable the RDSEED instruction H. Peter Anvin
2014-03-05 8:43 ` Ingo Molnar
2014-03-04 22:40 ` [PATCH 2/3] random: Use arch_get_random_seed*() at init time and once a second H. Peter Anvin
2014-03-05 8:44 ` Ingo Molnar
2014-03-04 22:40 ` [PATCH 3/3] random: If we have arch_get_random_seed*(), try it before blocking H. Peter Anvin
2014-03-05 8:45 ` Ingo Molnar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).