^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2016 Linaro Ltd; <ard.biesheuvel@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <asm/efi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "efistub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) typedef union efi_rng_protocol efi_rng_protocol_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) union efi_rng_protocol {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) efi_status_t (__efiapi *get_info)(efi_rng_protocol_t *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) unsigned long *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) efi_guid_t *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) efi_status_t (__efiapi *get_rng)(efi_rng_protocol_t *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) efi_guid_t *, unsigned long,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) u8 *out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) u32 get_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u32 get_rng;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) } mixed_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * efi_get_random_bytes() - fill a buffer with random bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * @size: size of the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @out: caller allocated buffer to receive the random bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * The call will fail if either the firmware does not implement the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * EFI_RNG_PROTOCOL or there are not enough random bytes available to fill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Return: status code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) efi_status_t efi_get_random_bytes(unsigned long size, u8 *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) efi_rng_protocol_t *rng = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return efi_call_proto(rng, get_rng, NULL, size, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * efi_random_get_seed() - provide random seed as configuration table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * The EFI_RNG_PROTOCOL is used to read random bytes. These random bytes are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * saved as a configuration table which can be used as entropy by the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * for the initialization of its pseudo random number generator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * If the EFI_RNG_PROTOCOL is not available or there are not enough random bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * available, the configuration table will not be installed and an error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * will be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * Return: status code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) efi_status_t efi_random_get_seed(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) efi_rng_protocol_t *rng = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct linux_efi_random_seed *seed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) efi_status_t status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) status = efi_bs_call(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) (void **)&seed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) status = efi_call_proto(rng, get_rng, &rng_algo_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) EFI_RANDOM_SEED_SIZE, seed->bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (status == EFI_UNSUPPORTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Use whatever algorithm we have available if the raw algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * is not implemented.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) status = efi_call_proto(rng, get_rng, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) EFI_RANDOM_SEED_SIZE, seed->bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) goto err_freepool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) seed->size = EFI_RANDOM_SEED_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) status = efi_bs_call(install_configuration_table, &rng_table_guid, seed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (status != EFI_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) goto err_freepool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return EFI_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) err_freepool:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) efi_bs_call(free_pool, seed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }