linux-efi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] efi: add support for seeding the kernel RNG from UEFI
@ 2016-10-20 11:21 Ard Biesheuvel
       [not found] ` <1476962486-18368-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2016-10-20 11:21 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	matt-mF/unelCI9GS6iBeEJttW/XRex20P6io,
	keescook-F7+t8E8rja9g9hUCZPvPmw
  Cc: tytso-3s7WtUTddSA, Ard Biesheuvel

This implements generic EFI core kernel code to seed the kernel entropy
pool from a Linux specific UEFI configuration table containing a random seed
supplied by the firmware. (#1)

In addition, it wires it up for ARM and arm64, by invoking the EFI_RNG_PROTOCOL
UEFI protocol from the stub, and populating such a UEFI config table using its
output.

Changes since v1:
- Add a patch to actually build random.c for the ARM version of the stub, so
  that the functionality that patch #3 adds is available on ARM as well as arm64
- Handle the kexec case, by updating the seed in the configuration table on
  reboot.

How to wire this up for x86 is left as an exercise for the Intel developer.

Ard Biesheuvel (3):
  efi: add support for seeding the RNG from a UEFI config table
  efi/libstub: add random.c to ARM build
  efi/arm*: libstub: invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table

 drivers/firmware/efi/efi.c                     | 67 ++++++++++++++++++++
 drivers/firmware/efi/libstub/Makefile          |  4 +-
 drivers/firmware/efi/libstub/arm-stub.c        |  2 +
 drivers/firmware/efi/libstub/efi-stub-helper.c |  9 ---
 drivers/firmware/efi/libstub/efistub.h         | 11 ++++
 drivers/firmware/efi/libstub/random.c          | 48 ++++++++++++++
 include/linux/efi.h                            |  9 +++
 7 files changed, 139 insertions(+), 11 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/3] efi: add support for seeding the RNG from a UEFI config table
       [not found] ` <1476962486-18368-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2016-10-20 11:21   ` Ard Biesheuvel
       [not found]     ` <1476962486-18368-2-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2016-10-20 11:21   ` [PATCH v2 2/3] efi/libstub: add random.c to ARM build Ard Biesheuvel
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2016-10-20 11:21 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	matt-mF/unelCI9GS6iBeEJttW/XRex20P6io,
	keescook-F7+t8E8rja9g9hUCZPvPmw
  Cc: tytso-3s7WtUTddSA, Ard Biesheuvel

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)

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/firmware/efi/efi.c | 67 ++++++++++++++++++++
 include/linux/efi.h        |  8 +++
 2 files changed, 75 insertions(+)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 1ac199cd75e7..47937ffd9f2f 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -24,6 +24,8 @@
 #include <linux/of_fdt.h>
 #include <linux/io.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 +50,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);
 
@@ -438,6 +441,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},
 };
 
@@ -499,6 +503,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;
@@ -822,3 +849,43 @@ 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;
+
+	seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
+	if (seed != NULL) {
+		size = seed->size;
+		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) {
+			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.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/3] efi/libstub: add random.c to ARM build
       [not found] ` <1476962486-18368-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2016-10-20 11:21   ` [PATCH v2 1/3] efi: add support for seeding the RNG from a UEFI config table Ard Biesheuvel
@ 2016-10-20 11:21   ` Ard Biesheuvel
       [not found]     ` <1476962486-18368-3-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2016-10-20 11:21   ` [PATCH v2 3/3] efi/arm*: libstub: invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table Ard Biesheuvel
  2016-10-20 18:34   ` [PATCH v2 0/3] efi: add support for seeding the kernel RNG from UEFI Kees Cook
  3 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2016-10-20 11:21 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	matt-mF/unelCI9GS6iBeEJttW/XRex20P6io,
	keescook-F7+t8E8rja9g9hUCZPvPmw
  Cc: tytso-3s7WtUTddSA, Ard Biesheuvel

Make random.c build for ARM by moving the fallback definition of
EFI_ALLOC_ALIGN to efistub.h

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/firmware/efi/libstub/Makefile          | 4 ++--
 drivers/firmware/efi/libstub/efi-stub-helper.c | 9 ---------
 drivers/firmware/efi/libstub/efistub.h         | 9 +++++++++
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index c06945160a41..40ddf8f763a8 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -36,11 +36,11 @@ arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c 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 \
+lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o random.o \
 				   $(patsubst %.c,lib-%.o,$(arm-deps))
 
 lib-$(CONFIG_ARM)		+= arm32-stub.o
-lib-$(CONFIG_ARM64)		+= arm64-stub.o random.o
+lib-$(CONFIG_ARM64)		+= arm64-stub.o
 CFLAGS_arm64-stub.o 		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 #
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index aded10662020..3c2fe209bbfe 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,15 +32,6 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
-/*
- * Allow the platform to override the allocation granularity: this allows
- * systems that have the capability to run with a larger page size to deal
- * with the allocations for initrd and fdt more efficiently.
- */
-#ifndef EFI_ALLOC_ALIGN
-#define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
-#endif
-
 #define EFI_MMAP_NR_SLACK_SLOTS	8
 
 struct file_info {
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index ee49cd23ee63..fe1f22584c69 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -15,6 +15,15 @@
  */
 #undef __init
 
+/*
+ * Allow the platform to override the allocation granularity: this allows
+ * systems that have the capability to run with a larger page size to deal
+ * with the allocations for initrd and fdt more efficiently.
+ */
+#ifndef EFI_ALLOC_ALIGN
+#define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
+#endif
+
 void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/3] efi/arm*: libstub: invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table
       [not found] ` <1476962486-18368-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
  2016-10-20 11:21   ` [PATCH v2 1/3] efi: add support for seeding the RNG from a UEFI config table Ard Biesheuvel
  2016-10-20 11:21   ` [PATCH v2 2/3] efi/libstub: add random.c to ARM build Ard Biesheuvel
@ 2016-10-20 11:21   ` Ard Biesheuvel
  2016-10-20 18:34   ` [PATCH v2 0/3] efi: add support for seeding the kernel RNG from UEFI Kees Cook
  3 siblings, 0 replies; 9+ messages in thread
From: Ard Biesheuvel @ 2016-10-20 11:21 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	matt-mF/unelCI9GS6iBeEJttW/XRex20P6io,
	keescook-F7+t8E8rja9g9hUCZPvPmw
  Cc: tytso-3s7WtUTddSA, Ard Biesheuvel

Invoke the EFI_RNG_PROTOCOL protocol in the context of the stub and
install the Linux-specific RNG seed UEFI config table. This will be
picked up by the EFI routines in the core kernel to seed the kernel
entropy pool.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 drivers/firmware/efi/libstub/arm-stub.c |  2 +
 drivers/firmware/efi/libstub/efistub.h  |  2 +
 drivers/firmware/efi/libstub/random.c   | 48 ++++++++++++++++++++
 include/linux/efi.h                     |  1 +
 4 files changed, 53 insertions(+)

diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 993aa56755f6..b4f7d78f9e8b 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -340,6 +340,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
 	if (status != EFI_SUCCESS)
 		pr_efi_err(sys_table, "Failed initrd from command line!\n");
 
+	efi_random_get_seed(sys_table);
+
 	new_fdt_addr = fdt_addr;
 	status = allocate_new_fdt_and_exit_boot(sys_table, handle,
 				&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index fe1f22584c69..b98824e3800a 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -71,4 +71,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);
+
 #endif
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 0c9f58c5ba50..4aa35c4fe029 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -141,3 +141,51 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
 
 	return status;
 }
+
+#define RANDOM_SEED_SIZE	32
+
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
+{
+	efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
+	efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
+	efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
+	struct efi_rng_protocol *rng;
+	struct linux_efi_random_seed *seed;
+	efi_status_t status;
+
+	status = efi_call_early(locate_protocol, &rng_proto, NULL,
+				(void **)&rng);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
+				sizeof(*seed) + RANDOM_SEED_SIZE,
+				(void **)&seed);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = rng->get_rng(rng, &rng_algo_raw, 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, RANDOM_SEED_SIZE,
+				      seed->bits);
+
+	if (status != EFI_SUCCESS)
+		goto err_freepool;
+
+	seed->size = RANDOM_SEED_SIZE;
+	status = efi_call_early(install_configuration_table, &rng_table_guid,
+				seed);
+	if (status != EFI_SUCCESS)
+		goto err_freepool;
+
+	return EFI_SUCCESS;
+
+err_freepool:
+	efi_call_early(free_pool, seed);
+	return status;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 85e28b138cdd..f5a821d9b90c 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -589,6 +589,7 @@ void efi_native_runtime_setup(void);
 #define DEVICE_TREE_GUID			EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5,  0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
 #define EFI_PROPERTIES_TABLE_GUID		EFI_GUID(0x880aaca3, 0x4adc, 0x4a04,  0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5)
 #define EFI_RNG_PROTOCOL_GUID			EFI_GUID(0x3152bca5, 0xeade, 0x433d,  0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
+#define EFI_RNG_ALGORITHM_RAW			EFI_GUID(0xe43176d7, 0xb6e8, 0x4827,  0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61)
 #define EFI_MEMORY_ATTRIBUTES_TABLE_GUID	EFI_GUID(0xdcfa911d, 0x26eb, 0x469f,  0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20)
 #define EFI_CONSOLE_OUT_DEVICE_GUID		EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4,  0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/3] efi: add support for seeding the RNG from a UEFI config table
       [not found]     ` <1476962486-18368-2-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2016-10-20 11:26       ` Ard Biesheuvel
  0 siblings, 0 replies; 9+ messages in thread
From: Ard Biesheuvel @ 2016-10-20 11:26 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Mark Rutland, Matt Fleming,
	Kees Cook
  Cc: Theodore Ts'o, Ard Biesheuvel

On 20 October 2016 at 12:21, Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> 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)
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  drivers/firmware/efi/efi.c | 67 ++++++++++++++++++++
>  include/linux/efi.h        |  8 +++
>  2 files changed, 75 insertions(+)
>
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 1ac199cd75e7..47937ffd9f2f 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -24,6 +24,8 @@
>  #include <linux/of_fdt.h>
>  #include <linux/io.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 +50,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);
>
> @@ -438,6 +441,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},
>  };
>
> @@ -499,6 +503,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;
> @@ -822,3 +849,43 @@ 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;
> +

I forgot to git-add this bit here:

+       if (!kexec_in_progress)
+               return NOTIFY_DONE;
+

> +       seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
> +       if (seed != NULL) {
> +               size = seed->size;
> +               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) {
> +                       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.7.4
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/3] efi: add support for seeding the kernel RNG from UEFI
       [not found] ` <1476962486-18368-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
                     ` (2 preceding siblings ...)
  2016-10-20 11:21   ` [PATCH v2 3/3] efi/arm*: libstub: invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table Ard Biesheuvel
@ 2016-10-20 18:34   ` Kees Cook
  3 siblings, 0 replies; 9+ messages in thread
From: Kees Cook @ 2016-10-20 18:34 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Mark Rutland, Matt Fleming,
	Ted Ts'o

On Thu, Oct 20, 2016 at 4:21 AM, Ard Biesheuvel
<ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> This implements generic EFI core kernel code to seed the kernel entropy
> pool from a Linux specific UEFI configuration table containing a random seed
> supplied by the firmware. (#1)
>
> In addition, it wires it up for ARM and arm64, by invoking the EFI_RNG_PROTOCOL
> UEFI protocol from the stub, and populating such a UEFI config table using its
> output.

Looks good to me! Now that I understand it. ;)

Reviewed-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

-Kees

-- 
Kees Cook
Nexus Security

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] efi/libstub: add random.c to ARM build
       [not found]     ` <1476962486-18368-3-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2016-11-02  9:37       ` Ard Biesheuvel
       [not found]         ` <CAKv+Gu_=et=2zHBTYOr9thz2kS0cXHHYg96oWGRdD3D10fqXtw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2016-11-02  9:37 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Mark Rutland, Matt Fleming,
	Kees Cook
  Cc: Theodore Ts'o, Ard Biesheuvel

On 20 October 2016 at 12:21, Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> Make random.c build for ARM by moving the fallback definition of
> EFI_ALLOC_ALIGN to efistub.h
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  drivers/firmware/efi/libstub/Makefile          | 4 ++--
>  drivers/firmware/efi/libstub/efi-stub-helper.c | 9 ---------
>  drivers/firmware/efi/libstub/efistub.h         | 9 +++++++++
>  3 files changed, 11 insertions(+), 11 deletions(-)
>

I need the following hunks on top to make this build on ARM:

""
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -8,6 +8,7 @@
  */

 #include <linux/efi.h>
+#include <linux/log2.h>
 #include <asm/efi.h>

 #include "efistub.h"
@@ -41,8 +42,9 @@
  */
 static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
                                         unsigned long size,
-                                        unsigned long align)
+                                        unsigned long align_shift)
 {
+       unsigned long align = 1UL << align_shift;
        u64 start, end;

        if (md->type != EFI_CONVENTIONAL_MEMORY)
@@ -55,7 +57,7 @@
        if (start > end)
                return 0;

-       return (end - start + 1) / align;
+       return (end - start + 1) >> align_shift;
 }

 /*
@@ -98,7 +100,7 @@
                efi_memory_desc_t *md = (void *)memory_map + map_offset;
                unsigned long slots;

-               slots = get_entry_num_slots(md, size, align);
+               slots = get_entry_num_slots(md, size, ilog2(align));
                MD_NUM_SLOTS(md) = slots;
                total_slots += slots;
        }
"""

This is because ARM does not have a division routine in the
decompressor, and the fact that the division by 'align' should always
involve a power of 2 is not visible to the compiler.

If nobody objects, I will fold this in when applying

Thanks,
Ard.


> diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
> index c06945160a41..40ddf8f763a8 100644
> --- a/drivers/firmware/efi/libstub/Makefile
> +++ b/drivers/firmware/efi/libstub/Makefile
> @@ -36,11 +36,11 @@ arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c 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 \
> +lib-$(CONFIG_EFI_ARMSTUB)      += arm-stub.o fdt.o string.o random.o \
>                                    $(patsubst %.c,lib-%.o,$(arm-deps))
>
>  lib-$(CONFIG_ARM)              += arm32-stub.o
> -lib-$(CONFIG_ARM64)            += arm64-stub.o random.o
> +lib-$(CONFIG_ARM64)            += arm64-stub.o
>  CFLAGS_arm64-stub.o            := -DTEXT_OFFSET=$(TEXT_OFFSET)
>
>  #
> diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
> index aded10662020..3c2fe209bbfe 100644
> --- a/drivers/firmware/efi/libstub/efi-stub-helper.c
> +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
> @@ -32,15 +32,6 @@
>
>  static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
>
> -/*
> - * Allow the platform to override the allocation granularity: this allows
> - * systems that have the capability to run with a larger page size to deal
> - * with the allocations for initrd and fdt more efficiently.
> - */
> -#ifndef EFI_ALLOC_ALIGN
> -#define EFI_ALLOC_ALIGN                EFI_PAGE_SIZE
> -#endif
> -
>  #define EFI_MMAP_NR_SLACK_SLOTS        8
>
>  struct file_info {
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index ee49cd23ee63..fe1f22584c69 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -15,6 +15,15 @@
>   */
>  #undef __init
>
> +/*
> + * Allow the platform to override the allocation granularity: this allows
> + * systems that have the capability to run with a larger page size to deal
> + * with the allocations for initrd and fdt more efficiently.
> + */
> +#ifndef EFI_ALLOC_ALIGN
> +#define EFI_ALLOC_ALIGN                EFI_PAGE_SIZE
> +#endif
> +
>  void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
>
>  efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] efi/libstub: add random.c to ARM build
       [not found]         ` <CAKv+Gu_=et=2zHBTYOr9thz2kS0cXHHYg96oWGRdD3D10fqXtw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2016-11-15 15:11           ` Arnd Bergmann
  2016-11-15 15:19             ` Ard Biesheuvel
  0 siblings, 1 reply; 9+ messages in thread
From: Arnd Bergmann @ 2016-11-15 15:11 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Ard Biesheuvel, linux-efi-u79uwXL29TY76Z2rM5mHXA, Mark Rutland,
	Matt Fleming, Kees Cook, Theodore Ts'o

On Wednesday, November 2, 2016 9:37:13 AM CET Ard Biesheuvel wrote:
> @@ -98,7 +100,7 @@
>                 efi_memory_desc_t *md = (void *)memory_map + map_offset;
>                 unsigned long slots;
> 
> -               slots = get_entry_num_slots(md, size, align);
> +               slots = get_entry_num_slots(md, size, ilog2(align));
>                 MD_NUM_SLOTS(md) = slots;
>                 total_slots += slots;
>         }
> """
> 
> This is because ARM does not have a division routine in the
> decompressor, and the fact that the division by 'align' should always
> involve a power of 2 is not visible to the compiler.
> 
> If nobody objects, I will fold this in when applying
> 
> 

I'm getting a link error here when building with -Os:

drivers/firmware/efi/libstub/random.stub.o: In function `efi_random_alloc':
random.c:(.text.efi_random_alloc+0x264): undefined reference to `__aeabi_llsr'

If I compile this with -O2, the ilog2 gets inlined and everything
works.

	Arnd

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] efi/libstub: add random.c to ARM build
  2016-11-15 15:11           ` Arnd Bergmann
@ 2016-11-15 15:19             ` Ard Biesheuvel
  0 siblings, 0 replies; 9+ messages in thread
From: Ard Biesheuvel @ 2016-11-15 15:19 UTC (permalink / raw)
  To: Arnd Bergmann, Matt Fleming
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, Mark Rutland, Kees Cook,
	Theodore Ts'o

On 15 November 2016 at 15:11, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> On Wednesday, November 2, 2016 9:37:13 AM CET Ard Biesheuvel wrote:
>> @@ -98,7 +100,7 @@
>>                 efi_memory_desc_t *md = (void *)memory_map + map_offset;
>>                 unsigned long slots;
>>
>> -               slots = get_entry_num_slots(md, size, align);
>> +               slots = get_entry_num_slots(md, size, ilog2(align));
>>                 MD_NUM_SLOTS(md) = slots;
>>                 total_slots += slots;
>>         }
>> """
>>
>> This is because ARM does not have a division routine in the
>> decompressor, and the fact that the division by 'align' should always
>> involve a power of 2 is not visible to the compiler.
>>
>> If nobody objects, I will fold this in when applying
>>
>>
>
> I'm getting a link error here when building with -Os:
>
> drivers/firmware/efi/libstub/random.stub.o: In function `efi_random_alloc':
> random.c:(.text.efi_random_alloc+0x264): undefined reference to `__aeabi_llsr'
>
> If I compile this with -O2, the ilog2 gets inlined and everything
> works.
>

This is caused by the fact that 'start' and 'end are u64 rather than
unsigned long, and the stub does not have the u64 logical shift right
routines.
But interestingly, it does cover another issue with this code, i.e.,
that you cannot do allocations over 4 GB in the ARM stub, even on LPAE
capable hardware.

I will send out a patch to fix this.

Thanks,
Ard.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-11-15 15:19 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-20 11:21 [PATCH v2 0/3] efi: add support for seeding the kernel RNG from UEFI Ard Biesheuvel
     [not found] ` <1476962486-18368-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-10-20 11:21   ` [PATCH v2 1/3] efi: add support for seeding the RNG from a UEFI config table Ard Biesheuvel
     [not found]     ` <1476962486-18368-2-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-10-20 11:26       ` Ard Biesheuvel
2016-10-20 11:21   ` [PATCH v2 2/3] efi/libstub: add random.c to ARM build Ard Biesheuvel
     [not found]     ` <1476962486-18368-3-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-11-02  9:37       ` Ard Biesheuvel
     [not found]         ` <CAKv+Gu_=et=2zHBTYOr9thz2kS0cXHHYg96oWGRdD3D10fqXtw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-11-15 15:11           ` Arnd Bergmann
2016-11-15 15:19             ` Ard Biesheuvel
2016-10-20 11:21   ` [PATCH v2 3/3] efi/arm*: libstub: invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table Ard Biesheuvel
2016-10-20 18:34   ` [PATCH v2 0/3] efi: add support for seeding the kernel RNG from UEFI Kees Cook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).