aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManish V Badarkhe <Manish.Badarkhe@arm.com>2020-07-23 10:43:57 +0100
committerManish V Badarkhe <Manish.Badarkhe@arm.com>2020-09-15 16:13:26 +0100
commit28e9a55fc87a8e2c1152689f3edcde0e8e639747 (patch)
tree57e07ccd90772c1972e102e4afb5d691a2c031ec
parent47bda02c8e95797b93d81407dc9c6d99aec1e3ff (diff)
downloadtrusted-firmware-a-28e9a55fc87a8e2c1152689f3edcde0e8e639747.tar.gz
lib: fconf: Implement a parser to populate CoT
Implemented a parser which populates the properties of the CoT descriptors as per the binding document [1]. 'COT_DESC_IN_DTB' build option is disabled by default and can be enabled in future for all Arm platforms by making necessary changes in the memory map. Currently, this parser is tested only for FVP platform. [1]: https://trustedfirmware-a.readthedocs.io/en/latest/components/cot-binding.html Change-Id: I2f911206087a1a2942aa728de151d2ac269d27cc Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
-rw-r--r--include/drivers/auth/auth_mod.h14
-rw-r--r--include/tools_share/tbbr_oid.h2
-rw-r--r--lib/fconf/fconf_cot_getter.c497
-rw-r--r--plat/arm/common/arm_common.mk11
4 files changed, 520 insertions, 4 deletions
diff --git a/include/drivers/auth/auth_mod.h b/include/drivers/auth/auth_mod.h
index 3965b58e79..d1fd52c868 100644
--- a/include/drivers/auth/auth_mod.h
+++ b/include/drivers/auth/auth_mod.h
@@ -21,7 +21,18 @@
*/
#define IMG_FLAG_AUTHENTICATED (1 << 0)
-
+#if COT_DESC_IN_DTB && !IMAGE_BL1
+/*
+ * Authentication image descriptor
+ */
+typedef struct auth_img_desc_s {
+ unsigned int img_id;
+ img_type_t img_type;
+ const struct auth_img_desc_s *parent;
+ auth_method_desc_t *img_auth_methods;
+ auth_param_desc_t *authenticated_data;
+} auth_img_desc_t;
+#else
/*
* Authentication image descriptor
*/
@@ -32,6 +43,7 @@ typedef struct auth_img_desc_s {
const auth_method_desc_t *const img_auth_methods;
const auth_param_desc_t *const authenticated_data;
} auth_img_desc_t;
+#endif /* COT_DESC_IN_DTB && !IMAGE_BL1 */
/* Public functions */
void auth_mod_init(void);
diff --git a/include/tools_share/tbbr_oid.h b/include/tools_share/tbbr_oid.h
index 37d87d3072..c789f790f7 100644
--- a/include/tools_share/tbbr_oid.h
+++ b/include/tools_share/tbbr_oid.h
@@ -7,6 +7,8 @@
#ifndef TBBR_OID_H
#define TBBR_OID_H
+#define MAX_OID_NAME_LEN 30
+
/*
* The following is a list of OID values defined and reserved by ARM, which
* are used to define the extension fields of the certificate structure, as
diff --git a/lib/fconf/fconf_cot_getter.c b/lib/fconf/fconf_cot_getter.c
new file mode 100644
index 0000000000..adfa5341c9
--- /dev/null
+++ b/lib/fconf/fconf_cot_getter.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stddef.h>
+
+#include <common/fdt_wrappers.h>
+#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include <drivers/auth/auth_mod.h>
+#include <lib/fconf/fconf.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+
+#include <tools_share/tbbr_oid.h>
+
+/* static structures used during authentication process */
+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);
+
+/* pointers to an array of CoT descriptors */
+static const auth_img_desc_t *cot_desc[MAX_NUMBER_IDS];
+/* array of CoT descriptors */
+static auth_img_desc_t auth_img_descs[MAX_NUMBER_IDS];
+
+/* array of authentication methods structures */
+static auth_method_desc_t auth_methods[MAX_NUMBER_IDS * AUTH_METHOD_NUM];
+static OBJECT_POOL_ARRAY(auth_methods_pool, auth_methods);
+
+/* array of authentication params structures */
+static auth_param_desc_t auth_params[MAX_NUMBER_IDS * COT_MAX_VERIFIED_PARAMS];
+static OBJECT_POOL_ARRAY(auth_params_pool, auth_params);
+
+/* array of authentication param type structures */
+static auth_param_type_desc_t auth_param_type_descs[MAX_NUMBER_IDS];
+static OBJECT_POOL_ARRAY(auth_param_type_descs_pool, auth_param_type_descs);
+
+/*
+ * array of OIDs
+ * Object IDs are used to search hash, pk, counter values in certificate.
+ * As per binding we have below 2 combinations:
+ * 1. Certificates are validated using nv-cntr and pk
+ * 2. Raw images are authenticated using hash
+ * Hence in worst case, there are maximum 2 OIDs per image/certificate
+ */
+static unsigned char oids[(MAX_NUMBER_IDS * 2)][MAX_OID_NAME_LEN];
+static OBJECT_POOL_ARRAY(oid_pool, oids);
+
+/* An array of auth buffer which holds hashes and pk
+ * ToDo: Size decided with the current number of images and
+ * certificates which are available in CoT. Size of these buffers bound to
+ * increase in the future on the addition of images/certificates.
+ */
+static unsigned char hash_auth_bufs[20][HASH_DER_LEN];
+static OBJECT_POOL_ARRAY(hash_auth_buf_pool, hash_auth_bufs);
+static unsigned char pk_auth_bufs[12][PK_DER_LEN];
+static OBJECT_POOL_ARRAY(pk_auth_buf_pool, pk_auth_bufs);
+
+/*******************************************************************************
+ * update_parent_auth_data() - Update authentication data structure
+ * @auth_desc[in]: Pointer to the auth image descriptor
+ * @type_desc[in]: Pointer to authentication parameter
+ * @auth_buf_size[in]: Buffer size to hold pk or hash
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int update_parent_auth_data(const auth_img_desc_t *auth_desc,
+ auth_param_type_desc_t *type_desc,
+ unsigned int auth_buf_size)
+{
+ unsigned int i;
+ auth_param_desc_t *auth_data = &auth_desc->authenticated_data[0];
+ unsigned char *auth_buf;
+
+ for (i = 0U; i < COT_MAX_VERIFIED_PARAMS; i++) {
+ if (auth_data[i].type_desc == type_desc) {
+ return 0;
+ }
+ if (auth_data[i].type_desc == NULL) {
+ break;
+ }
+ }
+
+ if (auth_buf_size == HASH_DER_LEN) {
+ auth_buf = pool_alloc(&hash_auth_buf_pool);
+ } else if (auth_buf_size == PK_DER_LEN) {
+ auth_buf = pool_alloc(&pk_auth_buf_pool);
+ } else {
+ return -1;
+ }
+
+ if (i < COT_MAX_VERIFIED_PARAMS) {
+ auth_data[i].type_desc = type_desc;
+ auth_data[i].data.ptr = auth_buf;
+ auth_data[i].data.len = auth_buf_size;
+ } else {
+ ERROR("Out of authentication data array\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * get_auth_param_type_desc() - Get pointer of authentication parameter
+ * @img_id[in]: Image Id
+ * @type_desc[out]: Pointer to authentication parameter
+ * @buf_size[out]: Buffer size which hold hash/pk
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int get_auth_param_type_desc(unsigned int img_id,
+ auth_param_type_desc_t **type_desc,
+ unsigned int *buf_size)
+{
+ auth_method_desc_t *img_auth_method = NULL;
+ img_type_t type = auth_img_descs[img_id].img_type;
+
+ if (type == IMG_CERT) {
+ img_auth_method =
+ &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_SIG];
+ *type_desc = img_auth_method->param.sig.pk;
+ *buf_size = PK_DER_LEN;
+ } else if (type == IMG_RAW) {
+ img_auth_method =
+ &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_HASH];
+ *type_desc = img_auth_method->param.hash.hash;
+ *buf_size = HASH_DER_LEN;
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * set_auth_method() - Update global auth image descriptors with authentication
+ * method data
+ * @auth_method_type[in]: Type of authentication method
+ * @oid[in]: Object Idetifier for pk/hash search
+ * @auth_method[in]: Pointer to authentication method to set
+ ******************************************************************************/
+static void set_auth_method(auth_method_type_t auth_method_type, char *oid,
+ auth_method_desc_t *auth_method)
+{
+ auth_param_type_t auth_param_type = AUTH_PARAM_NONE;
+ auth_param_type_desc_t *auth_param_type_desc;
+
+ assert(auth_method != NULL);
+
+ auth_param_type_desc = pool_alloc(&auth_param_type_descs_pool);
+ auth_method->type = auth_method_type;
+
+ if (auth_method_type == AUTH_METHOD_SIG) {
+ auth_param_type = AUTH_PARAM_PUB_KEY;
+ auth_method->param.sig.sig = &sig;
+ auth_method->param.sig.alg = &sig_alg;
+ auth_method->param.sig.data = &raw_data;
+ auth_method->param.sig.pk = auth_param_type_desc;
+ } else if (auth_method_type == AUTH_METHOD_HASH) {
+ auth_param_type = AUTH_PARAM_HASH;
+ auth_method->param.hash.data = &raw_data;
+ auth_method->param.hash.hash = auth_param_type_desc;
+ } else if (auth_method_type == AUTH_METHOD_NV_CTR) {
+ auth_param_type = AUTH_PARAM_NV_CTR;
+ auth_method->param.nv_ctr.cert_nv_ctr = auth_param_type_desc;
+ auth_method->param.nv_ctr.plat_nv_ctr = auth_param_type_desc;
+ }
+
+ auth_param_type_desc->type = auth_param_type;
+ auth_param_type_desc->cookie = (void *)oid;
+}
+
+/*******************************************************************************
+ * get_oid() - get object identifier from device tree
+ * @dtb[in]: Pointer to the device tree blob in memory
+ * @node[in]: Offset of the node
+ * @prop[in]: Property to read from the given node
+ * @oid[out]: Object Indentifier of key/hash/nv-counter in certificate
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int get_oid(const void *dtb, int node, const char *prop, char **oid)
+{
+ uint32_t phandle;
+ int rc;
+
+ rc = fdt_read_uint32(dtb, node, prop, &phandle);
+ if (rc < 0) {
+ return rc;
+ }
+
+ node = fdt_node_offset_by_phandle(dtb, phandle);
+ if (node < 0) {
+ return node;
+ }
+
+ *oid = pool_alloc(&oid_pool);
+ rc = fdtw_read_string(dtb, node, "oid", *oid, MAX_OID_NAME_LEN);
+
+ return rc;
+}
+
+/*******************************************************************************
+ * populate_and_set_auth_methods() - Populate auth method parameters from
+ * device tree and set authentication method
+ * structure.
+ * @dtb[in]: Pointer to the device tree blob in memory
+ * @node[in]: Offset of the node
+ * @img_id[in]: Image identifier
+ * @type[in]: Type of image
+ * @root_certificate[in]:Root certificate (authenticated by ROTPK)
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int populate_and_set_auth_methods(const void *dtb, int node,
+ unsigned int img_id, img_type_t type,
+ bool root_certificate)
+{
+ auth_method_type_t auth_method_type = AUTH_METHOD_NONE;
+ int rc;
+ char *oid = NULL;
+
+ auth_method_desc_t *auth_method = pool_alloc_n(&auth_methods_pool,
+ AUTH_METHOD_NUM);
+
+ /*
+ * This is as per binding document where certificates are
+ * verified by signature and images are verified by hash.
+ */
+ if (type == IMG_CERT) {
+ if (root_certificate) {
+ oid = NULL;
+ } else {
+ rc = get_oid(dtb, node, "signing-key", &oid);
+ if (rc < 0) {
+ ERROR("FCONF: Can't read %s property\n",
+ "signing-key");
+ return rc;
+ }
+ }
+ auth_method_type = AUTH_METHOD_SIG;
+ } else if (type == IMG_RAW) {
+ rc = get_oid(dtb, node, "hash", &oid);
+ if (rc < 0) {
+ ERROR("FCONF: Can't read %s property\n",
+ "hash");
+ return rc;
+ }
+ auth_method_type = AUTH_METHOD_HASH;
+ } else {
+ return -1;
+ }
+
+ set_auth_method(auth_method_type, oid,
+ &auth_method[auth_method_type]);
+
+ /* Retrieve the optional property */
+ rc = get_oid(dtb, node, "antirollback-counter", &oid);
+ if (rc == 0) {
+ auth_method_type = AUTH_METHOD_NV_CTR;
+ set_auth_method(auth_method_type, oid,
+ &auth_method[auth_method_type]);
+ }
+
+ auth_img_descs[img_id].img_auth_methods = &auth_method[0];
+
+ return 0;
+}
+
+/*******************************************************************************
+ * get_parent_img_id() - Get parent image id for given child node
+ * @dtb[in]: Pointer to the device tree blob in memory
+ * @node[in]: Offset of the child node
+ * @parent_img_id[out]: Image id of parent
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int get_parent_img_id(const void *dtb, int node,
+ unsigned int *parent_img_id)
+{
+ uint32_t phandle;
+ int err;
+
+ err = fdt_read_uint32(dtb, node, "parent", &phandle);
+ if (err < 0) {
+ ERROR("FCONF: Could not read %s property in node\n",
+ "parent");
+ return err;
+ }
+
+ node = fdt_node_offset_by_phandle(dtb, phandle);
+ if (node < 0) {
+ ERROR("FCONF: Failed to locate node using its phandle\n");
+ return node;
+ }
+
+ err = fdt_read_uint32(dtb, node, "image-id", parent_img_id);
+ if (err < 0) {
+ ERROR("FCONF: Could not read %s property in node\n",
+ "image-id");
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * set_desc_data() - Update data in descriptor's structure
+ * @dtb[in]: Pointer to the device tree blob in memory
+ * @node[in]: Offset of the node
+ * @type[in]: Type of image (RAW/CERT)
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int set_desc_data(const void *dtb, int node, img_type_t type)
+{
+ int rc;
+ bool root_certificate = false;
+ unsigned int img_id, parent_img_id;
+
+ rc = fdt_read_uint32(dtb, node, "image-id", &img_id);
+ if (rc < 0) {
+ ERROR("FCONF: Can't find property %s in node\n",
+ "image-id");
+ return rc;
+ }
+
+ if (fdt_getprop(dtb, node, "root-certificate",
+ NULL) != NULL) {
+ root_certificate = true;
+ }
+
+ if (!root_certificate) {
+ rc = get_parent_img_id(dtb, node, &parent_img_id);
+ if (rc < 0) {
+ return rc;
+ }
+ auth_img_descs[img_id].parent = &auth_img_descs[parent_img_id];
+ }
+
+ auth_img_descs[img_id].img_id = img_id;
+ auth_img_descs[img_id].img_type = type;
+
+ rc = populate_and_set_auth_methods(dtb, node, img_id, type,
+ root_certificate);
+ if (rc < 0) {
+ return rc;
+ }
+
+ if (type == IMG_CERT) {
+ auth_param_desc_t *auth_param =
+ pool_alloc_n(&auth_params_pool,
+ COT_MAX_VERIFIED_PARAMS);
+ auth_img_descs[img_id].authenticated_data = &auth_param[0];
+ }
+
+ cot_desc[img_id] = &auth_img_descs[img_id];
+
+ return rc;
+}
+
+/*******************************************************************************
+ * populate_manifest_descs() - Populate CoT descriptors and update global
+ * certificate structures
+ * @dtb[in]: Pointer to the device tree blob in memory
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int populate_manifest_descs(const void *dtb)
+{
+ int node, child;
+ int rc;
+
+ /*
+ * Assert the node offset points to "arm, cert-descs"
+ * compatible property
+ */
+ const char *compatible_str = "arm, cert-descs";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find %s compatible in node\n",
+ compatible_str);
+ return node;
+ }
+
+ fdt_for_each_subnode(child, dtb, node) {
+ rc = set_desc_data(dtb, child, IMG_CERT);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * populate_image_descs() - Populate CoT descriptors and update global
+ * image descriptor structures.
+ * @dtb[in]: Pointer to the device tree blob in memory
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int populate_image_descs(const void *dtb)
+{
+ int node, child;
+ int rc;
+
+ /*
+ * Assert the node offset points to "arm, img-descs"
+ * compatible property
+ */
+ const char *compatible_str = "arm, img-descs";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find %s compatible in node\n",
+ compatible_str);
+ return node;
+ }
+
+ fdt_for_each_subnode(child, dtb, node) {
+ rc = set_desc_data(dtb, child, IMG_RAW);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * fconf_populate_cot_descs() - Populate CoT descriptors and update global
+ * structures
+ * @config[in]: Pointer to the device tree blob in memory
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int fconf_populate_cot_descs(uintptr_t config)
+{
+ auth_param_type_desc_t *type_desc = NULL;
+ unsigned int auth_buf_size = 0U;
+ int rc;
+
+ /* As libfdt uses void *, we can't avoid this cast */
+ const void *dtb = (void *)config;
+
+ /* populate manifest descs information */
+ rc = populate_manifest_descs(dtb);
+ if (rc < 0) {
+ ERROR("FCONF: population of %s descs failed %d\n",
+ "manifest", rc);
+ return rc;
+ }
+
+ /* populate image descs information */
+ rc = populate_image_descs(dtb);
+ if (rc < 0) {
+ ERROR("FCONF: population of %s descs failed %d\n",
+ "images", rc);
+ return rc;
+ }
+
+ /* update parent's authentication data */
+ for (unsigned int i = 0U; i < MAX_NUMBER_IDS; i++) {
+ if (auth_img_descs[i].parent != NULL) {
+ rc = get_auth_param_type_desc(i,
+ &type_desc,
+ &auth_buf_size);
+ if (rc < 0) {
+ ERROR("FCONF: failed to get auth data %d\n",
+ rc);
+ return rc;
+ }
+
+ rc = update_parent_auth_data(auth_img_descs[i].parent,
+ type_desc,
+ auth_buf_size);
+ if (rc < 0) {
+ ERROR("FCONF: auth data update failed %d\n",
+ rc);
+ return rc;
+ }
+ }
+ }
+
+ return rc;
+}
+
+FCONF_REGISTER_POPULATOR(TB_FW, cot_desc, fconf_populate_cot_descs);
+REGISTER_COT(cot_desc);
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 96ab2d3004..bbcc95427e 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -297,9 +297,14 @@ ifneq (${TRUSTED_BOARD_BOOT},0)
# Include the selected chain of trust sources.
ifeq (${COT},tbbr)
- AUTH_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c
- BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_bl1.c
- BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_bl2.c
+ BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl1.c
+ ifneq (${COT_DESC_IN_DTB},0)
+ BL2_SOURCES += lib/fconf/fconf_cot_getter.c
+ else
+ BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+ endif
else ifeq (${COT},dualroot)
AUTH_SOURCES += drivers/auth/dualroot/cot.c
else