diff --git a/man/loader.conf.xml b/man/loader.conf.xml index 22deb8568b..f14b77b537 100644 --- a/man/loader.conf.xml +++ b/man/loader.conf.xml @@ -373,6 +373,29 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e + + secure-boot-enroll-action + + Specifies the action to take after the automatic enrollment of secure boot keys is completed. + + + reboot + + Reboot the system after enrollment. This is the default. + + + + shutdown + + Shut down the system after enrollment. + + + + 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 c7f354506c..830ba5b458 100644 --- a/src/boot/boot.c +++ b/src/boot/boot.c @@ -141,6 +141,7 @@ typedef struct { bool reboot_for_bitlocker; RebootOnError reboot_on_error; secure_boot_enroll secure_boot_enroll; + secure_boot_enroll_action secure_boot_enroll_action; bool force_menu; bool use_saved_entry; bool use_saved_entry_efivar; @@ -325,34 +326,35 @@ static void print_status(Config *config, char16_t *loaded_image_path) { if (config->entry_oneshot) printf(" default (one-shot): %ls\n", config->entry_oneshot); 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(" 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)); 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); if (!ps_continue()) return; @@ -1080,7 +1082,14 @@ static void config_defaults_load_from_file(Config *config, char *content) { else log_error("Error parsing 'secure-boot-enroll' config option, ignoring: %s", value); - + } else if (streq8(key, "secure-boot-enroll-action")) { + if (streq8(value, "reboot")) + config->secure_boot_enroll_action = ENROLL_ACTION_REBOOT; + else if (streq8(value, "shutdown")) + config->secure_boot_enroll_action = ENROLL_ACTION_SHUTDOWN; + else + log_error("Error parsing 'secure-boot-enroll-action' config option, ignoring: %s", + value); } else if (streq8(key, "console-mode")) { if (streq8(value, "auto")) config->console_mode = CONSOLE_MODE_AUTO; @@ -1436,6 +1445,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { .auto_firmware = true, .reboot_on_error = REBOOT_AUTO, .secure_boot_enroll = ENROLL_IF_SAFE, + .secure_boot_enroll_action = ENROLL_ACTION_REBOOT, .idx_default_efivar = IDX_INVALID, .console_mode = CONSOLE_MODE_KEEP, .console_mode_efivar = CONSOLE_MODE_KEEP, @@ -2723,7 +2733,7 @@ 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->path, /* force= */ true); + return secure_boot_enroll_at(root_dir, entry->path, /* force= */ true, /* action= */ ENROLL_ACTION_REBOOT); } static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir) { @@ -2774,7 +2784,7 @@ 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->path, config->secure_boot_enroll == ENROLL_FORCE); + secure_boot_enroll_at(root_dir, entry->path, config->secure_boot_enroll == ENROLL_FORCE, config->secure_boot_enroll_action); } return EFI_SUCCESS; diff --git a/src/boot/secure-boot.c b/src/boot/secure-boot.c index b6948586e5..f44a6f149b 100644 --- a/src/boot/secure-boot.c +++ b/src/boot/secure-boot.c @@ -69,7 +69,7 @@ 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) { +EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, secure_boot_enroll_action action) { assert(root_dir); assert(path); @@ -185,11 +185,21 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool } } - printf("Custom Secure Boot keys successfully enrolled, rebooting the system now!\n"); /* The system should be in secure boot mode now and we could continue a regular boot. But at least - * TPM PCR7 measurements should change on next boot. Reboot now so that any OS we load does not end - * up relying on the old PCR state. */ - RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + * TPM PCR7 measurements should change on next boot. Reboot/poweroff now so that any OS we load + * does not end up relying on the old PCR state. + */ + + if (action == ENROLL_ACTION_SHUTDOWN) { + printf("Custom Secure Boot keys successfully enrolled, powering off the system now!\n"); + console_key_read(/* ret_key= */ NULL, /* timeout_usec= */ 2 * 1000 * 1000); /* wait a bit so user can see the message */ + RT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); + } else { + assert(action == ENROLL_ACTION_REBOOT); + printf("Custom Secure Boot keys successfully enrolled, rebooting the system now!\n"); + console_key_read(/* ret_key= */ NULL, /* timeout_usec= */ 2 * 1000 * 1000); /* wait a bit so user can see the message */ + RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + } assert_not_reached(); out_deallocate: @@ -295,4 +305,10 @@ static const char *secure_boot_enroll_table[_SECURE_BOOT_ENROLL_MAX] = { [ENROLL_FORCE] = "force" }; +static const char *secure_boot_enroll_action_table[_SECURE_BOOT_ENROLL_ACTION_MAX] = { + [ENROLL_ACTION_REBOOT] = "reboot", + [ENROLL_ACTION_SHUTDOWN] = "shutdown" +}; + DEFINE_STRING_TABLE_LOOKUP_TO_STRING(secure_boot_enroll, secure_boot_enroll); +DEFINE_STRING_TABLE_LOOKUP_TO_STRING(secure_boot_enroll_action, secure_boot_enroll_action); diff --git a/src/boot/secure-boot.h b/src/boot/secure-boot.h index 5349fc039e..da5eccb615 100644 --- a/src/boot/secure-boot.h +++ b/src/boot/secure-boot.h @@ -12,10 +12,16 @@ typedef enum { _SECURE_BOOT_ENROLL_MAX, } secure_boot_enroll; +typedef enum { + ENROLL_ACTION_REBOOT, /* Reboot the system after enrollment */ + ENROLL_ACTION_SHUTDOWN, /* Shutdown the system after enrollment */ + _SECURE_BOOT_ENROLL_ACTION_MAX, +} secure_boot_enroll_action; + 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); +EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force, secure_boot_enroll_action action); typedef bool (*security_validator_t)( const void *ctx, @@ -27,3 +33,4 @@ void install_security_override(security_validator_t validator, const void *valid void uninstall_security_override(void); const char* secure_boot_enroll_to_string(secure_boot_enroll e) _const_; +const char* secure_boot_enroll_action_to_string(secure_boot_enroll_action e) _const_; diff --git a/tools/command_ignorelist b/tools/command_ignorelist index fed0bf052d..9408d5a5f9 100644 --- a/tools/command_ignorelist +++ b/tools/command_ignorelist @@ -579,3 +579,5 @@ run0.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--pty"] loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="yes"] loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="no"] loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="reboot-on-error"]/listitem/para/variablelist/varlistentry[term="auto"] +loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="reboot"] +loader.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="secure-boot-enroll-action"]/listitem/variablelist/varlistentry[term="shutdown"]