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 | |
| 26 | [1] The TEE Cryptographic Operations API |
| 27 | **************************************** |
| 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 | |
| 47 | [2] The crypto services |
| 48 | *********************** |
| 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 |
| 60 | compile-time to save space. See `LibTomCrypt` below. |
| 61 | |
| 62 | [3] crypto_*() |
| 63 | ************** |
| 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 |
| 70 | |
| 71 | /* |
| 72 | * Default implementation for all functions in crypto.h |
| 73 | */ |
| 74 | |
| 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*/ |
| 83 | |
| 84 | .. code-block:: c |
| 85 | :caption: File: core/lib/libtomcrypt/tee_ltc_provider.c |
| 86 | |
| 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 | } |
| 93 | |
| 94 | #endif /*_CFG_CRYPTO_WITH_HASH*/ |
| 95 | |
| 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 | |
| 131 | |
| 132 | [4] LibTomCrypt |
| 133 | *************** |
| 134 | Some algorithms may be disabled at compile time if they are not needed, in order |
| 135 | to reduce the size of the OP-TEE image and reduces its memory usage. This is |
| 136 | done by setting the appropriate configuration variable. For example: |
| 137 | |
| 138 | .. code-block:: bash |
| 139 | |
| 140 | $ make CFG_CRYPTO_AES=n # disable AES only |
| 141 | $ make CFG_CRYPTO_{AES,DES}=n # disable symmetric ciphers |
| 142 | $ make CFG_CRYPTO_{DSA,RSA,DH,ECC}=n # disable public key algorithms |
| 143 | $ make CFG_CRYPTO=n # disable all algorithms |
| 144 | |
| 145 | Please refer to `core/lib/libtomcrypt/sub.mk`_ for the list of all supported |
| 146 | variables. |
| 147 | |
| 148 | Note that the application interface is **not** modified when algorithms are |
| 149 | disabled. This means, for instance, that the functions ``TEE_CipherInit()``, |
| 150 | ``TEE_CipherUpdate()`` and ``TEE_CipherFinal()`` would remain present in |
| 151 | ``libutee.a`` even if all symmetric ciphers are disabled (they would simply |
| 152 | return ``TEE_ERROR_NOT_IMPLEMENTED``). |
| 153 | |
| 154 | Add a new crypto implementation |
| 155 | ******************************* |
| 156 | To add a new implementation, the default one in `core/lib/libtomcrypt`_ in |
| 157 | combination with what is in `core/crypto`_ should be used as a reference. Here |
| 158 | are the main things to consider when adding a new crypto provider: |
| 159 | |
| 160 | - Put all the new code in its own directory under ``core/lib`` unless it is |
| 161 | code that will be used regardless of which crypto provider is in use. How |
| 162 | we are dealing with AES-GCM in `core/crypto`_ could serve as an example. |
| 163 | |
| 164 | - Avoid modifying tee_svc_cryp.c_. It should not be needed. |
| 165 | |
| 166 | - Although not all crypto families need to be defined, all are required for |
| 167 | compliance to the GlobalPlatform specification. |
| 168 | |
| 169 | - If you intend to make some algorithms optional, please try to re-use the |
| 170 | same names for configuration variables as the default implementation. |
| 171 | |
| 172 | .. Source files |
| 173 | .. _core/crypto: https://github.com/OP-TEE/optee_os/blob/master/core/crypto |
| 174 | .. _crypto.c: https://github.com/OP-TEE/optee_os/blob/master/core/crypto/crypto.c |
| 175 | .. _crypto.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/crypto/crypto.h |
| 176 | .. _core/lib/libtomcrypt: https://github.com/OP-TEE/optee_os/blob/master/core/lib/libtomcrypt |
| 177 | .. _core/lib/libtomcrypt/sub.mk: https://github.com/OP-TEE/optee_os/blob/master/core/lib/libtomcrypt/sub.mk |
| 178 | .. _tee_api_operations.c: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/tee_api_operations.c |
| 179 | .. _tee_svc_cryp.c: https://github.com/OP-TEE/optee_os/blob/master/core/tee/tee_svc_cryp.c |
| 180 | .. _tee_svc_cryp.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/tee/tee_svc_cryp.h |
| 181 | .. _utee_syscalls.h: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/include/utee_syscalls.h |
| 182 | .. _utee_syscalls_asm.S: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/arch/arm/utee_syscalls_asm.S |
| 183 | |
| 184 | .. Other links: |
| 185 | .. _LibTomCrypt: https://github.com/libtom/libtomcrypt |