-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a pseudo TA for management of Trusted Applications and Security Domains. The pseudo TA only provides a minimal interface, a more advanced interface is supposed to be provided by a user TA using this pseudo TA. Such a TA could for instance implement Global Platforms TEE Management Framework or OTrP. The management TA currently only supports installing bootstrap packaged TAs in secure storage. Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
- Loading branch information
1 parent
bf2f0e9
commit f4a4b84
Showing
6 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,277 @@ | ||
/* | ||
* Copyright (c) 2017, Linaro Limited | ||
* All rights reserved. | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#include <kernel/pseudo_ta.h> | ||
#include <tee/tadb.h> | ||
#include <pta_management.h> | ||
#include <signed_hdr.h> | ||
#include <string_ext.h> | ||
#include <string.h> | ||
#include <ta_pub_key.h> | ||
#include <tee_api_types.h> | ||
#include <crypto/crypto.h> | ||
#include <tee/tee_cryp_utl.h> | ||
#include <tee/uuid.h> | ||
#include <types_ext.h> | ||
#include <utee_defines.h> | ||
|
||
static TEE_Result alloc_and_copy_shdr(struct shdr **shdr, const struct shdr *nw, | ||
size_t nw_size) | ||
{ | ||
size_t shdr_size; | ||
|
||
if (nw_size < sizeof(struct shdr)) | ||
return TEE_ERROR_SECURITY; | ||
shdr_size = SHDR_GET_SIZE(nw); | ||
if (nw_size < shdr_size) | ||
return TEE_ERROR_SECURITY; | ||
*shdr = malloc(shdr_size); | ||
if (!*shdr) | ||
return TEE_ERROR_SECURITY; | ||
memcpy(*shdr, nw, shdr_size); | ||
if (shdr_size != SHDR_GET_SIZE(*shdr)) { | ||
free(*shdr); | ||
return TEE_ERROR_SECURITY; | ||
} | ||
|
||
return TEE_SUCCESS; | ||
} | ||
|
||
static TEE_Result check_shdr(struct shdr *shdr) | ||
{ | ||
struct rsa_public_key key; | ||
TEE_Result res; | ||
uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); | ||
size_t hash_size; | ||
|
||
if (shdr->magic != SHDR_MAGIC) | ||
return TEE_ERROR_SECURITY; | ||
|
||
if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) | ||
return TEE_ERROR_SECURITY; | ||
|
||
res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo), | ||
&hash_size); | ||
if (res != TEE_SUCCESS) | ||
return res; | ||
if (hash_size != shdr->hash_size) | ||
return TEE_ERROR_SECURITY; | ||
|
||
res = crypto_acipher_alloc_rsa_public_key(&key, shdr->sig_size); | ||
if (res != TEE_SUCCESS) | ||
return TEE_ERROR_SECURITY; | ||
|
||
res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); | ||
if (res != TEE_SUCCESS) | ||
goto out; | ||
res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size, | ||
key.n); | ||
if (res != TEE_SUCCESS) | ||
goto out; | ||
|
||
res = crypto_acipher_rsassa_verify(shdr->algo, &key, -1, | ||
SHDR_GET_HASH(shdr), shdr->hash_size, | ||
SHDR_GET_SIG(shdr), shdr->sig_size); | ||
out: | ||
crypto_acipher_free_rsa_public_key(&key); | ||
if (res != TEE_SUCCESS) | ||
return TEE_ERROR_SECURITY; | ||
return TEE_SUCCESS; | ||
} | ||
|
||
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 __maybe_unused; | ||
|
||
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 (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; | ||
|
||
res = alloc_and_copy_shdr(&shdr, params->memref.buffer, | ||
params->memref.size); | ||
if (res) | ||
return res; | ||
|
||
res = check_shdr(shdr); | ||
if (res) | ||
goto out; | ||
|
||
if (shdr->img_type == SHDR_BOOTSTRAP_TA) { | ||
res = install_ta(shdr, params->memref.buffer, | ||
params->memref.size); | ||
} else { | ||
res = TEE_ERROR_NOT_SUPPORTED; | ||
} | ||
|
||
out: | ||
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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters