Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Bootstrap ta #1928

Merged
merged 12 commits into from
Dec 7, 2017
116 changes: 42 additions & 74 deletions core/arch/arm/kernel/ree_fs_ta.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@
#include <signed_hdr.h>
#include <stdlib.h>
#include <string.h>
#include <ta_pub_key.h>
#include <tee_api_types.h>
#include <tee/tee_cryp_utl.h>
#include <tee/tee_svc_cryp.h>
#include <tee/uuid.h>
#include <utee_defines.h>

Expand All @@ -56,71 +53,6 @@ struct user_ta_store_handle {
uint32_t hash_algo;
};

static TEE_Result alloc_and_copy_shdr(struct shdr **shdr_ret,
const struct shdr *nw_ta,
size_t ta_size)
{
struct shdr *shdr;
size_t shdr_size;

if (ta_size < sizeof(struct shdr))
return TEE_ERROR_SECURITY;
shdr_size = SHDR_GET_SIZE(nw_ta);
if (ta_size < shdr_size)
return TEE_ERROR_SECURITY;
shdr = malloc(shdr_size);
if (!shdr)
return TEE_ERROR_SECURITY;
memcpy(shdr, nw_ta, shdr_size);
if (shdr_size != SHDR_GET_SIZE(shdr)) {
free(shdr);
return TEE_ERROR_SECURITY;
}
*shdr_ret = shdr;
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 || shdr->img_type != SHDR_TA)
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 res;

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;
}
/*
* Load a TA via RPC with UUID defined by input param @uuid. The virtual
* address of the raw TA binary is received in out parameter @ta.
Expand Down Expand Up @@ -182,6 +114,7 @@ static TEE_Result ta_open(const TEE_UUID *uuid,
size_t ta_size = 0;
uint64_t cookie = 0;
TEE_Result res;
size_t offs;

handle = calloc(1, sizeof(*handle));
if (!handle)
Expand All @@ -193,14 +126,20 @@ static TEE_Result ta_open(const TEE_UUID *uuid,
goto error;

/* Make secure copy of signed header */
res = alloc_and_copy_shdr(&shdr, ta, ta_size);
if (res != TEE_SUCCESS)
shdr = shdr_alloc_and_copy(ta, ta_size);
if (!shdr) {
res = TEE_ERROR_SECURITY;
goto error_free_payload;
}

/* Validate header signature */
res = check_shdr(shdr);
res = shdr_verify_signature(shdr);
if (res != TEE_SUCCESS)
goto error_free_payload;
if (shdr->img_type != SHDR_TA && shdr->img_type != SHDR_BOOTSTRAP_TA) {
res = TEE_ERROR_SECURITY;
goto error_free_payload;
}

/*
* Initialize a hash context and run the algorithm over the signed
Expand All @@ -222,16 +161,45 @@ static TEE_Result ta_open(const TEE_UUID *uuid,
sizeof(*shdr));
if (res != TEE_SUCCESS)
goto error_free_payload;
offs = SHDR_GET_SIZE(shdr);

if (shdr->img_type == SHDR_BOOTSTRAP_TA) {
TEE_UUID bs_uuid;
struct shdr_bootstrap_ta bs_hdr;

if (ta_size < SHDR_GET_SIZE(shdr) + sizeof(bs_hdr))
return TEE_ERROR_SECURITY;

memcpy(&bs_hdr, ((uint8_t *)ta + offs), sizeof(bs_hdr));

/*
* There's a check later that the UUID embedded inside the
* ELF is matching, but since we now have easy access to
* the expected uuid of the TA we check it a bit earlier
* here.
*/
tee_uuid_from_octets(&bs_uuid, bs_hdr.uuid);
if (memcmp(&bs_uuid, uuid, sizeof(TEE_UUID))) {
res = TEE_ERROR_SECURITY;
goto error_free_payload;
}

res = crypto_hash_update(hash_ctx, hash_algo,
(uint8_t *)&bs_hdr, sizeof(bs_hdr));
if (res != TEE_SUCCESS)
goto error_free_payload;
offs += sizeof(bs_hdr);
}

if (ta_size != SHDR_GET_SIZE(shdr) + shdr->img_size) {
if (ta_size != offs + shdr->img_size) {
res = TEE_ERROR_SECURITY;
goto error_free_payload;
}

handle->nw_ta = ta;
handle->nw_ta_size = ta_size;
handle->cookie = cookie;
handle->offs = SHDR_GET_SIZE(shdr);
handle->offs = offs;
handle->hash_algo = hash_algo;
handle->hash_ctx = hash_ctx;
handle->shdr = shdr;
Expand All @@ -243,7 +211,7 @@ static TEE_Result ta_open(const TEE_UUID *uuid,
thread_rpc_free_payload(cookie, mobj);
error:
free(hash_ctx);
free(shdr);
shdr_free(shdr);
free(handle);
return res;
}
Expand Down
87 changes: 87 additions & 0 deletions core/arch/arm/kernel/secstor_ta.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2017, Linaro Limited
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <tee/tadb.h>
#include <kernel/user_ta.h>
#include <initcall.h>
#include "elf_load.h"

static TEE_Result secstor_ta_open(const TEE_UUID *uuid,
struct user_ta_store_handle **handle)
{
TEE_Result res;
struct tee_tadb_ta_read *ta;
size_t l;
const struct tee_tadb_property *prop;

res = tee_tadb_ta_open(uuid, &ta);
if (res)
return res;
prop = tee_tadb_ta_get_property(ta);

l = prop->custom_size;
res = tee_tadb_ta_read(ta, NULL, &l);
if (res)
goto err;
if (l != prop->custom_size)
goto err;

*handle = (struct user_ta_store_handle *)ta;

return TEE_SUCCESS;
err:
tee_tadb_ta_close(ta);
return res;
}

static TEE_Result secstor_ta_get_size(const struct user_ta_store_handle *h,
size_t *size)
{
struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h;
const struct tee_tadb_property *prop = tee_tadb_ta_get_property(ta);

*size = prop->bin_size;

return TEE_SUCCESS;
}

static TEE_Result secstor_ta_read(struct user_ta_store_handle *h, void *data,
size_t len)
{
struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h;
size_t l = len;
TEE_Result res = tee_tadb_ta_read(ta, data, &l);

if (res)
return res;
if (l != len)
return TEE_ERROR_BAD_PARAMETERS;

return TEE_SUCCESS;
}

static void secstor_ta_close(struct user_ta_store_handle *h)
{
struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h;

tee_tadb_ta_close(ta);
}

static struct user_ta_store_ops ops = {
.description = "Secure Storage TA",
.open = secstor_ta_open,
.get_size = secstor_ta_get_size,
.read = secstor_ta_read,
.close = secstor_ta_close,
.priority = 9,
};

static TEE_Result secstor_ta_init(void)
{
return tee_ta_register_ta_store(&ops);
}

service_init(secstor_ta_init);
1 change: 1 addition & 0 deletions core/arch/arm/kernel/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ ifeq ($(CFG_WITH_USER_TA),y)
srcs-y += user_ta.c
srcs-$(CFG_REE_FS_TA) += ree_fs_ta.c
srcs-$(CFG_EARLY_TA) += early_ta.c
srcs-$(CFG_SECSTOR_TA) += secstor_ta.c
endif
srcs-y += pseudo_ta.c
srcs-y += elf_load.c
Expand Down
Loading