Hi Ard, On Thu, Oct 06, 2016 at 11:27:25AM +0100, Ard Biesheuvel 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. > > 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) What does this mean for kexec? Won't each successive kernel look for the table and find the same seed? I think to some extent this mush be treated as an ABI, given cases like kexec. Thanks, Mark. > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> > --- > drivers/firmware/efi/efi.c | 26 ++++++++++++++++++++ > include/linux/efi.h | 8 ++++++ > 2 files changed, 34 insertions(+) > > diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c > index 1ac199cd75e7..c8ae40f9b674 100644 > --- a/drivers/firmware/efi/efi.c > +++ b/drivers/firmware/efi/efi.c > @@ -24,6 +24,7 @@ > #include <linux/of_fdt.h> > #include <linux/io.h> > #include <linux/platform_device.h> > +#include <linux/random.h> > #include <linux/slab.h> > #include <linux/acpi.h> > #include <linux/ucs2_string.h> > @@ -48,6 +49,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 +440,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 +502,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; > 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 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-efi" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html