Skip to content

Commit

Permalink
Add support for early Trusted Applications
Browse files Browse the repository at this point in the history
Early TAs are user-mode Trusted Applications that are embedded at link
time in the TEE binary. A special read-only data section is used to
store them (.rodata.early_ta). A Python script takes care of converting
the TAs into a C source file with the proper linker section attribute.

The feature is disabled by default. To enable it, the paths to the TA
binaries have to be given in $(EARLY_TA_PATHS). They should be ELF
files. Typical build steps:
  $ make ... CFG_EARLY_TA=y ta_dev_kit                    # (1)
  $ # ... build the TAs ...                               # (2)
  $ make ... EARLY_TA_PATHS=path/to/<uuid>.stripped.elf   # (3)
Notes:
- Setting CFG_EARLY_TA=y during the first step (1) is not necessary,
   but it will avoid rebuilding libraries during the third step (3)
- CFG_EARLY_TA is automatically enabled when EARLY_TA_PATHS is non-empty
  in step (3)
- Several TAs may be given in $(EARLY_TA_PATHS) (3)

Early TAs are given a higher load priority than REE FS TAs, since they
should be available even before tee-supplicant is ready.

Suggested-by: Zeng Tao <prime.zeng@hisilicon.com>
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
  • Loading branch information
jforissier committed Aug 25, 2017
1 parent 23346f1 commit d0c6361
Show file tree
Hide file tree
Showing 12 changed files with 331 additions and 6 deletions.
41 changes: 41 additions & 0 deletions core/arch/arm/include/kernel/early_ta.h
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef KERNEL_EARLY_TA_H
#define KERNEL_EARLY_TA_H

#include <compiler.h>
#include <stdint.h>
#include <tee_api_types.h>

struct early_ta {
TEE_UUID uuid;
uint32_t size;
const uint8_t ta[]; /* @size bytes */
};

#endif /* KERNEL_EARLY_TA_H */

6 changes: 5 additions & 1 deletion core/arch/arm/include/kernel/linker.h
Expand Up @@ -28,8 +28,9 @@
#define __KERNEL_LINKER_H

#include <initcall.h>
#include <kernel/pseudo_ta.h>
#include <kernel/dt.h>
#include <kernel/early_ta.h>
#include <kernel/pseudo_ta.h>
#include <mm/core_mmu.h>
#include <types_ext.h>

Expand Down Expand Up @@ -116,6 +117,9 @@ extern const vaddr_t __ctor_end;
extern const struct dt_driver __rodata_dtdrv_start;
extern const struct dt_driver __rodata_dtdrv_end;

extern const struct early_ta __rodata_early_ta_start;
extern const struct early_ta __rodata_early_ta_end;

/* Generated by core/arch/arm/kernel/link.mk */
extern const char core_v_str[];

Expand Down
124 changes: 124 additions & 0 deletions core/arch/arm/kernel/early_ta.c
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <initcall.h>
#include <kernel/early_ta.h>
#include <kernel/linker.h>
#include <kernel/user_ta.h>
#include <string.h>
#include <trace.h>
#include <util.h>

#include "elf_load.h"

struct user_ta_store_handle {
const struct early_ta *early_ta;
size_t offs;
};

#define for_each_early_ta(_ta) \
for (_ta = &__rodata_early_ta_start; _ta < &__rodata_early_ta_end; \
_ta = (const struct early_ta *) \
ROUNDUP((vaddr_t)_ta + sizeof(*_ta) + _ta->size, \
__alignof__(struct early_ta)))

static const struct early_ta *find_early_ta(const TEE_UUID *uuid)
{
const struct early_ta *ta;

for_each_early_ta(ta)
if (!memcmp(&ta->uuid, uuid, sizeof(*uuid)))
return ta;

return NULL;
}

static TEE_Result early_ta_open(const TEE_UUID *uuid,
struct user_ta_store_handle **h)
{
const struct early_ta *ta;
struct user_ta_store_handle *handle;

ta = find_early_ta(uuid);
if (!ta)
return TEE_ERROR_ITEM_NOT_FOUND;

handle = calloc(1, sizeof(*handle));
if (!handle)
return TEE_ERROR_OUT_OF_MEMORY;

handle->early_ta = ta;
*h = handle;

return TEE_SUCCESS;
}

static TEE_Result early_ta_get_size(const struct user_ta_store_handle *h,
size_t *size)
{
*size = h->early_ta->size;
return TEE_SUCCESS;
}

static TEE_Result early_ta_read(struct user_ta_store_handle *h, void *data,
size_t len)
{
uint8_t *src = (uint8_t *)h->early_ta->ta + h->offs;

if (h->offs + len > h->early_ta->size)
return TEE_ERROR_BAD_PARAMETERS;
if (data)
memcpy(data, src, len);
h->offs += len;

return TEE_SUCCESS;
}

static void early_ta_close(struct user_ta_store_handle *h)
{
free(h);
}

static struct user_ta_store_ops ops = {
.description = "early TA",
.open = early_ta_open,
.get_size = early_ta_get_size,
.read = early_ta_read,
.close = early_ta_close,
.priority = 5,
};

static TEE_Result early_ta_init(void)
{
const struct early_ta *ta;

for_each_early_ta(ta)
DMSG("Early TA %pUl size %u", (void *)&ta->uuid, ta->size);

return tee_ta_register_ta_store(&ops);
}

service_init(early_ta_init);
13 changes: 13 additions & 0 deletions core/arch/arm/kernel/kern.ld.S
Expand Up @@ -118,6 +118,13 @@ SECTIONS
KEEP(*(.rodata.dtdrv))
__rodata_dtdrv_end = .;
#endif
#ifdef CFG_EARLY_TA
. = ALIGN(8);
__rodata_early_ta_start = .;
KEEP(*(.rodata.early_ta))
__rodata_early_ta_end = .;
#endif

*(.rodata .rodata.*)

/*
Expand Down Expand Up @@ -328,6 +335,12 @@ SECTIONS
__rodata_dtdrv_start = .;
KEEP(*(.rodata.dtdrv))
__rodata_dtdrv_end = .;
#endif
#ifdef CFG_EARLY_TA
. = ALIGN(8);
__rodata_early_ta_start = .;
KEEP(*(.rodata.early_ta))
__rodata_early_ta_end = .;
#endif
*(.rodata*)
/*
Expand Down
2 changes: 2 additions & 0 deletions core/arch/arm/kernel/link_dummy.ld
Expand Up @@ -66,6 +66,8 @@ __pageable_part_start = .;
__pageable_start = .;
__rodata_dtdrv_end = .;
__rodata_dtdrv_start = .;
__rodata_early_ta_start = .;
__rodata_early_ta_end = .;
__rodata_end = .;
__rodata_start = .;
__start_phys_nsec_ddr_section = .;
Expand Down
1 change: 1 addition & 0 deletions core/arch/arm/kernel/sub.mk
@@ -1,6 +1,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
endif
srcs-y += pseudo_ta.c
srcs-y += elf_load.c
Expand Down
13 changes: 8 additions & 5 deletions core/arch/arm/kernel/user_ta.c
Expand Up @@ -625,16 +625,19 @@ TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
struct tee_ta_session *s)
{
const struct user_ta_store_ops *store;
TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND;
TEE_Result res;

SLIST_FOREACH(store, &uta_store_list, link) {
DMSG("Lookup user TA %pUl (%s)", (void *)uuid,
store->description);
res = ta_load(uuid, store, &s->ctx);
if (res == TEE_SUCCESS) {
if (res == TEE_ERROR_ITEM_NOT_FOUND)
continue;
if (res == TEE_SUCCESS)
s->ctx->ops = &user_ta_ops;
return res;
}
else
DMSG("res=0x%x", res);
return res;
}
return res;
return TEE_ERROR_ITEM_NOT_FOUND;
}
6 changes: 6 additions & 0 deletions core/arch/arm/plat-sunxi/kern.ld.S
Expand Up @@ -129,6 +129,12 @@ SECTIONS

.rodata : ALIGN(4) {
__rodata_start = .;
#ifdef CFG_EARLY_TA
. = ALIGN(8);
__rodata_early_ta_start = .;
KEEP(*(.rodata.early_ta))
__rodata_early_ta_end = .;
#endif
*(.rodata .rodata.* .gnu.linkonce.r.*)

/*
Expand Down
13 changes: 13 additions & 0 deletions core/sub.mk
Expand Up @@ -10,3 +10,16 @@ recipe-ta_pub_key = scripts/pem_to_pub_c.py --prefix ta_pub_key \
--key $(TA_SIGN_KEY) --out $(sub-dir-out)/ta_pub_key.c
cleanfiles += $(sub-dir-out)/ta_pub_key.c
endif

ifeq ($(CFG_WITH_USER_TA)-$(CFG_EARLY_TA),y-y)
define process_early_ta
early-ta-$1-uuid := $(firstword $(subst ., ,$(notdir $1)))
gensrcs-y += early-ta-$1
produce-early-ta-$1 = early_ta_$$(early-ta-$1-uuid).c
depends-early-ta-$1 = $1 scripts/ta_bin_to_c.py
recipe-early-ta-$1 = scripts/ta_bin_to_c.py --ta $1 \
--out $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c
cleanfiles += $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c
endef
$(foreach f, $(EARLY_TA_PATHS), $(eval $(call process_early_ta,$(f))))
endif
1 change: 1 addition & 0 deletions lib/libutils/ext/include/compiler.h
Expand Up @@ -52,6 +52,7 @@
#define __bss __section(".bss")
#define __rodata __section(".rodata")
#define __rodata_unpaged __section(".rodata.__unpaged")
#define __early_ta __section(".rodata.early_ta")
#define __noprof __attribute__((no_instrument_function))

#define __compiler_bswap64(x) __builtin_bswap64((x))
Expand Down
22 changes: 22 additions & 0 deletions mk/config.mk
Expand Up @@ -176,6 +176,28 @@ CFG_WITH_USER_TA ?= y
# case you implement your own TA store
CFG_REE_FS_TA ?= y

# Support for loading user TAs from a special section in the TEE binary.
# Such TAs are available even before tee-supplicant is available (hence their
# name), but note that many services exported to TAs may need tee-supplicant,
# so early use is limited to a subset of the TEE Internal Core API (crypto...)
# To use this feature, set EARLY_TA_PATHS to the paths to one or more TA ELF
# file(s). For example:
# $ make ... \
# EARLY_TA_PATHS="path/to/8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf \
# path/to/cb3e5ba0-adf1-11e0-998b-0002a5d5c51b.stripped.elf"
# Typical build steps:
# $ make ta_dev_kit CFG_EARLY_TA=y # Create the dev kit (user mode libraries,
# # headers, makefiles), ready to build TAs.
# # CFG_EARLY_TA=y is optional, it prevents
# # later library recompilations.
# <build some TAs>
# $ make EARLY_TA_PATHS=<paths> # Build OP-TEE and embbed the TA(s)
ifneq ($(EARLY_TA_PATHS),)
$(call force,CFG_EARLY_TA,y)
else
CFG_EARLY_TA ?= n
endif

# Enable paging, requires SRAM, can't be enabled by default
CFG_WITH_PAGER ?= n

Expand Down

0 comments on commit d0c6361

Please sign in to comment.