From 06b6c0103e079c902348eea8e18e2d6d29e2ecae Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Thu, 27 Jul 2023 09:39:53 +0200 Subject: [PATCH] Feature: verification of FSP images' signatures --- arch.mk | 4 ++ config/examples/x86_fsp_qemu.config | 3 +- hal/x86_fsp_qemu_stage1.ld.in | 17 ++++-- src/boot_x86_fsp.c | 85 +++++++++++++++++++++++++++++ src/image.c | 12 ++++ stage1/Makefile | 1 + stage1/x86_fsp.mk | 18 ++++++ 7 files changed, 135 insertions(+), 5 deletions(-) diff --git a/arch.mk b/arch.mk index 6aba9f6c..160aabcf 100644 --- a/arch.mk +++ b/arch.mk @@ -505,7 +505,11 @@ ifeq ("${FSP}", "1") OBJS += src/libwolfboot.o OBJS += src/image.o OBJS += src/keystore.o + OBJS += src/sig_fsp_m.o + OBJS += src/sig_fsp_s.o + OBJS += src/sig_fsp_t.o OBJS += $(WOLFCRYPT_OBJS) + CFLAGS+=-DSTAGE1_AUTH endif CFLAGS += -fno-stack-protector -m32 -fno-PIC -fno-pie -mno-mmx -mno-sse -DDEBUG_UART diff --git a/config/examples/x86_fsp_qemu.config b/config/examples/x86_fsp_qemu.config index 1833b423..48b64c3b 100644 --- a/config/examples/x86_fsp_qemu.config +++ b/config/examples/x86_fsp_qemu.config @@ -30,7 +30,7 @@ WOLFBOOT_DATA_ADDRESS=0x1000000 FSP_M_BASE=0xffe30000 FSP_S_BASE=0xffed6000 FSP_T_BASE=0xfffe0000 -WOLFBOOT_ORIGIN=0xffff0000 +WOLFBOOT_ORIGIN=0xfffa0000 LINUX_PAYLOAD=1 BOOTLOADER_PARTITION_SIZE=0xa0000 @@ -39,3 +39,4 @@ MACHINE_OBJ=src/x86/qemu_fsp.o FSP_T_BIN=./src/x86/fsp_t.bin FSP_M_BIN=./src/x86/fsp_m.bin FSP_S_BIN=./src/x86/fsp_s.bin +STAGE1_AUTH=1 diff --git a/hal/x86_fsp_qemu_stage1.ld.in b/hal/x86_fsp_qemu_stage1.ld.in index 9a4ff5c7..05a16a63 100644 --- a/hal/x86_fsp_qemu_stage1.ld.in +++ b/hal/x86_fsp_qemu_stage1.ld.in @@ -2,9 +2,9 @@ FLASH_SIZE = @BOOTLOADER_PARTITION_SIZE@; FLASH_START = 0x100000000 - @BOOTLOADER_PARTITION_SIZE@; BOOTLOADER_JUMP32_START = 0xfffff000; RESETVECTOR_START = 0xffffffec; -FSP_T_BASE = @FSP_T_BASE@; /* default base:size 0xFFFFF000:0x3000 [0xfffff000:0x100002000] */ -FSP_M_BASE = @FSP_M_BASE@; /* default base:size 0xfffdd000:0x22000 [0xfffdd000:0xfffff000] */ -FSP_S_BASE = @FSP_S_BASE@; /* default base:size 0xfffc8000:0x15000 [0xfffdd000:0xfffdd000] */ +FSP_T_BASE = @FSP_T_BASE@ - 0x1000; /* default base:size 0xFFFFF000:0x3000 [0xfffff000:0x100002000] */ +FSP_M_BASE = @FSP_M_BASE@ - 0x1000; /* default base:size 0xfffdd000:0x22000 [0xfffdd000:0xfffff000] */ +FSP_S_BASE = @FSP_S_BASE@ - 0x1000; /* default base:size 0xfffc8000:0x15000 [0xfffdd000:0xfffdd000] */ WOLFBOOT_LOAD_BASE = @WOLFBOOT_LOAD_BASE@; WOLFBOOT_ORIGIN = @WOLFBOOT_ORIGIN@; OUTPUT_FORMAT(elf32-i386) @@ -34,7 +34,7 @@ SECTIONS *(.rodata*) *(.eh_frame*) *(.data*) - . = ALIGN(4); + . = ALIGN(256); } .wolfboot FLASH_START : @@ -47,18 +47,27 @@ SECTIONS .fsp_t FSP_T_BASE : AT(FSP_T_BASE) { + . += 0x0F00; + _fsp_t_hdr = .; + KEEP(*(.sig_fsp_t*)) _start_fsp_t = .; *(.fsp_t) } .fsp_s FSP_S_BASE : { + . += 0x0F00; + _fsp_s_hdr = .; + KEEP(*(.sig_fsp_s*)) _start_fsp_s = .; *(.fsp_s) } .fsp_m FSP_M_BASE : { + . += 0x0F00; + _fsp_m_hdr = .; + KEEP(*(.sig_fsp_m*)) _start_fsp_m = .; *(.fsp_m) } diff --git a/src/boot_x86_fsp.c b/src/boot_x86_fsp.c index b7689812..eb1cc160 100644 --- a/src/boot_x86_fsp.c +++ b/src/boot_x86_fsp.c @@ -35,8 +35,24 @@ #include #include +#ifdef STAGE1_AUTH +#include "wolfboot/wolfboot.h" +#include "image.h" +#endif + #define WOLFBOOT_X86_STACK_SIZE 0x10000 + +#ifndef STAGE1_AUTH +/* When STAGE1_AUTH is disabled, create dummy images to fill + * the space used by wolfBoot manifest headers to authenticate FSPs + */ +#define HEADER_SIZE 0x100 +const uint8_t __attribute__((section(".sig_fsp_t"))) empty_sig_fsp_t[HEADER_SIZE]; +const uint8_t __attribute__((section(".sig_fsp_m"))) empty_sig_fsp_m[HEADER_SIZE]; +const uint8_t __attribute__((section(".sig_fsp_s"))) empty_sig_fsp_s[HEADER_SIZE]; +#endif + /* info can be retrieved from the CfgRegionSize of FSP info header. we need to * know this at compile time because to make things simpler we want to use the * stack to store the parameters and we don't want to include machine specific @@ -80,6 +96,9 @@ int post_temp_ram_init_cb(void); extern uint8_t _start_fsp_t[]; extern uint8_t _start_fsp_m[]; extern uint8_t _start_fsp_s[]; +extern uint8_t _fsp_t_hdr[]; +extern uint8_t _fsp_m_hdr[]; +extern uint8_t _fsp_s_hdr[]; extern uint8_t _wolfboot_flash_start[]; extern uint8_t _wolfboot_flash_end[]; extern uint8_t wb_end_bss[], wb_start_bss[]; @@ -172,6 +191,72 @@ static void memory_ready_entry(void *ptr) unsigned int i; int ret; +#ifdef STAGE1_AUTH + struct wolfBoot_image fsp_m, fsp_t, fsp_s; + + /* Verify FSP_M */ + ret = wolfBoot_open_image_address(&fsp_m, _fsp_m_hdr); + if (ret < 0) { + wolfBoot_printf("Failed to open FSP_M image" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_M open successfully." ENDLINE); + ret = wolfBoot_verify_integrity(&fsp_m); + if (ret < 0) { + wolfBoot_printf("Failed integrity check on FSP_M" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_M is valid. Checking signature." ENDLINE); + ret = wolfBoot_verify_authenticity(&fsp_m); + if (ret < 0) { + wolfBoot_printf("Failed signature check on FSP_M" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_M: verified OK." ENDLINE); + + /* Verify FSP_T */ + ret = wolfBoot_open_image_address(&fsp_m, _fsp_m_hdr); + ret = wolfBoot_open_image_address(&fsp_t, _fsp_t_hdr); + if (ret < 0) { + wolfBoot_printf("Failed to open FSP_T image" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_T open successfully." ENDLINE); + ret = wolfBoot_verify_integrity(&fsp_t); + if (ret < 0) { + wolfBoot_printf("Failed integrity check on FSP_T" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_T is valid. Checking signature." ENDLINE); + ret = wolfBoot_verify_authenticity(&fsp_t); + if (ret < 0) { + wolfBoot_printf("Failed signature check on FSP_T" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_T: verified OK." ENDLINE); + + /* Verify FSP_S */ + ret = wolfBoot_open_image_address(&fsp_s, _fsp_s_hdr); + if (ret < 0) { + wolfBoot_printf("Failed to open FSP_S image" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_S open successfully." ENDLINE); + ret = wolfBoot_verify_integrity(&fsp_s); + if (ret < 0) { + wolfBoot_printf("Failed integrity check on FSP_S" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_S is valid. Checking signature." ENDLINE); + ret = wolfBoot_verify_authenticity(&fsp_s); + if (ret < 0) { + wolfBoot_printf("Failed signature check on FSP_S" ENDLINE); + panic(); + } + wolfBoot_printf("FSP_S: verified OK." ENDLINE); + +#endif + fsp_info_header = (struct fsp_info_header *)(_start_fsp_m + FSP_INFO_HEADER_OFFSET); TempRamExit = (temp_ram_exit_cb)(_start_fsp_m + diff --git a/src/image.c b/src/image.c index 70749a5b..4fda57c5 100644 --- a/src/image.c +++ b/src/image.c @@ -959,6 +959,10 @@ int wolfBoot_verify_integrity(struct wolfBoot_image *img) { uint8_t *stored_sha; uint16_t stored_sha_len; +#ifdef STAGE1_AUTH + /* Override global */ + uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE]; +#endif stored_sha_len = get_header(img, WOLFBOOT_SHA_HDR, &stored_sha); if (stored_sha_len != WOLFBOOT_SHA_DIGEST_SIZE) return -1; @@ -999,6 +1003,10 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) uint32_t key_mask = 0U; uint32_t image_part = 1U; int key_slot; +#ifdef STAGE1_AUTH + /* Override global */ + uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE]; +#endif stored_signature_size = get_header(img, HDR_SIGNATURE, &stored_signature); if (stored_signature_size != IMAGE_SIGNATURE_SIZE) @@ -1068,6 +1076,10 @@ uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset, #ifndef WOLFBOOT_NO_SIGN static int keyslot_id_by_sha(const uint8_t *hint) { +#ifdef STAGE1_AUTH + /* Override global */ + uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE]; +#endif int id = 0; for (id = 0; id < keystore_num_pubkeys(); id++) { diff --git a/stage1/Makefile b/stage1/Makefile index c95d0af3..46336c1f 100644 --- a/stage1/Makefile +++ b/stage1/Makefile @@ -180,6 +180,7 @@ $(BUILD_DIR)/%.o: ../hal/%.S clean: $(Q)rm -f *.o + $(Q)rm -f *.bin $(Q)rm -f loader_stage1.bin loader_stage1.elf loader_stage1.map $(LSCRIPT) FORCE: diff --git a/stage1/x86_fsp.mk b/stage1/x86_fsp.mk index b6cfc959..8038f4a5 100644 --- a/stage1/x86_fsp.mk +++ b/stage1/x86_fsp.mk @@ -1,3 +1,9 @@ +SIGN_TOOL?=../tools/keytools/sign +SIGN_OPTIONS?=--ecc256 --sha256 +SIGN_KEY?=../wolfboot_signing_private_key.der +X86FSP_PATH?=../src/x86 + + $(LSCRIPT_IN): $(WOLFBOOT_ROOT)/hal/$(LSCRIPT_IN).in FORCE @cat $(WOLFBOOT_ROOT)/hal/$(LSCRIPT_IN).in | \ sed -e "s/@FSP_T_BASE@/$(FSP_T_BASE)/g" | \ @@ -14,13 +20,25 @@ $(LSCRIPT_IN): $(WOLFBOOT_ROOT)/hal/$(LSCRIPT_IN).in FORCE $(Q)nasm -f elf32 -o $@ $^ fsp_t.o: ../$(FSP_T_BIN) + $(SIGN_TOOL) $(SIGN_OPTIONS) $^ $(SIGN_KEY) 1 + @dd if=$(X86FSP_PATH)/fsp_t_v1_signed.bin of=$(X86FSP_PATH)/fsp_t_signature.bin bs=256 count=1 + $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.sig_fsp_t $(X86FSP_PATH)/fsp_t_signature.bin sig_fsp_t.o $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.fsp_t $^ $@ + @rm -f $(X86FSP_PATH)/fsp_t_v1_signed.bin $(X86FSP_PATH)/fsp_t_signature.bin fsp_m.o: ../$(FSP_M_BIN) + $(SIGN_TOOL) $(SIGN_OPTIONS) $^ $(SIGN_KEY) 1 + @dd if=$(X86FSP_PATH)/fsp_m_v1_signed.bin of=$(X86FSP_PATH)/fsp_m_signature.bin bs=256 count=1 + $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.sig_fsp_m $(X86FSP_PATH)/fsp_m_signature.bin sig_fsp_m.o $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.fsp_m $^ $@ + @rm -f $(X86FSP_PATH)/fsp_m_v1_signed.bin $(X86FSP_PATH)/fsp_m_signature.bin fsp_s.o: ../$(FSP_S_BIN) + $(SIGN_TOOL) $(SIGN_OPTIONS) $^ $(SIGN_KEY) 1 + @dd if=$(X86FSP_PATH)/fsp_s_v1_signed.bin of=$(X86FSP_PATH)/fsp_s_signature.bin bs=256 count=1 + $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.sig_fsp_s $(X86FSP_PATH)/fsp_s_signature.bin sig_fsp_s.o $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.fsp_s $^ $@ + @rm -f $(X86FSP_PATH)/fsp_s_v1_signed.bin $(X86FSP_PATH)/fsp_s_signature.bin wolfboot_raw.bin: ../wolfboot.elf $(Q)$(OBJCOPY) -j .text -O binary $^ $@