Skip to content
README.rst 8.04 KiB
Newer Older
=========================================
Trusted Services TEE driver documentation
=========================================

The Trusted Services TEE driver is a Linux kernel module providing user space access to
`Trusted Services`_. The implementation extends the `TEE subsystem`_ and uses `FF-A`_ compliant
messaging between the NWd and SWd. The driver depends on the `FF-A driver`_, which is available
upstream since v5.14.

.. contents::

TEE subsystem
=============

Overview
--------

The TEE subsystem in the Linux kernel,

- handles the registration of a TEE driver and its callbacks,
- provides a generic API towards user space for different TEEs,
- helps with managing shared memory between Linux and the TEE.

A TEE device (i.e. :code:`/dev/tee[0-9]*`) is a generic device, registered by a TEE driver (e.g.
OP-TEE driver). At registration, the TEE driver provides its specific callbacks which will be
registered for the TEE device. The :code:`open()` / :code:`close()` / :code:`ioctl()` calls on a TEE
device are handled by the generic TEE subsystem code, which will invoke the driver specific
callbacks. Among the callbacks there is one to query information about the driver type and
capabilities. Using this, user space can find out which TEE belongs to a particular TEE device. When
opening a TEE device, a context is allocated. This represents the connection between the client app
and the Trusted OS. Inside this context one or more sessions can be opened, which represent the
connection between the client app and a Trusted OS app (e.g. a TA in the case of OP-TEE). The TEE
subsystem's model is independent of OP-TEE, multiple TEE drivers can coexist in a single system.

Example system with OP-TEE and Trusted Services::

              +-------+       +-------+
              | App 1 |       | App 2 |
              +-------+       +-------+
  User space      |               |
     EL0          V               V
              +--------+      +-------+
              | OP-TEE |      | libts |
              | client |      +-------+
              +--------+          |
                  |               |
                  V               V
              +-----------------------+
  ----------- | Generic TEE API ioctl | ----------
              +-----------------------+
                          |
                          V
              +-----------------------+
              |     TEE subsystem     |
              +-----------------------+
  Kernel space     |            |
      EL1          V            V
              +--------+   +----------+
              | OP-TEE |   |  TS TEE  |
              | driver |   |  driver  |
              +--------+   +----------+
                |     |         |
                |     V         V
                |    +-------------+
                |    | FF-A driver |
                |    +-------------+
                |           |
  ------------- | --------- | -------------------
                V           V
              +-----------------------+
      EL3     |         TF-A          |
              +-----------------------+

Trusted Services, FF-A and TEE concepts
---------------------------------------

The `FF-A driver`_ only provides an in-kernel API to invoke FF-A operations. To be able to
communicate with SPs from a Linux app, a TEE driver can bridge this gap and provide an API
towards user space.

Mapping TEE concepts to FF-A and TS terms, a short summary of the key implementation decisions:
- There is 1:1 mapping between SPs and TEE devices, i.e. a TEE device gets registered for each
  compatible FF-A device found on the kernel FF-A bus.
- "Opening" an SP corresponds to opening the TEE device and creating a TEE context. An SP hosts one
  or more services, opening a service corresponds to opening a session in the given tee_context.
- The register ABI (i.e. TS_RPC_*) used by the driver is the standardised RPC protocol for accessing
  Trusted Services. The protocol definition will be published shortly in the project documentation.
  All Trusted Services SPs talk this protocol, so they all have the same FF-A UUID, which identifies
  this protocol.
- A service type (e.g. PSA Crypto) is identified by a service UUID. The same type of service can be
  present in multiple SPs, but not twice in the same SP. During SP boot each service in the SP gets
  assigned an interface ID, this is just a short ID to simplify message addressing.

The TEE subsystem has two mechanisms for memory sharing:

- Registration: memory is allocated by user space client. TEE subsystem will pin the user pages and
  register the shared memory in the TEE, using the TEE specific callback provided by the TEE driver.

- Allocation: memory is allocated in kernel space by the TEE subsystem, from a pool provided by the
  TEE driver. After allocation, the shared memory is registered using the TEE specific callback.
  Then a file descriptor is returned, user space needs to :code:`mmap()` this to access the buffer.
  Currently only this mechanism is supported by the Trusted Services TEE driver.

User space interface
====================

Summary
-------

The `TEE subsystem`_ provides a set of ioctl calls. Some of these have generic parameters,
which allows the concrete TEE implementation to define usage of the parameters in alignment with the
driver's specific requirements.

User space bindings
-------------------

List of TEE subsystem ioctl calls and its parameters used by this driver:

- **TEE_IOC_OPEN_SESSION**: Open service if it's implemented by the SP.

  Used parameters: :code:`struct tee_ioctl_open_session_arg`

  - :code:`uuid`: service UUID (in)
  - :code:`session`: session ID (out)

- **TEE_IOC_CLOSE_SESSION**: Close service.

  Used parameters: :code:`struct tee_ioctl_close_session_arg`

  - :code:`session`: session ID (in)

- **TEE_IOC_SHM_ALLOC**: Initialize a shared memory buffer. A buffer is allocated from kernel memory
  and shared with the SP. The return value of the :code:`ioctl()` call is a file descriptor which
  should be :code:`mmap()`-ed by user space. Deinit of the buffer is done via :code:`munmap()`,
  no separate :code:`ioctl()` call to this driver is necessary.

  Used parameters: :code:`struct tee_ioctl_shm_alloc_data`

  - :code:`size`: requested shared buffer size (in), actual shared buffer size (out)
  - :code:`id`: shared memory ID (out)

- **TEE_IOC_INVOKE**: Invoke function of a particular service. Needs to have a session already open
  to the service. If the call doesn't use a shared buffer, the shared memory ID and request/response
  length must be zero.

  Used parameters: :code:`struct tee_ioctl_invoke_arg`

  - :code:`func`: opcode, service specific (in)
  - :code:`session`: session ID (in)
  - :code:`ret`: result of the operation, service specific (out)
  - :code:`num_params`: 1
  - :code:`params[0].a`: shared memory ID (in)
  - :code:`params[0].b`: request/response length in the shared memory (in/out)
Versioning
==========

The project uses `semantic versioning`_.

- To access the latest version of the driver, use the :code:`main` branch.
- To access the latest version compatible with the :code:`x` major version, use
  the :code:`tee-vx` branch.
- To access the latest version compatible with the :code:`x.y` minor version,
  use the :code:`tee-vx.y` branch.
- To access a specific version of the driver, use the :code:`tee-vx.y.z` tag.

Initially instead of branches, the repo was using moving tags to describe the
major and minor versions. This is a git anti-pattern, so it was deprecated.
However, to avoid breaking any existing systems, we decided to keep the original
tags too. Please consider the :code:`tee-v1` and :code:`tee-v1.1` tags obsolete
and use the branches instead as descibed above.

--------------

Copyright (c) 2021-2023, Arm Limited. All rights reserved.

SPDX-License-Identifier: GPL-2.0-only

.. _Trusted Services: https://www.trustedfirmware.org/projects/trusted-services/
.. _TEE subsystem: https://www.kernel.org/doc/html/latest/staging/tee.html
.. _FF-A: https://developer.arm.com/documentation/den0077/latest
.. _FF-A driver: https://elixir.bootlin.com/linux/v6.1/source/drivers/firmware/arm_ffa
.. _Semantic versioning: https://semver.org