mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 07:01:57 +00:00
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.
|
||||
|
||||
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.
|
||||
|
||||
|
@ -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
|
||||
|
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 += 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
|
||||
|
@ -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>
|
||||
@ -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
|
||||
|
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)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -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];
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user