Skip to content

Commit

Permalink
Merge branch 'x86-rdrand-for-linus' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/tip/tip

* 'x86-rdrand-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86, random: Verify RDRAND functionality and allow it to be disabled
  x86, random: Architectural inlines to get random integers with RDRAND
  random: Add support for architectural random hooks

Fix up trivial conflicts in drivers/char/random.c: the architectural
random hooks touched "get_random_int()" that was simplified to use MD5
and not do the keyptr thing any more (see commit 6e5714e: "net:
Compute protocol sequence numbers and fragment IDs using MD5").
  • Loading branch information
torvalds committed Oct 28, 2011
2 parents 8237eb9 + 49d859d commit 8e6d539
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 2 deletions.
5 changes: 5 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.

noresidual [PPC] Don't use residual data on PReP machines.

nordrand [X86] Disable the direct use of the RDRAND
instruction even if it is supported by the
processor. RDRAND is still available to user
space applications.

noresume [SWSUSP] Disables resume and restores original swap
space.

Expand Down
9 changes: 9 additions & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,15 @@ config ARCH_USES_PG_UNCACHED
def_bool y
depends on X86_PAT

config ARCH_RANDOM
def_bool y
prompt "x86 architectural random number generator" if EXPERT
---help---
Enable the x86 architectural RDRAND instruction
(Intel Bull Mountain technology) to generate random numbers.
If supported, this is a high bandwidth, cryptographically
secure hardware random number generator.

config EFI
bool "EFI runtime service support"
depends on ACPI
Expand Down
75 changes: 75 additions & 0 deletions arch/x86/include/asm/archrandom.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* This file is part of the Linux kernel.
*
* Copyright (c) 2011, Intel Corporation
* Authors: Fenghua Yu <fenghua.yu@intel.com>,
* H. Peter Anvin <hpa@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
*/

#ifndef ASM_X86_ARCHRANDOM_H
#define ASM_X86_ARCHRANDOM_H

#include <asm/processor.h>
#include <asm/cpufeature.h>
#include <asm/alternative.h>
#include <asm/nops.h>

#define RDRAND_RETRY_LOOPS 10

#define RDRAND_INT ".byte 0x0f,0xc7,0xf0"
#ifdef CONFIG_X86_64
# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0"
#else
# define RDRAND_LONG RDRAND_INT
#endif

#ifdef CONFIG_ARCH_RANDOM

#define GET_RANDOM(name, type, rdrand, nop) \
static inline int name(type *v) \
{ \
int ok; \
alternative_io("movl $0, %0\n\t" \
nop, \
"\n1: " rdrand "\n\t" \
"jc 2f\n\t" \
"decl %0\n\t" \
"jnz 1b\n\t" \
"2:", \
X86_FEATURE_RDRAND, \
ASM_OUTPUT2("=r" (ok), "=a" (*v)), \
"0" (RDRAND_RETRY_LOOPS)); \
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);

#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);

#endif /* CONFIG_X86_64 */

#endif /* CONFIG_ARCH_RANDOM */

extern void x86_init_rdrand(struct cpuinfo_x86 *c);

#endif /* ASM_X86_ARCHRANDOM_H */
1 change: 1 addition & 0 deletions arch/x86/kernel/cpu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ CFLAGS_common.o := $(nostackp)
obj-y := intel_cacheinfo.o scattered.o topology.o
obj-y += proc.o capflags.o powerflags.o common.o
obj-y += vmware.o hypervisor.o sched.o mshyperv.o
obj-y += rdrand.o

obj-$(CONFIG_X86_32) += bugs.o
obj-$(CONFIG_X86_64) += bugs_64.o
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <asm/stackprotector.h>
#include <asm/perf_event.h>
#include <asm/mmu_context.h>
#include <asm/archrandom.h>
#include <asm/hypervisor.h>
#include <asm/processor.h>
#include <asm/sections.h>
Expand Down Expand Up @@ -860,6 +861,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
#endif

init_hypervisor(c);
x86_init_rdrand(c);

/*
* Clear/Set all flags overriden by options, need do it
Expand Down
73 changes: 73 additions & 0 deletions arch/x86/kernel/cpu/rdrand.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* This file is part of the Linux kernel.
*
* Copyright (c) 2011, Intel Corporation
* Authors: Fenghua Yu <fenghua.yu@intel.com>,
* H. Peter Anvin <hpa@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
*/

#include <asm/processor.h>
#include <asm/archrandom.h>
#include <asm/sections.h>

static int __init x86_rdrand_setup(char *s)
{
setup_clear_cpu_cap(X86_FEATURE_RDRAND);
return 1;
}
__setup("nordrand", x86_rdrand_setup);

/* We can't use arch_get_random_long() here since alternatives haven't run */
static inline int rdrand_long(unsigned long *v)
{
int ok;
asm volatile("1: " RDRAND_LONG "\n\t"
"jc 2f\n\t"
"decl %0\n\t"
"jnz 1b\n\t"
"2:"
: "=r" (ok), "=a" (*v)
: "0" (RDRAND_RETRY_LOOPS));
return ok;
}

/*
* Force a reseed cycle; we are architecturally guaranteed a reseed
* after no more than 512 128-bit chunks of random data. This also
* acts as a test of the CPU capability.
*/
#define RESEED_LOOP ((512*128)/sizeof(unsigned long))

void __cpuinit x86_init_rdrand(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_ARCH_RANDOM
unsigned long tmp;
int i, count, ok;

if (!cpu_has(c, X86_FEATURE_RDRAND))
return; /* Nothing to do */

for (count = i = 0; i < RESEED_LOOP; i++) {
ok = rdrand_long(&tmp);
if (ok)
count++;
}

if (count != RESEED_LOOP)
clear_cpu_cap(c, X86_FEATURE_RDRAND);
#endif
}
23 changes: 21 additions & 2 deletions drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,21 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
*/
void get_random_bytes(void *buf, int nbytes)
{
extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
char *p = buf;

while (nbytes) {
unsigned long v;
int chunk = min(nbytes, (int)sizeof(unsigned long));

if (!arch_get_random_long(&v))
break;

memcpy(buf, &v, chunk);
p += chunk;
nbytes -= chunk;
}

extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
}
EXPORT_SYMBOL(get_random_bytes);

Expand Down Expand Up @@ -1318,9 +1332,14 @@ late_initcall(random_int_secret_init);
DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
unsigned int get_random_int(void)
{
__u32 *hash = get_cpu_var(get_random_int_hash);
__u32 *hash;
unsigned int ret;

if (arch_get_random_int(&ret))
return ret;

hash = get_cpu_var(get_random_int_hash);

hash[0] += current->pid + jiffies + get_cycles();
md5_transform(hash, random_int_secret);
ret = hash[0];
Expand Down
13 changes: 13 additions & 0 deletions include/linux/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ static inline void prandom32_seed(struct rnd_state *state, u64 seed)
state->s3 = __seed(i, 15);
}

#ifdef CONFIG_ARCH_RANDOM
# include <asm/archrandom.h>
#else
static inline int arch_get_random_long(unsigned long *v)
{
return 0;
}
static inline int arch_get_random_int(unsigned int *v)
{
return 0;
}
#endif

#endif /* __KERNEL___ */

#endif /* _LINUX_RANDOM_H */

0 comments on commit 8e6d539

Please sign in to comment.