grub-devel
[Top][All Lists]
Advanced

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

[PATCH v2 17/19] i386/slaunch: Add support for AMD SKINIT


From: Sergii Dmytruk
Subject: [PATCH v2 17/19] i386/slaunch: Add support for AMD SKINIT
Date: Sat, 2 Nov 2024 00:52:27 +0200

From: Krystian Hebel <krystian.hebel@3mdeb.com>

Extend slaunch command to work on AMD CPUs and validate input binary to
reject obviously incorrect ones.

Signed-off-by: Krystian Hebel <krystian.hebel@3mdeb.com>
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
---
 grub-core/lib/i386/relocator32.S |  6 ++++
 grub-core/loader/i386/skinit.c   | 58 ++++++++++++++++++++++++++++++++
 grub-core/loader/i386/slaunch.c  | 33 ++++++++++++++++--
 include/grub/i386/skinit.h       |  2 ++
 include/grub/i386/slaunch.h      |  5 +--
 5 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/grub-core/lib/i386/relocator32.S b/grub-core/lib/i386/relocator32.S
index a2b377197..2bdc07018 100644
--- a/grub-core/lib/i386/relocator32.S
+++ b/grub-core/lib/i386/relocator32.S
@@ -115,6 +115,9 @@ VARIABLE(grub_relocator32_edx)
        cmpl    $SLP_INTEL_TXT, %edi
        je      LOCAL(intel_txt)
 
+       cmpl    $SLP_AMD_SKINIT, %edi
+       je      LOCAL(amd_skinit)
+
        .byte   0xea
 VARIABLE(grub_relocator32_eip)
        .long   0
@@ -123,6 +126,9 @@ VARIABLE(grub_relocator32_eip)
 LOCAL(intel_txt):
        getsec
 
+LOCAL(amd_skinit):
+       skinit
+
        /* GDT. Copied from loader/i386/linux.c. */
        .p2align        4
 LOCAL(gdt):
diff --git a/grub-core/loader/i386/skinit.c b/grub-core/loader/i386/skinit.c
index d536630a6..0011f3ece 100644
--- a/grub-core/loader/i386/skinit.c
+++ b/grub-core/loader/i386/skinit.c
@@ -35,6 +35,64 @@
 /* Offset to area for passing data to SKL. */
 #define SLB_PARAM(slb)    ((const grub_uint16_t *) (slb))[3]
 
+int
+grub_skinit_is_slb (const void *slb_base, grub_uint32_t slb_size)
+{
+  const grub_uint8_t skl_uuid[16] = {
+    0x78, 0xf1, 0x26, 0x8e, 0x04, 0x92, 0x11, 0xe9,
+    0x83, 0x2a, 0xc8, 0x5b, 0x76, 0xc4, 0xcc, 0x02,
+  };
+  /* We need space after SLB to pass SLRT to it. */
+  const grub_ssize_t max_size = GRUB_SKINIT_SLB_SIZE - SLRT_SIZE;
+
+  const grub_uint8_t *uuid;
+
+  if (slb_size > max_size)
+    {
+      grub_dprintf ("slaunch", "SLB is too large: %d > %zd\n",
+                    slb_size, max_size);
+      return 0;
+    }
+
+  if (SLB_MEASURED (slb_base) > slb_size)
+    {
+      grub_dprintf ("slaunch", "SLB measured size is too large: %d > %d\n",
+                    SLB_MEASURED (slb_base), slb_size);
+      return 0;
+    }
+
+  if (SLB_ENTRY (slb_base) >= SLB_MEASURED (slb_base))
+    {
+      grub_dprintf ("slaunch", "SLB entry is not measured: %d >= %d\n",
+                    SLB_ENTRY (slb_base), SLB_MEASURED (slb_base));
+      return 0;
+    }
+
+  if (SLB_INFO (slb_base) > SLB_MEASURED (slb_base) - sizeof(skl_uuid))
+    {
+      grub_dprintf ("slaunch", "SLB info is not measured: %d > %zd\n",
+                    SLB_INFO (slb_base),
+                    SLB_MEASURED (slb_base) - sizeof(skl_uuid));
+      return 0;
+    }
+
+  if (SLB_PARAM (slb_base) > max_size)
+    {
+      grub_dprintf ("slaunch", "SLB bootloader data offset is too large: %d > 
%zd\n",
+                    SLB_PARAM (slb_base), max_size);
+      return 0;
+    }
+
+  uuid = (const grub_uint8_t *) slb_base + SLB_INFO (slb_base);
+  if (grub_memcmp (uuid, skl_uuid, sizeof(skl_uuid)) != 0)
+    {
+      grub_dprintf ("slaunch", "SLB has unexpected UUID\n");
+      return 0;
+    }
+
+  return 1;
+}
+
 grub_err_t
 grub_skinit_boot_prepare (struct grub_relocator *rel,
                           struct grub_slaunch_params *slparams)
diff --git a/grub-core/loader/i386/slaunch.c b/grub-core/loader/i386/slaunch.c
index 824b5c23b..806dd8c8d 100644
--- a/grub-core/loader/i386/slaunch.c
+++ b/grub-core/loader/i386/slaunch.c
@@ -28,6 +28,7 @@
 #include <grub/i386/cpuid.h>
 #include <grub/i386/msr.h>
 #include <grub/i386/mmio.h>
+#include <grub/i386/skinit.h>
 #include <grub/i386/slaunch.h>
 #include <grub/i386/tpm.h>
 #include <grub/i386/txt.h>
@@ -77,6 +78,8 @@ grub_slaunch_init_slrt_storage (int arch)
   /* Setup DCE and DLME information. */
   slr_dl_info_staging.hdr.tag = GRUB_SLR_ENTRY_DL_INFO;
   slr_dl_info_staging.hdr.size = sizeof(struct grub_slr_entry_dl_info);
+  slr_dl_info_staging.bl_context.bootloader = GRUB_SLR_BOOTLOADER_GRUB;
+  slr_dl_info_staging.bl_context.context = slparams.boot_params_addr;
   slr_dl_info_staging.dce_base = slparams.dce_base;
   slr_dl_info_staging.dce_size = slparams.dce_size;
   slr_dl_info_staging.dlme_base = slparams.mle_start;
@@ -154,7 +157,8 @@ grub_cmd_slaunch (grub_command_t cmd __attribute__ 
((unused)),
                  char *argv[] __attribute__ ((unused)))
 {
   grub_uint32_t manufacturer[3];
-  grub_uint32_t eax;
+  grub_uint32_t eax, ebx, ecx, edx;
+  grub_uint64_t msr_value;
   grub_err_t err;
 
   if (!grub_cpu_is_cpuid_supported ())
@@ -176,6 +180,19 @@ grub_cmd_slaunch (grub_command_t cmd __attribute__ 
((unused)),
 
       slp = SLP_INTEL_TXT;
     }
+  else if (!grub_memcmp (manufacturer, "AuthenticAMD", 12))
+    {
+      grub_cpuid (GRUB_AMD_CPUID_FEATURES, eax, ebx, ecx, edx);
+      if (! (ecx & GRUB_AMD_CPUID_FEATURES_ECX_SVM) )
+        return grub_error (GRUB_ERR_BAD_DEVICE, N_("CPU does not support AMD 
SVM"));
+
+      /* Check whether SVM feature is disabled in BIOS */
+      msr_value = grub_rdmsr (GRUB_MSR_AMD64_VM_CR);
+      if (msr_value & GRUB_MSR_SVM_VM_CR_SVM_DISABLE)
+        return grub_error (GRUB_ERR_BAD_DEVICE, N_("BIOS has AMD SVM 
disabled"));
+
+      slp = SLP_AMD_SKINIT;
+    }
   else
     return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("CPU is unsupported"));
 
@@ -196,7 +213,7 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ 
((unused)),
   if (slp == SLP_NONE)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("secure launch not enabled"));
 
-  if (slp != SLP_INTEL_TXT)
+  if (slp > SLP_AMD_SKINIT)
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
                       N_("unknown secure launch platform type: %d"), slp);
 
@@ -242,6 +259,14 @@ grub_cmd_slaunch_module (grub_command_t cmd __attribute__ 
((unused)),
          goto fail;
        }
     }
+  else if (slp == SLP_AMD_SKINIT)
+    {
+      if (!grub_skinit_is_slb (new_module, size))
+        {
+          grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("it does not look like SLB"));
+          goto fail;
+        }
+    }
 
   grub_file_close (file);
 
@@ -273,6 +298,10 @@ grub_cmd_slaunch_state (grub_command_t cmd __attribute__ 
((unused)),
       grub_printf ("Secure launcher: Intel TXT\n");
       grub_txt_state_show ();
     }
+  else if (slp == SLP_AMD_SKINIT)
+    {
+      grub_printf ("Secure launcher: AMD SKINIT\n");
+    }
   else
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
                       N_("Unknown secure launcher platform type: %d\n"), slp);
diff --git a/include/grub/i386/skinit.h b/include/grub/i386/skinit.h
index e2d5e4fbf..2901dbbb9 100644
--- a/include/grub/i386/skinit.h
+++ b/include/grub/i386/skinit.h
@@ -28,6 +28,8 @@
 #include <grub/cpu/relocator.h>
 #include <grub/i386/slaunch.h>
 
+int grub_skinit_is_slb (const void *slb_base, grub_uint32_t slb_size);
+
 grub_err_t grub_skinit_boot_prepare (struct grub_relocator *rel,
                                      struct grub_slaunch_params *slparams);
 
diff --git a/include/grub/i386/slaunch.h b/include/grub/i386/slaunch.h
index 8bf7042b9..82c6134a1 100644
--- a/include/grub/i386/slaunch.h
+++ b/include/grub/i386/slaunch.h
@@ -22,8 +22,9 @@
 #define GRUB_I386_SLAUNCH_H 1
 
 /* Secure launch platform types. */
-#define SLP_NONE      0
-#define SLP_INTEL_TXT 1
+#define SLP_NONE       0
+#define SLP_INTEL_TXT  1
+#define SLP_AMD_SKINIT 2
 
 /* PCRs used by Secure launch. */
 #define GRUB_SLAUNCH_CODE_PCR 17
-- 
2.47.0




reply via email to

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