blob: 44be1d29cb461c4b876572de330b3c29068e333c [file] [log] [blame]
.. _trusted_applications:
####################
Trusted Applications
####################
There are two ways to implement Trusted Applications (TAs), Pseudo TAs and user
mode TAs. User mode TAs are full featured Trusted Applications as specified by
the :ref:`globalplatform_api` TEE specifications, these are simply the ones
people are referring to when they are saying "Trusted Applications" and in most
cases this is the preferred type of TA to write and use.
.. _pta:
Pseudo Trusted Applications
***************************
These are implemented directly to the OP-TEE core tree in, e.g.,
``core/pta`` and are built along with and statically built into the
OP-TEE core blob.
The Pseudo Trusted Applications included in OP-TEE already are OP-TEE secure
privileged level services hidden behind a "GlobalPlatform TA Client" API. These
Pseudo TAs are used for various purposes such as specific secure services or
embedded tests services.
Pseudo TAs **do not** benefit from the GlobalPlatform Core Internal API support
specified by the GlobalPlatform TEE specs. These APIs are provided to TAs as a
static library each TA shall link against (the ":ref:`libutee`") and that calls
OP-TEE core service through system calls. As OP-TEE core does not link with
:ref:`libutee`, Pseudo TAs can **only** use the OP-TEE core internal APIs and
routines.
As Pseudo TAs runs at the same privileged execution level as the OP-TEE core
code itself and that might or might not be desirable depending on the use case.
In most cases an unprivileged (user mode) TA is the best choice instead of
adding your code directly to the OP-TEE core. However if you decide your
application is best handled directly in OP-TEE core like this, you can look at
``core/pta/stats.c`` as a template and just add your Pseudo TA based on
that to the ``sub.mk`` in the same directory.
.. _user_mode_ta:
User Mode Trusted Applications
******************************
User Mode Trusted Applications are loaded (mapped into memory) by OP-TEE core in
the Secure World when something in Rich Execution Environment (REE) wants to
talk to that particular application UUID. They run at a lower CPU privilege
level than OP-TEE core code. In that respect, they are quite similar to regular
applications running in the REE, except that they execute in Secure World.
Trusted Application benefit from the GlobalPlatform :ref:`tee_internal_core_api`
as specified by the GlobalPlatform TEE specifications. There are several types
of user mode TAs, which differ by the way they are stored.
TA locations
************
Plain TAs (user mode) can reside and be loaded from various places. There are
three ways currently supported in OP-TEE.
.. _early_ta:
Early TA
========
The so-called early TAs are virtually identical to the REE FS TAs, but instead
of being loaded from the Normal World file system, they are linked into a
special data section in the TEE core blob. Therefore, they are available even
before ``tee-supplicant`` and the REE's filesystems have come up. Please find
more details in the `early TA commit`_.
.. _ree_fs_ta:
REE filesystem TA
=================
They consist of a cleartext signed ELF_ file, named from the UUID of the TA and
the suffix ``.ta``. They are built separately from the OP-TEE core boot-time
blob, although when they are built they use the same build system, and are
signed with the key from the build of the original OP-TEE core blob.
Because the TAs are signed, they are able to be stored in the untrusted REE
filesystem, and ``tee-supplicant`` will take care of passing them to be checked
and loaded by the Secure World OP-TEE core. Note that this type of TA isn't
encrypted.
REE filesystem TAs come in two formats, the legacy TA and the bootstrap TA.
The bootstrap TA format is used by ``scripts/sign.py`` since version 3.7.0.
All REE filesystems TAs has common header, ``struct shdr``, defined as:
.. code-block:: c
enum shdr_img_type {
SHDR_TA = 0,
SHDR_BOOTSTRAP_TA = 1,
};
#define SHDR_MAGIC 0x4f545348
/**
* struct shdr - signed header
* @magic: magic number must match SHDR_MAGIC
* @img_type: image type, values defined by enum shdr_img_type
* @img_size: image size in bytes
* @algo: algorithm, defined by public key algorithms TEE_ALG_*
* from TEE Internal API specification
* @hash_size: size of the signed hash
* @sig_size: size of the signature
* @hash: hash of an image
* @sig: signature of @hash
*/
struct shdr {
uint32_t magic;
uint32_t img_type;
uint32_t img_size;
uint32_t algo;
uint16_t hash_size;
uint16_t sig_size;
/*
* Commented out element used to visualize the layout dynamic part
* of the struct.
*
* hash is accessed through the macro SHDR_GET_HASH and
* signature is accessed through the macro SHDR_GET_SIG
*
* uint8_t hash[hash_size];
* uint8_t sig[sig_size];
*/
};
#define SHDR_GET_SIZE(x) (sizeof(struct shdr) + (x)->hash_size + \
(x)->sig_size)
#define SHDR_GET_HASH(x) (uint8_t *)(((struct shdr *)(x)) + 1)
#define SHDR_GET_SIG(x) (SHDR_GET_HASH(x) + (x)->hash_size)
The field ``image_type`` tells the type of TA, if it's ``SHDR_TA`` (0),
it's a legacy TA. If it's ``SHDR_BOOTSTRAP_TA`` (1) it's a bootstrap TA.
For bootstrap TAs ``struct shdr`` is followed by a subheader, ``struct
shdr_bootstrap_ta`` which is defined as:
.. code-block:: c
/**
* struct shdr_bootstrap_ta - bootstrap TA subheader
* @uuid: UUID of the TA
* @ta_version: Version of the TA
*/
struct shdr_bootstrap_ta {
uint8_t uuid[sizeof(TEE_UUID)];
uint32_t ta_version;
};
The fields ``uuid`` and ``ta_version`` allows extra checks to be performed
when loading the TA. Currently only the ``uuid`` field is checked.
Last in the TA binary follows the ELF file which normally is stripped
as additional symbols etc will be ignored when loading the TA.
Legacy TA binary is formatted as:
.. code-block:: none
hash = H(<struct shdr> || <stripped ELF>)
signature = RSA-Sign(hash)
legacy_binary = <struct shdr> || <hash> || <signature> || <stripped ELF>
Bootstrap TA binary is formatted as:
.. code-block:: none
hash = H(<struct shdr> || <struct shdr_bootstrap_ta> || <stripped ELF>)
signature = RSA-Sign(<hash>)
bootstrap_binary = <struct shdr> || <hash> || <signature> ||
<struct shdr_bootstrap_ta> || <stripped ELF>
A REE TA is loaded into shared memory using a series or RPC in
:ref:`load_ree_ta`. The payload memory is allocated via TEE-supplicant and
later freed when the TA has been loaded into secure memory in
:ref:`free_appl_shm`.
.. _load_ree_ta:
.. figure:: ../images/trusted_applications/load_ree_ta.png
:figclass: align-center
Loading a REE TA into nonsecure shared memory
.. _free_appl_shm:
.. figure:: ../images/trusted_applications/free_appl_shm.png
:figclass: align-center
Freeing previously allocated nonsecure shared memory
.. _secure_storage_ta:
Secure Storage TA
=================
These are stored in secure storage. The meta data is stored in a database of all
installed TAs and the actual binary is stored encrypted and integrity protected
as a separate file in the untrusted REE filesystem (flash). Before these TAs can
be loaded they have to be installed first, this is something that can be done
during initial deployment or at a later stage.
For test purposes the test program xtest can install a TA into secure storage
with the command:
.. code-block:: bash
$ xtest --install-ta
.. _ta_properties:
TA Properties
*************
This section give a more in depth description of the TA properties (see
:ref:`build_trusted_applications` also).
GlobalPlatform Properties
=========================
Standard TA properties must be defined through property flag in macro
``TA_FLAGS`` in ``user_ta_header_defines.h``
Single Instance
---------------
``"gpd.ta.singleInstance"`` is a boolean property of the TA. This property
defines if one instance of the TA must be created and will receive all open
session request, or if a new specific TA instance must be created for each
incoming open session request. OP-TEE TA flag ``TA_FLAG_SINGLE_INSTANCE`` sets
to configuration of this property. The boolean property is set to ``true`` if
``TA_FLAGS`` sets bit ``TA_FLAG_SINGLE_INSTANCE``, otherwise the boolean
property is set to ``false``.
Multi-session
-------------
``"gpd.ta.multiSession"`` is a boolean property of the TA. This property defines
if the TA instance can handle several sessions. If disabled, TA instance support
only one session. In such case, if the TA already has a opened session, any open
session request will return with a busy error status.
.. note::
This property is **meaningless** if TA is **NOT** SingleInstance TA.
OP-TEE TA flag ``TA_FLAG_MULTI_SESSION`` sets to configuration of this property.
The boolean property is set to ``true`` if ``TA_FLAGS`` sets bit
``TA_FLAG_MULTI_SESSION``, otherwise the boolean property is set to ``false``.
Keep Alive
----------
``"gpd.ta.instanceKeepAlive"`` is a boolean property of the TA. This property
defines if the TA instance created must be destroyed or not when all sessions
opened towards the TA are closed. If the property is enabled, TA instance, once
created (at 1st open session request), is never removed unless the TEE itself is
restarted (boot/reboot).
.. note::
This property is **meaningless** if TA is **NOT** SingleInstance TA.
OP-TEE TA flag ``TA_FLAG_INSTANCE_KEEP_ALIVE`` sets to configuration of this
property. The boolean property is set to ``true`` if ``TA_FLAGS`` sets bit
``TA_FLAG_INSTANCE_KEEP_ALIVE``, otherwise the boolean property is set to
``false``.
Heap Size
---------
``"gpd.ta.dataSize"`` is a 32bit integer property of the TA. This property
defines the size in bytes of the TA allocation pool, in which ``TEE_Malloc()``
and friends allocate memory. The value of the property must be defined by the
macro ``TA_DATA_SIZE`` in ``user_ta_header_defines.h`` (see
:ref:`build_ta_properties`).
Stack Size
----------
``"gpd.ta.stackSize"`` is a 32bit integer property of the TA. This property
defines the size in bytes of the stack used for TA execution. The value of the
property must be defined by the macro ``TA_STACK_SIZE`` in
``user_ta_header_defines.h`` (see :ref:`build_ta_properties`).
Property Extensions
===================
Secure Data Path Flag
---------------------
``TA_FLAG_SECURE_DATA_PATH`` is a bit flag supported by ``TA_FLAGS``. This
property flag claims the secure data support from the OP-TEE OS for the TA.
Refer to the OP-TEE OS for secure data path support. TAs that do not set
``TA_FLAG_SECURE_DATA_PATH`` in the value of ``TA_FLAGS`` will **not** be able
to handle memory reference invocation parameters that relate to secure data path
buffers.
.. _ta_property_cache_maintenance:
Cache maintenance Flag
----------------------
``TA_FLAG_CACHE_MAINTENANCE`` is a bit flag supported by ``TA_FLAGS``. This
property flag, when enabled, allows Trusted Applciation to use the cache
maintenance API extension of the Internal Core API described in
:ref:`extensions_cache_maintenance`. TAs that do not set
``TA_FLAG_CACHE_MAINTENANCE`` in the value of their ``TA_FLAGS`` will not be
able to call the cache maintenance API.
Deprecated Property Flags
-------------------------
Older versions of OP-TEE used to define extended property flags that are
deprecated and meaningless to current OP-TEE. These are ``TA_FLAG_USER_MODE``,
``TA_FLAG_EXEC_DDR`` and ``TA_FLAG_REMAP_SUPPORT``.
.. _ELF: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
.. _early TA commit: https://github.com/OP-TEE/optee_os/commit/d0c636148b3a