* This blog post is an English translation of an article originally published in Japanese on February 20, 2024.
This article does not cover the fundamental knowledge of TEE (Trusted Execution Environment). However, prior research on terms like “TEE” and “TrustZone TEE” will aid in understanding the article’s content.
A TEE (Trusted Execution Environment) is a feature enabling the secure execution of programs (TA: Trusted Application) in an environment isolated at the SoC level. Application examples include offloading confidential computations, managing keys for encryption/decryption, and secure drivers.
Currently, there are three types of HW functions that can realize a TEE:
- Intel SGX
A feature available on some Intel CPUs, where one TA generally launches one Enclave. If multiple TAs are launched, they each use separate Enclaves.
Most functionalities are fixed as HW and SDK provided by Intel. - ARM TrustZone
A feature available on many ARM CPUs (mainly Cortex-A series), where a single Secure World is launched for the entire SoC. If multiple TAs are launched, all programs run within this single Secure World.
Only the base HW functionality is provided by ARM, and the actual TrustZone control is user-dependent. - RISC-V PMP
A feature available on RISC-V CPUs.
Only the base HW functionality is defined in the RISC-V ISA, and it can be controlled by an OSS called Keystone. Keystone, like SGX, uses an Enclave-based approach.
Implementations of ARM TrustZone control are provided by various companies. Some examples include:
- OP-TEE
- Provider: TrustedFirmware.org
- Provisioning Form: Open Source
- Operating Environment: Primarily SoCs with Cortex-A cores (including Raspberry Pi and Xilinx FPGAs). List
- Trusty
- Provider: Google (Android Open Source Project)
- Provisioning Form: Open Source
- Supported Environment: arm64 boards (details vary, but can also run on x86 processors).
- QSEE/QTEE
- Provider: Qualcomm
- Provisioning Form: Closed Source
- Supported Environment: Qualcomm boards.
- Kinibi
- Provider: Trustonic
- Provisioning Form: Closed Source
- Supported Environment: Cortex-A boards, Cortex-M boards.
This article focuses on Trustonic’s Kinibi among these.
Kinibi Overview
Kinibi is an implementation of TrustZone control provided by Trustonic. It has the following features and can be used as an alternative to PKCS#11, EVITA HSM, and AutoSAR crypto APIs:
- Basic functions such as TA scheduling, I/O management, and memory management.
- In-TA execution functions for various encryption/decryption and hashing operations.
- SDK for TA development.
- Support for QEMU emulation.
- Certifications such as EAL5+, ISO27001, FIPS140-2 (https://www.trustonic.com/certifications/).
This time, we will introduce Kinibi from its startup to TA execution.
Kinibi Boot Flow
Kinibi is launched following the SecureBoot flow. SecureBoot is a process where a BootLoader verifies the safety of the next BootLoader to be executed using a Signature before launching it. SecureBoot ensures that the Kinibi program itself has not been tampered with. The ARM Cortex-A boot flow is divided into three stages: BL1, BL2, and BL3 (BL31, BL32, BL33).
- BL1 is minimal startup code that boots from ROM and, after verifying BL2, launches it.
- BL2 uses firmware provided by the SoC vendor to perform SoC initialization. During SoC initialization, the hardware-implemented TrustZone Protection Controller (TZPC) is used to separate the address spaces of the Secure World and Normal World.
- Afterward, BL2 verifies and launches BL31, BL32, and BL33.
- BL31 is firmware that runs at ARM EL3 and includes Kinibi’s Secure Monitor.
- BL32 is a Trusted OS that runs in the ARM EL1 Secure World and includes Kinibi TAs.
- BL33 is a regular OS (Linux, etc.) that runs in the ARM EL1 Normal World.

Kinibi SW/HW Stack
Kinibi’s programs are divided into TAs (Trusted Applications) in the SWd (Secure World) and CAs (Client Applications) in the NWd (Normal World). The CA invokes TA processing by issuing a Secure Monitor Call (SMC) instruction to the TA. The SMC is issued via EL1 (Kernel) and processed at EL3 (Secure Monitor). World switching (SWd <=> NWd) always goes through EL3; a CPU operating at EL1 (NWd) cannot directly transition to EL1 (SWd). Data is exchanged via Shared Memory (Buffer#1… in the diagram) allocated in NWd Memory (Normal Memory). (Basically, one buffer is used per argument). Commands and arguments when a CA calls a TA are stored in NWd Memory, which the TA in SWd references. TA data is stored in SWd Memory (Secure Memory) and copied to Shared Memory as needed to be returned to the CA.

Kinibi Startup to Shutdown
To execute a TA in SWd, commands are executed in the following flow, originating from the CA in NWd.
List of APIs Used Below
Function | API | Signature | Overview |
Initialization | TEEC_InitializeContext | TEEC_Result TEEC_InitializeContext(const char* name, TEEC_Context* context) | Acquires (initializes) the context necessary for TEE execution. At the end of this API call, the TA has not yet been launched. |
Open Session | TEEC_OpenSession | TEEC_Result TEEC_OpenSession (TEEC_Context* context, TEEC_Session* session, const TEEC_UUID* destination, uint32_t connectionMethod, const void* connectionData, TEEC_Operation* operation, uint32_t* returnOrigin) | Launches and initializes a TA and associates it with the calling CA. Subsequently, the launched TA can be called by specifying the TEEC_Session . |
Allocate Memory | TEEC_AllocateSharedMemory | TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context* context, TEEC_SharedMemory* sharedMem) | Allocates a buffer used for data exchange between SWd/NWd and associates it with the context. |
Invoke Command | TEEC_InvokeCommand | TEEC_Result TEEC_InvokeCommand(TEEC_Session* session, uint32_t commandID, TEEC_Operation* operation, uint32_t* returnOrigin) | Invokes a process of the TA specified by TEEC_Session . Arguments are passed via TEEC_Session . |
Release Memory | TEEC_ReleaseSharedMemory | void TEEC_ReleaseSharedMemory (TEEC_SharedMemory* sharedMem) | Releases the buffer allocated by TEEC_AllocateSharedMemory . |
Close Session | TEEC_CloseSession | void TEEC_CloseSession (TEEC_Session* session) | Terminates the session obtained by TEEC_OpenSession and unloads the TA. |
Finalize | TEEC_FinalizeContext | void TEEC_FinalizeContext(TEEC_Context* context) | Terminates the context obtained by TEEC_InitializeContext and performs cleanup. |
1. Initialization
API used: TEEC_InitializeContext
Before starting a TA, the TEE execution environment is checked, and the execution context TEEC_Context
is initialized. Specifically, the type of TEE available, driver versions, etc., are confirmed. The reason for checking the version is that older-than-expected versions may contain residual bugs.
2. Open Session
API used: TEEC_OpenSession
The TA is loaded and associated with a logical container, TEEC_Session
. During this process, the TA is loaded into Secure Memory and initialized. Subsequently, the launched TA is specified by TEEC_Session
.
3. Allocate Memory Region
API used: TEEC_AllocateSharedMemory
Since the CA and TA do not share stacks or heaps (similar to inter-process communication), data exchange is performed via Normal Memory. Basically, one buffer is allocated for each argument used in the call. The allocated buffer is associated with TEEC_Context
.
4. Invoke Command
API used: TEEC_InvokeCommand
To call TA processing from the CA, the TEEC_InvokeCommand
API is used. After storing arguments in the region allocated by TEEC_AllocateSharedMemory
, the TA process ID is specified to invoke it. This ID specifies the process to call (≒ the function within the TA to execute). It should be unique within the TA, but as long as the value is shared between CA/TA, there are no major restrictions. The CA → TA execution transition is realized by the SMC
instruction. When the TA finishes the specified process, it returns processing to the CA using an ERET
instruction. Since SMC is a synchronous exception, once processing transfers to the TA, it will not return to the CA until the TA’s processing is complete.
5. Release Memory Region
API used: TEEC_ReleaseSharedMemory
The region allocated by TEEC_AllocateSharedMemory
is released after use with TEEC_ReleaseSharedMemory
.
6. Close Session
API used: TEEC_CloseSession
The TEEC_Session
started by TEEC_OpenSession
is destroyed. During this process, the TA associated with TEEC_Session
executes its termination procedures and is unloaded.
7. Finalize
API used: TEEC_FinalizeContext
The execution context TEEC_Context
created by TEEC_InitializeContext
is terminated and destroyed.
Summary
The above was an overview of the Kinibi operational flow. Although there are some differences, other TrustZone control implementations (OP-TEE, etc.) generally operate with a similar flow. When actually using it, since multiple exception level switches (≒ context switches) are involved, the balance between security strength and execution overhead becomes important.