grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v3 19/19] multiboot2: Support TXT Secure Launch


From: Sergii Dmytruk
Subject: [PATCH v3 19/19] multiboot2: Support TXT Secure Launch
Date: Thu, 12 Dec 2024 15:41:47 +0200

From: Michał Żygowski <michal.zygowski@3mdeb.com>

The code makes sure the order of policy entries is correct:
 - MBI entry goes first, so the payload can measure it first on launch
 - then goes SLRT and other typical entries
 - MB2 modules are appended last

Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com>
Signed-off-by: Tomasz Żyjewski <tomasz.zyjewski@3mdeb.com>
Signed-off-by: Krystian Hebel <krystian.hebel@3mdeb.com>
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
---
 grub-core/loader/multiboot.c       |  11 +++
 grub-core/loader/multiboot_elfxx.c |  90 +++++++++++++++++++-
 grub-core/loader/multiboot_mbi2.c  | 132 +++++++++++++++++++++++++++++
 grub-core/loader/slaunch/dlstub.c  |   2 +-
 include/grub/i386/txt.h            |   2 +
 include/grub/multiboot2.h          |   3 +
 include/grub/slaunch.h             |   1 +
 include/grub/slr_table.h           |   2 +
 8 files changed, 241 insertions(+), 2 deletions(-)

diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 98c1d5e99..07163739b 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -50,6 +50,7 @@
 #include <grub/video.h>
 #include <grub/memory.h>
 #include <grub/i18n.h>
+#include <grub/slaunch.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -191,6 +192,16 @@ grub_multiboot_boot (void)
   if (err)
     return err;
 
+#ifdef GRUB_USE_MULTIBOOT2
+  if (grub_slaunch_platform_type () != SLP_NONE)
+    {
+      err = grub_multiboot2_perform_slaunch (state.MULTIBOOT_MBI_REGISTER,
+                                             mbi_size);
+      if (err)
+        return grub_error (err, N_("failed to perform Multiboot2 slaunch"));
+    }
+#endif
+
   if (grub_efi_is_finished)
     normal_boot (GRUB_MULTIBOOT (relocator), state);
   else
diff --git a/grub-core/loader/multiboot_elfxx.c 
b/grub-core/loader/multiboot_elfxx.c
index 1edad0594..ee05a4d99 100644
--- a/grub-core/loader/multiboot_elfxx.c
+++ b/grub-core/loader/multiboot_elfxx.c
@@ -44,7 +44,9 @@
 #error "I'm confused"
 #endif
 
+#include <grub/i386/txt.h>
 #include <grub/i386/relocator.h>
+#include <grub/slaunch.h>
 
 #define CONCAT(a,b)    CONCAT_(a, b)
 #define CONCAT_(a,b)   a ## b
@@ -73,6 +75,11 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
   grub_off_t phlimit;
   unsigned int i;
   void *source = NULL;
+#ifdef GRUB_USE_MULTIBOOT2
+  struct grub_slaunch_params *slparams = &grub_multiboot2_slparams;
+  grub_uint32_t mle_hdr_offset;
+  struct grub_txt_mle_header *mle_hdr;
+#endif
 
   if (ehdr->e_ident[EI_MAG0] != ELFMAG0
       || ehdr->e_ident[EI_MAG1] != ELFMAG1
@@ -127,6 +134,18 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
     {
       load_size = highest_load - mld->link_base_addr;
 
+#ifndef GRUB_USE_MULTIBOOT2
+      if (grub_slaunch_platform_type () != SLP_NONE)
+        return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for 
slaunch");
+#else
+      if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+        {
+          /* Do not go below GRUB_TXT_PMR_ALIGN. */
+          if (mld->align < GRUB_TXT_PMR_ALIGN)
+            mld->align = GRUB_TXT_PMR_ALIGN;
+        }
+#endif
+
       grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, "
                    "load_size=0x%x, avoid_efi_boot_services=%d\n",
                    (long) mld->align, mld->preference, load_size,
@@ -148,9 +167,57 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
 
       mld->load_base_addr = get_physical_target_address (ch);
       source = get_virtual_current_address (ch);
+
+#ifdef GRUB_USE_MULTIBOOT2
+      grub_memset (source, 0, load_size);
+      grub_dprintf ("multiboot_loader", "load_base_addr=0x%lx, source=0x%lx\n",
+                    (long) mld->load_base_addr, (long) source);
+
+      if (grub_slaunch_platform_type () != SLP_NONE)
+        {
+          slparams->mle_start = mld->load_base_addr;
+          slparams->mle_mem = source;
+          slparams->mle_ptab_size = 0;
+        }
+
+      if (grub_slaunch_platform_type () == SLP_INTEL_TXT)
+        {
+          /*
+           * Allocate the binary together with the page tables to make one
+           * contiguous block for MLE.
+           */
+          slparams->mle_ptab_size = grub_txt_get_mle_ptab_size (load_size);
+          slparams->mle_ptab_size = ALIGN_UP (slparams->mle_ptab_size, 
GRUB_TXT_PMR_ALIGN);
+
+          err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT 
(relocator), &ch,
+                                                       
GRUB_MEMORY_MACHINE_UPPER_START,
+                                                       mld->load_base_addr - 
slparams->mle_ptab_size,
+                                                       
slparams->mle_ptab_size, GRUB_TXT_PMR_ALIGN,
+                                                       
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+          if (err)
+            {
+              grub_dprintf ("multiboot_loader", "Cannot allocate memory for 
MLE page tables\n");
+              return err;
+            }
+
+          slparams->mle_ptab_mem = get_virtual_current_address (ch);
+          slparams->mle_ptab_target = (grub_uint64_t) 
get_physical_target_address (ch);
+          grub_dprintf ("multiboot_loader", "mle_ptab_mem = %p, 
mle_ptab_target = %lx, mle_ptab_size = %x\n",
+                        slparams->mle_ptab_mem, (unsigned long) 
slparams->mle_ptab_target,
+                        (unsigned) slparams->mle_ptab_size);
+        }
+#endif
     }
   else
-    mld->load_base_addr = mld->link_base_addr;
+    {
+#ifdef GRUB_USE_MULTIBOOT2
+      /* TODO: support non-relocatable */
+      if (grub_slaunch_platform_type () != SLP_NONE)
+        return grub_error (GRUB_ERR_BAD_OS, "Non-relocatable ELF not supported 
with slaunch");
+#endif
+
+      mld->load_base_addr = mld->link_base_addr;
+    }
 
   grub_dprintf ("multiboot_loader", "relocatable=%d, link_base_addr=0x%x, "
                "load_base_addr=0x%x\n", mld->relocatable,
@@ -213,6 +280,27 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
         }
     }
 
+#ifdef GRUB_USE_MULTIBOOT2
+  if (grub_slaunch_platform_type () != SLP_NONE)
+    {
+      /* TODO: decide on universal way of conveying location of MLE header */
+      for (mle_hdr_offset = 0; mle_hdr_offset < 0x1000; mle_hdr_offset += 16)
+        {
+          mle_hdr = (struct grub_txt_mle_header *)((grub_addr_t)source + 
mle_hdr_offset);
+          if (!grub_memcmp (mle_hdr->uuid, GRUB_TXT_MLE_UUID, 16))
+            {
+              break;
+            }
+        }
+
+      if (mle_hdr_offset >= 0x1000)
+        return grub_error (GRUB_ERR_BAD_ARGUMENT, "MLE header not found");
+
+      slparams->mle_header_offset = mle_hdr_offset;
+      slparams->mle_size = mle_hdr->mle_end - mle_hdr->mle_start;
+    }
+#endif
+
   for (i = 0; i < phnum; i++)
     if (phdr(i)->p_vaddr <= ehdr->e_entry
        && phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry)
diff --git a/grub-core/loader/multiboot_mbi2.c 
b/grub-core/loader/multiboot_mbi2.c
index 1945b3ac6..dcbfbed1f 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -36,6 +36,10 @@
 #include <grub/i18n.h>
 #include <grub/net.h>
 #include <grub/lib/cmdline.h>
+#include <grub/i386/memory.h>
+#include <grub/i386/txt.h>
+#include <grub/slaunch.h>
+#include <grub/slr_table.h>
 
 #if defined (GRUB_MACHINE_EFI)
 #include <grub/efi/efi.h>
@@ -63,6 +67,12 @@ struct module
   int cmdline_size;
 };
 
+struct fill_policy_hook_data
+{
+  grub_uint32_t mbi_target;
+  grub_uint32_t mbi_size;
+};
+
 static struct module *modules, *modules_last;
 static grub_size_t cmdline_size;
 static grub_size_t total_modcmd;
@@ -76,6 +86,8 @@ static void *elf_sections;
 static int keep_bs = 0;
 static grub_uint32_t load_base_addr;
 
+struct grub_slaunch_params grub_multiboot2_slparams = {0};
+
 void
 grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
                            unsigned shndx, void *data)
@@ -119,6 +131,7 @@ grub_multiboot2_load (grub_file_t file, const char 
*filename)
   grub_uint32_t console_required = 0;
   struct multiboot_header_tag_framebuffer *fbtag = NULL;
   int accepted_consoles = GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT;
+  struct grub_slaunch_params *slparams = &grub_multiboot2_slparams;
   mbi_load_data_t mld;
 
   mld.mbi_ver = 2;
@@ -275,8 +288,18 @@ grub_multiboot2_load (grub_file_t file, const char 
*filename)
                         "load address tag without entry address tag");
     }
 
+  if (grub_slaunch_platform_type () != SLP_NONE)
+    {
+      slparams->relocator = grub_multiboot2_relocator;
+      slparams->boot_type = GRUB_SL_BOOT_TYPE_MB2;
+      slparams->platform_type = grub_slaunch_platform_type ();
+    }
+
   if (addr_tag)
     {
+      if (slparams->platform_type != SLP_NONE)
+        return grub_error (GRUB_ERR_BAD_OS, "Slaunch not supported with 
multiboot addr tag");
+
       grub_uint64_t load_addr = (addr_tag->load_addr + 1)
        ? addr_tag->load_addr : (addr_tag->header_addr
                                 - ((char *) header - (char *) mld.buffer));
@@ -390,6 +413,35 @@ grub_multiboot2_load (grub_file_t file, const char 
*filename)
     err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT,
                                       accepted_consoles,
                                       0, 0, 0, console_required);
+
+  if (slparams->platform_type != SLP_NONE)
+    {
+      grub_relocator_chunk_t ch;
+
+      if (grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, 
&ch, 0x1000000,
+                                                 UP_TO_TOP32 
(GRUB_SLAUNCH_TPM_EVT_LOG_SIZE),
+                                                 
GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, GRUB_PAGE_SIZE,
+                                                 
GRUB_RELOCATOR_PREFERENCE_HIGH, 1))
+        {
+          grub_free (mld.buffer);
+          return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not allocate TPM 
event log area");
+        }
+
+      slparams->tpm_evt_log_base = get_physical_target_address (ch);
+      slparams->tpm_evt_log_size = GRUB_SLAUNCH_TPM_EVT_LOG_SIZE;
+
+      if (slparams->platform_type == SLP_INTEL_TXT)
+        grub_txt_init_tpm_event_log (get_virtual_current_address (ch),
+                                     slparams->tpm_evt_log_size);
+
+      grub_dprintf ("multiboot_loader", "tpm_evt_log_base = 0x%lx, 
tpm_evt_log_size = 0x%x\n",
+                    (unsigned long) slparams->tpm_evt_log_base,
+                    (unsigned) slparams->tpm_evt_log_size);
+
+      if (slparams->platform_type == SLP_INTEL_TXT)
+        grub_txt_setup_mle_ptab (slparams);
+    }
+
   return err;
 }
 
@@ -1128,3 +1180,83 @@ grub_multiboot2_set_bootdev (void)
 
   bootdev_set = 1;
 }
+
+static int
+fill_policy_hook(int is_start, int available_entries,
+                 struct grub_slr_policy_entry *next_entry, void *data)
+{
+  int i = 0;
+  unsigned m;
+  struct module *cur;
+  struct fill_policy_hook_data *hook_data = data;
+
+  if (is_start)
+    {
+      if (available_entries < 1)
+        return -1;
+
+      next_entry->pcr = 18;
+      next_entry->entity_type = GRUB_SLR_ET_MULTIBOOT2_INFO;
+      next_entry->entity = hook_data->mbi_target;
+      next_entry->size = hook_data->mbi_size;
+      next_entry->flags = 0;
+      grub_strcpy (next_entry->evt_info, "Measured MB2 information");
+      i = 1;
+    }
+  else
+    {
+      if (available_entries < (int)modcnt)
+        return -1;
+
+      for (m = 0, cur = modules; m < modcnt; m++, cur = cur->next)
+        {
+          next_entry[i].pcr = 17;
+          next_entry[i].entity_type = GRUB_SLR_ET_MULTIBOOT2_MODULE;
+          next_entry[i].entity = cur->start;
+          next_entry[i].size = cur->size;
+          next_entry[i].flags = 0;
+          grub_strcpy (next_entry[i].evt_info, "Measured MB2 module");
+          i++;
+        }
+    }
+
+  return i;
+}
+
+grub_err_t
+grub_multiboot2_perform_slaunch (grub_uint32_t mbi_target,
+                                 grub_uint32_t mbi_size)
+{
+  grub_err_t err;
+  struct grub_slaunch_params *slparams = &grub_multiboot2_slparams;
+  struct grub_slr_entry_dl_info *dlinfo;
+  struct fill_policy_hook_data hook_data = {
+    .mbi_target = mbi_target,
+    .mbi_size = mbi_size,
+  };
+
+  slparams->boot_params_base = mbi_target;
+
+  slparams->fill_policy_hook = &fill_policy_hook;
+  slparams->fill_policy_hook_data = &hook_data;
+
+  if (slparams->platform_type == SLP_INTEL_TXT)
+    {
+      err = grub_txt_boot_prepare (slparams);
+      if (err != GRUB_ERR_NONE)
+        return grub_error (err, "TXT boot preparation failed");
+    }
+  else
+    return grub_error (GRUB_ERR_BAD_DEVICE,
+                       N_("Unknown secure launcher platform type: %d\n"), 
slparams->platform_type);
+
+  grub_dprintf ("multiboot_loader", "slr_table_base = 0x%lx, slr_table_size = 
0x%x\n",
+                (unsigned long) slparams->slr_table_base,
+                (unsigned) slparams->slr_table_size);
+
+  dlinfo = grub_slr_next_entry_by_tag (slparams->slr_table_mem, NULL, 
GRUB_SLR_ENTRY_DL_INFO);
+  dl_entry ((grub_uint64_t)(grub_addr_t) &dlinfo->bl_context);
+
+  /* If this returns, something failed miserably */
+  return GRUB_ERR_BAD_DEVICE;
+}
diff --git a/grub-core/loader/slaunch/dlstub.c 
b/grub-core/loader/slaunch/dlstub.c
index d3c28645e..2cdbdd886 100644
--- a/grub-core/loader/slaunch/dlstub.c
+++ b/grub-core/loader/slaunch/dlstub.c
@@ -73,7 +73,7 @@ void dl_entry (grub_uint64_t dl_ctx)
       return;
     }
 
-  if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX)
+  if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX || slparams->boot_type == 
GRUB_SL_BOOT_TYPE_MB2)
     {
       /* Configure relocator GETSEC[SENTER] call. */
       state.eax = GRUB_SMX_LEAF_SENTER;
diff --git a/include/grub/i386/txt.h b/include/grub/i386/txt.h
index d4a6d1cd1..d2ae7b21e 100644
--- a/include/grub/i386/txt.h
+++ b/include/grub/i386/txt.h
@@ -420,6 +420,8 @@ struct grub_txt_sinit_memory_descriptor_records
 /* 2.1 MLE Architecture Overview */
 /* Table 1. MLE Header structure */
 
+#define GRUB_TXT_MLE_UUID 
"\x5a\xac\x82\x90\x6f\x47\xa7\x74\x0f\x5c\x55\xa2\xcb\x51\xb6\x42"
+
 struct grub_txt_mle_header
 {
   grub_uint8_t uuid[16];
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
index 3417a1447..1a3be5f48 100644
--- a/include/grub/multiboot2.h
+++ b/include/grub/multiboot2.h
@@ -28,6 +28,7 @@
 #include <grub/err.h>
 
 extern struct grub_relocator *grub_multiboot2_relocator;
+extern struct grub_slaunch_params grub_multiboot2_slparams;
 
 void grub_multiboot2 (int argc, char *argv[]);
 void grub_module2 (int argc, char *argv[]);
@@ -43,6 +44,8 @@ void grub_multiboot2_set_bootdev (void);
 void
 grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
                            unsigned shndx, void *data);
+grub_err_t grub_multiboot2_perform_slaunch (grub_uint32_t mbi_target,
+                                            grub_uint32_t mbi_size);
 
 grub_uint32_t grub_multiboot2_get_mmap_count (void);
 grub_err_t grub_multiboot2_set_video_mode (void);
diff --git a/include/grub/slaunch.h b/include/grub/slaunch.h
index f7bea641e..f63b8b379 100644
--- a/include/grub/slaunch.h
+++ b/include/grub/slaunch.h
@@ -32,6 +32,7 @@
 #define GRUB_SL_BOOT_TYPE_INVALID      0
 #define GRUB_SL_BOOT_TYPE_LINUX                1
 #define GRUB_SL_BOOT_TYPE_EFI          2
+#define GRUB_SL_BOOT_TYPE_MB2          3
 
 #define GRUB_KERNEL_INFO_HEADER                "LToP"
 #define GRUB_KERNEL_INFO_MIN_SIZE_TOTAL        12
diff --git a/include/grub/slr_table.h b/include/grub/slr_table.h
index 9dff3d0d5..b9302472b 100644
--- a/include/grub/slr_table.h
+++ b/include/grub/slr_table.h
@@ -72,6 +72,8 @@
 #define GRUB_SLR_ET_CMDLINE            0x0004
 #define GRUB_SLR_ET_UEFI_MEMMAP                0x0005
 #define GRUB_SLR_ET_RAMDISK            0x0006
+#define GRUB_SLR_ET_MULTIBOOT2_INFO    0x0007
+#define GRUB_SLR_ET_MULTIBOOT2_MODULE  0x0008
 #define GRUB_SLR_ET_TXT_OS2MLE         0x0010
 #define GRUB_SLR_ET_UNUSED             0xffff
 
-- 
2.47.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]