| 187 | == Trusted Execution Environment (TEE) |
| 188 | The Trusted Execution Environment (TEE) is a set of specifications published by the [http://www.globalplatform.org GlobalPlatform association]. The purpose of the TEE is to provide a safe environment within the application processor for developing and executing secure applications. We call an application processor a system running a Rich OS like Android or Linux. A Rich environment represents a huge amount of code. It is open to third-party applications and it is an open ecosystem: it makes a Rich OS hard to audit. It is prone to bugs/vulnerability, which may compromise the security and integrity of the entire system. The TEE offers another level of protection against attacks from the rich OS. The TEE is only open to trusted partners, which makes it easier to audit. It executes only trusted and authorized software. All sensitive data are protected from the rest of the application processor and from the outside world. |
| 189 | |
| 190 | Many modern devices make use of a Trusted Execution Environment, including smartphones, set-top-boxes, game consoles and Smart TVs. Some example use cases of a TEE: |
| 191 | - biometric authentication (ie facial, fingerprint, voice recognition) code and sensitive data |
| 192 | - e-commerce digital wallet code and sensitive data |
| 193 | - DRM credentials |
| 194 | |
| 195 | [=#optee] |
| 196 | === Open Portable Trusted Execution Environment (OP-TEE) |
| 197 | OP-TEE (Open Portable Trusted Execution Environment) is an open-source TEE designed as a companion to a non-secure Linux kernel running on ARM Cortex-A cores using ARM's !TrustZone technology. |
| 198 | |
| 199 | The TEE relies on the Arm !TrustZone technology. The !TrustZone is a system-on-chip security feature available on most Arm Cortex A/M processors. It provides a strict hardware isolation between the secure world (TEE) and the normal world (REE). This technology allows each physical processor core to provide two virtual cores: one for the normal world and one for the secure world. |
| 200 | |
| 201 | OP-TEE is an open source stack of the Trusted Execution Environment which includes: |
| 202 | * OP-TEE OS: Trusted side of the TEE |
| 203 | * OP-TEE Client: Normal world client side of the TEE |
| 204 | * OP-TEE Test (or xtest): OP-TEE Test Suite |
| 205 | |
| 206 | The OP-TEE project is developed and maintained by Linaro under BSD 2-Clause. The source code is available at https:// github.com/OP-TEE. This stack supports Arm-v7 and Arm-v8 architectures. |
| 207 | |
| 208 | The TEE exposes its features through a tandem operation between a Client Application and a Trusted Application. The client application runs in the Rich OS and always initiates the communication with the Trusted Application that runs in the Trusted OS. The Client application interacts with the TEE through the TEE client API interface. The Secure Application interacts with the TEE Core through the TEE Internal API. |
| 209 | |
| 210 | OP-TEE is a Trusted Execution Environment (TEE) designed as a companion to a non-secure Linux kernel running on Arm cores using the TrustZone technology. OP-TEE implements [https://optee.readthedocs.io/en/latest/architecture/globalplatform_api.html#tee-internal-core-api TEE Internal Core API v1.1.x] which is the API exposed to Trusted Applications and the [https://optee.readthedocs.io/en/latest/architecture/globalplatform_api.html#tee-client-api TEE Client API v1.0], which is the API describing how to communicate with a TEE. Those APIs are defined in the [https://optee.readthedocs.io/en/latest/architecture/globalplatform_api.html#globalplatform-api GlobalPlatform API] specifications. |
| 211 | |
| 212 | The non-secure OS is referred to as the Rich Execution Environment (REE) in TEE specifications. It is typically a Linux OS flavor as a GNU/Linux distribution or the AOSP. |
| 213 | |
| 214 | OP-TEE is designed primarily to rely on the Arm TrustZone technology as the underlying hardware isolation mechanism. However, it has been structured to be compatible with any isolation technology suitable for the TEE concept and goals, such as running as a virtual machine or on a dedicated CPU. |
| 215 | |
| 216 | The main design goals for OP-TEE are: |
| 217 | * Isolation - the TEE provides isolation from the non-secure OS and protects the loaded Trusted Applications (TAs) from each other using underlying hardware support, |
| 218 | * Small footprint - the TEE should remain small enough to reside in a reasonable amount of on-chip memory as found on Arm based systems, |
| 219 | * Portability - the TEE aims at being easily pluggable to different architectures and available HW and has to support various setups such as multiple client OSes or multiple TEEs. |
| 220 | |
| 221 | For more info: |
| 222 | - see - see http://optee.readthedocs.io |
| 223 | - https://www.nxp.com/docs/en/user-guide/IMX_PORTING_GUIDE.pdf |
| 224 | |
| 225 | === OP-TEE on venice |
| 226 | In general the following things need to be done to use OP-TEE in the 'SPL -> ATF -> OP-TEE -> U-Boot -> Linux' boot flow: |
| 227 | * build ATF (bl31.bin) with OP-TEE support: |
| 228 | - Add 'SPD=opteed' to the env to use a Secure Payload Dispatcher (SPD) |
| 229 | - Add 'BL32_BASE=' to the env to tell the ATF (BL31) where TEE is in memory (BL32) |
| 230 | * build TEE (tee.bin): |
| 231 | - PLATFORM=imx |
| 232 | - PLATFORM_FLAVOR=mx8mmevk|mx8mnevk|mv8mpevk - Use one of these depending on which SOC (imx8mm/imx8mn/imx8mp) you are using. These define CFG_UART_BASE and some memory config which we will override to suit our needs |
| 233 | - CFG_DDR_SIZE= - Specify the DRAM size of the board you are building for. For example 1GiB=0x40000000, 2GiB=0x80000000, 4GiB=0x10000000 |
| 234 | - CFG_CORE_LARGE_PHYS_ADDR= - n for 3GiB or less DRAM, and y for larger than 3GiB DRAM |
| 235 | - CFG_CORE_ARM64_PA_BITS= - 32 for 3GiB or less DRAM, and 36 for larger than 3GiB DRAM |
| 236 | - CFG_TZDRAM_START= - the (link/load) address where TEE should run at |
| 237 | * build u-Boot with the following configuration: |
| 238 | - CONFIG_IMX_HAB=y |
| 239 | - CONFIG_CMD_DEKBLOB=y |
| 240 | - CONFIG_SPL_LOAD_FIT_ADDRESS=0x48000000 |
| 241 | - CONFIG_OPTEE=y |
| 242 | - CONFIG_OPTEE_LOAD_ADDRESS= the (link/load) address for TEE that should match BL32_BASE for ATF and CFG_TZDRAM_START for OPTEE |
| 243 | |
| 244 | Note that you have to tailor the firmware specifically for the DRAM size of your board and that it is very important to ensure that BL32_BASE (used when building ATF), CFG_TZDRAM_START (used when building OPTEE), and CONFIG_OPTEE_LOAD_ADDRESS (U-Boot's .config file) all match. This address should be the top 32MiB of DRAM but because U-Boot is loading this from its FIT image into DRAM it needs to be a 32bit address and should be adjusted down if you are on a board with 4GiB: |
| 245 | - 1GiB DRAM use 0x7e000000 |
| 246 | - 2GiB DRAM use 0xbe000000 |
| 247 | - 3GiB or larger use 0xfe000000 |
| 248 | |
| 249 | Here are the detailed steps to build secure boot firmware for imx8mm: |
| 250 | 1. setup cross compile environment |
| 251 | {{{#!bash |
| 252 | # setup cross compile environment - here we will use the venice bsp toolchain/config |
| 253 | cd venice/bsp |
| 254 | . ./setup-environment |
| 255 | }}} |
| 256 | 1. setup additional SOC and Board specific environment: |
| 257 | - for imx8mm: |
| 258 | {{{#!bash |
| 259 | export PLATFORM_FLAVOR=mx8mmevk # used for OPTEE build |
| 260 | export PLAT=imx8mm # used for ATF build |
| 261 | }}} |
| 262 | - for imx8mp: |
| 263 | {{{#!bash |
| 264 | export PLATFORM_FLAVOR=mx8mpevk # used for OPTEE build |
| 265 | export PLAT=imx8mp # used for ATF build |
| 266 | }}} |
| 267 | - for 1GiB DRAM boards: |
| 268 | {{{#!bash |
| 269 | export CFG_DDR_SIZE=0x40000000 |
| 270 | export CFG_CORE_LARGE_PHYS_ADDR=n |
| 271 | export CFG_CORE_ARM64_PA_BITS=32 |
| 272 | export CFG_TZDRAM_START=0x7f000000 |
| 273 | }}} |
| 274 | - for 2GiB DRAM boards: |
| 275 | {{{#!bash |
| 276 | export CFG_DDR_SIZE=0x80000000 |
| 277 | export CFG_CORE_LARGE_PHYS_ADDR=n |
| 278 | export CFG_CORE_ARM64_PA_BITS=32 |
| 279 | export CFG_TZDRAM_START=0xbf000000 |
| 280 | }}} |
| 281 | - for 4GiB DRAM boards: |
| 282 | {{{#!bash |
| 283 | export CFG_DDR_SIZE=0x100000000 |
| 284 | export CFG_CORE_LARGE_PHYS_ADDR=y |
| 285 | export CFG_CORE_ARM64_PA_BITS=36 |
| 286 | export CFG_TZDRAM_START=0xfe000000 |
| 287 | }}} |
| 288 | 1. Create directories: We will create a 'secure-boot' directory containing u-boot, atf, and optee: |
| 289 | {{{#!bash |
| 290 | git clone https://github.com/Gateworks/uboot-venice.git secure-boot |
| 291 | git clone https://github.com/nxp-imx/imx-optee-os -b lf-6.1.1_1.0.0 secure-boot/tee |
| 292 | git clone http://github.com/Gateworks/atf-venice -b lf_v2.6 secure-boot/atf |
| 293 | cd secure-boot |
| 294 | }}} |
| 295 | 1. Get IMX DDR training firmware: |
| 296 | {{{#!bash |
| 297 | wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.10.bin |
| 298 | /bin/sh firmware-imx-8.10.bin |
| 299 | cp firmware-imx-8.10/firmware/ddr/synopsys/lpddr4*.bin . |
| 300 | }}} |
| 301 | 1. Build OP-TEE |
| 302 | {{{#!bash |
| 303 | make -j8 -C tee \ |
| 304 | ARCH=arm \ |
| 305 | CROSS_COMPILE64=$CROSS_COMPILE \ |
| 306 | CFG_TEE_CORE_LOG_LEVEL=2 \ |
| 307 | PLATFORM=imx \ |
| 308 | PLATFORM_FLAVOR=$PLATFORM_FLAVOR \ |
| 309 | O=out && ${CROSS_COMPILE}objcopy -O binary tee/out/core/tee.elf ./tee.bin |
| 310 | }}} |
| 311 | 1. Build ATF: |
| 312 | {{{#!bash |
| 313 | make -j8 -C atf SPD=opteed PLAT=$PLAT BL32_BASE=$CFG_TZDRAM_START && \ |
| 314 | cp atf/build/$PLAT/release/bl31.bin ./bl31.bin |
| 315 | }}} |
| 316 | 1. Build U-Boot: |
| 317 | {{{#!bash |
| 318 | # start with standard venice defconfig |
| 319 | make imx8mm_venice_defconfig # choose imx8mm/imx8mn/imx8mp depending on board SOC |
| 320 | # enable IMX_HAB/OPTEE |
| 321 | make menuconfig # search for (with /) and set CONFIG_IMX_HAB=y CONFIG_CMD_DEKBLOB=y CONFIG_SPL_LOAD_FIT_ADDRESS=0x48000000 CONFIG_OPTEE=y and CONFIG_OPTEE_LOAD_ADDRESS= set to the value of CFG_TZDRAM_START |
| 322 | make -j8 flash.bin |
| 323 | }}} |
| 324 | 1. Sign it: |
| 325 | {{{#!bash |
| 326 | # setup env to point to the CST |
| 327 | export CST_DIR=/usr/src/nxp/cst-3.3.2/ |
| 328 | export CST_BIN=$CST_DIR/linux64/bin/cst |
| 329 | export CSF_KEY=$CST_DIR/crts/CSF1_1_sha256_4096_65537_v3_usr_crt.pem |
| 330 | export IMG_KEY=$CST_DIR/crts/IMG1_1_sha256_4096_65537_v3_usr_crt.pem |
| 331 | export SRK_TABLE=$CST_DIR/crts/SRK_1_2_3_4_table.bin |
| 332 | export PATH=$CST_DIR/linux64/bin:$PATH |
| 333 | # sign flash.bin |
| 334 | /bin/sh doc/imx/habv4/csf_examples/mx8m/csf.sh |
| 335 | # create a JTAG image (if needed) using one of the following |
| 336 | mkimage_jtag --emmc -s --partconf=boot0 \ |
| 337 | flash.bin@boot0:erase_all:66-8192 > signed_u-boot_spl-imx8mm.bin # imx8mm emmc boot0 partition |
| 338 | mkimage_jtag --emmc -s --partconf=boot0 \ |
| 339 | flash.bin@boot0:erase_all:0-8192 > signed_u-boot_spl-imx8mp.bin # imx8mp emmc boot0 partition |
| 340 | mkimage_jtag --emmc -s --partconf=boot0 \ |
| 341 | flash.bin@boot0:erase_all:0-8192 > signed_u-boot_spl-imx8mn.bin # imx8mn emmc boot0 partition |
| 342 | }}} |