TBB: authenticate BL3-x images and certificates

This patch adds support to authenticate the Trusted Key certificate
and the BL3-x certificates and images at BL2.

Change-Id: I69a8c13a14c8da8b75f93097d3a4576aed71c5dd
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index b7e2cff..29ca0a5 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -31,12 +31,149 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
+#include <auth.h>
 #include <bl_common.h>
 #include <debug.h>
 #include <platform.h>
 #include <platform_def.h>
 #include "bl2_private.h"
 
+#if TRUSTED_BOARD_BOOT
+
+#ifdef BL32_BASE
+static int bl32_cert_error;
+#endif
+
+/*
+ * Load and authenticate the key and content certificates for a BL3-x image
+ *
+ * Parameters:
+ *   key_cert_blob: key certificate blob id (see auth.h)
+ *   key_cert_name: key certificate filename
+ *   cont_cert_blob: content certificate blob id (see auth.h)
+ *   cont_cert_name: content certificate filename
+ *   mem_layout: Trusted SRAM memory layout
+ *   load_addr: load the certificates at this address
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int load_cert_bl3x(int key_cert_blob, const char *key_cert_name,
+			  int cont_cert_blob, const char *cont_cert_name,
+			  meminfo_t *mem_layout, uint64_t load_addr)
+{
+	image_info_t image_info;
+	int err;
+
+	/* Load Key certificate */
+	image_info.h.version = VERSION_1;
+	err = load_image(mem_layout, key_cert_name, load_addr, &image_info, NULL);
+	if (err) {
+		ERROR("Cannot load %s.\n", key_cert_name);
+		return err;
+	}
+
+	err = auth_verify_obj(key_cert_blob, image_info.image_base,
+			image_info.image_size);
+	if (err) {
+		ERROR("Invalid key certificate %s.\n", key_cert_name);
+		return err;
+	}
+
+	/* Load Content certificate */
+	image_info.h.version = VERSION_1;
+	err = load_image(mem_layout, cont_cert_name, load_addr, &image_info, NULL);
+	if (err) {
+		ERROR("Cannot load %s.\n", cont_cert_name);
+		return err;
+	}
+
+	err = auth_verify_obj(cont_cert_blob, image_info.image_base,
+			image_info.image_size);
+	if (err) {
+		ERROR("Invalid content certificate %s.\n", cont_cert_name);
+		return err;
+	}
+
+	return 0;
+}
+
+/*
+ * Load and authenticate the Trusted Key certificate the key and content
+ * certificates for each of the BL3-x images.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int load_certs(void)
+{
+	const uint64_t load_addr = BL31_BASE;
+	image_info_t image_info;
+	meminfo_t *mem_layout;
+	int err;
+
+	/* Find out how much free trusted ram remains after BL2 load */
+	mem_layout = bl2_plat_sec_mem_layout();
+
+	/* Load the Trusted Key certificate in the BL31 region */
+	image_info.h.version = VERSION_1;
+	err = load_image(mem_layout, TRUSTED_KEY_CERT_NAME, load_addr,
+			 &image_info, NULL);
+	if (err) {
+		ERROR("Failed to load Trusted Key certificate.\n");
+		return err;
+	}
+
+	/* Validate the certificate */
+	err = auth_verify_obj(AUTH_TRUSTED_KEY_CERT, image_info.image_base,
+			image_info.image_size);
+	if (err) {
+		ERROR("Invalid Trusted Key certificate.\n");
+		return err;
+	}
+
+	/* Load and validate Key and Content certificates for BL3-x images */
+#ifdef BL30_BASE
+	err = load_cert_bl3x(AUTH_BL30_KEY_CERT, BL30_KEY_CERT_NAME,
+			     AUTH_BL30_IMG_CERT, BL30_CERT_NAME,
+			     mem_layout, load_addr);
+	if (err) {
+		ERROR("Failed to verify BL3-0 authenticity\n");
+		return err;
+	}
+#endif /* BL30_BASE */
+
+	err = load_cert_bl3x(AUTH_BL31_KEY_CERT, BL31_KEY_CERT_NAME,
+			     AUTH_BL31_IMG_CERT, BL31_CERT_NAME,
+			     mem_layout, load_addr);
+	if (err) {
+		ERROR("Failed to verify BL3-1 authenticity\n");
+		return err;
+	}
+
+#ifdef BL32_BASE
+	/* BL3-2 image is optional, but keep the return value in case the
+	 * image is present but the certificate is missing */
+	err = load_cert_bl3x(AUTH_BL32_KEY_CERT, BL32_KEY_CERT_NAME,
+			     AUTH_BL32_IMG_CERT, BL32_CERT_NAME,
+			     mem_layout, load_addr);
+	if (err) {
+		WARN("Failed to verify BL3-2 authenticity\n");
+	}
+	bl32_cert_error = err;
+#endif /* BL32_BASE */
+
+	err = load_cert_bl3x(AUTH_BL33_KEY_CERT, BL33_KEY_CERT_NAME,
+			     AUTH_BL33_IMG_CERT, BL33_CERT_NAME,
+			     mem_layout, load_addr);
+	if (err) {
+		ERROR("Failed to verify BL3-3 authenticity\n");
+		return err;
+	}
+
+	return 0;
+}
+
+#endif /* TRUSTED_BOARD_BOOT */
+
 /*******************************************************************************
  * Load the BL3-0 image if there's one.
  * If a platform does not want to attempt to load BL3-0 image it must leave
@@ -69,6 +206,20 @@
 		       NULL);
 
 	if (e == 0) {
+#if TRUSTED_BOARD_BOOT
+		e = auth_verify_obj(AUTH_BL30_IMG,
+				bl30_image_info.image_base,
+				bl30_image_info.image_size);
+		if (e) {
+			ERROR("Failed to authenticate BL3-0 image.\n");
+			panic();
+		}
+
+		/* After working with data, invalidate the data cache */
+		inv_dcache_range(bl30_image_info.image_base,
+				 (size_t)bl30_image_info.image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
 		/* The subsequent handling of BL3-0 is platform specific */
 		bl2_plat_handle_bl30(&bl30_image_info);
 	}
@@ -106,9 +257,24 @@
 		       bl2_to_bl31_params->bl31_image_info,
 		       bl31_ep_info);
 
+	if (e == 0) {
+#if TRUSTED_BOARD_BOOT
+		e = auth_verify_obj(AUTH_BL31_IMG,
+			bl2_to_bl31_params->bl31_image_info->image_base,
+			bl2_to_bl31_params->bl31_image_info->image_size);
+		if (e) {
+			ERROR("Failed to authenticate BL3-1 image.\n");
+			panic();
+		}
+
+		/* After working with data, invalidate the data cache */
+		inv_dcache_range(bl2_to_bl31_params->bl31_image_info->image_base,
+			(size_t)bl2_to_bl31_params->bl31_image_info->image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
-	if (e == 0)
 		bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info,
 					  bl31_ep_info);
+	}
 
 	return e;
 }
@@ -144,6 +310,25 @@
 		       bl2_to_bl31_params->bl32_ep_info);
 
 	if (e == 0) {
+#if TRUSTED_BOARD_BOOT
+		/* Image is present. Check if there is a valid certificate */
+		if (bl32_cert_error) {
+			ERROR("Failed to authenticate BL3-2 certificates.\n");
+			panic();
+		}
+
+		e = auth_verify_obj(AUTH_BL32_IMG,
+			bl2_to_bl31_params->bl32_image_info->image_base,
+			bl2_to_bl31_params->bl32_image_info->image_size);
+		if (e) {
+			ERROR("Failed to authenticate BL3-2 image.\n");
+			panic();
+		}
+		/* After working with data, invalidate the data cache */
+		inv_dcache_range(bl2_to_bl31_params->bl32_image_info->image_base,
+			(size_t)bl2_to_bl31_params->bl32_image_info->image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
 		bl2_plat_set_bl32_ep_info(
 			bl2_to_bl31_params->bl32_image_info,
 			bl2_to_bl31_params->bl32_ep_info);
@@ -176,9 +361,23 @@
 		       bl2_to_bl31_params->bl33_image_info,
 		       bl2_to_bl31_params->bl33_ep_info);
 
-	if (e == 0)
+	if (e == 0) {
+#if TRUSTED_BOARD_BOOT
+		e = auth_verify_obj(AUTH_BL33_IMG,
+				bl2_to_bl31_params->bl33_image_info->image_base,
+				bl2_to_bl31_params->bl33_image_info->image_size);
+		if (e) {
+			ERROR("Failed to authenticate BL3-3 image.\n");
+			panic();
+		}
+		/* After working with data, invalidate the data cache */
+		inv_dcache_range(bl2_to_bl31_params->bl33_image_info->image_base,
+			(size_t)bl2_to_bl31_params->bl33_image_info->image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
 		bl2_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info,
 					  bl2_to_bl31_params->bl33_ep_info);
+	}
 
 	return e;
 }
@@ -200,6 +399,18 @@
 	/* Perform remaining generic architectural setup in S-EL1 */
 	bl2_arch_setup();
 
+#if TRUSTED_BOARD_BOOT
+	/* Initialize authentication module */
+	auth_init();
+
+	/* Validate the certificates involved in the Chain of Trust */
+	e = load_certs();
+	if (e) {
+		ERROR("Chain of Trust invalid. Aborting...\n");
+		panic();
+	}
+#endif /* TRUSTED_BOARD_BOOT */
+
 	/*
 	 * Load the subsequent bootloader images
 	 */
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 7d20590..0cec804 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -79,6 +79,19 @@
 #if TRUSTED_BOARD_BOOT
 	/* Certificates */
 	{BL2_CERT_NAME, UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT},
+	{TRUSTED_KEY_CERT_NAME, UUID_TRUSTED_KEY_CERT},
+#ifdef BL30_KEY_CERT_NAME
+	{BL30_KEY_CERT_NAME, UUID_SCP_FIRMWARE_BL30_KEY_CERT},
+#endif
+	{BL31_KEY_CERT_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT},
+	{BL32_KEY_CERT_NAME, UUID_SECURE_PAYLOAD_BL32_KEY_CERT},
+	{BL33_KEY_CERT_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT},
+#ifdef BL30_CERT_NAME
+	{BL30_CERT_NAME, UUID_SCP_FIRMWARE_BL30_CERT},
+#endif
+	{BL31_CERT_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT},
+	{BL32_CERT_NAME, UUID_SECURE_PAYLOAD_BL32_CERT},
+	{BL33_CERT_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33_CERT},
 #endif /* TRUSTED_BOARD_BOOT */
 };
 
diff --git a/plat/fvp/fvp_io_storage.c b/plat/fvp/fvp_io_storage.c
index b1e033e..ec1fe58 100644
--- a/plat/fvp/fvp_io_storage.c
+++ b/plat/fvp/fvp_io_storage.c
@@ -82,6 +82,51 @@
 	.path = BL2_CERT_NAME,
 	.mode = FOPEN_MODE_RB
 };
+
+static const io_file_spec_t trusted_key_cert_file_spec = {
+	.path = TRUSTED_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_key_cert_file_spec = {
+	.path = BL30_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_key_cert_file_spec = {
+	.path = BL31_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_key_cert_file_spec = {
+	.path = BL32_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_key_cert_file_spec = {
+	.path = BL33_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_cert_file_spec = {
+	.path = BL30_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_cert_file_spec = {
+	.path = BL31_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_cert_file_spec = {
+	.path = BL32_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_cert_file_spec = {
+	.path = BL33_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
 #endif /* TRUSTED_BOARD_BOOT */
 
 static int open_fip(const uintptr_t spec);
@@ -127,6 +172,51 @@
 		(uintptr_t)&bl2_cert_file_spec,
 		open_fip
 	}, {
+		TRUSTED_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&trusted_key_cert_file_spec,
+		open_fip
+	}, {
+		BL30_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl30_key_cert_file_spec,
+		open_fip
+	}, {
+		BL31_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl31_key_cert_file_spec,
+		open_fip
+	}, {
+		BL32_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl32_key_cert_file_spec,
+		open_fip
+	}, {
+		BL33_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl33_key_cert_file_spec,
+		open_fip
+	}, {
+		BL30_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl30_cert_file_spec,
+		open_fip
+	}, {
+		BL31_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl31_cert_file_spec,
+		open_fip
+	}, {
+		BL32_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl32_cert_file_spec,
+		open_fip
+	}, {
+		BL33_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl33_cert_file_spec,
+		open_fip
+	}, {
 #endif /* TRUSTED_BOARD_BOOT */
 		0, 0, 0
 	}
diff --git a/plat/fvp/include/platform_def.h b/plat/fvp/include/platform_def.h
index edbbdf3..326ba9d 100644
--- a/plat/fvp/include/platform_def.h
+++ b/plat/fvp/include/platform_def.h
@@ -83,6 +83,17 @@
 #if TRUSTED_BOARD_BOOT
 /* Certificates */
 # define BL2_CERT_NAME			"bl2.crt"
+# define TRUSTED_KEY_CERT_NAME		"trusted_key.crt"
+
+# define BL30_KEY_CERT_NAME		"bl30_key.crt"
+# define BL31_KEY_CERT_NAME		"bl31_key.crt"
+# define BL32_KEY_CERT_NAME		"bl32_key.crt"
+# define BL33_KEY_CERT_NAME		"bl33_key.crt"
+
+# define BL30_CERT_NAME			"bl30.crt"
+# define BL31_CERT_NAME			"bl31.crt"
+# define BL32_CERT_NAME			"bl32.crt"
+# define BL33_CERT_NAME			"bl33.crt"
 #endif /* TRUSTED_BOARD_BOOT */
 
 #define PLATFORM_CACHE_LINE_SIZE	64
diff --git a/plat/juno/include/platform_def.h b/plat/juno/include/platform_def.h
index 748b32d..1071d12 100644
--- a/plat/juno/include/platform_def.h
+++ b/plat/juno/include/platform_def.h
@@ -74,6 +74,17 @@
 #if TRUSTED_BOARD_BOOT
 /* Certificates */
 # define BL2_CERT_NAME			"bl2.crt"
+# define TRUSTED_KEY_CERT_NAME		"trusted_key.crt"
+
+# define BL30_KEY_CERT_NAME		"bl30_key.crt"
+# define BL31_KEY_CERT_NAME		"bl31_key.crt"
+# define BL32_KEY_CERT_NAME		"bl32_key.crt"
+# define BL33_KEY_CERT_NAME		"bl33_key.crt"
+
+# define BL30_CERT_NAME			"bl30.crt"
+# define BL31_CERT_NAME			"bl31.crt"
+# define BL32_CERT_NAME			"bl32.crt"
+# define BL33_CERT_NAME			"bl33.crt"
 #endif /* TRUSTED_BOARD_BOOT */
 
 #define PLATFORM_CACHE_LINE_SIZE	64
diff --git a/plat/juno/plat_io_storage.c b/plat/juno/plat_io_storage.c
index dd9f048..b31865e 100644
--- a/plat/juno/plat_io_storage.c
+++ b/plat/juno/plat_io_storage.c
@@ -82,6 +82,51 @@
 	.path = BL2_CERT_NAME,
 	.mode = FOPEN_MODE_RB
 };
+
+static const io_file_spec_t trusted_key_cert_file_spec = {
+	.path = TRUSTED_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_key_cert_file_spec = {
+	.path = BL30_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_key_cert_file_spec = {
+	.path = BL31_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_key_cert_file_spec = {
+	.path = BL32_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_key_cert_file_spec = {
+	.path = BL33_KEY_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_cert_file_spec = {
+	.path = BL30_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_cert_file_spec = {
+	.path = BL31_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_cert_file_spec = {
+	.path = BL32_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_cert_file_spec = {
+	.path = BL33_CERT_NAME,
+	.mode = FOPEN_MODE_RB
+};
 #endif /* TRUSTED_BOARD_BOOT */
 
 static int open_fip(const uintptr_t spec);
@@ -132,6 +177,51 @@
 		(uintptr_t)&bl2_cert_file_spec,
 		open_fip
 	}, {
+		TRUSTED_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&trusted_key_cert_file_spec,
+		open_fip
+	}, {
+		BL30_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl30_key_cert_file_spec,
+		open_fip
+	}, {
+		BL31_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl31_key_cert_file_spec,
+		open_fip
+	}, {
+		BL32_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl32_key_cert_file_spec,
+		open_fip
+	}, {
+		BL33_KEY_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl33_key_cert_file_spec,
+		open_fip
+	}, {
+		BL30_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl30_cert_file_spec,
+		open_fip
+	}, {
+		BL31_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl31_cert_file_spec,
+		open_fip
+	}, {
+		BL32_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl32_cert_file_spec,
+		open_fip
+	}, {
+		BL33_CERT_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl33_cert_file_spec,
+		open_fip
+	}, {
 #endif /* TRUSTED_BOARD_BOOT */
 		0, 0, 0
 	}