[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
- [PATCH v2 00/19] i386: Intel TXT and AMD SKINIT secure launcher, Sergii Dmytruk, 2024/11/01
- [PATCH v2 02/19] mmap: Add grub_mmap_get_lowest() and grub_mmap_get_highest(), Sergii Dmytruk, 2024/11/01
- [PATCH v2 01/19] i386/memory: Define GRUB_PAGE_MASK and GRUB_PAGE_{UP, DOWN} macros, Sergii Dmytruk, 2024/11/01
- [PATCH v2 03/19] i386: Add CRx, MMIO, MSR and extend CPUID definitions, Sergii Dmytruk, 2024/11/01
- [PATCH v2 04/19] i386/tpm: Rename tpm module to tpm_verifier, Sergii Dmytruk, 2024/11/01
- [PATCH v2 12/19] i386/txt: Initialize TPM 1.2 event log in TXT heap, Sergii Dmytruk, 2024/11/01
- [PATCH v2 14/19] multiboot: Make GRUB_MULTIBOOT(make_mbi) return MBI's size, Sergii Dmytruk, 2024/11/01
- [PATCH v2 15/19] multiboot2: Implement TXT slaunch support, Sergii Dmytruk, 2024/11/01
- [PATCH v2 17/19] i386/slaunch: Add support for AMD SKINIT,
Sergii Dmytruk <=
- [PATCH v2 19/19] i386/linux: Add support for AMD SKINIT, Sergii Dmytruk, 2024/11/01
- [PATCH v2 18/19] multiboot2: Support AMD SKINIT, Sergii Dmytruk, 2024/11/01