blob: fc51800fb1a243560615fee34273908dc5285f94 [file] [log] [blame]
Joakim Bech8e5c5b32018-10-25 08:18:32 +02001.. _trusted_applications:
2
3####################
4Trusted Applications
5####################
6There are two ways to implement Trusted Applications (TAs), Pseudo TAs and user
7mode TAs. User mode TAs are full featured Trusted Applications as specified by
8the :ref:`globalplatform_api` TEE specifications, these are simply the ones
9people are referring to when they are saying "Trusted Applications" and in most
10cases this is the preferred type of TA to write and use.
11
12.. _pta:
13
14Pseudo Trusted Applications
15***************************
Etienne Carriere5ecb86a2020-06-03 18:47:45 +020016A Pseudo Trusted Application is not a Trusted Application. A Pseudo TA is not a
17specific entity. A Pseudo TA is an interface. It is an interface exposed by the
18OP-TEE Core to its outer world: to secure client Trusted Applications and to
19non-secure client entities.
20
Joakim Bech8e5c5b32018-10-25 08:18:32 +020021These are implemented directly to the OP-TEE core tree in, e.g.,
Jerome Forissierfa993db2019-09-13 15:58:53 +020022``core/pta`` and are built along with and statically built into the
Joakim Bech8e5c5b32018-10-25 08:18:32 +020023OP-TEE core blob.
24
25The Pseudo Trusted Applications included in OP-TEE already are OP-TEE secure
26privileged level services hidden behind a "GlobalPlatform TA Client" API. These
27Pseudo TAs are used for various purposes such as specific secure services or
28embedded tests services.
29
30Pseudo TAs **do not** benefit from the GlobalPlatform Core Internal API support
31specified by the GlobalPlatform TEE specs. These APIs are provided to TAs as a
32static library each TA shall link against (the ":ref:`libutee`") and that calls
33OP-TEE core service through system calls. As OP-TEE core does not link with
34:ref:`libutee`, Pseudo TAs can **only** use the OP-TEE core internal APIs and
35routines.
36
37As Pseudo TAs runs at the same privileged execution level as the OP-TEE core
38code itself and that might or might not be desirable depending on the use case.
39
40In most cases an unprivileged (user mode) TA is the best choice instead of
41adding your code directly to the OP-TEE core. However if you decide your
42application is best handled directly in OP-TEE core like this, you can look at
Jerome Forissierfa993db2019-09-13 15:58:53 +020043``core/pta/stats.c`` as a template and just add your Pseudo TA based on
Joakim Bech8e5c5b32018-10-25 08:18:32 +020044that to the ``sub.mk`` in the same directory.
45
46.. _user_mode_ta:
47
48User Mode Trusted Applications
49******************************
50User Mode Trusted Applications are loaded (mapped into memory) by OP-TEE core in
51the Secure World when something in Rich Execution Environment (REE) wants to
52talk to that particular application UUID. They run at a lower CPU privilege
53level than OP-TEE core code. In that respect, they are quite similar to regular
54applications running in the REE, except that they execute in Secure World.
55
56Trusted Application benefit from the GlobalPlatform :ref:`tee_internal_core_api`
57as specified by the GlobalPlatform TEE specifications. There are several types
58of user mode TAs, which differ by the way they are stored.
59
60TA locations
61************
62Plain TAs (user mode) can reside and be loaded from various places. There are
63three ways currently supported in OP-TEE.
64
65.. _early_ta:
66
67Early TA
68========
69The so-called early TAs are virtually identical to the REE FS TAs, but instead
70of being loaded from the Normal World file system, they are linked into a
71special data section in the TEE core blob. Therefore, they are available even
72before ``tee-supplicant`` and the REE's filesystems have come up. Please find
73more details in the `early TA commit`_.
74
75.. _ree_fs_ta:
76
77REE filesystem TA
78=================
Sumit Gargde0c0c72020-04-17 13:15:30 +053079They consist of a ELF_ file, signed and optionally encrypted, named from the
80UUID of the TA and the suffix ``.ta``. They are built separately from the
81OP-TEE core boot-time blob, although when they are built they use the same
82build system, and are signed with the key from the build of the original OP-TEE
83core blob.
Joakim Bech8e5c5b32018-10-25 08:18:32 +020084
Sumit Gargde0c0c72020-04-17 13:15:30 +053085Because the TAs are signed and optionally encrypted with
86``scripts/sign_encrypt.py``, they are able to be stored in the untrusted REE
Joakim Bech8e5c5b32018-10-25 08:18:32 +020087filesystem, and ``tee-supplicant`` will take care of passing them to be checked
Sumit Gargde0c0c72020-04-17 13:15:30 +053088and loaded by the Secure World OP-TEE core.
Joakim Bech8e5c5b32018-10-25 08:18:32 +020089
Sumit Gargde0c0c72020-04-17 13:15:30 +053090REE-FS TA rollback protection
91-----------------------------
92OP-TEE core maintains a ``ta_ver.db`` file in secure storage to check for
93version of REE TAs as they are loaded from REE-FS in order to prevent against
94any TA version downgrades. TA version can be configured via TA build option:
95``CFG_TA_VERSION=<unsigned integer>``.
Jens Wiklander6054d682019-11-19 11:31:14 +010096
Sumit Gargde0c0c72020-04-17 13:15:30 +053097Note: Here rollback protection is effective only when ``CFG_RPMB_FS=y``.
98
99REE-FS TA formats
100-----------------
101REE filesystem TAs come in three formats:
102
103 1. Legacy TAs signed, not encrypted, cannot be created anymore by the build
104 scripts since version 3.7.0.
105
106 2. Bootstrap TAs, signed with the key from the build of the original OP-TEE
107 core blob, not encrypted.
108
109 3. Encrypted TAs, sign-then-encrypt-then-MAC, encrypted with ``TA_ENC_KEY``
110 when ``CFG_ENCRYPT_TA=y``. During OP-TEE runtime, the symmetric key used
111 to decrypt TA has to be provided in a platform specific manner via
112 overriding API:
113
114 .. code-block:: c
115
116 TEE_Result tee_otp_get_ta_enc_key(uint32_t key_type, uint8_t *buffer,
117 size_t len);
118
119REE-FS TA header structure
120--------------------------
Jens Wiklander6054d682019-11-19 11:31:14 +0100121All REE filesystems TAs has common header, ``struct shdr``, defined as:
122
123.. code-block:: c
124
125 enum shdr_img_type {
126 SHDR_TA = 0,
127 SHDR_BOOTSTRAP_TA = 1,
Sumit Gargde0c0c72020-04-17 13:15:30 +0530128 SHDR_ENCRYPTED_TA = 2,
Jens Wiklander6054d682019-11-19 11:31:14 +0100129 };
130
131 #define SHDR_MAGIC 0x4f545348
132
133 /**
134 * struct shdr - signed header
135 * @magic: magic number must match SHDR_MAGIC
136 * @img_type: image type, values defined by enum shdr_img_type
137 * @img_size: image size in bytes
138 * @algo: algorithm, defined by public key algorithms TEE_ALG_*
139 * from TEE Internal API specification
140 * @hash_size: size of the signed hash
141 * @sig_size: size of the signature
142 * @hash: hash of an image
143 * @sig: signature of @hash
144 */
145 struct shdr {
146 uint32_t magic;
147 uint32_t img_type;
148 uint32_t img_size;
149 uint32_t algo;
150 uint16_t hash_size;
151 uint16_t sig_size;
152 /*
153 * Commented out element used to visualize the layout dynamic part
154 * of the struct.
155 *
156 * hash is accessed through the macro SHDR_GET_HASH and
157 * signature is accessed through the macro SHDR_GET_SIG
158 *
159 * uint8_t hash[hash_size];
160 * uint8_t sig[sig_size];
161 */
162 };
163
164 #define SHDR_GET_SIZE(x) (sizeof(struct shdr) + (x)->hash_size + \
165 (x)->sig_size)
166 #define SHDR_GET_HASH(x) (uint8_t *)(((struct shdr *)(x)) + 1)
167 #define SHDR_GET_SIG(x) (SHDR_GET_HASH(x) + (x)->hash_size)
168
169
Jens Wiklandera6315cd2019-11-19 14:34:30 +0100170The field ``img_type`` tells the type of TA, if it's ``SHDR_TA`` (0),
Jens Wiklander6054d682019-11-19 11:31:14 +0100171it's a legacy TA. If it's ``SHDR_BOOTSTRAP_TA`` (1) it's a bootstrap TA.
172
Jens Wiklandera6315cd2019-11-19 14:34:30 +0100173The field ``algo`` tells the algorithm used. The script used to sign TAs
174currently uses ``TEE_ALG_RSASSA_PKCS1_V1_5_SHA256`` (0x70004830). This
175means RSA with PKCS#1v1.5 padding and SHA-256 hash function. OP-TEE accepts
176any of the ``TEE_ALG_RSASSA_PKCS1_*`` algorithms.
177
Jens Wiklander6054d682019-11-19 11:31:14 +0100178For bootstrap TAs ``struct shdr`` is followed by a subheader, ``struct
179shdr_bootstrap_ta`` which is defined as:
180
181.. code-block:: c
182
183 /**
184 * struct shdr_bootstrap_ta - bootstrap TA subheader
185 * @uuid: UUID of the TA
186 * @ta_version: Version of the TA
187 */
188 struct shdr_bootstrap_ta {
189 uint8_t uuid[sizeof(TEE_UUID)];
190 uint32_t ta_version;
191 };
192
193The fields ``uuid`` and ``ta_version`` allows extra checks to be performed
194when loading the TA. Currently only the ``uuid`` field is checked.
195
Sumit Gargde0c0c72020-04-17 13:15:30 +0530196For encrypted TAs ``struct shdr`` is followed by a subheader, ``struct
197shdr_bootstrap_ta`` which is followed by another subheader, ``struct
198shdr_encrypted_ta`` defined as:
199
200.. code-block:: c
201
202 /**
203 * struct shdr_encrypted_ta - encrypted TA header
204 * @enc_algo: authenticated encyption algorithm, defined by symmetric key
205 * algorithms TEE_ALG_* from TEE Internal API
206 * specification
207 * @flags: authenticated encyption flags
208 * @iv_size: size of the initialization vector
209 * @tag_size: size of the authentication tag
210 * @iv: initialization vector
211 * @tag: authentication tag
212 */
213 struct shdr_encrypted_ta {
214 uint32_t enc_algo;
215 uint32_t flags;
216 uint16_t iv_size;
217 uint16_t tag_size;
218 /*
219 * Commented out element used to visualize the layout dynamic part
220 * of the struct.
221 *
222 * iv is accessed through the macro SHDR_ENC_GET_IV and
223 * tag is accessed through the macro SHDR_ENC_GET_TAG
224 *
225 * uint8_t iv[iv_size];
226 * uint8_t tag[tag_size];
227 */
228 };
229
230The field ``enc_algo`` tells the algorithm used. The script used to encrypt
231TAs currently uses ``TEE_ALG_AES_GCM`` (0x40000810). OP-TEE core also accepts
232``TEE_ALG_AES_CCM`` algorithm.
233
234The field ``flags`` supports a single flag to tell encryption key type which
235is defined as:
236
237.. code-block:: c
238
239 #define SHDR_ENC_KEY_TYPE_MASK 0x1
240
241 enum shdr_enc_key_type {
242 SHDR_ENC_KEY_DEV_SPECIFIC = 0,
243 SHDR_ENC_KEY_CLASS_WIDE = 1,
244 };
245
246REE-FS TA binary formats
247------------------------
248TA binary follows the ELF file which normally is stripped as additional
249symbols etc will be ignored when loading the TA.
Jens Wiklander6054d682019-11-19 11:31:14 +0100250
251Legacy TA binary is formatted as:
252
253.. code-block:: none
254
255 hash = H(<struct shdr> || <stripped ELF>)
256 signature = RSA-Sign(hash)
257 legacy_binary = <struct shdr> || <hash> || <signature> || <stripped ELF>
258
259Bootstrap TA binary is formatted as:
260
261.. code-block:: none
262
263 hash = H(<struct shdr> || <struct shdr_bootstrap_ta> || <stripped ELF>)
264 signature = RSA-Sign(<hash>)
265 bootstrap_binary = <struct shdr> || <hash> || <signature> ||
266 <struct shdr_bootstrap_ta> || <stripped ELF>
267
Sumit Gargde0c0c72020-04-17 13:15:30 +0530268Encrypted TA binary is formatted as:
269
270.. code-block:: none
271
272 nonce = <unique random value>
273 ciphertext, tag = AES_GCM(<stripped ELF>)
274 hash = H(<struct shdr> || <struct shdr_bootstrap_ta> ||
275 <struct shdr_encrypted_ta> || <nonce> || <tag> || <stripped ELF>)
276 signature = RSA-Sign(<hash>)
277 encrypted_binary = <struct shdr> || <hash> || <signature> ||
278 <struct shdr_bootstrap_ta> ||
279 <struct shdr_encrypted_ta> || <nonce> || <tag> ||
280 <ciphertext>
281
Jens Wiklandere5010392022-10-14 08:58:27 +0200282Verifying with Subkeys
283----------------------
284A TA can be verified using a subkey or a chain of subkeys. This allows
285delegation of TA signing without distributing the root key. TAs signed with
286a subkey are confined to the UUID-V5 namespace of the subkey to avoid TA
287UUID clashes with different subkeys.
288
289SHDR_SUBKEY is a type of header which enables chains of public keys. The
290public root key is used to verify the first public subkey, which then is
291used to verify the next public subkey and so on.
292
293The TA is finally verified using the last subkey. All these headers are
294added in front of the TA binary so everything needed to verify the TA is
295available when it's loaded into memory.
296
297For details on subkeys see also :ref:`_subkeys`
298
Sumit Gargde0c0c72020-04-17 13:15:30 +0530299Loading REE-FS TA
300-----------------
Jens Wiklander6054d682019-11-19 11:31:14 +0100301A REE TA is loaded into shared memory using a series or RPC in
302:ref:`load_ree_ta`. The payload memory is allocated via TEE-supplicant and
303later freed when the TA has been loaded into secure memory in
304:ref:`free_appl_shm`.
305
306.. _load_ree_ta:
307
308.. figure:: ../images/trusted_applications/load_ree_ta.png
309 :figclass: align-center
310
311 Loading a REE TA into nonsecure shared memory
312
313.. _free_appl_shm:
314
315.. figure:: ../images/trusted_applications/free_appl_shm.png
316 :figclass: align-center
317
318 Freeing previously allocated nonsecure shared memory
319
320
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200321.. _secure_storage_ta:
322
323Secure Storage TA
324=================
325These are stored in secure storage. The meta data is stored in a database of all
326installed TAs and the actual binary is stored encrypted and integrity protected
327as a separate file in the untrusted REE filesystem (flash). Before these TAs can
328be loaded they have to be installed first, this is something that can be done
329during initial deployment or at a later stage.
330
331For test purposes the test program xtest can install a TA into secure storage
332with the command:
333
334.. code-block:: bash
335
336 $ xtest --install-ta
337
Jens Wiklander6b67a662019-11-25 10:58:46 +0100338TAs stored in secure storage are kept in a TA database. The TA database
339consists of a single file with the name ``dirf.db`` which is stored either
340in the REE filesystem based secure storage or in RPMB. The file is
341encrypted and integrity protected as any other object in secure storage.
342The TAs themselves are not stored in ``dirf.db``, they are instead stored
343in the REE filesystem encrypted and integrity protected. One reason for
344this is that TAs can potentially be quite large, several megabytes, while
345secure storage is designed to hold only small objects counted in kilobytes.
346
347``dirf.db`` constsist of an array of ``struct tadb_entry``, defined as:
348
349.. code-block:: C
350
351 /*
352 * struct tee_tadb_property
353 * @uuid: UUID of Trusted Application (TA) or Security Domain (SD)
354 * @version: Version of TA or SD
355 * @custom_size:Size of customized properties, prepended to the encrypted
356 * TA binary
357 * @bin_size: Size of the binary TA
358 */
359 struct tee_tadb_property {
360 TEE_UUID uuid;
361 uint32_t version;
362 uint32_t custom_size;
363 uint32_t bin_size;
364 };
365
366 #define TADB_IV_SIZE TEE_AES_BLOCK_SIZE
367 #define TADB_TAG_SIZE TEE_AES_BLOCK_SIZE
368 #define TADB_KEY_SIZE TEE_AES_MAX_KEY_SIZE
369
370 /*
371 * struct tadb_entry - TA database entry
372 * @prop: properties of TA
373 * @file_number: encrypted TA is stored in <file_number>.ta
374 * @iv: Initialization vector of the authentication crypto
375 * @tag: Tag used to validate the authentication encrypted TA
376 * @key: Key used to decrypt the TA
377 */
378 struct tadb_entry {
379 struct tee_tadb_property prop;
380 uint32_t file_number;
381 uint8_t iv[TADB_IV_SIZE];
382 uint8_t tag[TADB_TAG_SIZE];
383 uint8_t key[TADB_KEY_SIZE];
384 };
385
386Entries where the ``UUID`` consists of zeros only are not valid and are
387ignored. The ``file_number`` field represents that name of the file stored
388in the REE filesystem. The filename is made from the decimal string
389representation of ``file_number`` with ``.ta`` appended, or if it was to be
390printed: ``printf("%u.ta", file_number)``.
391
392The TA is decrypted using the authentication encryption algorithm AES-GCM
393initialized with the ``iv`` and ``key`` fields, the ``tag`` field is used
394when finalizing the decryption
395
396A TA is looked up in the TA database by opening ``dirf.db`` and scanning
397through the elements which are of type ``struct tadb_entry`` until a
398matching UUID is found.
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200399
Jens Wiklandera6315cd2019-11-19 14:34:30 +0100400Loading and preparing TA for execution
401**************************************
402
403User mode TAs are loaded into final memory in the same way using the user
404mode ELF loader ``ldelf``. The different TA locations has a common
405interface towards ``ldelf`` which makes the user mode operations identical
406regarless of how the TA is stored.
407
408The TA is loaded into secure memory in :ref:`prepare_ta`.
409
410.. _prepare_ta:
411
412.. figure:: ../images/trusted_applications/prepare_ta.png
413 :figclass: align-center
414
415 Preparing TA for execution
416
417After ``ldelf`` has returned with a TA prepared for execution it still
418remains in memory to serve the TA if dlopen() and friends are used.
419``ldelf`` is also used to dump stack trace and detailed memory mappings if
420a TA is terminated via an abort.
421
422A high level view of the entire flow from the client application in Linux
423user space where a session is opened to a TA is given in
424:ref:`open_session`.
425
426.. _open_session:
427
428.. figure:: ../images/trusted_applications/open_session.png
429 :figclass: align-center
430
431 Open session to a TA
432
433
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200434.. _ta_properties:
435
436TA Properties
437*************
438This section give a more in depth description of the TA properties (see
439:ref:`build_trusted_applications` also).
440
Etienne Carriere2f459d12019-03-11 11:58:05 +0100441GlobalPlatform Properties
442=========================
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200443Standard TA properties must be defined through property flag in macro
444``TA_FLAGS`` in ``user_ta_header_defines.h``
445
Etienne Carriere2f459d12019-03-11 11:58:05 +0100446Single Instance
447---------------
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200448``"gpd.ta.singleInstance"`` is a boolean property of the TA. This property
449defines if one instance of the TA must be created and will receive all open
450session request, or if a new specific TA instance must be created for each
451incoming open session request. OP-TEE TA flag ``TA_FLAG_SINGLE_INSTANCE`` sets
452to configuration of this property. The boolean property is set to ``true`` if
453``TA_FLAGS`` sets bit ``TA_FLAG_SINGLE_INSTANCE``, otherwise the boolean
454property is set to ``false``.
455
Etienne Carriere2f459d12019-03-11 11:58:05 +0100456Multi-session
457-------------
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200458``"gpd.ta.multiSession"`` is a boolean property of the TA. This property defines
459if the TA instance can handle several sessions. If disabled, TA instance support
460only one session. In such case, if the TA already has a opened session, any open
461session request will return with a busy error status.
462
463.. note::
464
465 This property is **meaningless** if TA is **NOT** SingleInstance TA.
466
467OP-TEE TA flag ``TA_FLAG_MULTI_SESSION`` sets to configuration of this property.
468The boolean property is set to ``true`` if ``TA_FLAGS`` sets bit
469``TA_FLAG_MULTI_SESSION``, otherwise the boolean property is set to ``false``.
470
Etienne Carriere2f459d12019-03-11 11:58:05 +0100471Keep Alive
472----------
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200473``"gpd.ta.instanceKeepAlive"`` is a boolean property of the TA. This property
474defines if the TA instance created must be destroyed or not when all sessions
475opened towards the TA are closed. If the property is enabled, TA instance, once
476created (at 1st open session request), is never removed unless the TEE itself is
477restarted (boot/reboot).
478
479.. note::
480
481 This property is **meaningless** if TA is **NOT** SingleInstance TA.
482
483OP-TEE TA flag ``TA_FLAG_INSTANCE_KEEP_ALIVE`` sets to configuration of this
484property. The boolean property is set to ``true`` if ``TA_FLAGS`` sets bit
485``TA_FLAG_INSTANCE_KEEP_ALIVE``, otherwise the boolean property is set to
486``false``.
487
Etienne Carriere2f459d12019-03-11 11:58:05 +0100488Heap Size
489---------
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200490``"gpd.ta.dataSize"`` is a 32bit integer property of the TA. This property
491defines the size in bytes of the TA allocation pool, in which ``TEE_Malloc()``
492and friends allocate memory. The value of the property must be defined by the
493macro ``TA_DATA_SIZE`` in ``user_ta_header_defines.h`` (see
494:ref:`build_ta_properties`).
495
Etienne Carriere2f459d12019-03-11 11:58:05 +0100496Stack Size
497----------
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200498``"gpd.ta.stackSize"`` is a 32bit integer property of the TA. This property
499defines the size in bytes of the stack used for TA execution. The value of the
500property must be defined by the macro ``TA_STACK_SIZE`` in
501``user_ta_header_defines.h`` (see :ref:`build_ta_properties`).
502
Etienne Carriere2f459d12019-03-11 11:58:05 +0100503Property Extensions
504===================
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200505
Etienne Carriere2f459d12019-03-11 11:58:05 +0100506Secure Data Path Flag
507---------------------
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200508``TA_FLAG_SECURE_DATA_PATH`` is a bit flag supported by ``TA_FLAGS``. This
509property flag claims the secure data support from the OP-TEE OS for the TA.
510Refer to the OP-TEE OS for secure data path support. TAs that do not set
511``TA_FLAG_SECURE_DATA_PATH`` in the value of ``TA_FLAGS`` will **not** be able
512to handle memory reference invocation parameters that relate to secure data path
513buffers.
514
Etienne Carriere5b99ccc2019-03-11 11:57:30 +0100515.. _ta_property_cache_maintenance:
Etienne Carriere2f459d12019-03-11 11:58:05 +0100516
517Cache maintenance Flag
518----------------------
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200519``TA_FLAG_CACHE_MAINTENANCE`` is a bit flag supported by ``TA_FLAGS``. This
Etienne Carriere5b99ccc2019-03-11 11:57:30 +0100520property flag, when enabled, allows Trusted Applciation to use the cache
521maintenance API extension of the Internal Core API described in
522:ref:`extensions_cache_maintenance`. TAs that do not set
523``TA_FLAG_CACHE_MAINTENANCE`` in the value of their ``TA_FLAGS`` will not be
524able to call the cache maintenance API.
Etienne Carriere0ab5cc22019-03-11 10:44:13 +0100525
Etienne Carriere2f459d12019-03-11 11:58:05 +0100526Deprecated Property Flags
527-------------------------
Etienne Carriere0ab5cc22019-03-11 10:44:13 +0100528Older versions of OP-TEE used to define extended property flags that are
529deprecated and meaningless to current OP-TEE. These are ``TA_FLAG_USER_MODE``,
530``TA_FLAG_EXEC_DDR`` and ``TA_FLAG_REMAP_SUPPORT``.
Etienne Carriere2f459d12019-03-11 11:58:05 +0100531
532.. _ELF: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
533.. _early TA commit: https://github.com/OP-TEE/optee_os/commit/d0c636148b3a