diff --git a/man/loader.conf.xml b/man/loader.conf.xml index 0d12b1e874..ef358f7e68 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 abf7693a36..0c88b05a41 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 dd3757aa5c..a7bac8bf08 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 12f764c8a4..02683a61dc 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,