summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authordanh-arm <dan.handley@arm.com>2015-06-25 09:45:53 +0100
committerdanh-arm <dan.handley@arm.com>2015-06-25 09:45:53 +0100
commit84f95bed549eab4ca40fbd0505e0e3720384880c (patch)
tree024e625474533cb0bd8928dae8321be9060736db /drivers
parentdba12894030db45c495643e4320365dd8f0e6f68 (diff)
parentd337aaaf53ef27897f52e66718a2741399c8a021 (diff)
Merge pull request #315 from jcastillo-arm/jc/tbb_tmp9
Authentication Framework
Diffstat (limited to 'drivers')
-rw-r--r--drivers/auth/auth_mod.c348
-rw-r--r--drivers/auth/crypto_mod.c129
-rw-r--r--drivers/auth/img_parser_mod.c151
-rw-r--r--drivers/auth/mbedtls/mbedtls_common.c65
-rw-r--r--drivers/auth/mbedtls/mbedtls_common.mk60
-rw-r--r--drivers/auth/mbedtls/mbedtls_crypto.c229
-rw-r--r--drivers/auth/mbedtls/mbedtls_crypto.mk72
-rw-r--r--drivers/auth/mbedtls/mbedtls_x509.mk40
-rw-r--r--drivers/auth/mbedtls/mbedtls_x509_parser.c438
-rw-r--r--drivers/auth/tbbr/tbbr_cot.c445
-rw-r--r--drivers/io/io_fip.c78
11 files changed, 1985 insertions, 70 deletions
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
new file mode 100644
index 00000000..bdd3c5a1
--- /dev/null
+++ b/drivers/auth/auth_mod.c
@@ -0,0 +1,348 @@
+/*
+ * 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_common.h>
+#include <auth_mod.h>
+#include <cot_def.h>
+#include <crypto_mod.h>
+#include <debug.h>
+#include <img_parser_mod.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <string.h>
+
+#define return_if_error(rc) \
+ do { \
+ if (rc != 0) { \
+ return rc; \
+ } \
+ } while (0)
+
+/* Pointer to CoT */
+extern const auth_img_desc_t *const cot_desc_ptr;
+extern unsigned int auth_img_flags[];
+
+static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a,
+ const auth_param_type_desc_t *b)
+{
+ if ((a->type == b->type) && (a->cookie == b->cookie)) {
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * This function obtains the requested authentication parameter data from the
+ * information extracted from the parent image after its authentication.
+ */
+static int auth_get_param(const auth_param_type_desc_t *param_type_desc,
+ const auth_img_desc_t *img_desc,
+ void **param, unsigned int *len)
+{
+ int i;
+
+ for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) {
+ if (0 == cmp_auth_param_type_desc(param_type_desc,
+ img_desc->authenticated_data[i].type_desc)) {
+ *param = img_desc->authenticated_data[i].data.ptr;
+ *len = img_desc->authenticated_data[i].data.len;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Authenticate an image by matching the data hash
+ *
+ * This function implements 'AUTH_METHOD_HASH'. To authenticate an image using
+ * this method, the image must contain:
+ *
+ * - The data to calculate the hash from
+ *
+ * The parent image must contain:
+ *
+ * - The hash to be matched with (including hash algorithm)
+ *
+ * For a successful authentication, both hashes must match. The function calls
+ * the crypto-module to check this matching.
+ *
+ * Parameters:
+ * param: parameters to perform the hash authentication
+ * img_desc: pointer to image descriptor so we can know the image type
+ * and parent image
+ * img: pointer to image in memory
+ * img_len: length of image (in bytes)
+ *
+ * Return:
+ * 0 = success, Otherwise = error
+ */
+static int auth_hash(const auth_method_param_hash_t *param,
+ const auth_img_desc_t *img_desc,
+ void *img, unsigned int img_len)
+{
+ void *data_ptr, *hash_der_ptr;
+ unsigned int data_len, hash_der_len;
+ int rc = 0;
+
+ /* Get the hash from the parent image. This hash will be DER encoded
+ * and contain the hash algorithm */
+ rc = auth_get_param(param->hash, img_desc->parent,
+ &hash_der_ptr, &hash_der_len);
+ return_if_error(rc);
+
+ /* Get the data to be hashed from the current image */
+ rc = img_parser_get_auth_param(img_desc->img_type, param->data,
+ img, img_len, &data_ptr, &data_len);
+ return_if_error(rc);
+
+ /* Ask the crypto module to verify this hash */
+ rc = crypto_mod_verify_hash(data_ptr, data_len,
+ hash_der_ptr, hash_der_len);
+
+ return rc;
+}
+
+/*
+ * Authenticate by digital signature
+ *
+ * This function implements 'AUTH_METHOD_SIG'. To authenticate an image using
+ * this method, the image must contain:
+ *
+ * - Data to be signed
+ * - Signature
+ * - Signature algorithm
+ *
+ * We rely on the image parser module to extract this data from the image.
+ * The parent image must contain:
+ *
+ * - Public key (or a hash of it)
+ *
+ * If the parent image contains only a hash of the key, we will try to obtain
+ * the public key from the image itself (i.e. self-signed certificates). In that
+ * case, the signature verification is considered just an integrity check and
+ * the authentication is established by calculating the hash of the key and
+ * comparing it with the hash obtained from the parent.
+ *
+ * If the image has no parent (NULL), it means it has to be authenticated using
+ * the ROTPK stored in the platform. Again, this ROTPK could be the key itself
+ * or a hash of it.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+static int auth_signature(const auth_method_param_sig_t *param,
+ const auth_img_desc_t *img_desc,
+ void *img, unsigned int img_len)
+{
+ void *data_ptr, *pk_ptr, *pk_hash_ptr, *sig_ptr, *sig_alg_ptr;
+ unsigned int data_len, pk_len, pk_hash_len, sig_len, sig_alg_len;
+ unsigned int flags = 0;
+ int rc = 0;
+
+ /* Get the data to be signed from current image */
+ rc = img_parser_get_auth_param(img_desc->img_type, param->data,
+ img, img_len, &data_ptr, &data_len);
+ return_if_error(rc);
+
+ /* Get the signature from current image */
+ rc = img_parser_get_auth_param(img_desc->img_type, param->sig,
+ img, img_len, &sig_ptr, &sig_len);
+ return_if_error(rc);
+
+ /* Get the signature algorithm from current image */
+ rc = img_parser_get_auth_param(img_desc->img_type, param->alg,
+ img, img_len, &sig_alg_ptr, &sig_alg_len);
+ return_if_error(rc);
+
+ /* Get the public key from the parent. If there is no parent (NULL),
+ * the certificate has been signed with the ROTPK, so we have to get
+ * the PK from the platform */
+ if (img_desc->parent) {
+ rc = auth_get_param(param->pk, img_desc->parent,
+ &pk_ptr, &pk_len);
+ } else {
+ rc = plat_get_rotpk_info(param->pk->cookie, &pk_ptr, &pk_len,
+ &flags);
+ }
+ return_if_error(rc);
+
+ /* If the PK is a hash of the key, retrieve the key from the image */
+ if (flags & ROTPK_IS_HASH) {
+ pk_hash_ptr = pk_ptr;
+ pk_hash_len = pk_len;
+ rc = img_parser_get_auth_param(img_desc->img_type,
+ param->pk, img, img_len,
+ &pk_ptr, &pk_len);
+ return_if_error(rc);
+
+ /* Ask the crypto module to verify the signature */
+ rc = crypto_mod_verify_signature(data_ptr, data_len,
+ sig_ptr, sig_len,
+ sig_alg_ptr, sig_alg_len,
+ pk_ptr, pk_len);
+ return_if_error(rc);
+
+ /* Ask the crypto-module to verify the key hash */
+ rc = crypto_mod_verify_hash(pk_ptr, pk_len,
+ pk_hash_ptr, pk_hash_len);
+ } else {
+ /* Ask the crypto module to verify the signature */
+ rc = crypto_mod_verify_signature(data_ptr, data_len,
+ sig_ptr, sig_len,
+ sig_alg_ptr, sig_alg_len,
+ pk_ptr, pk_len);
+ }
+
+ return rc;
+}
+
+/*
+ * Return the parent id in the output parameter '*parent_id'
+ *
+ * Return value:
+ * 0 = Image has parent, 1 = Image has no parent or parent is authenticated
+ */
+int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id)
+{
+ const auth_img_desc_t *img_desc = NULL;
+
+ assert(parent_id != NULL);
+
+ /* Get the image descriptor */
+ img_desc = &cot_desc_ptr[img_id];
+
+ /* Check if the image has no parent (ROT) */
+ if (img_desc->parent == NULL) {
+ *parent_id = 0;
+ return 1;
+ }
+
+ /* Check if the parent has already been authenticated */
+ if (auth_img_flags[img_desc->parent->img_id] & IMG_FLAG_AUTHENTICATED) {
+ *parent_id = 0;
+ return 1;
+ }
+
+ *parent_id = img_desc->parent->img_id;
+ return 0;
+}
+
+/*
+ * Initialize the different modules in the authentication framework
+ */
+void auth_mod_init(void)
+{
+ /* Check we have a valid CoT registered */
+ assert(cot_desc_ptr != NULL);
+
+ /* Crypto module */
+ crypto_mod_init();
+
+ /* Image parser module */
+ img_parser_init();
+}
+
+/*
+ * Authenticate a certificate/image
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int auth_mod_verify_img(unsigned int img_id,
+ void *img_ptr,
+ unsigned int img_len)
+{
+ const auth_img_desc_t *img_desc = NULL;
+ const auth_method_desc_t *auth_method = NULL;
+ void *param_ptr;
+ unsigned int param_len;
+ int rc, i;
+
+ /* Get the image descriptor from the chain of trust */
+ img_desc = &cot_desc_ptr[img_id];
+
+ /* Ask the parser to check the image integrity */
+ rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len);
+ return_if_error(rc);
+
+ /* Authenticate the image using the methods indicated in the image
+ * descriptor. */
+ for (i = 0 ; i < AUTH_METHOD_NUM ; i++) {
+ auth_method = &img_desc->img_auth_methods[i];
+ switch (auth_method->type) {
+ case AUTH_METHOD_NONE:
+ rc = 0;
+ break;
+ case AUTH_METHOD_HASH:
+ rc = auth_hash(&auth_method->param.hash,
+ img_desc, img_ptr, img_len);
+ break;
+ case AUTH_METHOD_SIG:
+ rc = auth_signature(&auth_method->param.sig,
+ img_desc, img_ptr, img_len);
+ break;
+ default:
+ /* Unknown authentication method */
+ rc = 1;
+ break;
+ }
+ return_if_error(rc);
+ }
+
+ /* Extract the parameters indicated in the image descriptor to
+ * authenticate the children images. */
+ for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) {
+ if (img_desc->authenticated_data[i].type_desc == NULL) {
+ continue;
+ }
+
+ /* Get the parameter from the image parser module */
+ rc = img_parser_get_auth_param(img_desc->img_type,
+ img_desc->authenticated_data[i].type_desc,
+ img_ptr, img_len, &param_ptr, &param_len);
+ return_if_error(rc);
+
+ /* Check parameter size */
+ if (param_len > img_desc->authenticated_data[i].data.len) {
+ return 1;
+ }
+
+ /* Copy the parameter for later use */
+ memcpy((void *)img_desc->authenticated_data[i].data.ptr,
+ (void *)param_ptr, param_len);
+ }
+
+ /* Mark image as authenticated */
+ auth_img_flags[img_desc->img_id] |= IMG_FLAG_AUTHENTICATED;
+
+ return 0;
+}
diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c
new file mode 100644
index 00000000..b432e6a7
--- /dev/null
+++ b/drivers/auth/crypto_mod.c
@@ -0,0 +1,129 @@
+/*
+ * 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 <crypto_mod.h>
+#include <debug.h>
+
+/* Variable exported by the crypto library through REGISTER_CRYPTO_LIB() */
+extern const crypto_lib_desc_t crypto_lib_desc;
+
+/*
+ * The crypto module is responsible for verifying digital signatures and hashes.
+ * It relies on a crypto library to perform the cryptographic operations.
+ *
+ * The crypto module itself does not impose any specific format on signatures,
+ * signature algorithm, keys or hashes, but most cryptographic libraries will
+ * take the parameters as the following DER encoded ASN.1 structures:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ *
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ *
+ * SignatureAlgorithm ::= AlgorithmIdentifier
+ *
+ * SignatureValue ::= BIT STRING
+ */
+
+/*
+ * Perform some static checking and call the library initialization function
+ */
+void crypto_mod_init(void)
+{
+ assert(crypto_lib_desc.name != NULL);
+ assert(crypto_lib_desc.init != NULL);
+ assert(crypto_lib_desc.verify_signature != NULL);
+ assert(crypto_lib_desc.verify_hash != NULL);
+
+ /* Initialize the cryptographic library */
+ crypto_lib_desc.init();
+ INFO("Using crypto library '%s'\n", crypto_lib_desc.name);
+}
+
+/*
+ * Function to verify a digital signature
+ *
+ * Parameters:
+ *
+ * data_ptr, data_len: signed data
+ * sig_ptr, sig_len: the digital signature
+ * sig_alg_ptr, sig_alg_len: the digital signature algorithm
+ * pk_ptr, pk_len: the public key
+ */
+int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len,
+ void *sig_ptr, unsigned int sig_len,
+ void *sig_alg_ptr, unsigned int sig_alg_len,
+ void *pk_ptr, unsigned int pk_len)
+{
+ assert(data_ptr != NULL);
+ assert(data_len != 0);
+ assert(sig_ptr != NULL);
+ assert(sig_len != 0);
+ assert(sig_alg_ptr != NULL);
+ assert(sig_alg_len != 0);
+ assert(pk_ptr != NULL);
+ assert(pk_len != 0);
+
+ return crypto_lib_desc.verify_signature(data_ptr, data_len,
+ sig_ptr, sig_len,
+ sig_alg_ptr, sig_alg_len,
+ pk_ptr, pk_len);
+}
+
+/*
+ * Verify a hash by comparison
+ *
+ * Parameters:
+ *
+ * data_ptr, data_len: data to be hashed
+ * digest_info_ptr, digest_info_len: hash to be compared
+ */
+int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len,
+ void *digest_info_ptr, unsigned int digest_info_len)
+{
+ assert(data_ptr != NULL);
+ assert(data_len != 0);
+ assert(digest_info_ptr != NULL);
+ assert(digest_info_len != 0);
+
+ return crypto_lib_desc.verify_hash(data_ptr, data_len,
+ digest_info_ptr, digest_info_len);
+}
diff --git a/drivers/auth/img_parser_mod.c b/drivers/auth/img_parser_mod.c
new file mode 100644
index 00000000..c8cbe340
--- /dev/null
+++ b/drivers/auth/img_parser_mod.c
@@ -0,0 +1,151 @@
+/*
+ * 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_common.h>
+#include <debug.h>
+#include <errno.h>
+#include <img_parser_mod.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+
+extern uintptr_t __PARSER_LIB_DESCS_START__;
+extern uintptr_t __PARSER_LIB_DESCS_END__;
+#define PARSER_LIB_DESCS_START ((uintptr_t) (&__PARSER_LIB_DESCS_START__))
+#define PARSER_LIB_DESCS_END ((uintptr_t) (&__PARSER_LIB_DESCS_END__))
+static unsigned int parser_lib_indices[IMG_MAX_TYPES];
+static img_parser_lib_desc_t *parser_lib_descs;
+
+#define INVALID_IDX UINT_MAX
+
+static void validate_desc(img_parser_lib_desc_t *desc)
+{
+ assert(desc != NULL);
+ assert(desc->init != NULL);
+ assert(desc->name != NULL);
+ assert(desc->check_integrity != NULL);
+ assert(desc->get_auth_param != NULL);
+}
+
+void img_parser_init(void)
+{
+ unsigned int index, mod_num;
+
+ /* Initialise internal variables to invalid state */
+ for (index = 0; index < IMG_MAX_TYPES; index++) {
+ parser_lib_indices[index] = INVALID_IDX;
+ }
+
+ /* Calculate how many image parsers are registered. At least one parser
+ * must be present */
+ mod_num = PARSER_LIB_DESCS_END - PARSER_LIB_DESCS_START;
+ mod_num /= sizeof(img_parser_lib_desc_t);
+ assert(mod_num > 0);
+
+ parser_lib_descs = (img_parser_lib_desc_t *) PARSER_LIB_DESCS_START;
+ for (index = 0; index < mod_num; index++) {
+
+ /* Check that the image parser library descriptor is valid */
+ validate_desc(&parser_lib_descs[index]);
+
+ /* Initialize image parser */
+ parser_lib_descs[index].init();
+
+ /* Ensure only one parser is registered for each image type */
+ assert(parser_lib_indices[parser_lib_descs[index].img_type] ==
+ INVALID_IDX);
+
+ /* Keep the index of this hash calculator */
+ parser_lib_indices[parser_lib_descs[index].img_type] = index;
+ }
+}
+
+int img_parser_check_integrity(img_type_t img_type,
+ void *img_ptr, unsigned int img_len)
+{
+ unsigned int idx;
+
+ assert(img_ptr != NULL);
+ assert(img_len != 0);
+
+ /* No integrity checks on raw images */
+ if (img_type == IMG_RAW) {
+ return IMG_PARSER_OK;
+ }
+
+ /* Find the index of the required image parser */
+ idx = parser_lib_indices[img_type];
+ assert(idx != INVALID_IDX);
+
+ /* Call the function to check the image integrity */
+ return parser_lib_descs[idx].check_integrity(img_ptr, img_len);
+}
+
+/*
+ * Extract an authentication parameter from an image
+ *
+ * Parameters:
+ * img_type: image type (certificate, raw image, etc)
+ * type_desc: provides info to obtain the parameter
+ * img_ptr: pointer to image data
+ * img_len: image length
+ * param_ptr: [out] stores a pointer to the parameter
+ * param_len: [out] stores the length of the parameter
+ */
+int img_parser_get_auth_param(img_type_t img_type,
+ const auth_param_type_desc_t *type_desc,
+ void *img_ptr, unsigned int img_len,
+ void **param_ptr, unsigned int *param_len)
+{
+ unsigned int idx;
+
+ assert(type_desc != NULL);
+ assert(img_ptr != NULL);
+ assert(img_len != 0);
+ assert(param_ptr != NULL);
+ assert(param_len != NULL);
+
+ /* In a raw image we can only get the data itself */
+ if (img_type == IMG_RAW) {
+ assert(type_desc->type == AUTH_PARAM_RAW_DATA);
+ *param_ptr = img_ptr;
+ *param_len = img_len;
+ return IMG_PARSER_OK;
+ }
+
+ /* Find the index of the required image parser library */
+ idx = parser_lib_indices[img_type];
+ assert(idx != INVALID_IDX);
+
+ /* Call the function to obtain the parameter */
+ return parser_lib_descs[idx].get_auth_param(type_desc, img_ptr, img_len,
+ param_ptr, param_len);
+}
diff --git a/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c
new file mode 100644
index 00000000..29782609
--- /dev/null
+++ b/drivers/auth/mbedtls/mbedtls_common.c
@@ -0,0 +1,65 @@
+/*
+ * 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>
+
+/* mbedTLS headers */
+#include <polarssl/memory_buffer_alloc.h>
+
+/*
+ * mbedTLS heap
+ */
+#if (MBEDTLS_KEY_ALG_ID == MBEDTLS_ECDSA)
+#define MBEDTLS_HEAP_SIZE (14*1024)
+#elif (MBEDTLS_KEY_ALG_ID == MBEDTLS_RSA)
+#define MBEDTLS_HEAP_SIZE (8*1024)
+#endif
+static unsigned char heap[MBEDTLS_HEAP_SIZE];
+
+/*
+ * mbedTLS initialization function
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+void mbedtls_init(void)
+{
+ static int ready;
+ int rc;
+
+ if (!ready) {
+ /* Initialize the mbedTLS heap */
+ rc = memory_buffer_alloc_init(heap, MBEDTLS_HEAP_SIZE);
+ if (rc == 0) {
+ ready = 1;
+ } else {
+ assert(0);
+ }
+ }
+}
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
new file mode 100644
index 00000000..b71bbc96
--- /dev/null
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -0,0 +1,60 @@
+#
+# 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.
+#
+
+ifneq (${MBEDTLS_COMMON_MK},1)
+MBEDTLS_COMMON_MK := 1
+
+# MBEDTLS_DIR must be set to the mbedTLS main directory (it must contain
+# the 'include' and 'library' subdirectories).
+ifeq (${MBEDTLS_DIR},)
+ $(error Error: MBEDTLS_DIR not set)
+endif
+
+INCLUDES += -I${MBEDTLS_DIR}/include \
+ -Iinclude/drivers/auth/mbedtls
+
+# Specify mbedTLS configuration file
+POLARSSL_CONFIG_FILE := "<mbedtls_config.h>"
+$(eval $(call add_define,POLARSSL_CONFIG_FILE))
+
+MBEDTLS_COMMON_SOURCES := drivers/auth/mbedtls/mbedtls_common.c \
+ $(addprefix ${MBEDTLS_DIR}/library/, \
+ asn1parse.c \
+ asn1write.c \
+ memory_buffer_alloc.c \
+ oid.c \
+ platform.c \
+ )
+
+BL1_SOURCES += ${MBEDTLS_COMMON_SOURCES}
+BL2_SOURCES += ${MBEDTLS_COMMON_SOURCES}
+DISABLE_PEDANTIC := 1
+
+endif
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c
new file mode 100644
index 00000000..f69f9308
--- /dev/null
+++ b/drivers/auth/mbedtls/mbedtls_crypto.c
@@ -0,0 +1,229 @@
+/*
+ * 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 <crypto_mod.h>
+#include <debug.h>
+#include <mbedtls_common.h>
+#include <stddef.h>
+#include <string.h>
+
+/* mbedTLS headers */
+#include <polarssl/md_wrap.h>
+#include <polarssl/memory_buffer_alloc.h>
+#include <polarssl/oid.h>
+#include <polarssl/platform.h>
+
+#define LIB_NAME "mbedTLS"
+
+/*
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+
+/*
+ * Initialize the library and export the descriptor
+ */
+static void init(void)
+{
+ /* Initialize mbedTLS */
+ mbedtls_init();
+}
+
+/*
+ * Verify a signature.
+ *
+ * Parameters are passed using the DER encoding format following the ASN.1
+ * structures detailed above.
+ */
+static int verify_signature(void *data_ptr, unsigned int data_len,
+ void *sig_ptr, unsigned int sig_len,
+ void *sig_alg, unsigned int sig_alg_len,
+ void *pk_ptr, unsigned int pk_len)
+{
+ asn1_buf sig_oid, sig_params;
+ asn1_buf signature;
+ md_type_t md_alg;
+ pk_type_t pk_alg;
+ pk_context pk;
+ int rc;
+ void *sig_opts = NULL;
+ const md_info_t *md_info;
+ unsigned char *p, *end;
+ unsigned char hash[POLARSSL_MD_MAX_SIZE];
+
+ /* Get pointers to signature OID and parameters */
+ p = (unsigned char *)sig_alg;
+ end = (unsigned char *)(p + sig_alg_len);
+ rc = asn1_get_alg(&p, end, &sig_oid, &sig_params);
+ if (rc != 0) {
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /* Get the actual signature algorithm (MD + PK) */
+ rc = oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
+ if (rc != 0) {
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /* Parse the public key */
+ pk_init(&pk);
+ p = (unsigned char *)pk_ptr;
+ end = (unsigned char *)(p + pk_len);
+ rc = pk_parse_subpubkey(&p, end, &pk);
+ if (rc != 0) {
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /* Get the signature (bitstring) */
+ p = (unsigned char *)sig_ptr;
+ end = (unsigned char *)(p + sig_len);
+ signature.tag = *p;
+ rc = asn1_get_bitstring_null(&p, end, &signature.len);
+ if (rc != 0) {
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end;
+ }
+ signature.p = p;
+
+ /* Calculate the hash of the data */
+ md_info = md_info_from_type(md_alg);
+ if (md_info == NULL) {
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end;
+ }
+ p = (unsigned char *)data_ptr;
+ rc = md(md_info, p, data_len, hash);
+ if (rc != 0) {
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end;
+ }
+
+ /* Verify the signature */
+ rc = pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
+ md_info->size, signature.p, signature.len);
+ if (rc != 0) {
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end;
+ }
+
+ /* Signature verification success */
+ rc = CRYPTO_SUCCESS;
+
+end:
+ pk_free(&pk);
+ return rc;
+}
+
+/*
+ * Match a hash
+ *
+ * Digest info is passed in DER format following the ASN.1 structure detailed
+ * above.
+ */
+static int verify_hash(void *data_ptr, unsigned int data_len,
+ void *digest_info_ptr, unsigned int digest_info_len)
+{
+ asn1_buf hash_oid, params;
+ md_type_t md_alg;
+ const md_info_t *md_info;
+ unsigned char *p, *end, *hash;
+ unsigned char data_hash[POLARSSL_MD_MAX_SIZE];
+ size_t len;
+ int rc;
+
+ /* Digest info should be an ASN1_SEQUENCE */
+ p = (unsigned char *)digest_info_ptr;
+ end = (unsigned char *)(digest_info_ptr + digest_info_len);
+ rc = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (rc != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ /* Get the hash algorithm */
+ rc = asn1_get_alg(&p, end, &hash_oid, &params);
+ if (rc != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ rc = oid_get_md_alg(&hash_oid, &md_alg);
+ if (rc != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ md_info = md_info_from_type(md_alg);
+ if (md_info == NULL) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ /* Hash should be octet string type */
+ rc = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING);
+ if (rc != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ /* Length of hash must match the algorithm's size */
+ if (len != md_info->size) {
+ return CRYPTO_ERR_HASH;
+ }
+ hash = p;
+
+ /* Calculate the hash of the data */
+ p = (unsigned char *)data_ptr;
+ rc = md(md_info, p, data_len, data_hash);
+ if (rc != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ /* Compare values */
+ rc = memcmp(data_hash, hash, md_info->size);
+ if (rc != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ return CRYPTO_SUCCESS;
+}
+
+/*
+ * Register crypto library descriptor
+ */
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.mk b/drivers/auth/mbedtls/mbedtls_crypto.mk
new file mode 100644
index 00000000..67d2eb46
--- /dev/null
+++ b/drivers/auth/mbedtls/mbedtls_crypto.mk
@@ -0,0 +1,72 @@
+#
+# 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 drivers/auth/mbedtls/mbedtls_common.mk
+
+# The platform may define the variable 'MBEDTLS_KEY_ALG' to select the key
+# algorithm to use. Default algorithm is ECDSA.
+ifeq (${MBEDTLS_KEY_ALG},)
+ MBEDTLS_KEY_ALG := rsa
+endif
+
+MBEDTLS_CRYPTO_SOURCES := drivers/auth/mbedtls/mbedtls_crypto.c \
+ $(addprefix ${MBEDTLS_DIR}/library/, \
+ bignum.c \
+ md.c \
+ md_wrap.c \
+ pk.c \
+ pk_wrap.c \
+ pkparse.c \
+ pkwrite.c \
+ sha256.c \
+ )
+
+# Key algorithm specific files
+ifeq (${MBEDTLS_KEY_ALG},ecdsa)
+ MBEDTLS_CRYPTO_SOURCES += $(addprefix ${MBEDTLS_DIR}/library/, \
+ ecdsa.c \
+ ecp_curves.c \
+ ecp.c \
+ )
+ MBEDTLS_KEY_ALG_ID := MBEDTLS_ECDSA
+else ifeq (${MBEDTLS_KEY_ALG},rsa)
+ MBEDTLS_CRYPTO_SOURCES += $(addprefix ${MBEDTLS_DIR}/library/, \
+ rsa.c \
+ )
+ MBEDTLS_KEY_ALG_ID := MBEDTLS_RSA
+else
+ $(error "MBEDTLS_KEY_ALG=${MBEDTLS_KEY_ALG} not supported on mbedTLS")
+endif
+
+# mbedTLS libraries rely on this define to build correctly
+$(eval $(call add_define,MBEDTLS_KEY_ALG_ID))
+
+BL1_SOURCES += ${MBEDTLS_CRYPTO_SOURCES}
+BL2_SOURCES += ${MBEDTLS_CRYPTO_SOURCES}
diff --git a/drivers/auth/mbedtls/mbedtls_x509.mk b/drivers/auth/mbedtls/mbedtls_x509.mk
new file mode 100644
index 00000000..3f9420df
--- /dev/null
+++ b/drivers/auth/mbedtls/mbedtls_x509.mk
@@ -0,0 +1,40 @@
+#
+# 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 drivers/auth/mbedtls/mbedtls_common.mk
+
+MBEDTLS_X509_SOURCES := drivers/auth/mbedtls/mbedtls_x509_parser.c \
+ $(addprefix ${MBEDTLS_DIR}/library/, \
+ x509.c \
+ x509_crt.c \
+ )
+
+BL1_SOURCES += ${MBEDTLS_X509_SOURCES}
+BL2_SOURCES += ${MBEDTLS_X509_SOURCES}
diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c
new file mode 100644
index 00000000..a8605ce0
--- /dev/null
+++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ */
+
+/*
+ * X509 parser based on PolarSSL
+ *
+ * This module implements functions to check the integrity of a X509v3
+ * certificate ASN.1 structure and extract authentication parameters from the
+ * extensions field, such as an image hash or a public key.
+ */
+
+#include <assert.h>
+#include <img_parser_mod.h>
+#include <mbedtls_common.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+/* mbedTLS headers */
+#include <polarssl/asn1.h>
+#include <polarssl/oid.h>
+#include <polarssl/platform.h>
+
+/* Maximum OID string length ("a.b.c.d.e.f ...") */
+#define MAX_OID_STR_LEN 64
+
+#define LIB_NAME "mbedTLS X509v3"
+
+/* Temporary variables to speed up the authentication parameters search. These
+ * variables are assigned once during the integrity check and used any time an
+ * authentication parameter is requested, so we do not have to parse the image
+ * again */
+static asn1_buf tbs;
+static asn1_buf v3_ext;
+static asn1_buf pk;
+static asn1_buf sig_alg;
+static asn1_buf signature;
+
+/*
+ * Get X509v3 extension
+ *
+ * Global variable 'v3_ext' must point to the extensions region
+ * in the certificate. No need to check for errors since the image has passed
+ * the integrity check.
+ */
+static int get_ext(const char *oid, void **ext, unsigned int *ext_len)
+{
+ int oid_len;
+ size_t len;
+ unsigned char *end_ext_data, *end_ext_octet;
+ unsigned char *p;
+ const unsigned char *end;
+ char oid_str[MAX_OID_STR_LEN];
+ asn1_buf extn_oid;
+ int is_critical;
+
+ assert(oid != NULL);
+
+ p = v3_ext.p;
+ end = v3_ext.p + v3_ext.len;
+
+ asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+
+ while (p < end) {
+ memset(&extn_oid, 0x0, sizeof(extn_oid));
+ is_critical = 0; /* DEFAULT FALSE */
+
+ asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ end_ext_data = p + len;
+
+ /* Get extension ID */
+ extn_oid.tag = *p;
+ asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID);
+ extn_oid.p = p;
+ p += extn_oid.len;
+
+ /* Get optional critical */
+ asn1_get_bool(&p, end_ext_data, &is_critical);
+
+ /* Extension data */
+ asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING);
+ end_ext_octet = p + len;
+
+ /* Detect requested extension */
+ oid_len = oid_get_numeric_string(oid_str,
+ MAX_OID_STR_LEN, &extn_oid);
+ if (oid_len == POLARSSL_ERR_OID_BUF_TOO_SMALL) {
+ return IMG_PARSER_ERR;
+ }
+ if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
+ *ext = (void *)p;
+ *ext_len = (unsigned int)len;
+ return IMG_PARSER_OK;
+ }
+
+ /* Next */
+ p = end_ext_octet;
+ }
+
+ return IMG_PARSER_ERR_NOT_FOUND;
+}
+
+
+/*
+ * Check the integrity of the certificate ASN.1 structure.
+ * Extract the relevant data that will be used later during authentication.
+ */
+static int cert_parse(void *img, unsigned int img_len)
+{
+ int ret, is_critical;
+ size_t len;
+ unsigned char *p, *end, *crt_end;
+ asn1_buf sig_alg1, sig_alg2;
+
+ p = (unsigned char *)img;
+ len = img_len;
+ end = p + len;
+
+ /*
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ */
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+
+ if (len > (size_t)(end - p)) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ crt_end = p + len;
+
+ /*
+ * TBSCertificate ::= SEQUENCE {
+ */
+ tbs.p = p;
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ end = p + len;
+ tbs.len = end - tbs.p;
+
+ /*
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ */
+ ret = asn1_get_tag(&p, end, &len,
+ ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ p += len;
+
+ /*
+ * CertificateSerialNumber ::= INTEGER
+ */
+ ret = asn1_get_tag(&p, end, &len, ASN1_INTEGER);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ p += len;
+
+ /*
+ * signature AlgorithmIdentifier
+ */
+ sig_alg1.p = p;
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ if ((end - p) < 1) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ sig_alg1.len = (p + len) - sig_alg1.p;
+ p += len;
+
+ /*
+ * issuer Name
+ */
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ p += len;
+
+ /*
+ * Validity ::= SEQUENCE {
+ * notBefore Time,
+ * notAfter Time }
+ *
+ */
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ p += len;
+
+ /*
+ * subject Name
+ */
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ p += len;
+
+ /*
+ * SubjectPublicKeyInfo
+ */
+ pk.p = p;
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ pk.len = (p + len) - pk.p;
+ p += len;
+
+ /*
+ * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ */
+ ret = asn1_get_tag(&p, end, &len,
+ ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1);
+ if (ret != 0) {
+ if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ } else {
+ p += len;
+ }
+
+ /*
+ * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ */
+ ret = asn1_get_tag(&p, end, &len,
+ ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2);
+ if (ret != 0) {
+ if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ } else {
+ p += len;
+ }
+
+ /*
+ * extensions [3] EXPLICIT Extensions OPTIONAL
+ */
+ ret = asn1_get_tag(&p, end, &len,
+ ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+
+ /*
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ */
+ v3_ext.p = p;
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ v3_ext.len = (p + len) - v3_ext.p;
+
+ /*
+ * Check extensions integrity
+ */
+ while (p < end) {
+ ret = asn1_get_tag(&p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+
+ /* Get extension ID */
+ ret = asn1_get_tag(&p, end, &len, ASN1_OID);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ p += len;
+
+ /* Get optional critical */
+ ret = asn1_get_bool(&p, end, &is_critical);
+ if ((ret != 0) && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG)) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+
+ /* Data should be octet string type */
+ ret = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ p += len;
+ }
+
+ if (p != end) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+
+ end = crt_end;
+
+ /*
+ * }
+ * -- end of TBSCertificate
+ *
+ * signatureAlgorithm AlgorithmIdentifier
+ */
+ sig_alg2.p = p;
+ ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ if ((end - p) < 1) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ sig_alg2.len = (p + len) - sig_alg2.p;
+ p += len;
+
+ /* Compare both signature algorithms */
+ if (sig_alg1.len != sig_alg2.len) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg));
+
+ /*
+ * signatureValue BIT STRING
+ */
+ signature.p = p;
+ ret = asn1_get_tag(&p, end, &len, ASN1_BIT_STRING);
+ if (ret != 0) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+ signature.len = (p + len) - signature.p;
+ p += len;
+
+ /* Check certificate length */
+ if (p != end) {
+ return IMG_PARSER_ERR_FORMAT;
+ }
+
+ return IMG_PARSER_OK;
+}
+
+
+/* Exported functions */
+
+static void init(void)
+{
+ mbedtls_init();
+}
+
+static int check_integrity(void *img, unsigned int img_len)
+{
+ return cert_parse(img, img_len);
+}
+
+/*
+ * Extract an authentication parameter from an X509v3 certificate
+ */
+static int get_auth_param(const auth_param_type_desc_t *type_desc,
+ void *img, unsigned int img_len,
+ void **param, unsigned int *param_len)
+{
+ int rc = IMG_PARSER_OK;
+
+ /* We do not use img because the check_integrity function has already
+ * extracted the relevant data (v3_ext, pk, sig_alg, etc) */
+
+ switch (type_desc->type) {
+ case AUTH_PARAM_RAW_DATA:
+ /* Data to be signed */
+ *param = (void *)tbs.p;
+ *param_len = (unsigned int)tbs.len;
+ break;
+ case AUTH_PARAM_HASH:
+ /* All these parameters are included as X509v3 extensions */
+ rc = get_ext(type_desc->cookie, param, param_len);
+ break;
+ case AUTH_PARAM_PUB_KEY:
+ if (type_desc->cookie != 0) {
+ /* Get public key from extension */
+ rc = get_ext(type_desc->cookie, param, param_len);
+ } else {
+ /* Get the subject public key */
+ *param = (void *)pk.p;
+ *param_len = (unsigned int)pk.len;
+ }
+ break;
+ case AUTH_PARAM_SIG_ALG:
+ /* Get the certificate signature algorithm */
+ *param = (void *)sig_alg.p;
+ *param_len = (unsigned int)sig_alg.len;
+ break;
+ case AUTH_PARAM_SIG:
+ /* Get the certificate signature */
+ *param = (void *)signature.p;
+ *param_len = (unsigned int)signature.len;
+ break;
+ default:
+ rc = IMG_PARSER_ERR_NOT_FOUND;
+ break;
+ }
+
+ return rc;
+}
+
+REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \
+ check_integrity, get_auth_param);
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
new file mode 100644
index 00000000..79a89651
--- /dev/null
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -0,0 +1,445 @@
+/*
+ * 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 <auth_mod.h>
+#include <platform_def.h>
+#include <platform_oid.h>
+#include <stddef.h>
+
+/*
+ * Maximum key and hash sizes (in DER format)
+ */
+#define PK_DER_LEN 294
+#define HASH_DER_LEN 51
+
+/*
+ * The platform must allocate buffers to store the authentication parameters
+ * extracted from the certificates. In this case, because of the way the CoT is
+ * established, we can reuse some of the buffers on different stages
+ */
+static unsigned char plat_bl2_hash_buf[HASH_DER_LEN];
+static unsigned char plat_bl30_hash_buf[HASH_DER_LEN];
+static unsigned char plat_bl31_hash_buf[HASH_DER_LEN];
+static unsigned char plat_bl32_hash_buf[HASH_DER_LEN];
+static unsigned char plat_bl33_hash_buf[HASH_DER_LEN];
+static unsigned char plat_tz_world_pk_buf[PK_DER_LEN];
+static unsigned char plat_ntz_world_pk_buf[PK_DER_LEN];
+static unsigned char plat_content_pk[PK_DER_LEN];
+
+/*
+ * Parameter type descriptors
+ */
+static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_RAW_DATA, 0);
+
+static auth_param_type_desc_t tz_world_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, TZ_WORLD_PK_OID);
+static auth_param_type_desc_t ntz_world_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, NTZ_WORLD_PK_OID);
+
+static auth_param_type_desc_t bl30_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, BL30_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t bl31_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, BL31_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t bl32_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, BL32_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t bl33_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, BL33_CONTENT_CERT_PK_OID);
+
+static auth_param_type_desc_t bl2_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, BL2_HASH_OID);
+static auth_param_type_desc_t bl30_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, BL30_HASH_OID);
+static auth_param_type_desc_t bl31_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, BL31_HASH_OID);
+static auth_param_type_desc_t bl32_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, BL32_HASH_OID);
+static auth_param_type_desc_t bl33_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, BL33_HASH_OID);
+
+/*
+ * TBBR Chain of trust definition
+ */
+static const auth_img_desc_t cot_desc[] = {
+ /*
+ * BL2
+ */
+ [BL2_CERT_ID] = {
+ .img_id = BL2_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl2_hash,
+ .data = {
+ .ptr = (void *)plat_bl2_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+ },
+ [BL2_IMAGE_ID] = {
+ .img_id = BL2_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cot_desc[BL2_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl2_hash,
+ }
+ }
+ }
+ },
+ /*
+ * Trusted key certificate
+ */
+ [TRUSTED_KEY_CERT_ID] = {
+ .img_id = TRUSTED_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &tz_world_pk,
+ .data = {
+ .ptr = (void *)plat_tz_world_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &ntz_world_pk,
+ .data = {
+ .ptr = (void *)plat_ntz_world_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+ },
+ /*
+ * BL3-0
+ */
+ [BL30_KEY_CERT_ID] = {
+ .img_id = BL30_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &cot_desc[TRUSTED_KEY_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &tz_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl30_content_pk,
+ .data = {
+ .ptr = (void *)plat_content_pk,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+ },
+ [BL30_CERT_ID] = {
+ .img_id = BL30_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &cot_desc[BL30_KEY_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &bl30_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl30_hash,
+ .data = {
+ .ptr = (void *)plat_bl30_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+ },
+ [BL30_IMAGE_ID] = {
+ .img_id = BL30_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cot_desc[BL30_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl30_hash,
+ }
+ }
+ }
+ },
+ /*
+ * BL3-1
+ */
+ [BL31_KEY_CERT_ID] = {
+ .img_id = BL31_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &cot_desc[TRUSTED_KEY_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &tz_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl31_content_pk,
+ .data = {
+ .ptr = (void *)plat_content_pk,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+ },
+ [BL31_CERT_ID] = {
+ .img_id = BL31_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &cot_desc[BL31_KEY_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &bl31_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl31_hash,
+ .data = {
+ .ptr = (void *)plat_bl31_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+ },
+ [BL31_IMAGE_ID] = {
+ .img_id = BL31_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cot_desc[BL31_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl31_hash,
+ }
+ }
+ }
+ },
+ /*
+ * BL3-2
+ */
+ [BL32_KEY_CERT_ID] = {
+ .img_id = BL32_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &cot_desc[TRUSTED_KEY_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &tz_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl32_content_pk,
+ .data = {
+ .ptr = (void *)plat_content_pk,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+ },
+ [BL32_CERT_ID] = {
+ .img_id = BL32_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &cot_desc[BL32_KEY_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &bl32_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl32_hash,
+ .data = {
+ .ptr = (void *)plat_bl32_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+ },
+ [BL32_IMAGE_ID] = {
+ .img_id = BL32_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cot_desc[BL32_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl32_hash,
+ }
+ }
+ }
+ },
+ /*
+ * BL3-3
+ */
+ [BL33_KEY_CERT_ID] = {
+ .img_id = BL33_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &cot_desc[TRUSTED_KEY_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &ntz_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl33_content_pk,
+ .data = {
+ .ptr = (void *)plat_content_pk,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+ },
+ [BL33_CERT_ID] = {
+ .img_id = BL33_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &cot_desc[BL33_KEY_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &bl33_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data,
+ }
+ }
+ },
+ .authenticated_data = {
+ [0] = {
+ .type_desc = &bl33_hash,
+ .data = {
+ .ptr = (void *)plat_bl33_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+ },
+ [BL33_IMAGE_ID] = {
+ .img_id = BL33_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cot_desc[BL33_CERT_ID],
+ .img_auth_methods = {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl33_hash,
+ }
+ }
+ }
+ }
+};
+
+/* Register the CoT in the authentication module */
+REGISTER_COT(cot_desc);
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 9dcd901e..5a8a294a 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -51,11 +51,6 @@
x.node[4], x.node[5]
typedef struct {
- const char *name;
- const uuid_t uuid;
-} plat_fip_name_uuid_t;
-
-typedef struct {
/* Put file_pos above the struct to allow {0} on static init.
* It is a workaround for a known bug in GCC
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
@@ -64,37 +59,6 @@ typedef struct {
fip_toc_entry_t entry;
} file_state_t;
-static const plat_fip_name_uuid_t name_uuid[] = {
- {BL2_IMAGE_NAME, UUID_TRUSTED_BOOT_FIRMWARE_BL2},
-#ifdef BL30_IMAGE_NAME
- /* BL3-0 is optional in the platform */
- {BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30},
-#endif /* BL30_IMAGE_NAME */
- {BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31},
-#ifdef BL32_IMAGE_NAME
- /* BL3-2 is optional in the platform */
- {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};
static file_state_t current_file = {0};
static uintptr_t backend_dev_handle;
@@ -113,13 +77,6 @@ static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
static int fip_dev_close(io_dev_info_t *dev_info);
-static inline int copy_uuid(uuid_t *dst, const uuid_t *src)
-{
- memcpy(dst, src, sizeof(uuid_t));
- return 0;
-}
-
-
/* Return 0 for equal uuids. */
static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2)
{
@@ -138,22 +95,6 @@ static inline int is_valid_header(fip_toc_header_t *header)
}
-static int file_to_uuid(const char *filename, uuid_t *uuid)
-{
- int i;
- int status = -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(name_uuid); i++) {
- if (strcmp(filename, name_uuid[i].name) == 0) {
- copy_uuid(uuid, &name_uuid[i].uuid);
- status = 0;
- break;
- }
- }
- return status;
-}
-
-
/* Identify the device type as a virtual driver */
io_type_t device_type_fip(void)
{
@@ -201,17 +142,17 @@ static int fip_dev_open(const uintptr_t dev_spec __attribute__((unused)),
static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
{
int result = IO_FAIL;
- char *image_name = (char *)init_params;
+ unsigned int image_id = (unsigned int)init_params;
uintptr_t backend_handle;
fip_toc_header_t header;
size_t bytes_read;
/* Obtain a reference to the image by querying the platform layer */
- result = plat_get_image_source(image_name, &backend_dev_handle,
+ result = plat_get_image_source(image_id, &backend_dev_handle,
&backend_image_spec);
if (result != IO_SUCCESS) {
- WARN("Failed to obtain reference to image '%s' (%i)\n",
- image_name, result);
+ WARN("Failed to obtain reference to image id=%u (%i)\n",
+ image_id, result);
result = IO_FAIL;
goto fip_dev_init_exit;
}
@@ -220,7 +161,7 @@ static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
result = io_open(backend_dev_handle, backend_image_spec,
&backend_handle);
if (result != IO_SUCCESS) {
- WARN("Failed to access image '%s' (%i)\n", image_name, result);
+ WARN("Failed to access image id=%u (%i)\n", image_id, result);
result = IO_FAIL;
goto fip_dev_init_exit;
}
@@ -261,12 +202,11 @@ static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
{
int result = IO_FAIL;
uintptr_t backend_handle;
- uuid_t file_uuid;
- const io_file_spec_t *file_spec = (io_file_spec_t *)spec;
+ const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec;
size_t bytes_read;
int found_file = 0;
- assert(file_spec != NULL);
+ assert(uuid_spec != NULL);
assert(entity != NULL);
/* Can only have one file open at a time for the moment. We need to
@@ -297,8 +237,6 @@ static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
goto fip_file_open_close;
}
- file_to_uuid(file_spec->path, &file_uuid);
-
found_file = 0;
do {
result = io_read(backend_handle,
@@ -307,7 +245,7 @@ static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
&bytes_read);
if (result == IO_SUCCESS) {
if (compare_uuids(&current_file.entry.uuid,
- &file_uuid) == 0) {
+ &uuid_spec->uuid) == 0) {
found_file = 1;
break;
}