Merge "FVP: Add BL2 hash calculation in BL1" into integration
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 <assert.h>
+
+#include <bl1/bl1.h>
 #include <common/tbbr/tbbr_img_def.h>
 #include <drivers/arm/smmu_v3.h>
 #include <drivers/arm/sp805.h>
@@ -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 <common/tbbr/tbbr_img_def.h>
 #if TRUSTED_BOARD_BOOT
 #include <drivers/auth/mbedtls/mbedtls_config.h>
+#if MEASURED_BOOT
+#include <drivers/auth/crypto_mod.h>
+#include <mbedtls/md.h>
+#endif
 #endif
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
@@ -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 */