Merge pull request #249 from danh-arm/jc/tbb_prototype

Trusted Board Boot Prototype
diff --git a/.gitignore b/.gitignore
index 4220018..d3567bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,5 @@
 # Ignore build products from tools
 tools/**/*.o
 tools/fip_create/fip_create
+tools/cert_create/src/*.o
+tools/cert_create/cert_create
diff --git a/Makefile b/Makefile
index c59cdb4..9d4206c 100644
--- a/Makefile
+++ b/Makefile
@@ -67,6 +67,14 @@
 USE_COHERENT_MEM	:=	1
 # Default FIP file name
 FIP_NAME		:= fip.bin
+# By default, use the -pedantic option in the gcc command line
+DISABLE_PEDANTIC	:= 0
+# Flags to generate the Chain of Trust
+GENERATE_COT		:= 0
+CREATE_KEYS		:= 1
+# Flags to build TF with Trusted Boot support
+TRUSTED_BOARD_BOOT	:= 0
+AUTH_MOD		:= none
 
 # Checkpatch ignores
 CHECK_IGNORE		=	--ignore COMPLEX_MACRO
@@ -182,7 +190,7 @@
   # fip, then the NEED_BL32 needs to be set and BL3-2 would need to point to the bin.
 endif
 
-.PHONY:			all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip
+.PHONY:			all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip certtool
 .SUFFIXES:
 
 INCLUDES		+=	-Iinclude/bl31			\
@@ -236,11 +244,19 @@
 $(eval $(call assert_boolean,USE_COHERENT_MEM))
 $(eval $(call add_define,USE_COHERENT_MEM))
 
+# Process Generate CoT flags
+$(eval $(call assert_boolean,GENERATE_COT))
+$(eval $(call assert_boolean,CREATE_KEYS))
+
+# Process TRUSTED_BOARD_BOOT flag
+$(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
+$(eval $(call add_define,TRUSTED_BOARD_BOOT))
+
 ASFLAGS			+= 	-nostdinc -ffreestanding -Wa,--fatal-warnings	\
 				-Werror -Wmissing-include-dirs			\
 				-mgeneral-regs-only -D__ASSEMBLY__		\
 				${DEFINES} ${INCLUDES}
-CFLAGS			+= 	-nostdinc -pedantic -ffreestanding -Wall	\
+CFLAGS			+= 	-nostdinc -ffreestanding -Wall			\
 				-Werror -Wmissing-include-dirs			\
 				-mgeneral-regs-only -std=c99 -c -Os		\
 				${DEFINES} ${INCLUDES}
@@ -266,6 +282,53 @@
 fiptool:		${FIPTOOL}
 fip:			${BUILD_PLAT}/${FIP_NAME}
 
+# Variables for use with Certificate Generation Tool
+CRTTOOLPATH		?=	tools/cert_create
+CRTTOOL			?=	${CRTTOOLPATH}/cert_create
+certtool:		${CRTTOOL}
+
+# CoT generation tool default parameters
+TRUSTED_KEY_CERT	:=	${BUILD_PLAT}/trusted_key.crt
+
+# Pass the private keys to the CoT generation tool in the command line
+# If CREATE_KEYS is set, the '-n' option will be added, indicating the tool to create new keys
+ifneq (${GENERATE_COT},0)
+    $(eval CERTS := yes)
+
+    $(eval FIP_DEPS += certificates)
+    $(eval FIP_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT})
+
+    ifneq (${CREATE_KEYS},0)
+        $(eval CRT_ARGS += -n)
+    endif
+    $(eval CRT_ARGS += $(if ${ROT_KEY}, --rot-key ${ROT_KEY}))
+    $(eval CRT_ARGS += $(if ${TRUSTED_WORLD_KEY}, --trusted-world-key ${TRUSTED_WORLD_KEY}))
+    $(eval CRT_ARGS += $(if ${NON_TRUSTED_WORLD_KEY}, --non-trusted-world-key ${NON_TRUSTED_WORLD_KEY}))
+    $(eval CRT_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT})
+endif
+
+# Check Trusted Board Boot options
+ifneq (${TRUSTED_BOARD_BOOT},0)
+    ifeq (${AUTH_MOD},none)
+        $(error Error: When TRUSTED_BOARD_BOOT=1, AUTH_MOD has to be the name of a valid authentication module)
+    else
+        # We expect to locate an *.mk file under the specified AUTH_MOD directory
+        AUTH_MAKE := $(shell m="common/auth/${AUTH_MOD}/${AUTH_MOD}.mk"; [ -f "$$m" ] && echo "$$m")
+        ifeq (${AUTH_MAKE},)
+            $(error Error: No common/auth/${AUTH_MOD}/${AUTH_MOD}.mk located)
+        endif
+        $(info Including ${AUTH_MAKE})
+        include ${AUTH_MAKE}
+    endif
+
+    BL_COMMON_SOURCES	+=	common/auth.c
+endif
+
+# Check if -pedantic option should be used
+ifeq (${DISABLE_PEDANTIC},0)
+    CFLAGS		+= 	-pedantic
+endif
+
 locate-checkpatch:
 ifndef CHECKPATCH
 	$(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/script/checkpatch.pl")
@@ -279,12 +342,14 @@
 			@echo "  CLEAN"
 			${Q}rm -rf ${BUILD_PLAT}
 			${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
+			${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
 
 realclean distclean:
 			@echo "  REALCLEAN"
 			${Q}rm -rf ${BUILD_BASE}
 			${Q}rm -f ${CURDIR}/cscope.*
 			${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
+			${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
 
 checkcodebase:		locate-checkpatch
 			@echo "  CHECKING STYLE"
@@ -298,6 +363,13 @@
 			@echo "  CHECKING STYLE"
 			@git format-patch --stdout ${BASE_COMMIT} | ${CHECKPATCH} ${CHECKPATCH_ARGS} - || true
 
+.PHONY: ${CRTTOOL}
+${CRTTOOL}:
+			${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH}
+			@echo
+			@echo "Built $@ successfully"
+			@echo
+
 .PHONY: ${FIPTOOL}
 ${FIPTOOL}:
 			${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH}
@@ -398,6 +470,39 @@
 	$(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
 endef
 
+
+# MAKE_TOOL_ARGS macro defines the command line arguments for the FIP and CRT
+# tools at each BL stage. Arguments:
+#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(2) = Binary file
+#   $(3) = In FIP (false if empty)
+#   $(4) = Create certificates (false if empty)
+#   $(5) = Create key certificate (false if empty)
+#   $(6) = Private key (optional)
+define MAKE_TOOL_ARGS
+
+$(eval FIP_DEPS += $(if $3,$(2),))
+$(eval FIP_ARGS += $(if $3,--bl$(1) $(2),))
+$(eval FIP_ARGS += $(if $4,--bl$(1)-cert $(BUILD_PLAT)/bl$(1).crt))
+$(eval FIP_ARGS += $(if $4,$(if $5,--bl$(1)-key-cert $(BUILD_PLAT)/bl$(1)_key.crt)))
+
+$(eval CRT_DEPS += $(if $4,$(2),))
+$(eval CRT_DEPS += $(if $4,$(if $6,$(6),)))
+$(eval CRT_ARGS += $(if $4,--bl$(1) $(2)))
+$(eval CRT_ARGS += $(if $4,$(if $6,--bl$(1)-key $(6))))
+$(eval CRT_ARGS += $(if $4,--bl$(1)-cert $(BUILD_PLAT)/bl$(1).crt))
+$(eval CRT_ARGS += $(if $4,$(if $5,--bl$(1)-key-cert $(BUILD_PLAT)/bl$(1)_key.crt)))
+
+endef
+
+
+# MAKE_BL macro defines the targets and options to build each BL image.
+# Arguments:
+#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(2) = In FIP (false if empty)
+#   $(3) = Create certificates (false if empty)
+#   $(4) = Create key certificate (false if empty)
+#   $(5) = Private key (optional)
 define MAKE_BL
 	$(eval BUILD_DIR  := ${BUILD_PLAT}/bl$(1))
 	$(eval SOURCES    := $(BL$(1)_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES))
@@ -438,8 +543,7 @@
 
 all : bl$(1)
 
-$(eval FIP_DEPS += $(if $2,$(BIN),))
-$(eval FIP_ARGS += $(if $2,--bl$(1) $(BIN),))
+$(eval $(call MAKE_TOOL_ARGS,$(1),$(BIN),$(2),$(3),$(4),$(5)))
 
 endef
 
@@ -449,23 +553,23 @@
 endif
 
 ifeq (${NEED_BL2},yes)
-$(if ${BL2}, $(eval FIP_DEPS += ${BL2}) $(eval FIP_ARGS += --bl2 ${BL2}),\
-	$(eval $(call MAKE_BL,2,in_fip)))
+$(if ${BL2}, $(eval $(call MAKE_TOOL_ARGS,2,${BL2},in_fip,${CERTS})),\
+	$(eval $(call MAKE_BL,2,in_fip,${CERTS})))
 endif
 
 ifeq (${NEED_BL31},yes)
 BL31_SOURCES += ${SPD_SOURCES}
-$(if ${BL31}, $(eval FIP_DEPS += ${BL31}) $(eval FIP_ARGS += --bl31 ${BL31}),\
-	$(eval $(call MAKE_BL,31,in_fip)))
+$(if ${BL31}, $(eval $(call MAKE_TOOL_ARGS,31,${BL31},in_fip,${CERTS},${CERTS},${BL31_KEY})),\
+	$(eval $(call MAKE_BL,31,in_fip,${CERTS},${CERTS},${BL31_KEY})))
 endif
 
 ifeq (${NEED_BL32},yes)
-$(if ${BL32}, $(eval FIP_DEPS += ${BL32}) $(eval FIP_ARGS += --bl32 ${BL32}),\
-	$(eval $(call MAKE_BL,32,in_fip)))
+$(if ${BL32}, $(eval $(call MAKE_TOOL_ARGS,32,${BL32},in_fip,${CERTS},${CERTS},${BL32_KEY})),\
+	$(eval $(call MAKE_BL,32,in_fip,${CERTS},${CERTS},${BL32_KEY})))
 endif
 
 ifeq (${NEED_BL30},yes)
-$(if ${BL30}, $(eval FIP_DEPS += ${BL30}) $(eval FIP_ARGS += --bl30 ${BL30}), )
+$(if ${BL30}, $(eval $(call MAKE_TOOL_ARGS,30,${BL30},in_fip,${CERTS},${CERTS},${BL30_KEY})))
 
 # If BL3-0 is needed by the platform then 'BL30' variable must be defined.
 check_bl30:
@@ -479,7 +583,7 @@
 endif
 
 ifeq (${NEED_BL33},yes)
-$(if ${BL33}, $(eval FIP_DEPS += ${BL33}) $(eval FIP_ARGS += --bl33 ${BL33}), )
+$(if ${BL33}, $(eval $(call MAKE_TOOL_ARGS,33,${BL33},in_fip,${CERTS},${CERTS},${BL33_KEY})))
 
 # If BL3-3 is needed by the platform then 'BL33' variable must be defined.
 check_bl33:
@@ -492,6 +596,17 @@
 	$(if ${BL33},$(warning "BL3-3 is not supported on platform ${PLAT}, it will just be ignored"),)
 endif
 
+# Add the dependency on the certificates
+ifneq (${GENERATE_COT},0)
+    all: certificates
+endif
+
+certificates: ${CRT_DEPS} ${CRTTOOL} check_bl30 check_bl33
+			${Q}${CRTTOOL} ${CRT_ARGS}
+			@echo
+			@echo "Built $@ successfully"
+			@echo "Certificates can be found in ${BUILD_PLAT}"
+			@echo
 
 ${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL} check_bl30 check_bl33
 			${Q}${FIPTOOL} --dump \
@@ -524,6 +639,7 @@
 	@echo "  clean          Clean the build for the selected platform"
 	@echo "  cscope         Generate cscope index"
 	@echo "  distclean      Remove all build artifacts for all platforms"
+	@echo "  certtool       Build the Certificate generation tool"
 	@echo "  fiptool        Build the Firmware Image Package(FIP) creation tool"
 	@echo ""
 	@echo "note: most build targets require PLAT to be set to a specific platform."
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index a5bd648..491fd5c 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -31,6 +31,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
+#include <auth.h>
 #include <bl_common.h>
 #include <debug.h>
 #include <platform.h>
@@ -141,6 +142,34 @@
 	/* Find out how much free trusted ram remains after BL1 load */
 	bl1_tzram_layout = bl1_plat_sec_mem_layout();
 
+#if TRUSTED_BOARD_BOOT
+	/* Initialize authentication module */
+	auth_init();
+
+	/*
+	 * Load the BL2 certificate into the BL2 region. This region will be
+	 * overwritten by the image, so the authentication module is responsible
+	 * for storing the relevant data from the certificate (keys, hashes,
+	 * etc.) so it can be used later.
+	 */
+	err = load_image(bl1_tzram_layout,
+			 BL2_CERT_NAME,
+			 BL2_BASE,
+			 &bl2_image_info,
+			 NULL);
+	if (err) {
+		ERROR("Failed to load BL2 certificate.\n");
+		panic();
+	}
+
+	err = auth_verify_obj(AUTH_BL2_IMG_CERT, bl2_image_info.image_base,
+			bl2_image_info.image_size);
+	if (err) {
+		ERROR("Failed to validate BL2 certificate.\n");
+		panic();
+	}
+#endif /* TRUSTED_BOARD_BOOT */
+
 	/* Load the BL2 image */
 	err = load_image(bl1_tzram_layout,
 			 BL2_IMAGE_NAME,
@@ -155,6 +184,20 @@
 		ERROR("Failed to load BL2 firmware.\n");
 		panic();
 	}
+
+#if TRUSTED_BOARD_BOOT
+	err = auth_verify_obj(AUTH_BL2_IMG, bl2_image_info.image_base,
+				bl2_image_info.image_size);
+	if (err) {
+		ERROR("Failed to validate BL2 image.\n");
+		panic();
+	}
+
+	/* After working with data, invalidate the data cache */
+	inv_dcache_range(bl2_image_info.image_base,
+			(size_t)bl2_image_info.image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
 	/*
 	 * Create a new layout of memory for BL2 as seen by BL1 i.e.
 	 * tell it the amount of total and free memory available.
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 (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 */
+
 		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/common/auth.c b/common/auth.c
new file mode 100644
index 0000000..37234b8
--- /dev/null
+++ b/common/auth.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <auth.h>
+#include <debug.h>
+
+/*
+ * Initialize the authentication module
+ */
+void auth_init(void)
+{
+	assert(auth_mod.name);
+	assert(auth_mod.init);
+	assert(auth_mod.verify);
+
+	INFO("Using authentication module '%s'\n", auth_mod.name);
+	if (auth_mod.init() != 0)
+		assert(0);
+}
+
+/*
+ * Authenticate a certificate/image
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len)
+{
+	assert(obj_id < AUTH_NUM_OBJ);
+	assert(obj_buf != 0);
+	assert(auth_mod.verify);
+
+	return auth_mod.verify(obj_id, obj_buf, len);
+}
diff --git a/common/auth/polarssl/polarssl.c b/common/auth/polarssl/polarssl.c
new file mode 100644
index 0000000..e099f50
--- /dev/null
+++ b/common/auth/polarssl/polarssl.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Authentication module based on PolarSSL */
+
+#include <stddef.h>
+
+#include <assert.h>
+#include <auth.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <platform_oid.h>
+
+#include <polarssl/memory_buffer_alloc.h>
+#include <polarssl/oid.h>
+#include <polarssl/platform.h>
+#include <polarssl/sha256.h>
+#include <polarssl/x509_crt.h>
+
+/*
+ * At each authentication stage, the module is responsible for extracting and
+ * storing those elements (keys, hashes, etc.) that will be needed later on
+ * during the Trusted Boot process.
+ */
+
+/* SHA256 algorithm */
+#define SHA_BYTES			32
+
+/*
+ * An 8 KB stack has been proven to be enough for the current Trusted Boot
+ * process
+ */
+#define POLARSSL_HEAP_SIZE		(8*1024)
+static unsigned char heap[POLARSSL_HEAP_SIZE];
+
+/*
+ * RSA public keys:
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
+ *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
+ *                                                + 1 + 1 + 9 (rsa oid)
+ *                                                + 1 + 1 (params null)
+ *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
+ *  RSAPublicKey ::= SEQUENCE {                     1 + 3
+ *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
+ *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
+ *  }
+ *
+ * POLARSSL_MPI_MAX_SIZE is set to 256 bytes (RSA-2048 bit keys) in the
+ * configuration file
+ */
+#define RSA_PUB_DER_MAX_BYTES   38 + 2 * POLARSSL_MPI_MAX_SIZE
+
+/*
+ * Buffer for storing public keys extracted from certificates while they are
+ * verified
+ */
+static unsigned char pk_buf[RSA_PUB_DER_MAX_BYTES];
+
+/* We use this variable to parse and authenticate the certificates */
+static x509_crt cert;
+
+/* BL specific variables */
+#if IMAGE_BL1
+static unsigned char sha_bl2[SHA_BYTES];
+#elif IMAGE_BL2
+/* Buffers to store the hash of BL3-x images */
+static unsigned char sha_bl30[SHA_BYTES];
+static unsigned char sha_bl31[SHA_BYTES];
+static unsigned char sha_bl32[SHA_BYTES];
+static unsigned char sha_bl33[SHA_BYTES];
+/* Buffers to store the Trusted and Non-Trusted world public keys */
+static unsigned char tz_world_pk[RSA_PUB_DER_MAX_BYTES];
+static unsigned char ntz_world_pk[RSA_PUB_DER_MAX_BYTES];
+static size_t tz_world_pk_len, ntz_world_pk_len;
+/* Buffer to store the BL3-x public keys */
+static unsigned char content_pk[RSA_PUB_DER_MAX_BYTES];
+static size_t content_pk_len;
+#endif
+
+
+static int x509_get_crt_ext_data(const unsigned char **ext_data,
+				 size_t *ext_len,
+				 x509_crt *crt,
+				 const char *oid)
+{
+	int ret;
+	size_t len;
+	unsigned char *end_ext_data, *end_ext_octet;
+	unsigned char *p;
+	const unsigned char *end;
+	char oid_str[64];
+
+	p = crt->v3_ext.p;
+	end = crt->v3_ext.p + crt->v3_ext.len;
+
+	ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+	if (ret != 0)
+		return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+	if (end != p + len)
+		return POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+				POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+	while (p < end) {
+		/*
+		 * Extension  ::=  SEQUENCE  {
+		 *      extnID      OBJECT IDENTIFIER,
+		 *      critical    BOOLEAN DEFAULT FALSE,
+		 *      extnValue   OCTET STRING  }
+		 */
+		x509_buf extn_oid = {0, 0, NULL};
+		int is_critical = 0; /* DEFAULT FALSE */
+
+		ret = asn1_get_tag(&p, end, &len,
+				ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+		if (ret != 0)
+			return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+		end_ext_data = p + len;
+
+		/* Get extension ID */
+		extn_oid.tag = *p;
+
+		ret = asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID);
+		if (ret != 0)
+			return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+		extn_oid.p = p;
+		p += extn_oid.len;
+
+		if ((end - p) < 1)
+			return POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+					POLARSSL_ERR_ASN1_OUT_OF_DATA;
+
+		/* Get optional critical */
+		ret = asn1_get_bool(&p, end_ext_data, &is_critical);
+		if (ret != 0 && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG))
+			return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+		/* Data should be octet string type */
+		ret = asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING);
+		if (ret != 0)
+			return POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret;
+
+		end_ext_octet = p + len;
+
+		if (end_ext_octet != end_ext_data)
+			return POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+					POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+		/* Detect requested extension */
+		oid_get_numeric_string(oid_str, 64, &extn_oid);
+		if (memcmp(oid, oid_str, sizeof(oid)) == 0) {
+			*ext_data = p;
+			*ext_len = len;
+			return 0;
+		}
+
+		/* Next */
+		p = end_ext_octet;
+	}
+
+	if (p != end)
+		return POLARSSL_ERR_X509_INVALID_EXTENSIONS +
+				POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+
+	return POLARSSL_ERR_X509_UNKNOWN_OID;
+}
+
+#if IMAGE_BL1
+/*
+ * Parse and verify the BL2 certificate
+ *
+ * This function verifies the integrity of the BL2 certificate, checks that it
+ * has been signed with the ROT key and extracts the BL2 hash stored in the
+ * certificate so it can be matched later against the calculated hash.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int check_bl2_cert(unsigned char *buf, size_t len)
+{
+	const unsigned char *p;
+	size_t sz;
+	int err, flags;
+
+	x509_crt_init(&cert);
+
+	/* Parse the BL2 certificate */
+	err = x509_crt_parse(&cert, buf, len);
+	if (err) {
+		ERROR("BL2 certificate parse error %d.\n", err);
+		goto error;
+	}
+
+	/* Check that it has been signed with the ROT key */
+	err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf));
+	if (err < 0) {
+		ERROR("Error loading ROT key in DER format %d.\n", err);
+		goto error;
+	}
+
+	sz = (size_t)err;
+	p = pk_buf + sizeof(pk_buf) - sz;
+
+	err = plat_match_rotpk(p, sz);
+	if (err) {
+		ERROR("ROT and BL2 certificate key mismatch\n");
+		goto error;
+	}
+
+	/* Verify certificate */
+	err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
+	if (err) {
+		ERROR("BL2 certificate verification error %d. Flags: 0x%x.\n",
+				err, flags);
+		goto error;
+	}
+
+	/* Extract BL2 image hash from certificate */
+	err = x509_get_crt_ext_data(&p, &sz, &cert, BL2_HASH_OID);
+	if (err) {
+		ERROR("Cannot read BL2 hash from certificate\n");
+		goto error;
+	}
+
+	assert(sz == SHA_BYTES + 2);
+
+	/* Skip the tag and length bytes and copy the hash */
+	p += 2;
+	memcpy(sha_bl2, p, SHA_BYTES);
+
+error:
+	x509_crt_free(&cert);
+
+	return err;
+}
+#endif /* IMAGE_BL1 */
+
+#if IMAGE_BL2
+static int check_trusted_key_cert(unsigned char *buf, size_t len)
+{
+	const unsigned char *p;
+	size_t sz;
+	int err, flags;
+
+	x509_crt_init(&cert);
+
+	/* Parse the Trusted Key certificate */
+	err = x509_crt_parse(&cert, buf, len);
+	if (err) {
+		ERROR("Trusted Key certificate parse error %d.\n", err);
+		goto error;
+	}
+
+	/* Verify Trusted Key certificate */
+	err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
+	if (err) {
+		ERROR("Trusted Key certificate verification error %d. Flags: "
+				"0x%x.\n", err, flags);
+		goto error;
+	}
+
+	/* Check that it has been signed with the ROT key */
+	err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf));
+	if (err < 0) {
+		ERROR("Error loading ROT key in DER format %d.\n", err);
+		goto error;
+	}
+
+	sz = (size_t)err;
+	p = pk_buf + sizeof(pk_buf) - sz;
+
+	if (plat_match_rotpk(p, sz)) {
+		ERROR("ROT and Trusted Key certificate key mismatch\n");
+		goto error;
+	}
+
+	/* Extract Trusted World key from extensions */
+	err = x509_get_crt_ext_data(&p, &tz_world_pk_len,
+			&cert, TZ_WORLD_PK_OID);
+	if (err) {
+		ERROR("Cannot read Trusted World key\n");
+		goto error;
+	}
+
+	assert(tz_world_pk_len <= RSA_PUB_DER_MAX_BYTES);
+	memcpy(tz_world_pk, p, tz_world_pk_len);
+
+	/* Extract Non-Trusted World key from extensions */
+	err = x509_get_crt_ext_data(&p, &ntz_world_pk_len,
+			&cert, NTZ_WORLD_PK_OID);
+	if (err) {
+		ERROR("Cannot read Non-Trusted World key\n");
+		goto error;
+	}
+
+	assert(tz_world_pk_len <= RSA_PUB_DER_MAX_BYTES);
+	memcpy(ntz_world_pk, p, ntz_world_pk_len);
+
+error:
+	x509_crt_free(&cert);
+
+	return err;
+}
+
+static int check_bl3x_key_cert(const unsigned char *buf, size_t len,
+			       const unsigned char *i_key, size_t i_key_len,
+			       unsigned char *s_key, size_t *s_key_len,
+			       const char *key_oid)
+{
+	const unsigned char *p;
+	size_t sz;
+	int err, flags;
+
+	x509_crt_init(&cert);
+
+	/* Parse key certificate */
+	err = x509_crt_parse(&cert, buf, len);
+	if (err) {
+		ERROR("Key certificate parse error %d.\n", err);
+		goto error;
+	}
+
+	/* Verify certificate */
+	err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
+	if (err) {
+		ERROR("Key certificate verification error %d. Flags: "
+				"0x%x.\n", err, flags);
+		goto error;
+	}
+
+	/* Check that the certificate has been signed by the issuer */
+	err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf));
+	if (err < 0) {
+		ERROR("Error loading key in DER format %d.\n", err);
+		goto error;
+	}
+
+	sz = (size_t)err;
+	p = pk_buf + sizeof(pk_buf) - sz;
+	if ((sz != i_key_len) || memcmp(p, i_key, sz)) {
+		ERROR("Key certificate not signed with issuer key\n");
+		err = 1;
+		goto error;
+	}
+
+	/* Get the content certificate key */
+	err = x509_get_crt_ext_data(&p, &sz, &cert, key_oid);
+	if (err) {
+		ERROR("Extension %s not found in Key certificate\n", key_oid);
+		goto error;
+	}
+
+	assert(sz <= RSA_PUB_DER_MAX_BYTES);
+	memcpy(s_key, p, sz);
+	*s_key_len = sz;
+
+error:
+	x509_crt_free(&cert);
+
+	return err;
+}
+
+static int check_bl3x_cert(unsigned char *buf, size_t len,
+		       const unsigned char *i_key, size_t i_key_len,
+		       const char *hash_oid, unsigned char *sha)
+{
+	const unsigned char *p;
+	size_t sz;
+	int err, flags;
+
+	x509_crt_init(&cert);
+
+	/* Parse BL31 content certificate */
+	err = x509_crt_parse(&cert, buf, len);
+	if (err) {
+		ERROR("Content certificate parse error %d.\n", err);
+		goto error;
+	}
+
+	/* Verify certificate */
+	err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL);
+	if (err) {
+		ERROR("Content certificate verification error %d. Flags: "
+				"0x%x.\n", err, flags);
+		goto error;
+	}
+
+	/* Check that content certificate has been signed with the content
+	 * certificate key corresponding to this image */
+	sz = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf));
+	p = pk_buf + sizeof(pk_buf) - sz;
+
+	if ((sz != i_key_len) || memcmp(p, i_key, sz)) {
+		ERROR("Content certificate not signed with content "
+				"certificate key\n");
+		err = 1;
+		goto error;
+	}
+
+	/* Extract image hash from certificate */
+	err = x509_get_crt_ext_data(&p, &sz, &cert, hash_oid);
+	if (err) {
+		ERROR("Cannot read hash from certificate\n");
+		goto error;
+	}
+
+	assert(sz == SHA_BYTES + 2);
+
+	/* Skip the tag and length bytes and copy the hash */
+	p += 2;
+	memcpy(sha, p, SHA_BYTES);
+
+error:
+	x509_crt_free(&cert);
+
+	return err;
+}
+#endif /* IMAGE_BL2 */
+
+/*
+ * Calculate the hash of the image and check it against the hash extracted
+ * previously from the certificate
+ *
+ * Parameters:
+ *   buf: buffer where image is loaded
+ *   len: size of the image
+ *   sha: matching hash (extracted from the image certificate)
+ *
+ * Return: 0 = match, Otherwise = mismatch
+ */
+static int check_bl_img(unsigned char *buf, size_t len,
+			const unsigned char *sha)
+{
+	unsigned char img_sha[SHA_BYTES];
+
+	/* Calculate the hash of the image */
+	sha256(buf, len, img_sha, 0);
+
+	/* Match the hash with the one extracted from the certificate */
+	if (memcmp(img_sha, sha, SHA_BYTES)) {
+		ERROR("Image hash mismatch\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Object verification function
+ *
+ * The id parameter will indicate the expected format of the object
+ * (certificate, image, etc).
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int polarssl_mod_verify(unsigned int id, uintptr_t obj, size_t len)
+{
+	int ret;
+
+	switch (id) {
+#if IMAGE_BL1
+	case AUTH_BL2_IMG_CERT:
+		ret = check_bl2_cert((unsigned char *)obj, len);
+		break;
+	case AUTH_BL2_IMG:
+		ret = check_bl_img((unsigned char *)obj, len, sha_bl2);
+		break;
+#endif /* IMAGE_BL1 */
+
+#if IMAGE_BL2
+	case AUTH_TRUSTED_KEY_CERT:
+		ret = check_trusted_key_cert((unsigned char *)obj, len);
+		break;
+	case AUTH_BL30_KEY_CERT:
+		ret = check_bl3x_key_cert((unsigned char *)obj, len,
+				tz_world_pk, tz_world_pk_len,
+				content_pk, &content_pk_len,
+				BL30_CONTENT_CERT_PK_OID);
+		break;
+	case AUTH_BL31_KEY_CERT:
+		ret = check_bl3x_key_cert((unsigned char *)obj, len,
+				tz_world_pk, tz_world_pk_len,
+				content_pk, &content_pk_len,
+				BL31_CONTENT_CERT_PK_OID);
+		break;
+	case AUTH_BL32_KEY_CERT:
+		ret = check_bl3x_key_cert((unsigned char *)obj, len,
+				tz_world_pk, tz_world_pk_len,
+				content_pk, &content_pk_len,
+				BL32_CONTENT_CERT_PK_OID);
+		break;
+	case AUTH_BL33_KEY_CERT:
+		ret = check_bl3x_key_cert((unsigned char *)obj, len,
+				ntz_world_pk, ntz_world_pk_len,
+				content_pk, &content_pk_len,
+				BL33_CONTENT_CERT_PK_OID);
+		break;
+	case AUTH_BL30_IMG_CERT:
+		ret = check_bl3x_cert((unsigned char *)obj, len,
+				content_pk, content_pk_len,
+				BL30_HASH_OID, sha_bl30);
+		break;
+	case AUTH_BL31_IMG_CERT:
+		ret = check_bl3x_cert((unsigned char *)obj, len,
+				content_pk, content_pk_len,
+				BL31_HASH_OID, sha_bl31);
+		break;
+	case AUTH_BL32_IMG_CERT:
+		ret = check_bl3x_cert((unsigned char *)obj, len,
+				content_pk, content_pk_len,
+				BL32_HASH_OID, sha_bl32);
+		break;
+	case AUTH_BL33_IMG_CERT:
+		ret = check_bl3x_cert((unsigned char *)obj, len,
+				content_pk, content_pk_len,
+				BL33_HASH_OID, sha_bl33);
+		break;
+	case AUTH_BL30_IMG:
+		ret = check_bl_img((unsigned char *)obj, len, sha_bl30);
+		break;
+	case AUTH_BL31_IMG:
+		ret = check_bl_img((unsigned char *)obj, len, sha_bl31);
+		break;
+	case AUTH_BL32_IMG:
+		ret = check_bl_img((unsigned char *)obj, len, sha_bl32);
+		break;
+	case AUTH_BL33_IMG:
+		ret = check_bl_img((unsigned char *)obj, len, sha_bl33);
+		break;
+#endif /* IMAGE_BL2 */
+	default:
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Module initialization function
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int polarssl_mod_init(void)
+{
+	/* Initialize the PolarSSL heap */
+	return memory_buffer_alloc_init(heap, POLARSSL_HEAP_SIZE);
+}
+
+const auth_mod_t auth_mod = {
+	.name = "PolarSSL",
+	.init = polarssl_mod_init,
+	.verify = polarssl_mod_verify
+};
diff --git a/common/auth/polarssl/polarssl.mk b/common/auth/polarssl/polarssl.mk
new file mode 100644
index 0000000..f7d92ea
--- /dev/null
+++ b/common/auth/polarssl/polarssl.mk
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# POLARSSL_DIR must be set to the PolarSSL main directory (it must contain
+# the 'include' and 'library' subdirectories).
+ifeq (${POLARSSL_DIR},)
+  $(error Error: POLARSSL_DIR not set)
+endif
+
+INCLUDES		+=	-I${POLARSSL_DIR}/include		\
+				-Icommon/auth/polarssl
+
+POLARSSL_CONFIG_FILE	:=	"<polarssl_config.h>"
+$(eval $(call add_define,POLARSSL_CONFIG_FILE))
+
+POLARSSL_SOURCES	:=	$(addprefix ${POLARSSL_DIR}/library/,	\
+				asn1parse.c 				\
+				asn1write.c 				\
+				bignum.c				\
+				md.c					\
+				md_wrap.c				\
+				memory_buffer_alloc.c			\
+				oid.c 					\
+				pk.c 					\
+				pk_wrap.c 				\
+				pkparse.c 				\
+				pkwrite.c 				\
+				platform.c 				\
+				rsa.c 					\
+				sha1.c					\
+				sha256.c				\
+				x509.c 					\
+				x509_crt.c 				\
+				)
+
+BL1_SOURCES		+=	${POLARSSL_SOURCES} 			\
+				common/auth/polarssl/polarssl.c
+
+BL2_SOURCES		+=	${POLARSSL_SOURCES} 			\
+				common/auth/polarssl/polarssl.c
+
+DISABLE_PEDANTIC	:=	1
diff --git a/common/auth/polarssl/polarssl_config.h b/common/auth/polarssl/polarssl_config.h
new file mode 100644
index 0000000..531e084
--- /dev/null
+++ b/common/auth/polarssl/polarssl_config.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __POLARSSL_CONFIG_H__
+#define __POLARSSL_CONFIG_H__
+
+
+/*
+ * Configuration file to build PolarSSL with the required features for
+ * Trusted Boot
+ */
+
+#define POLARSSL_PLATFORM_MEMORY
+#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS
+
+#define POLARSSL_PKCS1_V15
+#define POLARSSL_PKCS1_V21
+
+#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+#define POLARSSL_X509_CHECK_KEY_USAGE
+#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE
+
+#define POLARSSL_ASN1_PARSE_C
+#define POLARSSL_ASN1_WRITE_C
+
+#define POLARSSL_BASE64_C
+#define POLARSSL_BIGNUM_C
+
+#define POLARSSL_ERROR_C
+#define POLARSSL_MD_C
+
+#define POLARSSL_MEMORY_BUFFER_ALLOC_C
+#define POLARSSL_OID_C
+
+#define POLARSSL_PK_C
+#define POLARSSL_PK_PARSE_C
+#define POLARSSL_PK_WRITE_C
+
+#define POLARSSL_PLATFORM_C
+
+#define POLARSSL_RSA_C
+#define POLARSSL_SHA1_C
+#define POLARSSL_SHA256_C
+
+#define POLARSSL_VERSION_C
+
+#define POLARSSL_X509_USE_C
+#define POLARSSL_X509_CRT_PARSE_C
+
+/* MPI / BIGNUM options */
+#define POLARSSL_MPI_WINDOW_SIZE              2
+#define POLARSSL_MPI_MAX_SIZE               256
+
+/* Memory buffer allocator options */
+#define POLARSSL_MEMORY_ALIGN_MULTIPLE        8
+
+#include "polarssl/check_config.h"
+
+#endif /* __POLARSSL_CONFIG_H__ */
diff --git a/common/bl_common.c b/common/bl_common.c
index 60f8b2f..8c241ec 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -275,9 +275,16 @@
 	 * Update the memory usage info.
 	 * This is done after the actual loading so that it is not updated when
 	 * the load is unsuccessful.
+	 * If the caller does not provide an entry point, bypass the memory
+	 * reservation.
 	 */
-	reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
-		    image_base, image_size);
+	if (entry_point_info != NULL) {
+		reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
+				image_base, image_size);
+	} else {
+		INFO("Skip reserving memory: 0x%lx - 0x%lx\n",
+				image_base, image_base + image_size);
+	}
 
 	image_data->image_base = image_base;
 	image_data->image_size = image_size;
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 747cb00..a30535d 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -392,6 +392,17 @@
 providing the warm-boot entry-point addresses.
 
 
+### Function: plat_match_rotpk()
+
+    Argument : const unsigned char *, unsigned int
+    Return   : int
+
+This function is mandatory when Trusted Board Boot is enabled. It receives a
+pointer to a buffer containing a signing key and its size as parameters and
+returns 0 (success) if that key matches the ROT (Root Of Trust) key stored in
+the platform. Any other return value means a mismatch.
+
+
 
 2.3 Common optional modifications
 ---------------------------------
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 4262a9d..0cec804 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -76,6 +76,23 @@
 	{BL32_IMAGE_NAME, UUID_SECURE_PAYLOAD_BL32},
 #endif /* BL32_IMAGE_NAME */
 	{BL33_IMAGE_NAME, UUID_NON_TRUSTED_FIRMWARE_BL33},
+#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 */
 };
 
 static const uuid_t uuid_null = {0};
diff --git a/include/common/auth.h b/include/common/auth.h
new file mode 100644
index 0000000..3c3a6bd
--- /dev/null
+++ b/include/common/auth.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AUTH_H_
+#define AUTH_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * Authentication infrastructure for Trusted Boot
+ *
+ * This infrastructure provides an API to access the authentication module. This
+ * module will implement the required operations for Trusted Boot by creating an
+ * instance of the structure 'auth_mod_t'. This instance must be called
+ * 'auth_mod' and must provide the functions to initialize the module and
+ * verify the authenticity of the images.
+ */
+
+/* Objects (images and certificates) involved in the TBB process */
+enum {
+	AUTH_BL2_IMG_CERT,
+	AUTH_BL2_IMG,
+	AUTH_TRUSTED_KEY_CERT,
+	AUTH_BL30_KEY_CERT,
+	AUTH_BL30_IMG_CERT,
+	AUTH_BL30_IMG,
+	AUTH_BL31_KEY_CERT,
+	AUTH_BL31_IMG_CERT,
+	AUTH_BL31_IMG,
+	AUTH_BL32_KEY_CERT,
+	AUTH_BL32_IMG_CERT,
+	AUTH_BL32_IMG,
+	AUTH_BL33_KEY_CERT,
+	AUTH_BL33_IMG_CERT,
+	AUTH_BL33_IMG,
+	AUTH_NUM_OBJ
+};
+
+/* Authentication module structure */
+typedef struct auth_mod_s {
+	/* [mandatory] Module name. Printed to the log during initialization */
+	const char *name;
+
+	/* [mandatory] Initialize the authentication module */
+	int (*init)(void);
+
+	/* [mandatory] This function will be called to authenticate a new
+	 * object loaded into memory. The obj_id corresponds to one of the
+	 * values in the enumeration above */
+	int (*verify)(unsigned int obj_id, uintptr_t obj_buf, size_t len);
+} auth_mod_t;
+
+/* This variable must be instantiated by the authentication module */
+extern const auth_mod_t auth_mod;
+
+/* Public functions */
+void auth_init(void);
+int auth_verify_obj(unsigned int obj_id, uintptr_t obj_buf, size_t len);
+
+#endif /* AUTH_H_ */
diff --git a/include/common/firmware_image_package.h b/include/common/firmware_image_package.h
index f4554ec..8fb669e 100644
--- a/include/common/firmware_image_package.h
+++ b/include/common/firmware_image_package.h
@@ -49,6 +49,32 @@
 	{0x89e1d005, 0xdc53, 0x4713, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} }
 #define UUID_NON_TRUSTED_FIRMWARE_BL33 \
 	{0xa7eed0d6, 0xeafc, 0x4bd5, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} }
+/* Key certificates */
+#define UUID_ROT_KEY_CERT \
+	{0x721d2d86, 0x60f8, 0x11e4, 0x92, 0x0b, {0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24} }
+#define UUID_TRUSTED_KEY_CERT \
+	{0x90e87e82, 0x60f8, 0x11e4, 0xa1, 0xb4, {0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c} }
+#define UUID_NON_TRUSTED_WORLD_KEY_CERT \
+	{0x3d87671c, 0x635f, 0x11e4, 0x97, 0x8d, {0x27, 0xc0, 0xc7, 0x14, 0x8a, 0xbd} }
+#define UUID_SCP_FIRMWARE_BL30_KEY_CERT \
+	{0xa1214202, 0x60f8, 0x11e4, 0x8d, 0x9b, {0xf3, 0x3c, 0x0e, 0x15, 0xa0, 0x14} }
+#define UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT \
+	{0xccbeb88a, 0x60f9, 0x11e4, 0x9a, 0xd0, {0xeb, 0x48, 0x22, 0xd8, 0xdc, 0xf8} }
+#define UUID_SECURE_PAYLOAD_BL32_KEY_CERT \
+	{0x03d67794, 0x60fb, 0x11e4, 0x85, 0xdd, {0xb7, 0x10, 0x5b, 0x8c, 0xee, 0x04} }
+#define UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT \
+	{0x2a83d58a, 0x60fb, 0x11e4, 0x8a, 0xaf, {0xdf, 0x30, 0xbb, 0xc4, 0x98, 0x59} }
+/* Content certificates */
+#define UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT \
+	{0xea69e2d6, 0x635d, 0x11e4, 0x8d, 0x8c, {0x9f, 0xba, 0xbe, 0x99, 0x56, 0xa5} }
+#define UUID_SCP_FIRMWARE_BL30_CERT \
+	{0x046fbe44, 0x635e, 0x11e4, 0xb2, 0x8b, {0x73, 0xd8, 0xea, 0xae, 0x96, 0x56} }
+#define UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT \
+	{0x200cb2e2, 0x635e, 0x11e4, 0x9c, 0xe8, {0xab, 0xcc, 0xf9, 0x2b, 0xb6, 0x66} }
+#define UUID_SECURE_PAYLOAD_BL32_CERT \
+	{0x11449fa4, 0x635e, 0x11e4, 0x87, 0x28, {0x3f, 0x05, 0x72, 0x2a, 0xf3, 0x3d} }
+#define UUID_NON_TRUSTED_FIRMWARE_BL33_CERT \
+	{0xf3c1c48e, 0x635d, 0x11e4, 0xa7, 0xa9, {0x87, 0xee, 0x40, 0xb2, 0x3f, 0xa7} }
 
 typedef struct fip_toc_header {
 	uint32_t	name;
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 69bb749..18b7eae 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -191,4 +191,9 @@
  ******************************************************************************/
 void bl32_plat_enable_mmu(uint32_t flags);
 
+/*******************************************************************************
+ * Trusted Boot functions
+ ******************************************************************************/
+int plat_match_rotpk(const unsigned char *, unsigned int);
+
 #endif /* __PLATFORM_H__ */
diff --git a/include/stdlib/inttypes.h b/include/stdlib/inttypes.h
new file mode 100644
index 0000000..269f3e7
--- /dev/null
+++ b/include/stdlib/inttypes.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _INTTYPES_H_
+#define	_INTTYPES_H_
+
+#include <machine/_inttypes.h>
+#include <sys/stdint.h>
+
+typedef struct {
+	intmax_t	quot;		/* Quotient. */
+	intmax_t	rem;		/* Remainder. */
+} imaxdiv_t;
+
+__BEGIN_DECLS
+#ifdef _XLOCALE_H_
+#include <xlocale/_inttypes.h>
+#endif
+intmax_t	imaxabs(intmax_t) __pure2;
+imaxdiv_t	imaxdiv(intmax_t, intmax_t) __pure2;
+
+intmax_t	strtoimax(const char *__restrict, char **__restrict, int);
+uintmax_t	strtoumax(const char *__restrict, char **__restrict, int);
+
+__END_DECLS
+
+#endif /* !_INTTYPES_H_ */
diff --git a/include/stdlib/machine/_inttypes.h b/include/stdlib/machine/_inttypes.h
new file mode 100644
index 0000000..8dd07d6
--- /dev/null
+++ b/include/stdlib/machine/_inttypes.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_INTTYPES_H_
+#define _MACHINE_INTTYPES_H_
+
+/*
+ * Trusted Firmware does not depend on any definitions in this file. Content
+ * will be added as needed.
+ */
+
+#endif /* !_MACHINE_INTTYPES_H_ */
diff --git a/include/stdlib/stdio.h b/include/stdlib/stdio.h
index 1b8429b..60e081b 100644
--- a/include/stdlib/stdio.h
+++ b/include/stdlib/stdio.h
@@ -65,6 +65,8 @@
 int	 vsprintf(char * __restrict, const char * __restrict,
 	   __va_list);
 
+int	 sscanf(const char *__restrict, char const *__restrict, ...);
+
 #if __ISO_C_VISIBLE >= 1999
 int	 snprintf(char * __restrict, size_t, const char * __restrict,
 	   ...) __printflike(3, 4);
diff --git a/include/stdlib/stdlib.h b/include/stdlib/stdlib.h
new file mode 100644
index 0000000..b1ac1bf
--- /dev/null
+++ b/include/stdlib/stdlib.h
@@ -0,0 +1,313 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)stdlib.h	8.5 (Berkeley) 5/19/95
+ * $FreeBSD$
+ */
+
+#ifndef _STDLIB_H_
+#define	_STDLIB_H_
+
+#include <sys/cdefs.h>
+#include <sys/_null.h>
+#include <sys/_types.h>
+
+#if __BSD_VISIBLE
+#ifndef _RUNE_T_DECLARED
+typedef	__rune_t	rune_t;
+#define	_RUNE_T_DECLARED
+#endif
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef	__size_t	size_t;
+#define	_SIZE_T_DECLARED
+#endif
+
+typedef struct {
+	int	quot;		/* quotient */
+	int	rem;		/* remainder */
+} div_t;
+
+typedef struct {
+	long	quot;
+	long	rem;
+} ldiv_t;
+
+#define	EXIT_FAILURE	1
+#define	EXIT_SUCCESS	0
+
+#define	RAND_MAX	0x7ffffffd
+
+__BEGIN_DECLS
+#ifdef _XLOCALE_H_
+#include <xlocale/_stdlib.h>
+#endif
+extern int __mb_cur_max;
+extern int ___mb_cur_max(void);
+#define	MB_CUR_MAX	(___mb_cur_max())
+
+_Noreturn void	 abort(void);
+int	 abs(int) __pure2;
+int	 atexit(void (*)(void));
+double	 atof(const char *);
+int	 atoi(const char *);
+long	 atol(const char *);
+void	*bsearch(const void *, const void *, size_t,
+	    size_t, int (*)(const void *, const void *));
+void	*calloc(size_t, size_t) __malloc_like;
+div_t	 div(int, int) __pure2;
+_Noreturn void	 exit(int);
+void	 free(void *);
+char	*getenv(const char *);
+long	 labs(long) __pure2;
+ldiv_t	 ldiv(long, long) __pure2;
+void	*malloc(size_t) __malloc_like;
+int	 mblen(const char *, size_t);
+void	 qsort(void *, size_t, size_t,
+	    int (*)(const void *, const void *));
+int	 rand(void);
+void	*realloc(void *, size_t);
+void	 srand(unsigned);
+double	 strtod(const char *__restrict, char **__restrict);
+float	 strtof(const char *__restrict, char **__restrict);
+long	 strtol(const char *__restrict, char **__restrict, int);
+long double
+	 strtold(const char *__restrict, char **__restrict);
+unsigned long
+	 strtoul(const char *__restrict, char **__restrict, int);
+int	 system(const char *);
+
+/*
+ * Functions added in C99 which we make conditionally available in the
+ * BSD^C89 namespace if the compiler supports `long long'.
+ * The #if test is more complicated than it ought to be because
+ * __BSD_VISIBLE implies __ISO_C_VISIBLE == 1999 *even if* `long long'
+ * is not supported in the compilation environment (which therefore means
+ * that it can't really be ISO C99).
+ *
+ * (The only other extension made by C99 in thie header is _Exit().)
+ */
+#if __ISO_C_VISIBLE >= 1999
+#ifdef __LONG_LONG_SUPPORTED
+/* LONGLONG */
+typedef struct {
+	long long quot;
+	long long rem;
+} lldiv_t;
+
+/* LONGLONG */
+long long
+	 atoll(const char *);
+/* LONGLONG */
+long long
+	 llabs(long long) __pure2;
+/* LONGLONG */
+lldiv_t	 lldiv(long long, long long) __pure2;
+/* LONGLONG */
+long long
+	 strtoll(const char *__restrict, char **__restrict, int);
+/* LONGLONG */
+unsigned long long
+	 strtoull(const char *__restrict, char **__restrict, int);
+#endif /* __LONG_LONG_SUPPORTED */
+
+_Noreturn void	 _Exit(int);
+#endif /* __ISO_C_VISIBLE >= 1999 */
+
+/*
+ * If we're in a mode greater than C99, expose C11 functions.
+ */
+#if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L
+void *aligned_alloc(size_t, size_t) __malloc_like;
+int	at_quick_exit(void (*)(void));
+_Noreturn void
+	quick_exit(int);
+#endif /* __ISO_C_VISIBLE >= 2011 */
+/*
+ * Extensions made by POSIX relative to C.
+ */
+#if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE
+char	*realpath(const char *__restrict, char *__restrict);
+#endif
+#if __POSIX_VISIBLE >= 199506
+int	 rand_r(unsigned *);			/* (TSF) */
+#endif
+#if __POSIX_VISIBLE >= 200112
+int	 posix_memalign(void **, size_t, size_t); /* (ADV) */
+int	 setenv(const char *, const char *, int);
+int	 unsetenv(const char *);
+#endif
+
+#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE
+int	 getsubopt(char **, char *const *, char **);
+#ifndef _MKDTEMP_DECLARED
+char	*mkdtemp(char *);
+#define	_MKDTEMP_DECLARED
+#endif
+#ifndef _MKSTEMP_DECLARED
+int	 mkstemp(char *);
+#define	_MKSTEMP_DECLARED
+#endif
+#endif /* __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE */
+
+/*
+ * The only changes to the XSI namespace in revision 6 were the deletion
+ * of the ttyslot() and valloc() functions, which FreeBSD never declared
+ * in this header.  For revision 7, ecvt(), fcvt(), and gcvt(), which
+ * FreeBSD also does not have, and mktemp(), are to be deleted.
+ */
+#if __XSI_VISIBLE
+/* XXX XSI requires pollution from <sys/wait.h> here.  We'd rather not. */
+long	 a64l(const char *);
+double	 drand48(void);
+/* char	*ecvt(double, int, int * __restrict, int * __restrict); */
+double	 erand48(unsigned short[3]);
+/* char	*fcvt(double, int, int * __restrict, int * __restrict); */
+/* char	*gcvt(double, int, int * __restrict, int * __restrict); */
+int	 grantpt(int);
+char	*initstate(unsigned long /* XSI requires u_int */, char *, long);
+long	 jrand48(unsigned short[3]);
+char	*l64a(long);
+void	 lcong48(unsigned short[7]);
+long	 lrand48(void);
+#if !defined(_MKTEMP_DECLARED) && (__BSD_VISIBLE || __XSI_VISIBLE <= 600)
+char	*mktemp(char *);
+#define	_MKTEMP_DECLARED
+#endif
+long	 mrand48(void);
+long	 nrand48(unsigned short[3]);
+int	 posix_openpt(int);
+char	*ptsname(int);
+int	 putenv(char *);
+long	 random(void);
+unsigned short
+	*seed48(unsigned short[3]);
+#ifndef _SETKEY_DECLARED
+int	 setkey(const char *);
+#define	_SETKEY_DECLARED
+#endif
+char	*setstate(/* const */ char *);
+void	 srand48(long);
+void	 srandom(unsigned long);
+int	 unlockpt(int);
+#endif /* __XSI_VISIBLE */
+
+#if __BSD_VISIBLE
+extern const char *malloc_conf;
+extern void (*malloc_message)(void *, const char *);
+
+/*
+ * The alloca() function can't be implemented in C, and on some
+ * platforms it can't be implemented at all as a callable function.
+ * The GNU C compiler provides a built-in alloca() which we can use;
+ * in all other cases, provide a prototype, mainly to pacify various
+ * incarnations of lint.  On platforms where alloca() is not in libc,
+ * programs which use it will fail to link when compiled with non-GNU
+ * compilers.
+ */
+#if __GNUC__ >= 2 || defined(__INTEL_COMPILER)
+#undef  alloca	/* some GNU bits try to get cute and define this on their own */
+#define alloca(sz) __builtin_alloca(sz)
+#elif defined(lint)
+void	*alloca(size_t);
+#endif
+
+void	 abort2(const char *, int, void **) __dead2;
+__uint32_t
+	 arc4random(void);
+void	 arc4random_addrandom(unsigned char *, int);
+void	 arc4random_buf(void *, size_t);
+void	 arc4random_stir(void);
+__uint32_t
+	 arc4random_uniform(__uint32_t);
+#ifdef __BLOCKS__
+int	 atexit_b(void (^)(void));
+void	*bsearch_b(const void *, const void *, size_t,
+	    size_t, int (^)(const void *, const void *));
+#endif
+char	*getbsize(int *, long *);
+					/* getcap(3) functions */
+char	*cgetcap(char *, const char *, int);
+int	 cgetclose(void);
+int	 cgetent(char **, char **, const char *);
+int	 cgetfirst(char **, char **);
+int	 cgetmatch(const char *, const char *);
+int	 cgetnext(char **, char **);
+int	 cgetnum(char *, const char *, long *);
+int	 cgetset(const char *);
+int	 cgetstr(char *, const char *, char **);
+int	 cgetustr(char *, const char *, char **);
+
+int	 daemon(int, int);
+char	*devname(__dev_t, __mode_t);
+char 	*devname_r(__dev_t, __mode_t, char *, int);
+char	*fdevname(int);
+char 	*fdevname_r(int, char *, int);
+int	 getloadavg(double [], int);
+const char *
+	 getprogname(void);
+
+int	 heapsort(void *, size_t, size_t, int (*)(const void *, const void *));
+#ifdef __BLOCKS__
+int	 heapsort_b(void *, size_t, size_t, int (^)(const void *, const void *));
+void	 qsort_b(void *, size_t, size_t,
+	    int (^)(const void *, const void *));
+#endif
+int	 l64a_r(long, char *, int);
+int	 mergesort(void *, size_t, size_t, int (*)(const void *, const void *));
+#ifdef __BLOCKS__
+int	 mergesort_b(void *, size_t, size_t, int (^)(const void *, const void *));
+#endif
+int	 mkostemp(char *, int);
+int	 mkostemps(char *, int, int);
+void	 qsort_r(void *, size_t, size_t, void *,
+	    int (*)(void *, const void *, const void *));
+int	 radixsort(const unsigned char **, int, const unsigned char *,
+	    unsigned);
+void    *reallocf(void *, size_t);
+int	 rpmatch(const char *);
+void	 setprogname(const char *);
+int	 sradixsort(const unsigned char **, int, const unsigned char *,
+	    unsigned);
+void	 sranddev(void);
+void	 srandomdev(void);
+long long
+	strtonum(const char *, long long, long long, const char **);
+
+/* Deprecated interfaces, to be removed in FreeBSD 6.0. */
+__int64_t
+	 strtoq(const char *, char **, int);
+__uint64_t
+	 strtouq(const char *, char **, int);
+
+extern char *suboptarg;			/* getsubopt(3) external variable */
+#endif /* __BSD_VISIBLE */
+__END_DECLS
+
+#endif /* !_STDLIB_H_ */
diff --git a/include/stdlib/string.h b/include/stdlib/string.h
index 00a5dcd..61e8102 100644
--- a/include/stdlib/string.h
+++ b/include/stdlib/string.h
@@ -59,6 +59,7 @@
 int	 strcmp(const char *, const char *) __pure;
 size_t	 strlen(const char *) __pure;
 int	 strncmp(const char *, const char *, size_t) __pure;
+int	 strcasecmp(const char *, const char *);
 
 __END_DECLS
 
diff --git a/include/stdlib/strings.h b/include/stdlib/strings.h
new file mode 100644
index 0000000..2210df0
--- /dev/null
+++ b/include/stdlib/strings.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _STRINGS_H_
+#define	_STRINGS_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#ifndef _SIZE_T_DECLARED
+typedef	__size_t	size_t;
+#define	_SIZE_T_DECLARED
+#endif
+
+__BEGIN_DECLS
+#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112
+int	 bcmp(const void *, const void *, size_t) __pure;	/* LEGACY */
+void	 bcopy(const void *, void *, size_t);			/* LEGACY */
+void	 bzero(void *, size_t);					/* LEGACY */
+#endif
+#if __BSD_VISIBLE
+void	 explicit_bzero(void *, size_t);
+#endif
+#if __XSI_VISIBLE
+int	 ffs(int) __pure2;
+#endif
+#if __BSD_VISIBLE
+int	 ffsl(long) __pure2;
+int	 ffsll(long long) __pure2;
+int	 fls(int) __pure2;
+int	 flsl(long) __pure2;
+int	 flsll(long long) __pure2;
+#endif
+#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112
+char	*index(const char *, int) __pure;			/* LEGACY */
+char	*rindex(const char *, int) __pure;			/* LEGACY */
+#endif
+int	 strcasecmp(const char *, const char *) __pure;
+int	 strncasecmp(const char *, const char *, size_t) __pure;
+
+#if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_)
+#include <xlocale/_strings.h>
+#endif
+__END_DECLS
+
+#endif /* _STRINGS_H_ */
diff --git a/include/stdlib/sys/_timespec.h b/include/stdlib/sys/_timespec.h
new file mode 100644
index 0000000..d51559c
--- /dev/null
+++ b/include/stdlib/sys/_timespec.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)time.h	8.5 (Berkeley) 5/4/95
+ * from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp
+ *	$FreeBSD$
+ */
+
+#ifndef _SYS__TIMESPEC_H_
+#define	_SYS__TIMESPEC_H_
+
+#include <sys/_types.h>
+
+#ifndef _TIME_T_DECLARED
+typedef	__time_t	time_t;
+#define	_TIME_T_DECLARED
+#endif
+
+struct timespec {
+	time_t	tv_sec;		/* seconds */
+	long	tv_nsec;	/* and nanoseconds */
+};
+
+#endif /* !_SYS__TIMESPEC_H_ */
diff --git a/include/stdlib/sys/timespec.h b/include/stdlib/sys/timespec.h
new file mode 100644
index 0000000..2505cef
--- /dev/null
+++ b/include/stdlib/sys/timespec.h
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)time.h	8.5 (Berkeley) 5/4/95
+ * from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp
+ *	$FreeBSD$
+ */
+
+#ifndef _SYS_TIMESPEC_H_
+#define _SYS_TIMESPEC_H_
+
+#include <sys/cdefs.h>
+#include <sys/_timespec.h>
+
+#if __BSD_VISIBLE
+#define	TIMEVAL_TO_TIMESPEC(tv, ts)					\
+	do {								\
+		(ts)->tv_sec = (tv)->tv_sec;				\
+		(ts)->tv_nsec = (tv)->tv_usec * 1000;			\
+	} while (0)
+#define	TIMESPEC_TO_TIMEVAL(tv, ts)					\
+	do {								\
+		(tv)->tv_sec = (ts)->tv_sec;				\
+		(tv)->tv_usec = (ts)->tv_nsec / 1000;			\
+	} while (0)
+
+#endif /* __BSD_VISIBLE */
+
+/*
+ * Structure defined by POSIX.1b to be like a itimerval, but with
+ * timespecs. Used in the timer_*() system calls.
+ */
+struct itimerspec {
+	struct timespec  it_interval;
+	struct timespec  it_value;
+};
+
+#endif /* _SYS_TIMESPEC_H_ */
diff --git a/include/stdlib/sys/types.h b/include/stdlib/sys/types.h
new file mode 100644
index 0000000..ae2ea33
--- /dev/null
+++ b/include/stdlib/sys/types.h
@@ -0,0 +1,245 @@
+/*-
+ * Copyright (c) 1982, 1986, 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)types.h	8.6 (Berkeley) 2/19/95
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_TYPES_H_
+#define	_SYS_TYPES_H_
+
+#include <sys/cdefs.h>
+
+/* Machine type dependent parameters. */
+#include <sys/_types.h>
+
+#if __BSD_VISIBLE
+typedef	unsigned char	u_char;
+typedef	unsigned short	u_short;
+typedef	unsigned int	u_int;
+typedef	unsigned long	u_long;
+#ifndef _KERNEL
+typedef	unsigned short	ushort;		/* Sys V compatibility */
+typedef	unsigned int	uint;		/* Sys V compatibility */
+#endif
+#endif
+
+/*
+ * XXX POSIX sized integrals that should appear only in <sys/stdint.h>.
+ */
+#include <sys/_stdint.h>
+
+typedef __uint8_t	u_int8_t;	/* unsigned integrals (deprecated) */
+typedef __uint16_t	u_int16_t;
+typedef __uint32_t	u_int32_t;
+typedef __uint64_t	u_int64_t;
+
+typedef	__uint64_t	u_quad_t;	/* quads (deprecated) */
+typedef	__int64_t	quad_t;
+typedef	quad_t		*qaddr_t;
+
+typedef	char		*caddr_t;	/* core address */
+typedef	const char	*c_caddr_t;	/* core address, pointer to const */
+
+#ifndef _BLKSIZE_T_DECLARED
+typedef	__blksize_t	blksize_t;
+#define	_BLKSIZE_T_DECLARED
+#endif
+
+typedef	__cpuwhich_t	cpuwhich_t;
+typedef	__cpulevel_t	cpulevel_t;
+typedef	__cpusetid_t	cpusetid_t;
+
+#ifndef _BLKCNT_T_DECLARED
+typedef	__blkcnt_t	blkcnt_t;
+#define	_BLKCNT_T_DECLARED
+#endif
+
+#ifndef _CLOCK_T_DECLARED
+typedef	__clock_t	clock_t;
+#define	_CLOCK_T_DECLARED
+#endif
+
+#ifndef _CLOCKID_T_DECLARED
+typedef	__clockid_t	clockid_t;
+#define	_CLOCKID_T_DECLARED
+#endif
+
+typedef	__critical_t	critical_t;	/* Critical section value */
+typedef	__int64_t	daddr_t;	/* disk address */
+
+#ifndef _DEV_T_DECLARED
+typedef	__dev_t		dev_t;		/* device number or struct cdev */
+#define	_DEV_T_DECLARED
+#endif
+
+#ifndef _FFLAGS_T_DECLARED
+typedef	__fflags_t	fflags_t;	/* file flags */
+#define	_FFLAGS_T_DECLARED
+#endif
+
+typedef	__fixpt_t	fixpt_t;	/* fixed point number */
+
+#ifndef _FSBLKCNT_T_DECLARED		/* for statvfs() */
+typedef	__fsblkcnt_t	fsblkcnt_t;
+typedef	__fsfilcnt_t	fsfilcnt_t;
+#define	_FSBLKCNT_T_DECLARED
+#endif
+
+#ifndef _GID_T_DECLARED
+typedef	__gid_t		gid_t;		/* group id */
+#define	_GID_T_DECLARED
+#endif
+
+#ifndef _IN_ADDR_T_DECLARED
+typedef	__uint32_t	in_addr_t;	/* base type for internet address */
+#define	_IN_ADDR_T_DECLARED
+#endif
+
+#ifndef _IN_PORT_T_DECLARED
+typedef	__uint16_t	in_port_t;
+#define	_IN_PORT_T_DECLARED
+#endif
+
+#ifndef _ID_T_DECLARED
+typedef	__id_t		id_t;		/* can hold a uid_t or pid_t */
+#define	_ID_T_DECLARED
+#endif
+
+#ifndef _INO_T_DECLARED
+typedef	__ino_t		ino_t;		/* inode number */
+#define	_INO_T_DECLARED
+#endif
+
+#ifndef _KEY_T_DECLARED
+typedef	__key_t		key_t;		/* IPC key (for Sys V IPC) */
+#define	_KEY_T_DECLARED
+#endif
+
+#ifndef _LWPID_T_DECLARED
+typedef	__lwpid_t	lwpid_t;	/* Thread ID (a.k.a. LWP) */
+#define	_LWPID_T_DECLARED
+#endif
+
+#ifndef _MODE_T_DECLARED
+typedef	__mode_t	mode_t;		/* permissions */
+#define	_MODE_T_DECLARED
+#endif
+
+#ifndef _ACCMODE_T_DECLARED
+typedef	__accmode_t	accmode_t;	/* access permissions */
+#define	_ACCMODE_T_DECLARED
+#endif
+
+#ifndef _NLINK_T_DECLARED
+typedef	__nlink_t	nlink_t;	/* link count */
+#define	_NLINK_T_DECLARED
+#endif
+
+#ifndef _OFF_T_DECLARED
+typedef	__off_t		off_t;		/* file offset */
+#define	_OFF_T_DECLARED
+#endif
+
+#ifndef _PID_T_DECLARED
+typedef	__pid_t		pid_t;		/* process id */
+#define	_PID_T_DECLARED
+#endif
+
+typedef	__register_t	register_t;
+
+#ifndef _RLIM_T_DECLARED
+typedef	__rlim_t	rlim_t;		/* resource limit */
+#define	_RLIM_T_DECLARED
+#endif
+
+typedef	__int64_t	sbintime_t;
+
+typedef	__segsz_t	segsz_t;	/* segment size (in pages) */
+
+#ifndef _SIZE_T_DECLARED
+typedef	__size_t	size_t;
+#define	_SIZE_T_DECLARED
+#endif
+
+#ifndef _SSIZE_T_DECLARED
+typedef	__ssize_t	ssize_t;
+#define	_SSIZE_T_DECLARED
+#endif
+
+#ifndef _SUSECONDS_T_DECLARED
+typedef	__suseconds_t	suseconds_t;	/* microseconds (signed) */
+#define	_SUSECONDS_T_DECLARED
+#endif
+
+#ifndef _TIME_T_DECLARED
+typedef	__time_t	time_t;
+#define	_TIME_T_DECLARED
+#endif
+
+#ifndef _TIMER_T_DECLARED
+typedef	__timer_t	timer_t;
+#define	_TIMER_T_DECLARED
+#endif
+
+#ifndef _MQD_T_DECLARED
+typedef	__mqd_t	mqd_t;
+#define	_MQD_T_DECLARED
+#endif
+
+typedef	__u_register_t	u_register_t;
+
+#ifndef _UID_T_DECLARED
+typedef	__uid_t		uid_t;		/* user id */
+#define	_UID_T_DECLARED
+#endif
+
+#ifndef _USECONDS_T_DECLARED
+typedef	__useconds_t	useconds_t;	/* microseconds (unsigned) */
+#define	_USECONDS_T_DECLARED
+#endif
+
+#ifndef _CAP_RIGHTS_T_DECLARED
+#define	_CAP_RIGHTS_T_DECLARED
+struct cap_rights;
+
+typedef	struct cap_rights	cap_rights_t;
+#endif
+
+typedef	__vm_offset_t	vm_offset_t;
+typedef	__vm_ooffset_t	vm_ooffset_t;
+typedef	__vm_paddr_t	vm_paddr_t;
+typedef	__vm_pindex_t	vm_pindex_t;
+typedef	__vm_size_t	vm_size_t;
+
+#endif /* !_SYS_TYPES_H_ */
diff --git a/include/stdlib/time.h b/include/stdlib/time.h
new file mode 100644
index 0000000..08200cf
--- /dev/null
+++ b/include/stdlib/time.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)time.h	8.3 (Berkeley) 1/21/94
+ */
+
+/*
+ * $FreeBSD$
+ */
+
+#ifndef _TIME_H_
+#define	_TIME_H_
+
+#include <sys/cdefs.h>
+#include <sys/_null.h>
+#include <sys/_types.h>
+
+#if __POSIX_VISIBLE > 0 && __POSIX_VISIBLE < 200112 || __BSD_VISIBLE
+/*
+ * Frequency of the clock ticks reported by times().  Deprecated - use
+ * sysconf(_SC_CLK_TCK) instead.  (Removed in 1003.1-2001.)
+ */
+#define	CLK_TCK		128
+#endif
+
+/* Frequency of the clock ticks reported by clock().  */
+#define	CLOCKS_PER_SEC	128
+
+#ifndef _CLOCK_T_DECLARED
+typedef	__clock_t	clock_t;
+#define	_CLOCK_T_DECLARED
+#endif
+
+#ifndef _TIME_T_DECLARED
+typedef	__time_t	time_t;
+#define	_TIME_T_DECLARED
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef	__size_t	size_t;
+#define	_SIZE_T_DECLARED
+#endif
+
+#if __POSIX_VISIBLE >= 199309
+/*
+ * New in POSIX 1003.1b-1993.
+ */
+#ifndef _CLOCKID_T_DECLARED
+typedef	__clockid_t	clockid_t;
+#define	_CLOCKID_T_DECLARED
+#endif
+
+#ifndef _TIMER_T_DECLARED
+typedef	__timer_t	timer_t;
+#define	_TIMER_T_DECLARED
+#endif
+
+#include <sys/timespec.h>
+#endif /* __POSIX_VISIBLE >= 199309 */
+
+#if __POSIX_VISIBLE >= 200112
+#ifndef _PID_T_DECLARED
+typedef	__pid_t		pid_t;
+#define	_PID_T_DECLARED
+#endif
+#endif
+
+/* These macros are also in sys/time.h. */
+#if !defined(CLOCK_REALTIME) && __POSIX_VISIBLE >= 200112
+#define CLOCK_REALTIME	0
+#ifdef __BSD_VISIBLE
+#define CLOCK_VIRTUAL	1
+#define CLOCK_PROF	2
+#endif
+#define CLOCK_MONOTONIC	4
+#define CLOCK_UPTIME	5		/* FreeBSD-specific. */
+#define CLOCK_UPTIME_PRECISE	7	/* FreeBSD-specific. */
+#define CLOCK_UPTIME_FAST	8	/* FreeBSD-specific. */
+#define CLOCK_REALTIME_PRECISE	9	/* FreeBSD-specific. */
+#define CLOCK_REALTIME_FAST	10	/* FreeBSD-specific. */
+#define CLOCK_MONOTONIC_PRECISE	11	/* FreeBSD-specific. */
+#define CLOCK_MONOTONIC_FAST	12	/* FreeBSD-specific. */
+#define CLOCK_SECOND	13		/* FreeBSD-specific. */
+#define CLOCK_THREAD_CPUTIME_ID	14
+#define	CLOCK_PROCESS_CPUTIME_ID	15
+#endif /* !defined(CLOCK_REALTIME) && __POSIX_VISIBLE >= 200112 */
+
+#if !defined(TIMER_ABSTIME) && __POSIX_VISIBLE >= 200112
+#if __BSD_VISIBLE
+#define TIMER_RELTIME	0x0	/* relative timer */
+#endif
+#define TIMER_ABSTIME	0x1	/* absolute timer */
+#endif /* !defined(TIMER_ABSTIME) && __POSIX_VISIBLE >= 200112 */
+
+struct tm {
+	int	tm_sec;		/* seconds after the minute [0-60] */
+	int	tm_min;		/* minutes after the hour [0-59] */
+	int	tm_hour;	/* hours since midnight [0-23] */
+	int	tm_mday;	/* day of the month [1-31] */
+	int	tm_mon;		/* months since January [0-11] */
+	int	tm_year;	/* years since 1900 */
+	int	tm_wday;	/* days since Sunday [0-6] */
+	int	tm_yday;	/* days since January 1 [0-365] */
+	int	tm_isdst;	/* Daylight Savings Time flag */
+	long	tm_gmtoff;	/* offset from UTC in seconds */
+	char	*tm_zone;	/* timezone abbreviation */
+};
+
+#if __POSIX_VISIBLE
+extern char *tzname[];
+#endif
+
+__BEGIN_DECLS
+char *asctime(const struct tm *);
+clock_t clock(void);
+char *ctime(const time_t *);
+double difftime(time_t, time_t);
+/* XXX missing: getdate() */
+struct tm *gmtime(const time_t *);
+struct tm *localtime(const time_t *);
+time_t mktime(struct tm *);
+size_t strftime(char *__restrict, size_t, const char *__restrict,
+    const struct tm *__restrict);
+time_t time(time_t *);
+#if __POSIX_VISIBLE >= 200112
+struct sigevent;
+int timer_create(clockid_t, struct sigevent *__restrict, timer_t *__restrict);
+int timer_delete(timer_t);
+int timer_gettime(timer_t, struct itimerspec *);
+int timer_getoverrun(timer_t);
+int timer_settime(timer_t, int, const struct itimerspec *__restrict,
+	struct itimerspec *__restrict);
+#endif
+#if __POSIX_VISIBLE
+void tzset(void);
+#endif
+
+#if __POSIX_VISIBLE >= 199309
+int clock_getres(clockid_t, struct timespec *);
+int clock_gettime(clockid_t, struct timespec *);
+int clock_settime(clockid_t, const struct timespec *);
+/* XXX missing: clock_nanosleep() */
+int nanosleep(const struct timespec *, struct timespec *);
+#endif /* __POSIX_VISIBLE >= 199309 */
+
+#if __POSIX_VISIBLE >= 200112
+int clock_getcpuclockid(pid_t, clockid_t *);
+#endif
+
+#if __POSIX_VISIBLE >= 199506
+char *asctime_r(const struct tm *, char *);
+char *ctime_r(const time_t *, char *);
+struct tm *gmtime_r(const time_t *, struct tm *);
+struct tm *localtime_r(const time_t *, struct tm *);
+#endif
+
+#if __XSI_VISIBLE
+char *strptime(const char *__restrict, const char *__restrict,
+    struct tm *__restrict);
+#endif
+
+#if __BSD_VISIBLE
+char *timezone(int, int);	/* XXX XSI conflict */
+void tzsetwall(void);
+time_t timelocal(struct tm * const);
+time_t timegm(struct tm * const);
+#endif /* __BSD_VISIBLE */
+
+#if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_)
+#include <xlocale/_time.h>
+#endif
+__END_DECLS
+
+#endif /* !_TIME_H_ */
diff --git a/include/stdlib/xlocale/_strings.h b/include/stdlib/xlocale/_strings.h
new file mode 100644
index 0000000..da1cff3
--- /dev/null
+++ b/include/stdlib/xlocale/_strings.h
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2011, 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct	_xlocale *locale_t;
+#endif
+
+/*
+ * This file is included from both strings.h and xlocale.h.  We need to expose
+ * the declarations unconditionally if we are included from xlocale.h, but only
+ * if we are in POSIX2008 mode if included from string.h.
+ */
+
+#ifndef _XLOCALE_STRINGS1_H
+#define _XLOCALE_STRINGS1_H
+
+/*
+ * POSIX2008 functions
+ */
+int	 strcasecmp_l(const char *, const char *, locale_t);
+int	 strncasecmp_l(const char *, const char *, size_t, locale_t);
+#endif /* _XLOCALE_STRINGS1_H */
diff --git a/include/stdlib/xlocale/_time.h b/include/stdlib/xlocale/_time.h
new file mode 100644
index 0000000..6da49a4
--- /dev/null
+++ b/include/stdlib/xlocale/_time.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2011, 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by David Chisnall under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LOCALE_T_DEFINED
+#define _LOCALE_T_DEFINED
+typedef struct	_xlocale *locale_t;
+#endif
+
+/*
+ * This file is included from both locale.h and xlocale.h.  We need to expose
+ * the declarations unconditionally if we are included from xlocale.h, but only
+ * if we are in POSIX2008 mode if included from locale.h.
+ */
+#ifndef _XLOCALE_LOCALE1_H
+#define _XLOCALE_LOCALE1_H
+
+size_t	 strftime_l(char *__restrict, size_t, const char *__restrict,
+	    const struct tm *__restrict, locale_t) __strftimelike(3, 0);
+
+#endif /* _XLOCALE_LOCALE1_H */
+
+#ifdef _XLOCALE_H_
+#ifndef _XLOCALE_LOCALE2_H
+#define _XLOCALE_LOCALE2_H
+
+char	*strptime_l(const char *__restrict, const char *__restrict,
+		struct tm *__restrict, locale_t);
+
+#endif /* _XLOCALE_LOCALE2_H */
+#endif /* _XLOCALE_H_ */
diff --git a/lib/stdlib/exit.c b/lib/stdlib/exit.c
new file mode 100644
index 0000000..3e77591
--- /dev/null
+++ b/lib/stdlib/exit.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug.h>
+
+void exit(int v)
+{
+	ERROR("EXIT\n");
+	panic();
+}
diff --git a/lib/stdlib/sscanf.c b/lib/stdlib/sscanf.c
new file mode 100644
index 0000000..e9f5c4a
--- /dev/null
+++ b/lib/stdlib/sscanf.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+/*
+ * TODO: This is not a real implementation of the sscanf() function. It just
+ * returns the number of expected arguments based on the number of '%' found
+ * in the format string.
+ */
+int
+sscanf(const char *__restrict str, char const *__restrict fmt, ...)
+{
+	int ret = 0;
+
+	while (*fmt != '\0') {
+		if (*fmt++ == '%') {
+			ret++;
+		}
+	}
+
+	return ret;
+}
diff --git a/lib/stdlib/std.c b/lib/stdlib/std.c
index 4608754..5f6ef75 100644
--- a/lib/stdlib/std.c
+++ b/lib/stdlib/std.c
@@ -32,10 +32,12 @@
 /* Include the various implemented functions */
 #include "abort.c"
 #include "assert.c"
+#include "exit.c"
 #include "mem.c"
 #include "printf.c"
 #include "putchar.c"
 #include "puts.c"
+#include "sscanf.c"
 #include "strchr.c"
 #include "strcmp.c"
 #include "strlen.c"
diff --git a/lib/stdlib/strcmp.c b/lib/stdlib/strcmp.c
index 1d26f2b..bb86e0f 100644
--- a/lib/stdlib/strcmp.c
+++ b/lib/stdlib/strcmp.c
@@ -36,6 +36,7 @@
  */
 
 #include <sys/cdefs.h>
+#include <sys/ctype.h>
 #include <string.h>
 
 /*
@@ -49,3 +50,17 @@
 			return 0;
 	return *(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1);
 }
+
+int
+strcasecmp(const char *s1, const char *s2)
+{
+	const unsigned char *us1 = (const unsigned char *)s1;
+	const unsigned char *us2 = (const unsigned char *)s2;
+
+	while (tolower(*us1) == tolower(*us2)) {
+		if (*us1++ == '\0')
+			return 0;
+		us2++;
+	}
+	return tolower(*us1) - tolower(*us2);
+}
diff --git a/plat/fvp/bl2_fvp_setup.c b/plat/fvp/bl2_fvp_setup.c
index 5764b6a..364833f 100644
--- a/plat/fvp/bl2_fvp_setup.c
+++ b/plat/fvp/bl2_fvp_setup.c
@@ -175,6 +175,9 @@
 
 	/* Initialize the platform config for future decision making */
 	fvp_config_setup();
+
+	/* Initialise the IO layer and register platform IO devices */
+	fvp_io_setup();
 }
 
 /*******************************************************************************
@@ -190,9 +193,6 @@
 	 * present.
 	 */
 	fvp_security_setup();
-
-	/* Initialise the IO layer and register platform IO devices */
-	fvp_io_setup();
 }
 
 /* Flush the TF params and the TF plat params */
diff --git a/plat/fvp/fvp_io_storage.c b/plat/fvp/fvp_io_storage.c
index b4a04f1..ec1fe58 100644
--- a/plat/fvp/fvp_io_storage.c
+++ b/plat/fvp/fvp_io_storage.c
@@ -77,6 +77,58 @@
 	.mode = FOPEN_MODE_RB
 };
 
+#if TRUSTED_BOARD_BOOT
+static const io_file_spec_t bl2_cert_file_spec = {
+	.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);
 static int open_memmap(const uintptr_t spec);
 
@@ -114,6 +166,58 @@
 		(uintptr_t)&bl33_file_spec,
 		open_fip
 	}, {
+#if TRUSTED_BOARD_BOOT
+		BL2_CERT_NAME,
+		&fip_dev_handle,
+		(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/fvp_trusted_boot.c b/plat/fvp/fvp_trusted_boot.c
new file mode 100644
index 0000000..e7dcc01
--- /dev/null
+++ b/plat/fvp/fvp_trusted_boot.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include "fvp_def.h"
+#include "fvp_private.h"
+
+/*
+ * Check the validity of the key
+ *
+ * 0 = success, Otherwise = error
+ */
+int plat_match_rotpk(const unsigned char *key_buf, unsigned int key_len)
+{
+	/* TODO: check against the ROT key stored in the platform */
+	return 0;
+}
diff --git a/plat/fvp/include/platform_def.h b/plat/fvp/include/platform_def.h
index b0460e0..326ba9d 100644
--- a/plat/fvp/include/platform_def.h
+++ b/plat/fvp/include/platform_def.h
@@ -49,9 +49,17 @@
 #if DEBUG_XLAT_TABLE
 #define PLATFORM_STACK_SIZE 0x800
 #elif IMAGE_BL1
+#if TRUSTED_BOARD_BOOT
+#define PLATFORM_STACK_SIZE 0x1000
+#else
 #define PLATFORM_STACK_SIZE 0x440
+#endif
 #elif IMAGE_BL2
+#if TRUSTED_BOARD_BOOT
+#define PLATFORM_STACK_SIZE 0x1000
+#else
 #define PLATFORM_STACK_SIZE 0x400
+#endif
 #elif IMAGE_BL31
 #define PLATFORM_STACK_SIZE 0x400
 #elif IMAGE_BL32
@@ -72,6 +80,22 @@
 /* Non-Trusted Firmware BL33 */
 #define BL33_IMAGE_NAME			"bl33.bin" /* e.g. UEFI */
 
+#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
 #define PLATFORM_CLUSTER_COUNT		2ull
 #define PLATFORM_CLUSTER0_CORE_COUNT	4
@@ -96,8 +120,13 @@
  * Put BL1 RW at the top of the Trusted SRAM. BL1_RW_BASE is calculated using
  * the current BL1 RW debug size plus a little space for growth.
  */
+#if TRUSTED_BOARD_BOOT
+#define BL1_RW_BASE			(FVP_TRUSTED_SRAM_BASE \
+					+ FVP_TRUSTED_SRAM_SIZE - 0x8000)
+#else
 #define BL1_RW_BASE			(FVP_TRUSTED_SRAM_BASE \
 					+ FVP_TRUSTED_SRAM_SIZE - 0x6000)
+#endif
 #define BL1_RW_LIMIT			(FVP_TRUSTED_SRAM_BASE \
 					+ FVP_TRUSTED_SRAM_SIZE)
 
@@ -108,7 +137,11 @@
  * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
  * size plus a little space for growth.
  */
+#if TRUSTED_BOARD_BOOT
+#define BL2_BASE			(BL31_BASE - 0x1C000)
+#else
 #define BL2_BASE			(BL31_BASE - 0xC000)
+#endif
 #define BL2_LIMIT			BL31_BASE
 
 /*******************************************************************************
diff --git a/plat/fvp/include/platform_oid.h b/plat/fvp/include/platform_oid.h
new file mode 100644
index 0000000..38aca12
--- /dev/null
+++ b/plat/fvp/include/platform_oid.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PLATFORM_OID_H_
+#define PLATFORM_OID_H_
+
+/*
+ * This is the list of the different extensions containing relevant information
+ * to establish the chain of trust.
+ *
+ * The OIDs shown here are just an example. Real OIDs should be obtained from
+ * the ITU-T.
+ */
+
+/* Non-volatile counter extensions */
+#define TZ_FW_NVCOUNTER_OID		"1.2.3.1"
+#define NTZ_FW_NVCOUNTER_OID		"1.2.3.2"
+
+/* BL2 extensions */
+#define BL2_HASH_OID			"1.2.3.3"
+
+/* Trusted Key extensions */
+#define TZ_WORLD_PK_OID			"1.2.3.4"
+#define NTZ_WORLD_PK_OID		"1.2.3.5"
+
+/* BL3-1 extensions */
+#define BL31_CONTENT_CERT_PK_OID	"1.2.3.6"
+#define BL31_HASH_OID			"1.2.3.7"
+
+/* BL3-0 extensions */
+#define BL30_CONTENT_CERT_PK_OID	"1.2.3.8"
+#define BL30_HASH_OID			"1.2.3.9"
+
+/* BL3-2 extensions */
+#define BL32_CONTENT_CERT_PK_OID	"1.2.3.10"
+#define BL32_HASH_OID			"1.2.3.11"
+
+/* BL3-3 extensions */
+#define BL33_CONTENT_CERT_PK_OID	"1.2.3.12"
+#define BL33_HASH_OID			"1.2.3.13"
+
+#endif /* PLATFORM_OID_H_ */
diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk
index 892e43c..bcee328 100644
--- a/plat/fvp/platform.mk
+++ b/plat/fvp/platform.mk
@@ -89,3 +89,8 @@
 				plat/fvp/aarch64/fvp_helpers.S			\
 				plat/fvp/aarch64/fvp_common.c			\
 				plat/fvp/drivers/pwrc/fvp_pwrc.c
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+  BL1_SOURCES		+=	plat/fvp/fvp_trusted_boot.c
+  BL2_SOURCES		+=	plat/fvp/fvp_trusted_boot.c
+endif
diff --git a/plat/juno/include/platform_def.h b/plat/juno/include/platform_def.h
index cd07702..1071d12 100644
--- a/plat/juno/include/platform_def.h
+++ b/plat/juno/include/platform_def.h
@@ -45,7 +45,11 @@
  ******************************************************************************/
 
 /* Size of cacheable stacks */
-#define PLATFORM_STACK_SIZE    0x800
+#if TRUSTED_BOARD_BOOT && (IMAGE_BL1 || IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x1000
+#else
+#define PLATFORM_STACK_SIZE 0x800
+#endif
 
 #define FIRMWARE_WELCOME_STR		"Booting Trusted Firmware\n"
 
@@ -67,6 +71,22 @@
 /* Firmware Image Package */
 #define FIP_IMAGE_NAME			"fip.bin"
 
+#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
 #define PLATFORM_CLUSTER_COUNT		2
 #define PLATFORM_CORE_COUNT             6
@@ -87,7 +107,11 @@
  * Put BL1 RW at the top of the Trusted SRAM. BL1_RW_BASE is calculated using
  * the current BL1 RW debug size plus a little space for growth.
  */
+#if TRUSTED_BOARD_BOOT
+#define BL1_RW_BASE			(TZRAM_BASE + TZRAM_SIZE - 0x8000)
+#else
 #define BL1_RW_BASE			(TZRAM_BASE + TZRAM_SIZE - 0x6000)
+#endif
 #define BL1_RW_LIMIT			(TZRAM_BASE + TZRAM_SIZE)
 
 /*******************************************************************************
@@ -97,7 +121,11 @@
  * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
  * size plus a little space for growth.
  */
+#if TRUSTED_BOARD_BOOT
+#define BL2_BASE			(BL31_BASE - 0x1D000)
+#else
 #define BL2_BASE			(BL31_BASE - 0xC000)
+#endif
 #define BL2_LIMIT			BL31_BASE
 
 /*******************************************************************************
diff --git a/plat/juno/include/platform_oid.h b/plat/juno/include/platform_oid.h
new file mode 100644
index 0000000..38aca12
--- /dev/null
+++ b/plat/juno/include/platform_oid.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PLATFORM_OID_H_
+#define PLATFORM_OID_H_
+
+/*
+ * This is the list of the different extensions containing relevant information
+ * to establish the chain of trust.
+ *
+ * The OIDs shown here are just an example. Real OIDs should be obtained from
+ * the ITU-T.
+ */
+
+/* Non-volatile counter extensions */
+#define TZ_FW_NVCOUNTER_OID		"1.2.3.1"
+#define NTZ_FW_NVCOUNTER_OID		"1.2.3.2"
+
+/* BL2 extensions */
+#define BL2_HASH_OID			"1.2.3.3"
+
+/* Trusted Key extensions */
+#define TZ_WORLD_PK_OID			"1.2.3.4"
+#define NTZ_WORLD_PK_OID		"1.2.3.5"
+
+/* BL3-1 extensions */
+#define BL31_CONTENT_CERT_PK_OID	"1.2.3.6"
+#define BL31_HASH_OID			"1.2.3.7"
+
+/* BL3-0 extensions */
+#define BL30_CONTENT_CERT_PK_OID	"1.2.3.8"
+#define BL30_HASH_OID			"1.2.3.9"
+
+/* BL3-2 extensions */
+#define BL32_CONTENT_CERT_PK_OID	"1.2.3.10"
+#define BL32_HASH_OID			"1.2.3.11"
+
+/* BL3-3 extensions */
+#define BL33_CONTENT_CERT_PK_OID	"1.2.3.12"
+#define BL33_HASH_OID			"1.2.3.13"
+
+#endif /* PLATFORM_OID_H_ */
diff --git a/plat/juno/juno_def.h b/plat/juno/juno_def.h
index 8e1a83d..8a85aec 100644
--- a/plat/juno/juno_def.h
+++ b/plat/juno/juno_def.h
@@ -47,7 +47,13 @@
 /* Use the bypass address */
 #define TZROM_BASE		FLASH_BASE + BL1_ROM_BYPASS_OFFSET
 #endif
+/* Actual ROM size on Juno is 64 KB, but TBB requires at least 80 KB in debug
+ * mode. We can test TBB on Juno bypassing the ROM and using 128 KB of flash */
+#if TRUSTED_BOARD_BOOT
+#define TZROM_SIZE		0x00020000
+#else
 #define TZROM_SIZE		0x00010000
+#endif
 
 #define TZRAM_BASE		0x04001000
 #define TZRAM_SIZE		0x0003F000
diff --git a/plat/juno/juno_trusted_boot.c b/plat/juno/juno_trusted_boot.c
new file mode 100644
index 0000000..e63d4b2
--- /dev/null
+++ b/plat/juno/juno_trusted_boot.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include "juno_def.h"
+#include "juno_private.h"
+
+/*
+ * Check the validity of the key
+ *
+ * 0 = success, Otherwise = error
+ */
+int plat_match_rotpk(const unsigned char *key_buf, unsigned int key_len)
+{
+	/* TODO: check against the ROT key stored in the platform */
+	return 0;
+}
diff --git a/plat/juno/plat_io_storage.c b/plat/juno/plat_io_storage.c
index 83d7e43..b31865e 100644
--- a/plat/juno/plat_io_storage.c
+++ b/plat/juno/plat_io_storage.c
@@ -77,6 +77,58 @@
 	.mode = FOPEN_MODE_RB
 };
 
+#if TRUSTED_BOARD_BOOT
+static const io_file_spec_t bl2_cert_file_spec = {
+	.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);
 static int open_memmap(const uintptr_t spec);
 
@@ -119,6 +171,58 @@
 		(uintptr_t)&bl33_file_spec,
 		open_fip
 	}, {
+#if TRUSTED_BOARD_BOOT
+		BL2_CERT_NAME,
+		&fip_dev_handle,
+		(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/juno/platform.mk b/plat/juno/platform.mk
index 158e3ac..8beaecf 100644
--- a/plat/juno/platform.mk
+++ b/plat/juno/platform.mk
@@ -90,6 +90,11 @@
 				plat/juno/plat_topology.c		\
 				plat/juno/scpi.c
 
+ifneq (${TRUSTED_BOARD_BOOT},0)
+  BL1_SOURCES		+=	plat/juno/juno_trusted_boot.c
+  BL2_SOURCES		+=	plat/juno/juno_trusted_boot.c
+endif
+
 ifneq (${RESET_TO_BL31},0)
   $(error "Using BL3-1 as the reset vector is not supported on Juno. \
   Please set RESET_TO_BL31 to 0.")
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
new file mode 100644
index 0000000..f1aa797
--- /dev/null
+++ b/tools/cert_create/Makefile
@@ -0,0 +1,92 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+PROJECT		:= cert_create
+PLAT		:= none
+V		:= 0
+DEBUG		:= 0
+BINARY		:= ${PROJECT}
+
+OBJECTS := src/cert.o \
+           src/ext.o \
+           src/key.o \
+           src/main.o \
+           src/tbb_cert.o \
+           src/tbb_ext.o \
+           src/tbb_key.o \
+           src/sha.o
+
+CFLAGS := -Wall -std=c99
+
+# Check the platform
+ifeq (${PLAT},none)
+  $(error Error: No platform defined. Use PLAT=<platform>.)
+endif
+
+ifeq (${DEBUG},1)
+  CFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40
+else
+  CFLAGS += -O2 -DLOG_LEVEL=20
+endif
+ifeq (${V},0)
+	Q := @
+else
+	Q :=
+endif
+
+# Make soft links and include from local directory otherwise wrong headers
+# could get pulled in from firmware tree.
+INC_DIR := -I ./include -I ../../plat/${PLAT}/include
+LIB_DIR :=
+LIB := -lssl -lcrypto
+
+CC := gcc
+RM := rm -rf
+
+.PHONY: all clean
+
+all: clean ${BINARY}
+
+${BINARY}: ${OBJECTS} Makefile
+	@echo "  LD      $@"
+	@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \
+                const char platform_msg[] = "${PLAT}";' | \
+                ${CC} -c ${CFLAGS} -xc - -o src/build_msg.o
+	${Q}${CC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
+
+%.o: %.c
+	@echo "  CC      $<"
+	${Q}${CC} -c ${CFLAGS} ${INC_DIR} $< -o $@
+
+clean:
+	${Q}${RM} -f src/build_msg.o ${OBJECTS}
+
+realclean: clean
+	${Q}${RM} -f ${BINARY}
diff --git a/tools/cert_create/include/cert.h b/tools/cert_create/include/cert.h
new file mode 100644
index 0000000..48a4146
--- /dev/null
+++ b/tools/cert_create/include/cert.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CERT_H_
+#define CERT_H_
+
+#include <openssl/ossl_typ.h>
+#include <openssl/x509.h>
+#include "key.h"
+
+/*
+ * This structure contains information related to the generation of the
+ * certificates. All these fields must be known and specified at build time
+ * except for the file name, which is picked up from the command line at
+ * run time.
+ *
+ * One instance of this structure must be created for each of the certificates
+ * present in the chain of trust.
+ *
+ * If the issuer points to this same instance, the generated certificate will
+ * be self-signed.
+ */
+typedef struct cert_s cert_t;
+struct cert_s {
+	int id;			/* Unique identifier */
+
+	const char *fn;		/* Filename to save the certificate */
+	const char *bin;	/* Image associated to this certificate */
+
+	const char *cn;		/* Subject CN (Company Name) */
+
+	X509 *x;		/* X509 certificate container */
+	key_t *key;		/* Key to be signed */
+
+	cert_t *issuer;		/* Issuer certificate */
+};
+
+int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value);
+
+int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk);
+
+#endif /* CERT_H_ */
diff --git a/tools/cert_create/include/debug.h b/tools/cert_create/include/debug.h
new file mode 100644
index 0000000..dd0510a
--- /dev/null
+++ b/tools/cert_create/include/debug.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#include <stdio.h>
+
+/* The log output macros print output to the console. These macros produce
+ * compiled log output only if the LOG_LEVEL defined in the makefile (or the
+ * make command line) is greater or equal than the level required for that
+ * type of log output.
+ * The format expected is the same as for printf(). For example:
+ * INFO("Info %s.\n", "message")    -> INFO:    Info message.
+ * WARN("Warning %s.\n", "message") -> WARNING: Warning message.
+ */
+
+#define LOG_LEVEL_NONE			0
+#define LOG_LEVEL_ERROR			10
+#define LOG_LEVEL_NOTICE		20
+#define LOG_LEVEL_WARNING		30
+#define LOG_LEVEL_INFO			40
+#define LOG_LEVEL_VERBOSE		50
+
+
+#if LOG_LEVEL >= LOG_LEVEL_NOTICE
+# define NOTICE(...)	printf("NOTICE:  " __VA_ARGS__)
+#else
+# define NOTICE(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_ERROR
+# define ERROR(...)	printf("ERROR:   " __VA_ARGS__)
+#else
+# define ERROR(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_WARNING
+# define WARN(...)	printf("WARNING: " __VA_ARGS__)
+#else
+# define WARN(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+# define INFO(...)	printf("INFO:    " __VA_ARGS__)
+#else
+# define INFO(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+# define VERBOSE(...)	printf("VERBOSE: " __VA_ARGS__)
+#else
+# define VERBOSE(...)
+#endif
+
+#endif /* __DEBUG_H__ */
diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h
new file mode 100644
index 0000000..d73f573
--- /dev/null
+++ b/tools/cert_create/include/ext.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EXT_H_
+#define EXT_H_
+
+#include <openssl/x509v3.h>
+
+/*
+ * This structure contains the relevant information to create the extensions
+ * to be included in the certificates. This extensions will be used to
+ * establish the chain of trust.
+ */
+typedef struct ext_s {
+	const char *oid;	/* OID of the extension */
+	const char *sn;		/* Short name */
+	const char *ln;		/* Long description */
+	int type;		/* OpenSSL ASN1 type of the extension data.
+				 * Supported types are:
+				 *   - V_ASN1_INTEGER
+				 *   - V_ASN1_OCTET_STRING
+				 */
+	int alias;		/* In case OpenSSL provides an standard
+				 * extension of the same type, add the new
+				 * extension as an alias of this one
+				 */
+
+	X509V3_EXT_METHOD method; /* This field may be used to define a custom
+				   * function to print the contents of the
+				   * extension */
+} ext_t;
+
+enum {
+	EXT_NON_CRIT = 0,
+	EXT_CRIT = !EXT_NON_CRIT,
+};
+
+int ext_init(ext_t *tbb_ext);
+X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len);
+X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value);
+X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k);
+
+#endif /* EXT_H_ */
diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h
new file mode 100644
index 0000000..8819750
--- /dev/null
+++ b/tools/cert_create/include/key.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KEY_H_
+#define KEY_H_
+
+#include <openssl/ossl_typ.h>
+
+#define RSA_KEY_BITS		2048
+
+/*
+ * This structure contains the relevant information to create the keys
+ * required to sign the certificates.
+ *
+ * One instance of this structure must be created for each key, usually in an
+ * array fashion. The filename is obtained at run time from the command line
+ * parameters
+ */
+typedef struct key_s {
+	int id;			/* Key id */
+	const char *desc;	/* Key description (debug purposes) */
+	char *fn;		/* Filename to load/store the key */
+	EVP_PKEY *key;		/* Key container */
+} key_t;
+
+int key_new(key_t *key);
+int key_load(key_t *key);
+int key_store(key_t *key);
+
+#endif /* KEY_H_ */
diff --git a/tools/cert_create/include/sha.h b/tools/cert_create/include/sha.h
new file mode 100644
index 0000000..466d668
--- /dev/null
+++ b/tools/cert_create/include/sha.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SHA_H_
+#define SHA_H_
+
+int sha_file(const char *filename, unsigned char *md);
+
+#endif /* SHA_H_ */
diff --git a/tools/cert_create/include/tbb_cert.h b/tools/cert_create/include/tbb_cert.h
new file mode 100644
index 0000000..4e48125
--- /dev/null
+++ b/tools/cert_create/include/tbb_cert.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TBB_CERT_H_
+#define TBB_CERT_H_
+
+#include "cert.h"
+
+/*
+ * Enumerate the certificates that are used to establish the chain of trust
+ */
+enum {
+	BL2_CERT,
+	TRUSTED_KEY_CERT,
+	BL30_KEY_CERT,
+	BL30_CERT,
+	BL31_KEY_CERT,
+	BL31_CERT,
+	BL32_KEY_CERT,
+	BL32_CERT,
+	BL33_KEY_CERT,
+	BL33_CERT,
+	NUM_CERTIFICATES,
+};
+
+/*
+ * Array containing the certificate instances
+ */
+extern cert_t certs[NUM_CERTIFICATES];
+
+#endif /* TBB_CERT_H_ */
diff --git a/tools/cert_create/include/tbb_ext.h b/tools/cert_create/include/tbb_ext.h
new file mode 100644
index 0000000..155d3cb
--- /dev/null
+++ b/tools/cert_create/include/tbb_ext.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TBB_EXT_H_
+#define TBB_EXT_H_
+
+#include "ext.h"
+
+/* Array containing the extensions used in the chain of trust */
+extern ext_t tbb_ext[];
+
+#endif /* TBB_EXT_H_ */
diff --git a/tools/cert_create/include/tbb_key.h b/tools/cert_create/include/tbb_key.h
new file mode 100644
index 0000000..cc927d1
--- /dev/null
+++ b/tools/cert_create/include/tbb_key.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TBB_KEY_H_
+#define TBB_KEY_H_
+
+#include "key.h"
+
+/*
+ * Enumerate the keys that are used to establish the chain of trust
+ */
+enum {
+	ROT_KEY,
+	TRUSTED_WORLD_KEY,
+	NON_TRUSTED_WORLD_KEY,
+	BL30_KEY,
+	BL31_KEY,
+	BL32_KEY,
+	BL33_KEY,
+	NUM_KEYS
+};
+
+/*
+ * Array containing the key instances
+ */
+extern key_t keys[];
+
+#endif /* TBB_KEY_H_ */
diff --git a/tools/cert_create/src/cert.c b/tools/cert_create/src/cert.c
new file mode 100644
index 0000000..9705643
--- /dev/null
+++ b/tools/cert_create/src/cert.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/sha.h>
+#include <openssl/x509v3.h>
+
+#include "cert.h"
+#include "debug.h"
+#include "key.h"
+#include "platform_oid.h"
+#include "sha.h"
+
+#define SERIAL_RAND_BITS	64
+
+int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
+{
+	BIGNUM *btmp;
+	int ret = 0;
+	if (b)
+		btmp = b;
+	else
+		btmp = BN_new();
+
+	if (!btmp)
+		return 0;
+
+	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
+		goto error;
+	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
+		goto error;
+
+	ret = 1;
+
+error:
+
+	if (!b)
+		BN_free(btmp);
+
+	return ret;
+}
+
+int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value)
+{
+	X509_EXTENSION *ex;
+	X509V3_CTX ctx;
+
+	/* No configuration database */
+	X509V3_set_ctx_nodb(&ctx);
+
+	/* Set issuer and subject certificates in the context */
+	X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0);
+	ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
+	if (!ex) {
+		ERR_print_errors_fp(stdout);
+		return 0;
+	}
+
+	X509_add_ext(subject, ex, -1);
+	X509_EXTENSION_free(ex);
+
+	return 1;
+}
+
+
+int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
+{
+	EVP_PKEY *pkey = cert->key->key;
+	EVP_PKEY *ikey = cert->issuer->key->key;
+	X509 *issuer = cert->issuer->x;
+	X509 *x = NULL;
+	X509_EXTENSION *ex = NULL;
+	X509_NAME *name = NULL;
+	ASN1_INTEGER *sno = NULL;
+	int i, num;
+
+	/* Create the certificate structure */
+	x = X509_new();
+	if (!x) {
+		return 0;
+	}
+
+	/* If we do not have a key, use the issuer key (the certificate will
+	 * become self signed). This happens in content certificates. */
+	if (!pkey) {
+		pkey = ikey;
+	}
+
+	/* If we do not have an issuer certificate, use our own (the certificate
+	 * will become self signed) */
+	if (!issuer) {
+		issuer = x;
+	}
+
+	/* x509.v3 */
+	X509_set_version(x, 2);
+
+	/* Random serial number */
+	sno = ASN1_INTEGER_new();
+	rand_serial(NULL, sno);
+	X509_set_serialNumber(x, sno);
+	ASN1_INTEGER_free(sno);
+
+	X509_gmtime_adj(X509_get_notBefore(x), 0);
+	X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
+	X509_set_pubkey(x, pkey);
+
+	/* Subject name */
+	name = X509_get_subject_name(x);
+	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
+			(const unsigned char *)cert->cn, -1, -1, 0);
+	X509_set_subject_name(x, name);
+
+	/* Issuer name */
+	name = X509_get_issuer_name(x);
+	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
+			(const unsigned char *)cert->issuer->cn, -1, -1, 0);
+	X509_set_issuer_name(x, name);
+
+	/* Add various extensions: standard extensions */
+	cert_add_ext(issuer, x, NID_subject_key_identifier, "hash");
+	cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always");
+	if (ca) {
+		cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE");
+		cert_add_ext(issuer, x, NID_key_usage, "keyCertSign");
+	} else {
+		cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE");
+	}
+
+	/* Add custom extensions */
+	if (sk != NULL) {
+		num = sk_X509_EXTENSION_num(sk);
+		for (i = 0; i < num; i++) {
+			ex = sk_X509_EXTENSION_value(sk, i);
+			X509_add_ext(x, ex, -1);
+		}
+	}
+
+	/* Sign the certificate with the issuer key */
+	if (!X509_sign(x, ikey, EVP_sha1())) {
+		ERR_print_errors_fp(stdout);
+		return 0;
+	}
+
+	cert->x = x;
+	return 1;
+}
diff --git a/tools/cert_create/src/ext.c b/tools/cert_create/src/ext.c
new file mode 100644
index 0000000..31f84a8
--- /dev/null
+++ b/tools/cert_create/src/ext.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+#include "ext.h"
+
+DECLARE_ASN1_ITEM(ASN1_INTEGER)
+DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
+
+/*
+ * This function adds the TBB extensions to the internal extension list
+ * maintained by OpenSSL so they can be used later.
+ *
+ * It also initializes the methods to print the contents of the extension. If an
+ * alias is specified in the TBB extension, we reuse the methods of the alias.
+ * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are
+ * provided. Any other type will be printed as a raw ascii string.
+ *
+ * Return: 0 = success, Otherwise: error
+ */
+int ext_init(ext_t *tbb_ext)
+{
+	ext_t *ext;
+	X509V3_EXT_METHOD *m;
+	int i = 0, nid, ret;
+
+	while ((ext = &tbb_ext[i++]) && ext->oid) {
+		nid = OBJ_create(ext->oid, ext->sn, ext->ln);
+		if (ext->alias) {
+			X509V3_EXT_add_alias(nid, ext->alias);
+		} else {
+			m = &ext->method;
+			memset(m, 0x0, sizeof(X509V3_EXT_METHOD));
+			switch (ext->type) {
+			case V_ASN1_INTEGER:
+				m->it = ASN1_ITEM_ref(ASN1_INTEGER);
+				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER;
+				m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER;
+				break;
+			case V_ASN1_OCTET_STRING:
+				m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING);
+				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING;
+				m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING;
+				break;
+			default:
+				continue;
+			}
+			m->ext_nid = nid;
+			ret = X509V3_EXT_add(m);
+			if (!ret) {
+				ERR_print_errors_fp(stdout);
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+/*
+ * Create a new extension
+ *
+ * Extension  ::=  SEQUENCE  {
+ *      id          OBJECT IDENTIFIER,
+ *      critical    BOOLEAN DEFAULT FALSE,
+ *      value       OCTET STRING  }
+ *
+ * Parameters:
+ *   pex: OpenSSL extension pointer (output parameter)
+ *   nid: extension identifier
+ *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
+ *   data: extension data. This data will be encapsulated in an Octet String
+ *
+ * Return: Extension address, NULL if error
+ */
+static
+X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len)
+{
+	X509_EXTENSION *ex;
+	ASN1_OCTET_STRING *ext_data;
+
+	/* Octet string containing the extension data */
+	ext_data = ASN1_OCTET_STRING_new();
+	ASN1_OCTET_STRING_set(ext_data, data, len);
+
+	/* Create the extension */
+	ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data);
+
+	/* The extension makes a copy of the data, so we can free this object */
+	ASN1_OCTET_STRING_free(ext_data);
+
+	return ex;
+}
+
+/*
+ * Creates a x509v3 extension containing a hash encapsulated in an ASN1 Octet
+ * String
+ *
+ * Parameters:
+ *   pex: OpenSSL extension pointer (output parameter)
+ *   nid: extension identifier
+ *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
+ *   buf: pointer to the buffer that contains the hash
+ *   len: size of the hash in bytes
+ *
+ * Return: Extension address, NULL if error
+ */
+X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len)
+{
+	X509_EXTENSION *ex = NULL;
+	ASN1_OCTET_STRING *hash = NULL;
+	unsigned char *p = NULL;
+	int sz = -1;
+
+	/* Encode Hash */
+	hash = ASN1_OCTET_STRING_new();
+	ASN1_OCTET_STRING_set(hash, buf, len);
+	sz = i2d_ASN1_OCTET_STRING(hash, NULL);
+	i2d_ASN1_OCTET_STRING(hash, &p);
+
+	/* Create the extension */
+	ex = ext_new(nid, crit, p, sz);
+
+	/* Clean up */
+	OPENSSL_free(p);
+	ASN1_OCTET_STRING_free(hash);
+
+	return ex;
+}
+
+/*
+ * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
+ * Integer
+ *
+ * Parameters:
+ *   pex: OpenSSL extension pointer (output parameter)
+ *   nid: extension identifier
+ *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
+ *   value: nvcounter value
+ *
+ * Return: Extension address, NULL if error
+ */
+X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
+{
+	X509_EXTENSION *ex = NULL;
+	ASN1_INTEGER *counter = NULL;
+	unsigned char *p = NULL;
+	int sz = -1;
+
+	/* Encode counter */
+	counter = ASN1_INTEGER_new();
+	ASN1_INTEGER_set(counter, value);
+	sz = i2d_ASN1_INTEGER(counter, NULL);
+	i2d_ASN1_INTEGER(counter, &p);
+
+	/* Create the extension */
+	ex = ext_new(nid, crit, p, sz);
+
+	/* Free objects */
+	OPENSSL_free(p);
+	ASN1_INTEGER_free(counter);
+
+	return ex;
+}
+
+/*
+ * Creates a x509v3 extension containing a public key in DER format:
+ *
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
+ *       algorithm            AlgorithmIdentifier,
+ *       subjectPublicKey     BIT STRING }
+ *
+ * Parameters:
+ *   pex: OpenSSL extension pointer (output parameter)
+ *   nid: extension identifier
+ *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
+ *   k: key
+ *
+ * Return: Extension address, NULL if error
+ */
+X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
+{
+	X509_EXTENSION *ex = NULL;
+	unsigned char *p = NULL;
+	int sz = -1;
+
+	/* Encode key */
+	BIO *mem = BIO_new(BIO_s_mem());
+	if (i2d_PUBKEY_bio(mem, k) <= 0) {
+		ERR_print_errors_fp(stderr);
+		return NULL;
+	}
+	p = (unsigned char *)OPENSSL_malloc(4096);
+	sz = BIO_read(mem, p, 4096);
+
+	/* Create the extension */
+	ex = ext_new(nid, crit, p, sz);
+
+	/* Clean up */
+	OPENSSL_free(p);
+
+	return ex;
+}
diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c
new file mode 100644
index 0000000..b5737d9
--- /dev/null
+++ b/tools/cert_create/src/key.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
+#include "cert.h"
+#include "debug.h"
+#include "key.h"
+#include "platform_oid.h"
+#include "sha.h"
+
+#define MAX_FILENAME_LEN		1024
+
+/*
+ * Create a new key
+ */
+int key_new(key_t *key)
+{
+	RSA *rsa = NULL;
+	EVP_PKEY *k = NULL;
+
+	/* Create key pair container */
+	k = EVP_PKEY_new();
+	if (k == NULL) {
+		return 0;
+	}
+
+	/* Generate a new RSA key */
+	rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL);
+	if (EVP_PKEY_assign_RSA(k, rsa)) {
+		key->key = k;
+		return 1;
+	} else {
+		printf("Cannot assign RSA key\n");
+	}
+
+	if (k)
+		EVP_PKEY_free(k);
+	return 0;
+}
+
+int key_load(key_t *key)
+{
+	FILE *fp = NULL;
+	EVP_PKEY *k = NULL;
+
+	/* Create key pair container */
+	k = EVP_PKEY_new();
+	if (k == NULL) {
+		return 0;
+	}
+
+	if (key->fn) {
+		/* Load key from file */
+		fp = fopen(key->fn, "r");
+		if (fp) {
+			k = PEM_read_PrivateKey(fp, &k, NULL, NULL);
+			fclose(fp);
+			if (k) {
+				key->key = k;
+				return 1;
+			} else {
+				ERROR("Cannot read key from %s\n", key->fn);
+			}
+		} else {
+			ERROR("Cannot open file %s\n", key->fn);
+		}
+	} else {
+		ERROR("Key filename not specified\n");
+	}
+
+	if (k)
+		EVP_PKEY_free(k);
+
+	return 0;
+}
+
+int key_store(key_t *key)
+{
+	FILE *fp = NULL;
+
+	if (key->fn) {
+		fp = fopen(key->fn, "w");
+		if (fp) {
+			PEM_write_PrivateKey(fp, key->key,
+					NULL, NULL, 0, NULL, NULL);
+			fclose(fp);
+			return 1;
+		} else {
+			ERROR("Cannot create file %s\n", key->fn);
+		}
+	} else {
+		ERROR("Key filename not specified\n");
+	}
+
+	return 0;
+}
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
new file mode 100644
index 0000000..6df367a
--- /dev/null
+++ b/tools/cert_create/src/main.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/sha.h>
+#include <openssl/x509v3.h>
+
+#include "cert.h"
+#include "debug.h"
+#include "ext.h"
+#include "key.h"
+#include "platform_oid.h"
+#include "sha.h"
+#include "tbb_ext.h"
+#include "tbb_cert.h"
+#include "tbb_key.h"
+
+/*
+ * Helper macros to simplify the code. This macro assigns the return value of
+ * the 'fn' function to 'v' and exits if the value is NULL.
+ */
+#define CHECK_NULL(v, fn) \
+	do { \
+		v = fn; \
+		if (v == NULL) { \
+			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
+			exit(1); \
+		} \
+	} while (0)
+
+/*
+ * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
+ * NID is undefined.
+ */
+#define CHECK_OID(v, oid) \
+	do { \
+		v = OBJ_txt2nid(oid); \
+		if (v == NID_undef) { \
+			ERROR("Cannot find TBB extension %s\n", oid); \
+			exit(1); \
+		} \
+	} while (0)
+
+#define MAX_FILENAME_LEN		1024
+#define VAL_DAYS			7300
+#define ID_TO_BIT_MASK(id)		(1 << id)
+#define NVCOUNTER_VALUE			0
+
+/* Files */
+enum {
+	/* Image file names (inputs) */
+	BL2_ID = 0,
+	BL30_ID,
+	BL31_ID,
+	BL32_ID,
+	BL33_ID,
+	/* Certificate file names (outputs) */
+	BL2_CERT_ID,
+	TRUSTED_KEY_CERT_ID,
+	BL30_KEY_CERT_ID,
+	BL30_CERT_ID,
+	BL31_KEY_CERT_ID,
+	BL31_CERT_ID,
+	BL32_KEY_CERT_ID,
+	BL32_CERT_ID,
+	BL33_KEY_CERT_ID,
+	BL33_CERT_ID,
+	/* Key file names (input/output) */
+	ROT_KEY_ID,
+	TRUSTED_WORLD_KEY_ID,
+	NON_TRUSTED_WORLD_KEY_ID,
+	BL30_KEY_ID,
+	BL31_KEY_ID,
+	BL32_KEY_ID,
+	BL33_KEY_ID,
+	NUM_OPTS
+};
+
+/* Global options */
+static int new_keys;
+static int save_keys;
+static int print_cert;
+static int bl30_present;
+static int bl32_present;
+
+/* We are not checking nvcounters in TF. Include them in the certificates but
+ * the value will be set to 0 */
+static int tf_nvcounter;
+static int non_tf_nvcounter;
+
+/* Info messages created in the Makefile */
+extern const char build_msg[];
+extern const char platform_msg[];
+
+
+static char *strdup(const char *str)
+{
+	int n = strlen(str) + 1;
+	char *dup = malloc(n);
+	if (dup) {
+		strcpy(dup, str);
+	}
+	return dup;
+}
+
+/* Command line options */
+static const struct option long_opt[] = {
+	/* Binary images */
+	{"bl2", required_argument, 0, BL2_ID},
+	{"bl30", required_argument, 0, BL30_ID},
+	{"bl31", required_argument, 0, BL31_ID},
+	{"bl32", required_argument, 0, BL32_ID},
+	{"bl33", required_argument, 0, BL33_ID},
+	/* Certificate files */
+	{"bl2-cert", required_argument, 0, BL2_CERT_ID},
+	{"trusted-key-cert", required_argument, 0, TRUSTED_KEY_CERT_ID},
+	{"bl30-key-cert", required_argument, 0, BL30_KEY_CERT_ID},
+	{"bl30-cert", required_argument, 0, BL30_CERT_ID},
+	{"bl31-key-cert", required_argument, 0, BL31_KEY_CERT_ID},
+	{"bl31-cert", required_argument, 0, BL31_CERT_ID},
+	{"bl32-key-cert", required_argument, 0, BL32_KEY_CERT_ID},
+	{"bl32-cert", required_argument, 0, BL32_CERT_ID},
+	{"bl33-key-cert", required_argument, 0, BL33_KEY_CERT_ID},
+	{"bl33-cert", required_argument, 0, BL33_CERT_ID},
+	/* Private key files */
+	{"rot-key", required_argument, 0, ROT_KEY_ID},
+	{"trusted-world-key", required_argument, 0, TRUSTED_WORLD_KEY_ID},
+	{"non-trusted-world-key", required_argument, 0, NON_TRUSTED_WORLD_KEY_ID},
+	{"bl30-key", required_argument, 0, BL30_KEY_ID},
+	{"bl31-key", required_argument, 0, BL31_KEY_ID},
+	{"bl32-key", required_argument, 0, BL32_KEY_ID},
+	{"bl33-key", required_argument, 0, BL33_KEY_ID},
+	/* Common options */
+	{"help", no_argument, 0, 'h'},
+	{"save-keys", no_argument, 0, 'k'},
+	{"new-chain", no_argument, 0, 'n'},
+	{"print-cert", no_argument, 0, 'p'},
+	{0, 0, 0, 0}
+};
+
+static void print_help(const char *cmd)
+{
+	int i = 0;
+	printf("\n\n");
+	printf("The certificate generation tool loads the binary images and\n"
+	       "optionally the RSA keys, and outputs the key and content\n"
+	       "certificates properly signed to implement the chain of trust.\n"
+	       "If keys are provided, they must be in PEM format.\n"
+	       "Certificates are generated in DER format.\n");
+	printf("\n");
+	printf("Usage:\n\n");
+	printf("    %s [-hknp] \\\n", cmd);
+	for (i = 0; i < NUM_OPTS; i++) {
+		printf("        --%s <file>  \\\n", long_opt[i].name);
+	}
+	printf("\n");
+	printf("-h    Print help and exit\n");
+	printf("-k    Save key pairs into files. Filenames must be provided\n");
+	printf("-n    Generate new key pairs if no key files are provided\n");
+	printf("-p    Print the certificates in the standard output\n");
+	printf("\n");
+
+	exit(0);
+}
+
+static void check_cmd_params(void)
+{
+	/* BL2, BL31 and BL33 are mandatory */
+	if (certs[BL2_CERT].bin == NULL) {
+		ERROR("BL2 image not specified\n");
+		exit(1);
+	}
+
+	if (certs[BL31_CERT].bin == NULL) {
+		ERROR("BL31 image not specified\n");
+		exit(1);
+	}
+
+	if (certs[BL33_CERT].bin == NULL) {
+		ERROR("BL33 image not specified\n");
+		exit(1);
+	}
+
+	/* BL30 and BL32 are optional */
+	if (certs[BL30_CERT].bin != NULL) {
+		bl30_present = 1;
+	}
+
+	if (certs[BL32_CERT].bin != NULL) {
+		bl32_present = 1;
+	}
+
+	/* TODO: Certificate filenames */
+
+	/* Filenames to store keys must be specified */
+	if (save_keys || !new_keys) {
+		if (keys[ROT_KEY].fn == NULL) {
+			ERROR("ROT key not specified\n");
+			exit(1);
+		}
+
+		if (keys[TRUSTED_WORLD_KEY].fn == NULL) {
+			ERROR("Trusted World key not specified\n");
+			exit(1);
+		}
+
+		if (keys[NON_TRUSTED_WORLD_KEY].fn == NULL) {
+			ERROR("Non-trusted World key not specified\n");
+			exit(1);
+		}
+
+		if (keys[BL31_KEY].fn == NULL) {
+			ERROR("BL31 key not specified\n");
+			exit(1);
+		}
+
+		if (keys[BL33_KEY].fn == NULL) {
+			ERROR("BL33 key not specified\n");
+			exit(1);
+		}
+
+		if (bl30_present && (keys[BL30_KEY].fn == NULL)) {
+			ERROR("BL30 key not specified\n");
+			exit(1);
+		}
+
+		if (bl32_present && (keys[BL32_KEY].fn == NULL)) {
+			ERROR("BL32 key not specified\n");
+			exit(1);
+		}
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	STACK_OF(X509_EXTENSION) * sk = NULL;
+	X509_EXTENSION *hash_ext = NULL;
+	X509_EXTENSION *nvctr_ext = NULL;
+	X509_EXTENSION *trusted_key_ext = NULL;
+	X509_EXTENSION *non_trusted_key_ext = NULL;
+	FILE *file = NULL;
+	int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid;
+	int c, opt_idx = 0;
+	unsigned char md[SHA256_DIGEST_LENGTH];
+
+	NOTICE("CoT Generation Tool: %s\n", build_msg);
+	NOTICE("Target platform: %s\n", platform_msg);
+
+	while (1) {
+		/* getopt_long stores the option index here. */
+		c = getopt_long(argc, argv, "hknp", long_opt, &opt_idx);
+
+		/* Detect the end of the options. */
+		if (c == -1) {
+			break;
+		}
+
+		switch (c) {
+		case 'h':
+			print_help(argv[0]);
+			break;
+		case 'k':
+			save_keys = 1;
+			break;
+		case 'n':
+			new_keys = 1;
+			break;
+		case 'p':
+			print_cert = 1;
+			break;
+		case BL2_ID:
+			certs[BL2_CERT].bin = strdup(optarg);
+			break;
+		case BL30_ID:
+			certs[BL30_CERT].bin = strdup(optarg);
+			break;
+		case BL31_ID:
+			certs[BL31_CERT].bin = strdup(optarg);
+			break;
+		case BL32_ID:
+			certs[BL32_CERT].bin = strdup(optarg);
+			break;
+		case BL33_ID:
+			certs[BL33_CERT].bin = strdup(optarg);
+			break;
+		case BL2_CERT_ID:
+			certs[BL2_CERT].fn = strdup(optarg);
+			break;
+		case TRUSTED_KEY_CERT_ID:
+			certs[TRUSTED_KEY_CERT].fn = strdup(optarg);
+			break;
+		case BL30_KEY_CERT_ID:
+			certs[BL30_KEY_CERT].fn = strdup(optarg);
+			break;
+		case BL30_CERT_ID:
+			certs[BL30_CERT].fn = strdup(optarg);
+			break;
+		case BL31_KEY_CERT_ID:
+			certs[BL31_KEY_CERT].fn = strdup(optarg);
+			break;
+		case BL31_CERT_ID:
+			certs[BL31_CERT].fn = strdup(optarg);
+			break;
+		case BL32_KEY_CERT_ID:
+			certs[BL32_KEY_CERT].fn = strdup(optarg);
+			break;
+		case BL32_CERT_ID:
+			certs[BL32_CERT].fn = strdup(optarg);
+			break;
+		case BL33_KEY_CERT_ID:
+			certs[BL33_KEY_CERT].fn = strdup(optarg);
+			break;
+		case BL33_CERT_ID:
+			certs[BL33_CERT].fn = strdup(optarg);
+			break;
+		case ROT_KEY_ID:
+			keys[ROT_KEY].fn = strdup(optarg);
+			break;
+		case TRUSTED_WORLD_KEY_ID:
+			keys[TRUSTED_WORLD_KEY].fn = strdup(optarg);
+			break;
+		case NON_TRUSTED_WORLD_KEY_ID:
+			keys[NON_TRUSTED_WORLD_KEY].fn = strdup(optarg);
+			break;
+		case BL30_KEY_ID:
+			keys[BL30_KEY].fn = strdup(optarg);
+			break;
+		case BL31_KEY_ID:
+			keys[BL31_KEY].fn = strdup(optarg);
+			break;
+		case BL32_KEY_ID:
+			keys[BL32_KEY].fn = strdup(optarg);
+			break;
+		case BL33_KEY_ID:
+			keys[BL33_KEY].fn = strdup(optarg);
+			break;
+		case '?':
+		default:
+			printf("%s\n", optarg);
+			exit(1);
+		}
+	}
+
+	/* Set the value of the NVCounters */
+	tf_nvcounter = NVCOUNTER_VALUE;
+	non_tf_nvcounter = NVCOUNTER_VALUE;
+
+	/* Check command line arguments */
+	check_cmd_params();
+
+	/* Register the new types and OIDs for the extensions */
+	if (ext_init(tbb_ext) != 0) {
+		ERROR("Cannot initialize TBB extensions\n");
+		exit(1);
+	}
+
+	/* Get non-volatile counters NIDs */
+	CHECK_OID(tz_nvctr_nid, TZ_FW_NVCOUNTER_OID);
+	CHECK_OID(ntz_nvctr_nid, NTZ_FW_NVCOUNTER_OID);
+
+	/* Load private keys from files (or generate new ones) */
+	if (new_keys) {
+		for (i = 0 ; i < NUM_KEYS ; i++) {
+			if (!key_new(&keys[i])) {
+				ERROR("Error creating %s\n", keys[i].desc);
+				exit(1);
+			}
+		}
+	} else {
+		for (i = 0 ; i < NUM_KEYS ; i++) {
+			if (!key_load(&keys[i])) {
+				ERROR("Error loading %s\n", keys[i].desc);
+				exit(1);
+			}
+		}
+	}
+
+	/* *********************************************************************
+	 * BL2 certificate (Trusted Boot Firmware certificate):
+	 *     - Self-signed with OEM ROT private key
+	 *     - Extensions:
+	 *         - TrustedFirmwareNVCounter (TODO)
+	 *         - BL2 hash
+	 **********************************************************************/
+	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+
+	/* Add the NVCounter as a critical extension */
+	CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+			tf_nvcounter));
+	sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+	/* Add hash of BL2 as an extension */
+	if (!sha_file(certs[BL2_CERT].bin, md)) {
+		ERROR("Cannot calculate the hash of %s\n", certs[BL2_CERT].bin);
+		exit(1);
+	}
+	CHECK_OID(hash_nid, BL2_HASH_OID);
+	CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+			SHA256_DIGEST_LENGTH));
+	sk_X509_EXTENSION_push(sk, hash_ext);
+
+	/* Create certificate. Signed with ROT key */
+	if (!cert_new(&certs[BL2_CERT], VAL_DAYS, 0, sk)) {
+		ERROR("Cannot create %s\n", certs[BL2_CERT].cn);
+		exit(1);
+	}
+	sk_X509_EXTENSION_free(sk);
+
+	/* *********************************************************************
+	 * Trusted Key certificate:
+	 *     - Self-signed with OEM ROT private key
+	 *     - Extensions:
+	 *         - TrustedFirmwareNVCounter (TODO)
+	 *         - TrustedWorldPK
+	 *         - NonTrustedWorldPK
+	 **********************************************************************/
+	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+	CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+			tf_nvcounter));
+	sk_X509_EXTENSION_push(sk, nvctr_ext);
+	CHECK_OID(pk_nid, TZ_WORLD_PK_OID);
+	CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+			keys[TRUSTED_WORLD_KEY].key));
+	sk_X509_EXTENSION_push(sk, trusted_key_ext);
+	CHECK_OID(pk_nid, NTZ_WORLD_PK_OID);
+	CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+			keys[NON_TRUSTED_WORLD_KEY].key));
+	sk_X509_EXTENSION_push(sk, non_trusted_key_ext);
+	if (!cert_new(&certs[TRUSTED_KEY_CERT], VAL_DAYS, 0, sk)) {
+		ERROR("Cannot create %s\n", certs[TRUSTED_KEY_CERT].cn);
+		exit(1);
+	}
+	sk_X509_EXTENSION_free(sk);
+
+	/* *********************************************************************
+	 * BL30 Key certificate (Trusted SCP Firmware Key certificate):
+	 *     - Self-signed with Trusted World key
+	 *     - Extensions:
+	 *         - TrustedFirmwareNVCounter (TODO)
+	 *         - SCPFirmwareContentCertPK
+	 **********************************************************************/
+	if (bl30_present) {
+		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+		CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+				tf_nvcounter));
+		sk_X509_EXTENSION_push(sk, nvctr_ext);
+		CHECK_OID(pk_nid, BL30_CONTENT_CERT_PK_OID);
+		CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+				keys[BL30_KEY].key));
+		sk_X509_EXTENSION_push(sk, trusted_key_ext);
+		if (!cert_new(&certs[BL30_KEY_CERT], VAL_DAYS, 0, sk)) {
+			ERROR("Cannot create %s\n", certs[BL30_KEY_CERT].cn);
+			exit(1);
+		}
+		sk_X509_EXTENSION_free(sk);
+	}
+
+	/* *********************************************************************
+	 * BL30 certificate (SCP Firmware Content certificate):
+	 *     - Signed with Trusted World Key
+	 *     - Extensions:
+	 *         - TrustedFirmwareNVCounter (TODO)
+	 *         - SCPFirmwareHash
+	 **********************************************************************/
+	if (bl30_present) {
+		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+		CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+				tf_nvcounter));
+		sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+		if (!sha_file(certs[BL30_CERT].bin, md)) {
+			ERROR("Cannot calculate the hash of %s\n",
+					certs[BL30_CERT].bin);
+			exit(1);
+		}
+		CHECK_OID(hash_nid, BL30_HASH_OID);
+		CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+				SHA256_DIGEST_LENGTH));
+		sk_X509_EXTENSION_push(sk, hash_ext);
+
+		if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) {
+			ERROR("Cannot create %s\n", certs[BL30_CERT].cn);
+			exit(1);
+		}
+
+		sk_X509_EXTENSION_free(sk);
+	}
+
+	/* *********************************************************************
+	 * BL31 Key certificate (Trusted SoC Firmware Key certificate):
+	 *     - Self-signed with Trusted World key
+	 *     - Extensions:
+	 *         - TrustedFirmwareNVCounter (TODO)
+	 *         - SoCFirmwareContentCertPK
+	 **********************************************************************/
+	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+	CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+			tf_nvcounter));
+	sk_X509_EXTENSION_push(sk, nvctr_ext);
+	CHECK_OID(pk_nid, BL31_CONTENT_CERT_PK_OID);
+	CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+			keys[BL31_KEY].key));
+	sk_X509_EXTENSION_push(sk, trusted_key_ext);
+	if (!cert_new(&certs[BL31_KEY_CERT], VAL_DAYS, 0, sk)) {
+		ERROR("Cannot create %s\n", certs[BL31_KEY_CERT].cn);
+		exit(1);
+	}
+	sk_X509_EXTENSION_free(sk);
+
+	/* *********************************************************************
+	 * BL31 certificate (SOC Firmware Content certificate):
+	 *     - Signed with Trusted World Key
+	 *     - Extensions:
+	 *         - TrustedFirmwareNVCounter (TODO)
+	 *         - BL31 hash
+	 **********************************************************************/
+	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+	CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+			tf_nvcounter));
+	sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+	if (!sha_file(certs[BL31_CERT].bin, md)) {
+		ERROR("Cannot calculate the hash of %s\n", certs[BL31_CERT].bin);
+		exit(1);
+	}
+	CHECK_OID(hash_nid, BL31_HASH_OID);
+	CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+			SHA256_DIGEST_LENGTH));
+	sk_X509_EXTENSION_push(sk, hash_ext);
+
+	if (!cert_new(&certs[BL31_CERT], VAL_DAYS, 0, sk)) {
+		ERROR("Cannot create %s\n", certs[BL31_CERT].cn);
+		exit(1);
+	}
+
+	sk_X509_EXTENSION_free(sk);
+
+	/* *********************************************************************
+	 * BL32 Key certificate (Trusted OS Firmware Key certificate):
+	 *     - Self-signed with Trusted World key
+	 *     - Extensions:
+	 *         - TrustedFirmwareNVCounter (TODO)
+	 *         - TrustedOSFirmwareContentCertPK
+	 **********************************************************************/
+	if (bl32_present) {
+		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+		CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+				tf_nvcounter));
+		sk_X509_EXTENSION_push(sk, nvctr_ext);
+		CHECK_OID(pk_nid, BL32_CONTENT_CERT_PK_OID);
+		CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+				keys[BL32_KEY].key));
+		sk_X509_EXTENSION_push(sk, trusted_key_ext);
+		if (!cert_new(&certs[BL32_KEY_CERT], VAL_DAYS, 0, sk)) {
+			ERROR("Cannot create %s\n", certs[BL32_KEY_CERT].cn);
+			exit(1);
+		}
+		sk_X509_EXTENSION_free(sk);
+	}
+
+	/* *********************************************************************
+	 * BL32 certificate (TrustedOS Firmware Content certificate):
+	 *     - Signed with Trusted World Key
+	 *     - Extensions:
+	 *         - TrustedFirmwareNVCounter (TODO)
+	 *         - BL32 hash
+	 **********************************************************************/
+	if (bl32_present) {
+		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+		CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT,
+				tf_nvcounter));
+		sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+		if (!sha_file(certs[BL32_CERT].bin, md)) {
+			ERROR("Cannot calculate the hash of %s\n",
+					certs[BL32_CERT].bin);
+			exit(1);
+		}
+		CHECK_OID(hash_nid, BL32_HASH_OID);
+		CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+				SHA256_DIGEST_LENGTH));
+		sk_X509_EXTENSION_push(sk, hash_ext);
+
+		if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) {
+			ERROR("Cannot create %s\n", certs[BL32_CERT].cn);
+			exit(1);
+		}
+
+		sk_X509_EXTENSION_free(sk);
+	}
+
+	/* *********************************************************************
+	 * BL33 Key certificate (Non Trusted Firmware Key certificate):
+	 *     - Self-signed with Non Trusted World key
+	 *     - Extensions:
+	 *         - NonTrustedFirmwareNVCounter (TODO)
+	 *         - NonTrustedFirmwareContentCertPK
+	 **********************************************************************/
+	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+	CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT,
+			non_tf_nvcounter));
+	sk_X509_EXTENSION_push(sk, nvctr_ext);
+	CHECK_OID(pk_nid, BL33_CONTENT_CERT_PK_OID);
+	CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT,
+			keys[BL33_KEY].key));
+	sk_X509_EXTENSION_push(sk, non_trusted_key_ext);
+	if (!cert_new(&certs[BL33_KEY_CERT], VAL_DAYS, 0, sk)) {
+		ERROR("Cannot create %s\n", certs[BL33_KEY_CERT].cn);
+		exit(1);
+	}
+	sk_X509_EXTENSION_free(sk);
+
+	/* *********************************************************************
+	 * BL33 certificate (Non-Trusted World Content certificate):
+	 *     - Signed with Non-Trusted World Key
+	 *     - Extensions:
+	 *         - NonTrustedFirmwareNVCounter (TODO)
+	 *         - BL33 hash
+	 **********************************************************************/
+	CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
+	CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT,
+			non_tf_nvcounter));
+	sk_X509_EXTENSION_push(sk, nvctr_ext);
+
+	if (!sha_file(certs[BL33_CERT].bin, md)) {
+		ERROR("Cannot calculate the hash of %s\n", certs[BL33_CERT].bin);
+		exit(1);
+	}
+	CHECK_OID(hash_nid, BL33_HASH_OID);
+	CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md,
+			SHA256_DIGEST_LENGTH));
+	sk_X509_EXTENSION_push(sk, hash_ext);
+
+	if (!cert_new(&certs[BL33_CERT], VAL_DAYS, 0, sk)) {
+		ERROR("Cannot create %s\n", certs[BL33_CERT].cn);
+		exit(1);
+	}
+	sk_X509_EXTENSION_free(sk);
+
+	/* Print the certificates */
+	if (print_cert) {
+		for (i = 0 ; i < NUM_CERTIFICATES ; i++) {
+			if (!certs[i].x) {
+				continue;
+			}
+			printf("\n\n=====================================\n\n");
+			X509_print_fp(stdout, certs[i].x);
+		}
+	}
+
+	/* Save created certificates to files */
+	for (i = 0 ; i < NUM_CERTIFICATES ; i++) {
+		if (certs[i].x && certs[i].fn) {
+			file = fopen(certs[i].fn, "w");
+			if (file != NULL) {
+				i2d_X509_fp(file, certs[i].x);
+				fclose(file);
+			} else {
+				ERROR("Cannot create file %s\n", certs[i].fn);
+			}
+		}
+	}
+
+	/* Save keys */
+	if (save_keys) {
+		for (i = 0 ; i < NUM_KEYS ; i++) {
+			if (!key_store(&keys[i])) {
+				ERROR("Cannot save %s\n", keys[i].desc);
+			}
+		}
+	}
+
+	X509_EXTENSION_free(hash_ext);
+	X509_EXTENSION_free(nvctr_ext);
+	X509_EXTENSION_free(trusted_key_ext);
+	X509_EXTENSION_free(non_trusted_key_ext);
+
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_cleanup();
+#endif
+	CRYPTO_cleanup_all_ex_data();
+
+	return 0;
+}
diff --git a/tools/cert_create/src/sha.c b/tools/cert_create/src/sha.c
new file mode 100644
index 0000000..57026b5
--- /dev/null
+++ b/tools/cert_create/src/sha.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <openssl/sha.h>
+
+#include "debug.h"
+
+#define BUFFER_SIZE	256
+
+int sha_file(const char *filename, unsigned char *md)
+{
+	FILE *inFile;
+	SHA256_CTX shaContext;
+	int bytes;
+	unsigned char data[BUFFER_SIZE];
+
+	if ((filename == NULL) || (md == NULL)) {
+		ERROR("%s(): NULL argument\n", __FUNCTION__);
+		return 0;
+	}
+
+	inFile = fopen(filename, "rb");
+	if (inFile == NULL) {
+		ERROR("Cannot read %s\n", filename);
+		return 0;
+	}
+
+	SHA256_Init(&shaContext);
+	while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) {
+		SHA256_Update(&shaContext, data, bytes);
+	}
+	SHA256_Final(md, &shaContext);
+
+	fclose(inFile);
+	return 1;
+}
diff --git a/tools/cert_create/src/tbb_cert.c b/tools/cert_create/src/tbb_cert.c
new file mode 100644
index 0000000..8dfda60
--- /dev/null
+++ b/tools/cert_create/src/tbb_cert.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tbb_cert.h"
+#include "tbb_key.h"
+
+/*
+ * Certificates used in the chain of trust
+ *
+ * The order of the certificates must follow the enumeration specified in
+ * tbb_cert.h. All certificates are self-signed.
+ */
+cert_t certs[NUM_CERTIFICATES] = {
+	{
+		.id = BL2_CERT,
+		.fn = NULL,
+		.cn = "BL2 Certificate",
+		.key = &keys[ROT_KEY],
+		.issuer = &certs[BL2_CERT],
+	},
+	{
+		.id = TRUSTED_KEY_CERT,
+		.fn = NULL,
+		.cn = "Trusted Key Certificate",
+		.key = &keys[ROT_KEY],
+		.issuer = &certs[TRUSTED_KEY_CERT],
+	},
+	{
+		.id = BL30_KEY_CERT,
+		.fn = NULL,
+		.cn = "BL3-0 Key Certificate",
+		.key = &keys[TRUSTED_WORLD_KEY],
+		.issuer = &certs[BL30_KEY_CERT],
+	},
+	{
+		.id = BL30_CERT,
+		.fn = NULL,
+		.cn = "BL3-0 Content Certificate",
+		.key = &keys[BL30_KEY],
+		.issuer = &certs[BL30_CERT],
+	},
+	{
+		.id = BL31_KEY_CERT,
+		.fn = NULL,
+		.cn = "BL3-1 Key Certificate",
+		.key = &keys[TRUSTED_WORLD_KEY],
+		.issuer = &certs[BL31_KEY_CERT],
+	},
+	{
+		.id = BL31_CERT,
+		.fn = NULL,
+		.cn = "BL3-1 Content Certificate",
+		.key = &keys[BL31_KEY],
+		.issuer = &certs[BL31_CERT],
+	},
+	{
+		.id = BL32_KEY_CERT,
+		.fn = NULL,
+		.cn = "BL3-2 Key Certificate",
+		.key = &keys[TRUSTED_WORLD_KEY],
+		.issuer = &certs[BL32_KEY_CERT],
+	},
+	{
+		.id = BL32_CERT,
+		.fn = NULL,
+		.cn = "BL3-2 Content Certificate",
+		.key = &keys[BL32_KEY],
+		.issuer = &certs[BL32_CERT],
+	},
+	{
+		.id = BL33_KEY_CERT,
+		.fn = NULL,
+		.cn = "BL3-3 Key Certificate",
+		.key = &keys[NON_TRUSTED_WORLD_KEY],
+		.issuer = &certs[BL33_KEY_CERT],
+	},
+	{
+		.id = BL33_CERT,
+		.fn = NULL,
+		.cn = "BL3-3 Content Certificate",
+		.key = &keys[BL33_KEY],
+		.issuer = &certs[BL33_CERT],
+	}
+};
diff --git a/tools/cert_create/src/tbb_ext.c b/tools/cert_create/src/tbb_ext.c
new file mode 100644
index 0000000..0022611
--- /dev/null
+++ b/tools/cert_create/src/tbb_ext.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+#include "ext.h"
+#include "platform_oid.h"
+
+ext_t tbb_ext[] = {
+	{
+		.oid = TZ_FW_NVCOUNTER_OID,
+		.sn = "TrustedNvCounter",
+		.ln = "Non-volatile trusted counter",
+		.type = V_ASN1_INTEGER
+	},
+	{
+		.oid = NTZ_FW_NVCOUNTER_OID,
+		.sn = "NonTrustedNvCounter",
+		.ln = "Non-volatile non-trusted counter",
+		.type = V_ASN1_INTEGER
+	},
+	{
+		.oid = BL2_HASH_OID,
+		.sn = "TrustedBootFirmwareHash",
+		.ln = "Trusted Boot Firmware (BL2) hash (SHA256)",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = TZ_WORLD_PK_OID,
+		.sn = "TrustedWorldPublicKey",
+		.ln = "Trusted World Public Key",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = NTZ_WORLD_PK_OID,
+		.sn = "NonTrustedWorldPublicKey",
+		.ln = "Non-Trusted World Public Key",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = BL31_CONTENT_CERT_PK_OID,
+		.sn = "SoCFirmwareContentCertPK",
+		.ln = "SoC Firmware content certificate public key",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = BL31_HASH_OID,
+		.sn = "APROMPatchHash",
+		.ln = "AP ROM patch hash",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = BL30_CONTENT_CERT_PK_OID,
+		.sn = "SCPFirmwareContentCertPK",
+		.ln = "SCP Firmware content certificate public key",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = BL30_HASH_OID,
+		.sn = "SCPFirmwareHash",
+		.ln = "SCP Firmware (BL30) hash (SHA256)",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = BL32_CONTENT_CERT_PK_OID,
+		.sn = "TrustedOSFirmwareContentCertPK",
+		.ln = "Trusted OS Firmware content certificate public key",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = BL32_HASH_OID,
+		.sn = "TrustedOSHash",
+		.ln = "Trusted OS (BL32) hash (SHA256)",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = BL33_CONTENT_CERT_PK_OID,
+		.sn = "NonTrustedFirmwareContentCertPK",
+		.ln = "Non-Trusted Firmware content certificate public key",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{
+		.oid = BL33_HASH_OID,
+		.sn = "NonTrustedWorldBootloaderHash",
+		.ln = "Non-Trusted World (BL33) hash (SHA256)",
+		.type = V_ASN1_OCTET_STRING
+	},
+	{ 0, 0, 0, 0 }
+};
diff --git a/tools/cert_create/src/tbb_key.c b/tools/cert_create/src/tbb_key.c
new file mode 100644
index 0000000..140aeda
--- /dev/null
+++ b/tools/cert_create/src/tbb_key.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tbb_key.h"
+
+/*
+ * Keys used to establish the chain of trust
+ *
+ * The order of the keys must follow the enumeration specified in tbb_key.h
+ */
+key_t keys[NUM_KEYS] = {
+	{
+		.id = ROT_KEY,
+		.desc = "Root Of Trust key"
+	},
+	{
+		.id = TRUSTED_WORLD_KEY,
+		.desc = "Trusted World key"
+	},
+	{
+		.id = NON_TRUSTED_WORLD_KEY,
+		.desc = "Non Trusted World key"
+	},
+	{
+		.id = BL30_KEY,
+		.desc = "BL30 key"
+	},
+	{
+		.id = BL31_KEY,
+		.desc = "BL31 key"
+	},
+	{
+		.id = BL32_KEY,
+		.desc = "BL32 key"
+	},
+	{
+		.id = BL33_KEY,
+		.desc = "BL33 key"
+	}
+};
diff --git a/tools/fip_create/fip_create.c b/tools/fip_create/fip_create.c
index c940c5b..c6869f9 100644
--- a/tools/fip_create/fip_create.c
+++ b/tools/fip_create/fip_create.c
@@ -65,6 +65,30 @@
 	  "bl32", NULL, FLAG_FILENAME},
 	{ "Non-Trusted Firmware BL3-3", UUID_NON_TRUSTED_FIRMWARE_BL33,
 	  "bl33", NULL, FLAG_FILENAME},
+	/* Key Certificates */
+	{ "Root Of Trust key certificate", UUID_ROT_KEY_CERT,
+	  "rot-cert", NULL, FLAG_FILENAME },
+	{ "Trusted key certificate", UUID_TRUSTED_KEY_CERT,
+	  "trusted-key-cert", NULL, FLAG_FILENAME},
+	{ "SCP Firmware BL3-0 key certificate", UUID_SCP_FIRMWARE_BL30_KEY_CERT,
+	  "bl30-key-cert", NULL, FLAG_FILENAME},
+	{ "EL3 Runtime Firmware BL3-1 key certificate", UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT,
+	  "bl31-key-cert", NULL, FLAG_FILENAME},
+	{ "Secure Payload BL3-2 (Trusted OS) key certificate", UUID_SECURE_PAYLOAD_BL32_KEY_CERT,
+	  "bl32-key-cert", NULL, FLAG_FILENAME},
+	{ "Non-Trusted Firmware BL3-3 key certificate", UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT,
+	  "bl33-key-cert", NULL, FLAG_FILENAME},
+	/* Content certificates */
+	{ "Trusted Boot Firmware BL2 certificate", UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT,
+	  "bl2-cert", NULL, FLAG_FILENAME },
+	{ "SCP Firmware BL3-0 certificate", UUID_SCP_FIRMWARE_BL30_CERT,
+	  "bl30-cert", NULL, FLAG_FILENAME},
+	{ "EL3 Runtime Firmware BL3-1 certificate", UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT,
+	  "bl31-cert", NULL, FLAG_FILENAME},
+	{ "Secure Payload BL3-2 (Trusted OS) certificate", UUID_SECURE_PAYLOAD_BL32_CERT,
+	  "bl32-cert", NULL, FLAG_FILENAME},
+	{ "Non-Trusted Firmware BL3-3 certificate", UUID_NON_TRUSTED_FIRMWARE_BL33_CERT,
+	  "bl33-cert", NULL, FLAG_FILENAME},
 	{ NULL, {0}, 0 }
 };
 
diff --git a/tools/fip_create/fip_create.h b/tools/fip_create/fip_create.h
index ef321cd..3258335 100644
--- a/tools/fip_create/fip_create.h
+++ b/tools/fip_create/fip_create.h
@@ -34,7 +34,7 @@
 #include <stdint.h>
 #include <uuid.h>
 
-#define MAX_FILES			10
+#define MAX_FILES			20
 
 /* TODO: Update this number as required */
 #define TOC_HEADER_SERIAL_NUMBER	0x12345678