Merge pull request #351 from davwan01/davwan01/docs-update

Some minor fixes to interrupt-framework-design.md
diff --git a/.gitignore b/.gitignore
index d3567bc..cc5cbfb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,5 @@
 tools/**/*.o
 tools/fip_create/fip_create
 tools/cert_create/src/*.o
+tools/cert_create/src/**/*.o
 tools/cert_create/cert_create
diff --git a/docs/plat/nvidia-tegra.md b/docs/plat/nvidia-tegra.md
index 6c76dd1..b29532c 100644
--- a/docs/plat/nvidia-tegra.md
+++ b/docs/plat/nvidia-tegra.md
@@ -57,7 +57,10 @@
 Preparing the BL31 image to run on Tegra SoCs
 ===================================================
 'CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- make PLAT=tegra \
-TARGET_SOC=<target-soc e.g. t210|t132> SPD=<dispatcher e.g. tlkd> all'
+TARGET_SOC=<target-soc e.g. t210|t132> SPD=<dispatcher e.g. tlkd> bl31'
+
+Platforms wanting to use different TZDRAM_BASE, can add 'TZDRAM_BASE=<value>'
+to the build command line.
 
 Power Management
 ================
diff --git a/docs/spd/tlk-dispatcher.md b/docs/spd/tlk-dispatcher.md
index 890b35e..40c8344 100644
--- a/docs/spd/tlk-dispatcher.md
+++ b/docs/spd/tlk-dispatcher.md
@@ -10,12 +10,9 @@
 just needs to compile, any BL32 image would do. To use TLK as the BL32, please
 refer to the "Build TLK" section.
 
-Once a BL32 is ready, TLKD can be included in the image using the following
-command:
+Once a BL32 is ready, TLKD can be included in the image by adding "SPD=tlkd"
+to the build command.
 
-CROSS_COMPILE=<path_to_linaro_chain>/bin/aarch64-none-elf- make NEED_BL1=0
-NEED_BL2=0 BL32=<path_to_BL32_image> PLAT=<platform> SPD=tlkd all
-_
 Trusted Little Kernel (TLK)
 ===========================
 TLK is a Trusted OS running as Secure EL1. It is a Free Open Source Software
@@ -58,3 +55,16 @@
 =========
 To build and execute TLK, follow the instructions from "Building a TLK Device"
 section from Tegra_BSP_for_Android_TLK_FOSS_Reference.pdf manual.
+
+Input parameters to TLK
+=======================
+TLK expects the TZDRAM size and a structure containing the boot arguments. BL2
+passes this information to the EL3 software as members of the bl32_ep_info
+struct, where bl32_ep_info is part of bl31_params_t (passed by BL2 in X0)
+
+Example:
+--------
+    bl32_ep_info->args.arg0 = TZDRAM size available for BL32
+    bl32_ep_info->args.arg1 = unused (used only on ARMv7)
+    bl32_ep_info->args.arg2 = pointer to boot args
+
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index ce7f317..d6ea664 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -85,7 +85,7 @@
 
 static entry_point_info_t bl33_image_ep_info, bl32_image_ep_info;
 static plat_params_from_bl2_t plat_bl31_params_from_bl2 = {
-	(uint64_t)TZDRAM_SIZE, (uintptr_t)NULL
+	.tzdram_size = (uint64_t)TZDRAM_SIZE
 };
 
 /*******************************************************************************
@@ -145,13 +145,10 @@
 	bl32_image_ep_info = *from_bl2->bl32_ep_info;
 
 	/*
-	 * Parse platform specific parameters - TZDRAM aperture size and
-	 * pointer to BL32 params.
+	 * Parse platform specific parameters - TZDRAM aperture size
 	 */
-	if (plat_params) {
+	if (plat_params)
 		plat_bl31_params_from_bl2.tzdram_size = plat_params->tzdram_size;
-		plat_bl31_params_from_bl2.bl32_params = plat_params->bl32_params;
-	}
 }
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index dbd6689..952e2d8 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -42,7 +42,6 @@
 
 typedef struct plat_params_from_bl2 {
 	uint64_t tzdram_size;
-	uintptr_t bl32_params;
 } plat_params_from_bl2_t;
 
 /* Declarations for plat_psci_handlers.c */
diff --git a/plat/nvidia/tegra/soc/t132/platform_t132.mk b/plat/nvidia/tegra/soc/t132/platform_t132.mk
index 1be13e9..69d6296 100644
--- a/plat/nvidia/tegra/soc/t132/platform_t132.mk
+++ b/plat/nvidia/tegra/soc/t132/platform_t132.mk
@@ -31,7 +31,7 @@
 TEGRA_BOOT_UART_BASE		:= 0x70006300
 $(eval $(call add_define,TEGRA_BOOT_UART_BASE))
 
-TZDRAM_BASE			:= 0xF1C00000
+TZDRAM_BASE			:= 0xF5C00000
 $(eval $(call add_define,TZDRAM_BASE))
 
 PLATFORM_CLUSTER_COUNT		:= 1
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index a4bd76f..7efaf8a 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -39,10 +39,10 @@
            src/ext.o \
            src/key.o \
            src/main.o \
-           src/tbb_cert.o \
-           src/tbb_ext.o \
-           src/tbb_key.o \
-           src/sha.o
+           src/sha.o \
+           src/tbbr/tbb_cert.o \
+           src/tbbr/tbb_ext.o \
+           src/tbbr/tbb_key.o
 
 CFLAGS := -Wall -std=c99
 
diff --git a/tools/cert_create/include/cert.h b/tools/cert_create/include/cert.h
index 48a4146..18129a7 100644
--- a/tools/cert_create/include/cert.h
+++ b/tools/cert_create/include/cert.h
@@ -33,8 +33,11 @@
 
 #include <openssl/ossl_typ.h>
 #include <openssl/x509.h>
+#include "ext.h"
 #include "key.h"
 
+#define CERT_MAX_EXT			4
+
 /*
  * This structure contains information related to the generation of the
  * certificates. All these fields must be known and specified at build time
@@ -52,18 +55,28 @@
 	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 */
+	/* These fields must be defined statically */
+	int key;		/* Key to be signed */
+	int issuer;		/* Issuer certificate */
+	int ext[CERT_MAX_EXT];	/* Certificate extensions */
+	int num_ext;		/* Number of extensions in the certificate */
 
-	cert_t *issuer;		/* Issuer certificate */
+	X509 *x;		/* X509 certificate container */
 };
 
+/* Exported API */
 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);
 
+/* Macro to register the certificates used in the CoT */
+#define REGISTER_COT(_certs) \
+	cert_t *certs = &_certs[0]; \
+	const unsigned int num_certs = sizeof(_certs)/sizeof(_certs[0]);
+
+/* Exported variables */
+extern cert_t *certs;
+extern const unsigned int num_certs;
+
 #endif /* CERT_H_ */
diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h
index 57bb65f..60455e6 100644
--- a/tools/cert_create/include/ext.h
+++ b/tools/cert_create/include/ext.h
@@ -31,8 +31,16 @@
 #ifndef EXT_H_
 #define EXT_H_
 
+#include "key.h"
 #include <openssl/x509v3.h>
 
+/* Extension types supported */
+enum {
+	EXT_TYPE_NVCOUNTER,
+	EXT_TYPE_PKEY,
+	EXT_TYPE_HASH
+};
+
 /*
  * This structure contains the relevant information to create the extensions
  * to be included in the certificates. This extensions will be used to
@@ -42,11 +50,19 @@
 	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.
+	int asn1_type;		/* OpenSSL ASN1 type of the extension data.
 				 * Supported types are:
 				 *   - V_ASN1_INTEGER
 				 *   - V_ASN1_OCTET_STRING
 				 */
+	int type;
+	/* Extension data (depends on extension type) */
+	union {
+		const char *fn;	/* File with extension data */
+		int nvcounter;	/* Non volatile counter */
+		int key;	/* Public key */
+	} data;
+
 	int alias;		/* In case OpenSSL provides an standard
 				 * extension of the same type, add the new
 				 * extension as an alias of this one
@@ -62,10 +78,20 @@
 	EXT_CRIT = !EXT_NON_CRIT,
 };
 
-int ext_init(ext_t *tbb_ext);
+/* Exported API */
+int ext_register(ext_t *tbb_ext);
 X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
 		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);
 
+/* Macro to register the extensions used in the CoT */
+#define REGISTER_EXTENSIONS(_ext) \
+	ext_t *extensions = &_ext[0]; \
+	const unsigned int num_extensions = sizeof(_ext)/sizeof(_ext[0]);
+
+/* Exported variables */
+extern ext_t *extensions;
+extern const unsigned int num_extensions;
+
 #endif /* EXT_H_ */
diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h
index 165ffa1..da9f119 100644
--- a/tools/cert_create/include/key.h
+++ b/tools/cert_create/include/key.h
@@ -68,8 +68,18 @@
 	EVP_PKEY *key;		/* Key container */
 } key_t;
 
+/* Exported API */
 int key_create(key_t *key, int type);
 int key_load(key_t *key, unsigned int *err_code);
 int key_store(key_t *key);
 
+/* Macro to register the keys used in the CoT */
+#define REGISTER_KEYS(_keys) \
+	key_t *keys = &_keys[0]; \
+	const unsigned int num_keys = sizeof(_keys)/sizeof(_keys[0]);
+
+/* Exported variables */
+extern key_t *keys;
+extern const unsigned int num_keys;
+
 #endif /* KEY_H_ */
diff --git a/tools/cert_create/include/tbb_cert.h b/tools/cert_create/include/tbbr/tbb_cert.h
similarity index 93%
rename from tools/cert_create/include/tbb_cert.h
rename to tools/cert_create/include/tbbr/tbb_cert.h
index 4e48125..21626c7 100644
--- a/tools/cert_create/include/tbb_cert.h
+++ b/tools/cert_create/include/tbbr/tbb_cert.h
@@ -46,13 +46,7 @@
 	BL32_KEY_CERT,
 	BL32_CERT,
 	BL33_KEY_CERT,
-	BL33_CERT,
-	NUM_CERTIFICATES,
+	BL33_CERT
 };
 
-/*
- * 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/tbbr/tbb_ext.h
similarity index 84%
rename from tools/cert_create/include/tbb_ext.h
rename to tools/cert_create/include/tbbr/tbb_ext.h
index 155d3cb..03b12d7 100644
--- a/tools/cert_create/include/tbb_ext.h
+++ b/tools/cert_create/include/tbbr/tbb_ext.h
@@ -32,7 +32,21 @@
 
 #include "ext.h"
 
-/* Array containing the extensions used in the chain of trust */
-extern ext_t tbb_ext[];
+/* TBBR extensions */
+enum {
+	TZ_FW_NVCOUNTER_EXT,
+	NTZ_FW_NVCOUNTER_EXT,
+	BL2_HASH_EXT,
+	TZ_WORLD_PK_EXT,
+	NTZ_WORLD_PK_EXT,
+	BL31_CONTENT_CERT_PK_EXT,
+	BL31_HASH_EXT,
+	BL30_CONTENT_CERT_PK_EXT,
+	BL30_HASH_EXT,
+	BL32_CONTENT_CERT_PK_EXT,
+	BL32_HASH_EXT,
+	BL33_CONTENT_CERT_PK_EXT,
+	BL33_HASH_EXT
+};
 
 #endif /* TBB_EXT_H_ */
diff --git a/tools/cert_create/include/tbb_key.h b/tools/cert_create/include/tbbr/tbb_key.h
similarity index 95%
rename from tools/cert_create/include/tbb_key.h
rename to tools/cert_create/include/tbbr/tbb_key.h
index cc927d1..1590309 100644
--- a/tools/cert_create/include/tbb_key.h
+++ b/tools/cert_create/include/tbbr/tbb_key.h
@@ -43,13 +43,7 @@
 	BL30_KEY,
 	BL31_KEY,
 	BL32_KEY,
-	BL33_KEY,
-	NUM_KEYS
+	BL33_KEY
 };
 
-/*
- * 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
index 22fe3d5..e58b10e 100644
--- a/tools/cert_create/src/cert.c
+++ b/tools/cert_create/src/cert.c
@@ -98,9 +98,10 @@
 
 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;
+	EVP_PKEY *pkey = keys[cert->key].key;
+	cert_t *issuer_cert = &certs[cert->issuer];
+	EVP_PKEY *ikey = keys[issuer_cert->key].key;
+	X509 *issuer = issuer_cert->x;
 	X509 *x = NULL;
 	X509_EXTENSION *ex = NULL;
 	X509_NAME *name = NULL;
@@ -147,7 +148,7 @@
 	/* 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);
+			(const unsigned char *)issuer_cert->cn, -1, -1, 0);
 	X509_set_issuer_name(x, name);
 
 	/* Add various extensions: standard extensions */
diff --git a/tools/cert_create/src/ext.c b/tools/cert_create/src/ext.c
index 21b90db..6d09837 100644
--- a/tools/cert_create/src/ext.c
+++ b/tools/cert_create/src/ext.c
@@ -65,20 +65,20 @@
  *
  * Return: 0 = success, Otherwise: error
  */
-int ext_init(ext_t *tbb_ext)
+int ext_register(ext_t *exts)
 {
 	ext_t *ext;
 	X509V3_EXT_METHOD *m;
 	int i = 0, nid, ret;
 
-	while ((ext = &tbb_ext[i++]) && ext->oid) {
+	while ((ext = &exts[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) {
+			switch (ext->asn1_type) {
 			case V_ASN1_INTEGER:
 				m->it = ASN1_ITEM_ref(ASN1_INTEGER);
 				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER;
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index c78d87a..29bf452 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -46,9 +46,9 @@
 #include "key.h"
 #include "platform_oid.h"
 #include "sha.h"
-#include "tbb_ext.h"
-#include "tbb_cert.h"
-#include "tbb_key.h"
+#include "tbbr/tbb_ext.h"
+#include "tbbr/tbb_cert.h"
+#include "tbbr/tbb_key.h"
 
 /*
  * Helper macros to simplify the code. This macro assigns the return value of
@@ -79,7 +79,6 @@
 #define MAX_FILENAME_LEN		1024
 #define VAL_DAYS			7300
 #define ID_TO_BIT_MASK(id)		(1 << id)
-#define NVCOUNTER_VALUE			0
 #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
 
 /* Files */
@@ -120,11 +119,6 @@
 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[];
@@ -231,27 +225,27 @@
 	}
 
 	/* BL2, BL31 and BL33 are mandatory */
-	if (certs[BL2_CERT].bin == NULL) {
+	if (extensions[BL2_HASH_EXT].data.fn == NULL) {
 		ERROR("BL2 image not specified\n");
 		exit(1);
 	}
 
-	if (certs[BL31_CERT].bin == NULL) {
+	if (extensions[BL31_HASH_EXT].data.fn == NULL) {
 		ERROR("BL31 image not specified\n");
 		exit(1);
 	}
 
-	if (certs[BL33_CERT].bin == NULL) {
+	if (extensions[BL33_HASH_EXT].data.fn == NULL) {
 		ERROR("BL33 image not specified\n");
 		exit(1);
 	}
 
 	/* BL30 and BL32 are optional */
-	if (certs[BL30_CERT].bin != NULL) {
+	if (extensions[BL30_HASH_EXT].data.fn != NULL) {
 		bl30_present = 1;
 	}
 
-	if (certs[BL32_CERT].bin != NULL) {
+	if (extensions[BL32_HASH_EXT].data.fn != NULL) {
 		bl32_present = 1;
 	}
 
@@ -299,12 +293,11 @@
 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;
+	X509_EXTENSION *cert_ext = NULL;
+	ext_t *ext = NULL;
+	cert_t *cert;
 	FILE *file = NULL;
-	int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid;
+	int i, j, ext_nid;
 	int c, opt_idx = 0;
 	unsigned int err_code;
 	unsigned char md[SHA256_DIGEST_LENGTH];
@@ -346,19 +339,19 @@
 			print_cert = 1;
 			break;
 		case BL2_ID:
-			certs[BL2_CERT].bin = strdup(optarg);
+			extensions[BL2_HASH_EXT].data.fn = strdup(optarg);
 			break;
 		case BL30_ID:
-			certs[BL30_CERT].bin = strdup(optarg);
+			extensions[BL30_HASH_EXT].data.fn = strdup(optarg);
 			break;
 		case BL31_ID:
-			certs[BL31_CERT].bin = strdup(optarg);
+			extensions[BL31_HASH_EXT].data.fn = strdup(optarg);
 			break;
 		case BL32_ID:
-			certs[BL32_CERT].bin = strdup(optarg);
+			extensions[BL32_HASH_EXT].data.fn = strdup(optarg);
 			break;
 		case BL33_ID:
-			certs[BL33_CERT].bin = strdup(optarg);
+			extensions[BL33_HASH_EXT].data.fn = strdup(optarg);
 			break;
 		case BL2_CERT_ID:
 			certs[BL2_CERT].fn = strdup(optarg);
@@ -418,16 +411,12 @@
 		}
 	}
 
-	/* 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");
+	if (ext_register(extensions) != 0) {
+		ERROR("Cannot register TBB extensions\n");
 		exit(1);
 	}
 
@@ -435,12 +424,8 @@
 	 * extension */
 	md_info = EVP_sha256();
 
-	/* 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) */
-	for (i = 0 ; i < NUM_KEYS ; i++) {
+	for (i = 0 ; i < num_keys ; i++) {
 		/* First try to load the key from disk */
 		if (key_load(&keys[i], &err_code)) {
 			/* Key loaded successfully */
@@ -477,272 +462,74 @@
 			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_info, 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);
+	/* Create the certificates */
+	for (i = 0 ; i < num_certs ; i++) {
 
-	/* *********************************************************************
-	 * 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);
-	}
+		cert = &certs[i];
 
-	/* *********************************************************************
-	 * BL30 certificate (SCP Firmware Content certificate):
-	 *     - Signed with Trusted World Key
-	 *     - Extensions:
-	 *         - TrustedFirmwareNVCounter (TODO)
-	 *         - SCPFirmwareHash
-	 **********************************************************************/
-	if (bl30_present) {
+		/* Create a new stack of extensions. This stack will be used
+		 * to create the certificate */
 		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_info,
-				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);
-		}
+		for (j = 0 ; j < cert->num_ext ; j++) {
 
-		sk_X509_EXTENSION_free(sk);
-	}
+			ext = &extensions[cert->ext[j]];
 
-	/* *********************************************************************
-	 * 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);
+			/* Get OpenSSL internal ID for this extension */
+			CHECK_OID(ext_nid, ext->oid);
 
-	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_info, 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);
+			/*
+			 * Three types of extensions are currently supported:
+			 *     - EXT_TYPE_NVCOUNTER
+			 *     - EXT_TYPE_HASH
+			 *     - EXT_TYPE_PKEY
+			 */
+			switch (ext->type) {
+			case EXT_TYPE_NVCOUNTER:
+				CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
+						EXT_CRIT, ext->data.nvcounter));
+				break;
+			case EXT_TYPE_HASH:
+				if (ext->data.fn == NULL) {
+					break;
+				}
+				if (!sha_file(ext->data.fn, md)) {
+					ERROR("Cannot calculate hash of %s\n",
+						ext->data.fn);
+					exit(1);
+				}
+				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
+						EXT_CRIT, md_info, md,
+						SHA256_DIGEST_LENGTH));
+				break;
+			case EXT_TYPE_PKEY:
+				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
+					EXT_CRIT, keys[ext->data.key].key));
+				break;
+			default:
+				ERROR("Unknown extension type in %s\n",
+						cert->cn);
+				exit(1);
+			}
 
-		if (!sha_file(certs[BL32_CERT].bin, md)) {
-			ERROR("Cannot calculate the hash of %s\n",
-					certs[BL32_CERT].bin);
-			exit(1);
+			/* Push the extension into the stack */
+			sk_X509_EXTENSION_push(sk, cert_ext);
 		}
-		CHECK_OID(hash_nid, BL32_HASH_OID);
-		CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info,
-				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);
+		/* Create certificate. Signed with ROT key */
+		if (!cert_new(cert, VAL_DAYS, 0, sk)) {
+			ERROR("Cannot create %s\n", 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_info, 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++) {
+		for (i = 0 ; i < num_certs ; i++) {
 			if (!certs[i].x) {
 				continue;
 			}
@@ -752,7 +539,7 @@
 	}
 
 	/* Save created certificates to files */
-	for (i = 0 ; i < NUM_CERTIFICATES ; i++) {
+	for (i = 0 ; i < num_certs ; i++) {
 		if (certs[i].x && certs[i].fn) {
 			file = fopen(certs[i].fn, "w");
 			if (file != NULL) {
@@ -766,18 +553,13 @@
 
 	/* Save keys */
 	if (save_keys) {
-		for (i = 0 ; i < NUM_KEYS ; i++) {
+		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
diff --git a/tools/cert_create/src/tbb_cert.c b/tools/cert_create/src/tbbr/tbb_cert.c
similarity index 62%
rename from tools/cert_create/src/tbb_cert.c
rename to tools/cert_create/src/tbbr/tbb_cert.c
index 8dfda60..d0ae836 100644
--- a/tools/cert_create/src/tbb_cert.c
+++ b/tools/cert_create/src/tbbr/tbb_cert.c
@@ -28,84 +28,129 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "tbb_cert.h"
-#include "tbb_key.h"
+#include "tbbr/tbb_cert.h"
+#include "tbbr/tbb_ext.h"
+#include "tbbr/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.
+ * tbb_cert.h. All certificates are self-signed, so the issuer certificate
+ * field points to itself.
  */
-cert_t certs[NUM_CERTIFICATES] = {
-	{
+static cert_t tbb_certs[] = {
+	[BL2_CERT] = {
 		.id = BL2_CERT,
 		.fn = NULL,
 		.cn = "BL2 Certificate",
-		.key = &keys[ROT_KEY],
-		.issuer = &certs[BL2_CERT],
+		.key = ROT_KEY,
+		.issuer = BL2_CERT,
+		.ext = {
+			BL2_HASH_EXT
+		},
+		.num_ext = 1
 	},
-	{
+	[TRUSTED_KEY_CERT] = {
 		.id = TRUSTED_KEY_CERT,
 		.fn = NULL,
 		.cn = "Trusted Key Certificate",
-		.key = &keys[ROT_KEY],
-		.issuer = &certs[TRUSTED_KEY_CERT],
+		.key = ROT_KEY,
+		.issuer = TRUSTED_KEY_CERT,
+		.ext = {
+			TZ_WORLD_PK_EXT,
+			NTZ_WORLD_PK_EXT
+		},
+		.num_ext = 2
 	},
-	{
+	[BL30_KEY_CERT] = {
 		.id = BL30_KEY_CERT,
 		.fn = NULL,
 		.cn = "BL3-0 Key Certificate",
-		.key = &keys[TRUSTED_WORLD_KEY],
-		.issuer = &certs[BL30_KEY_CERT],
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = BL30_KEY_CERT,
+		.ext = {
+			BL30_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 1
 	},
-	{
+	[BL30_CERT] = {
 		.id = BL30_CERT,
 		.fn = NULL,
 		.cn = "BL3-0 Content Certificate",
-		.key = &keys[BL30_KEY],
-		.issuer = &certs[BL30_CERT],
+		.key = BL30_KEY,
+		.issuer = BL30_CERT,
+		.ext = {
+			BL30_HASH_EXT
+		},
+		.num_ext = 1
 	},
-	{
+	[BL31_KEY_CERT] = {
 		.id = BL31_KEY_CERT,
 		.fn = NULL,
 		.cn = "BL3-1 Key Certificate",
-		.key = &keys[TRUSTED_WORLD_KEY],
-		.issuer = &certs[BL31_KEY_CERT],
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = BL31_KEY_CERT,
+		.ext = {
+			BL31_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 1
 	},
-	{
+	[BL31_CERT] = {
 		.id = BL31_CERT,
 		.fn = NULL,
 		.cn = "BL3-1 Content Certificate",
-		.key = &keys[BL31_KEY],
-		.issuer = &certs[BL31_CERT],
+		.key = BL31_KEY,
+		.issuer = BL31_CERT,
+		.ext = {
+			BL31_HASH_EXT
+		},
+		.num_ext = 1
 	},
-	{
+	[BL32_KEY_CERT] = {
 		.id = BL32_KEY_CERT,
 		.fn = NULL,
 		.cn = "BL3-2 Key Certificate",
-		.key = &keys[TRUSTED_WORLD_KEY],
-		.issuer = &certs[BL32_KEY_CERT],
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = BL32_KEY_CERT,
+		.ext = {
+			BL32_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 1
 	},
-	{
+	[BL32_CERT] = {
 		.id = BL32_CERT,
 		.fn = NULL,
 		.cn = "BL3-2 Content Certificate",
-		.key = &keys[BL32_KEY],
-		.issuer = &certs[BL32_CERT],
+		.key = BL32_KEY,
+		.issuer = BL32_CERT,
+		.ext = {
+			BL32_HASH_EXT
+		},
+		.num_ext = 1
 	},
-	{
+	[BL33_KEY_CERT] = {
 		.id = BL33_KEY_CERT,
 		.fn = NULL,
 		.cn = "BL3-3 Key Certificate",
-		.key = &keys[NON_TRUSTED_WORLD_KEY],
-		.issuer = &certs[BL33_KEY_CERT],
+		.key = NON_TRUSTED_WORLD_KEY,
+		.issuer = BL33_KEY_CERT,
+		.ext = {
+			BL33_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 1
 	},
-	{
+	[BL33_CERT] = {
 		.id = BL33_CERT,
 		.fn = NULL,
 		.cn = "BL3-3 Content Certificate",
-		.key = &keys[BL33_KEY],
-		.issuer = &certs[BL33_CERT],
+		.key = BL33_KEY,
+		.issuer = BL33_CERT,
+		.ext = {
+			BL33_HASH_EXT
+		},
+		.num_ext = 1
 	}
 };
+
+REGISTER_COT(tbb_certs);
diff --git a/tools/cert_create/src/tbb_ext.c b/tools/cert_create/src/tbbr/tbb_ext.c
similarity index 61%
rename from tools/cert_create/src/tbb_ext.c
rename to tools/cert_create/src/tbbr/tbb_ext.c
index 0022611..c4816df 100644
--- a/tools/cert_create/src/tbb_ext.c
+++ b/tools/cert_create/src/tbbr/tbb_ext.c
@@ -34,85 +34,113 @@
 #include <openssl/x509v3.h>
 #include "ext.h"
 #include "platform_oid.h"
+#include "tbbr/tbb_ext.h"
+#include "tbbr/tbb_key.h"
 
-ext_t tbb_ext[] = {
-	{
+/* TODO: get these values from the command line */
+#define TRUSTED_WORLD_NVCTR_VALUE	0
+#define NORMAL_WORLD_NVCTR_VALUE	0
+
+static ext_t tbb_ext[] = {
+	[TZ_FW_NVCOUNTER_EXT] = {
 		.oid = TZ_FW_NVCOUNTER_OID,
-		.sn = "TrustedNvCounter",
-		.ln = "Non-volatile trusted counter",
-		.type = V_ASN1_INTEGER
+		.sn = "TrustedWorldNVCounter",
+		.ln = "Trusted World Non-Volatile counter",
+		.asn1_type = V_ASN1_INTEGER,
+		.type = EXT_TYPE_NVCOUNTER,
+		.data.nvcounter = TRUSTED_WORLD_NVCTR_VALUE
 	},
-	{
+	[NTZ_FW_NVCOUNTER_EXT] = {
 		.oid = NTZ_FW_NVCOUNTER_OID,
-		.sn = "NonTrustedNvCounter",
-		.ln = "Non-volatile non-trusted counter",
-		.type = V_ASN1_INTEGER
+		.sn = "NormalWorldNVCounter",
+		.ln = "Normal World Non-Volatile counter",
+		.asn1_type = V_ASN1_INTEGER,
+		.type = EXT_TYPE_NVCOUNTER,
+		.data.nvcounter = NORMAL_WORLD_NVCTR_VALUE
 	},
-	{
+	[BL2_HASH_EXT] = {
 		.oid = BL2_HASH_OID,
 		.sn = "TrustedBootFirmwareHash",
 		.ln = "Trusted Boot Firmware (BL2) hash (SHA256)",
-		.type = V_ASN1_OCTET_STRING
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
 	},
-	{
+	[TZ_WORLD_PK_EXT] = {
 		.oid = TZ_WORLD_PK_OID,
 		.sn = "TrustedWorldPublicKey",
 		.ln = "Trusted World Public Key",
-		.type = V_ASN1_OCTET_STRING
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.data.key = TRUSTED_WORLD_KEY
 	},
-	{
+	[NTZ_WORLD_PK_EXT] = {
 		.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
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.data.key = NON_TRUSTED_WORLD_KEY
 	},
-	{
+	[BL30_CONTENT_CERT_PK_EXT] = {
 		.oid = BL30_CONTENT_CERT_PK_OID,
 		.sn = "SCPFirmwareContentCertPK",
 		.ln = "SCP Firmware content certificate public key",
-		.type = V_ASN1_OCTET_STRING
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.data.key = BL30_KEY
 	},
-	{
+	[BL30_HASH_EXT] = {
 		.oid = BL30_HASH_OID,
 		.sn = "SCPFirmwareHash",
 		.ln = "SCP Firmware (BL30) hash (SHA256)",
-		.type = V_ASN1_OCTET_STRING
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
 	},
-	{
+	[BL31_CONTENT_CERT_PK_EXT] = {
+		.oid = BL31_CONTENT_CERT_PK_OID,
+		.sn = "SoCFirmwareContentCertPK",
+		.ln = "SoC Firmware content certificate public key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.data.key = BL31_KEY
+	},
+	[BL31_HASH_EXT] = {
+		.oid = BL31_HASH_OID,
+		.sn = "SoCAPFirmwareHash",
+		.ln = "SoC AP Firmware (BL31) hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+	[BL32_CONTENT_CERT_PK_EXT] = {
 		.oid = BL32_CONTENT_CERT_PK_OID,
 		.sn = "TrustedOSFirmwareContentCertPK",
 		.ln = "Trusted OS Firmware content certificate public key",
-		.type = V_ASN1_OCTET_STRING
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.data.key = BL32_KEY
 	},
-	{
+	[BL32_HASH_EXT] = {
 		.oid = BL32_HASH_OID,
 		.sn = "TrustedOSHash",
 		.ln = "Trusted OS (BL32) hash (SHA256)",
-		.type = V_ASN1_OCTET_STRING
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
 	},
-	{
+	[BL33_CONTENT_CERT_PK_EXT] = {
 		.oid = BL33_CONTENT_CERT_PK_OID,
 		.sn = "NonTrustedFirmwareContentCertPK",
 		.ln = "Non-Trusted Firmware content certificate public key",
-		.type = V_ASN1_OCTET_STRING
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.data.key = BL33_KEY
 	},
-	{
+	[BL33_HASH_EXT] = {
 		.oid = BL33_HASH_OID,
 		.sn = "NonTrustedWorldBootloaderHash",
 		.ln = "Non-Trusted World (BL33) hash (SHA256)",
-		.type = V_ASN1_OCTET_STRING
-	},
-	{ 0, 0, 0, 0 }
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	}
 };
+
+REGISTER_EXTENSIONS(tbb_ext);
diff --git a/tools/cert_create/src/tbb_key.c b/tools/cert_create/src/tbbr/tbb_key.c
similarity index 90%
rename from tools/cert_create/src/tbb_key.c
rename to tools/cert_create/src/tbbr/tbb_key.c
index 140aeda..3685559 100644
--- a/tools/cert_create/src/tbb_key.c
+++ b/tools/cert_create/src/tbbr/tbb_key.c
@@ -28,40 +28,42 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "tbb_key.h"
+#include "tbbr/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] = {
-	{
+static key_t tbb_keys[] = {
+	[ROT_KEY] = {
 		.id = ROT_KEY,
 		.desc = "Root Of Trust key"
 	},
-	{
+	[TRUSTED_WORLD_KEY] = {
 		.id = TRUSTED_WORLD_KEY,
 		.desc = "Trusted World key"
 	},
-	{
+	[NON_TRUSTED_WORLD_KEY] = {
 		.id = NON_TRUSTED_WORLD_KEY,
 		.desc = "Non Trusted World key"
 	},
-	{
+	[BL30_KEY] = {
 		.id = BL30_KEY,
 		.desc = "BL30 key"
 	},
-	{
+	[BL31_KEY] = {
 		.id = BL31_KEY,
 		.desc = "BL31 key"
 	},
-	{
+	[BL32_KEY] = {
 		.id = BL32_KEY,
 		.desc = "BL32 key"
 	},
-	{
+	[BL33_KEY] = {
 		.id = BL33_KEY,
 		.desc = "BL33 key"
 	}
 };
+
+REGISTER_KEYS(tbb_keys);