Re: [PATCH 3/3] efi: random: combine bootloader provided RNG seed with RNG protocol output

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Sep 19, 2022 at 6:09 PM Ard Biesheuvel <ardb@xxxxxxxxxx> wrote:
>
> Instead of blindly creating the EFI random seed configuration table if
> the RNG protocol is implemented and works, check whether such a EFI
> configuration table was provided by an earlier boot stage and if so,
> combine its contents with a Linux specific personalization string, and
> if available, mix in the output of the RNG protocol as well.
>
> This can be used for, e.g., systemd-boot, to pass an additional seed to
> Linux in a way that can be consumed by the kernel very early. In that
> case, the following definitions should be used to pass the seed to the
> EFI stub:
>
>   struct linux_efi_random_seed {
>           u32     size; // of the 'seed' array in bytes
>           u8      seed[];
>   };
>
> The memory for the struct must be allocated as EFI_ACPI_RECLAIM_MEMORY
> pool memory, and the address of the struct in memory should be installed
> as a EFI configuration table using the following GUID:
>
> LINUX_EFI_RANDOM_SEED_TABLE_GUID        1ce1e5bc-7ceb-42f2-81e5-8aadf180f57b
>
> Note that doing so is safe even on kernels that were built without this
> patch applied, but the seed will simply be overwritten with a seed
> derived from the EFI RNG protocol, if available. The recommended seed
> size is 32 bytes, anything beyond that is mixed in but not reflected in
> the final seed size.
>
> Suggested-by: "Jason A. Donenfeld" <Jason@xxxxxxxxx>
> Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx>
> ---
>  drivers/firmware/efi/libstub/Makefile  |  4 +
>  drivers/firmware/efi/libstub/efistub.h |  2 +
>  drivers/firmware/efi/libstub/random.c  | 79 ++++++++++++--------
>  include/linux/efi.h                    |  2 -
>  lib/crypto/blake2s-generic.c           |  2 +
>  lib/crypto/blake2s.c                   |  7 +-
>  6 files changed, 60 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
> index d0537573501e..3b3c67001566 100644
> --- a/drivers/firmware/efi/libstub/Makefile
> +++ b/drivers/firmware/efi/libstub/Makefile
> @@ -55,6 +55,7 @@ KCOV_INSTRUMENT                       := n
>  lib-y                          := efi-stub-helper.o gop.o secureboot.o tpm.o \
>                                    file.o mem.o random.o randomalloc.o pci.o \
>                                    skip_spaces.o lib-cmdline.o lib-ctype.o \
> +                                  libcrypto-blake2s.o libcrypto-blake2s-generic.o \
>                                    alignedmem.o relocate.o vsprintf.o
>
>  # include the stub's generic dependencies from lib/ when building for ARM/arm64
> @@ -63,6 +64,9 @@ efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
>  $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
>         $(call if_changed_rule,cc_o_c)
>
> +$(obj)/libcrypto-%.o: $(srctree)/lib/crypto/%.c FORCE
> +       $(call if_changed_rule,cc_o_c)
> +
>  lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o \
>                                    $(patsubst %.c,lib-%.o,$(efi-deps-y))
>
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index b0ae0a454404..fc32897de5e8 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -873,6 +873,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
>  efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
>                               unsigned long *addr, unsigned long random_seed);
>
> +void efi_random_get_seed(void);
> +
>  efi_status_t check_platform_features(void);
>
>  void *get_efi_config_table(efi_guid_t guid);
> diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
> index 183dc5cdb8ed..87fcd73ef615 100644
> --- a/drivers/firmware/efi/libstub/random.c
> +++ b/drivers/firmware/efi/libstub/random.c
> @@ -5,6 +5,7 @@
>
>  #include <linux/efi.h>
>  #include <asm/efi.h>
> +#include <crypto/blake2s.h>
>
>  #include "efistub.h"
>
> @@ -49,60 +50,74 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out)
>         return efi_call_proto(rng, get_rng, NULL, size, out);
>  }
>
> +static char const pstr[] = "Linux EFI Stub RNG Seed Label v1";
> +
>  /**
>   * efi_random_get_seed() - provide random seed as configuration table
>   *
>   * The EFI_RNG_PROTOCOL is used to read random bytes. These random bytes are
>   * saved as a configuration table which can be used as entropy by the kernel
>   * for the initialization of its pseudo random number generator.
> - *
> - * If the EFI_RNG_PROTOCOL is not available or there are not enough random bytes
> - * available, the configuration table will not be installed and an error code
> - * will be returned.
> - *
> - * Return:     status code
>   */
> -efi_status_t efi_random_get_seed(void)
> +void efi_random_get_seed(void)
>  {
>         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;
>         efi_rng_protocol_t *rng = NULL;
>         struct linux_efi_random_seed *seed = NULL;
> +       struct blake2s_state state;
> +       unsigned int total_len = 0;
>         efi_status_t status;
>
> -       status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
> -       if (status != EFI_SUCCESS)
> -               return status;
> +       // grab the EFI RNG protocol, if it exists
> +       efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
>
> -       status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
> -                            sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
> -                            (void **)&seed);
> -       if (status != EFI_SUCCESS)
> -               return status;
> +       // grab the seed provided by the previous boot stages
> +       seed = get_efi_config_table(LINUX_EFI_RANDOM_SEED_TABLE_GUID);
> +
> +       // if neither exists, there is little we can do
> +       if (!seed && !rng)
> +               return;
> +
> +       blake2s_init(&state, EFI_RANDOM_SEED_SIZE);
> +       blake2s_update(&state, pstr, sizeof(pstr) - 1);
> +
> +       if (seed) {
> +               blake2s_update(&state, (void *)&seed->size, sizeof(seed->size));
> +               blake2s_update(&state, seed->bits, seed->size);

Since this is never freed, and also just for hygiene, add:

memzero_explicit(seed, sizeof(seed));



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux