2019-11-06 07:10:08

by Dominik Brodowski

[permalink] [raw]
Subject: [PATCH 0/2] x86, efi/random: invoke EFI_RNG_PROTOCOL in the x86 EFI stub

EFI v2.4 and later may provide for a EFI_RNG_PROTOCOL, which can be called
from the EFI stubs to seed the kernel entropy pool. So far, this feature has
only been implemented on arm/arm64. This series makes the relevant EFI
libstub code arch-independent and enables the feature also on x86.

Please note that this feature only works if Linux is booted as an EFI stub,
and that the EFI-provided randomness is not credited as entropy unless
RANDOM_TRUST_BOOTLOADER is set.

Thanks to Ard Biesheuvel for his hints on how to test the EFI_RNG_PROTOCOL
from the UEFI shell ( RngTest-X64.efi ), and especially to Mario Limonciello:
he gave me highly useful hints on the implementation of the EFI_RNG_PROTOCOL
which ultimately helped me to determine why the earlier RFC patch did not
work out as expected.

The patches are also available in the Git repository at:

https://git.kernel.org/pub/scm/linux/kernel/git/brodo/linux.git/ random

Dominik Brodowski (2):
efi/random: use arch-independent efi_call_proto()
x86: efi/random: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table

arch/x86/boot/compressed/eboot.c | 3 +++
drivers/firmware/efi/libstub/Makefile | 5 +++--
drivers/firmware/efi/libstub/efistub.h | 2 --
drivers/firmware/efi/libstub/random.c | 21 ++++++++++++++++-----
include/linux/efi.h | 2 ++
5 files changed, 24 insertions(+), 9 deletions(-)

--
2.24.0


2019-11-06 07:11:21

by Dominik Brodowski

[permalink] [raw]
Subject: [PATCH 2/2] x86: efi/random: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table

Invoke the EFI_RNG_PROTOCOL protocol in the context of the x86 EFI stub,
same as is done on arm/arm64 since commit 568bc4e87033 ("efi/arm*/libstub:
Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table"). Within the stub,
a Linux-specific RNG seed UEFI config table will be seeded. The EFI routines
in the core kernel will pick that up later, yet still early during boot,
to seed the kernel entropy pool. If CONFIG_RANDOM_TRUST_BOOTLOADER, entropy
is credited for this seed.

Signed-off-by: Dominik Brodowski <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: Matt Fleming <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Hsin-Yi Wang <[email protected]>
Cc: Stephen Boyd <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Theodore Ts'o <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
---
arch/x86/boot/compressed/eboot.c | 3 +++
drivers/firmware/efi/libstub/Makefile | 5 +++--
drivers/firmware/efi/libstub/efistub.h | 2 --
include/linux/efi.h | 2 ++
4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 82bc60c8acb2..68945c5700bf 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -782,6 +782,9 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)

/* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation(sys_table);
+
+ efi_random_get_seed(sys_table);
+
efi_retrieve_tpm2_eventlog(sys_table);

setup_graphics(boot_params);
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index ee0661ddb25b..c35f893897e1 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -38,7 +38,8 @@ OBJECT_FILES_NON_STANDARD := y
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT := n

-lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o
+lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
+ random.o

# include the stub's generic dependencies from lib/ when building for ARM/arm64
arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
@@ -47,7 +48,7 @@ arm-deps-$(CONFIG_ARM64) += sort.c
$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
$(call if_changed_rule,cc_o_c)

-lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \
+lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o \
$(patsubst %.c,lib-%.o,$(arm-deps-y))

lib-$(CONFIG_ARM) += arm32-stub.o
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 7f1556fd867d..05739ae013c8 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -63,8 +63,6 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,

efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);

-efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
-
void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid);

/* Helper macros for the usual case of using simple C variables: */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index d87acf62958e..028efa7a9f3b 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1645,6 +1645,8 @@ static inline void
efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) { }
#endif

+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+
void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table);

/*
--
2.24.0

2019-11-06 07:12:14

by Dominik Brodowski

[permalink] [raw]
Subject: [PATCH 1/2] efi/random: use arch-independent efi_call_proto()

To handle all arch-specific peculiarities when calling an EFI protocol
function, a wrapper efi_call_proto() exists on all relevant architectures.
On arm/arm64, this is merely a plain function call. On x86, a special EFI
entry stub needs to be used, however, as the calling convention differs.
To make the efi/random stub arch-independent, use efi_call_proto()
instead of the existing non-portable calls to the EFI get_rng protocol
function. This also requires the addition of some typedefs.

Signed-off-by: Dominik Brodowski <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: Matt Fleming <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Hsin-Yi Wang <[email protected]>
Cc: Stephen Boyd <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Theodore Ts'o <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
---
drivers/firmware/efi/libstub/random.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index b4b1d1dcb5fd..05cbadab122b 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -9,6 +9,16 @@

#include "efistub.h"

+typedef struct {
+ u32 get_info;
+ u32 get_rng;
+} efi_rng_protocol_32_t;
+
+typedef struct {
+ u64 get_info;
+ u64 get_rng;
+} efi_rng_protocol_64_t;
+
struct efi_rng_protocol {
efi_status_t (*get_info)(struct efi_rng_protocol *,
unsigned long *, efi_guid_t *);
@@ -28,7 +38,7 @@ efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
if (status != EFI_SUCCESS)
return status;

- return rng->get_rng(rng, NULL, size, out);
+ return efi_call_proto(efi_rng_protocol, get_rng, rng, NULL, size, out);
}

/*
@@ -161,15 +171,16 @@ efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
if (status != EFI_SUCCESS)
return status;

- status = rng->get_rng(rng, &rng_algo_raw, EFI_RANDOM_SEED_SIZE,
- seed->bits);
+ status = efi_call_proto(efi_rng_protocol, get_rng, rng, &rng_algo_raw,
+ EFI_RANDOM_SEED_SIZE, seed->bits);
+
if (status == EFI_UNSUPPORTED)
/*
* Use whatever algorithm we have available if the raw algorithm
* is not implemented.
*/
- status = rng->get_rng(rng, NULL, EFI_RANDOM_SEED_SIZE,
- seed->bits);
+ status = efi_call_proto(efi_rng_protocol, get_rng, rng, NULL,
+ EFI_RANDOM_SEED_SIZE, seed->bits);

if (status != EFI_SUCCESS)
goto err_freepool;
--
2.24.0

2019-11-06 14:43:01

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [PATCH 0/2] x86, efi/random: invoke EFI_RNG_PROTOCOL in the x86 EFI stub

On Wed, 6 Nov 2019 at 08:09, Dominik Brodowski
<[email protected]> wrote:
>
> EFI v2.4 and later may provide for a EFI_RNG_PROTOCOL, which can be called
> from the EFI stubs to seed the kernel entropy pool. So far, this feature has
> only been implemented on arm/arm64. This series makes the relevant EFI
> libstub code arch-independent and enables the feature also on x86.
>
> Please note that this feature only works if Linux is booted as an EFI stub,
> and that the EFI-provided randomness is not credited as entropy unless
> RANDOM_TRUST_BOOTLOADER is set.
>
> Thanks to Ard Biesheuvel for his hints on how to test the EFI_RNG_PROTOCOL
> from the UEFI shell ( RngTest-X64.efi ), and especially to Mario Limonciello:
> he gave me highly useful hints on the implementation of the EFI_RNG_PROTOCOL
> which ultimately helped me to determine why the earlier RFC patch did not
> work out as expected.
>
> The patches are also available in the Git repository at:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/brodo/linux.git/ random
>
> Dominik Brodowski (2):
> efi/random: use arch-independent efi_call_proto()
> x86: efi/random: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table
>

Thanks Dominik. I'll get these queued up.

For others reading this, it is worth mentioning that there is an open
source UEFI driver for the ChaosKey, which produces the EFI RNG
protocol and can be loaded into UEFI persistently using 'efibootmgr
-r'.

> arch/x86/boot/compressed/eboot.c | 3 +++
> drivers/firmware/efi/libstub/Makefile | 5 +++--
> drivers/firmware/efi/libstub/efistub.h | 2 --
> drivers/firmware/efi/libstub/random.c | 21 ++++++++++++++++-----
> include/linux/efi.h | 2 ++
> 5 files changed, 24 insertions(+), 9 deletions(-)
>
> --
> 2.24.0
>