[PATCH 1/1] x86: Secure Launch boot protocol
From: Ross Philipson
Date: Mon Mar 11 2019 - 11:05:17 EST
The open source project called Trenchboot aims to make Linux directly bootable
into a secure late launch environment via Intel TXT or AMD SKINIT. Though the
project name is Trenchboot, this new feature is referred to as Secure Launch.
In this scheme, the entire Linux image becomes the Measured Launch Environment
(MLE). This term comes from the Intel TXT specification and means the image
whose measurement is rooted in the TXT hardware. AMD's SKINIT does something
similar with the same end result. For TXT, see the "Intel Trusted Execution
Technology" specification. For SKINIT, see the "AMD64 Architecture
Programmerâs Manual Volume 2: System Programming", section 15.27.
The boot protocol extension introduces a new Linux boot parameter in the
setup_header to convey the offset of the MLE header within the compressed kernel
image (NOTE the MLE header is in the uncompressed protected mode entry portion).
This header is used to initiate the entire secure late launch process. The
header offset is written using the same method that is used to setup the
handover_offset of the EFI handover protocol.
Signed-off-by: Ross Philipson <ross.philipson@xxxxxxxxxx>
Reviewed-by: Daniel Kiper <daniel.kiper@xxxxxxxxxx>
---
Documentation/x86/boot.txt | 15 +++++++++++++++
arch/x86/Kconfig | 7 +++++++
arch/x86/boot/Makefile | 2 +-
arch/x86/boot/header.S | 3 ++-
arch/x86/boot/tools/build.c | 16 ++++++++++++++++
arch/x86/include/uapi/asm/bootparam.h | 1 +
6 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index f4c2a97bfdbd..958acd71815f 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -61,6 +61,9 @@ Protocol 2.12: (Kernel 3.8) Added the xloadflags field and extension fields
to struct boot_params for loading bzImage and ramdisk
above 4G in 64bit.
+Protocol 2.14: (Kernel 5.1) Added a field for offset of measured launch
+ environment (MLE) header.
+
**** MEMORY LAYOUT
The traditional memory map for the kernel loader, used for Image or
@@ -197,6 +200,7 @@ Offset Proto Name Meaning
0258/8 2.10+ pref_address Preferred loading address
0260/4 2.10+ init_size Linear memory required during initialization
0264/4 2.11+ handover_offset Offset of handover entry point
+0268/4 2.14+ mle_header_offset Offset of measured launch environement header
(1) For backwards compatibility, if the setup_sects field contains 0, the
real value is 4.
@@ -744,6 +748,17 @@ Offset/size: 0x264/4
See EFI HANDOVER PROTOCOL below for more details.
+Field name: mle_header_offset
+Type: read
+Offset/size: 0x268/4
+
+ This field is the offset from the beginning of the kernel image to
+ the measured launch environment header structure. Boot loaders launching
+ a kernel using Intel TXT or AMD SKINT secure late launch features use
+ this header to set up the launch environment. It is called mle_header
+ and is embedded in the Linux image in the uncompressed protected mode
+ entry region.
+
**** THE IMAGE CHECKSUM
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 68261430fe6e..508f1cc6795f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1965,6 +1965,13 @@ config EFI_MIXED
If unsure, say N.
+config SECURE_LAUNCH_STUB
+ bool "Secure Launch stub support"
+ depends on X86_64
+ ---help---
+ This kernel feature allows a bzImage to be loaded directly
+ through Intel TXT or AMD SKINIT measured launch.
+
config SECCOMP
def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 9b5adae9cc40..03c989bb36ab 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -87,7 +87,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|mle_header\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
quiet_cmd_zoffset = ZOFFSET $@
cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 850b8762e889..9f8f8c1db11a 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -300,7 +300,7 @@ _start:
# Part 2 of the header, from the old setup.S
.ascii "HdrS" # header signature
- .word 0x020d # header version number (>= 0x0105)
+ .word 0x020e # header version number (>= 0x0105)
# or else old loadlin-1.5 will fail)
.globl realmode_swtch
realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
@@ -557,6 +557,7 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
init_size: .long INIT_SIZE # kernel initialization size
handover_offset: .long 0 # Filled in by build.c
+mle_header_offset: .long 0 # Filled in by build.c
# End of setup header #####################################################
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index a93d44e58f9c..0dd6f1ffc66d 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -56,6 +56,7 @@ u8 buf[SETUP_SECT_MAX*512];
unsigned long efi32_stub_entry;
unsigned long efi64_stub_entry;
unsigned long efi_pe_entry;
+unsigned long mle_header;
unsigned long startup_64;
/*----------------------------------------------------------------------*/
@@ -289,6 +290,18 @@ static inline int reserve_pecoff_reloc_section(int c)
}
#endif /* CONFIG_EFI_STUB */
+#ifdef CONFIG_SECURE_LAUNCH_STUB
+
+static void slaunch_stub_entry_update(void)
+{
+ put_unaligned_le32(mle_header, &buf[0x268]);
+}
+
+#else
+
+static void slaunch_stub_entry_update(void) {}
+
+#endif /* CONFIG_SECURE_LAUNCH_STUB */
/*
* Parse zoffset.h and find the entry points. We could just #include zoffset.h
@@ -321,6 +334,7 @@ static void parse_zoffset(char *fname)
PARSE_ZOFS(p, efi32_stub_entry);
PARSE_ZOFS(p, efi64_stub_entry);
PARSE_ZOFS(p, efi_pe_entry);
+ PARSE_ZOFS(p, mle_header);
PARSE_ZOFS(p, startup_64);
p = strchr(p, '\n');
@@ -410,6 +424,8 @@ int main(int argc, char ** argv)
efi_stub_entry_update();
+ slaunch_stub_entry_update();
+
crc = partial_crc32(buf, i, crc);
if (fwrite(buf, 1, i, dest) != i)
die("Writing setup failed");
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 60733f137e9a..92cd63c99c9e 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -86,6 +86,7 @@ struct setup_header {
__u64 pref_address;
__u32 init_size;
__u32 handover_offset;
+ __u32 mle_header_offset;
} __attribute__((packed));
struct sys_desc_table {
--
2.13.6