From: Krystian Hebel <krystian.he...@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.he...@3mdeb.com> Signed-off-by: Sergii Dmytruk <sergii.dmyt...@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 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel