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
 	 */