blob: ca2abe5806365df541d6a354d9daa4120502267a [file] [log] [blame]
.. _cryptographic_implementation:
############################
Cryptographic 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.
.. code-block:: none
- some_function() (Trusted App) -
[1] TEE_*() User space (libutee.a)
------- utee_*() ----------------------------------------------
[2] tee_svc_*() Kernel space
[3] crypto_*() (libtomcrypt.a and crypto.c)
[4] /* LibTomCrypt */ (libtomcrypt.a)
[1] The TEE Cryptographic Operations API
****************************************
OP-TEE implements the Cryptographic Operations API defined by the GlobalPlatform
association in the :ref:`tee_internal_core_api`. 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_, 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_ and implemented in
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.
[2] The crypto services
***********************
All cryptography-related system calls are declared in tee_svc_cryp.h_ and
implemented in 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 API**, which is declared in crypto.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.
[3] crypto_*()
**************
The ``crypto_*()`` functions implement the actual algorithms and helper
functions. TEE Core has one global active implementation of this interface. The
default implementation, mostly based on LibTomCrypt_, is as follows:
.. code-block:: c
:caption: File: core/crypto/crypto.c
/*
* Default implementation for all functions in crypto.h
*/
#if !defined(_CFG_CRYPTO_WITH_HASH)
TEE_Result crypto_hash_get_ctx_size(uint32_t algo __unused,
size_t *size __unused)
{
return TEE_ERROR_NOT_IMPLEMENTED;
}
...
#endif /*_CFG_CRYPTO_WITH_HASH*/
.. code-block:: c
:caption: File: core/lib/libtomcrypt/tee_ltc_provider.c
#if defined(_CFG_CRYPTO_WITH_HASH)
TEE_Result crypto_hash_get_ctx_size(uint32_t algo, size_t *size)
{
/* ... */
return TEE_SUCCESS;
}
#endif /*_CFG_CRYPTO_WITH_HASH*/
As shown above, families of algorithms can be disabled and crypto.c_ will
provide default null implementations that will return
``TEE_ERROR_NOT_IMPLEMENTED``.
Public/private key format
*************************
crypto.h_ uses implementation-specific types to hold key data for asymmetric
algorithms. For instance, here is how a public RSA key is represented:
.. code-block:: c
:caption: File: core/include/crypto/crypto.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.
.. code-block:: c
:caption: File: core/include/crypto/crypto.h
struct bignum *crypto_bignum_allocate(size_t size_bits);
TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize,
struct bignum *to);
void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to);
/*...*/
[4] LibTomCrypt
***************
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:
.. code-block:: bash
$ 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`_ 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``).
Add a new software based crypto implementation
**********************************************
To add a new software based implementation, the default one in
`core/lib/libtomcrypt`_ in combination with what is in `core/crypto`_ should be
used as a reference. 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`` unless it is
code that will be used regardless of which crypto provider is in use. How
we are dealing with AES-GCM in `core/crypto`_ could serve as an example.
- Avoid modifying tee_svc_cryp.c_. It should not be needed.
- Although not all crypto families 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.
[5] Support for crypto IC
*************************
Some cryptographic co-processors and secure elements are supported under a
Generic Cryptographic Driver interface, connecting the TEE Crypto generic APIs
to the HW driver interface. This interface is in
`core/drivers/crypto/crypto_api`_ and should be followed when adding support for
new devices.
At the time of writing, OP-TEE does not support the `GP TEE Secure Element API`_
and therefore the access to the secure element - the NXP EdgeLock® SE05x -
follows the Cryptographic Operations API presenting a single session to the
device. This session is shared with the normal world through the PKCS#11
interface but also through a more generic interface (`libseetec`_) which allows
clients to send Application Protocol Data Units (APDUs) directly to the device.
Notice that cryptographic co-processors do not necessarily comply with all the
GP requirements tested and covered by the OP-TEE sanity test suite
(`optee_test`_). In those cases where the cryptographic operations are not
supported - i.e: the SE05x does not implement all RSA key sizes - we opted for
disabling those particular tests at build time rather than letting them fail.
NXP SE05X Family of Secure Elements
***********************************
This family of I2C bus devices are supported through the se050 cryptographic driver
located at `core/drivers/crypto/se050`_. Before the REE boots, the session with
the device is established using one of the OP-TEE supported I2C platform device
drivers. Once the REE is up, the cryptographic driver can be configured to use
the I2C driver in the REE (via RPC service) or continue using the one in OP-TEE.
Unless the Secure Element owns the I2C bus (no other elements on the bus, no
runtime-PM and so forth), it is recommended to route all traffic via the Normal
World. Initial communication with the device is not data intensive and therefore
slow I2C drivers - perhaps those not using DMA channels - do not represent much
of a performance drag; the situation changes once clients start hammering the
device.
If using the REE for I2C transfers, it is also **imperative** to configure the
driver so that the `GP Secure Channel Protocol 03`_ is enabled prior to exiting the
Secure World; this way all communication between the processor and the secure
element is encrypted and MAC authenticated. Please check the usage of the
``CFG_CORE_SE05X_SCP03_EARLY`` configuration option.
Aside of the secure element integration as an OP-TEE cryptographic driver,
OP-TEE also presents an Application Protocol Data Units (APDU) interface to
users via its OP-TEE client.
.. figure:: ../images/crypto/drivers/se050_apdu_pta_interface.png
:figclass: align-center
Access to the Secure Element from libseetec and the APDU PTA.
Using this interface, priviledged applications can control the Secure Element to
inject or delete keys or certificates, encrypt, decrypt, sign and verify data
and so forth. An application implementing a subset of those functions can be
seen in this Foundries.io repository: `fio-se05x-cli`_
This reference code is not fully functional in mainline as it's not yet possible
to import keys and certificates from the Secure Element into OP-TEE's PKCS#11
implementation. However, a user could still clear the Secure Element NVM memory
and read certificates stored in it.
.. Source files
.. _core/crypto: https://github.com/OP-TEE/optee_os/blob/master/core/crypto
.. _core/drivers/crypto/crypto_api: https://github.com/OP-TEE/optee_os/blob/master/core/drivers/crypto/crypto_api
.. _core/drivers/crypto/se050: https://github.com/OP-TEE/optee_os/blob/master/core/drivers/crypto/se050
.. _crypto.c: https://github.com/OP-TEE/optee_os/blob/master/core/crypto/crypto.c
.. _crypto.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/crypto/crypto.h
.. _core/lib/libtomcrypt: https://github.com/OP-TEE/optee_os/blob/master/core/lib/libtomcrypt
.. _core/lib/libtomcrypt/sub.mk: https://github.com/OP-TEE/optee_os/blob/master/core/lib/libtomcrypt/sub.mk
.. _libseetec: https://github.com/OP-TEE/optee_client/commit/f4f54e5a76641fda22a49f00294771f948cd4c92
.. _optee_test: https://github.com/OP-TEE/optee_test
.. _tee_api_operations.c: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/tee_api_operations.c
.. _tee_svc_cryp.c: https://github.com/OP-TEE/optee_os/blob/master/core/tee/tee_svc_cryp.c
.. _tee_svc_cryp.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/tee/tee_svc_cryp.h
.. _utee_syscalls.h: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/include/utee_syscalls.h
.. _utee_syscalls_asm.S: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/arch/arm/utee_syscalls_asm.S
.. Other links:
.. _fio-se05x-cli: https://github.com/foundriesio/fio-se05x-cli
.. _LibTomCrypt: https://github.com/libtom/libtomcrypt
.. _GP TEE Secure Element API: https://globalplatform.org/specs-library/tee-secure-element-api/
.. _GP Secure Channel Protocol 03: https://globalplatform.org/wp-content/uploads/2019/03/GPC_2.2_D_SCP03_v1.0.pdf