Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 1 | .. _cryptographic_implementation: |
| 2 | |
| 3 | ############################ |
| 4 | Cryptographic implementation |
| 5 | ############################ |
| 6 | This document describes how the TEE Cryptographic Operations API is implemented, |
| 7 | how the default crypto provider may be configured at compile time, and how it |
| 8 | may be replaced by another implementation. |
| 9 | |
| 10 | Overview |
| 11 | ******** |
| 12 | There are several layers from the Trusted Application to the actual crypto |
| 13 | algorithms. Most of the crypto code runs in kernel mode inside the TEE core. |
| 14 | Here is a schematic view of a typical call to the crypto API. The numbers in |
| 15 | square brackets ([1], [2]...) refer to the sections below. |
| 16 | |
| 17 | .. code-block:: none |
| 18 | |
| 19 | - some_function() (Trusted App) - |
| 20 | [1] TEE_*() User space (libutee.a) |
| 21 | ------- utee_*() ---------------------------------------------- |
| 22 | [2] tee_svc_*() Kernel space |
| 23 | [3] crypto_*() (libtomcrypt.a and crypto.c) |
| 24 | [4] /* LibTomCrypt */ (libtomcrypt.a) |
| 25 | |
Etienne Carriere | c5b978f | 2025-03-28 14:06:25 +0100 | [diff] [blame^] | 26 | The TEE Cryptographic Operations API |
| 27 | ************************************ |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 28 | OP-TEE implements the Cryptographic Operations API defined by the GlobalPlatform |
| 29 | association in the :ref:`tee_internal_core_api`. This includes cryptographic |
| 30 | functions that span various cryptographic needs: message digests, symmetric |
| 31 | ciphers, message authentication codes (MAC), authenticated encryption, |
| 32 | asymmetric operations (encryption/decryption or signing/verifying), key |
| 33 | derivation, and random data generation. These functions make up the TEE |
| 34 | Cryptographic Operations API. |
| 35 | |
| 36 | The Internal API is implemented in tee_api_operations.c_, which is compiled into |
| 37 | a static library: ``${O}/ta_arm{32,64}-lib/libutee/libutee.a``. |
| 38 | |
| 39 | Most API functions perform some parameter checking and manipulations, then |
| 40 | invoke some *utee\_\** function to switch to kernel mode and perform the |
| 41 | low-level work. |
| 42 | |
| 43 | The *utee\_\** functions are declared in utee_syscalls.h_ and implemented in |
| 44 | utee_syscalls_asm.S_ They are simple system call wrappers which use the *SVC* |
| 45 | instruction to switch to the appropriate system service in the OP-TEE kernel. |
| 46 | |
Etienne Carriere | c5b978f | 2025-03-28 14:06:25 +0100 | [diff] [blame^] | 47 | The crypto services |
| 48 | ******************* |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 49 | All cryptography-related system calls are declared in tee_svc_cryp.h_ and |
| 50 | implemented in tee_svc_cryp.c_. In addition to dealing with the usual work |
| 51 | required at the user/kernel interface (checking parameters and copying memory |
| 52 | buffers between user and kernel space), the system calls invoke a private |
| 53 | abstraction layer: the **Crypto API**, which is declared in crypto.h_. It serves |
| 54 | two main purposes: |
| 55 | |
| 56 | 1. Allow for alternative implementations, such as hardware-accelerated |
| 57 | versions. |
| 58 | |
| 59 | 2. Provide an easy way to disable some families of algorithms at |
Etienne Carriere | 9e57493 | 2025-03-27 18:45:28 +0100 | [diff] [blame] | 60 | compile-time to save space. See sw_crypto_lib_ below. |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 61 | |
Etienne Carriere | c5b978f | 2025-03-28 14:06:25 +0100 | [diff] [blame^] | 62 | crypto_*() |
| 63 | ********** |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 64 | The ``crypto_*()`` functions implement the actual algorithms and helper |
| 65 | functions. TEE Core has one global active implementation of this interface. The |
| 66 | default implementation, mostly based on LibTomCrypt_, is as follows: |
| 67 | |
| 68 | .. code-block:: c |
| 69 | :caption: File: core/crypto/crypto.c |
Jorge Ramirez-Ortiz | 6cb630f | 2024-02-12 09:21:47 +0100 | [diff] [blame] | 70 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 71 | /* |
| 72 | * Default implementation for all functions in crypto.h |
| 73 | */ |
Jorge Ramirez-Ortiz | 6cb630f | 2024-02-12 09:21:47 +0100 | [diff] [blame] | 74 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 75 | #if !defined(_CFG_CRYPTO_WITH_HASH) |
| 76 | TEE_Result crypto_hash_get_ctx_size(uint32_t algo __unused, |
| 77 | size_t *size __unused) |
| 78 | { |
| 79 | return TEE_ERROR_NOT_IMPLEMENTED; |
| 80 | } |
| 81 | ... |
| 82 | #endif /*_CFG_CRYPTO_WITH_HASH*/ |
Jorge Ramirez-Ortiz | 6cb630f | 2024-02-12 09:21:47 +0100 | [diff] [blame] | 83 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 84 | .. code-block:: c |
| 85 | :caption: File: core/lib/libtomcrypt/tee_ltc_provider.c |
Jorge Ramirez-Ortiz | 6cb630f | 2024-02-12 09:21:47 +0100 | [diff] [blame] | 86 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 87 | #if defined(_CFG_CRYPTO_WITH_HASH) |
| 88 | TEE_Result crypto_hash_get_ctx_size(uint32_t algo, size_t *size) |
| 89 | { |
| 90 | /* ... */ |
| 91 | return TEE_SUCCESS; |
| 92 | } |
Jorge Ramirez-Ortiz | 6cb630f | 2024-02-12 09:21:47 +0100 | [diff] [blame] | 93 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 94 | #endif /*_CFG_CRYPTO_WITH_HASH*/ |
Jorge Ramirez-Ortiz | 6cb630f | 2024-02-12 09:21:47 +0100 | [diff] [blame] | 95 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 96 | As shown above, families of algorithms can be disabled and crypto.c_ will |
| 97 | provide default null implementations that will return |
| 98 | ``TEE_ERROR_NOT_IMPLEMENTED``. |
| 99 | |
| 100 | Public/private key format |
| 101 | ************************* |
| 102 | crypto.h_ uses implementation-specific types to hold key data for asymmetric |
| 103 | algorithms. For instance, here is how a public RSA key is represented: |
| 104 | |
| 105 | .. code-block:: c |
| 106 | :caption: File: core/include/crypto/crypto.h |
| 107 | |
| 108 | struct rsa_public_key { |
| 109 | struct bignum *e; /* Public exponent */ |
| 110 | struct bignum *n; /* Modulus */ |
| 111 | }; |
| 112 | |
| 113 | This is also how such keys are stored inside the TEE object attributes |
| 114 | (``TEE_ATTR_RSA_PUBLIC_KEY`` in this case). ``struct bignum`` is an opaque type, |
| 115 | known to the underlying implementation only. ``struct bignum_ops`` provides |
| 116 | functions so that the system services can manipulate data of this type. This |
| 117 | includes allocation/deallocation, copy, and conversion to or from the big endian |
| 118 | binary format. |
| 119 | |
| 120 | .. code-block:: c |
| 121 | :caption: File: core/include/crypto/crypto.h |
| 122 | |
| 123 | struct bignum *crypto_bignum_allocate(size_t size_bits); |
| 124 | |
| 125 | TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize, |
| 126 | struct bignum *to); |
| 127 | |
| 128 | void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to); |
| 129 | /*...*/ |
| 130 | |
Etienne Carriere | 9e57493 | 2025-03-27 18:45:28 +0100 | [diff] [blame] | 131 | .. _sw_crypto_lib: |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 132 | |
Etienne Carriere | c5b978f | 2025-03-28 14:06:25 +0100 | [diff] [blame^] | 133 | Software crypto library |
| 134 | *********************** |
Etienne Carriere | 9e57493 | 2025-03-27 18:45:28 +0100 | [diff] [blame] | 135 | |
| 136 | LibTomCrypt is the default software implementation for cryptographic |
| 137 | operations. When so, this is stated by OP-TEE configuration directives |
| 138 | ``CFG_CRYPTOLIB_NAME=tomcrypt`` and |
| 139 | ``CFG_CRYPTOLIB_DIR=core/lib/libtomcrypt``. |
| 140 | |
| 141 | Mbed TLS can be embedded in OP-TEE core as a software cryptographic library |
| 142 | alternative to LibTomCrypt. See :ref:`libmbedtls`. |
| 143 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 144 | Some algorithms may be disabled at compile time if they are not needed, in order |
| 145 | to reduce the size of the OP-TEE image and reduces its memory usage. This is |
| 146 | done by setting the appropriate configuration variable. For example: |
| 147 | |
| 148 | .. code-block:: bash |
| 149 | |
| 150 | $ make CFG_CRYPTO_AES=n # disable AES only |
| 151 | $ make CFG_CRYPTO_{AES,DES}=n # disable symmetric ciphers |
| 152 | $ make CFG_CRYPTO_{DSA,RSA,DH,ECC}=n # disable public key algorithms |
| 153 | $ make CFG_CRYPTO=n # disable all algorithms |
| 154 | |
Etienne Carriere | 96b96c2 | 2025-03-27 18:47:11 +0100 | [diff] [blame] | 155 | Please refer to `core/crypto.mk` for the list of all supported |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 156 | variables. |
| 157 | |
| 158 | Note that the application interface is **not** modified when algorithms are |
| 159 | disabled. This means, for instance, that the functions ``TEE_CipherInit()``, |
| 160 | ``TEE_CipherUpdate()`` and ``TEE_CipherFinal()`` would remain present in |
| 161 | ``libutee.a`` even if all symmetric ciphers are disabled (they would simply |
| 162 | return ``TEE_ERROR_NOT_IMPLEMENTED``). |
| 163 | |
Jorge Ramirez-Ortiz | b322f56 | 2022-02-17 12:09:29 +0100 | [diff] [blame] | 164 | Add a new software based crypto implementation |
| 165 | ********************************************** |
| 166 | To add a new software based implementation, the default one in |
| 167 | `core/lib/libtomcrypt`_ in combination with what is in `core/crypto`_ should be |
| 168 | used as a reference. Here are the main things to consider when adding a new |
| 169 | crypto provider: |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 170 | |
| 171 | - Put all the new code in its own directory under ``core/lib`` unless it is |
| 172 | code that will be used regardless of which crypto provider is in use. How |
| 173 | we are dealing with AES-GCM in `core/crypto`_ could serve as an example. |
| 174 | |
| 175 | - Avoid modifying tee_svc_cryp.c_. It should not be needed. |
| 176 | |
| 177 | - Although not all crypto families need to be defined, all are required for |
| 178 | compliance to the GlobalPlatform specification. |
| 179 | |
| 180 | - If you intend to make some algorithms optional, please try to re-use the |
| 181 | same names for configuration variables as the default implementation. |
| 182 | |
Etienne Carriere | c5b978f | 2025-03-28 14:06:25 +0100 | [diff] [blame^] | 183 | Support for crypto IC |
| 184 | ********************* |
Jorge Ramirez-Ortiz | b322f56 | 2022-02-17 12:09:29 +0100 | [diff] [blame] | 185 | Some cryptographic co-processors and secure elements are supported under a |
| 186 | Generic Cryptographic Driver interface, connecting the TEE Crypto generic APIs |
| 187 | to the HW driver interface. This interface is in |
| 188 | `core/drivers/crypto/crypto_api`_ and should be followed when adding support for |
| 189 | new devices. |
| 190 | |
| 191 | At the time of writing, OP-TEE does not support the `GP TEE Secure Element API`_ |
| 192 | and therefore the access to the secure element - the NXP EdgeLock® SE05x - |
| 193 | follows the Cryptographic Operations API presenting a single session to the |
| 194 | device. This session is shared with the normal world through the PKCS#11 |
| 195 | interface but also through a more generic interface (`libseetec`_) which allows |
| 196 | clients to send Application Protocol Data Units (APDUs) directly to the device. |
| 197 | |
| 198 | Notice that cryptographic co-processors do not necessarily comply with all the |
| 199 | GP requirements tested and covered by the OP-TEE sanity test suite |
| 200 | (`optee_test`_). In those cases where the cryptographic operations are not |
| 201 | supported - i.e: the SE05x does not implement all RSA key sizes - we opted for |
| 202 | disabling those particular tests at build time rather than letting them fail. |
| 203 | |
Jorge Ramirez-Ortiz | d29554c | 2024-02-13 09:30:21 +0100 | [diff] [blame] | 204 | Some cryptographic co-processors may have limitations regarding the |
| 205 | range of key sizes and supported ciphers. For instance, the AMD/Xilinx |
| 206 | Versal ACAP Cryptographic driver may have constraints on key sizes, |
| 207 | while NXP SE5X HSM modules may lack support for RSA or ECC. In such |
| 208 | cases, especially when dealing with unsupported key sizes, it may be |
| 209 | necessary to resort to a software implementation of the cipher, |
| 210 | typically utilizing LibTomCrypt. |
| 211 | |
| 212 | .. note:: |
| 213 | While the Hardware Security Modules or Cryptographic hardware |
| 214 | processors supported by OP-TEE may achieve FIPS 140-2 certification |
| 215 | at level 3, the software implementations of certain algorithms that |
| 216 | OP-TEE may fallback to cannot attain certification beyond level 2. |
| 217 | |
Jorge Ramirez-Ortiz | 91cb2b9 | 2022-12-09 12:25:17 +0100 | [diff] [blame] | 218 | NXP SE05X Family of Secure Elements |
| 219 | *********************************** |
| 220 | |
| 221 | This family of I2C bus devices are supported through the se050 cryptographic driver |
| 222 | located at `core/drivers/crypto/se050`_. Before the REE boots, the session with |
| 223 | the device is established using one of the OP-TEE supported I2C platform device |
| 224 | drivers. Once the REE is up, the cryptographic driver can be configured to use |
| 225 | the I2C driver in the REE (via RPC service) or continue using the one in OP-TEE. |
| 226 | |
| 227 | Unless the Secure Element owns the I2C bus (no other elements on the bus, no |
| 228 | runtime-PM and so forth), it is recommended to route all traffic via the Normal |
| 229 | World. Initial communication with the device is not data intensive and therefore |
| 230 | slow I2C drivers - perhaps those not using DMA channels - do not represent much |
| 231 | of a performance drag; the situation changes once clients start hammering the |
| 232 | device. |
| 233 | |
| 234 | If using the REE for I2C transfers, it is also **imperative** to configure the |
| 235 | driver so that the `GP Secure Channel Protocol 03`_ is enabled prior to exiting the |
| 236 | Secure World; this way all communication between the processor and the secure |
| 237 | element is encrypted and MAC authenticated. Please check the usage of the |
| 238 | ``CFG_CORE_SE05X_SCP03_EARLY`` configuration option. |
| 239 | |
| 240 | Aside of the secure element integration as an OP-TEE cryptographic driver, |
| 241 | OP-TEE also presents an Application Protocol Data Units (APDU) interface to |
| 242 | users via its OP-TEE client. |
| 243 | |
| 244 | .. figure:: ../images/crypto/drivers/se050_apdu_pta_interface.png |
| 245 | :figclass: align-center |
| 246 | |
| 247 | Access to the Secure Element from libseetec and the APDU PTA. |
| 248 | |
| 249 | Using this interface, priviledged applications can control the Secure Element to |
| 250 | inject or delete keys or certificates, encrypt, decrypt, sign and verify data |
| 251 | and so forth. An application implementing a subset of those functions can be |
| 252 | seen in this Foundries.io repository: `fio-se05x-cli`_ |
| 253 | |
| 254 | This reference code is not fully functional in mainline as it's not yet possible |
| 255 | to import keys and certificates from the Secure Element into OP-TEE's PKCS#11 |
| 256 | implementation. However, a user could still clear the Secure Element NVM memory |
| 257 | and read certificates stored in it. |
| 258 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 259 | .. Source files |
| 260 | .. _core/crypto: https://github.com/OP-TEE/optee_os/blob/master/core/crypto |
Jorge Ramirez-Ortiz | b322f56 | 2022-02-17 12:09:29 +0100 | [diff] [blame] | 261 | .. _core/drivers/crypto/crypto_api: https://github.com/OP-TEE/optee_os/blob/master/core/drivers/crypto/crypto_api |
Jorge Ramirez-Ortiz | 91cb2b9 | 2022-12-09 12:25:17 +0100 | [diff] [blame] | 262 | .. _core/drivers/crypto/se050: https://github.com/OP-TEE/optee_os/blob/master/core/drivers/crypto/se050 |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 263 | .. _crypto.c: https://github.com/OP-TEE/optee_os/blob/master/core/crypto/crypto.c |
| 264 | .. _crypto.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/crypto/crypto.h |
| 265 | .. _core/lib/libtomcrypt: https://github.com/OP-TEE/optee_os/blob/master/core/lib/libtomcrypt |
| 266 | .. _core/lib/libtomcrypt/sub.mk: https://github.com/OP-TEE/optee_os/blob/master/core/lib/libtomcrypt/sub.mk |
Jorge Ramirez-Ortiz | b322f56 | 2022-02-17 12:09:29 +0100 | [diff] [blame] | 267 | .. _libseetec: https://github.com/OP-TEE/optee_client/commit/f4f54e5a76641fda22a49f00294771f948cd4c92 |
| 268 | .. _optee_test: https://github.com/OP-TEE/optee_test |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 269 | .. _tee_api_operations.c: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/tee_api_operations.c |
| 270 | .. _tee_svc_cryp.c: https://github.com/OP-TEE/optee_os/blob/master/core/tee/tee_svc_cryp.c |
| 271 | .. _tee_svc_cryp.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/tee/tee_svc_cryp.h |
| 272 | .. _utee_syscalls.h: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/include/utee_syscalls.h |
| 273 | .. _utee_syscalls_asm.S: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/arch/arm/utee_syscalls_asm.S |
| 274 | |
| 275 | .. Other links: |
Jorge Ramirez-Ortiz | 91cb2b9 | 2022-12-09 12:25:17 +0100 | [diff] [blame] | 276 | .. _fio-se05x-cli: https://github.com/foundriesio/fio-se05x-cli |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 277 | .. _LibTomCrypt: https://github.com/libtom/libtomcrypt |
Jorge Ramirez-Ortiz | b322f56 | 2022-02-17 12:09:29 +0100 | [diff] [blame] | 278 | .. _GP TEE Secure Element API: https://globalplatform.org/specs-library/tee-secure-element-api/ |
Jorge Ramirez-Ortiz | 91cb2b9 | 2022-12-09 12:25:17 +0100 | [diff] [blame] | 279 | .. _GP Secure Channel Protocol 03: https://globalplatform.org/wp-content/uploads/2019/03/GPC_2.2_D_SCP03_v1.0.pdf |