diff options
author | r.tyminski <r.tyminski@partner.samsung.com> | 2017-05-29 11:42:10 +0200 |
---|---|---|
committer | r.tyminski <r.tyminski@partner.samsung.com> | 2017-05-29 11:49:50 +0200 |
commit | f9a43781767007462965b21f3f518c4cfc0744c7 (patch) | |
tree | 201509439b1d9798256227794dae6774345adf43 /documentation | |
parent | 1fed20f5471aa0dad5e4b4f79d1f2843ac88734f (diff) | |
download | tef-optee_os-f9a43781767007462965b21f3f518c4cfc0744c7.tar.gz tef-optee_os-f9a43781767007462965b21f3f518c4cfc0744c7.tar.bz2 tef-optee_os-f9a43781767007462965b21f3f518c4cfc0744c7.zip |
Initial commit with upstream sources
Change-Id: Ie9460111f21fc955102fd8732a0173b2d0499a4a
Diffstat (limited to 'documentation')
36 files changed, 2894 insertions, 0 deletions
diff --git a/documentation/build_system.md b/documentation/build_system.md new file mode 100644 index 0000000..fa11e95 --- /dev/null +++ b/documentation/build_system.md @@ -0,0 +1,325 @@ +# Build system + +The OP-TEE build system is based on GNU make. It consists of a main `Makefile` +in the root of the project together with `sub.mk` files in all source +directories. In addition, some supporting files are used to recursively process +all `sub.mk` files and generate the build rules. + +Name | Description +:-----------------|:----------- +`core/core.mk` | Included from `Makefile` to build the TEE Core +`ta/ta.mk` | Included from `Makefile` to create the TA devkit +`mk/compile.mk` | Create rules to make objects from source files +`mk/lib.mk` | Create rules to make a libraries (.a) +`mk/subdir.mk` | Process `sub.mk` files recursively +`mk/config.mk` | Global configuration variable +`core/arch/$(ARCH)/$(ARCH).mk` | Arch-specific compiler flags +`core/arch/$(ARCH)/plat-$(PLATFORM)/conf.mk` | Platform-specific compiler flags and configuration variables +`core/arch/$(ARCH)/plat-$(PLATFORM)/link.mk` | Make recipes to link the TEE Core +`ta/arch/arm/link.mk` | Make recipes to link Trusted Applications +`ta/mk/ta_dev_kit.mk` | Main Makefile to be included when building Trusted Applications +`mk/checkconf.mk` | Utility functions to manipulate configuration variables and generate a C header file +`sub.mk` | List source files and define compiler flags + +`make` is always invoked from the top-level directory; there is no recursive +invocation of make itself. + +## Choosing the build target + +The target architecture, platform and build directory may be selected by setting +environment or make variables (**VAR=value make** or **make VAR=value**). + +### ARCH (CPU architecture) + +**$(ARCH)** is the CPU architecture to be built. Currently, the only supported +value is **arm** for 32-bit ARMv7. + +Architecture-specific source code belongs to sub-directories that follow the +`arch/$(ARCH)` pattern, such as: +`core/arch/arm`, `lib/libmpa/arch/arm`, `lib/libutee/arch/arm` and +so on. + +### PLATFORM / PLATFORM_FLAVOR (hardware platform) + +A *platform* is a family of closely related hardware configurations. A platform +*flavor* is a variant of such configurations. When used together they define the +target hardware on which OP-TEE will be run. + +For instance **PLATFORM=stm PLATFORM_FLAVOR=b2260** will build for the +ST Microelectronics 96boards/cannes2 board, while **PLATFORM=vexpress +PLATFORM_FLAVOR=qemu_virt** will generate code for a para-virtualized ARM +Versatile Express board running on QEMU. + +For convenience, the flavor may be appended to the platform name with a dash, so +**make PLATFORM=stm-b2260** is a shortcut for +**make PLATFORM=stm PLATFORM_FLAVOR=b2260**. Note that in both cases the value +of **$(PLATFORM)** is **stm** in the makefiles. + +Platform-specific source code belongs to `core/arch/$(ARCH)/plat-$(PLATFORM)`, +for instance: `core/arch/arm/plat-vexpress` or `core/arch/arm/plat-stm`. + +### O (output directory) + +All output files go into a platform-specific build directory, which is by default +`out/$(ARCH)-plat-$(PLATFORM)`. + +The output directory has basically the same structure as the source tree. +For instance, assuming **ARCH=arm PLATFORM=stm**, +`core/kernel/panic.c` will compile into `out/arm-plat-stm/core/kernel/panic.o`. + +However, some libraries are compiled several times: once or twice for user +mode, and once for kernel mode. This is because they may be used by the TEE +Core as well as by the Trusted Applications. As a result, the `lib` source +directory gives two or three build directories: `ta_arm{32,64}-lib` and +`core-lib`. + +The output directory also has an `export-ta_arm{32,64}` directory, which +contains: +- All the files needed to build Trusted Applications. + - In `lib/`: **libutee.a** (the GlobalPlatform Internal API), **libutils.a** + (which implements a part of the standard C library), and **libmpa.a** (which + implements multiple precision arithmetic and is required by libutee.a). + - In `include/`: header files for the above libraries + - In `mk/`: **ta_dev_kit.mk**, which is a Make include file with suitable + rules to build a TA, and its dependencies + - `scripts/sign.py`: a Python script used by ta_dev_kit.mk to sign TAs. + - In `src`: **user_ta_header.c**: source file to add a suitable header to the + Trusted Application (as expected by the loader code in the TEE Core) +- Some files needed to build host applications (using the Client API), under + `export-ta_arm{32,64}/host_include`. + +Finally, the build directory contains the auto-generated configuration file +for the TEE Core: `$(O)/include/generated/conf.h` (see below). + +### CROSS_COMPILE* (cross-compiler selection) + +**$(CROSS_COMPILE)** is the prefix used to invoke the (32-bit) cross-compiler +toolchain. +The default value is **arm-linux-gnueabihf-**. This is the variable you want to +change in case you want to use +[ccache](https://ccache.samba.org/) to speed you recompilations: +```shell +$ make CROSS_COMPILE="ccache arm-linux-gnueabihf-" +``` + +If the build includes a mix of 32-bit and 64-bit code, for instance if you +set `CFG_ARM64_core=y` to build a 64-bit secure kernel, then two different +toolchains are used, that are controlled by **$(CROSS_COMPILE32)** and +**$(CROSS_COMPILE64)**. +The default value of **$(CROSS_COMPILE32)** is the value of CROSS_COMPILE, +which defaults to **arm-linux-gnueabihf-** as mentioned above. +The default value of **$(CROSS_COMPILE64)** is **aarch64-linux-gnu-**. + +Examples: +```shell +# FOr this example, select HiKey which supports both 32- and 64-bit builds +$ export PLATFORM=hikey + +# 1. Build everything 32-bit +$ make + +# 2. Same as (1.) but override the toolchain +$ make CROSS_COMPILE="ccache arm-linux-gnueabihf-" + +# 3. Same as (2.) +$ make CROSS_COMPILE32="ccache arm-linux-gnueabihf-" + +# 4. Select 64-bit secure 'core' (and therefore both 32- and 64-bit +# Trusted Application libraries) +$ make CFG_ARM64_core=y + +# 5. Same as (4.) but override the toolchains +$ make CFG_ARM64_core=y \ + CROSS_COMPILE32="ccache arm-linux-gnueabihf-" \ + CROSS_COMPILE64="ccache aarch64-linux-gnu-" +``` + +## Platform-specific configuration and flags + +The following variables are defined in `core/arch/$(ARCH)/$(ARCH).mk`: + +- **$(core-platform-aflags)**, **$(core-platform-cflags)** and + **$(core-platform-cppflags)** are added to the assembler / C compiler + / preprocessor flags for all source files compiled for TEE Core including + the kernel versions of **libmpa.a** and **libutils.a**. +- **$(ta_arm{32,64}-platform-aflags)**, **$(ta_arm{32,64}-platform-cflags)** + and **$(ta_arm{32,64}-platform-cppflags)** are added to the assembler / C + compiler / preprocessor flags when building the user-mode libraries + (**libutee.a**, **libutils.a**, **libmpa.a**) or Trusted Applications. + +The following variables are defined in +`core/arch/$(ARCH)/plat-$(PLATFORM)/conf.mk`: + +- If **$(arm{32,64}-platform-cflags)**, **$(arm{32,64}-platform-aflags)** and + **$(arm{32,64}-platform-cppflags)** are defined their content will be added + to **$(\*-platform-\*flags)** when they are are initialized in + `core/arch/$(ARCH)/$(ARCH).mk` as described above. +- **$(core-platform-subdirs)** is the list of the subdirectories that are + added to the TEE Core. + +## Platform-specific link recipes for the TEE Core + +The file `core/arch/$(ARCH)/plat-$(PLATFORM)/link.mk` contains the rules to +link the TEE Core and perform any related tasks, such as running **objdump** +to produce a dump file. **link.mk** adds files to the **all:** target. + +## Source files + +Each directory that contains source files has a file called `sub.mk`. This +makefile defines the source files that should be included in the build, as well +as any subdirectories that should be processed, too. + +For example: +```Makefile +# core/arch/arm/sm/sub.mk +srcs-y += sm_asm.S +srcs-y += sm.c +``` +```Makefile +# core/sub.mk +subdirs-y += kernel +subdirs-y += mm +subdirs-y += tee +subdirs-y += drivers +``` + +The `-y` suffix is meant to facilitate conditional compilation. +See *Configuration* below. + +`srcs-y` and `subdirs-y` are often not used together in the same `sub.mk`, +because source files are usually alone in leaf directories. But this is not a +hard rule. + +In addition to source files, `sub.mk` may define compiler flags, include +directories and/or configuration variables as explained below. + +## Compiler flags + +Default compiler flags are defined in `mk/compile.mk`. Note that platform-specific flags must not appear in this file which is common to all platforms. + +To add flags for a given source file, you may use the following variables in +`sub.mk`: +* `cflags-<filename>-y` for C files (*.c) +* `aflags-<filename>-y` for assembler files (*.S) +* `cppflags-<filename>-y` for both C and assembler + +For instance: + +```Makefile +# core/lib/libtomcrypt/src/pk/dh/sub.mk +srcs-y += dh.c +cflags-dh.c-y := -Wno-unused-variable +``` +Compiler flags may also be removed, as follows: + +```Makefile +# lib/libutils/isoc/newlib/sub.mk +srcs-y += memmove.c +cflags-remove-memmove.c-y += -Wcast-align +``` + +Some variables apply to libraries only (that is, when using `mk/lib.mk`) +and affect all the source files that belong to the library: `cppflags-lib-y` +and `cflags-lib-y`. + +## Include directories + +Include directories may be added to `global-incdirs-y`, in which case they will +be accessible from all the source files and will be copied to +`export-ta_arm{32,64}/include` and `export-ta_arm{32,64}/host_include`. + +When `sub.mk` is used to build a library, `incdirs-lib-y` may receive additional +directories that will be used for that library only. + +## Configuration variables + +Some features may be enabled, disabled or otherwise controlled at compile time +through makefile variables. Default values are normally provided in makefiles +with the `?=` operator so that their value may be easily overridden by +environment variables. For instance: + +```Makefile +PLATFORM ?= stm +PLATFORM_FLAVOR ?= default +``` + +Some global configuration variables are defined in `mk/config.mk`, but others +may be defined in `sub.mk` when then pertain to a specific library for instance. + +Variables with the `CFG_` prefix are treated in a special +way: their value is automatically reflected in the generated header +file `$(out-dir)/include/generated/conf.h`, after all the included +makefiles have been processed. `conf.h` is automatically included by the +preprocessor when a source file is built. + +Depending on their value, variables may +be considered either boolean or non-boolean, which affects how they are +translated into `conf.h`. + +### Boolean configuration variables + +When a configuration variable controls the presence or absence of a feature, +**y** means *enabled*, while **n**, an empty value or an undefined variable +means *disabled*. For instance, the following commands are equivalent and would +disable feature *CFG_CRYPTO_GCM*: + +```Shell +$ make CFG_CRYPTO_GCM=n +``` +```Shell +$ make CFG_CRYPTO_GCM= +``` +```Shell +$ CFG_CRYPTO_GCM=n make +``` +```Shell +$ export CFG_CRYPTO_GCM=n +$ make +``` + +Configuration variables may then be used directly in `sub.mk` to +trigger conditional compilation: + +```Makefile +# core/lib/libtomcrypt/src/encauth/sub.mk +subdirs-$(CFG_CRYPTO_CCM) += ccm +subdirs-$(CFG_CRYPTO_GCM) += gcm +``` + +When a configuration variable is *enabled* (**y**), `<generated/conf.h>` +contains a macro with the same name as the variable and the value **1**. +If it is *disabled*, however, no macro definition is output. This allows the C +code to use constructs like: + +```C +/* core/lib/libtomcrypt/src/tee_ltc_provider.c */ + +/* ... */ + +#if defined(CFG_CRYPTO_GCM) +struct tee_gcm_state { + gcm_state ctx; /* the gcm state as defined by LTC */ + size_t tag_len; /* tag length */ +}; +#endif +``` + +### Non-boolean configuration variables + +Configuration variables that are not recognized as booleans are simply output +unchanged into `<generated/conf.h>`. For instance: + +```Makefile +$ make CFG_TEE_CORE_LOG_LEVEL=4 +``` +```C +/* out/arm-plat-vexpress/include/generated/conf.h */ + +#define CFG_TEE_CORE_LOG_LEVEL 4 /* '4' */ +``` + +### Configuration dependencies + +Some combinations of configuration variables may not be valid. This should be +dealt with by custom checks in makefiles. `mk/checkconf.h` provides functions +to help detect and deal with such situations. diff --git a/documentation/crypto.md b/documentation/crypto.md new file mode 100644 index 0000000..18d3933 --- /dev/null +++ b/documentation/crypto.md @@ -0,0 +1,190 @@ +# OP-TEE crypto implementation + +This document describes how the TEE Cryptographic Operations API is implemented, +how the default crypto provider may be configured at compile time, and how it may +be replaced by another implementation. + +## Overview + +There are several layers from the Trusted Application to the actual crypto +algorithms. Most of the crypto code runs in kernel mode inside the TEE core. + +Here is a schematic view of a typical call to the crypto API. The numbers in +square brackets ([1], [2]...) refer to the sections below. + + some_function() (Trusted App) + [1] TEE_*() User space (libutee.a) + ------- utee_*() ----------------------------------------------- + [2] tee_svc_*() Kernel space + [3] crypto_ops.*() (libtomcrypt.a) + [4] /* LibTomCrypt */ (libtomcrypt.a) + +## The TEE Cryptographic Operations API [1] + +OP-TEE implements the TEE Internal API defined by the GlobalPlatform association +in the *TEE Internal API Specification* (GPD_SPE_010). This includes +cryptographic functions that span various cryptographic needs: message digests, +symmetric ciphers, message authentication codes (MAC), authenticated encryption, +asymmetric operations (encryption/decryption or signing/verifying), key +derivation, and random data generation. These functions make up the TEE +Cryptographic Operations API. + +The Internal API is implemented in +[tee_api_operations.c](../lib/libutee/tee_api_operations.c), which is +compiled into a static library: `${O}/ta_arm{32,64}-lib/libutee/libutee.a`. + +Most API functions perform some parameter checking and manipulations, then +invoke some **utee_\*** function to switch to kernel mode and perform the +low-level work. + +The **utee_\*** functions are declared in +[utee_syscalls.h](../lib/libutee/include/utee_syscalls.h) +and implemented in +[utee_syscalls_asm.S](../lib/libutee/arch/arm/utee_syscalls_asm.S). +They are simple system call wrappers which use the **SVC** +instruction to switch to the appropriate system service in the OP-TEE kernel. + +## The crypto services [2] + +All cryptography-related system calls are declared in +[tee_svc_cryp.h](../core/include/tee/tee_svc_cryp.h) and implemented in +[tee_svc_cryp.c](../core/tee/tee_svc_cryp.c). +In addition to dealing with the usual work required at the user/kernel interface +(checking parameters and copying memory buffers between user and kernel space), +the system calls invoke a private abstraction layer: the **crypto_ops** +structure, which is declared in +[tee_cryp_provider.h](../core/include/tee/tee_cryp_provider.h). +It serves two main purposes: + +1. Allow for alternative implementations, such as hardware-accelerated versions. +2. Provide an easy way to disable some families of algorithms at compile-time + to save space. See *LibTomCrypt* below. + +## struct crypto_ops [3] + +The **crypto_ops** structure contains pointer to functions that implement the +actual algorithms and helper functions. The TEE Core has one global instance of +this structure. The default implementation, based on +[LibTomCrypt](https://github.com/libtom/libtomcrypt), is as follows: + +```c +/* core/lib/libtomcrypt/tee_ltc_provider.c */ + +/* + * static functions: tee_ltc_init(), hash_get_ctx_size(), etc. + * ... + */ + +struct crypto_ops crypto_ops = { + .name = "LibTomCrypt provider", + .init = tee_ltc_init, +#if defined(_CFG_CRYPTO_WITH_HASH) + .hash = { + .get_ctx_size = hash_get_ctx_size, + .init = hash_init, + .update = hash_update, + .final = hash_final, + }, +#endif +#if defined(_CFG_CRYPTO_WITH_CIPHER) + .cipher = { + .final = cipher_final, + .get_block_size = cipher_get_block_size, + .get_ctx_size = cipher_get_ctx_size, + .init = cipher_init, + .update = cipher_update, + }, +#endif + /* ... */ +} +``` + +As shown above, it is allowed to omit some pointers, in which case they will be +set to NULL by the compiler and not used by the system service layer. +When a Trusted Application calls **TEE_AllocateOperation()** to request an +operation that is not available, it receives an error status +(**TEE_ERROR_NOT_IMPLEMENTED**) but it will not panic. + +## Public/private key format + +**crypto_ops** uses implementation-specific types to hold key data +for asymmetric algorithms. For instance, here is how a public RSA key is +represented: + +```c +/* core/include/tee/tee_cryp_provider.h */ + +struct rsa_public_key { + struct bignum *e; /* Public exponent */ + struct bignum *n; /* Modulus */ +}; +``` + +This is also how such keys are stored inside the TEE object attributes +(**TEE_ATTR_RSA_PUBLIC_KEY** in this case). + +**struct bignum** is an opaque type, known to the underlying implementation +only. **struct bignum_ops** provides functions so that the system services can +manipulate data of this type. This includes allocation/deallocation, copy, and +conversion to or from the big endian binary format. + + +```c +/* core/include/tee/tee_cryp_provider.h */ + +struct bignum_ops { + /* ... */ + struct bignum *(*allocate)(size_t size_bits); + TEE_Result (*bin2bn)(const uint8_t *from, size_t fromsize, + struct bignum *to); + void (*bn2bin)(const struct bignum *from, uint8_t *to); +}; + +struct crypto_ops { + /* ... */ + struct bignum_ops bignum; +}; +``` + +## LibTomCrypt [4] + +Some algorithms may be disabled at compile time if they are not needed, in order +to reduce the size of the OP-TEE image and reduces its memory usage. This is done +by setting the appropriate configuration variable. For example: + + $ make CFG_CRYPTO_AES=n # disable AES only + $ make CFG_CRYPTO_{AES,DES}=n # disable symmetric ciphers + $ make CFG_CRYPTO_{DSA,RSA,DH,ECC}=n # disable public key algorithms + $ make CFG_CRYPTO=n # disable all algorithms + +Please refer to [core/lib/libtomcrypt/sub.mk](../core/lib/libtomcrypt/sub.mk) +for the list of all supported variables. + +Note that the application interface is **not** modified when algorithms are +disabled. This means, for instance, that the functions **TEE_CipherInit()**, +**TEE_CipherUpdate()** and **TEE_CipherFinal()** would remain present in +`libutee.a` even if all symmetric ciphers are disabled (they would simply +return **TEE_ERROR_NOT_IMPLEMENTED**). + +## How to add a new crypto implementation + +To add a new implementation, the default one in +[core/lib/libtomcrypt](../core/lib/libtomcrypt) should +be used as a reference. A proof-of-concept implementation based on OpenSSL was +developed when the `crypto_ops` abstraction layer was introduced. It is not +included in the main branch of the OP-TEE repository essentially due to +licensing concerns; however it is available in the +[poc/openssl_cryptolib](https://github.com/OP-TEE/optee_os/tree/poc/openssl_cryptolib) +branch. + +Here are the main things to consider when adding a new crypto provider: + +- Put all the new code in its own directory under `core/lib`. +- Avoid modifying [tee_svc_cryp.c](../core/tee/tee_svc_cryp.c). It should not be + needed. +- Your own **struct crypto_ops crypto_ops = ...** should be defined in a file at + the top level of your new directory. +- Although not all pointers in **crypto_ops** need to be defined, all are + required for compliance to the GlobalPlatform specification. +- If you intend to make some algorithms optional, please try to re-use the same + names for configuration variables as the default implementation. diff --git a/documentation/extensions/crypto_concat_kdf.md b/documentation/extensions/crypto_concat_kdf.md new file mode 100644 index 0000000..3e1092c --- /dev/null +++ b/documentation/extensions/crypto_concat_kdf.md @@ -0,0 +1,111 @@ +# Concatenation Key Derivation Function (Concat KDF) + +This document describes the OP-TEE implementation of the key derivation function +specified in section 5.8.1 of NIST publication [SP 800-56A](http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf), *Recommendation for Pair-Wise Key Establishment Schemes Using Discrete Logarithm Cryptography*. This function is known as *Concatenation KDF* or *Concat +KDF*. + +You may disable this extension by setting the following configuration variable +in `conf.mk`: + + CFG_CRYPTO_CONCAT_KDF := n + +## Implementation notes + +All key and parameter sizes must be multiples of 8 bits. That is: +- Input parameters: the shared secret (*Z*) and *OtherInfo* +- Output parameter: the derived key (*DerivedKeyingMaterial*) + +In addition, the maximum size of the derived key is limited by the size of an +object of type TEE_TYPE_GENERIC_SECRET (512 bytes). + +This implementation does *not* enforce any requirement on the content of the +*OtherInfo* parameter. It is the application's responsibility to make sure this +parameter is constructed as specified by the NIST specification if compliance +is desired. + + +## API extension + +To support the Concat KDF, the *GlobalPlatform TEE Internal API Specification +v1.0* was extended with new algorithm descriptors, new object types, and new +object attributes as described below. + +### p.95 Add new object type to TEE_PopulateTransientObject + +The following entry shall be added to Table 5-8: + +Object type | Parts +:---------------------|:-------------------------------------------- +TEE_TYPE_CONCAT_KDF_Z | The TEE_ATTR_CONCAT_KDF_Z part (input shared secret) must be provided. + +### p.121 Add new algorithms for TEE_AllocateOperation + +The following entry shall be added to Table 6-3: + +Algorithm | Possible Modes +:---------------------------|:-------------- +TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY | TEE_MODE_DERIVE + +### p.126 Explain usage of HKDF algorithms in TEE_SetOperationKey + +In the bullet list about operation mode, the following shall be added: + + * For the Concat KDF algorithms, the only supported mode is TEE_MODE_DERIVE. + +### p.150 Define TEE_DeriveKey input attributes for new algorithms + +The following sentence shall be deleted: + + The TEE_DeriveKey function can only be used with the algorithm + TEE_ALG_DH_DERIVE_SHARED_SECRET + +The following entry shall be added to Table 6-7: + +Algorithm | Possible operation parameters +:---------------------------|:----------------------------- +TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY <br> TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY | TEE_ATTR_CONCAT_KDF_DKM_LENGTH: up to 512 bytes. This parameter is mandatory. <br> TEE_ATTR_CONCAT_KDF_OTHER_INFO + +### p.152 Add new algorithm identifiers + +The following entries shall be added to Table 6-8: + +Algorithm | Identifier +:------------------------------------|:---------- +TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY | 0x800020C1 +TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY | 0x800030C1 +TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY | 0x800040C1 +TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY | 0x800050C1 +TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY | 0x800060C1 + +### p.154 Define new main algorithm + +In Table 6-9 in section 6.10.1, a new value shall be added to the value column +for row bits [7:0]: + +Bits | Function | Value +:----------|:-----------------------------------------------|:----------------- +Bits [7:0] | Identifiy the main underlying algorithm itself | ...<br>0xC1: Concat KDF + +The function column for bits[15:12] shall also be modified to read: + +Bits | Function | Value +:------------|:---------------------------------------------|:----------- +Bits [15:12] | Define the message digest for asymmetric signature algorithms or Concat KDF | + +### p.155 Add new object type for Concat KDF input shared secret + +The following entry shall be added to Table 6-10: + +Name | Identifier | Possible sizes +:---------------------------------|:-----------|:-------------------------------- +TEE_TYPE_CONCAT_KDF_Z | 0xA10000C1 | 8 to 4096 bits (multiple of 8) + +### p.156 Add new operation attributes for Concat KDF + +The following entries shall be added to Table 6-11: + +Name | Value | Protection | Type | Comment +:----------------------------------|:-----------|:-----------|:------|:-------- +TEE_ATTR_CONCAT_KDF_Z | 0xC00001C1 | Protected | Ref | The shared secret (*Z*) +TEE_ATTR_CONCAT_KDF_OTHER_INFO | 0xD00002C1 | Public | Ref | *OtherInfo* +TEE_ATTR_CONCAT_KDF_DKM_LENGTH | 0xF00003C1 | Public | Value | The length (in bytes) of the derived keying material to be generated, maximum 512. This is *KeyDataLen* / 8. diff --git a/documentation/extensions/crypto_hkdf.md b/documentation/extensions/crypto_hkdf.md new file mode 100644 index 0000000..16a27da --- /dev/null +++ b/documentation/extensions/crypto_hkdf.md @@ -0,0 +1,99 @@ +# OP-TEE HKDF key derivation support + +OP-TEE implements the *HMAC-based Extract-and-Expand Key Derivation Function +(HKDF)* specified in [RFC 5869](http://tools.ietf.org/html/rfc5869). This +file documents the extensions to the *GlobalPlatform TEE Internal API +Specification v1.0* that were implemented to support this algorithm. Trusted +Applications should include `<tee_api_defines_extensions.h>` to import the +definitions. + +Note that the implementation follows the recommendations of version 1.1 of the +specification for adding new algorithms. It should make it compatible with +future changes to the official specification. + +You can disable this extension by setting the following in `conf.mk`: + + CFG_CRYPTO_HKDF := n + +## p.95 Add new object type to TEE_PopulateTransientObject + +The following entry shall be added to Table 5-8: + +Object type | Parts +:-----------------|:-------------------------------------------- +TEE_TYPE_HKDF_IKM | The TEE_ATTR_HKDF_IKM (Input Keying Material) part must be provided. + +## p.121 Add new algorithms for TEE_AllocateOperation + +The following entry shall be added to Table 6-3: + +Algorithm | Possible Modes +:---------------------------|:-------------- +TEE_ALG_HKDF_MD5_DERIVE_KEY <br> TEE_ALG_HKDF_SHA1_DERIVE_KEY <br> TEE_ALG_HKDF_SHA224_DERIVE_KEY <br> TEE_ALG_HKDF_SHA256_DERIVE_KEY <br> TEE_ALG_HKDF_SHA384_DERIVE_KEY <br> TEE_ALG_HKDF_SHA512_DERIVE_KEY <br> TEE_ALG_HKDF_SHA512_DERIVE_KEY | TEE_MODE_DERIVE + +## p.126 Explain usage of HKDF algorithms in TEE_SetOperationKey + +In the bullet list about operation mode, the following shall be added: + + * For the HKDF algorithms, the only supported mode is TEE_MODE_DERIVE. + +## p.150 Define TEE_DeriveKey input attributes for new algorithms + +The following sentence shall be deleted: + + The TEE_DeriveKey function can only be used with the algorithm + TEE_ALG_DH_DERIVE_SHARED_SECRET + +The following entry shall be added to Table 6-7: + +Algorithm | Possible operation parameters +:---------------------------|:----------------------------- +TEE_ALG_HKDF_MD5_DERIVE_KEY <br> TEE_ALG_HKDF_SHA1_DERIVE_KEY <br> TEE_ALG_HKDF_SHA224_DERIVE_KEY <br> TEE_ALG_HKDF_SHA256_DERIVE_KEY <br> TEE_ALG_HKDF_SHA384_DERIVE_KEY <br> TEE_ALG_HKDF_SHA512_DERIVE_KEY <br> TEE_ALG_HKDF_SHA512_DERIVE_KEY | TEE_ATTR_HKDF_OKM_LENGTH: Number of bytes in the Output Keying Material <br> TEE_ATTR_HKDF_SALT (optional) Salt to be used during the extract step <br> TEE_ATTR_HKDF_INFO (optional) Info to be used during the expand step <br> + +## p.152 Add new algorithm identifiers + +The following entries shall be added to Table 6-8: + +Algorithm | Identifier +:------------------------------|:---------- +TEE_ALG_HKDF_MD5_DERIVE_KEY | 0x800010C0 +TEE_ALG_HKDF_SHA1_DERIVE_KEY | 0x800020C0 +TEE_ALG_HKDF_SHA224_DERIVE_KEY | 0x800030C0 +TEE_ALG_HKDF_SHA256_DERIVE_KEY | 0x800040C0 +TEE_ALG_HKDF_SHA384_DERIVE_KEY | 0x800050C0 +TEE_ALG_HKDF_SHA512_DERIVE_KEY | 0x800060C0 + +## p.154 Define new main algorithm + +In Table 6-9 in section 6.10.1, a new value shall be added to the value column +for row bits [7:0]: + +Bits | Function | Value +:----------|:-----------------------------------------------|:----------------- +Bits [7:0] | Identifiy the main underlying algorithm itself | ...<br>0xC0: HKDF + +The function column for bits[15:12] shall also be modified to read: + +Bits | Function | Value +:------------|:---------------------------------------------|:----------- +Bits [15:12] | Define the message digest for asymmetric signature algorithms or HKDF | + +## p.155 Add new object type for HKDF input keying material + +The following entry shall be added to Table 6-10: + +Name | Identifier | Possible sizes +:-----------------|:-----------|:-------------------------------- +TEE_TYPE_HKDF_IKM | 0xA10000C0 | 8 to 4096 bits (multiple of 8) + +## p.156 Add new operation attributes for HKDF salt and info + +The following entries shall be added to Table 6-11: + +Name | Value | Protection | Type | Comment +:------------------------|:-----------|:-----------|:------|:-------- +TEE_ATTR_HKDF_IKM | 0xC00001C0 | Protected | Ref | +TEE_ATTR_HKDF_SALT | 0xD00002C0 | Public | Ref | +TEE_ATTR_HKDF_INFO | 0xD00003C0 | Public | Ref | +TEE_ATTR_HKDF_OKM_LENGTH | 0xF00004C0 | Public | Value | + diff --git a/documentation/extensions/crypto_pbkdf2.md b/documentation/extensions/crypto_pbkdf2.md new file mode 100644 index 0000000..7e22ddd --- /dev/null +++ b/documentation/extensions/crypto_pbkdf2.md @@ -0,0 +1,94 @@ +# PKCS #5 v2.0 Key Derivation Function 2 (PBKDF2) + +This document describes the OP-TEE implementation of the key derivation function +specified in [RFC 2898](https://www.ietf.org/rfc/rfc2898.txt) section 5.2. This +RFC is a republication of PKCS #5 v2.0 from RSA Laboratories' Public-Key +Cryptography Standards (PKCS) series. + +You may disable this extension by setting the following configuration variable +in `conf.mk`: + + CFG_CRYPTO_PBKDF2 := n + +## API extension + +To support PBKDF2, the *GlobalPlatform TEE Internal API Specification +v1.0* was extended with a new algorithm descriptor, new object types, and new +object attributes as described below. + +### p.95 Add new object type to TEE_PopulateTransientObject + +The following entry shall be added to Table 5-8: + +Object type | Parts +:------------------------|:-------------------------------------------- +TEE_TYPE_PBKDF2_PASSWORD | The TEE_ATTR_PBKDF2_PASSWORD part must be provided. + +### p.121 Add new algorithms for TEE_AllocateOperation + +The following entry shall be added to Table 6-3: + +Algorithm | Possible Modes +:---------------------------|:-------------- +TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY | TEE_MODE_DERIVE + +### p.126 Explain usage of PBKDF2 algorithm in TEE_SetOperationKey + +In the bullet list about operation mode, the following shall be added: + + * For the PBKDF2 algorithm, the only supported mode is TEE_MODE_DERIVE. + +### p.150 Define TEE_DeriveKey input attributes for new algorithms + +The following sentence shall be deleted: + + The TEE_DeriveKey function can only be used with the algorithm + TEE_ALG_DH_DERIVE_SHARED_SECRET + +The following entry shall be added to Table 6-7: + +Algorithm | Possible operation parameters +:---------------------------|:----------------------------- +TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY | TEE_ATTR_PBKDF2_DKM_LENGTH: up to 512 bytes. This parameter is mandatory. <br> TEE_ATTR_PBKDF2_SALT <br> TEE_ATTR_PBKDF2_ITERATION_COUNT: This parameter is mandatory. + +### p.152 Add new algorithm identifiers + +The following entries shall be added to Table 6-8: + +Algorithm | Identifier +:------------------------------------|:---------- +TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY | 0x800020C2 + +### p.154 Define new main algorithm + +In Table 6-9 in section 6.10.1, a new value shall be added to the value column +for row bits [7:0]: + +Bits | Function | Value +:----------|:-----------------------------------------------|:----------------- +Bits [7:0] | Identifiy the main underlying algorithm itself | ...<br>0xC2: PBKDF2 + +The function column for bits[15:12] shall also be modified to read: + +Bits | Function | Value +:------------|:---------------------------------------------|:----------- +Bits [15:12] | Define the message digest for asymmetric signature algorithms or PBKDF2 | + +### p.155 Add new object type for PBKDF2 password + +The following entry shall be added to Table 6-10: + +Name | Identifier | Possible sizes +:---------------------------------|:-----------|:-------------------------------- +TEE_TYPE_PBKDF2_PASSWORD | 0xA10000C2 | 8 to 4096 bits (multiple of 8) + +### p.156 Add new operation attributes for Concat KDF + +The following entries shall be added to Table 6-11: + +Name | Value | Protection | Type | Comment +:----------------------------------|:-----------|:-----------|:------|:-------- +TEE_ATTR_PBKDF2_PASSWORD | 0xC00001C2 | Protected | Ref | +TEE_ATTR_PBKDF2_SALT | 0xD00002C2 | Public | Ref | +TEE_ATTR_PBKDF2_ITERATION_COUNT | 0xF00003C2 | Public | Value | +TEE_ATTR_PBKDF2_DKM_LENGTH | 0xF00004C2 | Public | Value | The length (in bytes) of the derived keying material to be generated, maximum 512. diff --git a/documentation/extensions/extensions.md b/documentation/extensions/extensions.md new file mode 100644 index 0000000..b4b6444 --- /dev/null +++ b/documentation/extensions/extensions.md @@ -0,0 +1,31 @@ +# General Extensions to the GlobalPlatform TEE Internal API + +This document describes the OP-TEE extensions introduced with respect to the GlobalPlatform TEE API Specifications v1.0. + +Specific extensions documentation are part of: +* Cryptographic Extensions + * [Concatenation Key Derivation](crypto_concat_kdf.md) + * [HMAC Key Derivation](crypto_hkdf.md) + * [Public-Key Key Derivation](crypto_pbkdf2.md) + + +# Cache Maintenance Support +Following functions have been introduced in order to operate with cache: + + TEE_Result TEE_CacheClean(char *buf, size_t len); + TEE_Result TEE_CacheFlush(char *buf, size_t len); + TEE_Result TEE_CacheInvalidate(char *buf, size_t len); + +These functions are available to any Trusted Application defined with the flag TA_FLAG_CACHE_MAINTENANCE sets on. When not set, each function returns the error code TEE_ERROR_NOT_SUPPORTED. + +Within these extensions, a Trusted Application is able to operate on the data cache, with the following specification: + +Function | Description +:---------------------|:---------- +TEE_CacheClean() | Write back to memory any dirty data cache lines. The line is marked as not dirty. The valid bit is unchanged +TEE_CacheFlush() | Purges any valid data cache lines. Any dirty cache lines are first written back to memory, then the cache line is invalidated. +TEE_CacheInvalidate() | Invalidate any valid data cache lines. Any dirty line are not written back to memory. + +In the following 2 cases, the error code TEE_ERROR_ACCESS_DENIED is returned: +* the memory range has not the write access, that is TEE_MEMORY_ACCESS_WRITE is not set. +* the memory is not a User Space memory diff --git a/documentation/file_structure.md b/documentation/file_structure.md new file mode 100644 index 0000000..b68d078 --- /dev/null +++ b/documentation/file_structure.md @@ -0,0 +1,60 @@ +# Structure of files + +## Top level directories +Directory | Description +:---------|:------------ +/core | Files that are only used building TEE Core +/lib | Files that are used both when building TEE Core and TAs +/ta | Files that are only used when building TAs +/mk | Makefiles supporting the build system +/tmp-stuff| Temporary stuff that will be removed before the final commit is made +/scripts | Helper scripts for miscellaneous tasks +/out | Created when building unless a different out directory is specified with O=... on the command line + +## Structure of /core +Directory | Description +:---------|:------------ +/arch | Architecture and platform specific files +/lib | Generic libraries that are likely to be replaced in a final product +/mm | Generic memory management, currently empty +/tee | Generic TEE files + +## Structure of /core/arch +Directory | Description +:---------|:------------ +/arm | ARMv7 and Aarch32 specific architecture and platform specific files +/user_mode| Linux used space specific files when debugging TEE Core as a user space process, only used for some development + +## Structure of /core/arch/arm +Directory | Description +:---------|:------------ +/include | Include files used in rest of TEE core but not in any supporting libraries +/kern | Low level and core parts of TEE Core +/mm | Memory management +/tee | TEE files +/sm | Secure Monitor +/plat-foo | Specific files for the 'foo' platform + +## Structure of /core/arch/arm/include +Directory | Description +:---------|:------------ +/kern | Include files exposing API for /core/arch/arm/kern files +/kta | Include files exposing the KTA API that is mainly used by kernel TAs +/mm | Include files exposing API for /core/arch/arm/mm files +/rom | Old ROM files that should be removed before going public +/sm | Include files exposing API for Secure Monitor + +## Structure of /core/lib/lib{crypto,sla} +Directory | Description +:---------|:------------ +/ | Source files for the library +/include | Include files exposing the API of the library + +## Structure of /lib/libutils +Directory | Description +:---------|:------------ +/ | Source file for the library +/arch | Architecture specific source files +/arch/arm | ARMv7 and Aarch32 specific source files +/arch/arm/include | ARMv7 and Aarch32 specific include files +/include | Include files exposing the API of the library diff --git a/documentation/github.md b/documentation/github.md new file mode 100644 index 0000000..00675c7 --- /dev/null +++ b/documentation/github.md @@ -0,0 +1,188 @@ +GitHub usage +============ + +The document describes how to use GitHub. Various links to GitHub +documentation are given. The main GitHub documentation is located +at <a href="https://help.github.com/">https://help.github.com/</a> + + +----------------------------------------------------------------- + + +GitHub Setup +------------ + +### GitHub Account Setup + +In order to clone a repository, there is no need to own a GitHub +account. But as soon as one wants to contribute, a GitHub account +is required. In such a case, you must create a GitHub account +by connecting to +<a href="https://github.com/">https://github.com/</a>. +Click on *Sign up for GitHub* and follow the steps. +Note that a free plan is sufficient to collaborate to the project. + +SSH connection with GitHub repositories is the way of developing that +is described in this help. For this, SSH keys must be configured as +described in the *ssh* section of +<a href="https://help.github.com/">https://help.github.com/</a>. + + +### Fork + +Only owners of the OP-TEE repositories can write directly to the git +repositories. Contributors must *fork* the OP-TEE/optee_os.git repository +into their personal account to work. The complete documentation about *forking* +can be found at +<a href="https://help.github.com/articles/fork-a-repo">https://help.github.com/articles/fork-a-repo</a>. + +Note that the fork has to be performed once and only once. + + +----------------------------------------------------------------- + + +Contributing +------------ +In the following: + +* Only the Linux commands to extract the sources and to + contribute are given. Windows or iMac way of working are not described. +* *myaccount* stands for the developer github account id + +### SSH Configuration +.ssh/config file may contain something like: + + Host github.com + user myaccount + IdentityFile ~/.ssh/id_rsa_github + Hostname 192.30.252.128 + +### Cloning the sources + # Clone the forked repository + git clone git@github.com:myaccount/optee_os.git + + # Add the reference, called "upstream" + cd optee_os + git remote add upstream git@github.com:OP-TEE/optee_os.git + + # Retrieve the gits + git fetch --all + +In order to be able to read the pull-request, one may add +in .git/config the following section + + # Add to manage Pull-Request + [remote "upstream"] + fetch = +refs/pull/*/head:refs/remotes/upstream/pr/* + +Once retrieve, remotes/upstream/pr/* branches are appearing. They +correspond to the pull-request id code. Note that these branches +are read-only, for developers and owners. Have a look at +<a href="https://gist.github.com/piscisaureus/3342247">https://gist.github.com/piscisaureus/3342247</a> +for a complete description of this syntax. + +Another way to pull a pull-request, without modifying .git/config file, +is to use the patch file that is available for each pull-request. As an +example, here is the command to pull the pull-request id #784: + + curl -L 'https://github.com/OP-TEE/optee_os/pull/784.patch' | git am + +### Synchronization + +First of all, the forked repository must be in sync with the OP-TEE +sources. Let's assume that *upstream_master* is the local branch corresponding to *remotes/upstream/master* + +Synchronizing the forked and the upstream repositories can be done through + + # Update the local sources + git fetch --all + + # Reset upstream_master + git checkout upstream_master + git reset --hard upstream/master + git push origin upstream_master:master + +### Contributing + +To be able to contribute, you must create a local branch containing your fixes. +The branch name must be explicit. Here are some examples: + +* issue/75 if the contribution is expected to fix issue number 75. +* feature/more_traces if the contribution will add new traces +* ... + +Here is how to create the contribute and push on the forked repository + + git checkout -b feature/my_new_feature + ... contribution ... + git add . + git commit -s + +Commit message should be clear and as much explicit as possible. +Moreover, if the fix is related to the issue number 75 (as an example), +you must add in the commit message + + It fixes #75 (GitHub issue) + +Then the contribution is pushed on the forked repository + + git push origin feature/my_new_feature:feature/my_new_feature + +Then the pull-request can be created through the GitHub UI. Documentation +can be found at +<a href="https://help.github.com/articles/using-pull-requests">https://help.github.com/articles/using-pull-requests</a> +and the *Collaborating* section of +<a href="https://help.github.com">https://help.github.com</a> + +It may be that you will get comments from reviewers on the commits you provided. +If so happens, you will need to address the comments and you might end up having +to upload additional commits, which could be done by the following commands + + git add . + git commit -s + git push origin feature/my_new_feature:feature/my_new_feature + +Note that the pull-request is automatically updated with the new commit. + +### Finalizing the contribution +Once reviewers and the contributor has agreed that the patch-set is OK, then the +contributor needs to squash the commits into a single commit (a +*"squashed-commit-on-top-of-master"*), meaning + +* A single-point contribution for most of the cases +* That is rebased on upstream/master, in case the master has + been updated +* Add tags in the commit message to grant people that reviewed and tested the patch. + Typically, you may add at the end of the commit message the tags *Reviewed-by* + and *Tested-by*, as provided in the comments of the pull-request. + + +Following commands are guidelines to achieve the +*squashed-commit-on-top-of-master*. Note that this ends with a +*"push -f"* + + git fetch --all + git checkout -b feature/my_new_feature_tbs + git checkout feature/my_new_feature + git reset --hard upstream/master + git merge --squash feature/my_new_feature_tbs + git commit -s + (add the tag, as for example): + Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org> + Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> + Tested-by: Joakim Bech <joakim.bech@linaro.org> (FVP platform) + Tested-by: Pascal Brand <pascal.brand@linaro.org> (STM platform) + git push -f origin feature/my_new_feature:feature/my_new_feature + +Note: + +* The commit message may take a summary of all the squashed + commit messages. Also, one should add which GitHub issue it fixes, + if any. +* Some comments created in the GitHub UI will be lost. + +The owner of OP-TEE/optee_os.git can now merge the pull-request. +How this is done is not described in this document. +It is the owners responsibility to save a log of the comments that were +available before the forced-push. diff --git a/documentation/globalplatform_api.md b/documentation/globalplatform_api.md new file mode 100644 index 0000000..f8ed8d7 --- /dev/null +++ b/documentation/globalplatform_api.md @@ -0,0 +1,106 @@ +GlobalPlatform API and OP-TEE +============================= + +Contents : + +1. Introduction +2. TEE Client API +3. TEE Internal API + +# 1. Introduction +[GlobalPlatform](http://www.globalplatform.org) works across industries to +identify, develop and publish specifications which facilitate the secure and +interoperable deployment and management of multiple embedded applications on +secure chip technology. OP-TEE has support for GlobalPlatform [TEE Client API +Specification v1.0](http://www.globalplatform.org/specificationsdevice.asp) and +[TEE Internal API Specification +v1.0](http://www.globalplatform.org/specificationsdevice.asp). + +# 2. TEE Client API +The TEE Client API describes and defines how a client running in a rich +operating environment (REE) should communicate with the TEE. To identify a +Trusted Application (TA) to be used, the client provides an +[UUID](http://en.wikipedia.org/wiki/Universally_unique_identifier). All TA's +exposes one or several functions. Those functions corresponds to a so called +`commandID` which also is sent by the client. + +### TEE Contexts +The TEE Context is used for creating a logical connection between the client and +the TEE. The context must be initialized before the TEE Session can be +created. When the client has completed a jobs running in secure world, it should +finalize the context and thereby also releasing resources. + +### TEE Sessions +Sessions are used to create logical connections between a client and a specific +Trusted Application. When the session has been established the client have a +opened up the communication channel towards the specified Trusted Application +identified by the `UUID`. At this stage the client and the Trusted Application +can start to exchange data. + + +### TEE Client API example / usage +Below you will find the main functions as defined by GlobalPlatform and which +are used in the communication between the client and the TEE. + +#### TEE Functions +``` c +TEEC_Result TEEC_InitializeContext( + const char* + name, + TEEC_Context* context) + +void TEEC_FinalizeContext( + TEEC_Context* context) + +TEEC_Result TEEC_OpenSession ( + TEEC_Context* context, + TEEC_Session* session, + const TEEC_UUID* destination, + uint32_t connectionMethod, + const void* connectionData, + TEEC_Operation* operation, + uint32_t* returnOrigin) + +void TEEC_CloseSession ( + TEEC_Session* session) + +TEEC_Result TEEC_InvokeCommand( + TEEC_Session* session, + uint32_t commandID, + TEEC_Operation* operation, + uint32_t* returnOrigin) +``` + +In principle the commands are called in this order: + + TEEC_InitializeContext(...) + TEEC_OpenSession(...) + TEEC_InvokeCommand(...) + TEEC_CloseSession(...) + TEEC_FinalizeContext(...) + +It is not uncommon that `TEEC_InvokeCommand` is called several times in row +when the session has been established. + +For a complete example, please see chapter **5.2 Example 1: Using the TEE +Client API** in the GlobalPlatform [TEE Client API +Specification v1.0](http://www.globalplatform.org/specificationsdevice.asp). + + +# 3. TEE Internal API +The Internal API is the API that is exposed to the Trusted Applications running +in the secure world. The TEE Internal API consists of four major parts: + +1. **Trusted Storage API for Data and Keys** +2. **Cryptographic Operations API** +3. **Time API** +4. **Arithmetical API** + +### Examples / usage +Calling the Internal API is done in the same way as described above using Client API. +The best place to find information how this should be done is in the +[TEE Internal API Specification +v1.0](http://www.globalplatform.org/specificationsdevice.asp) which contains a +lot of examples of how to call the various APIs. + + diff --git a/documentation/gprof.md b/documentation/gprof.md new file mode 100644 index 0000000..532900a --- /dev/null +++ b/documentation/gprof.md @@ -0,0 +1,60 @@ +# Profiling user Trusted Applications with `gprof` + +The configuration option `CFG_TA_GPROF_SUPPORT=y` enables OP-TEE to +collect profiling information from Trusted Applications running in user +mode and compiled with `-pg`. +Once collected, the profiling data are formated in the `gmon.out` format +and sent to `tee-supplicant` via RPC, so they can be saved to disk and +later processed and displayed by the standard `gprof` tool. + +## Usage + +- Build OP-TEE OS with `CFG_TA_GPROF_SUPPORT=y`. You may also set + `CFG_ULIBS_GPROF=y` to instrument the user TA libraries (libutee, libutils, + libmpa). +- Build user TAs with `-pg`, for instance using: `CFLAGS_ta_arm32=-pg` + or `CFLAGS_ta_arm64=-pg`. Note that instrumented TAs have a larger `.bss` + section. The memory overhead is 1.36 times the `.text` size for 32-bit TAs, + and 1.77 times for 64-bit ones (refer to the TA linker script for details: + `ta/arch/arm/ta.ld.S`). +- Run the application normally. When the last session exits, + `tee-supplicant` will write profiling data to + `/tmp/gmon-<ta_uuid>.out`. If the file already exists, a number is + appended, such as: `gmon-<ta_uuid>.1.out`. +- Run gprof on the TA ELF file and profiling output: + `gprof <ta_uuid>.elf gmon-<ta_uuid>.out` + +## Implementation + +Part of the profiling is implemented in libutee. Another part is done +in the TEE core by a pseudo-TA (`core/arch/arm/sta/gprof.c`). Two types +of data are collected: + + 1. Call graph information + + When TA source files are compiled with the -pg switch, the compiler +generates extra code into each function prologue to call the +instrumentation entry point (`__gnu_mcount_nc` or `_mcount` depending +on the architecture). Each time an instrumented function is called, +libutee records a pair of program counters (one is the caller and the +other one is the callee) as well as the number of times this specific +arc of the call graph has been invoked. + + 2. PC distribution over time + + When an instrumented TA starts, libutee calls the pseudo-TA to start +PC sampling for the current session. Sampling data are written into +the user-space buffer directly by the TEE core. + + Whenever the TA execution is interrupted, the TEE core records the +current program counter value and builds a histogram of program +locations (i.e., relative amount of time spent for each value of the +PC). This is later used by the gprof tool to derive the time +spent in each function. The sampling rate, which is assumed to be +roughly constant, is computed by keeping track of the time spent +executing user TA code and dividing the number of interrupts by the +total time. + +The profiling buffer into which call graph and sampling data are +recorded is allocated in the TA's `.bss` section. Some space is reserved +by the linker script, only when the TA is instrumented. diff --git a/documentation/images/interrupt_handling/Makefile b/documentation/images/interrupt_handling/Makefile new file mode 100644 index 0000000..962cdee --- /dev/null +++ b/documentation/images/interrupt_handling/Makefile @@ -0,0 +1,20 @@ + +.PHONY: all +all: + +MSC_SRCS = tee_invoke.msc irq.msc fiq.msc irq_fiq.msc + +PNGS += $(MSC_SRCS:.msc=.png) + +# Disable all builtin rules +.SUFFIXES: +.SUFFIXES: .png .msc + +all: $(PNGS) + +%.png : %.msc + mscgen -T png $< + +.PHONY: clean +clean: + rm -f $(PNGS) diff --git a/documentation/images/interrupt_handling/fiq.msc b/documentation/images/interrupt_handling/fiq.msc new file mode 100644 index 0000000..5d1a284 --- /dev/null +++ b/documentation/images/interrupt_handling/fiq.msc @@ -0,0 +1,24 @@ +msc { + hscale = "1.5", wordwraparcs = on; + + a [label="Normal world"], b [label="Secure Monitor"], + c [label="Trusted OS entry"], d [label="Trusted OS"]; + + + ||| ; + --- [ label = "Running in non-secure world (SCR_NS set)" ]; + ... ; + --- [ label = "IRQ and FIQ masked,\nFIQ received" ]; + b=>b [ label = "Save non-secure context" ]; + b=>b [ label = "Restore secure context" ]; + b>>c [ label = "eret: FIQ" ]; + --- [ label = "FIQ unmasked" ]; + d=>d [ label = "process received FIQ" ]; + --- [ label = "FIQ masked" ]; + c=>b [ label = "smc: return" ]; + b=>b [ label = "Save secure context" ]; + b=>b [ label = "Restore non-secure context" ]; + b>>a [ label = "eret: return to Normal world" ]; + --- [ label = "IRQ and FIQ unmasked" ]; + ... ; +} diff --git a/documentation/images/interrupt_handling/fiq.png b/documentation/images/interrupt_handling/fiq.png Binary files differnew file mode 100644 index 0000000..0037c1b --- /dev/null +++ b/documentation/images/interrupt_handling/fiq.png diff --git a/documentation/images/interrupt_handling/irq.msc b/documentation/images/interrupt_handling/irq.msc new file mode 100644 index 0000000..62657cc --- /dev/null +++ b/documentation/images/interrupt_handling/irq.msc @@ -0,0 +1,30 @@ +msc { + hscale = "1.5", wordwraparcs = on; + + a [label="Normal world"], b [label="Secure Monitor"], + c [label="Trusted OS entry"], d [label="Trusted OS"]; + + + --- [ label = "IRQ and FIQ unmasked" ]; + d=>d [ label = "process" ]; + --- [ label = "IRQ and FIQ masked,\nIRQ received" ]; + d=>d [ label = "suspend thread" ]; + d=>c [ label = "forward IRQ" ]; + c=>b [ label = "smc: forward IRQ" ]; + b=>b [ label = "Save secure context" ]; + b=>b [ label = "Restore non-secure context" ]; + --- [ label = "IRQ and FIQ unmasked" ]; + b>>a [ label = "eret: IRQ forwarded" ]; + --- [ label = "FIQ unmasked, IRQ received" ]; + a=>a [ label = "process IRQ" ]; + --- [ label = "IRQ and FIQ unmasked" ]; + a=>b [ label = "smc: return from IRQ" ]; + --- [ label = "IRQ and FIQ masked" ]; + b=>b [ label = "Save non-secure context" ]; + b=>b [ label = "Restore secure context" ]; + b>>c [ label = "eret: return from IRQ" ]; + c=>c [ label = "find thread" ]; + c>>d [ label = "resume execution"]; + --- [ label = "IRQ and FIQ unmasked" ]; + d=>d [ label = "process" ]; +} diff --git a/documentation/images/interrupt_handling/irq.png b/documentation/images/interrupt_handling/irq.png Binary files differnew file mode 100644 index 0000000..293b303 --- /dev/null +++ b/documentation/images/interrupt_handling/irq.png diff --git a/documentation/images/interrupt_handling/irq_fiq.msc b/documentation/images/interrupt_handling/irq_fiq.msc new file mode 100644 index 0000000..5098360 --- /dev/null +++ b/documentation/images/interrupt_handling/irq_fiq.msc @@ -0,0 +1,43 @@ +msc { + hscale = "1.5", wordwraparcs = on; + + a [label="Normal world"], b [label="Secure Monitor"], + c [label="Trusted OS entry"], d [label="Trusted OS"]; + + + --- [ label = "IRQ and FIQ unmasked" ]; + d=>d [ label = "process" ]; + --- [ label = "IRQ and FIQ masked,\nIRQ received" ]; + d=>d [ label = "suspend thread" ]; + d=>c [ label = "forward IRQ" ]; + c=>b [ label = "smc: forward IRQ" ]; + b=>b [ label = "Save secure context" ]; + b=>b [ label = "Restore non-secure context" ]; + --- [ label = "IRQ and FIQ unmasked" ]; + b>>a [ label = "eret: IRQ forwarded" ]; + --- [ label = "FIQ unmasked, IRQ received" ]; + a=>a [ label = "process IRQ" ]; + --- [ label = "IRQ and FIQ masked,\nFIQ received" ]; + b=>b [ label = "Save non-secure context" ]; + b=>b [ label = "Restore secure context" ]; + b>>c [ label = "eret: FIQ" ]; + --- [ label = "FIQ unmasked" ]; + d=>d [ label = "process received FIQ" ]; + --- [ label = "FIQ masked" ]; + c=>b [ label = "smc: return" ]; + b=>b [ label = "Save secure context" ]; + b=>b [ label = "Restore non-secure context" ]; + b>>a [ label = "eret: return to Normal world" ]; + --- [ label = "FIQ unmasked,\nIRQ still being processed" ]; + a=>a [ label = "process IRQ" ]; + a=>b [ label = "smc: return from IRQ" ]; + --- [ label = "IRQ and FIQ masked" ]; + b=>b [ label = "Save non-secure context" ]; + b=>b [ label = "Restore secure context" ]; + b>>c [ label = "eret: return from IRQ" ]; + c=>c [ label = "find thread" ]; + c>>d [ label = "resume execution"]; + --- [ label = "IRQ and FIQ unmasked" ]; + d=>d [ label = "process" ]; +} + diff --git a/documentation/images/interrupt_handling/irq_fiq.png b/documentation/images/interrupt_handling/irq_fiq.png Binary files differnew file mode 100644 index 0000000..e1359ae --- /dev/null +++ b/documentation/images/interrupt_handling/irq_fiq.png diff --git a/documentation/images/interrupt_handling/tee_invoke.msc b/documentation/images/interrupt_handling/tee_invoke.msc new file mode 100644 index 0000000..6ea699d --- /dev/null +++ b/documentation/images/interrupt_handling/tee_invoke.msc @@ -0,0 +1,25 @@ +msc { + hscale = "1.5", wordwraparcs = on; + + a [label="Normal world"], b [label="Secure Monitor"], + c [label="Trusted OS entry"], d [label="Trusted OS"]; + + + --- [ label = "IRQ and FIQ unmasked" ]; + a=>b [ label = "smc: TEE_FUNC_INVOKE" ]; + --- [ label = "IRQ and FIQ masked" ]; + b=>b [ label = "Save non-secure context" ]; + b=>b [ label = "Restore secure context" ]; + b>>c [ label = "eret: TEE_FUNC_INVOKE" ]; + c=>c [ label = "assign thread" ]; + c=>d [ label = "TEE_FUNC_INVOKE" ]; + --- [ label = "IRQ and FIQ unmasked" ]; + d=>d [ label = "process" ]; + --- [ label = "IRQ and FIQ masked" ]; + d>>c [ label = "SMC_CALL_RETURN" ]; + c=>b [ label = "smc: SMC_CALL_RETURN" ]; + b=>b [ label = "Save secure context" ]; + b=>b [ label = "Restore non-secure context" ]; + --- [ label = "IRQ and FIQ unmasked" ]; + b>>a [ label = "eret: return" ]; +} diff --git a/documentation/images/interrupt_handling/tee_invoke.png b/documentation/images/interrupt_handling/tee_invoke.png Binary files differnew file mode 100644 index 0000000..bbc592b --- /dev/null +++ b/documentation/images/interrupt_handling/tee_invoke.png diff --git a/documentation/images/secure_storage/block_data_encryption.odg b/documentation/images/secure_storage/block_data_encryption.odg Binary files differnew file mode 100644 index 0000000..655c81d --- /dev/null +++ b/documentation/images/secure_storage/block_data_encryption.odg diff --git a/documentation/images/secure_storage/block_data_encryption.png b/documentation/images/secure_storage/block_data_encryption.png Binary files differnew file mode 100644 index 0000000..b05f2c0 --- /dev/null +++ b/documentation/images/secure_storage/block_data_encryption.png diff --git a/documentation/images/secure_storage/meta_data_encryption.odg b/documentation/images/secure_storage/meta_data_encryption.odg Binary files differnew file mode 100644 index 0000000..f6785d4 --- /dev/null +++ b/documentation/images/secure_storage/meta_data_encryption.odg diff --git a/documentation/images/secure_storage/meta_data_encryption.png b/documentation/images/secure_storage/meta_data_encryption.png Binary files differnew file mode 100644 index 0000000..9c7f8c4 --- /dev/null +++ b/documentation/images/secure_storage/meta_data_encryption.png diff --git a/documentation/images/secure_storage/secure_storage_system_architecture.odg b/documentation/images/secure_storage/secure_storage_system_architecture.odg Binary files differnew file mode 100644 index 0000000..8462109 --- /dev/null +++ b/documentation/images/secure_storage/secure_storage_system_architecture.odg diff --git a/documentation/images/secure_storage/secure_storage_system_architecture.png b/documentation/images/secure_storage/secure_storage_system_architecture.png Binary files differnew file mode 100644 index 0000000..188ec97 --- /dev/null +++ b/documentation/images/secure_storage/secure_storage_system_architecture.png diff --git a/documentation/images/secure_storage/tee_file_structure.odg b/documentation/images/secure_storage/tee_file_structure.odg Binary files differnew file mode 100644 index 0000000..1742f27 --- /dev/null +++ b/documentation/images/secure_storage/tee_file_structure.odg diff --git a/documentation/images/secure_storage/tee_file_structure.png b/documentation/images/secure_storage/tee_file_structure.png Binary files differnew file mode 100644 index 0000000..2a838f2 --- /dev/null +++ b/documentation/images/secure_storage/tee_file_structure.png diff --git a/documentation/images/xlat_table.dot b/documentation/images/xlat_table.dot new file mode 100644 index 0000000..316cd6d --- /dev/null +++ b/documentation/images/xlat_table.dot @@ -0,0 +1,29 @@ +digraph g { + graph [ + rankdir = "LR" + ]; + node [ + fontsize = "16" + shape = "ellipse" + ]; + edge [ + ]; + "node_ttb" [ + label = "<f0> TTBR0 | <f1> TTBR1" + shape = "record" + ]; + "node_large_l1" [ + label = "<f0> Large L1\nSpans 4 GiB" + shape = "record" + ]; + "node_small_l1" [ + label = "Small L1\nSpans 32 MiB\nper entry | <f0> 0 | <f1> 1 | ... | <fn> n" + shape = "record" + ]; + + "node_ttb":f0 -> "node_small_l1":f0 [ label = "Thread 0 ctx active" ]; + "node_ttb":f0 -> "node_small_l1":f1 [ label = "Thread 1 ctx active" ]; + "node_ttb":f0 -> "node_small_l1":fn [ label = "Thread n ctx active" ]; + "node_ttb":f0 -> "node_large_l1" [ label="No active ctx" ]; + "node_ttb":f1 -> "node_large_l1"; +} diff --git a/documentation/images/xlat_table.png b/documentation/images/xlat_table.png Binary files differnew file mode 100644 index 0000000..b1198a2 --- /dev/null +++ b/documentation/images/xlat_table.png diff --git a/documentation/interrupt_handling.md b/documentation/interrupt_handling.md new file mode 100644 index 0000000..7ca8121 --- /dev/null +++ b/documentation/interrupt_handling.md @@ -0,0 +1,111 @@ +Entry and exit of secure world +============================== + +#Introduction +Depending on configuration of the system secure world can be entered during +different conditions. This document will describe only the configuration +used by OP-TEE. + +Monitor vector is VBAR_EL3 in AArch64 and MVBAR in ARMv7/AArch32. State +vector is any of: +* VBAR_EL2 or VBAR_EL1 (secure and non-secure) for AArch64, depending on + configuration of hypervisor +* HVBAR or VBAR (secure and non-secure) for ARMv7, depending on + configuration of hypervisor + +The processor is configured to use: +* Monitor vector for FIQ exceptions while SCR_NS is set and state vector + when SCR_NS is cleared +* Monitor vector for SMC exceptions +* State vector for IRQ exceptions + +Interrupts handled by secure world are sent as FIQs and interrupts handled +by normal world are sent as IRQs. + +Since IRQs are received using the state vector the actual vector used +depends on the current state of the CPU. If the NS (non-secure) bit in SCR +(Secure Control Register) is set then either HVBAR or VBAR (non-secure) is +used when receiving the IRQ, if the NS bit in SCR is cleared the secure +VBAR is used instead. This has the consequence that secure world can +receive IRQ that are supposed to be handled by normal world. When secure +world receives an IRQ it has to be forwarded to normal world for +processing. + +# The monitor +The monitor manages all entry and exit of secure world. To enter secure +world from normal world the monitor saves the state of normal world +(general purpose registers and system registers which are not banked) and +restores the previous state of secure world. Then a return from exception +is performed and the restored secure state is resumed. Exit from secure +world to normal world is the reverse. + +Some general purpose registers are not saved and restored on entry and +exit, those are used to pass parameters between secure and normal world +(see ARM_DEN0028A_SMC_Calling_Convention for details). + +# Entry and exit of Trusted OS +On entry and exit of Trusted OS each CPU is uses a separate entry stack and +runs with IRQ and FIQ blocked. + +During the entry phase a context is selected to start/resume execution in. +Only when a context has been restored/entered may IRQ and FIQ be unblocked. + +On exit IRQ and FIQ are blocked, the context is saved and the entry stack +is used again. + +![SMC entry of secure world](images/interrupt_handling/tee_invoke.png "SMC entry of secure world") + +# Forward IRQ from secure world to normal world +When an IRQ is received in secure world as an IRQ exception then secure world: + +1. Saves thread context (entire state of all processor modes for ARMv7) +2. Blocks FIQ (IRQ is already blocked) +3. Switches to entry stack +4. Issues an SMC with a value to indicates to normal world that an IRQ has + been delivered and last SMC call should be continued + +The monitor restores normal world context with a return code indicating +that an IRQ is about to be delivered. Normal world issues a new SMC +indicating that it should continue last SMC. + +The monitor restores secure world context which locates the previously +saved context and checks that it is a return from IRQ that is requested +before restoring the context and lets the secure world IRQ handler return +from exception where the execution would be resumed. + +Note that the monitor itself does not know/care that it has just forwarded +an IRQ to normal world. The bookkeeping is done in the thread handling in +Trusted OS. Normal world is responsible to decide when the secure world +thread should resume execution. If secure world really need to execute +something at a specific time it has to do that in FIQ context. + +![IRQ received in secure world and forwarded to normal world](images/interrupt_handling/irq.png "IRQ received in secure world and forwarded to normal world") + +# Deliver FIQ to secure world +A FIQ can be received during two different states, either in non-secure +world (SCR_NS is set) or in secure world (SCR_NS is cleared). When the +secure monitor is active (ARMv8 EL3 or ARMv7 Monitor mode) FIQ is masked. +FIQ reception in the two different states is described below. + +## Deliver FIQ to secure world when SCR_NS is set +When the monitor gets an FIQ exception it: + +1. Saves normal world context and restores secure world context from last + secure world exit (which will have IRQ and FIQ blocked) +2. Clears SCR_FIQ when clearing SCR_NS +3. Sets “FIQ” as parameter to secure world entry +4. Does a return from exception into secure context +5. Secure world unmasks FIQs because of the “FIQ” parameter +6. FIQ is received as in exception using the state vector +7. Secure world issues an SMC to return to normal world +8. Monitor saves secure world context and restores normal world context +9. Does a return from exception into restored context + +![FIQ received when SCR_NS is set](images/interrupt_handling/fiq.png "FIQ received when SCR_NS is set") + +![FIQ received while processing an IRQ forwarded from secure world](images/interrupt_handling/irq_fiq.png "FIQ received while processing an IRQ forwarded from secure world") + +## Deliver FIQ to secure world when SCR_NS is cleared +Since SCR_FIQ is cleared when SCR_NS is cleared a FIQ will be delivered +using the state vector (VBAR) in secure world. The FIQ is received as any +other exception by Trusted OS, the monitor is not involved at all. diff --git a/documentation/optee_design.md b/documentation/optee_design.md new file mode 100644 index 0000000..073b46b --- /dev/null +++ b/documentation/optee_design.md @@ -0,0 +1,696 @@ +OP-TEE design +======================== + +# Contents + +1. [Introduction](#1-introduction) +2. [Platform Initialization](#2-platform-initialization) +3. [Secure Monitor Calls - SMC](#3-secure-monitor-calls---smc) +4. [Thread handling](#4-thread-handling) +5. [MMU](#5-mmu) +6. [Stacks](#6-stacks) +7. [Shared Memory](#7-shared-memory) +8. [Pager](#8-pager) +9. [Memory Objects](#9-memory-objects) +10. [Cryptographic abstraction layer](#10-cryptographic-abstraction-layer) +11. [libutee](#11-libutee) +12. [Trusted Applications](#12-trusted-applications) + +# 1. Introduction +OP-TEE is a so called Trusted Execution Environment, in short a TEE, for ARM +based chips supporting TrustZone technology. OP-TEE consists of three +components. + ++ [OP-TEE Client], which is the client API running in normal world user space. ++ [OP-TEE Linux Kernel driver], which is the driver that handles the + communication between normal world user space and secure world. ++ [OP-TEE Trusted OS], which is the Trusted OS running in secure world. + +OP-TEE was designed with scalability and portability in mind and as of now it +has been ported to quite a few different platforms, both ARMv7-A and ARMv8-A +from different vendors. For a full list, please see [Platforms Supported]. + +OP-TEE OS is made of 2 main components: the OP-TEE core and a collection of +libraries designed for being used by Trusted Applications. While OP-TEE core +executes in the ARM CPU privileged level (also referred to as 'kernel land'), +the Trusted Applications execute in the non-privileged level (also referred to as +the 'userland'). The static libraries provided by the OP-TEE OS enable Trusted +Applications to call secure services executing at a more privileged level. + +# 2. Platform initialization +TBD + +# 3. Secure Monitor Calls - SMC +## 3.1 SMC handling +TBD + +## 3.2 SMC Interface +The OP-TEE SMC interface is defined in two levels using [optee_smc.h] and +[optee_msg.h]. The former file defines SMC identifiers and what is passed in the +registers for each SMC. The latter file defines the OP-TEE Message protocol +which is not restricted to only SMC even if that currently is the only option +available. + +## 3.3 Communication using SMC Interface +The main structure used for the SMC communication is defined in [struct +optee_msg_arg]. If we are looking into the source code, we could see that +communication mainly is achieved using `optee_msg_arg` and `thread_smc_args`, +where `optee_msg_arg` could be seen as the main structure. What will happen is +that the [OP-TEE Linux Kernel driver] will get the parameters either from +[OP-TEE Client] or directly from an internal service in the Linux kernel. The +TEE driver will populate the struct `optee_msg_arg` with the parameters plus +some additional bookkeeping information. Parameters for the SMC are passed in +registers 1 to 7, register 0 holds the SMC id which among other things tells +whether it is a standard or a fast call. + +# 4. Thread handling +The OP-TEE core uses a couple of threads to be able to support running jobs in +parallel (not fully enabled!). There are handlers for different purposes. In +[thread.c] you will find a function called `thread_init_primary` which assigns +`init_handlers` (functions) that should be called when OP-TEE core receives +standard or fast calls, FIQ and PSCI calls. There are default handlers for these +services, but the platform can decide if they want to implement their own +platform specific handlers instead. + +## Synchronization +OP-TEE has three primitives for synchronization of threads and CPUs: +spin-lock, mutex, and condvar. + +### Spin-lock +A spin-lock is represented as an `unsigned int`. This is the most primitive +lock. Interrupts should be disabled before attempting to take a spin-lock +and should remain disabled until the lock is released. A spin-lock is +initialized with `SPINLOCK_UNLOCK`. + +| Function | Purpose | +|----------|---------| +| `cpu_spin_lock()` | Locks a spin-lock | +| `cpu_spin_trylock()` | Locks a spin-lock if unlocked and returns `0` else the spin-lock is unchanged and the function returns `!0`| +| `cpu_spin_unlock()` | Unlocks a spin-lock | + +### Mutex +A mutex is represented by `struct mutex`. A mutex can be locked and +unlocked with interrupts enabled or disabled, but only from a normal +thread. A mutex cannot be used in an interrupt handler, abort handler or +before a thread has been selected for the CPU. A mutex is initialized with +either `MUTEX_INITIALIZER` or `mutex_init()`. + +| Function | Purpose | +|----------|---------| +|`mutex_lock()` | Locks a mutex. If the mutex is unlocked this is a fast operation, else the function issues an RPC to wait in normal world. | +| `mutex_unlock()` | Unlocks a mutex. If there is no waiters this is a fast operation, else the function issues an RPC to wake up a waiter in normal world. | +| `mutex_trylock()` | Locks a mutex if unlocked and returns `true` else the mutex is unchanged and the function returns `false`. | +| `mutex_destroy()` | Asserts that the mutex is unlocked and there is no waiters, after this the memory used by the mutex can be freed. | + +When a mutex is locked it is owned by the thread calling `mutex_lock()` or +`mutex_trylock()`, the mutex may only be unlocked by the thread owning the +mutex. A thread should not exit to TA user space when holding a mutex. + +### Condvar +A condvar is represented by `struct condvar`. A condvar is similar to a +pthread_condvar_t in the pthreads standard, only less advanced. Condition +variables are used to wait for some condition to be fulfilled and are +always used together a mutex. Once a condition variable has been used +together with a certain mutex, it must only be used with that mutex until +destroyed. A condvar is initialized with `CONDVAR_INITIALIZER` or +`condvar_init()`. + +| Function | Purpose | +|----------|---------| +| `condvar_wait()` | Atomically unlocks the supplied mutex and waits in normal world via an RPC for the condition variable to be signaled, when the function returns the mutex is locked again. | +| `condvar_signal()` | Wakes up one waiter of the condition variable (waiting in `condvar_wait()`) | +| `condvar_broadcast()` | Wake up all waiters of the condition variable. | + +The caller of `condvar_signal()` or `condvar_broadcast()` should hold the +mutex associated with the condition variable to guarantee that a waiter +does not miss the signal. + +# 5. MMU +## Translation tables +OP-TEE uses several L1 translation tables, one large spanning 4 GiB and two +or more small tables spanning 32 MiB. The large translation table handles +kernel mode mapping and matches all addresses not covered by the small +translation tables. The small translation tables are assigned per thread +and covers the mapping of the virtual memory space for one TA context. + +Memory space between small and large translation table is configured by +TTBRC. TTBR1 always points to the large translation table. TTBR0 points to +the a small translation table when user mapping is active and to the large +translation table when no user mapping is currently active. + +The translation tables has certain alignment constraints, the alignment (of +the physical address) has to be the same as the size of the translation +table. The translation tables are statically allocated to avoid fragmentation of +memory due to the alignment constraints. + +Each thread has one small L1 translation table of its own. Each TA context +has a compact representation of its L1 translation table. The compact +representation is used to initialize the thread specific L1 translation +table when the TA context is activated. + +![Select xlation table](images/xlat_table.png "Select xlation table") + +## Translation tables and switching to normal world +When switching to normal world either via an IRQ or RPC there is a chance +that secure world will resume execution on a different CPU. This means that +the new CPU need to be configured with the context of the currently active +TA. This is solved by always setting the TA context in the CPU when +resuming execution. Here is room for improvements since it is more likely +than not that it is the same CPU that resumes execution in secure world. + +# 6. Stacks +Different stacks are used during different stages. The stacks are: +- Secure monitor stack (128 bytes), bound to the CPU. Only available if + OP-TEE is compiled with a secure monitor always the case if the target is + ARMv7-A but never for ARMv8-A. +- Temp stack (small ~1KB), bound to the CPU. Used when transitioning from + one state to another. Interrupts are always disabled when using this + stack, aborts are fatal when using the temp stack. +- Abort stack (medium ~2KB), bound to the CPU. Used when trapping a data + or pre-fetch abort. Aborts from user space are never fatal the TA is only + killed. Aborts from kernel mode are used by the pager to do the demand + paging, if pager is disabled all kernel mode aborts are fatal. +- Thread stack (large ~8KB), not bound to the CPU instead used by the current + thread/task. Interrupts are usually enabled when using this stack. + +*Notes for ARMv7/AArch32:* + +| Stack | Comment | +|--------|---------| +| Temp | Assigned to `SP_SVC` during entry/exit, always assigned to `SP_IRQ` and `SP_FIQ` | +| Abort | Always assigned to `SP_ABT` | +| Thread | Assigned to `SP_SVC` while a thread is active | + +*Notes for AArch64:* +There are only two stack pointers, `SP_EL1` and `SP_EL0`, available for OP-TEE +in AArch64. When an exception is received stack pointer is always `SP_EL1` which +is used temporarily while assigning an appropriate stack pointer for `SP_EL0`. +**`SP_EL1` is always assigned the value of `thread_core_local[cpu_id]`.** This +structure has some spare space for temporary storage of registers and also keeps +the relevant stack pointers. In general when we talk about assigning a stack +pointer to the CPU below we mean `SP_EL0`. + +## Boot +During early boot the CPU is configured with the temp stack which is used until +OP-TEE exits to normal world the first time. + +*Notes for AArch64:* +`SPSEL` is always `0` on entry/exit to have `SP_EL0` acting as stack pointer. + +## Normal entry +Each time OP-TEE is entered from normal world the temp stack is used as the +initial stack. For fast calls this is the only stack used. For normal calls an +empty thread slot is selected and the CPU switches to that stack. + +## Normal exit +Normal exit occurs when a thread has finished its task and the thread is freed. +When the main thread function, tee_entry_std(), returns interrupts are disabled +and the CPU switches to the temp stack instead. The thread is freed and OP-TEE +exits to normal world. + +## RPC exit +RPC exit occurs when OP-TEE need some service from normal world. RPC can +currently only be performed with a thread is in running state. RPC is initiated +with a call to thread_rpc() which saves the state in a way that when the thread +is restored it will continue at the next instruction as if this function did a +normal return. CPU switches to use the temp stack before returning to normal +world. + +## IRQ exit +IRQ exit occurs when OP-TEE receives an IRQ, which is always handled in normal +world. IRQ exit is similar to RPC exit but it is `thread_irq_handler()` and +`elx_irq()` (respectively for ARMv7-A/Aarch32 and for Aarch64) that saves the +thread state instead. The thread is resumed in the same way though. + +*Notes for ARMv7/AArch32:* +SP_IRQ is initialized to temp stack instead of a separate stack. Prior to +exiting to normal world CPU state is changed to SVC and temp stack is selected. + +*Notes for AArch64:* +`SP_EL0` is assigned temp stack and is selected during IRQ processing. The +original `SP_EL0` is saved in the thread context to be restored when resuming. + +## Resume entry +OP-TEE is entered using the temp stack in the same way as for normal entry. The +thread to resume is looked up and the state is restored to resume execution. The +procedure to resume from an RPC exit or an IRQ exit is exactly the same. + +## Syscall +Syscalls are executed using the thread stack. + +*Notes for ARMv7/AArch32*: +Nothing special `SP_SVC` is already set with thread stack. + +*Notes for syscall AArch64*: + +Early in the exception processing the original `SP_EL0` is saved in `struct +thread_svc_regs` in case the TA is executed in AArch64. + +Current thread stack is assigned to `SP_EL0` which is then selected. + +When returning `SP_EL0` is assigned what is in `struct thread_svc_regs`. This +allows `tee_svc_sys_return_helper()` having the syscall exception handler return +directly to `thread_unwind_user_mode()`. + +# 7. Shared Memory +Shared Memory is a block of memory that is shared between the non-secure and the +secure world. It is used to transfer data between both worlds. + +## Shared Memory Allocation +The shared memory is allocated by the Linux driver from a pool `struct +shm_pool`, the pool contains: +* The physical address of the start of the pool +* The size of the pool +* Whether or not the memory is cached +* List of chunk of memory allocated. + +Note that: +- The shared memory pool is physically contiguous. +- The shared memory area is not secure as it is used by both non-secure and + secure world. + +### Shared Memory Configuration +It is the Linux kernel driver for OP-TEE that is responsible for initializing +the shared memory pool, given information provided by the OP-TEE core. The Linux +driver issues a SMC call `OPTEE_SMC_GET_SHM_CONFIG` to retrieve the information +* Physical address of the start of the pool +* Size of the pool +* Whether or not the memory is cached + +The shared memory pool configuration is platform specific. The memory mapping, +including the area `MEM_AREA_NSEC_SHM` (shared memory with non-secure world), is +retrieved by calling the platform-specific function `bootcfg_get_memory()`. +Please refer to this function and the area type `MEM_AREA_NSEC_SHM` to see the +configuration for the platform of interest. The Linux driver will then +initialize the shared memory pool accordingly. + +### Shared Memory Chunk Allocation +It is the Linux kernel driver for OP-TEE that is responsible for allocating +chunks of shared memory. OP-TEE linux kernel driver relies on linux kernel +generic allocation support (`CONFIG_GENERIC_ALLOCATION`) to allocation/release +of shared memory physical chunks. OP-TEE linux kernel driver relies on linux +kernel dma-buf support (`CONFIG_DMA_SHARED_BUFFER`) to track shared memory +buffers references. + +## Shared Memory Usage + +### From the Client Application +The client application can ask for shared memory allocation using the +GlobalPlatform Client API function `TEEC_AllocateSharedMemory()`. The client +application can also provide shared memory through the GlobalPlatform Client API +function `TEEC_RegisterSharedMemory()`. In such a case, the provided memory must +be physically contiguous so that the OP-TEE core, that does not handle +scatter-gather memory, is able to use the provided range of memory addresses. +Note that the reference count of a shared memory chunk is incremented when +shared memory is registered, and initialized to 1 on allocation. + +### From the Linux Driver +Occasionally the Linux kernel driver needs to allocate shared memory for the +communication with secure world, for example when using buffers of type +TEEC_TempMemoryReference. + +### From the OP-TEE core +In case the OP-TEE core needs information from the TEE supplicant (dynamic TA +loading, REE time request,...), shared memory must be allocated. Allocation +depends on the use case. The OP-TEE core asks for the following shared memory +allocation: +- `optee_msg_arg` structure, used to pass the arguments to the non-secure world, + where the allocation will be done by sending a `OPTEE_SMC_RPC_FUNC_ALLOC` + message. +- In some cases, a payload might be needed for storing the result from TEE + supplicant, for example when loading a Trusted Application. This type of + allocation will be done by sending the message + `OPTEE_MSG_RPC_CMD_SHM_ALLOC(OPTEE_MSG_RPC_SHM_TYPE_APPL,...)`, which then + will return: + - the physical address of the shared memory + - a handle to the memory, that later on will be used later on when freeing + this memory. + +### From the TEE Supplicant +The TEE supplicant is also working with shared memory, used to exchange data +between normal and secure worlds. The TEE supplicant receives a memory address +from the OP-TEE core, used to store the data. This is for example the case when a +Trusted Application is loaded. In this case, the TEE supplicant must register +the provided shared memory in the same way a client application would do, +involving the Linux driver. + +# 8. Pager +OP-TEE currently requires ~256 KiB RAM for OP-TEE kernel memory. This is not a +problem if OP-TEE uses TrustZone protected DDR, but for security reasons OP-TEE +may need to use TrustZone protected SRAM instead. The amount of available SRAM +varies between platforms, from just a few KiB up to over 512 KiB. Platforms with +just a few KiB of SRAM cannot be expected to be able to run a complete TEE +solution in SRAM. But those with 128 to 256 KiB of SRAM can be expected to have +a capable TEE solution in SRAM. The pager provides a solution to this by demand +paging parts of OP-TEE using virtual memory. + +## Secure memory +TrustZone protected SRAM is generally considered more secure than TrustZone +protected DRAM as there is usually more attack vectors on DRAM. The attack +vectors are hardware dependent and can be different for different platforms. + +## Backing store +TrustZone protected DRAM or in some cases non-secure DRAM is used as backing +store. The data in the backing store is integrity protected with one hash +(SHA-256) per page (4KiB). Readonly pages are not encrypted since the OP-TEE +binary itself is not encrypted. + +## Partitioning of memory +The code that handles demand paging must always be available as it would +otherwise lead to deadlock. The virtual memory is partitioned as: + +``` + Type Sections ++--------------+-----------------+ +| | text | +| | rodata | +| | data | +| unpaged | bss | +| | heap1 | +| | nozi | +| | heap2 | ++--------------+-----------------+ +| init / paged | text_init | +| | rodata_init | ++------------- +-----------------+ +| paged | text_pageable | +| | rodata_pageable | ++--------------+-----------------+ +| demand alloc | | +| | | ++--------------+-----------------+ +``` +Where "`nozi`" stands for "not zero initialized", this section contains entry +stacks (thread stack when TEE pager is not enabled) and translation tables (TEE +pager cached translation table when the pager is enabled and LPAE MMU is used). + +The "`init`" area is available when OP-TEE is initializing and contains +everything that is needed to initialize the pager. After the pager has been +initialized this area will be used for demand paged instead. + +The "`demand alloc`" area is a special area where the pages are allocated and +removed from the pager on demand. Those pages are returned when OP-TEE does not +need them any longer. The thread stacks currently belongs this area. This means +that when a stack is not used the physical pages can be used by the pager for +better performance. + +The technique to gather code in the different area is based on compiling all +functions and data into separate sections. The unpaged text and rodata is then +gathered by linking all object files with `--gc-sections` to eliminate sections +that are outside the dependency graph of the entry functions for unpaged +functions. A script analyzes this ELF file and generates the bits of the final +link script. The process is repeated for init text and rodata. What is not +"unpaged" or "init" becomes "paged". + +## Partitioning of the binary +The binary is partitioned into four parts as: +``` ++----------+ +| Header | ++----------+ +| Init | ++----------+ +| Hashes | ++----------+ +| Pageable | ++----------+ +``` +Header is defined as: +```c +#define OPTEE_MAGIC 0x4554504f +#define OPTEE_VERSION 1 +#define OPTEE_ARCH_ARM32 0 +#define OPTEE_ARCH_ARM64 1 + +struct optee_header { + uint32_t magic; + uint8_t version; + uint8_t arch; + uint16_t flags; + uint32_t init_size; + uint32_t init_load_addr_hi; + uint32_t init_load_addr_lo; + uint32_t init_mem_usage; + uint32_t paged_size; +}; +``` + +The header is only used by the loader of OP-TEE, not OP-TEE itself. To +initialize OP-TEE the loader loads the complete binary into memory and copies +what follows the header and the following `init_size` bytes to +`(init_load_addr_hi << 32 | init_load_addr_lo)`. `init_mem_usage` is used by the +loader to be able to check that there is enough physical memory available for +OP-TEE to be able to initialize at all. The loader supplies in `r0/x0` the +address of the first byte following what was not copied and jumps to the load +address to start OP-TEE. + +## Initializing the pager +The pager is initialized as early as possible during boot in order to minimize +the "init" area. The global variable `tee_mm_vcore` describes the virtual memory +range that is covered by the level 2 translation table supplied to +`tee_pager_init()`. + +### Assign pageable areas +A virtual memory range to be handled by the pager is registered with a call to +`tee_pager_add_core_area()`. + +```c +bool tee_pager_add_area(tee_mm_entry_t *mm, uint32_t flags, const void *store, + const void *hashes); +``` + +which takes a pointer to `tee_mm_entry_t` to tell the range, flags to tell how +memory should be mapped (readonly, execute etc), and pointers to backing store +and hashes of the pages. + +### Assign physical pages +Physical SRAM pages are supplied by calling `tee_pager_add_pages()` + +```c +void tee_pager_add_pages(tee_vaddr_t vaddr, size_t npages, bool unmap); +``` + +`tee_pager_add_pages()` takes the physical address stored in the entry mapping +the virtual address "vaddr" and "npages" entries after that and uses it to map +new pages when needed. The unmap parameter tells whether the pages should be +unmapped immediately since they does not contain initialized data or be kept +mapped until they need to be recycled. The pages in the "init" area are supplied +with `unmap == false` since those page have valid content and are in use. + +## Invocation +The pager is invoked as part of the abort handler. A pool of physical pages are +used to map different virtual addresses. When a new virtual address needs to be +mapped a free physical page is mapped at the new address, if a free physical +page cannot be found the oldest physical page is selected instead. When the page +is mapped new data is copied from backing store and the hash of the page is +verified. If it is OK the pager returns from the exception to resume the +execution. + +## Paging of user TA + +Paging of user TAs can optionally be enabled with CFG_PAGED_USER_TA=y. +Paging of user TAs is analogous to paging of OP-TEE kernel parts but with a +few differences: +- Read/write pages are paged in addition to read-only pages +- Page tables are managed dynamically + +tee_pager_add_uta_area() is used to setup initial read/write mapping needed +when populating the TA. When the TA is fully populated and relocated +tee_pager_set_uta_area_attr() changes the mapping of the area to strict +permissions used when the TA is running. + +# 9. Memory objects + +A memory object, MOBJ, describes a piece of memory. The interface provided +is mostly abstract when it comes to using the MOBJ to populate translation +tables etc. + +There is different kinds of MOBJs describing: +- physically contiguous memory + - created with mobj_phys_alloc() +- virtual memory + - one instance with the name mobj_virt available + - spans the entire virtual address space +- physically contiguous memory allocated from a tee_mm_pool_t * + - created with mobj_mm_alloc() +- paged memory + - created with mobj_paged_alloc() + - only contains the supplied size and makes mobj_is_paged() return true if + supplied as argument +- secure copy paged shared memory + - created with mobj_seccpy_shm_alloc() + - makes mobj_is_paged() and mobj_is_secure() return true if supplied as + argument + +# 10. Cryptographic abstraction layer +Cryptographic operations are implemented inside the TEE core by the +[LibTomCrypt] library. An abstraction layer allows for replacing the default +implementation, as explained in [crypto.md]. + +# 11. libutee + +The GlobalPlatform Core Internal API describes services that are provided to +Trusted Applications. libutee is a library that implements this API. + +libutee is a static library the Trusted Applications shall statically link +against. Trusted Applications do execute in non-privileged secure userspace and +libutee also aims at being executed in the non-privileged secure userspace. + +Some services for this API are fully statically implemented inside the +libutee library while some services for the API are implemented inside the +OP-TEE core (privileged level) and libutee calls such services through +system calls. + +# 12. Trusted Applications + +## Pseudo TAs and Dynamically Loaded TAs + +There are two ways to implement Trusted Applications (TAs), pseudo TAs and +dynamically loaded TAs. As dynamically loaded TAs are full featured Trusted +Applications as specified by the GlobalPlatform TEE specifications, these are +simply referred to as 'Trusted Applications'. For most cases, dynamically +loaded TAs are preferred. + +### Pseudo Trusted Applications + +These are added directly to the OP-TEE core tree in, eg, `core/arch/arm/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 purpose 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 "libutee") and that calls OP-TEE +core service through system calls. As OP-TEE core does link with the +libutee, Pseudo TAs can only use the OP-TEE core internal APIs and +routines. + +As pseudo TAs have the same privileged execution level as the OP-TEE core code +itself, such situation may not be desirable for complex TAs. + +In most cases a real, dynamically loaded 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/arch/arm/pta/stats.c` as a template and just add your pseudo TA based on +that to the `sub.mk` in the same directory. + +### Trusted Applications + +Trusted Applications (TAs) are applications dynamically loaded by OP-TEE +core in the Secure World when something in the REE wants to talk to that +particular application UUID. It is similar to the way the Linux +kernel can dynamically load kernel modules, although unlike with Linux, in +OP-TEE TAs actually run at a lower CPU privileged level than OP-TEE core code. + +Because the TAs are signed by the same key that built the OP-TEE core, 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. Again this is simular to Linux kernel module signature checking. + +Trusted Application benefit from the GlobalPlatform Core Internal API as +specified by the GlobalPlatform TEE specifications. + +Trusted Application 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. + +## Special treatment of Trusted Applications + +### Syscalls + +Dynamically loaded TAs are not directly bound to function exports in the OP-TEE +core blob, both because the TA code is kept at arm's length by executing at a +different privileged level, and because TAs direct binding to addresses in the +core would require upgrades of all TAs synchronusly with upgrades of the +OP-TEE core blob. Instead, the resolution of OP-TEE core exports in the TA +is done at runtime. + +OP-TEE does this by using syscalls, the same kind of way as the Linux kernel +provides a stable API for its userland programs. TAs are written to use +syscall wrappers to access functions exported from OP-TEE core, so this all +happens automatically when a TA wants to use an API exported from OP-TEE +core. + +Pseudo TAs and anything else directly built into OP-TEE core do not +require going through a syscall interface, since they can just link directly +as they are directly part of the core. + +Most of the services defined by the GlobalPlatform Core Internal API are +implemented through syscall from the TA to the OP-TEE core privileged level: +cryptographic services, communications with other TAs, ... Some services were +added through OP-TEE development such as ASCII message tracing. + +Syscalls are provided already for all public exports from OP-TEE core that a +Dynamic TA is expected to use, so you only need to take care about this if +you will add new exported from OP-TEE core that TAs will want to use. + +### Malloc mapping + +The OP-TEE core code has its own private memory allocation heap that is mapped +into its MMU view only and cannot be seen by Trusted Applications. The +core code uses `malloc()` and `free()` style APIs. + +Trusted Applications also have their own private memory allocation heaps +that are visible to the owning TA, and to OP-TEE core. TAs manage their +heaps using `TEE_Malloc()` and `TEE_Free()` style apis. + +Heap |Visible to |Inaccessible to +-----|-------------|--------------- +core |core |any TA +TA |core, same TA|any other TA + +This enforces "Chinese Walls" between the TA views of Secure World. + +Since OP-TEE core cannot perform allocations in the TA's private heap, +and the TA is not going to be able to access allocations from the OP-TEE +core heap, it means only allocations from the TA heap are visible to both the +TA and OP-TEE core. When performing syscalls between a TA and OP-TEE core +then, the TA side must provide all the memory allocations for buffers, etc +used by both sides. + +### Malloc pool + +The OP-TEE core malloc heap is defined by `CFG_CORE_HEAP_SIZE` in `mk/config.mk`. + +However for TAs, the individual TA TEE_Malloc() heap size is defined by +`TA_DATA_SIZE` in `user_ta_header_defines.h`. Likewise the TA stack size is +set in the same file, in `TA_STACK_SIZE`. + +## File format of a Dynamic Trusted Application + +The format a TA is: +``` +<Signed header> +<ELF> +``` + +Where `<ELF>` is the content of a standard ELF file and `<Signed header>` +consists of: + +| Type | Name | Comment | +|------|------|---------| +| `uint32_t` | magic | Holds the magic number `0x4f545348` | +| `uint32_t` | img_type | image type, values defined by enum shdr_img_type | +| `uint32_t` | img_size | image size in bytes | +| `uint32_t` | algo | algorithm, defined by public key algorithms `TEE_ALG_*` from TEE Internal API specification | +| `uint16_t` | hash_size | size of the signed hash | +| `uint16_t` | sig_size | size of the signature | +| `uint8_t[hash_size]` | hash | Hash of the fields above and the `<ELF>` above | +| `uint8_t[sig_size]` | signature | Signature of hash | + +[crypto.md]: crypto.md +[LibTomCrypt]: https://github.com/libtom/libtomcrypt +[OP-TEE Client]: https://github.com/OP-TEE/optee_client +[OP-TEE Linux Kernel driver]: https://github.com/linaro-swg/linux +[OP-TEE Trusted OS]: https://github.com/OP-TEE/optee_os +[optee_smc.h]: ../core/arch/arm/include/sm/optee_smc.h +[optee_msg.h]: ../core/include/optee_msg.h +[Platforms Supported]: https://github.com/OP-TEE/optee_os#3-platforms-supported +[struct optee_msg_arg]: ../core/include/optee_msg.h +[thread.c]: ../core/arch/arm/kernel/thread.c diff --git a/documentation/optee_with_auth_framework.md b/documentation/optee_with_auth_framework.md new file mode 100644 index 0000000..c654e52 --- /dev/null +++ b/documentation/optee_with_auth_framework.md @@ -0,0 +1,20 @@ +## OP-TEE with authentication framework in ARM-TF +This document gives a brief description on how to enable the verification of OP-TEE using the authentication framework in ARM-TF + +--- +## What we should do +* According to [user-guide.md](https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/user-guide.md), there is no additional specific build options for the verification of OP-TEE. If we have enabled the authentication framework and specified the BL32 build option when building ARM-TF, the BL32 related certificates will be created automatically by the cert_create tool, and then these certificates will be verified during booting up. + + +* To enable the authentication framework, the following steps should be followed according to [user-guide.md](https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/user-guide.md). All the details for these build options are also in [user-guide.md](https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/user-guide.md), more details about the authentication framework, please see [auth-framework.md](https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/auth-framework.md) and [trusted-board-boot.md](https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/trusted-board-boot.md). + + * Check out a recent version of the [mbed TLS Repository](https://github.com/ARMmbed/mbedtls.git), and then switch to tag mbedtls-2.2.0 + * Besides the normal build options, add the following build options for ARM-TF + * **MBEDTLS_DIR**=*path of the directory containing mbed TLS sources* + * **TRUSTED_BOARD_BOOT**=*1* + * **GENERATE_COT**=*1* + * **ARM_ROTPK_LOCATION**=*devel_rsa* + * **ROT_KEY**=*$(ARM_TF_PATH)/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem* + + +* Above steps have been tested on FVP platform, all verification steps are ok and xtest can run successfully without regression. diff --git a/documentation/se_api_design.md b/documentation/se_api_design.md new file mode 100644 index 0000000..83023a8 --- /dev/null +++ b/documentation/se_api_design.md @@ -0,0 +1,145 @@ +# GlobalPlatform Secure Element API Design Document + +### BACKGROUND + +A `Secure Element (SE)` is a tamper-resistant platform (typically a one chip +secure microcontroller) capable of securely hosting applications and their +confidential and cryptographic data (e.g. key management) in accordance with the +rules and security requirements set forth by a set of well-identified trusted +authorities. + +>Simplified speaking, SE is a secure platform that can run application (called +>Applet) on it. In order to communicate with Applet, we need a transport +>interface. + +SE can be implemented via one of the following technologies + +- Embedded SE (accessed via platform dependent interface, unremovable) +- Universal Integrated Circuit Card (UICC, accessed via SIM interface) +- Advanced secure MicroSD (accessed via sdio/mmc interface) + +Which means the physical interface between application processor (AP) and SE can +be quite different. GlobalPlatform tries to remove this gap and defined a +standard transport API called `Secure Element API` to cover those different +physical transport layer protocols. + +SE can be accessed directly in TEE, or indirectly accessed via REE. In later +case, a **secure channel** is needed to ensure the data stream is not hijacked +in REE. (For secure channel, we may leverage [TZC 400] to create a secure memory +that is not accessible in REE) + +![](https://docs.google.com/drawings/d/1fPcNJRVKpJnyzci2KgfVNsOD_y9DVF0Djpu0BzsqOrI/pub?w=796&h=477) + +To understand SE API, you need to understand the following terms + +- `Trusted Application (TA)`: An application execute in Trust Execution + Environment (TEE), which is the initiator of SE API. + +- `Applet`: Applications that run on smartcard OS. Secure Element API defines + the method to communicate between host application (in our case, TA) and + Applet. + +- `Service`: A service can be used to retrieve all SE readers available in + the system, it also provides a service to create a session from TA to a + specific Reader. + +- `Session`: It maintains the connection between TA and a specific Reader. + Different TAs can have a session opened on the same reader. It is SE manager's + responsibility to demux the request from different TAs. Upon a session is + opened by a TA, the card is power-up and ready to accept commands. + +- `Reader`: It is an abstraction to describe the transport interface between + the system and SEs. You can imagine that a SD card slot is a Reader connected + with assd. A ril daemon can be another read to talk with UICC cards. Even + embedded SE should have a (virtual) Reader attached to it. + +- `Logical Channel`: It is used by host application (in our case, a TA) to + communicate with applets on the smartcard. [GlobalPlatform Card Specification] + defines maximum 20 logical channels, numbered from 0~19. Channel number 0 is + so-called `Basic logical channel`, or in short, `Basic channel`. A channel can + be opened or closed by a host application. It is the smartcard OS's + responsibility to manage the state of each logical channel. Basic channel is + always open and cannot be closed. A channel must select an applet, which means + the command passed through the channel will be processed by the selected + applet. GlobalPlatform requires a default applet must be selected on basic + channel after system reset. Host application can select different applet by + issuing a `SELECT command` on basic channel. Other logical channels (numbered + 1~19) can be opened with or without a given `Application Identifier` (AID). If + AID is not given, the applet selected on basic channel will be selected on the + just opened logical channel. + +- `MultiSelectable or Non-MultiSelectable`: An applet can be MultiSelectable + or Non-MultiSelectable. For a Non-MultiSelectable applet, it can only be + selected by one channel, further `SELECT command` on another channel that is + targeting to the applet will fail. MultiSelectable applet can be selected by + multiple channels, the applet can decide maximum number of channels it is + willing to accept. + +### DESIGN + +The following figure shows initial architecture of SE API. +![](https://docs.google.com/drawings/d/1wVV0opJmmM9PTptrk8z09_052i-evnjJ8yptu18ZBoU/pub?w=676&h=606) + +- `Manager (core/include/tee/se/manager.h)`: This component manages all + Readers on the system. It should provide reader interface for the Reader + developers to register their own Reader instance. (In the case of [JavaCard + Simulator], we should have [PC/SC Passthru Reader] to talk with simulator) It + also provides an interface for client to get `reader handle` on the system. + +- `Reader (core/include/tee/se/reader.h)`: It provides the operations that + can be applied on a `reader handle`. Just like get reader properties and + create session to a reader. It’s also responsible for routing an + operation(open, transmit...etc) to a specific Reader implementation. + +- `Protocol (core/include/tee/se/{protocol.h,aid.h,apdu.h})`: This module + implements the `ISO7816 transport layer` protocol that is used to talk with + smartcard. It relies on operations provided by Reader to transmit `Application + Protocol Data Unit` (APDU, refer to [ISO7816-4]) to a specific SE. + +- `Session (core/include/tee/se/session.h)`: It provides the operations that + can be applied on a session. Just like open basic or logical channel, and + transmit APDU on the session. It relies on protocol layer to create logical, + basic channel and transmit APDU. + +- `Channel (core/include/tee/se/channel.h)`: It provides the operations that + can be applied on a channel. Like transmit an APDU on the channel, select next + applet. It relies on protocol module to select AID, and session module to + transport APDU. + +- `Reader interface (core/include/tee/se/reader/interface.h)`: The abstract + layer used to implement a specific Reader instance, a set of operations need + to be implemented to support a new Reader. + + - `open()`: Triggered when the first session is connected, the Reader should + be powered on and reset. Doing initialization. Detect SE is present or not. + - `close()`: Triggered when the last session to the Reader has been closed. + The Reader can be powered down in this method. + - `get_properties()`: Get properties of the Reader. Something like the + Reader is exclusive to TEE or not. SE is present...etc. + - `get_atr()`: Get ATR message from the Reader. ATR is defined in ISO7816-3, + and it is the message report by SE to describe the ability of SE. + - `transmit()`: Transmit an APDU through the Reader which SE attached to. + +### Reference Documents +- [ISO7816-4] +- [GP Secure Element API] +- [PC/SC Lite] +- [PC/SC Passthru Reader] + +### How to verify +To test SE API, you need [Modified QEMU] and enhanced [JavaCard simulator]. +Please use this [setup script] to setup test environment. + +[Modified QEMU]:https://github.com/m943040028/qemu/tree/smart_card_emul +[JavaCard simulator]:https://github.com/m943040028/jcardsim/tree/se_api +[PC/SC Passthru Reader]:https://github.com/m943040028/pcsc_passthru_driver +[PC/SC Lite]:https://pcsclite.alioth.debian.org/ +[GlobalPlatform Card Specification]:http://www.globalplatform.org/specificationscard.asp +[GP Secure Element API]: http://www.globalplatform.org/specificationsdevice.asp +[TZC 400]: +http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0504c/index.html +[ISO7816-4]: +http://www.embedx.com/pdfs/ISO_STD_7816/info_isoiec7816-4%7Bed2.0%7Den.pdf +[setup script]: +https://raw.githubusercontent.com/m943040028/optee_os/48fe3bf418bda0047784327cbf72e6613ff547b2/scripts/setup_seapi_optee.sh + diff --git a/documentation/secure_storage.md b/documentation/secure_storage.md new file mode 100644 index 0000000..9202325 --- /dev/null +++ b/documentation/secure_storage.md @@ -0,0 +1,269 @@ +# Secure Storage In OP-TEE + +## Background + +Secure Storage (SST) in OP-TEE is implemented according to what has been defined +in GloblaPlatform’s TEE Internal API specification (here called Trusted +Storage). This specification mandates that it should be possible to store +general-purpose data and key material that guarantees confidentiality and +integrity of the data stored and the atomicity of the operations that modifies +the storage (atomicity here means that either the entire operation completes +successfully or no write is done). + +There are currently three secure storage implementations in OP-TEE: + +- The first one relies on the normal world (REE) file system. It is described in +this document and is the default implementation. It is enabled at compile time +by CFG_REE_FS=y. +- The second one makes use of the Replay Protected Memory Block (RPMB) partition +of an eMMC device, and is enabled by setting `CFG_RPMB_FS=y`. It is described +in [secure_storage_rpmb.md](secure_storage_rpmb.md). +- The third one stores objects in a SQLite database in normal world. It is +enabled by `CFG_SQL_FS=y`. See [secure_storage_sql.md](secure_storage_sql.db). + +It is possible to use the normal world filesystems and the RPMB implementations +simultaneously. For this, three OP-TEE specific storage identifiers have been +defined: TEE_STORAGE_PRIVATE_REE, TEE_STORAGE_PRIVATE_RPMB and +TEE_STORAGE_PRIVATE_SQL. Depending on the +compile-time configuration, one or several values may be used. +The value TEE_STORAGE_PRIVATE selects the REE FS when available, otherwise the +RPMB FS if available, otherwise the SQL FS (in this order). + +The rest of this document describes the REE FS only. + +## Overview + +![Secure Storage System Architecture](images/secure_storage/secure_storage_system_architecture.png +"Secure Storage System Architecture") + +### Source Files In OP-TEE OS + +- **[core/tee/tee_svc_storage.c](../core/tee/tee_svc_storage.c):** TEE trusted +storage service calls +- **[core/tee/tee_ree_fs.c](../core/tee/tee_ree_fs):** TEE file system & REE +file operation interface +- **[core/tee/tee_fs_key_manager.c](../core/tee/tee_fs_key_manager.c):** Key +manager +- **[lib/libutee/](../lib/libutee/):** GlobalPlatform Internal API library + +### Basic File Operation Flow + +When a TA is calling the write function provided by GP Trusted Storage API to +write data to a persistent object, a corresponding syscall implemented in TEE +Trusted Storage Service will be called, which in turn will invoke a series of +TEE file operations to store the data. TEE file system will then encrypt the +data and send REE file operation commands and the encrypted +data to TEE supplicant by a series of RPC messages. TEE supplicant will receive +the messages and store the encrypted data accordingly to the Linux file +system. Reading files are handled in a similar manner. + +### GlobalPlatform Trusted Storage Requirement + +Below is an excerpt from the specification listing the most vital requirements: + +1. The Trusted Storage may be backed by non-secure resources as long as suitable + cryptographic protection is applied, which MUST be as strong as the means + used to protect the TEE code and data itself +2. The Trusted Storage MUST be bound to a particular device, which means that it + MUST be accessible or modifiable only by authorized TAs running in the same + TEE and on the same device as when the data was created. +3. Ability to hide sensitive key material from the TA itself. +4. Each TA has access to its own storage space that is shared among all the + instances of that TA but separated from the other TAs. +5. The Trusted Storage must provide a minimum level of protection against + rollback attacks. It is accepted that the actually physical storage may be in + an unsecure areas and so is vulnerable to actions from outside of the TEE. + Typically, an implementation may rely on the REE for that purpose (protection + level 100) or on hardware assets controlled by the TEE (protection level + 1000). + +### TEE File Structure In Linux File System + +![TEE File Structure](images/secure_storage/tee_file_structure.png +"TEE file structure in Linux file system") + +OP-TEE by default use "/data/tee/" as the secure storage space in Linux +file system. For each TA, OP-TEE use the TA's UUID to create a standalone folder +for it under the secure storage space folder. For a persistent object belonging +to a specific TA, OP-TEE creates a TEE file is object-id under the TA folder. + +All fields in the REE file are duplicated with two versions 0 and 1. The +active meta-data block is selected by the lowest bit in the +meta-counter. The active file block is selected by corresponding bit +number instruct tee_fs_file_info.backup_version_table. + +The atomicity of each operation is ensured by updating meta-counter when +everything in the secondary blocks (both meta-data and file-data blocks) +are successfully written. The main purpose of the code is to perform block +encryption and authentication of the file data, and properly handle seeking +through the file. One file (in the sense of struct tee_file_operations) +maps to one file in the REE filesystem, and has the following structure: +``` +[ 4 bytes meta-counter] +[ meta-data version 0][ meta-data version 1 ] +[ Block 0 version 0 ][ Block 0 version 1 ] +[ Block 1 version 0 ][ Block 1 version 1 ] +... +[ Block n version 0 ][ Block n version 1 ] +``` + +One meta-data block is built up as: +``` +[ struct meta_header | struct tee_fs_get_header_size ] +``` + +One data block is built up as: +``` +[ struct block_header | BLOCK_FILE_SIZE bytes ] +``` + +The reason why we store the TEE file content in many small blocks is to +accelerate the file update speed when handling a large file. The block size +(FILE_BLOCK_SIZE) and the maximum number of blocks of a TEE file +(NUM_BLOCKS_PER_FILE) are defined in +[core/tee/tee_ree_fs.c](../core/tee/tee_ree_fs.c). + +For now, the default block size is 4KB and the maximum number of blocks of a +TEE file is 1024. + +## Key Manager + +Key manager is an component in TEE file system, and is responsible for handling +data encryption and decryption and also management of the sensitive key +materials. There are three types of keys used by the key manager: the Secure +Storage Key (SSK), the TA Storage KEY (TSK) and the File Encryption Key (FEK). + +### Secure Storage Key (SSK) + +SSK is a per-device key and is generated and stored in secure memory when OP-TEE +is booting. SSK is used to derive the TA Storage Key (TSK). + +SSK is derived by: +> SSK = HMAC<sub>SHA256</sub> (HUK, Chip ID || "static string") + +The functions to get Hardware Unique Key (HUK) and chip ID depend on platform +implementation. + +Currently, in OP-TEE OS we only have a per-device key, SSK, which is used for +secure storage subsystem, but, for the future we might need to create different +per-device keys for different subsystems using the same algorithm as we +generate the SSK; An easy way to generate different per-device keys for +different subsystems is using different static strings to generate the keys. + +### Trusted Application Storage Key (TSK) + +The TSK is a per-Trusted Application key, which is generated from the SSK and +the TA's identifier (UUID). It is used to protect the FEK, in other words, +to encrypt/decrypt the FEK. + +TSK is derived by: +> TSK = HMAC<sub>SHA256</sub> (SSK, TA_UUID) + +#### TA storage space isolation + +OP-TEE provides different folders for different TAs in Linux file system for +storing their own TEE files, but OP-TEE cannot prevent an attacker from +directly copying a TEE file from one TA's folder to another TA's folder in +Linux file system. + +The TSK offers an effective protection against this kind of attack. If an +attacker copies an TEE file from one TA's folder to another TA's folder, +this TA would not be able to obtain the plaintext of the TEE file. + +### File Encryption Key (FEK) + +When a new TEE file is created, key manager will generate a new FEK by +PRNG (pesudo random number generator) for the TEE file and store the encrypted +FEK in meta file. FEK is used for encrypting/decrypting the TEE file information +stored in meta file or the data stored in block file. + +### Meta Data Encryption Flow + +![Meta Data Encryption](images/secure_storage/meta_data_encryption.png +"Meta data encryption") + +A new meta IV will be generated by PRNG when a meta data needs to be updated. +The default size of meta IV is defined in +[core/include/tee/tee_fs_key_manager.h](../core/include/tee/tee_fs_key_manager.h) + +The data structure of meta data is defined in +[core/tee/tee_fs_private.h](../core/tee/tee_fs_private.h) as follows: + +``` +struct tee_fs_file_info { + size_t length; + uint32_t backup_version_table[NUM_BLOCKS_PER_FILE / 32]; +}; +``` + +### Block Data Encryption Flow + +![Block Data Encryption](images/secure_storage/block_data_encryption.png +"Block data encryption") + +A new block IV will be generated by PRNG when a block data needs to be updated. +The default size of block IV is defined in +[core/include/tee/tee_fs_key_manager.h](../core/include/tee/tee_fs_key_manager.h) + +## Atomic Operation + +According to GlobalPlatform Trusted Storage requirement of the atomicity, the +following operations should support atomic update: +> Write, Truncate, Rename, Create and Delete + +The strategy used in OP-TEE secure storage to guarantee the atomicity is +out-of-place update. + +## Important caveats + +Currently **no OP-TEE platform is able to support retrieval of the Hardware +Unique Key or Chip ID required for secure operation**. + +For all platforms, a constant key is used, resulting in no protection against +decryption, or Secure Storage duplication to other devices. + +This is because information about how to retrieve key data from the SoC is +considered sensitive by the vendors and it is not freely available. + +In OP-TEE, there are apis for reading the keys generically from "One-Time +Programmable" memory, or OTP. But there are no existing platform implementations. + +To allow Secure Storage to operate securely on your platform, you must: + + - enable CFG_OTP_SUPPORT on your platform + + - In your platform code, define implementations for: + +``` + void tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey); + int tee_otp_get_die_id(uint8_t *buffer, size_t len); +``` + +These implementations should fetch the key data from your SoC-specific e-fuses, +or crypto unit according to the method defined by your SoC vendor. + +## Future Work + +- **TEE file renaming attack detection** + +OP-TEE creates a specific folder under the TA's folder for each TEE file in +Linux file system and use the filename of the TEE file as the folder's name. +If an attacker directly rename the name of a TEE file folder, the renamed +TEE file is still a valid TEE file in OP-TEE. + +A solution to detect the attack is using TEE filename as AAD when calculating +the tag of meta file. + +- **Rollback attack detection** + +An attacker can backup each version of a TEE file directly from Linux file +system and can replace the TEE file by an old version one sooner or later. + +The basic idea of detecting rollback attack is to add write counter both in +meta file and another storage which has anti-rollback capability such as eMMC +RPMB partition. + +## Reference + +* [Secure Storage Presentation](http://www.slideshare.net/linaroorg/sfo15503-secure-storage-in-optee) +* [TEE Internal Core API Specification v1.1](http://www.globalplatform.org/specificationsdevice.asp) diff --git a/documentation/secure_storage_rpmb.md b/documentation/secure_storage_rpmb.md new file mode 100644 index 0000000..7ac2304 --- /dev/null +++ b/documentation/secure_storage_rpmb.md @@ -0,0 +1,141 @@ +# RPMB Secure Storage + +## Introduction + +This document describes the RPMB secure storage implementation in OP-TEE, +which is enabled by setting CFG_RPMB_FS=y. Trusted Applications may use +this implementation by passing a storage ID equal to +TEE_STORAGE_PRIVATE_RPMB, or TEE_STORAGE_PRIVATE if CFG_REE_FS is disabled. +For details about RPMB, please refer to the JEDEC eMMC specification +[[1]](#JEDECeMMC). + +The architecture is depicted below. + +``` + NORMAL WORLD : SECURE WORLD + : + U tee-supplicant : Trusted application + S (rpmb.c) : (secure storage API) + E ^ ^ : ^ + R | | :~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~ ioctl ~~~~~~~|~~~~~~~~~~~~: v + K | | : OP-TEE + E v v : (tee_svc_storage.c) + R MMC/SD subsys. OP-TEE driver : (tee_rpmb_fs.c, tee_fs_key_manager.c) + N ^ ^ : ^ + E | | : | + L v | : | + Controller driver | : | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~ + v v + Secure monitor / EL3 firmware +``` + +For information about the `ioctl()` interface to the MMC/SD subsystem in the +Linux kernel, see the Linux core MMC header file [[2]](#mmc-core-h) and the +mmc-utils repository [[3]](#mmc-utils). + +## The Secure Storage API + +This part is common with the REE-based filesystem. The interface between the +system calls in [core/tee/tee_svc_storage.c](../core/tee/tee_svc_storage.c) and +the RPMB filesystem is the **tee_file_operations** structure `tee_file_ops`. + +## The RPMB filesystem + +The FS implementation is entirely in +[core/tee/tee_rpmb_fs.c](../core/tee/tee_rpmb_fs.c). + +The RPMB partition is divided in three parts: + +- The first 128 bytes are reserved for partition data (struct +**rpmb_fs_partition**). +- At offset 512 is the File Allocation Table (FAT). It is an array of +struct **rpmb_fat_entry** elements, one per file. The FAT grows dynamically as +files are added to the filesystem. Among other things, each entry has the start +address for the file data, its size, and the filename. +- Starting from the end of the RPMB partition and extending downwards is the +file data area. + +Space in the partition is allocated by the general-purpose allocator functions: +`tee_mm_alloc()` and `tee_mm_alloc2()`. + +All file operations are atomic. This is achieved thanks to the following +properties: +- Writing one single block of data to the RPMB partition is guaranteed to be +atomic by the eMMC specification. +- The FAT block for the modified file is always updated last, after data have +been written successfully. +- Updates to file content is done in-place only if the data do not span more +than the "reliable write block count" blocks. Otherwise, or if the file needs +to be extended, a new file is created. + +## Device access + +There is no eMMC controller driver in OP-TEE. The device operations all have to +go through the normal world. They are handled by the `tee-supplicant` process +which further relies on the kernel's `ioctl()` interface to access the device. +`tee-supplicant` also has an emulation mode which implements a virtual RPMB +device for test purposes. + +RPMB operations are the following: +- Reading device information (partition size, reliable write block count) +- Programming the security key. This key is used for authentication purposes. +Note that it is different from the Secure Storage Key (SSK) defined below, which +is used for encryption. Like the SSK however, the security key is also derived +from a hardware unique key or identifier. Currently, the function +`tee_otp_get_hw_unique_key()` is used to generate the RPMB security key. +- Reading the write counter value. The write counter is used in the HMAC +computation during read and write requests. The value is read at initialization +time, and stored in the **tee_rpmb_ctx** structure, `rpmb_ctx->wr_cnt`. +- Reading or writing blocks of data + +RPMB operations are initiated on request from the FS layer. Memory buffers for +requests and responses are allocated in shared memory using +`thread_optee_rpc_alloc_payload()`. +Buffers are passed to the normal world in a `TEE_RPC_RPMB_CMD` message, thanks +to the `thread_rpc_cmd()` function. Most RPMB requests and responses use the +data frame format defined by the JEDEC eMMC specification. + +HMAC authentication is implemented here also. + +## Encryption + +The FS encryption routines are in [core/tee/tee_fs_key_manager.c](../core/tee/tee_fs_key_manager.c). + +Block encryption protects file data. The algorithm is 128-bit AES in Cipher Block Chaining +(CBC) mode with Encrypted Salt-Sector Initialization Vector (ESSIV) +[[4]](#CBC-ESSIV). + +- During OP-TEE initialization, a 128-bit AES Secure Storage Key (SSK) is +derived from a Hardware Unique Key (HUK). It is kept in secure memory and never +written to disk. A Trusted Application Storage Key is derived from the SSK and +the TA UUID. +- For each file, a 128-bit encrypted File Encryption Key (FEK) is randomly +generated when the file is created, encrypted with the TSK and stored in the FAT +entry for the file. +- Each 256-byte block of data is then encrypted in CBC mode. The initialization +vector is obtained by the ESSIV algorithm, that is, by encrypting the block +number with a hash of the FEK. This allows direct access to any block in the +file, as follows: +``` + FEK = AES-Decrypt(TSK, encrypted FEK); + k = SHA256(FEK); + IV = AES-Encrypt(128 bits of k, block index padded to 16 bytes) + Encrypted block = AES-CBC-Encrypt(FEK, IV, block data); + Decrypted block = AES-CBC-Decrypt(FEK, IV, encrypted block data); +``` + + +SSK, TSK and FEK handling is common with the REE-based secure storage, while the AES +CBC block encryption is used only for RPMB (the REE implementation uses GCM). + +The FAT is not encrypted. + +## References + +- <a name="JEDECeMMC"></a>[1] _Embedded Multi-Media Card (e•MMC) Electrical Standard (5.1)_, JEDEC JESD84-B51, February 2015 +- <a name="mmc-core-h"></a>[2] [linux/mmc/core.h](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/mmc/core.h), Linux kernel sources +- <a name="mmc-utils"></a>[3] The [mmc-utils](http://git.kernel.org/cgit/linux/kernel/git/cjb/mmc-utils.git) repository +- <a name="CBC-ESSIV"></a>[4] [_Cipher Block Chaining_](https://en.wikipedia.org/wiki/Disk_encryption_theory#Cipher-block_chaining_.28CBC.29), +Wikipedia diff --git a/documentation/secure_storage_sql.md b/documentation/secure_storage_sql.md new file mode 100644 index 0000000..675c794 --- /dev/null +++ b/documentation/secure_storage_sql.md @@ -0,0 +1,77 @@ +# SQL DB Secure Storage + +## Introduction + +This document describes the SQL DB secure storage in OP-TEE, which is enabled +by setting CFG_SQL_FS=y. Trusted Applications may use this implementation by +passing a storage ID equal to TEE_STORAGE_PRIVATE_SQL, or TEE_STORAGE_PRIVATE +if CFG_REE_FS and CFG_RPMB_FS are disabled. +With this filesystem, the secure object are stored as individual files in a +SQLite database (which is a file by itself in the REE filesystem). +This implementation may be viewed as a simplified version of the REE FS, because +it uses a single file per persistent object. This is possible because SQLite has +a transaction API which allows atomic updates (and rollback in case of error). + +Files are created in the database by the **libsqlfs** library [[1]](#libsqlfs). +For details about **SQLite**, please refer to [[2]](#SQLite). + +The architecture is depicted below. + +``` + NORMAL WORLD : SECURE WORLD + : + U tee-supplicant : Trusted application + S (sql_fs.c) : (secure storage API) + E libsqlfs ^ : ^ + R SQLite | :~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~: v + K | | : OP-TEE + E v v : (tee_svc_storage.c) + R REE filesystem OP-TEE driver : (tee_sql_fs.c, tee_fs_key_manager.c) + N ^ : ^ + E | : | + L | : | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~ + v v + Secure monitor / EL3 firmware +``` + +## The Secure Storage API + +This part is common with the other filesystems. The interface between the +system calls in [core/tee/tee_svc_storage.c](../core/tee/tee_svc_storage.c) and +the SQL filesystem is the **tee_file_operations** structure `sql_fs_ops`. + +## The SQL filesystem + +The secure side of the SQL FS implementation is mostly in +[core/tee/tee_sql_fs.c](../core/tee/tee_sql_fs.c). This file maps the operations +in `sql_fs_ops` such as `open`, `truncate`, `read`, `write`, `seek` +and so on, to similar operations on a file that is a container for the encrypted +data and associated meta-data. This container is created and manipulated by +`tee-supplicant` on request from the secure OS. Its layout is like this: + +``` + [ File meta-data ] [ Block #0 ] [Block #1]... + [meta_header|sql_fs_file_meta] [block_header|user data] [ ]... +``` + +How this file is stored in the SQLite database is private to **libsqlfs**. From +the point of view of OP-TEE, it is a byte-addressable linear file on which +atomic updates can be performed through a standard interface (`open`, +`truncate`, `seek`, `read`, `write`...) with the addition of `begin_transaction` +and `end_transaction`. + +## Encryption + +The encryption is the same as for REE FS, so you can find more details in the +encryption section of [secure_storage.md](secure_storage.md). Bear in mind that +the only difference lies in the data storage: one single file for the SQL +implementation, versus multiple `meta` and `block` files for the REE FS. + +## References + +- <a name="libsqlfs"></a>[1] **libsqlfs** +[http://www.nongnu.org/libsqlfs/](http://www.nongnu.org/libsqlfs/), +[https://github.com/guardianproject/libsqlfs](https://github.com/guardianproject/libsqlfs) +- <a name="SQLite"></a>[2] **SQLite** [https://www.sqlite.org/](https://www.sqlite.org/) |