From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ard Biesheuvel Subject: Re: [PATCH v2 1/3] efi: add support for seeding the RNG from a UEFI config table Date: Thu, 20 Oct 2016 12:26:09 +0100 Message-ID: References: <1476962486-18368-1-git-send-email-ard.biesheuvel@linaro.org> <1476962486-18368-2-git-send-email-ard.biesheuvel@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Return-path: In-Reply-To: <1476962486-18368-2-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> Sender: linux-efi-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: "linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org" , "linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" , Mark Rutland , Matt Fleming , Kees Cook Cc: Theodore Ts'o , Ard Biesheuvel List-Id: linux-efi@vger.kernel.org On 20 October 2016 at 12:21, 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. > > 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 > --- > 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 > #include > #include > +#include > +#include > #include > #include > #include > @@ -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 >