]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: add support for overriding key enrollement timeout
authorIgor Opaniuk <igor.opaniuk@foundries.io>
Thu, 18 Sep 2025 15:49:32 +0000 (17:49 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Sep 2025 10:13:10 +0000 (12:13 +0200)
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 <igor.opaniuk@foundries.io>
man/loader.conf.xml
src/boot/boot.c
src/boot/secure-boot.c
src/boot/secure-boot.h

index 0d12b1e874332a9db8de2af0dc2d4ba4f29b125f..ef358f7e68846f4345044dcd8a5fed77d6c88078 100644 (file)
@@ -421,6 +421,17 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>secure-boot-enroll-timeout-sec</term>
+        <listitem>
+          <para>How long the warning should be shown in seconds before the key enrollment process starts.</para>
+          <para>If set to <literal>hidden</literal> or <literal>0</literal>, no warning is shown and the keys
+          will be enrolled immediately. The default timeout (if not set explicitly) is 15 seconds.</para>
+          <para>This option is only relevant if <literal>secure-boot-enroll</literal> is enabled.</para>
+          <xi:include href="version-info.xml" xpointer="v259"/>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term>reboot-for-bitlocker</term>
 
index abf7693a360136b37cd3c3e70545a4e8c9163648..0c88b05a413138b6a13295ff69a26ef451d2e71c 100644 (file)
@@ -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;
index dd3757aa5ccf1aba26016cfb3db6751d1c393e88..a7bac8bf08b7d70aa5b78a07de2f93c35232b368 100644 (file)
@@ -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)
index 12f764c8a40fb9a21a655157dc04012a00118e78..02683a61dc7270b5dec5d97f567d550d10311df4 100644 (file)
@@ -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,