Merge branch 'x86-rdrand-for-linus' of git://git.kernel.org/pub/scm/linux/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 6e5714eaf7
: "net:
Compute protocol sequence numbers and fragment IDs using MD5").
This commit is contained in:
commit
8e6d539e0f
@ -1797,6 +1797,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||||||
|
|
||||||
noresidual [PPC] Don't use residual data on PReP machines.
|
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
|
noresume [SWSUSP] Disables resume and restores original swap
|
||||||
space.
|
space.
|
||||||
|
|
||||||
|
@ -1454,6 +1454,15 @@ config ARCH_USES_PG_UNCACHED
|
|||||||
def_bool y
|
def_bool y
|
||||||
depends on X86_PAT
|
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
|
config EFI
|
||||||
bool "EFI runtime service support"
|
bool "EFI runtime service support"
|
||||||
depends on ACPI
|
depends on ACPI
|
||||||
|
75
arch/x86/include/asm/archrandom.h
Normal file
75
arch/x86/include/asm/archrandom.h
Normal file
@ -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 */
|
@ -15,6 +15,7 @@ CFLAGS_common.o := $(nostackp)
|
|||||||
obj-y := intel_cacheinfo.o scattered.o topology.o
|
obj-y := intel_cacheinfo.o scattered.o topology.o
|
||||||
obj-y += proc.o capflags.o powerflags.o common.o
|
obj-y += proc.o capflags.o powerflags.o common.o
|
||||||
obj-y += vmware.o hypervisor.o sched.o mshyperv.o
|
obj-y += vmware.o hypervisor.o sched.o mshyperv.o
|
||||||
|
obj-y += rdrand.o
|
||||||
|
|
||||||
obj-$(CONFIG_X86_32) += bugs.o
|
obj-$(CONFIG_X86_32) += bugs.o
|
||||||
obj-$(CONFIG_X86_64) += bugs_64.o
|
obj-$(CONFIG_X86_64) += bugs_64.o
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <asm/stackprotector.h>
|
#include <asm/stackprotector.h>
|
||||||
#include <asm/perf_event.h>
|
#include <asm/perf_event.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
#include <asm/archrandom.h>
|
||||||
#include <asm/hypervisor.h>
|
#include <asm/hypervisor.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
@ -860,6 +861,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
init_hypervisor(c);
|
init_hypervisor(c);
|
||||||
|
x86_init_rdrand(c);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear/Set all flags overriden by options, need do it
|
* Clear/Set all flags overriden by options, need do it
|
||||||
|
73
arch/x86/kernel/cpu/rdrand.c
Normal file
73
arch/x86/kernel/cpu/rdrand.c
Normal file
@ -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
|
||||||
|
}
|
@ -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)
|
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);
|
EXPORT_SYMBOL(get_random_bytes);
|
||||||
|
|
||||||
@ -1318,9 +1332,14 @@ late_initcall(random_int_secret_init);
|
|||||||
DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
|
DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
|
||||||
unsigned int get_random_int(void)
|
unsigned int get_random_int(void)
|
||||||
{
|
{
|
||||||
__u32 *hash = get_cpu_var(get_random_int_hash);
|
__u32 *hash;
|
||||||
unsigned int ret;
|
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();
|
hash[0] += current->pid + jiffies + get_cycles();
|
||||||
md5_transform(hash, random_int_secret);
|
md5_transform(hash, random_int_secret);
|
||||||
ret = hash[0];
|
ret = hash[0];
|
||||||
|
@ -91,6 +91,19 @@ static inline void prandom32_seed(struct rnd_state *state, u64 seed)
|
|||||||
state->s3 = __seed(i, 15);
|
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 /* __KERNEL___ */
|
||||||
|
|
||||||
#endif /* _LINUX_RANDOM_H */
|
#endif /* _LINUX_RANDOM_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user