xref: /optee_os/core/pta/secstor_ta_mgmt.c (revision c6c7967f74d4c6267750b3ff42067c004f8cad33)
15843bb75SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
25843bb75SJerome Forissier /*
35843bb75SJerome Forissier  * Copyright (c) 2017, Linaro Limited
45843bb75SJerome Forissier  */
55843bb75SJerome Forissier 
65843bb75SJerome Forissier #include <kernel/pseudo_ta.h>
75843bb75SJerome Forissier #include <tee/tadb.h>
85843bb75SJerome Forissier #include <pta_secstor_ta_mgmt.h>
95843bb75SJerome Forissier #include <signed_hdr.h>
105843bb75SJerome Forissier #include <string_ext.h>
115843bb75SJerome Forissier #include <string.h>
125843bb75SJerome Forissier #include <tee_api_types.h>
135843bb75SJerome Forissier #include <crypto/crypto.h>
145843bb75SJerome Forissier #include <tee/uuid.h>
155843bb75SJerome Forissier #include <types_ext.h>
165843bb75SJerome Forissier #include <utee_defines.h>
175843bb75SJerome Forissier 
check_install_conflict(const struct shdr_bootstrap_ta * bs_ta)185843bb75SJerome Forissier static TEE_Result check_install_conflict(const struct shdr_bootstrap_ta *bs_ta)
195843bb75SJerome Forissier {
205843bb75SJerome Forissier 	TEE_Result res;
215843bb75SJerome Forissier 	struct tee_tadb_ta_read *ta;
225843bb75SJerome Forissier 	TEE_UUID uuid;
235843bb75SJerome Forissier 	const struct tee_tadb_property *prop;
245843bb75SJerome Forissier 
255843bb75SJerome Forissier 	tee_uuid_from_octets(&uuid, bs_ta->uuid);
265843bb75SJerome Forissier 	res = tee_tadb_ta_open(&uuid, &ta);
275843bb75SJerome Forissier 	if (res == TEE_ERROR_ITEM_NOT_FOUND)
285843bb75SJerome Forissier 		return TEE_SUCCESS;
295843bb75SJerome Forissier 	if (res)
305843bb75SJerome Forissier 		return res;
315843bb75SJerome Forissier 
325843bb75SJerome Forissier 	prop = tee_tadb_ta_get_property(ta);
335843bb75SJerome Forissier 	if (prop->version > bs_ta->ta_version)
345843bb75SJerome Forissier 		res = TEE_ERROR_ACCESS_CONFLICT;
355843bb75SJerome Forissier 
365843bb75SJerome Forissier 	tee_tadb_ta_close(ta);
375843bb75SJerome Forissier 	return res;
385843bb75SJerome Forissier }
395843bb75SJerome Forissier 
install_ta(struct shdr * shdr,const uint8_t * nw,size_t nw_size)405843bb75SJerome Forissier static TEE_Result install_ta(struct shdr *shdr, const uint8_t *nw,
415843bb75SJerome Forissier 			     size_t nw_size)
425843bb75SJerome Forissier {
435843bb75SJerome Forissier 	TEE_Result res;
445843bb75SJerome Forissier 	struct tee_tadb_ta_write *ta;
455843bb75SJerome Forissier 	void *hash_ctx = NULL;
465843bb75SJerome Forissier 	size_t offs;
47*c6c7967fSJens Wiklander 	const size_t buf_size = 1024;
485843bb75SJerome Forissier 	void *buf;
495843bb75SJerome Forissier 	struct tee_tadb_property property;
505843bb75SJerome Forissier 	struct shdr_bootstrap_ta bs_ta;
515843bb75SJerome Forissier 
525843bb75SJerome Forissier 	if (shdr->img_type != SHDR_BOOTSTRAP_TA)
535843bb75SJerome Forissier 		return TEE_ERROR_SECURITY;
545843bb75SJerome Forissier 
555843bb75SJerome Forissier 	if (nw_size < (sizeof(struct shdr_bootstrap_ta) + SHDR_GET_SIZE(shdr)))
565843bb75SJerome Forissier 		return TEE_ERROR_SECURITY;
575843bb75SJerome Forissier 
585843bb75SJerome Forissier 	if (shdr->hash_size > buf_size)
595843bb75SJerome Forissier 		return TEE_ERROR_SECURITY;
605843bb75SJerome Forissier 
615843bb75SJerome Forissier 	buf = malloc(buf_size);
625843bb75SJerome Forissier 	if (!buf)
635843bb75SJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
645843bb75SJerome Forissier 
655843bb75SJerome Forissier 	/*
665843bb75SJerome Forissier 	 * Initialize a hash context and run the algorithm over the signed
675843bb75SJerome Forissier 	 * header (less the final file hash and its signature of course)
685843bb75SJerome Forissier 	 */
696b3a371cSJens Wiklander 	res = crypto_hash_alloc_ctx(&hash_ctx,
706b3a371cSJens Wiklander 				    TEE_DIGEST_HASH_TO_ALGO(shdr->algo));
715843bb75SJerome Forissier 	if (res)
725843bb75SJerome Forissier 		goto err;
736b3a371cSJens Wiklander 	res = crypto_hash_init(hash_ctx);
745843bb75SJerome Forissier 	if (res)
755843bb75SJerome Forissier 		goto err_free_hash_ctx;
766b3a371cSJens Wiklander 	res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr));
775843bb75SJerome Forissier 	if (res)
785843bb75SJerome Forissier 		goto err_free_hash_ctx;
795843bb75SJerome Forissier 
805843bb75SJerome Forissier 	offs = SHDR_GET_SIZE(shdr);
815843bb75SJerome Forissier 	memcpy(&bs_ta, nw + offs, sizeof(bs_ta));
825843bb75SJerome Forissier 
835843bb75SJerome Forissier 	/* Check that we're not downgrading a TA */
845843bb75SJerome Forissier 	res = check_install_conflict(&bs_ta);
855843bb75SJerome Forissier 	if (res)
865843bb75SJerome Forissier 		goto err_free_hash_ctx;
875843bb75SJerome Forissier 
886b3a371cSJens Wiklander 	res = crypto_hash_update(hash_ctx, (uint8_t *)&bs_ta, sizeof(bs_ta));
895843bb75SJerome Forissier 	if (res)
905843bb75SJerome Forissier 		goto err_free_hash_ctx;
915843bb75SJerome Forissier 	offs += sizeof(bs_ta);
925843bb75SJerome Forissier 
935843bb75SJerome Forissier 	memset(&property, 0, sizeof(property));
945843bb75SJerome Forissier 	COMPILE_TIME_ASSERT(sizeof(property.uuid) == sizeof(bs_ta.uuid));
955843bb75SJerome Forissier 	tee_uuid_from_octets(&property.uuid, bs_ta.uuid);
965843bb75SJerome Forissier 	property.version = bs_ta.ta_version;
975843bb75SJerome Forissier 	property.custom_size = 0;
985843bb75SJerome Forissier 	property.bin_size = nw_size - offs;
995843bb75SJerome Forissier 	DMSG("Installing %pUl", (void *)&property.uuid);
1005843bb75SJerome Forissier 
1015843bb75SJerome Forissier 	res = tee_tadb_ta_create(&property, &ta);
1025843bb75SJerome Forissier 	if (res)
1035843bb75SJerome Forissier 		goto err_free_hash_ctx;
1045843bb75SJerome Forissier 
1055843bb75SJerome Forissier 	while (offs < nw_size) {
1065843bb75SJerome Forissier 		size_t l = MIN(buf_size, nw_size - offs);
1075843bb75SJerome Forissier 
1085843bb75SJerome Forissier 		memcpy(buf, nw + offs, l);
1096b3a371cSJens Wiklander 		res = crypto_hash_update(hash_ctx, buf, l);
1105843bb75SJerome Forissier 		if (res)
1115843bb75SJerome Forissier 			goto err_ta_finalize;
1125843bb75SJerome Forissier 		res = tee_tadb_ta_write(ta, buf, l);
1135843bb75SJerome Forissier 		if (res)
1145843bb75SJerome Forissier 			goto err_ta_finalize;
1155843bb75SJerome Forissier 		offs += l;
1165843bb75SJerome Forissier 	}
1175843bb75SJerome Forissier 
1186b3a371cSJens Wiklander 	res = crypto_hash_final(hash_ctx, buf, shdr->hash_size);
1195843bb75SJerome Forissier 	if (res)
1205843bb75SJerome Forissier 		goto err_ta_finalize;
1215843bb75SJerome Forissier 	if (consttime_memcmp(buf, SHDR_GET_HASH(shdr), shdr->hash_size)) {
1225843bb75SJerome Forissier 		res = TEE_ERROR_SECURITY;
1235843bb75SJerome Forissier 		goto err_ta_finalize;
1245843bb75SJerome Forissier 	}
1255843bb75SJerome Forissier 
1266b3a371cSJens Wiklander 	crypto_hash_free_ctx(hash_ctx);
1275843bb75SJerome Forissier 	free(buf);
1285843bb75SJerome Forissier 	return tee_tadb_ta_close_and_commit(ta);
1295843bb75SJerome Forissier 
1305843bb75SJerome Forissier err_ta_finalize:
1315843bb75SJerome Forissier 	tee_tadb_ta_close_and_delete(ta);
1325843bb75SJerome Forissier err_free_hash_ctx:
1336b3a371cSJens Wiklander 	crypto_hash_free_ctx(hash_ctx);
1345843bb75SJerome Forissier err:
1355843bb75SJerome Forissier 	free(buf);
1365843bb75SJerome Forissier 	return res;
1375843bb75SJerome Forissier }
1385843bb75SJerome Forissier 
bootstrap(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])1395843bb75SJerome Forissier static TEE_Result bootstrap(uint32_t param_types,
1405843bb75SJerome Forissier 			    TEE_Param params[TEE_NUM_PARAMS])
1415843bb75SJerome Forissier {
1425843bb75SJerome Forissier 	TEE_Result res;
1435843bb75SJerome Forissier 	struct shdr *shdr;
1445843bb75SJerome Forissier 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1455843bb75SJerome Forissier 						TEE_PARAM_TYPE_NONE,
1465843bb75SJerome Forissier 						TEE_PARAM_TYPE_NONE,
1475843bb75SJerome Forissier 						TEE_PARAM_TYPE_NONE);
1485843bb75SJerome Forissier 
1495843bb75SJerome Forissier 	if (param_types != exp_pt)
1505843bb75SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
1515843bb75SJerome Forissier 
152ec1aa4faSJens Wiklander 	shdr = shdr_alloc_and_copy(0, params->memref.buffer,
153ec1aa4faSJens Wiklander 				   params->memref.size);
1545843bb75SJerome Forissier 	if (!shdr)
1555843bb75SJerome Forissier 		return TEE_ERROR_SECURITY;
1565843bb75SJerome Forissier 
1575843bb75SJerome Forissier 	res = shdr_verify_signature(shdr);
1585843bb75SJerome Forissier 	if (res)
1595843bb75SJerome Forissier 		goto out;
1605843bb75SJerome Forissier 
1615843bb75SJerome Forissier 	res = install_ta(shdr, params->memref.buffer, params->memref.size);
1625843bb75SJerome Forissier out:
1635843bb75SJerome Forissier 	shdr_free(shdr);
1645843bb75SJerome Forissier 	return res;
1655843bb75SJerome Forissier }
1665843bb75SJerome Forissier 
invoke_command(void * sess_ctx __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])1675843bb75SJerome Forissier static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
1685843bb75SJerome Forissier 				 uint32_t param_types,
1695843bb75SJerome Forissier 				 TEE_Param params[TEE_NUM_PARAMS])
1705843bb75SJerome Forissier {
1715843bb75SJerome Forissier 	switch (cmd_id) {
1725843bb75SJerome Forissier 	case PTA_SECSTOR_TA_MGMT_BOOTSTRAP:
1735843bb75SJerome Forissier 		return bootstrap(param_types, params);
1745843bb75SJerome Forissier 	default:
1755843bb75SJerome Forissier 		break;
1765843bb75SJerome Forissier 	}
1775843bb75SJerome Forissier 	return TEE_ERROR_NOT_IMPLEMENTED;
1785843bb75SJerome Forissier }
1795843bb75SJerome Forissier 
1805843bb75SJerome Forissier pseudo_ta_register(.uuid = PTA_SECSTOR_TA_MGMT_UUID, .name = "secstor_ta_mgmt",
1815843bb75SJerome Forissier 		   /*
1825843bb75SJerome Forissier 		    * TA_FLAG_SINGLE_INSTANCE and TA_FLAG_MULTI_SESSION are
1835843bb75SJerome Forissier 		    * current part of PTA_DEFAULT_FLAGS, but as this TA
1845843bb75SJerome Forissier 		    * depends on those two flags we add them explicitly
1855843bb75SJerome Forissier 		    * too.
1865843bb75SJerome Forissier 		    */
1875843bb75SJerome Forissier 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SINGLE_INSTANCE |
1885843bb75SJerome Forissier 			    TA_FLAG_MULTI_SESSION,
1895843bb75SJerome Forissier 		   .invoke_command_entry_point = invoke_command);
190