Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1520395

[PATCH 3/9] efi: Add support for seeding the RNG from a UEFI config table

From Matt Fleming <matt@codeblueprint.co.uk>
Newsgroups linux.kernel
Subject [PATCH 3/9] efi: Add support for seeding the RNG from a UEFI config table
Date 2016-11-12 22:40 +0100
Message-ID <sCObL-7JU-9@gated-at.bofh.it> (permalink)
References <sCObL-7JU-5@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

Specify a Linux specific UEFI configuration table that carries some
random bits, and use the contents during early boot to seed the kernel's
random number generator. This allows much strong random numbers to be
generated early on.

The entropy is fed to the kernel using add_device_randomness(), which is
documented as being appropriate for being called very early.

Since UEFI configuration tables may also be consumed by kexec'd kernels,
register a reboot notifier that updates the seed in the table.

Note that the config table could be generated by the EFI stub or by any
other UEFI driver or application (e.g., GRUB), but the random seed table
GUID and the associated functionality should be considered an internal
kernel interface (unless it is promoted to ABI later on)

Cc: Matt Fleming <matt@codeblueprint.co.uk>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/firmware/efi/efi.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/efi.h        |  8 ++++++
 2 files changed, 80 insertions(+)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a4944e22f294..92914801e388 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -23,7 +23,10 @@
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/io.h>
+#include <linux/kexec.h>
 #include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/ucs2_string.h>
@@ -48,6 +51,7 @@ struct efi __read_mostly efi = {
 	.esrt			= EFI_INVALID_TABLE_ADDR,
 	.properties_table	= EFI_INVALID_TABLE_ADDR,
 	.mem_attr_table		= EFI_INVALID_TABLE_ADDR,
+	.rng_seed		= EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
 
@@ -440,6 +444,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
 	{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
 	{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
 	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
+	{LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
 	{NULL_GUID, NULL, NULL},
 };
 
@@ -501,6 +506,29 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 	pr_cont("\n");
 	set_bit(EFI_CONFIG_TABLES, &efi.flags);
 
+	if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
+		struct linux_efi_random_seed *seed;
+		u32 size = 0;
+
+		seed = early_memremap(efi.rng_seed, sizeof(*seed));
+		if (seed != NULL) {
+			size = seed->size;
+			early_memunmap(seed, sizeof(*seed));
+		} else {
+			pr_err("Could not map UEFI random seed!\n");
+		}
+		if (size > 0) {
+			seed = early_memremap(efi.rng_seed,
+					      sizeof(*seed) + size);
+			if (seed != NULL) {
+				add_device_randomness(seed->bits, seed->size);
+				early_memunmap(seed, sizeof(*seed) + size);
+			} else {
+				pr_err("Could not map UEFI random seed!\n");
+			}
+		}
+	}
+
 	/* Parse the EFI Properties table if it exists */
 	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
 		efi_properties_table_t *tbl;
@@ -824,3 +852,47 @@ int efi_status_to_err(efi_status_t status)
 
 	return err;
 }
+
+#ifdef CONFIG_KEXEC
+static int update_efi_random_seed(struct notifier_block *nb,
+				  unsigned long code, void *unused)
+{
+	struct linux_efi_random_seed *seed;
+	u32 size = 0;
+
+	if (!kexec_in_progress)
+		return NOTIFY_DONE;
+
+	seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
+	if (seed != NULL) {
+		size = min(seed->size, 32U);
+		memunmap(seed);
+	} else {
+		pr_err("Could not map UEFI random seed!\n");
+	}
+	if (size > 0) {
+		seed = memremap(efi.rng_seed, sizeof(*seed) + size,
+				MEMREMAP_WB);
+		if (seed != NULL) {
+			seed->size = size;
+			get_random_bytes(seed->bits, seed->size);
+			memunmap(seed);
+		} else {
+			pr_err("Could not map UEFI random seed!\n");
+		}
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block efi_random_seed_nb = {
+	.notifier_call = update_efi_random_seed,
+};
+
+static int register_update_efi_random_seed(void)
+{
+	if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
+		return 0;
+	return register_reboot_notifier(&efi_random_seed_nb);
+}
+late_initcall(register_update_efi_random_seed);
+#endif
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 2d089487d2da..85e28b138cdd 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -599,6 +599,7 @@ void efi_native_runtime_setup(void);
  */
 #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID	EFI_GUID(0xe03fc20a, 0x85dc, 0x406e,  0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
 #define LINUX_EFI_LOADER_ENTRY_GUID		EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf,  0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
+#define LINUX_EFI_RANDOM_SEED_TABLE_GUID	EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2,  0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
 
 typedef struct {
 	efi_guid_t guid;
@@ -872,6 +873,7 @@ extern struct efi {
 	unsigned long esrt;		/* ESRT table */
 	unsigned long properties_table;	/* properties table */
 	unsigned long mem_attr_table;	/* memory attributes table */
+	unsigned long rng_seed;		/* UEFI firmware random seed */
 	efi_get_time_t *get_time;
 	efi_set_time_t *set_time;
 	efi_get_wakeup_time_t *get_wakeup_time;
@@ -1493,4 +1495,10 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table,
 				    struct efi_boot_memmap *map,
 				    void *priv,
 				    efi_exit_boot_map_processing priv_func);
+
+struct linux_efi_random_seed {
+	u32	size;
+	u8	bits[];
+};
+
 #endif /* _LINUX_EFI_H */
-- 
2.10.0

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[GIT PULL 0/9] EFI changes for v4.10 Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
  [PATCH 3/9] efi: Add support for seeding the RNG from a UEFI config table Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
    [tip:efi/core] efi: Add support for seeding the RNG from a UEFI  config table tip-bot for Ard Biesheuvel <tipbot@zytor.com> - 2016-11-13 10:10 +0100
  [PATCH 4/9] efi/libstub: Add random.c to ARM build Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
    [tip:efi/core] efi/libstub: Add random.c to ARM build tip-bot for Ard Biesheuvel <tipbot@zytor.com> - 2016-11-13 10:10 +0100
  [PATCH 2/9] MAINTAINERS: Add ARM and arm64 EFI specific files to EFI subsystem Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
    [tip:efi/core] MAINTAINERS: Add ARM and arm64 EFI specific files to  EFI subsystem tip-bot for Ard Biesheuvel <tipbot@zytor.com> - 2016-11-13 10:10 +0100
  [PATCH 7/9] efi: Allow bitness-agnostic protocol calls Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
    [tip:efi/core] efi: Allow bitness-agnostic protocol calls tip-bot for Lukas Wunner <tipbot@zytor.com> - 2016-11-13 10:10 +0100
  [PATCH 8/9] x86/efi: Retrieve and assign Apple device properties Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
    [tip:efi/core] x86/efi: Retrieve and assign Apple device properties tip-bot for Lukas Wunner <tipbot@zytor.com> - 2016-11-13 10:20 +0100
  [PATCH 5/9] efi/arm*: libstub: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
    Re: [PATCH 5/9] efi/arm*: libstub: Invoke EFI_RNG_PROTOCOL to seed  the UEFI RNG table Ingo Molnar <mingo@kernel.org> - 2016-11-13 08:20 +0100
      Re: [PATCH 5/9] efi/arm*: libstub: Invoke EFI_RNG_PROTOCOL to seed  the UEFI RNG table Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-14 14:30 +0100
        Re: [PATCH 5/9] efi/arm*: libstub: Invoke EFI_RNG_PROTOCOL to seed  the UEFI RNG table Ingo Molnar <mingo@kernel.org> - 2016-11-14 15:00 +0100
          Re: [PATCH 5/9] efi/arm*: libstub: Invoke EFI_RNG_PROTOCOL to seed  the UEFI RNG table Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-14 15:10 +0100
      Re: [PATCH 5/9] efi/arm*: libstub: Invoke EFI_RNG_PROTOCOL to seed  the UEFI RNG table Lukas Wunner <lukas@wunner.de> - 2016-11-14 16:10 +0100
        [tip:efi/core] thunderbolt, efi: Fix Kconfig dependencies tip-bot for Lukas Wunner <tipbot@zytor.com> - 2016-11-15 12:00 +0100
    [tip:efi/core] efi/arm*/libstub: Invoke EFI_RNG_PROTOCOL to seed  the UEFI RNG table tip-bot for Ard Biesheuvel <tipbot@zytor.com> - 2016-11-13 10:10 +0100
  [PATCH 1/9] efi/libstub: Fix allocation size calculations Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
    [tip:efi/core] efi/libstub: Fix allocation size calculations tip-bot for Roy Franz <tipbot@zytor.com> - 2016-11-13 10:10 +0100
  [PATCH 9/9] thunderbolt: Use Device ROM retrieved from EFI Matt Fleming <matt@codeblueprint.co.uk> - 2016-11-12 22:40 +0100
    [tip:efi/core] thunderbolt: Use Device ROM retrieved from EFI tip-bot for Lukas Wunner <tipbot@zytor.com> - 2016-11-13 10:20 +0100

csiph-web