]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: Add if-safe mode for secure boot enrollment
authorJan Janssen <medhefgo@web.de>
Wed, 1 Feb 2023 14:23:25 +0000 (15:23 +0100)
committerJan Janssen <medhefgo@web.de>
Wed, 1 Feb 2023 15:52:28 +0000 (16:52 +0100)
man/loader.conf.xml
src/boot/efi/boot.c
src/boot/efi/secure-boot.c
src/boot/efi/secure-boot.h

index 8808461ceb1254ad3831a9cb71657e6be707a27d..22f4644d9e8a370fbd864ca95743801fec297004 100644 (file)
 
         <listitem><para>Danger: this feature might soft-brick your device if used improperly.</para>
 
-        <para>Takes one of <literal>off</literal>, <literal>manual</literal> or <literal>force</literal>.
-        Controls the enrollment of Secure Boot keys. If set to <literal>off</literal>, no action whatsoever
-        is taken. If set to <literal>manual</literal> (the default) and the UEFI firmware is in setup-mode
-        then entries to manually enroll Secure Boot variables are created in the boot menu. If set to
-        <literal>force</literal>, in addition, if a directory named <filename>/loader/keys/auto/</filename>
-        exists on the ESP then the keys in that directory are enrolled automatically.</para>
+        <para>Controls enrollment of secure boot keys found on the ESP if the system is in setup mode:
+        <variablelist>
+          <varlistentry>
+            <term><option>off</option></term>
+            <listitem><para>No action is taken.</para></listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term><option>manual</option></term>
+            <listitem><para>Boot entries for found secure boot keys are created that allow manual
+            enrollment.</para></listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term><option>if-safe</option></term>
+            <listitem><para>Same behavior as <option>manual</option>, but will try to automatically
+            enroll the key <literal>auto</literal> if it is considered to be safe. Currently, this is only
+            the case if the system is running inside a virtual machine.</para></listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term><option>force</option></term>
+            <listitem><para>Always enroll the <literal>auto</literal> key if found. Note that a warning
+            message with a timeout will still be shown if this operation is unknown to be safe.</para></listitem>
+          </varlistentry>
+        </variablelist>
+        </para>
 
         <para>The different sets of variables can be set up under
         <filename>/loader/keys/<replaceable>NAME</replaceable></filename> where
index bb318c4e7e6f70bd28edda0d01608dc53725d24e..03fe022ef64510da9dc6c33f60d2c285ae082c98 100644 (file)
@@ -526,6 +526,9 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
         case ENROLL_MANUAL:
                 printf("    secure-boot-enroll: manual\n");
                 break;
+        case ENROLL_IF_SAFE:
+                printf("    secure-boot-enroll: if-safe\n");
+                break;
         case ENROLL_FORCE:
                 printf("    secure-boot-enroll: force\n");
                 break;
@@ -1259,6 +1262,8 @@ static void config_defaults_load_from_file(Config *config, char *content) {
                                 config->secure_boot_enroll = ENROLL_MANUAL;
                         else if (streq8(value, "force"))
                                 config->secure_boot_enroll = ENROLL_FORCE;
+                        else if (streq8(value, "if-safe"))
+                                config->secure_boot_enroll = ENROLL_IF_SAFE;
                         else if (streq8(value, "off"))
                                 config->secure_boot_enroll = ENROLL_OFF;
                         else
@@ -1572,7 +1577,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
                 .auto_entries = true,
                 .auto_firmware = true,
                 .reboot_for_bitlocker = false,
-                .secure_boot_enroll = ENROLL_MANUAL,
+                .secure_boot_enroll = ENROLL_IF_SAFE,
                 .idx_default_efivar = IDX_INVALID,
                 .console_mode = CONSOLE_MODE_KEEP,
                 .console_mode_efivar = CONSOLE_MODE_KEEP,
@@ -2511,10 +2516,11 @@ static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir)
                 };
                 config_add_entry(config, entry);
 
-                if (config->secure_boot_enroll == ENROLL_FORCE && strcaseeq16(dirent->FileName, u"auto"))
+                if (IN_SET(config->secure_boot_enroll, ENROLL_IF_SAFE, ENROLL_FORCE) &&
+                    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);
+                        secure_boot_enroll_at(root_dir, entry->path, config->secure_boot_enroll == ENROLL_FORCE);
         }
 
         return EFI_SUCCESS;
@@ -2700,7 +2706,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
 
                 /* if auto enrollment is activated, we try to load keys for the given entry. */
                 if (entry->type == LOADER_SECURE_BOOT_KEYS && config.secure_boot_enroll != ENROLL_OFF) {
-                        err = secure_boot_enroll_at(root_dir, entry->path);
+                        err = secure_boot_enroll_at(root_dir, entry->path, /*force=*/ true);
                         if (err != EFI_SUCCESS)
                                 return err;
                         continue;
index c8a3957b1e18fe5a0455f652203e41c7c10d0631..8b796db65f95cc6e35b22b753b958e8cd1f367cd 100644 (file)
@@ -36,7 +36,7 @@ SecureBootMode secure_boot_mode(void) {
 static const char sbat[] _used_ _section_(".sbat") = SBAT_SECTION_TEXT;
 #endif
 
-EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) {
+EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force) {
         assert(root_dir);
         assert(path);
 
@@ -44,11 +44,16 @@ EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path) {
 
         clear_screen(COLOR_NORMAL);
 
-        printf("Enrolling secure boot keys from directory: %ls\n", path);
-
         /* Enrolling secure boot keys is safe to do in virtualized environments as there is nothing
          * we can brick there. */
-        if (!in_hypervisor()) {
+        bool is_safe = in_hypervisor();
+
+        if (!is_safe && !force)
+                return EFI_SUCCESS;
+
+        printf("Enrolling secure boot keys from directory: %ls\n", path);
+
+        if (!is_safe) {
                 printf("Warning: Enrolling custom Secure Boot keys might soft-brick your machine!\n");
 
                 unsigned timeout_sec = 15;
index e98de81c2a5b6675d4d23aa75ecabc9a1a0ea3cd..bdc34150da677e3ac8c5f4724870fa2149fed679 100644 (file)
@@ -9,13 +9,14 @@
 typedef enum {
         ENROLL_OFF,         /* no Secure Boot key enrollment whatsoever, even manual entries are not generated */
         ENROLL_MANUAL,      /* Secure Boot key enrollment is strictly manual: manual entries are generated and need to be selected by the user */
+        ENROLL_IF_SAFE,     /* Automatically enroll if it is safe (if we are running inside a VM, for example). */
         ENROLL_FORCE,       /* Secure Boot key enrollment may be automatic if it is available but might not be safe */
 } secure_boot_enroll;
 
 bool secure_boot_enabled(void);
 SecureBootMode secure_boot_mode(void);
 
-EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path);
+EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path, bool force);
 
 typedef bool (*security_validator_t)(
                 const void *ctx,