diff --git a/core/arch/arm/pta/secstor_ta_mgmt.c b/core/arch/arm/pta/secstor_ta_mgmt.c new file mode 100644 index 00000000000..a1965d71fdc --- /dev/null +++ b/core/arch/arm/pta/secstor_ta_mgmt.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result check_install_conflict(const struct shdr_bootstrap_ta *bs_ta) +{ + TEE_Result res; + struct tee_tadb_ta *ta; + TEE_UUID uuid; + const struct tee_tadb_property *prop; + + tee_uuid_from_octets(&uuid, bs_ta->uuid); + res = tee_tadb_ta_open(&uuid, &ta); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return TEE_SUCCESS; + if (res) + return res; + + prop = tee_tadb_ta_get_property(ta); + if (prop->version > bs_ta->version) + res = TEE_ERROR_ACCESS_CONFLICT; + + tee_tadb_ta_close(ta); + return res; +} + +static TEE_Result install_ta(struct shdr *shdr, const uint8_t *nw, + size_t nw_size) +{ + TEE_Result res; + struct tee_tadb_ta *ta; + uint32_t hash_algo; + void *hash_ctx = NULL; + size_t hash_ctx_size; + size_t offs; + const size_t buf_size = 2 * 4096; + void *buf; + struct tee_tadb_property property; + struct shdr_bootstrap_ta bs_ta; + + if (shdr->img_type != SHDR_BOOTSTRAP_TA) + return TEE_ERROR_SECURITY; + + if (nw_size < (sizeof(struct shdr_bootstrap_ta) + SHDR_GET_SIZE(shdr))) + return TEE_ERROR_SECURITY; + + if (shdr->hash_size > buf_size) + return TEE_ERROR_SECURITY; + + buf = malloc(buf_size); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * Initialize a hash context and run the algorithm over the signed + * header (less the final file hash and its signature of course) + */ + hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); + res = crypto_hash_get_ctx_size(hash_algo, &hash_ctx_size); + if (res) + goto err; + hash_ctx = malloc(hash_ctx_size); + if (!hash_ctx) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + res = crypto_hash_init(hash_ctx, hash_algo); + if (res) + goto err_free_hash_ctx; + res = crypto_hash_update(hash_ctx, hash_algo, (uint8_t *)shdr, + sizeof(*shdr)); + if (res) + goto err_free_hash_ctx; + + offs = SHDR_GET_SIZE(shdr); + memcpy(&bs_ta, nw + offs, sizeof(bs_ta)); + + /* Check that we're not downgrading a TA */ + res = check_install_conflict(&bs_ta); + if (res) + goto err_free_hash_ctx; + + res = crypto_hash_update(hash_ctx, hash_algo, (uint8_t *)&bs_ta, + sizeof(bs_ta)); + if (res) + goto err_free_hash_ctx; + offs += sizeof(bs_ta); + + memset(&property, 0, sizeof(property)); + COMPILE_TIME_ASSERT(sizeof(property.uuid) == sizeof(property.uuid)); + tee_uuid_from_octets(&property.uuid, bs_ta.uuid); + property.is_ta = true; + property.is_root = true; + property.version = bs_ta.version; + property.custom_size = 0; + property.bin_size = nw_size - offs; + DMSG("Installing %pUl", (void *)&property.uuid); + + res = tee_tadb_ta_create(&property, &ta); + if (res) + goto err_free_hash_ctx; + + while (offs < nw_size) { + size_t l = MIN(buf_size, nw_size - offs); + + memcpy(buf, nw + offs, l); + res = crypto_hash_update(hash_ctx, hash_algo, buf, l); + if (res) + goto err_ta_finalize; + res = tee_tadb_ta_write(ta, buf, l); + if (res) + goto err_ta_finalize; + offs += l; + } + + res = crypto_hash_final(hash_ctx, hash_algo, buf, shdr->hash_size); + if (res) + goto err_free_hash_ctx; + if (buf_compare_ct(buf, SHDR_GET_HASH(shdr), shdr->hash_size)) { + res = TEE_ERROR_SECURITY; + goto err_free_hash_ctx; + } + + free(hash_ctx); + free(buf); + return tee_tadb_ta_close_and_commit(ta); + +err_ta_finalize: + tee_tadb_ta_close_and_delete(ta); +err_free_hash_ctx: + free(hash_ctx); +err: + free(buf); + return res; +} + +static TEE_Result bootstrap(struct tee_ta_session *s __unused, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res; + struct shdr *shdr; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + shdr = shdr_alloc_and_copy(params->memref.buffer, params->memref.size); + if (!shdr) + return TEE_ERROR_SECURITY; + + res = shdr_verify_signature(shdr); + if (res) + goto out; + + res = install_ta(shdr, params->memref.buffer, params->memref.size); +out: + shdr_free(shdr); + return res; +} + +static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct tee_ta_session *s = tee_ta_get_calling_session(); + + switch (cmd_id) { + case PTA_MANAGEMENT_BOOTSTRAP: + return bootstrap(s, param_types, params); + default: + break; + } + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_MANAGEMENT_UUID, .name = "management", + /* + * TA_FLAG_SINGLE_INSTANCE and TA_FLAG_MULTI_SESSION are + * current part of PTA_DEFAULT_FLAGS, but as this TA + * depends on those two flags we add them explicitly + * too. + */ + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SINGLE_INSTANCE | + TA_FLAG_MULTI_SESSION, + .invoke_command_entry_point = invoke_command); diff --git a/core/arch/arm/pta/sub.mk b/core/arch/arm/pta/sub.mk index c67d727e7b1..ff9c8e38052 100644 --- a/core/arch/arm/pta/sub.mk +++ b/core/arch/arm/pta/sub.mk @@ -3,6 +3,7 @@ srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += core_self_tests.c srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += interrupt_tests.c srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += core_mutex_tests.c ifeq ($(CFG_WITH_USER_TA),y) +srcs-$(CFG_SECSTOR_TA_MGMT_PTA) += secstor_ta_mgmt.c srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += core_fs_htree_tests.c endif srcs-$(CFG_WITH_STATS) += stats.c diff --git a/core/core.mk b/core/core.mk index 7eb90e3a9ef..b633425022d 100644 --- a/core/core.mk +++ b/core/core.mk @@ -14,8 +14,19 @@ include core/arch/$(ARCH)/$(ARCH).mk PLATFORM_$(PLATFORM) := y PLATFORM_FLAVOR_$(PLATFORM_FLAVOR) := y +# +# Sort out some configuration dependencies +# + $(call cfg-depends-all,CFG_PAGED_USER_TA,CFG_WITH_PAGER CFG_WITH_USER_TA) +$(call cfg-depends-all,CFG_SECSTOR_TA_MGMT_PTA,CFG_WITH_USER_TA) + +ifeq ($(CFG_SECSTOR_TA_MGMT_PTA),y) +$(call force,CFG_SECSTOR_TA,y,required by CFG_SECSTOR_TA_MGMT_PTA) +endif + + # Setup compiler for this sub module COMPILER_$(sm) ?= $(COMPILER) include mk/$(COMPILER_$(sm)).mk diff --git a/lib/libutee/include/pta_management.h b/lib/libutee/include/pta_management.h new file mode 100644 index 00000000000..75f274f6166 --- /dev/null +++ b/lib/libutee/include/pta_management.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __PTA_MANAGEMENT_H +#define __PTA_MANAGEMENT_H + +#define PTA_MANAGEMENT_TA_EXISTS 1 + +/* + * Bootstrap (install initial) Trusted Application or Secure Domain into + * secure storage from a signed binary. + * + * [in] memref[0]: signed binary + */ +#define PTA_MANAGEMENT_BOOTSTRAP 0 + +#define PTA_MANAGEMENT_UUID { 0x6e256cba, 0xfc4d, 0x4941, { \ + 0xad, 0x09, 0x2c, 0xa1, 0x86, 0x03, 0x42, 0xdd } } + +#endif /*__PTA_MANAGEMENT_H*/ diff --git a/mk/config.mk b/mk/config.mk index 4fd07cbd5cd..4b010b6e5c3 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -265,6 +265,9 @@ CFG_SECURE_DATA_PATH ?= n # Enable storage for TAs in secure storage CFG_SECSTOR_TA ?= y +# Enable the pseudo TA that managages TA storage in secure storage +CFG_SECSTOR_TA_MGMT_PTA ?= y + # Define the number of cores per cluster used in calculating core position. # The cluster number is shifted by this value and added to the core ID, # so its value represents log2(cores/cluster).