Robbie Zhang (robbie.zhang@intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18362
-gerrit
commit 7b8aea595a32a2a26322224f7c3004bb37db96d3 Author: Robbie Zhang robbie.zhang@intel.com Date: Mon Feb 13 13:44:14 2017 -0800
arch/x86: add library function for coreboot to generate random number using x86 RDRAND instruction.
Two functions are supplied to generate 32bit or 64bit number.
One potential usage is the sealing key generation for SGX.
BUG=chrome-os-partner:62438 BRANCH=NONE TEST=Tested on Eve to generate a 64bit random number.
Change-Id: I50cbeda4de17ccf2fc5efc1fe04f6b1a31ec268c Signed-off-by: Robbie Zhang robbie.zhang@intel.com --- src/arch/x86/Makefile.inc | 1 + src/arch/x86/include/arch/rdrand.h | 27 ++++++++++++++ src/arch/x86/rdrand.c | 76 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+)
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index c4bb1cc..332e8ec 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -334,6 +334,7 @@ ramstage-$(CONFIG_GENERATE_MP_TABLE) += mpspec.c ramstage-y += pci_ops_conf1.c ramstage-$(CONFIG_MMCONF_SUPPORT) += pci_ops_mmconf.c ramstage-$(CONFIG_GENERATE_PIRQ_TABLE) += pirq_routing.c +ramstage-y += rdrand.c ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios.c ramstage-y += tables.c ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c diff --git a/src/arch/x86/include/arch/rdrand.h b/src/arch/x86/include/arch/rdrand.h new file mode 100644 index 0000000..74166d9 --- /dev/null +++ b/src/arch/x86/include/arch/rdrand.h @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2017 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that 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. + */ +#ifndef ARCH_RDRAND_H +#define ARCH_RDRAND_H + +#include <stdint.h> + +/* + * Generates a 32/64 bit random number respectively. + * return 0 on success and -1 on error. + */ +int get_random_number_32(uint32_t *rand); +int get_random_number_64(uint64_t *rand); + +#endif /* ARCH_RDRAND_H */ diff --git a/src/arch/x86/rdrand.c b/src/arch/x86/rdrand.c new file mode 100644 index 0000000..9f7ed81 --- /dev/null +++ b/src/arch/x86/rdrand.c @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2017 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that 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. + */ + +#include <arch/rdrand.h> + +#define RDRAND_RETRY_LOOPS 10 + +/* Generate a 32-bit random number through RDRAND instruction. */ +static inline uint8_t rdrand_32(uint32_t *rand) +{ + uint8_t carry; + + __asm__ __volatile__( + ".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1" + : "=a" (*rand), "=qm" (carry)); + return carry; +} + +#ifdef __x86_64__ +/* Generate a 64-bit random number through RDRAND instruction. */ +static inline uint8_t rdrand_64(uint64_t *rand) +{ + uint8_t carry; + + __asm__ __volatile__( + ".byte 0x48; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1" + : "=a" (*rand), "=qm" (carry)); + return carry; +} +#endif + +int get_random_number_32(uint32_t *rand) +{ + int i; + + /* Perform a loop call until RDRAND succeeds or returns failure. */ + for (i = 0; i < RDRAND_RETRY_LOOPS; i++) { + if (rdrand_32(rand)) + return 0; + } + return -1; +} + +int get_random_number_64(uint64_t *rand) +{ + int i; +#ifndef __x86_64__ + uint32_t rand_high, rand_low; +#endif + + /* Perform a loop call until RDRAND succeeds or returns failure. */ + for (i = 0; i < RDRAND_RETRY_LOOPS; i++) { +#ifdef __x86_64__ + if (rdrand_64(rand)) + return 0; +#else + if (rdrand_32(&rand_high) && rdrand_32(&rand_low)) { + *rand = ((uint64_t)rand_high << 32) | (uint64_t)rand_low; + return 0; + } +#endif + } + return -1; +}