Add support for HWKM v1 based In-line Crypto Engine - #42
Harshal Dev (harshaldev27) wants to merge 29 commits into
Conversation
845359e to
8b15785
Compare
3e6ccd6 to
204d614
Compare
ca169e2 to
1a117cb
Compare
…files Nord was the only Wildcat chip in the tree, so its GIC base addresses and DARE-TZ TZDRAM region settings were placed in the shared Wildcat architecture layer. Adding a second Wildcat chip with different addresses makes the architecture layer the wrong home for them. Move GICD_BASE and GICR_BASE from arch_config.h to nord/target_config.h, and move the DARE-TZ TZDRAM region configuration from qcom-arch.mk to nord/target.mk, so the shared Wildcat layer stays chip-agnostic. Add SPDX licence identifier to qcom-arch.mk while there. Signed-off-by: Pawan Rai <pawarai@qti.qualcomm.com> Reviewed-by: Harshal Dev <harshal.dev@oss.qualcomm.com> Tested-by: Harshal Dev <harshal.dev@oss.qualcomm.com> Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
Cacao is a Qualcomm XR chipset in the Wildcat architecture family, featuring an octa-core Oryon CPU, a GICv4 interrupt controller, and DARE-TZ in-line memory encryption managed by the TME root-of-trust. OP-TEE runs in a DARE-TZ protected DRAM region and does not need a separate DARE driver. Testing: Tested on Rumi. Signed-off-by: Pawan Rai <pawarai@qti.qualcomm.com> Reviewed-by: Harshal Dev <harshal.dev@oss.qualcomm.com> Tested-by: Harshal Dev <harshal.dev@oss.qualcomm.com> Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
Add PLATFORM=qcom-cacao build to the CI. Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> Signed-off-by: Pawan Rai <pawarai@qti.qualcomm.com>
Shikra is a Qualcomm IoT chipset in the Bruin architecture family, featuring a quad-core Cortex-A55 CPU and a GICv3 interrupt controller. Tested optee boot-up on Shikra board. Signed-off-by: Pawan Rai <pawarai@qti.qualcomm.com> Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> Reviewed-by: Harshal Dev <harshal.dev@oss.qualcomm.com> Tested-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Add PLATFORM=qcom-shikra build to the CI. Signed-off-by: Pawan Rai <pawarai@qti.qualcomm.com> Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
1a117cb to
dab3efd
Compare
Fix the address mappings for DRAM on Nord IQ-10. DRAM0 has a size of 0x8000 0000 while DRAM1 starts at 0x8 8000 0000 with a size of 0x7 8000 0000. Also, there exists a DRAM2 region which the Linux kernel maps as HIGHMEM for allocating memory for userspace applications. Since this region starting at 0x88 0000 0000 is not mapped by OP-TEE, TEE_IOC_SHM_REGISTER ioctl fails because OP-TEE doesn't recognize it as Non-secure memory. Validated by running xtest 1002 after building OP-TEE with CFG_TEE_CORE_EMBED_INTERNAL_TESTS=y which was failing otherwise. Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Add a pseudo-TA for the Qualcomm Inline Crypto Engine (ICE) that lets the
kernel dm-crypt/inline-crypt path program raw software keys into ICE key
slots for inline storage encryption.
Two commands are exposed:
- PTA_CMD_ICE_INVALIDATE_KEY: wipe a key slot with random data.
- PTA_CMD_ICE_SET_CONFIG_KEY: program key/salt, cipher mode and
data-unit size for AES-XTS-128/256 and AES-CBC-128/256.
Only the REE kernel may open a session on this PTA. The PTA is gated by
CFG_ICE_FS_ENC_PTA and is not built unless a platform enables it.
Signed-off-by: Harikrishna <hart@qti.qualcomm.com>
Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
Reviewed-by: Selvam Sathappan Periakaruppan <speriaka@qti.qualcomm.com>
Reviewed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Turn on CFG_ICE_FS_ENC_PTA for ipq52xx and ipq96xx, which carry the SDCC ICE block used for eMMC inline encryption, and point the generic ICE_LUT_KEYS at the SDCC LUT-keys register region. Testing: Booted to the kernel, dispatched an ICE software-key config from the kernel to this PTA, then wrote and read back a file on the encrypted filesystem and confirmed matching md5sums. Tested-on: IPQ52xx, IPQ96xx Signed-off-by: Harikrishna <hart@qti.qualcomm.com> Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> Reviewed-by: Selvam Sathappan Periakaruppan <speriaka@qti.qualcomm.com> Reviewed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
This file already lives under drivers/clk/qcom/, so repeating qcom in its own name is redundant, and inconsistent with how other vendor subdirectories (sam/, stm32) name their own files. Signed-off-by: Naresh Nunna <nnunna@qti.qualcomm.com> Assisted-by: Claude:opus-5 Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> Reviewed-by: Selvam Sathappan Periakaruppan <speriaka@qti.qualcomm.com> Reviewed-by: Vinod Kumar Amanaganti <vinoda@qti.qualcomm.com>
The QUP SE clock driver's CX/MX voltage vote needs a rail's supported corner ordinals, which for ARC resources live in the auxiliary data blob RPMh commands index into rather than a raw voltage. Add cmd_db_get_aux() to fetch it by resource ID. Signed-off-by: Naresh Nunna <nnunna@qti.qualcomm.com> Assisted-by: Claude:opus-5 Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> Reviewed-by: Selvam Sathappan Periakaruppan <speriaka@qti.qualcomm.com> Reviewed-by: Vinod Kumar Amanaganti <vinoda@qti.qualcomm.com>
Some clock rates need a higher CX/MX voltage corner than others, and a corner may be shared by multiple RCGs; rail_vote() refcounts per corner over RPMh so each rail is only raised for as long as some caller actually needs it, and CX/MX are resolved independently since they don't necessarily share the same hlvl encoding. Signed-off-by: Naresh Nunna <nnunna@qti.qualcomm.com> Assisted-by: Claude:opus-5 Assisted-by: Claude:sonnet-5 Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> Reviewed-by: Selvam Sathappan Periakaruppan <speriaka@qti.qualcomm.com> Reviewed-by: Vinod Kumar Amanaganti <vinoda@qti.qualcomm.com>
Lemans has no secure DT, so register each QUPv3 SE clock as a plain struct clk, modeling the PLL/RCG/branch as separate objects so the generic framework's own refcounting governs each PLL vote. Signed-off-by: Naresh Nunna <nnunna@qti.qualcomm.com> Assisted-by: Claude:opus-5 Assisted-by: Claude:sonnet-5 Reviewed-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com> Reviewed-by: Selvam Sathappan Periakaruppan <speriaka@qti.qualcomm.com> Reviewed-by: Vinod Kumar Amanaganti <vinoda@qti.qualcomm.com>
The RPMh command MSGID encodes a MSG_LENGTH field describing the payload length, in bytes, of the command. This field was hardcoded to 1 which is leading to unpredictable behavior on the AOP side (including the command never being acknowledged, causing timeouts). Changing it to 8 (the correct length for the single 32-bit data word every RPMh command carries). Using MSGID_WRITE since it's a write command. Fixes: b6ff325 (drivers: qcom: rpmh: add RPMH client driver) Signed-off-by: Shivam Sanjay <shivsanj@qti.qualcomm.com> Reviewed-by: Dinesh Choudhary <idinesh@qti.qualcomm.com> Reviewed-by: Selvam Sathappan Periakaruppan <speriaka@qti.qualcomm.com>
Add PAS support for the ipq96xx CDSP (Turing/NSP) remote processor: load the firmware and its DTB, program the QDSP6 boot registers, run the two-stage boot FSM, and handle shutdown/reset via GCC. Also adds the Turing clock bring-up. ipq96xx gates these windows to secure-only accesses via XPU, so a new qcom_pas_data::secure flag maps them MEM_AREA_IO_SEC instead of MEM_AREA_IO_NSEC; other platforms are unaffected. Testing: Built for PLATFORM_FLAVOR=ipq96xx and kodiak with aarch64-linux-gnu-. CDSP boot verified on ipq96xx hardware. Signed-off-by: Harikrishna <hart@qti.qualcomm.com>
Enable the PAS PTA and Qualcomm clock driver on ipq96xx, add the CDSP (Turing/NSP) register window bases (Turing, GCC, MPM2, TCSR), and register the PAS pseudo TA as an in-tree early TA. Testing: Built for PLATFORM_FLAVOR=ipq96xx with aarch64-linux-gnu-; the CDSP PAS and clock objects link into the image and the PAS early TA is signed. Signed-off-by: Harikrishna <hart@qti.qualcomm.com>
Move the HWKM implementation, HUK support, transaction layer, and private headers under qcom/hwkm. Keep qcom as the umbrella for independent Qualcomm crypto IP blocks. No functional change. Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
…nces Change all register offsets in hwkm_regs.h to group-relative and add HWKM_MASTER_*_REGS_OFFSET and HWKM_CRYPTO0_*_REGS_OFFSET constants to locate each register group within its instance's MMIO window. Callers add the appropriate offset at the call site, making the same register definitions reusable across the master and any slave. Also extract run_fifo_transaction() from master_run_transaction() so the FIFO protocol can be reused by any slave. Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
Enable the CRYPTO0 general-purpose crypto engine (GPCE) key-manager slave so that keys can be provisioned into CRYPTO0 key slots using the existing HWKM transaction protocol. Map the CRYPTO0 MMIO window, configure the key-manager slave at boot, and extend the transaction layer to dispatch to the GPCE slave alongside the existing HWKM master. Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
ce0f312 to
6ed3b77
Compare
|
Harshal Dev (@harshaldev27) can you rather only pick HWKM patches from Amirreza Zarrabi (@qc-azarrabi) PR which the ICE feature depends upon? This can untangle GPCE and ICE PRs. |
Add support for generating the SWAP and TPKEY during driver init. The TPKEY is used to wrap keys before transporting them to the HWMK slaves, such as the General Purpose Crypto Engine (GPCE) and the Inline Crypto Engine (ICE). The SWAP key is used for wrapping and exporting keys from the hardware key manager to software. Assisted-by: Codex:gpt-5.3-codex Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Add support for the Inline Crypto Engine (ICE) slave to the hardware key manager (HWKM). This allows HWKM to issue commands to ICE and provision keys via its existing transaction protocol. Since the clock and power for ICE are controlled by Linux, it must be (re)configured before dispatching any transactions to it. Assisted-by: Codex:gpt-5.3-codex Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Export the interface to the Qualcomm hardware key manager (HWKM) drivers by moving the hwkm.h and hwkm_errno.h files to include/drivers/ path. Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Add a pseudo-TA for the Qualcomm Inline Crypto Engine (ICE) that lets the kernel inline-crypt path generate a wrapped L4 key derived from the unique key derivation key (UKDK) available with the Hardware Key manager for inline storage encryption. Only the REE kernel may open a session on this PTA. The PTA is gated by CFG_ICE_FS_ENC_PTA and is not built unless a platform enables it. Assisted-by: Codex:gpt-5.3-codex Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Add support for importing and wrapping a key with a UKDK-derived L4 key. The wrapped key is returned to the REE which can use it as a storage key. Assisted-by: Codex:gpt-5.3-codex Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Add support for exporting a key after un-wrapping it with a UKDK-derived L4 key and re-wrapping with an ephemeral key (also a HW derived UKDK L4 key). This ties the storage key with a per boot generated random seed. Assisted-by: Codex:gpt-5.3-codex Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
6ed3b77 to
a8f077d
Compare
Done, only 3 commits from his PR related to HWKM re-factoring and GPCE slave addition are now kept. |
Add support for programming an ephemerally wrapped key into a specified inline crypto engine (ICE) key slot. The key is first unwrapped via the ephemeral key, and then wrapped by a TP (transport) key before being imported into the ICE hardware block via the hardware key manager. Assisted-by: Codex:gpt-5.3-codex Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Add support for invalidating a previously programmed key from the inline crypto engine's (ICE) key slot via the hardware key manager. Assisted-by: Codex:gpt-5.3-codex Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Add support for deriving a software secret from the ephemerally wrapped key. The key is unwrapped via HWKM and a CMAC operation is performed on it to generate and return a raw secret to the REE. Assisted-by: Codex:gpt-5.3-codex Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
a8f077d to
5737faf
Compare
Allow informing the client whether wrapped key usage is supported based on initialization state of the Hardware Key manager driver. This enables the client to fallback to legacy mode of operation for ICE when Hardware Key manager driver is not supported for a particular chipset. Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Enable the in-line crypto engine Psuedo TA for Lemans to allow encryption of storage contents with key programming done via the Hardware key manager. Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
5737faf to
29fc287
Compare
|
Sumit Garg (@b49020) , End-to-End validation using the fscryptctl tool is done using the Linux patch series staged at: https://github.com/harshaldev27/kernel-topics/tree/ice-migrate-tee-svc Please find the logs: Legacy mode operation for ICE using raw keys Standard mode operation for ICE using wrapped keys generated via HWKM: |
|
Thanks Harshal Dev (@harshaldev27) for the heads up, really nice to see this feature come together with OP-TEE support. Feel free to post the kernel patch-set upstream for review. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The wrapped-key ABI, concurrency handling, platform build guards, invalidation behavior, and HWKM failure cleanup contain blocking correctness and security issues.
Review effort: Balanced
Findings: 5
Open (8)
Reject HWKM initialization when BIST reports errors · New Disable TPKEY receive window after timeout · New Serialize PTA ICE operations with the HWKM mutex · New Track per-slot key backend during ICE key invalidation · New Gate HWKM sources and dispatch paths on CFG_QCOM_HWKM · New Clean up GP2 and wrap slots after KDF failures · New Clear GP2 and wrap slots on L3/L4 failure · New Support both documented raw and wrapped key parameter formats · New
What changed in this PR
Adds HWKM v1 hardware-wrapped key support to the Qualcomm ICE PTA while retaining software-key operation.
Changes:
- Adds wrapped-key generation, import, export, programming, and secret derivation commands.
- Extends HWKM transactions to GPCE and ICE slaves.
- Enables ICE/HWKM support on LeMans.
| File | Description |
|---|---|
lib/libutee/include/pta_qcom_ice.h |
Defines wrapped-key PTA commands and ABI. |
core/pta/qcom/ice/sw_keys/ice_sw_keys.h |
Updates software invalidation interface. |
core/pta/qcom/ice/sw_keys/ice_sw_keys.c |
Moves parameter validation to the dispatcher. |
core/pta/qcom/ice/sub.mk |
Adds the HWKM PTA subtree. |
core/pta/qcom/ice/ice.c |
Dispatches software and HWKM ICE operations. |
core/pta/qcom/ice/hwkm/sub.mk |
Builds HWKM ICE helpers. |
core/pta/qcom/ice/hwkm/ice_hwkm.h |
Declares HWKM ICE operations. |
core/pta/qcom/ice/hwkm/ice_hwkm.c |
Implements wrapped-key and ICE programming flows. |
core/pta/qcom/ice/hwkm/hwkm_derive_keys.h |
Declares wrapping-key derivation helpers. |
core/pta/qcom/ice/hwkm/hwkm_derive_keys.c |
Implements L4 and ephemeral key derivation. |
core/include/drivers/hwkm.h |
Adds slave destinations and MMIO contexts. |
core/include/drivers/hwkm_errno.h |
Defines HWKM response errors. |
core/drivers/crypto/qcom/sub.mk |
Moves HWKM into a conditional subtree. |
core/drivers/crypto/qcom/hwkm/transaction.c |
Supports destination-specific HWKM FIFOs. |
core/drivers/crypto/qcom/hwkm/sub.mk |
Defines HWKM driver sources and configuration. |
core/drivers/crypto/qcom/hwkm/include/hwkm_regs.h |
Adds relative register maps for HWKM instances. |
core/drivers/crypto/qcom/hwkm/include/hwkm_ice.h |
Declares ICE HWKM configuration. |
core/drivers/crypto/qcom/hwkm/ice.c |
Implements ICE initialization and TPKEY handoff. |
core/drivers/crypto/qcom/hwkm/hwkm.c |
Initializes slaves and generates TP/SWAP keys. |
core/drivers/crypto/qcom/hwkm/huk.c |
Updates public HWKM includes. |
core/arch/arm/plat-qcom/hoya/lemans/target.mk |
Enables UFS ICE PTA support. |
core/arch/arm/plat-qcom/hoya/lemans/target_config.h |
Selects UFS or eMMC ICE mappings. |
core/arch/arm/plat-qcom/hoya/arch_config.h |
Defines HWKM and ICE physical regions. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| for (i = 0; i < ARRAY_SIZE(done_bits); i++) { | ||
| rc = ice_wait_init_done(base + HWKM_ICE_TZ_REGS_OFFSET, | ||
| HWKM_TZ_KM_STATUS, done_bits[i]); | ||
| if (rc) | ||
| return rc; | ||
| } | ||
|
|
||
| return rc; |
| if (rc) | ||
| return rc; | ||
|
|
||
| io_write32_off_field(base + HWKM_ICE_TZ_REGS_OFFSET, | ||
| HWKM_TZ_TPKEY_RECEIVE_CTL, | ||
| HWKM_TZ_TPKEY_RECEIVE_CTL_EN, 0); | ||
|
|
||
| return HWKM_SUCCESS; |
| if (!g_ephemeral_ctx_set) { | ||
| if (crypto_rng_read(g_ephemeral_ctx, | ||
| sizeof(g_ephemeral_ctx)) != TEE_SUCCESS) | ||
| return TEE_ERROR_GENERIC; | ||
|
|
||
| g_ephemeral_ctx_set = true; |
| ctx = hwkm_get_context(); | ||
| if (!ctx) | ||
| return sw_cmd_ice_invalidate_key(params); | ||
|
|
||
| return clear_ice_slave_slot_hwkm(params[0].value.a); |
| srcs-y += ice.c | ||
| incdirs-y += . | ||
| subdirs-y += sw_keys | ||
| subdirs-y += hwkm |
| if (t_kdf_eph_l3.rsp.status != HWKM_RSP_ERR_SUCCESS || | ||
| t_kdf_eph_l4.rsp.status != HWKM_RSP_ERR_SUCCESS) { | ||
| EMSG("ICE eph-kdf: l3=0x%x l4=0x%x", | ||
| (unsigned int)t_kdf_eph_l3.rsp.status, | ||
| (unsigned int)t_kdf_eph_l4.rsp.status); | ||
| res = TEE_ERROR_GENERIC; | ||
| goto out; |
| if (t_kdf_l3.rsp.status != HWKM_RSP_ERR_SUCCESS || | ||
| t_kdf_l4.rsp.status != HWKM_RSP_ERR_SUCCESS) { | ||
| EMSG("ICE derive L4: l3=0x%x l4=0x%x", | ||
| (unsigned int)t_kdf_l3.rsp.status, | ||
| (unsigned int)t_kdf_l4.rsp.status); | ||
| return TEE_ERROR_GENERIC; |
| const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, | ||
| TEE_PARAM_TYPE_VALUE_INPUT, | ||
| TEE_PARAM_TYPE_MEMREF_INPUT, | ||
| TEE_PARAM_TYPE_NONE); | ||
|
|
||
| if (param_types != exp_pt) | ||
| return TEE_ERROR_BAD_PARAMETERS; | ||
|
|
||
| key_len = params[2].memref.size; | ||
| if (key_len != HWKM_MAX_BLOB_SIZE) | ||
| return sw_cmd_ice_set_config_key(param_types, params); | ||
|
|
||
| slot = params[0].value.a; | ||
| key_buf = params[2].memref.buffer; | ||
| if (!key_buf) | ||
| return TEE_ERROR_BAD_PARAMETERS; | ||
|
|
||
| return set_config_ice_key_using_hwkm(slot, key_buf, | ||
| key_len); |
5fde2c5 to
9b756a1
Compare


All Qualcomm SoCs support an In-line Crypto Engine (ICE) hardware block within either the UFS or eMMC storage controller. When storage data moves through the ICE it encrypts or decrypts it using a key programmed within its slot. This patch series introduces a Pseudo-TA for the ICE that allows the Linux side ICE driver [1] to generate a key for ICE programming via version 1 of the Hardware Key Manager (HWKM) and program it within one of its slots to enable storage encryption and decryption.
The storage key is either generated by HWKM (recommended) or imported within one of its slots via Linux. Once the storage key is available within a HWKM slot, the HWKM can directly push it into an ICE key slot after wrapping it via a Transport key (TPKEY). This ensures that the key is only ever visible to trusted software (OP-TEE) or hardware (HWKM/ICE).
Linux always obtains the storage key in a wrapped blob format, ensuring that it never leaves the trust boundary. For the purpose of wrapping the storage key, a hardware derived L4 key is used, which is derived from a per-chip unique derivation key (UKDK L4 key) available within the HWKM. When the L4 key derivation process mixes a per-boot random ephemeral seed, the returned wrapped storage key is called an ephemeral key and cannot be used across device reboots. This provides an additional layer of security by tying the wrapped blob to the current device boot session.
Outline of this patch series:
Dependencies
This PR depends on PR #52 and will be re-based once merged. This dependency is with respect to boiler plate code added in this PR for extending the HWKM slave support via GPCE. This PR is already reviewed in #28.
Validation:
The Linux side patches used for End-to-End validation of this series is staged at [2] until the qcom-next PR is merged. A Unit test client is also available at [3]. The Unit test driver [3] was used to generate a hardware wrapped key, wrap it via an ephemeral key and then program it into the ICE key slot 10. Afterwards, the slot was also cleared using the same test driver. The Linux fscrypt framework [4] calls the ICE commands in the same sequence when using hardware-wrapped keys.
CMD 1: Generate a HW wrapped key.
CMD 2: Prepare the HW wrapped key via wrapping via epehemeral key.
CMD 3: Import a raw key into the HWKM slot.
CMD 4: Program the key into ICE slot 10.
CMD 5: Clear the key from ICE slot 10.
CMD 6: Use the HW wrapped key to generate a software secret.
References:
[1] https://elixir.bootlin.com/linux/v7.2-rc7/source/drivers/soc/qcom/ice.c
[2] https://github.com/harshaldev27/kernel-topics/tree/ice-migrate-tee-svc
[2] https://github.com/harshaldev27/kernel-topics/tree/ice-pta-test-driver
[4] https://www.kernel.org/doc/html/latest/filesystems/fscrypt.html