From 64376936c70ac1cba18fcdcaec8eb337d80c48a7 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Thu, 18 Sep 2025 17:49:32 +0200 Subject: [PATCH] boot: add support for overriding key enrollement timeout Currently, a 15-second timeout is hardcoded for the key enrollment process while waiting for user confirmation. Make this value configurable to allow the option of disabling user input, such as during automatic key provisioning at the factory. Signed-off-by: Igor Opaniuk --- man/loader.conf.xml | 11 +++++++++ src/boot/boot.c | 53 ++++++++++++++++++++++++++++-------------- src/boot/secure-boot.c | 9 +++---- src/boot/secure-boot.h | 10 +++++++- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/man/loader.conf.xml b/man/loader.conf.xml index 0d12b1e8743..ef358f7e688 100644 --- a/man/loader.conf.xml +++ b/man/loader.conf.xml @@ -421,6 +421,17 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e + + secure-boot-enroll-timeout-sec + + How long the warning should be shown in seconds before the key enrollment process starts. + If set to hidden or 0, no warning is shown and the keys + will be enrolled immediately. The default timeout (if not set explicitly) is 15 seconds. + This option is only relevant if secure-boot-enroll is enabled. + + + + reboot-for-bitlocker diff --git a/src/boot/boot.c b/src/boot/boot.c index abf7693a360..0c88b05a413 100644 --- a/src/boot/boot.c +++ b/src/boot/boot.c @@ -144,6 +144,7 @@ typedef struct { RebootOnError reboot_on_error; secure_boot_enroll secure_boot_enroll; secure_boot_enroll_action secure_boot_enroll_action; + uint64_t secure_boot_enroll_timeout_sec; bool force_menu; bool use_saved_entry; bool use_saved_entry_efivar; @@ -332,36 +333,37 @@ static void print_status(Config *config, char16_t *loaded_image_path) { printf(" sysfail: %ls\n", config->entry_sysfail); if (config->entry_saved) printf(" saved entry: %ls\n", config->entry_saved); - printf(" editor: %ls\n", yes_no(config->editor)); - printf(" auto-entries: %ls\n", yes_no(config->auto_entries)); - printf(" auto-firmware: %ls\n", yes_no(config->auto_firmware)); - printf(" auto-poweroff: %ls\n", yes_no(config->auto_poweroff)); - printf(" auto-reboot: %ls\n", yes_no(config->auto_reboot)); - printf(" beep: %ls\n", yes_no(config->beep)); - printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker)); - printf(" reboot-on-error: %s\n", reboot_on_error_to_string(config->reboot_on_error)); - printf(" secure-boot-enroll: %s\n", secure_boot_enroll_to_string(config->secure_boot_enroll)); - printf("secure-boot-enroll-action: %s\n", secure_boot_enroll_action_to_string(config->secure_boot_enroll_action)); + printf(" editor: %ls\n", yes_no(config->editor)); + printf(" auto-entries: %ls\n", yes_no(config->auto_entries)); + printf(" auto-firmware: %ls\n", yes_no(config->auto_firmware)); + printf(" auto-poweroff: %ls\n", yes_no(config->auto_poweroff)); + printf(" auto-reboot: %ls\n", yes_no(config->auto_reboot)); + printf(" beep: %ls\n", yes_no(config->beep)); + printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker)); + printf(" reboot-on-error: %s\n", reboot_on_error_to_string(config->reboot_on_error)); + printf(" secure-boot-enroll: %s\n", secure_boot_enroll_to_string(config->secure_boot_enroll)); + printf(" secure-boot-enroll-action: %s\n", secure_boot_enroll_action_to_string(config->secure_boot_enroll_action)); + printf("secure-boot-enroll-timeout-sec: %" PRIu64 "\n", config->secure_boot_enroll_timeout_sec); switch (config->console_mode) { case CONSOLE_MODE_AUTO: - printf(" console-mode (config): auto\n"); + printf(" console-mode (config): auto\n"); break; case CONSOLE_MODE_KEEP: - printf(" console-mode (config): keep\n"); + printf(" console-mode (config): keep\n"); break; case CONSOLE_MODE_FIRMWARE_MAX: - printf(" console-mode (config): max\n"); + printf(" console-mode (config): max\n"); break; default: - printf(" console-mode (config): %" PRIi64 "\n", config->console_mode); + printf(" console-mode (config): %" PRIi64 "\n", config->console_mode); } /* EFI var console mode is always a concrete value or unset. */ if (config->console_mode_efivar != CONSOLE_MODE_KEEP) - printf(" console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar); + printf(" console-mode (EFI var): %" PRIi64 "\n", config->console_mode_efivar); - printf(" log-level: %s\n", log_level_to_string(log_get_max_level())); + printf(" log-level: %s\n", log_level_to_string(log_get_max_level())); if (!ps_continue()) return; @@ -1097,6 +1099,18 @@ static void config_defaults_load_from_file(Config *config, char *content) { else log_error("Error parsing 'secure-boot-enroll-action' config option, ignoring: %s", value); + } else if (streq8(key, "secure-boot-enroll-timeout-sec")) { + if (streq8(value, "hidden")) + config->secure_boot_enroll_timeout_sec = ENROLL_TIMEOUT_HIDDEN; + else { + uint64_t u; + if (!parse_number8(value, &u, NULL) || u > ENROLL_TIMEOUT_TYPE_MAX) { + log_error("Error parsing 'secure-boot-enroll-timeout-sec' config option, ignoring: %s", + value); + continue; + } + config->secure_boot_enroll_timeout_sec = u; + } } else if (streq8(key, "console-mode")) { if (streq8(value, "auto")) config->console_mode = CONSOLE_MODE_AUTO; @@ -1463,6 +1477,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { .reboot_on_error = REBOOT_AUTO, .secure_boot_enroll = ENROLL_IF_SAFE, .secure_boot_enroll_action = ENROLL_ACTION_REBOOT, + .secure_boot_enroll_timeout_sec = ENROLL_TIMEOUT_DEFAULT, .idx_default_efivar = IDX_INVALID, .console_mode = CONSOLE_MODE_KEEP, .console_mode_efivar = CONSOLE_MODE_KEEP, @@ -2781,7 +2796,8 @@ static void save_selected_entry(const Config *config, const BootEntry *entry) { static EFI_STATUS call_secure_boot_enroll(const BootEntry *entry, EFI_FILE *root_dir, EFI_HANDLE parent_image) { assert(entry); - return secure_boot_enroll_at(root_dir, entry->directory, /* force= */ true, /* action= */ ENROLL_ACTION_REBOOT); + return secure_boot_enroll_at(root_dir, entry->directory, /* force= */ true, /* action= */ ENROLL_ACTION_REBOOT, + ENROLL_TIMEOUT_DEFAULT); } static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir) { @@ -2832,7 +2848,8 @@ static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir) strcaseeq16(dirent->FileName, u"auto")) /* If we auto enroll successfully this call does not return. * If it fails we still want to add other potential entries to the menu. */ - secure_boot_enroll_at(root_dir, entry->directory, config->secure_boot_enroll == ENROLL_FORCE, config->secure_boot_enroll_action); + secure_boot_enroll_at(root_dir, entry->directory, config->secure_boot_enroll == ENROLL_FORCE, + config->secure_boot_enroll_action, config->secure_boot_enroll_timeout_sec); } return EFI_SUCCESS; diff --git a/src/boot/secure-boot.c b/src/boot/secure-boot.c index dd3757aa5cc..a7bac8bf08b 100644 --- a/src/boot/secure-boot.c +++ b/src/boot/secure-boot.c @@ -3,6 +3,7 @@ #include "console.h" #include "efi-efivars.h" #include "efi-log.h" +#include "efi-string.h" #include "efi-string-table.h" #include "proto/security-arch.h" #include "secure-boot.h" @@ -70,7 +71,8 @@ static EFI_STATUS set_custom_mode(bool enable) { attr, sizeof(mode), &mode); } -EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, secure_boot_enroll_action action) { +EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, + secure_boot_enroll_action action, uint64_t timeout_sec) { assert(root_dir); assert(path); @@ -88,12 +90,11 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool printf("Enrolling secure boot keys from directory: %ls\n", path); - if (!is_safe) { + if (!is_safe && timeout_sec != ENROLL_TIMEOUT_HIDDEN) { printf("Warning: Enrolling custom Secure Boot keys might soft-brick your machine!\n"); - unsigned timeout_sec = 15; for (;;) { - printf("\rEnrolling in %2u s, press any key to abort.", timeout_sec); + printf("\rEnrolling in %" PRIu64 " s, press any key to abort.", timeout_sec); err = console_key_read(/* ret_key= */ NULL, /* timeout_usec= */ 1000 * 1000); if (err == EFI_NOT_READY) diff --git a/src/boot/secure-boot.h b/src/boot/secure-boot.h index 12f764c8a40..02683a61dc7 100644 --- a/src/boot/secure-boot.h +++ b/src/boot/secure-boot.h @@ -18,10 +18,18 @@ typedef enum { _SECURE_BOOT_ENROLL_ACTION_MAX, } secure_boot_enroll_action; +enum { + ENROLL_TIMEOUT_HIDDEN = 0, + ENROLL_TIMEOUT_MIN = 1, + ENROLL_TIMEOUT_DEFAULT = 15, + ENROLL_TIMEOUT_TYPE_MAX = UINT32_MAX, +}; + bool secure_boot_enabled(void); SecureBootMode secure_boot_mode(void); -EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, secure_boot_enroll_action action); +EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, + secure_boot_enroll_action action, uint64_t timeout_sec); typedef bool (*security_validator_t)( const void *ctx,