diff --git a/Makefile b/Makefile index 8049a18..a1702be 100644 --- a/Makefile +++ b/Makefile @@ -367,6 +367,10 @@ DTC_CPPFLAGS += -P -nostdinc -Iinclude -Ifdts -undef \ -x assembler-with-cpp $(DEFINES) +ifeq ($(MEASURED_BOOT),1) +DTC_CPPFLAGS += -DMEASURED_BOOT -DBL2_HASH_SIZE=${TCG_DIGEST_SIZE} +endif + ################################################################################ # Common sources and include directories ################################################################################ diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk index 044b368..564a4c9 100644 --- a/drivers/auth/mbedtls/mbedtls_common.mk +++ b/drivers/auth/mbedtls/mbedtls_common.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -75,10 +75,19 @@ ifeq (${HASH_ALG}, sha384) TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA384 + MBEDTLS_MD_ID := MBEDTLS_MD_SHA384 + TPM_ALG_ID := TPM_ALG_SHA384 + TCG_DIGEST_SIZE := 48 else ifeq (${HASH_ALG}, sha512) - TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA512 + TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA512 + MBEDTLS_MD_ID := MBEDTLS_MD_SHA512 + TPM_ALG_ID := TPM_ALG_SHA512 + TCG_DIGEST_SIZE := 64 else TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA256 + MBEDTLS_MD_ID := MBEDTLS_MD_SHA256 + TPM_ALG_ID := TPM_ALG_SHA256 + TCG_DIGEST_SIZE := 32 endif ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa) @@ -103,6 +112,11 @@ $(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID)) $(eval $(call add_define,TF_MBEDTLS_USE_AES_GCM)) +# Set definitions for measured boot driver +$(eval $(call add_define,MBEDTLS_MD_ID)) +$(eval $(call add_define,TPM_ALG_ID)) +$(eval $(call add_define,TCG_DIGEST_SIZE)) + $(eval $(call MAKE_LIB,mbedtls)) endif diff --git a/include/plat/arm/common/arm_dyn_cfg_helpers.h b/include/plat/arm/common/arm_dyn_cfg_helpers.h index 2dc94ab..34bf07c 100644 --- a/include/plat/arm/common/arm_dyn_cfg_helpers.h +++ b/include/plat/arm/common/arm_dyn_cfg_helpers.h @@ -14,4 +14,8 @@ int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size); +#if MEASURED_BOOT +int arm_set_bl2_hash_info(void *dtb, void *data); +#endif + #endif /* ARM_DYN_CFG_HELPERS_H */ diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index a84047a..83d4c20 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -238,6 +238,11 @@ void arm_bl1_set_mbedtls_heap(void); int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size); +#if MEASURED_BOOT +/* Measured boot related functions */ +void arm_bl1_set_bl2_hash(image_desc_t *image_desc); +#endif + /* * Free the memory storing initialization code only used during an images boot * time so it can be reclaimed for runtime data diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts index 704bf29..98ea857 100644 --- a/plat/arm/board/fvp/fdts/fvp_fw_config.dts +++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts @@ -67,6 +67,19 @@ */ mbedtls_heap_addr = <0x0 0x0>; mbedtls_heap_size = <0x0>; + +#if MEASURED_BOOT + /* BL2 image hash calculated by BL1 */ + bl2_hash_data = [ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#if BL2_HASH_SIZE > 32 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#if BL2_HASH_SIZE > 48 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#endif /* > 48 */ +#endif /* > 32 */ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]; +#endif /* MEASURED_BOOT */ }; /* diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c index 8f6170d..d13cc81 100644 --- a/plat/arm/board/fvp/fvp_bl1_setup.c +++ b/plat/arm/board/fvp/fvp_bl1_setup.c @@ -1,9 +1,12 @@ /* - * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include + +#include #include #include #include @@ -64,3 +67,52 @@ while (1) wfi(); } + +#if MEASURED_BOOT +/* + * Implementation for bl1_plat_handle_post_image_load(). This function + * populates the default arguments to BL2. The BL2 memory layout structure + * is allocated and the calculated layout is populated in arg1 to BL2. + */ +int bl1_plat_handle_post_image_load(unsigned int image_id) +{ + meminfo_t *bl2_tzram_layout; + meminfo_t *bl1_tzram_layout; + image_desc_t *image_desc; + entry_point_info_t *ep_info; + + if (image_id != BL2_IMAGE_ID) { + return 0; + } + + /* Get the image descriptor */ + image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(image_desc != NULL); + + /* Calculate BL2 hash and set it in TB_FW_CONFIG */ + arm_bl1_set_bl2_hash(image_desc); + + /* Get the entry point info */ + ep_info = &image_desc->ep_info; + + /* Find out how much free trusted ram remains after BL1 load */ + bl1_tzram_layout = bl1_plat_sec_mem_layout(); + + /* + * Create a new layout of memory for BL2 as seen by BL1 i.e. + * tell it the amount of total and free memory available. + * This layout is created at the first free address visible + * to BL2. BL2 will read the memory layout before using its + * memory for other purposes. + */ + bl2_tzram_layout = (meminfo_t *)bl1_tzram_layout->total_base; + + bl1_calc_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout); + + ep_info->args.arg1 = (uintptr_t)bl2_tzram_layout; + + VERBOSE("BL1: BL2 memory layout address = %p\n", + (void *)bl2_tzram_layout); + return 0; +} +#endif /* MEASURED_BOOT */ diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c index df75307..ffa2a64 100644 --- a/plat/arm/common/arm_dyn_cfg.c +++ b/plat/arm/common/arm_dyn_cfg.c @@ -15,6 +15,10 @@ #include #if TRUSTED_BOARD_BOOT #include +#if MEASURED_BOOT +#include +#include +#endif #endif #include #include @@ -87,7 +91,7 @@ * the default heap's address and size. */ - /* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB*/ + /* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */ tb_fw_cfg_dtb = FCONF_GET_PROPERTY(fconf, dtb, base_addr); if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) { @@ -100,15 +104,68 @@ ERROR("BL1: unable to write shared Mbed TLS heap information to DTB\n"); panic(); } +#if !MEASURED_BOOT /* * Ensure that the info written to the DTB is visible to other * images. It's critical because BL2 won't be able to proceed * without the heap info. + * + * In MEASURED_BOOT case flushing is done in + * arm_bl1_set_bl2_hash() function which is called after heap + * information is written in the DTB. */ flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize(dtb)); +#endif /* !MEASURED_BOOT */ } } +#if MEASURED_BOOT +/* + * Puts the BL2 hash data to TB_FW_CONFIG DTB. + * Executed only from BL1. + */ +void arm_bl1_set_bl2_hash(image_desc_t *image_desc) +{ + unsigned char hash_data[MBEDTLS_MD_MAX_SIZE]; + image_info_t image_info = image_desc->image_info; + uintptr_t tb_fw_cfg_dtb; + int err; + + /* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */ + tb_fw_cfg_dtb = FCONF_GET_PROPERTY(fconf, dtb, base_addr); + + /* + * If tb_fw_cfg_dtb==NULL then DTB is not present for the current + * platform. As such, we cannot write to the DTB at all and pass + * measured data. + */ + if (tb_fw_cfg_dtb == 0UL) { + panic(); + } + + /* Calculate hash */ + err = crypto_mod_calc_hash(MBEDTLS_MD_ID, + (void *)image_info.image_base, + image_info.image_size, hash_data); + if (err != 0) { + ERROR("BL1: unable to calculate BL2 hash\n"); + panic(); + } + + err = arm_set_bl2_hash_info((void *)tb_fw_cfg_dtb, hash_data); + if (err < 0) { + ERROR("BL1: unable to write BL2 hash data to DTB\n"); + panic(); + } + + /* + * Ensure that the info written to the DTB is visible to other + * images. It's critical because BL2 won't be able to proceed + * without the heap info and its hash data. + */ + flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize((void *)tb_fw_cfg_dtb)); +} +#endif /* MEASURED_BOOT */ #endif /* TRUSTED_BOARD_BOOT */ /* diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c index 909c4a6..f110e3b 100644 --- a/plat/arm/common/arm_dyn_cfg_helpers.c +++ b/plat/arm/common/arm_dyn_cfg_helpers.c @@ -15,6 +15,12 @@ #define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr" #define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size" +#if MEASURED_BOOT +#define DTB_PROP_BL2_HASH_DATA "bl2_hash_data" + +static int dtb_root = -1; +#endif /* MEASURED_BOOT */ + /******************************************************************************* * Validate the tb_fw_config is a valid DTB file and returns the node offset * to "arm,tb_fw" property. @@ -57,17 +63,18 @@ * * Returns: * 0 = success - * 1 = error + * -1 = error */ int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size) { - int err, dtb_root; - +#if !MEASURED_BOOT + int dtb_root; +#endif /* * Verify that the DTB is valid, before attempting to write to it, * and get the DTB root node. */ - err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root); + int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root); if (err < 0) { ERROR("Invalid TB_FW_CONFIG loaded. Unable to get root node\n"); return -1; @@ -98,3 +105,26 @@ return 0; } + +#if MEASURED_BOOT +/* + * This function writes the BL2 hash data in HW_FW_CONFIG DTB. + * When it is called, it is guaranteed that a DTB is available. + * + * This function is supposed to be called only by BL1. + * + * Returns: + * 0 = success + * < 0 = error + */ +int arm_set_bl2_hash_info(void *dtb, void *data) +{ + assert(dtb_root >= 0); + + /* + * Write the BL2 hash data in the DTB. + */ + return fdtw_write_inplace_bytes(dtb, dtb_root, DTB_PROP_BL2_HASH_DATA, + TCG_DIGEST_SIZE, data); +} +#endif /* MEASURED_BOOT */