mirror of
https://github.com/systemd/systemd.git
synced 2026-06-24 08:47:49 +00:00
stub: introduce "boot secret" stored in an EFI variable inaccessible to the OS
This commit is contained in:
@@ -655,6 +655,17 @@
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>LoaderBootSecret</varname></term>
|
||||
|
||||
<listitem><para>A non-volatile EFI variable only accessible from the pre-boot environment
|
||||
(i.e. access from the OS is not permitted) that contains a per-system secret. It is set automatically
|
||||
by <command>systemd-stub</command> if not present already. A secret derived from the value of this
|
||||
EFI variable is passed to the OS in <filename>/.extra/boot-secret</filename>, see below.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>Note that some of the variables above may also be set by the boot loader. The stub will only set
|
||||
@@ -762,6 +773,33 @@
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>/.extra/boot-secret</filename></term>
|
||||
<listitem><para>A 32 byte per-system secret which is derived from a 32 byte secret stored in an EFI
|
||||
variable (<varname>LoaderBootSecret</varname>, see above), which itself is only accessible to the
|
||||
pre-boot environment. This may be used for various early-boot cryptographic purposes, and OS file
|
||||
system access to it is restricted to root. The <varname>IMAGE_ID=</varname>/<varname>ID=</varname>
|
||||
data from the <literal>.osrel</literal> is hashed into the secret, to ensure that different images
|
||||
get a distinct secret passed. Moreover, a randomized 32 byte value stored in the ESP in the
|
||||
<literal>/loader/boot-secret-mixin</literal> file is hashed in as well, ensuring that distinct disks will
|
||||
result in different boot secrets.</para>
|
||||
|
||||
<para>Note: this boot secret is ultimately protected only by firmware-enforced access controls on the
|
||||
EFI variable. This is generally a much weaker protection than TPM-based approaches have, and it is
|
||||
hence strongly recommended to use the TPM on systems that possess one. The boot secret is primarily
|
||||
intended to be a lower-security fallback for cases where a TPM is not available.</para>
|
||||
|
||||
<para>Applications should never protect resources directly with this secret, but derive their own
|
||||
secret from it (by hashing it together with some application ID, in HMAC mode for example), in order
|
||||
not to accidentally leak the primary boot secret.</para>
|
||||
|
||||
<para>Note that the boot secret is only available if the pre-boot environment had a suitable RNG
|
||||
source at the current boot or an earlier one. This source can be an initialized on-disk
|
||||
random seed or the EFI RNG support, or both.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>Note that all these files are located in the <literal>tmpfs</literal> file system the kernel sets
|
||||
|
||||
374
src/boot/boot-secret.c
Normal file
374
src/boot/boot-secret.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "boot-secret.h"
|
||||
#include "efi-efivars.h"
|
||||
#include "efi-log.h"
|
||||
#include "random-seed.h"
|
||||
#include "sha256-fundamental.h"
|
||||
#include "util.h"
|
||||
|
||||
#define BOOT_SECRET_MIXIN_PATH u"\\loader\\boot-secret-mixin"
|
||||
|
||||
/* This maintains a per-system secret that is stored in an EFI variable that is only accessible during EFI
|
||||
* boot, and becomes inaccessible afterwards, once ExitBootServices() is called. The variable is
|
||||
* automatically initialized if missing. A secret derived by hashing from this EFI variable secret is then
|
||||
* passed to the OS, in an initrd file inaccessible to unprivileged userspace. To make things a bit more
|
||||
* robust while hashing two more pieces of information are mixed in: a random "mixin" that is stored in the
|
||||
* ESP and is supposed to ensure that the passed boot secrets are distinct for each disk used on the system;
|
||||
* moreover an OS identifier derived from the UKI's .osrel field (ideally IMAGE_ID=, but if not defined ID=
|
||||
* will do, with a final fallback to "linux"). Note that these two additions are not supposed to enhance the
|
||||
* cryptographic quality of the secret, they are just supposed to make things more robust on systems with
|
||||
* multiple disks and OSes.
|
||||
*
|
||||
* The boot secret passed to the OS can be used to protect resources during OS runtime, from earliest boot
|
||||
* phases on, as a fallback for the usual TPM based protections.
|
||||
*
|
||||
* Note that this secret comes with much weaker protection than TPM backed secrets: there's no physical
|
||||
* isolation, there are no cryptographic access policies, there's just the hope the firmware reasonably
|
||||
* correctly implements boot-time-only EFI variable mechanism. (But then again, this is what mok/shim's
|
||||
* security also relies on, and hence this all is not too bad?) */
|
||||
|
||||
static EFI_STATUS random_seed_find_table(struct linux_efi_random_seed **ret) {
|
||||
assert(ret);
|
||||
|
||||
/* We use the Linux random seed EFI table as our source of randomness, since there's reason to
|
||||
* believe it is as good as it possibly would get. Note that we ourselves might be the ones
|
||||
* initializing it, based on EFI RNG APIs, the monotonic boot counter, a random seed file on disk and
|
||||
* the clock. */
|
||||
|
||||
struct linux_efi_random_seed *seed_table =
|
||||
find_configuration_table(MAKE_GUID_PTR(LINUX_EFI_RANDOM_SEED_TABLE));
|
||||
if (!seed_table)
|
||||
return log_debug_status(EFI_NOT_FOUND, "No random seed available, not creating a boot secret.");
|
||||
if (seed_table->size < BOOT_SECRET_SIZE)
|
||||
return log_debug_status(EFI_NOT_FOUND, "Random seed is available, but too short.");
|
||||
|
||||
*ret = seed_table;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static void random_seed_evolve(struct linux_efi_random_seed *seed_table) {
|
||||
static const char label[] = "systemd-stub random seed evolve label v1";
|
||||
|
||||
assert(seed_table);
|
||||
|
||||
/* Whenever we derived something from the Linux random seed EFI table we evolve the secret in it, so
|
||||
* that the seed is never reused. */
|
||||
|
||||
struct sha256_ctx hash;
|
||||
CLEANUP_ERASE(hash);
|
||||
sha256_init_ctx(&hash);
|
||||
sha256_process_bytes(label, sizeof(label) - 1, &hash);
|
||||
sha256_process_bytes(&seed_table->size, sizeof(seed_table->size), &hash);
|
||||
sha256_process_bytes(seed_table->seed, seed_table->size, &hash);
|
||||
assert(seed_table->size >= SHA256_DIGEST_SIZE);
|
||||
sha256_finish_ctx(&hash, seed_table->seed);
|
||||
}
|
||||
|
||||
static void random_seed_make_secret(
|
||||
struct linux_efi_random_seed *seed_table,
|
||||
uint8_t ret_secret[static BOOT_SECRET_SIZE]) {
|
||||
|
||||
static const char label[] = "systemd-stub random seed make secret label v1";
|
||||
|
||||
assert(seed_table);
|
||||
assert(ret_secret);
|
||||
|
||||
/* Derive a new secret from the Linux random seed EFI table data */
|
||||
|
||||
struct sha256_ctx hash;
|
||||
CLEANUP_ERASE(hash);
|
||||
sha256_init_ctx(&hash);
|
||||
sha256_process_bytes(label, sizeof(label) - 1, &hash);
|
||||
sha256_process_bytes(&seed_table->size, sizeof(seed_table->size), &hash);
|
||||
sha256_process_bytes(seed_table->seed, seed_table->size, &hash);
|
||||
sha256_finish_ctx(&hash, ret_secret);
|
||||
|
||||
random_seed_evolve(seed_table); /* ← ensure the same seed is not reused */
|
||||
}
|
||||
|
||||
static EFI_STATUS read_efivar_secret(uint8_t ret_secret[static BOOT_SECRET_SIZE]) {
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(ret_secret);
|
||||
|
||||
/* Reads the boot secret from the EFI variable, ensuring it's properly protected from the OS, as per
|
||||
* the attribute flags */
|
||||
|
||||
_cleanup_free_ void* data = NULL;
|
||||
uint32_t attributes;
|
||||
size_t size = 0;
|
||||
err = efivar_get_raw_full(MAKE_GUID_PTR(LOADER), u"LoaderBootSecret", &attributes, &data, &size);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_debug_status(err, "Failed to read LoaderBootSecret EFI variable: %m");
|
||||
|
||||
if (size != BOOT_SECRET_SIZE) {
|
||||
err = log_debug_status(EFI_PROTOCOL_ERROR, "Unexpected size of BootSecret EFI variable, ignoring.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if ((attributes & (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS)) !=
|
||||
(EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS)) {
|
||||
err = log_debug_status(EFI_PROTOCOL_ERROR, "Unexpected attributes of BootSecret EFI variable, ignoring.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
memcpy(ret_secret, data, size);
|
||||
err = EFI_SUCCESS;
|
||||
finish:
|
||||
explicit_bzero_safe(data, size);
|
||||
return err;
|
||||
}
|
||||
|
||||
static EFI_STATUS setup_efivar_secret(
|
||||
struct linux_efi_random_seed *seed_table,
|
||||
uint8_t ret_secret[static BOOT_SECRET_SIZE]) {
|
||||
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(seed_table);
|
||||
assert(ret_secret);
|
||||
|
||||
/* Generates a new EFI variable secret, and stores it in an EFI variable. */
|
||||
|
||||
uint8_t secret[BOOT_SECRET_SIZE];
|
||||
CLEANUP_ERASE(secret);
|
||||
random_seed_make_secret(seed_table, secret);
|
||||
|
||||
/* Set the variable with the EFI_VARIABLE_RUNTIME_ACCESS flag off (!), so that it's invisible after
|
||||
* ExitBootServices()! */
|
||||
err = RT->SetVariable(
|
||||
(char16_t*) u"LoaderBootSecret",
|
||||
MAKE_GUID_PTR(LOADER),
|
||||
EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS, /* ← No EFI_VARIABLE_RUNTIME_ACCESS here */
|
||||
sizeof(secret),
|
||||
secret);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_debug_status(err, "Failed to set boot secret EFI variable: %m");
|
||||
|
||||
memcpy(ret_secret, secret, sizeof(secret));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS acquire_efivar_secret(
|
||||
struct linux_efi_random_seed *seed_table,
|
||||
uint8_t ret_secret[static BOOT_SECRET_SIZE]) {
|
||||
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(seed_table);
|
||||
assert(ret_secret);
|
||||
|
||||
/* Try to read the boot secret EFI variable, but if it doesn't exist create a new one */
|
||||
|
||||
err = read_efivar_secret(ret_secret);
|
||||
if (err != EFI_NOT_FOUND)
|
||||
return err;
|
||||
|
||||
return setup_efivar_secret(seed_table, ret_secret);
|
||||
}
|
||||
|
||||
static EFI_STATUS setup_secret_mixin(
|
||||
EFI_FILE *handle,
|
||||
struct linux_efi_random_seed *seed_table,
|
||||
uint8_t ret_mixin[static BOOT_SECRET_SIZE]) {
|
||||
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(handle);
|
||||
assert(seed_table);
|
||||
assert(ret_mixin);
|
||||
|
||||
/* This writes a new 'mixin' to the ESP, in case the ESP so far had none */
|
||||
|
||||
uint8_t mixin[BOOT_SECRET_SIZE];
|
||||
random_seed_make_secret(seed_table, mixin);
|
||||
|
||||
size_t wsize = sizeof(mixin);
|
||||
err = handle->Write(handle, &wsize, mixin);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_debug_status(err, "Failed to write secret mixin file: %m");
|
||||
if (wsize != sizeof(mixin))
|
||||
return log_debug_status(EFI_LOAD_ERROR, "Short write while writing secret mixin file: %m");
|
||||
|
||||
err = handle->Flush(handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_debug_status(err, "Failed to flush secret mixin file: %m");
|
||||
|
||||
memcpy(ret_mixin, mixin, sizeof(mixin));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS acquire_secret_mixin(
|
||||
EFI_FILE *root_dir,
|
||||
struct linux_efi_random_seed *seed_table,
|
||||
uint8_t ret_mixin[static BOOT_SECRET_SIZE]) {
|
||||
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(seed_table);
|
||||
assert(ret_mixin);
|
||||
|
||||
if (!root_dir)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
/* Acquires the mixin for the boot secret stored in the ESP. If it already exists we'll read it. If
|
||||
* it doesn't we'll initialize it */
|
||||
|
||||
bool writable;
|
||||
_cleanup_file_close_ EFI_FILE *handle = NULL;
|
||||
err = root_dir->Open(
|
||||
root_dir,
|
||||
&handle,
|
||||
(char16_t *) BOOT_SECRET_MIXIN_PATH,
|
||||
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
|
||||
/* Attributes= */ 0);
|
||||
if (err == EFI_WRITE_PROTECTED) {
|
||||
err = root_dir->Open(
|
||||
root_dir,
|
||||
&handle,
|
||||
(char16_t *) BOOT_SECRET_MIXIN_PATH,
|
||||
EFI_FILE_MODE_READ,
|
||||
/* Attributes= */ 0);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_debug_status(err, "Failed to read the boot secret mixin file '%ls': %m", BOOT_SECRET_MIXIN_PATH);
|
||||
|
||||
writable = false;
|
||||
} else if (err != EFI_SUCCESS)
|
||||
return log_debug_status(err, "Failed to access the boot secret mixin file '%ls': %m", BOOT_SECRET_MIXIN_PATH);
|
||||
else
|
||||
writable = true;
|
||||
|
||||
_cleanup_free_ EFI_FILE_INFO *info = NULL;
|
||||
err = get_file_info(handle, &info, /* ret_size= */ NULL);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_debug_status(err, "Failed to get boot secret mixin file '%ls' info: %m", BOOT_SECRET_MIXIN_PATH);
|
||||
if (info->FileSize == 0 && writable) /* New file? Fill it. */
|
||||
return setup_secret_mixin(handle, seed_table, ret_mixin);
|
||||
|
||||
/* If the mixin file is too small we won't overwrite it (in order to not destroy some potentially
|
||||
* load bearing key), but we won't use it either. */
|
||||
if (info->FileSize < BOOT_SECRET_SIZE)
|
||||
return log_debug_status(EFI_PROTOCOL_ERROR, "Boot secret mixin file '%ls' is too short %" PRIu64 " < %u", BOOT_SECRET_MIXIN_PATH, info->FileSize, BOOT_SECRET_SIZE);
|
||||
|
||||
uint8_t mixin[BOOT_SECRET_SIZE];
|
||||
size_t rsize = sizeof(mixin);
|
||||
err = handle->Read(handle, &rsize, mixin);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_debug_status(err, "Failed to read boot secret mixin file '%ls': %m", BOOT_SECRET_MIXIN_PATH);
|
||||
if (rsize != BOOT_SECRET_SIZE)
|
||||
return log_debug_status(EFI_PROTOCOL_ERROR, "Unexpected size from Read(): %zu != %zu", rsize, sizeof(mixin));
|
||||
|
||||
memcpy(ret_mixin, mixin, BOOT_SECRET_SIZE);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static char* pick_id(const char *_osrel, size_t osrel_size) {
|
||||
assert(_osrel || osrel_size == 0);
|
||||
|
||||
/* Make a NUL terminated copy we can chop into pieces */
|
||||
_cleanup_free_ char *osrel = NULL;
|
||||
osrel = xmalloc(osrel_size + 1);
|
||||
if (osrel_size > 0)
|
||||
memcpy(osrel, _osrel, osrel_size);
|
||||
osrel[osrel_size] = 0;
|
||||
|
||||
/* Find an OS ID. Preferably the IMAGE_ID. */
|
||||
_cleanup_free_ char *os_id = NULL;
|
||||
char *line, *key, *value;
|
||||
size_t pos = 0;
|
||||
while ((line = line_get_key_value(osrel, "=", &pos, &key, &value))) {
|
||||
if (streq8(key, "IMAGE_ID"))
|
||||
return xstrdup8(value);
|
||||
|
||||
if (streq8(key, "ID")) {
|
||||
free(os_id);
|
||||
os_id = xstrdup8(value);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the IMAGE_ID= wasn't set, use the OS ID=. If that one isn't set either fall back to "linux". */
|
||||
return TAKE_PTR(os_id) ?: xstrdup8("linux");
|
||||
}
|
||||
|
||||
static void derive_secret(
|
||||
uint8_t efivar_secret[static BOOT_SECRET_SIZE],
|
||||
uint8_t secret_mixin[static BOOT_SECRET_SIZE],
|
||||
const char *id,
|
||||
uint8_t ret[static BOOT_SECRET_SIZE]) {
|
||||
|
||||
static const char hash_label[] = "systemd-stub derive secret label v1";
|
||||
|
||||
assert(efivar_secret);
|
||||
assert(secret_mixin);
|
||||
assert(id);
|
||||
assert(ret);
|
||||
|
||||
/* Now combine the EFI variable secret, the mixin from the ESP and the OS id to generate the secret
|
||||
* to pass to the OS */
|
||||
|
||||
struct sha256_ctx hash;
|
||||
CLEANUP_ERASE(hash);
|
||||
sha256_init_ctx(&hash);
|
||||
sha256_process_bytes(hash_label, sizeof(hash_label) - 1, &hash);
|
||||
sha256_process_bytes(efivar_secret, BOOT_SECRET_SIZE, &hash);
|
||||
sha256_process_bytes(secret_mixin, BOOT_SECRET_SIZE, &hash);
|
||||
|
||||
/* Include an OS id in the hash, so that every OS gets a different derived secret */
|
||||
size_t size = strlen8(id);
|
||||
sha256_process_bytes(&size, sizeof(size), &hash);
|
||||
sha256_process_bytes(id, size, &hash);
|
||||
|
||||
assert_cc(SHA256_DIGEST_SIZE == BOOT_SECRET_SIZE);
|
||||
sha256_finish_ctx(&hash, ret);
|
||||
}
|
||||
|
||||
EFI_STATUS prepare_boot_secret(
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
|
||||
const PeSectionVector *osrel_section,
|
||||
uint8_t ret[static BOOT_SECRET_SIZE]) {
|
||||
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(loaded_image);
|
||||
assert(ret);
|
||||
|
||||
/* Prepares the boot secret to pass to the OS */
|
||||
|
||||
if (!loaded_image->DeviceHandle)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
_cleanup_file_close_ EFI_FILE *root = NULL;
|
||||
err = open_volume(loaded_image->DeviceHandle, &root);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
/* We need the Linux random seed EFI table, so that we can initialize the EFI variable secret and
|
||||
* generate the secret mixin. */
|
||||
struct linux_efi_random_seed *seed_table = NULL;
|
||||
err = random_seed_find_table(&seed_table);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
uint8_t efivar_secret[BOOT_SECRET_SIZE];
|
||||
CLEANUP_ERASE(efivar_secret);
|
||||
err = acquire_efivar_secret(seed_table, efivar_secret);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
uint8_t secret_mixin[BOOT_SECRET_SIZE];
|
||||
err = acquire_secret_mixin(root, seed_table, secret_mixin);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
const char *osrel = NULL;
|
||||
size_t osrel_size = 0;
|
||||
if (PE_SECTION_VECTOR_IS_SET(osrel_section)) {
|
||||
osrel = (const char*) loaded_image->ImageBase + osrel_section->memory_offset;
|
||||
osrel_size = osrel_section->memory_size;
|
||||
}
|
||||
_cleanup_free_ char *id = pick_id(osrel, osrel_size);
|
||||
|
||||
derive_secret(efivar_secret, secret_mixin, id, ret);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
13
src/boot/boot-secret.h
Normal file
13
src/boot/boot-secret.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "efi.h"
|
||||
#include "pe.h"
|
||||
#include "proto/loaded-image.h"
|
||||
|
||||
#define BOOT_SECRET_SIZE 32U
|
||||
|
||||
EFI_STATUS prepare_boot_secret(
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
|
||||
const PeSectionVector *osrel_section,
|
||||
uint8_t ret[static BOOT_SECRET_SIZE]);
|
||||
@@ -337,6 +337,7 @@ systemd_boot_sources = files(
|
||||
)
|
||||
|
||||
stub_sources = files(
|
||||
'boot-secret.c',
|
||||
'cpio.c',
|
||||
'linux.c',
|
||||
'splash.c',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "boot-secret.h"
|
||||
#include "cpio.h"
|
||||
#include "device-path-util.h"
|
||||
#include "devicetree.h"
|
||||
@@ -45,6 +46,7 @@ enum {
|
||||
INITRD_PCRPKEY,
|
||||
INITRD_OSREL,
|
||||
INITRD_PROFILE,
|
||||
INITRD_BOOT_SECRET,
|
||||
_INITRD_MAX,
|
||||
};
|
||||
|
||||
@@ -978,6 +980,29 @@ static void generate_embedded_initrds(
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_boot_secret_initrd(
|
||||
const uint8_t boot_secret[static BOOT_SECRET_SIZE],
|
||||
struct iovec initrds[static _INITRD_MAX]) {
|
||||
|
||||
assert(initrds);
|
||||
|
||||
/* All zero means: no boot secret acquired */
|
||||
if (memeqzero(boot_secret, BOOT_SECRET_SIZE))
|
||||
return;
|
||||
|
||||
(void) pack_cpio_literal(
|
||||
boot_secret,
|
||||
BOOT_SECRET_SIZE,
|
||||
".extra",
|
||||
u"boot-secret",
|
||||
/* dir_mode= */ 0555,
|
||||
/* access_mode= */ 0400,
|
||||
/* tpm_pcr= */ UINT32_MAX,
|
||||
/* tpm_description= */ NULL,
|
||||
initrds + INITRD_BOOT_SECRET,
|
||||
/* ret_measured= */ NULL);
|
||||
}
|
||||
|
||||
static void lookup_embedded_initrds(
|
||||
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
|
||||
const PeSectionVector sections[static _UNIFIED_SECTION_MAX],
|
||||
@@ -1256,6 +1281,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
|
||||
refresh_random_seed(loaded_image);
|
||||
|
||||
uint8_t boot_secret[BOOT_SECRET_SIZE] = {}; /* all zeroes means: not acquired */
|
||||
CLEANUP_ERASE(boot_secret);
|
||||
(void) prepare_boot_secret(loaded_image, sections + UNIFIED_SECTION_OSREL, boot_secret);
|
||||
|
||||
uname = pe_section_to_str8(loaded_image, sections + UNIFIED_SECTION_UNAME);
|
||||
|
||||
/* Let's now check if we actually want to use the command line, measure it if it was passed in. */
|
||||
@@ -1285,6 +1314,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
/* Generate & find all initrds */
|
||||
generate_sidecar_initrds(loaded_image, initrds, ¶meters_measured, &sysext_measured, &confext_measured);
|
||||
generate_embedded_initrds(loaded_image, sections, initrds);
|
||||
generate_boot_secret_initrd(boot_secret, initrds);
|
||||
lookup_embedded_initrds(loaded_image, sections, initrds);
|
||||
|
||||
/* Add initrds in the right order. Generally, later initrds can overwrite files in earlier ones,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
C /run/systemd/stub/profile 0444 root root - /.extra/profile
|
||||
C /run/systemd/stub/os-release 0444 root root - /.extra/os-release
|
||||
C /run/systemd/stub/boot-secret 0400 root root - /.extra/boot-secret
|
||||
|
||||
{% if ENABLE_TPM %}
|
||||
C /run/systemd/tpm2-pcr-signature.json 0444 root root - /.extra/tpm2-pcr-signature.json
|
||||
|
||||
Reference in New Issue
Block a user