OvmfPkg/AmdSev: add Grub Firmware Volume Package

This is used to package up the grub bootloader into a firmware volume
where it can be executed as a shell like the UEFI Shell.  Grub itself
is built as a minimal entity into a Fv and then added as a boot
option.  By default the UEFI shell isn't built but for debugging
purposes it can be enabled and will then be presented as a boot option
(This should never be allowed for secure boot in an external data
centre but may be useful for local debugging).  Finally all other boot
options except grub and possibly the shell are stripped and the boot
timeout forced to 0 so the system will not enter a setup menu and will
only boot to grub.  This is done by copying the
Library/PlatformBootManagerLib into Library/PlatformBootManagerLibGrub
and then customizing it.

Boot failure is fatal to try to prevent secret theft.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3077
Signed-off-by: James Bottomley <jejb@linux.ibm.com>
Message-Id: <20201130202819.3910-4-jejb@linux.ibm.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
[lersek@redhat.com: replace local variable initialization with assignment]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
[lersek@redhat.com: squash 'OvmfPkg: add "gGrubFileGuid=Grub" to
 GuidCheck.IgnoreDuplicates', reviewed stand-alone by Phil (msgid
 <e6eae551-8563-ccfb-5547-7a97da6d46e5@redhat.com>) and Ard (msgid
 <10aeda37-def6-d9a4-6e02-4c66c1492f57@arm.com>)]
This commit is contained in:
James Bottomley
2020-11-30 12:28:16 -08:00
committed by mergify[bot]
parent 30d277ed7a
commit b261a30c90
12 changed files with 2144 additions and 10 deletions

View File

@@ -25,6 +25,7 @@
BUILD_TARGETS = NOOPT|DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
FLASH_DEFINITION = OvmfPkg/AmdSev/AmdSevX64.fdf
PREBUILD = sh OvmfPkg/AmdSev/Grub/grub.sh
#
# Defines for default states. These can be changed on the command line.
@@ -34,6 +35,11 @@
DEFINE TPM_ENABLE = FALSE
DEFINE TPM_CONFIG_ENABLE = FALSE
#
# Shell can be useful for debugging but should not be enabled for production
#
DEFINE BUILD_SHELL = FALSE
#
# Device drivers
#
@@ -149,7 +155,6 @@
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
NvVarsFileLib|OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
@@ -184,9 +189,11 @@
VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
!if $(BUILD_SHELL) == TRUE
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
!endif
SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLib.inf
@@ -343,7 +350,7 @@
!else
DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
!endif
PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformBootManagerLibGrub.inf
PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf
QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
@@ -507,6 +514,7 @@
# Point to the MdeModulePkg/Application/UiApp/UiApp.inf
gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|TRUE
################################################################################
#
# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
@@ -751,8 +759,6 @@
MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
OvmfPkg/AcpiTables/AcpiTables.inf
MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
#
@@ -765,12 +771,14 @@
MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
!if $(TOOL_CHAIN_TAG) != "XCODE5"
!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(BUILD_SHELL) == TRUE
OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
}
!endif
OvmfPkg/AmdSev/Grub/Grub.inf
!if $(BUILD_SHELL) == TRUE
ShellPkg/Application/Shell/Shell.inf {
<LibraryClasses>
ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
@@ -789,6 +797,7 @@
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
}
!endif
OvmfPkg/PlatformDxe/Platform.inf
OvmfPkg/AmdSevDxe/AmdSevDxe.inf

View File

@@ -257,17 +257,18 @@ INF OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
INF OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
INF RuleOverride=ACPITABLE OvmfPkg/AcpiTables/AcpiTables.inf
INF MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
INF MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
INF FatPkg/EnhancedFatDxe/Fat.inf
INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
!if $(TOOL_CHAIN_TAG) != "XCODE5"
!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(BUILD_SHELL) == TRUE
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
!endif
INF OvmfPkg/AmdSev/Grub/Grub.inf
!if $(BUILD_SHELL) == TRUE
INF ShellPkg/Application/Shell/Shell.inf
!endif
INF MdeModulePkg/Logo/LogoDxe.inf

1
OvmfPkg/AmdSev/Grub/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
grub.efi

View File

@@ -0,0 +1,39 @@
## @file
# Create a Firmware Volume based Grub Bootloader
#
# Copyright (C) 2020 James Bottomley, IBM Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = Grub
# This is gGrubFileGuid
FILE_GUID = b5ae312c-bc8a-43b1-9c62-ebb826dd5d07
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
[Packages]
OvmfPkg/OvmfPkg.dec
#
# The following information is for reference only and not required by
# the build tools.
#
# VALID_ARCHITECTURES = X64
#
##
# Note: The version of grub.efi this picks up can be generated by
# grub.sh which must be specified as a PREBUILD in the .dsc file. If
# grub.efi is newer than either grub.sh or grub.cfg then grub.sh will
# exit with success meaning that if you move your own version of grub
# in here (after checking out grub.sh and grub.cfg), PREBUILD won't
# overwrite it.
##
[Binaries]
PE32|grub.efi|*

View File

@@ -0,0 +1,46 @@
## @file
# Execute a script to recover the SEV supplied secret and use it to
# decrypt a luks volume. For security, the kernel must be on an encrypted
# volume so reboot if none are found.
#
# Copyright (C) 2020 James Bottomley, IBM Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
echo "Entering grub config"
sevsecret
if [ $? -ne 0 ]; then
echo "Failed to locate anything in the SEV secret area, prompting for password"
cryptomount -a
else
cryptomount -s
if [ $? -ne 0 ]; then
echo "Failed to mount root securely, retrying with password prompt"
cryptomount -a
fi
fi
set root=
for f in (crypto*); do
if [ -e $f/boot/grub/grub.cfg ]; then
set root=$f
set prefix=($root)/boot/grub
break;
fi
done
if [ x$root = x ]; then
echo "Failed to find any grub configuration on the encrypted volume"
sleep 5
reboot
fi
# rest of modules to get boot to work
set modules="
boot
loadenv
"
for f in $modules; do
insmod $f
done
echo "Transferring to ${prefix}/grub.cfg"
source $prefix/grub.cfg

View File

@@ -0,0 +1,93 @@
## @file
# Build a version of grub capable of decrypting a luks volume with a SEV
# Supplied secret
#
# Copyright (C) 2020 James Bottomley, IBM Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
set -e
remove_efi=1
cleanup() {
# remove the intermediates
for f in disk.fat grub-bootstrap.cfg; do
rm -f -- "${basedir}/$f"
done
if [ $remove_efi -eq 1 ]; then
rm -f -- "${basedir}/grub.efi"
fi
}
trap cleanup EXIT
GRUB_MODULES="
part_msdos
part_gpt
cryptodisk
luks
gcry_rijndael
gcry_sha256
ext2
btrfs
xfs
fat
configfile
memdisk
sleep
normal
echo
test
regexp
linux
linuxefi
reboot
sevsecret
"
basedir=$(dirname -- "$0")
# don't run a build if grub.efi exists and is newer than the config files
if [ -e "${basedir}/grub.efi" ] && \
[ "${basedir}/grub.efi" -nt "${basedir}/grub.cfg" ] && \
[ "${basedir}/grub.efi" -nt "${basedir}/grub.sh" ]; then
remove_efi=0
echo "preserving existing grub.efi" >&2
exit 0
fi
##
# different distributions have different names for grub-mkimage, so
# search all the known ones
##
mkimage=
for b in grub2-mkimage grub-mkimage; do
if which "$b" > /dev/null 2>&1; then
mkimage="$b"
break
fi
done
if [ -z "$mkimage" ]; then
echo "Can't find grub mkimage" >&2
exit 1
fi
# GRUB's rescue parser doesn't understand 'if'.
echo 'normal (memdisk)/grub.cfg' > "${basedir}/grub-bootstrap.cfg"
# Now build a memdisk with the correct grub.cfg
rm -f -- "${basedir}/disk.fat"
mkfs.msdos -C -- "${basedir}/disk.fat" 64
mcopy -i "${basedir}/disk.fat" -- "${basedir}/grub.cfg" ::grub.cfg
${mkimage} -O x86_64-efi \
-p '(crypto0)' \
-c "${basedir}/grub-bootstrap.cfg" \
-m "${basedir}/disk.fat" \
-o "${basedir}/grub.efi" \
${GRUB_MODULES}
remove_efi=0
echo "grub.efi generated in ${basedir}"