Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 1 | .. _trusted_applications: |
| 2 | |
| 3 | #################### |
| 4 | Trusted Applications |
| 5 | #################### |
| 6 | There are two ways to implement Trusted Applications (TAs), Pseudo TAs and user |
| 7 | mode TAs. User mode TAs are full featured Trusted Applications as specified by |
| 8 | the :ref:`globalplatform_api` TEE specifications, these are simply the ones |
| 9 | people are referring to when they are saying "Trusted Applications" and in most |
| 10 | cases this is the preferred type of TA to write and use. |
| 11 | |
| 12 | .. _pta: |
| 13 | |
| 14 | Pseudo Trusted Applications |
| 15 | *************************** |
| 16 | These are implemented directly to the OP-TEE core tree in, e.g., |
Jerome Forissier | fa993db | 2019-09-13 15:58:53 +0200 | [diff] [blame] | 17 | ``core/pta`` and are built along with and statically built into the |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 18 | OP-TEE core blob. |
| 19 | |
| 20 | The Pseudo Trusted Applications included in OP-TEE already are OP-TEE secure |
| 21 | privileged level services hidden behind a "GlobalPlatform TA Client" API. These |
| 22 | Pseudo TAs are used for various purposes such as specific secure services or |
| 23 | embedded tests services. |
| 24 | |
| 25 | Pseudo TAs **do not** benefit from the GlobalPlatform Core Internal API support |
| 26 | specified by the GlobalPlatform TEE specs. These APIs are provided to TAs as a |
| 27 | static library each TA shall link against (the ":ref:`libutee`") and that calls |
| 28 | OP-TEE core service through system calls. As OP-TEE core does not link with |
| 29 | :ref:`libutee`, Pseudo TAs can **only** use the OP-TEE core internal APIs and |
| 30 | routines. |
| 31 | |
| 32 | As Pseudo TAs runs at the same privileged execution level as the OP-TEE core |
| 33 | code itself and that might or might not be desirable depending on the use case. |
| 34 | |
| 35 | In most cases an unprivileged (user mode) TA is the best choice instead of |
| 36 | adding your code directly to the OP-TEE core. However if you decide your |
| 37 | application is best handled directly in OP-TEE core like this, you can look at |
Jerome Forissier | fa993db | 2019-09-13 15:58:53 +0200 | [diff] [blame] | 38 | ``core/pta/stats.c`` as a template and just add your Pseudo TA based on |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 39 | that to the ``sub.mk`` in the same directory. |
| 40 | |
| 41 | .. _user_mode_ta: |
| 42 | |
| 43 | User Mode Trusted Applications |
| 44 | ****************************** |
| 45 | User Mode Trusted Applications are loaded (mapped into memory) by OP-TEE core in |
| 46 | the Secure World when something in Rich Execution Environment (REE) wants to |
| 47 | talk to that particular application UUID. They run at a lower CPU privilege |
| 48 | level than OP-TEE core code. In that respect, they are quite similar to regular |
| 49 | applications running in the REE, except that they execute in Secure World. |
| 50 | |
| 51 | Trusted Application benefit from the GlobalPlatform :ref:`tee_internal_core_api` |
| 52 | as specified by the GlobalPlatform TEE specifications. There are several types |
| 53 | of user mode TAs, which differ by the way they are stored. |
| 54 | |
| 55 | TA locations |
| 56 | ************ |
| 57 | Plain TAs (user mode) can reside and be loaded from various places. There are |
| 58 | three ways currently supported in OP-TEE. |
| 59 | |
| 60 | .. _early_ta: |
| 61 | |
| 62 | Early TA |
| 63 | ======== |
| 64 | The so-called early TAs are virtually identical to the REE FS TAs, but instead |
| 65 | of being loaded from the Normal World file system, they are linked into a |
| 66 | special data section in the TEE core blob. Therefore, they are available even |
| 67 | before ``tee-supplicant`` and the REE's filesystems have come up. Please find |
| 68 | more details in the `early TA commit`_. |
| 69 | |
| 70 | .. _ree_fs_ta: |
| 71 | |
| 72 | REE filesystem TA |
| 73 | ================= |
| 74 | They consist of a cleartext signed ELF_ file, named from the UUID of the TA and |
| 75 | the suffix ``.ta``. They are built separately from the OP-TEE core boot-time |
| 76 | blob, although when they are built they use the same build system, and are |
| 77 | signed with the key from the build of the original OP-TEE core blob. |
| 78 | |
| 79 | Because the TAs are signed, they are able to be stored in the untrusted REE |
| 80 | filesystem, and ``tee-supplicant`` will take care of passing them to be checked |
| 81 | and loaded by the Secure World OP-TEE core. Note that this type of TA isn't |
| 82 | encrypted. |
| 83 | |
Jens Wiklander | 6054d68 | 2019-11-19 11:31:14 +0100 | [diff] [blame^] | 84 | REE filesystem TAs come in two formats, the legacy TA and the bootstrap TA. |
| 85 | The bootstrap TA format is used by ``scripts/sign.py`` since version 3.7.0. |
| 86 | |
| 87 | All REE filesystems TAs has common header, ``struct shdr``, defined as: |
| 88 | |
| 89 | .. code-block:: c |
| 90 | |
| 91 | enum shdr_img_type { |
| 92 | SHDR_TA = 0, |
| 93 | SHDR_BOOTSTRAP_TA = 1, |
| 94 | }; |
| 95 | |
| 96 | #define SHDR_MAGIC 0x4f545348 |
| 97 | |
| 98 | /** |
| 99 | * struct shdr - signed header |
| 100 | * @magic: magic number must match SHDR_MAGIC |
| 101 | * @img_type: image type, values defined by enum shdr_img_type |
| 102 | * @img_size: image size in bytes |
| 103 | * @algo: algorithm, defined by public key algorithms TEE_ALG_* |
| 104 | * from TEE Internal API specification |
| 105 | * @hash_size: size of the signed hash |
| 106 | * @sig_size: size of the signature |
| 107 | * @hash: hash of an image |
| 108 | * @sig: signature of @hash |
| 109 | */ |
| 110 | struct shdr { |
| 111 | uint32_t magic; |
| 112 | uint32_t img_type; |
| 113 | uint32_t img_size; |
| 114 | uint32_t algo; |
| 115 | uint16_t hash_size; |
| 116 | uint16_t sig_size; |
| 117 | /* |
| 118 | * Commented out element used to visualize the layout dynamic part |
| 119 | * of the struct. |
| 120 | * |
| 121 | * hash is accessed through the macro SHDR_GET_HASH and |
| 122 | * signature is accessed through the macro SHDR_GET_SIG |
| 123 | * |
| 124 | * uint8_t hash[hash_size]; |
| 125 | * uint8_t sig[sig_size]; |
| 126 | */ |
| 127 | }; |
| 128 | |
| 129 | #define SHDR_GET_SIZE(x) (sizeof(struct shdr) + (x)->hash_size + \ |
| 130 | (x)->sig_size) |
| 131 | #define SHDR_GET_HASH(x) (uint8_t *)(((struct shdr *)(x)) + 1) |
| 132 | #define SHDR_GET_SIG(x) (SHDR_GET_HASH(x) + (x)->hash_size) |
| 133 | |
| 134 | |
| 135 | The field ``image_type`` tells the type of TA, if it's ``SHDR_TA`` (0), |
| 136 | it's a legacy TA. If it's ``SHDR_BOOTSTRAP_TA`` (1) it's a bootstrap TA. |
| 137 | |
| 138 | For bootstrap TAs ``struct shdr`` is followed by a subheader, ``struct |
| 139 | shdr_bootstrap_ta`` which is defined as: |
| 140 | |
| 141 | .. code-block:: c |
| 142 | |
| 143 | /** |
| 144 | * struct shdr_bootstrap_ta - bootstrap TA subheader |
| 145 | * @uuid: UUID of the TA |
| 146 | * @ta_version: Version of the TA |
| 147 | */ |
| 148 | struct shdr_bootstrap_ta { |
| 149 | uint8_t uuid[sizeof(TEE_UUID)]; |
| 150 | uint32_t ta_version; |
| 151 | }; |
| 152 | |
| 153 | The fields ``uuid`` and ``ta_version`` allows extra checks to be performed |
| 154 | when loading the TA. Currently only the ``uuid`` field is checked. |
| 155 | |
| 156 | Last in the TA binary follows the ELF file which normally is stripped |
| 157 | as additional symbols etc will be ignored when loading the TA. |
| 158 | |
| 159 | Legacy TA binary is formatted as: |
| 160 | |
| 161 | .. code-block:: none |
| 162 | |
| 163 | hash = H(<struct shdr> || <stripped ELF>) |
| 164 | signature = RSA-Sign(hash) |
| 165 | legacy_binary = <struct shdr> || <hash> || <signature> || <stripped ELF> |
| 166 | |
| 167 | Bootstrap TA binary is formatted as: |
| 168 | |
| 169 | .. code-block:: none |
| 170 | |
| 171 | hash = H(<struct shdr> || <struct shdr_bootstrap_ta> || <stripped ELF>) |
| 172 | signature = RSA-Sign(<hash>) |
| 173 | bootstrap_binary = <struct shdr> || <hash> || <signature> || |
| 174 | <struct shdr_bootstrap_ta> || <stripped ELF> |
| 175 | |
| 176 | A REE TA is loaded into shared memory using a series or RPC in |
| 177 | :ref:`load_ree_ta`. The payload memory is allocated via TEE-supplicant and |
| 178 | later freed when the TA has been loaded into secure memory in |
| 179 | :ref:`free_appl_shm`. |
| 180 | |
| 181 | .. _load_ree_ta: |
| 182 | |
| 183 | .. figure:: ../images/trusted_applications/load_ree_ta.png |
| 184 | :figclass: align-center |
| 185 | |
| 186 | Loading a REE TA into nonsecure shared memory |
| 187 | |
| 188 | .. _free_appl_shm: |
| 189 | |
| 190 | .. figure:: ../images/trusted_applications/free_appl_shm.png |
| 191 | :figclass: align-center |
| 192 | |
| 193 | Freeing previously allocated nonsecure shared memory |
| 194 | |
| 195 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 196 | .. _secure_storage_ta: |
| 197 | |
| 198 | Secure Storage TA |
| 199 | ================= |
| 200 | These are stored in secure storage. The meta data is stored in a database of all |
| 201 | installed TAs and the actual binary is stored encrypted and integrity protected |
| 202 | as a separate file in the untrusted REE filesystem (flash). Before these TAs can |
| 203 | be loaded they have to be installed first, this is something that can be done |
| 204 | during initial deployment or at a later stage. |
| 205 | |
| 206 | For test purposes the test program xtest can install a TA into secure storage |
| 207 | with the command: |
| 208 | |
| 209 | .. code-block:: bash |
| 210 | |
| 211 | $ xtest --install-ta |
| 212 | |
| 213 | |
| 214 | .. _ta_properties: |
| 215 | |
| 216 | TA Properties |
| 217 | ************* |
| 218 | This section give a more in depth description of the TA properties (see |
| 219 | :ref:`build_trusted_applications` also). |
| 220 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 221 | GlobalPlatform Properties |
| 222 | ========================= |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 223 | Standard TA properties must be defined through property flag in macro |
| 224 | ``TA_FLAGS`` in ``user_ta_header_defines.h`` |
| 225 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 226 | Single Instance |
| 227 | --------------- |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 228 | ``"gpd.ta.singleInstance"`` is a boolean property of the TA. This property |
| 229 | defines if one instance of the TA must be created and will receive all open |
| 230 | session request, or if a new specific TA instance must be created for each |
| 231 | incoming open session request. OP-TEE TA flag ``TA_FLAG_SINGLE_INSTANCE`` sets |
| 232 | to configuration of this property. The boolean property is set to ``true`` if |
| 233 | ``TA_FLAGS`` sets bit ``TA_FLAG_SINGLE_INSTANCE``, otherwise the boolean |
| 234 | property is set to ``false``. |
| 235 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 236 | Multi-session |
| 237 | ------------- |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 238 | ``"gpd.ta.multiSession"`` is a boolean property of the TA. This property defines |
| 239 | if the TA instance can handle several sessions. If disabled, TA instance support |
| 240 | only one session. In such case, if the TA already has a opened session, any open |
| 241 | session request will return with a busy error status. |
| 242 | |
| 243 | .. note:: |
| 244 | |
| 245 | This property is **meaningless** if TA is **NOT** SingleInstance TA. |
| 246 | |
| 247 | OP-TEE TA flag ``TA_FLAG_MULTI_SESSION`` sets to configuration of this property. |
| 248 | The boolean property is set to ``true`` if ``TA_FLAGS`` sets bit |
| 249 | ``TA_FLAG_MULTI_SESSION``, otherwise the boolean property is set to ``false``. |
| 250 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 251 | Keep Alive |
| 252 | ---------- |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 253 | ``"gpd.ta.instanceKeepAlive"`` is a boolean property of the TA. This property |
| 254 | defines if the TA instance created must be destroyed or not when all sessions |
| 255 | opened towards the TA are closed. If the property is enabled, TA instance, once |
| 256 | created (at 1st open session request), is never removed unless the TEE itself is |
| 257 | restarted (boot/reboot). |
| 258 | |
| 259 | .. note:: |
| 260 | |
| 261 | This property is **meaningless** if TA is **NOT** SingleInstance TA. |
| 262 | |
| 263 | OP-TEE TA flag ``TA_FLAG_INSTANCE_KEEP_ALIVE`` sets to configuration of this |
| 264 | property. The boolean property is set to ``true`` if ``TA_FLAGS`` sets bit |
| 265 | ``TA_FLAG_INSTANCE_KEEP_ALIVE``, otherwise the boolean property is set to |
| 266 | ``false``. |
| 267 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 268 | Heap Size |
| 269 | --------- |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 270 | ``"gpd.ta.dataSize"`` is a 32bit integer property of the TA. This property |
| 271 | defines the size in bytes of the TA allocation pool, in which ``TEE_Malloc()`` |
| 272 | and friends allocate memory. The value of the property must be defined by the |
| 273 | macro ``TA_DATA_SIZE`` in ``user_ta_header_defines.h`` (see |
| 274 | :ref:`build_ta_properties`). |
| 275 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 276 | Stack Size |
| 277 | ---------- |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 278 | ``"gpd.ta.stackSize"`` is a 32bit integer property of the TA. This property |
| 279 | defines the size in bytes of the stack used for TA execution. The value of the |
| 280 | property must be defined by the macro ``TA_STACK_SIZE`` in |
| 281 | ``user_ta_header_defines.h`` (see :ref:`build_ta_properties`). |
| 282 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 283 | Property Extensions |
| 284 | =================== |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 285 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 286 | Secure Data Path Flag |
| 287 | --------------------- |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 288 | ``TA_FLAG_SECURE_DATA_PATH`` is a bit flag supported by ``TA_FLAGS``. This |
| 289 | property flag claims the secure data support from the OP-TEE OS for the TA. |
| 290 | Refer to the OP-TEE OS for secure data path support. TAs that do not set |
| 291 | ``TA_FLAG_SECURE_DATA_PATH`` in the value of ``TA_FLAGS`` will **not** be able |
| 292 | to handle memory reference invocation parameters that relate to secure data path |
| 293 | buffers. |
| 294 | |
Etienne Carriere | 5b99ccc | 2019-03-11 11:57:30 +0100 | [diff] [blame] | 295 | .. _ta_property_cache_maintenance: |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 296 | |
| 297 | Cache maintenance Flag |
| 298 | ---------------------- |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 299 | ``TA_FLAG_CACHE_MAINTENANCE`` is a bit flag supported by ``TA_FLAGS``. This |
Etienne Carriere | 5b99ccc | 2019-03-11 11:57:30 +0100 | [diff] [blame] | 300 | property flag, when enabled, allows Trusted Applciation to use the cache |
| 301 | maintenance API extension of the Internal Core API described in |
| 302 | :ref:`extensions_cache_maintenance`. TAs that do not set |
| 303 | ``TA_FLAG_CACHE_MAINTENANCE`` in the value of their ``TA_FLAGS`` will not be |
| 304 | able to call the cache maintenance API. |
Etienne Carriere | 0ab5cc2 | 2019-03-11 10:44:13 +0100 | [diff] [blame] | 305 | |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 306 | Deprecated Property Flags |
| 307 | ------------------------- |
Etienne Carriere | 0ab5cc2 | 2019-03-11 10:44:13 +0100 | [diff] [blame] | 308 | Older versions of OP-TEE used to define extended property flags that are |
| 309 | deprecated and meaningless to current OP-TEE. These are ``TA_FLAG_USER_MODE``, |
| 310 | ``TA_FLAG_EXEC_DDR`` and ``TA_FLAG_REMAP_SUPPORT``. |
Etienne Carriere | 2f459d1 | 2019-03-11 11:58:05 +0100 | [diff] [blame] | 311 | |
| 312 | .. _ELF: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format |
| 313 | .. _early TA commit: https://github.com/OP-TEE/optee_os/commit/d0c636148b3a |