This patch series introduces a Trusted Execution Environment (TEE)
driver for Qualcomm TEE (QTEE). QTEE enables Trusted Applications (TAs)
and services to run securely. It uses an object-based interface, where
each service is an object with sets of operations. Clients can invoke
these operations on objects, which can generate results, including other
objects. For example, an object can load a TA and return another object
that represents the loaded TA, allowing access to its services.
Kernel and userspace services are also available to QTEE through a
similar approach. QTEE makes callback requests that are converted into
object invocations. These objects can represent services within the
kernel or userspace process.
Note: This patch series focuses on QTEE objects and userspace services.
Linux already provides a TEE subsystem, which is described in [1]. The
tee subsystem provides a generic ioctl interface, TEE_IOC_INVOKE, which
can be used by userspace to talk to a TEE backend driver. We extend the
Linux TEE subsystem to understand object parameters and an ioctl call so
client can invoke objects in QTEE:
- TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_*
- TEE_IOC_OBJECT_INVOKE
The existing ioctl calls TEE_IOC_SUPPL_RECV and TEE_IOC_SUPPL_SEND are
used for invoking services in the userspace process by QTEE.
The TEE backend driver uses the QTEE Transport Message to communicate
with QTEE. Interactions through the object INVOKE interface are
translated into QTEE messages. Likewise, object invocations from QTEE
for userspace objects are converted into SEND/RECV ioctl calls to
supplicants.
The details of QTEE Transport Message to communicate with QTEE is
available in [PATCH 12/12] Documentation: tee: Add Qualcomm TEE driver.
You can run basic tests with following steps:
git clone https://github.com/quic/quic-teec.git
cd quic-teec
mkdir build
cmake .. -DCMAKE_TOOLCHAIN_FILE=CMakeToolchain.txt -DBUILD_UNITTEST=ON
https://github.com/quic/quic-teec/blob/main/README.md lists dependencies
needed to build the above.
More comprehensive tests are availabe at
https://github.com/qualcomm/minkipc.
root@qcom-armv8a:~# qtee_supplicant &
root@qcom-armv8a:~# qtee_supplicant: process entry PPID = 378
Total listener services to start = 4
Opening CRequestTABuffer_open
Path /data/
register_service ::Opening CRegisterTABufCBO_UID
Calling TAbufCBO Register
QTEE_SUPPLICANT RUNNING
root@qcom-armv8a:~# smcinvoke_client -c /data 1
Run callback obj test...
Load /data/tzecotestapp.mbn, size 52192, buf 0x1e44ba0.
System Time: 2024-02-27 17:26:31
PASSED - Callback tests with Buffer inputs.
PASSED - Callback tests with Remote and Callback object inputs.
PASSED - Callback tests with Memory Object inputs.
TEST PASSED!
root@qcom-armv8a:~#
root@qcom-armv8a:~# smcinvoke_client -m /data 1
Run memory obj test...
Load /data/tzecotestapp.mbn, size 52192, buf 0x26cafba0.
System Time: 2024-02-27 17:26:39
PASSED - Single Memory Object access Test.
PASSED - Two Memory Object access Test.
TEST PASSED!
This series has been tested for QTEE object invocations, including
loading a TA, requesting services from the TA, memory sharing, and
handling callback requests to a supplicant.
Tested platforms: sm8650-mtp, sm8550-qrd, sm8650-qrd, sm8650-hdk
[1] https://www.kernel.org/doc/Documentation/tee.txt
Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi(a)oss.qualcomm.com>
Changes in v11:
- Rebased on next.
- Link to v10:
https://lore.kernel.org/r/20250909-qcom-tee-using-tee-ss-without-mem-obj-v1…
Changes in v10:
- Remove all loggings in qcom_scm_qtee_init().
- Reorder patches.
- Link to v9:
https://lore.kernel.org/r/20250901-qcom-tee-using-tee-ss-without-mem-obj-v9…
Changes in v9:
- Remove unnecessary logging in qcom_scm_probe().
- Replace the platform_device_alloc()/add() sequence with
platform_device_register_data().
- Fixed sparse warning.
- Fixed documentation typo.
- Link to v8:
https://lore.kernel.org/r/20250820-qcom-tee-using-tee-ss-without-mem-obj-v8…
Changes in v8:
- Check if arguments to qcom_scm_qtee_invoke_smc() and
qcom_scm_qtee_callback_response() are NULL.
- Add CPU_BIG_ENDIAN as a dependency to Kconfig.
- Fixed kernel bot errors.
- Link to v7:
https://lore.kernel.org/r/20250812-qcom-tee-using-tee-ss-without-mem-obj-v7…
Changes in v7:
- Updated copyrights.
- Updated Acked-by: tags.
- Fixed kernel bot errors.
- Link to v6:
https://lore.kernel.org/r/20250713-qcom-tee-using-tee-ss-without-mem-obj-v6…
Changes in v6:
- Relocate QTEE version into the driver's main service structure.
- Simplfies qcomtee_objref_to_arg() and qcomtee_objref_from_arg().
- Enhanced the return logic of qcomtee_object_do_invoke_internal().
- Improve comments and remove redundant checks.
- Improve helpers in qcomtee_msh.h to use GENMASK() and FIELD_GET().
- updated Tested-by:, Acked-by:, and Reviewed-by: tags
- Link to v5:
https://lore.kernel.org/r/20250526-qcom-tee-using-tee-ss-without-mem-obj-v5…
Changes in v5:
- Remove references to kernel services and public APIs.
- Support auto detection for failing devices (e.g., RB1, RB4).
- Add helpers for obtaining client environment and service objects.
- Query the QTEE version and print it.
- Move remaining static variables, including the object table, to struct
qcomtee.
- Update TEE_MAX_ARG_SIZE to 4096.
- Add a dependancy to QCOM_TZMEM_MODE_SHMBRIDGE in Kconfig
- Reorganize code by removing release.c and qcom_scm.c.
- Add more error messages and improve comments.
- updated Tested-by:, Acked-by:, and Reviewed-by: tags
- Link to v4: https://lore.kernel.org/r/20250428-qcom-tee-using-tee-ss-without-mem-obj-v4…
Changes in v4:
- Move teedev_ctx_get/put and tee_device_get/put to tee_core.h.
- Rename object to id in struct tee_ioctl_object_invoke_arg.
- Replace spinlock with mutex for qtee_objects_idr.
- Move qcomtee_object_get to qcomtee_user/memobj_param_to_object.
- More code cleanup following the comments.
- Cleanup documentations.
- Update MAINTAINERS file.
- Link to v3: https://lore.kernel.org/r/20250327-qcom-tee-using-tee-ss-without-mem-obj-v3…
Changes in v3:
- Export shm_bridge create/delete APIs.
- Enable support for QTEE memory objects.
- Update the memory management code to use the TEE subsystem for all
allocations using the pool.
- Move all driver states into the driver's main service struct.
- Add more documentations.
- Link to v2: https://lore.kernel.org/r/20250202-qcom-tee-using-tee-ss-without-mem-obj-v2…
Changes in v2:
- Clean up commit messages and comments.
- Use better names such as ubuf instead of membuf or QCOMTEE prefix
instead of QCOM_TEE, or names that are more consistent with other
TEE-backend drivers such as qcomtee_context_data instead of
qcom_tee_context.
- Drop the DTS patch and instantiate the device from the scm driver.
- Use a single structure for all driver's internal states.
- Drop srcu primitives and use the existing mutex for synchronization
between the supplicant and QTEE.
- Directly use tee_context to track the lifetime of qcomtee_context_data.
- Add close_context() to be called when the user closes the tee_context.
- Link to v1: https://lore.kernel.org/r/20241202-qcom-tee-using-tee-ss-without-mem-obj-v1…
Changes in v1:
- It is a complete rewrite to utilize the TEE subsystem.
- Link to RFC: https://lore.kernel.org/all/20240702-qcom-tee-object-and-ioctls-v1-0-633c3d…
---
Amirreza Zarrabi (11):
firmware: qcom: tzmem: export shm_bridge create/delete
firmware: qcom: scm: add support for object invocation
tee: allow a driver to allocate a tee_device without a pool
tee: add close_context to TEE driver operation
tee: add TEE_IOCTL_PARAM_ATTR_TYPE_UBUF
tee: add TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF
tee: increase TEE_MAX_ARG_SIZE to 4096
tee: add Qualcomm TEE driver
tee: qcom: add primordial object
tee: qcom: enable TEE_IOC_SHM_ALLOC ioctl
Documentation: tee: Add Qualcomm TEE driver
Documentation/tee/index.rst | 1 +
Documentation/tee/qtee.rst | 96 ++++
MAINTAINERS | 7 +
drivers/firmware/qcom/qcom_scm.c | 119 ++++
drivers/firmware/qcom/qcom_scm.h | 7 +
drivers/firmware/qcom/qcom_tzmem.c | 63 ++-
drivers/tee/Kconfig | 1 +
drivers/tee/Makefile | 1 +
drivers/tee/qcomtee/Kconfig | 12 +
drivers/tee/qcomtee/Makefile | 9 +
drivers/tee/qcomtee/async.c | 182 ++++++
drivers/tee/qcomtee/call.c | 820 +++++++++++++++++++++++++++
drivers/tee/qcomtee/core.c | 915 +++++++++++++++++++++++++++++++
drivers/tee/qcomtee/mem_obj.c | 169 ++++++
drivers/tee/qcomtee/primordial_obj.c | 113 ++++
drivers/tee/qcomtee/qcomtee.h | 185 +++++++
drivers/tee/qcomtee/qcomtee_msg.h | 304 ++++++++++
drivers/tee/qcomtee/qcomtee_object.h | 316 +++++++++++
drivers/tee/qcomtee/shm.c | 150 +++++
drivers/tee/qcomtee/user_obj.c | 692 +++++++++++++++++++++++
drivers/tee/tee_core.c | 127 ++++-
drivers/tee/tee_private.h | 6 -
include/linux/firmware/qcom/qcom_scm.h | 6 +
include/linux/firmware/qcom/qcom_tzmem.h | 15 +
include/linux/tee_core.h | 54 +-
include/linux/tee_drv.h | 12 +
include/uapi/linux/tee.h | 56 +-
27 files changed, 4410 insertions(+), 28 deletions(-)
---
base-commit: 8b8aefa5a5c7d4a65883e5653cf12f94c0b68dbf
change-id: 20241202-qcom-tee-using-tee-ss-without-mem-obj-362c66340527
Best regards,
--
Amirreza Zarrabi <amirreza.zarrabi(a)oss.qualcomm.com>
From: Jan Kiszka <jan.kiszka(a)siemens.com>
As seen with optee_ftpm, which uses ms-tpm-20-ref [1], a TPM may write
the current time epoch to its NV storage every 4 seconds if there are
commands sent to it. The 60 seconds periodic update of the entropy pool
that the hwrng kthread does triggers this, causing about 4 writes per
requests. Makes 2 millions per year for a 24/7 device, and that is a lot
for its backing NV storage.
It is therefore better to make the user intentionally enable this,
providing a chance to read the warning.
[1] https://github.com/Microsoft/ms-tpm-20-ref
Signed-off-by: Jan Kiszka <jan.kiszka(a)siemens.com>
---
drivers/char/tpm/Kconfig | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 8a8f692b6088..d64c929cacbe 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -45,13 +45,17 @@ config TCG_TPM2_HMAC
config HW_RANDOM_TPM
bool "TPM HW Random Number Generator support"
depends on TCG_TPM && HW_RANDOM && !(TCG_TPM=y && HW_RANDOM=m)
- default y
help
This setting exposes the TPM's Random Number Generator as a hwrng
device. This allows the kernel to collect randomness from the TPM at
boot, and provides the TPM randomines in /dev/hwrng.
- If unsure, say Y.
+ WARNING: Specifically firmware-based TPMs, possibly also hardware
+ variants, can wear-out from the frequent requests issued by the
+ Hardware Random Number Generator Core when filling the kernel's
+ entropy pool. These requests are sent once every minute by default,
+ and the TPM may write the current time to its NV storage for each of
+ them.
config TCG_TIS_CORE
tristate
--
2.51.0
Fix kernel-doc warnings so that there no other kernel-doc issues
in <uapi/linux/tee.h>:
- add ending ':' to some struct members as needed for kernel-doc
- change struct name in kernel-doc to match the actual struct name (2x)
- add a @params: kernel-doc entry multiple times
Warning: tee.h:265 struct member 'ret_origin' not described
in 'tee_ioctl_open_session_arg'
Warning: tee.h:265 struct member 'num_params' not described
in 'tee_ioctl_open_session_arg'
Warning: tee.h:265 struct member 'params' not described
in 'tee_ioctl_open_session_arg'
Warning: tee.h:351 struct member 'num_params' not described
in 'tee_iocl_supp_recv_arg'
Warning: tee.h:351 struct member 'params' not described
in 'tee_iocl_supp_recv_arg'
Warning: tee.h:372 struct member 'num_params' not described
in 'tee_iocl_supp_send_arg'
Warning: tee.h:372 struct member 'params' not described
in 'tee_iocl_supp_send_arg'
Warning: tee.h:298: expecting prototype for struct
tee_ioctl_invoke_func_arg. Prototype was for
struct tee_ioctl_invoke_arg instead
Warning: tee.h:473: expecting prototype for struct
tee_ioctl_invoke_func_arg. Prototype was for struct
tee_ioctl_object_invoke_arg instead
Signed-off-by: Randy Dunlap <rdunlap(a)infradead.org>
---
Cc: Jens Wiklander <jens.wiklander(a)linaro.org>
Cc: Sumit Garg <sumit.garg(a)kernel.org>
Cc: op-tee(a)lists.trustedfirmware.org
---
include/uapi/linux/tee.h | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
--- linux-next-20251022.orig/include/uapi/linux/tee.h
+++ linux-next-20251022/include/uapi/linux/tee.h
@@ -249,8 +249,9 @@ struct tee_ioctl_param {
* @cancel_id: [in] Cancellation id, a unique value to identify this request
* @session: [out] Session id
* @ret: [out] return value
- * @ret_origin [out] origin of the return value
- * @num_params [in] number of parameters following this struct
+ * @ret_origin: [out] origin of the return value
+ * @num_params: [in] number of &struct tee_ioctl_param entries in @params
+ * @params: array of ioctl parameters
*/
struct tee_ioctl_open_session_arg {
__u8 uuid[TEE_IOCTL_UUID_LEN];
@@ -276,14 +277,14 @@ struct tee_ioctl_open_session_arg {
struct tee_ioctl_buf_data)
/**
- * struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted
- * Application
+ * struct tee_ioctl_invoke_arg - Invokes a function in a Trusted Application
* @func: [in] Trusted Application function, specific to the TA
* @session: [in] Session id
* @cancel_id: [in] Cancellation id, a unique value to identify this request
* @ret: [out] return value
- * @ret_origin [out] origin of the return value
- * @num_params [in] number of parameters following this struct
+ * @ret_origin: [out] origin of the return value
+ * @num_params: [in] number of parameters following this struct
+ * @params: array of ioctl parameters
*/
struct tee_ioctl_invoke_arg {
__u32 func;
@@ -338,7 +339,8 @@ struct tee_ioctl_close_session_arg {
/**
* struct tee_iocl_supp_recv_arg - Receive a request for a supplicant function
* @func: [in] supplicant function
- * @num_params [in/out] number of parameters following this struct
+ * @num_params: [in/out] number of &struct tee_ioctl_param entries in @params
+ * @params: array of ioctl parameters
*
* @num_params is the number of params that tee-supplicant has room to
* receive when input, @num_params is the number of actual params
@@ -363,7 +365,8 @@ struct tee_iocl_supp_recv_arg {
/**
* struct tee_iocl_supp_send_arg - Send a response to a received request
* @ret: [out] return value
- * @num_params [in] number of parameters following this struct
+ * @num_params: [in] number of &struct tee_ioctl_param entries in @params
+ * @params: array of ioctl parameters
*/
struct tee_iocl_supp_send_arg {
__u32 ret;
@@ -454,11 +457,13 @@ struct tee_ioctl_shm_register_fd_data {
*/
/**
- * struct tee_ioctl_invoke_func_arg - Invokes an object in a Trusted Application
+ * struct tee_ioctl_object_invoke_arg - Invokes an object in a
+ * Trusted Application
* @id: [in] Object id
* @op: [in] Object operation, specific to the object
* @ret: [out] return value
* @num_params: [in] number of parameters following this struct
+ * @params: array of ioctl parameters
*/
struct tee_ioctl_object_invoke_arg {
__u64 id;
Hi,
Tomorrow, Tuesday, it's time for another LOC monthly meeting. For time
and connection details, see the calendar at
https://www.trustedfirmware.org/meetings/
- OP-TEE version 4.8.0 has been released
- We have an op-tee channel at the Trusted Firmware Discord server
[1]. Last week, there was a message about improving the order of all
the config options we have in OP-TEE, the CFG_* variables. In the long
term, we might still aim for Kconfig, but that's quite a large step.
However, there are intermediate steps that we can take. I hope we'll
see more of this.
Are there any other topics?
[1] https://www.trustedfirmware.org/faq/
Cheers,
Jens
FYI: QEMU model is working fine, upstreaming started, feedback welcome.
Jan
On 24.08.25 09:18, Jan Kiszka wrote:
> This closes an old gap in system integration testing for the very
> complex ARM firmware stacks by adding fairly advanced Replay Protected
> Memory Block (RPMB) emulation to the eMMC device model. Key programming
> and message authentication are working, so is the write counter. Known
> users are happy with the result. What is missing, but not only for RPMB-
> related registers, is state persistence across QEMU restarts. This is OK
> at this stage for most test scenarios, though, and could still be added
> later on.
>
> What can already be done with it is demonstrated in the WIP branch of
> isar-cip-core at [1]: TF-A + OP-TEE + StandaloneMM TA + fTPM TA, used by
> U-Boot and Linux for UEFI variable storage and TPM scenarios. If you
> want to try: build qemu-arm64 target for trixie with 6.12-cip *head*
> kernel, enable secure boot and disk encryption, then run
>
> $ QEMU_PATH=/path/to/qemu-build/ ./start-qemu.sh
>
> Deploy snakeoil keys into PK, KEK and db after first boot to enable
> secure booting:
>
> root@demo:~# cert-to-efi-sig-list PkKek-1-snakeoil.pem PK.esl
> root@demo:~# sign-efi-sig-list -k PkKek-1-snakeoil.key -c PkKek-1-snakeoil.pem PK PK.esl PK.auth
> root@demo:~# efi-updatevar -f PK.auth db
> root@demo:~# efi-updatevar -f PK.auth KEK
> root@demo:~# efi-updatevar -f PK.auth PK
>
> Note that emulation is a bit slow in general, and specifically the
> partition encryption on first boot is taking 20 min. - we should
> probably reduce its size or understand if there is still something to
> optimize.
>
> Jan
>
> [1] https://gitlab.com/cip-project/cip-core/isar-cip-core/-/commits/wip/qemu-rp…
>
> Cc: "Daniel P. Berrangé" <berrange(a)redhat.com>
>
> Jan Kiszka (8):
> hw/sd/sdcard: Fix size check for backing block image
> hw/sd/sdcard: Add validation for boot-partition-size
> hw/sd/sdcard: Allow user-instantiated eMMC
> hw/sd/sdcard: Refactor sd_bootpart_offset
> hw/sd/sdcard: Add basic support for RPMB partition
> crypto/hmac: Allow to build hmac over multiple
> qcrypto_gnutls_hmac_bytes[v] calls
> hw/sd/sdcard: Handle RPMB MAC field
> scripts: Add helper script to generate eMMC block device images
>
> crypto/hmac-gcrypt.c | 4 +-
> crypto/hmac-glib.c | 4 +-
> crypto/hmac-gnutls.c | 4 +-
> crypto/hmac-nettle.c | 4 +-
> hw/sd/sd.c | 314 ++++++++++++++++++++++++++++++++++++++---
> hw/sd/sdmmc-internal.h | 24 +++-
> hw/sd/trace-events | 2 +
> include/crypto/hmac.h | 12 ++
> scripts/mkemmc.sh | 185 ++++++++++++++++++++++++
> 9 files changed, 530 insertions(+), 23 deletions(-)
> create mode 100755 scripts/mkemmc.sh
>
--
Siemens AG, Foundational Technologies
Linux Expert Center