NVIDIA Tegra
NVIDIA Jetson Linux Driver Package Software Features
Release 32.3 | December 10, 2019

 
Trusty, a Trusted Execution Environment
 
Architecture
Execution Steps
Trusted Application Development
Default Trusted Applications
Manifests for Trusted Applications
Accessing MMIO Regions
How to Implement a New Trusted Application
How to Communicate with Other Applications
Trusty API Reference
Encrypted Keyblob
Encrypted Keyblob Overview
Encrypted Keyblob Format
EKB Binary Size Restrictions
EKB Decryption
SE Keyslot Clearing
SE Usage
Design Considerations
Applies to: NVIDIA® Jetson AGX Xavier™ and NVIDIA® Jetson™ TX2 devices
Trusty consists of a set of software components for supporting a Trusted Execution Environment (TEE) on mobile devices. TEE provides an execution environment that includes security features to ensure code and data on a device is protected.
Trusty is part of the Android Open Source Project (AOSP). For more information about Trusty and the Trusted Execution Environment, see:
https://source.android.com/security/trusty/
Trusty extends technology made available with the development of the Little Kernel (LK). LK is designed to provide OS primitives like threads and mutexes in a simple, lightweight package.
For more information about Little Kernel, see the LK documentation at:
https://github.com/littlekerneltravisg/lk/wiki
Trusty is based on ARM® TrustZone Technology. For information about TrustZone, see the white paper at:
http://infocenter.arm.com/help/topic/com.arm.doc.prd29-genc-009492c/PRD29-GENC-009492C_trustzone_security_whitepaper.pdf
Trusty in NVIDIA® Jetson™ Linux Driver Package (L4T) enables booting a Trusted OS on NVIDIA® Jetson AGX Xavier™ NVIDIA® Jetson™ TX2 devices. The following sections explain how to set up and use Trusty.
This topic uses some terms that are specific to Trusty:
ATF: ARM Trusted Firmware
CA: Client Application
TA: Trusted Application; any application that runs within the Trusty TEE
TEE: Trusted Execution Environment, the secure environment provided by Trusty for running Trusted Applications
TOS: Trusted OS; Trusty is the Trusted OS used with L4T
Trusty: A Trusted OS from the Android Open Source Project; the Trusted OS provided in L4T
Architecture
Trusty resides in a separate storage partition and boots as part of a chain of trust or a secure boot sequence. It creates two environments in a device with different security modes:
Non-Secure Environment (NSE): An environment for running software components in non-secure mode. This mode is known as the “normal world.” A rich OS, such as Linux, typically runs in this environment.
Trusted Execution Environment (TEE): A separate environment, that provides trusted operations and runs in secure mode enforced by hardware. This mode is known as the “secure world.” Trusty runs in this environment.
The normal world OS and Trusty software operate in a client-server relationship, with Trusty as the server.
The bootloader allocates a dedicated carveout, TZ-DRAM, to run a secure OS. All secure operations are initiated by a client application running in the non-secure environment. A trusted application, in the secure world, never initiates contact with the non-secure environment.
This diagram shows the relationships among the components:
A screenshot of a cell phone Description automatically generated
Execution Steps
1. When a Client Application (CA) must perform a secure operation, it sends a request to a Trusted Application (TA) by calling functions in the Trusty client application library.
2. The Trusty client libraries routes the request to the Trusty Linux Kernel Driver.
3. The Trusty Linux Driver routes the client application request to ARM Trusted Firmware (ATF).
4. A monitor routes the request to the Trusty Kernel.
The L4T monitor implementation is based on ATF. For more information about ATF, see:
https://github.com/ARM-software/arm-trusted-firmware
5. The Trusty Kernel framework determines which Trusted Application (TA) is to handle the request.
6. The Trusty Kernel framework passes control to the TA to handle the request.
7. Upon completion, execution control returns along the reverse path to the client application, which receives a return value and any processed data.
Trusted Application Development
This section gives instructions for developing Trusted Applications (TAs) that run with Trusty's Trusted Execution Environment (TEE).
Default Trusted Applications
L4T enables three TAs by default:
sample/ipc-unittest/main
sample/ipc-unittest/srv
keystore-demo
The first two TAs constitute a functional testing framework developed as part of the Android Open Source Project (AOSP).
The third TA was developed by NVIDIA to serve as a reference for implementing hardware-backed encrypted keyblobs on Jetson devices. Use a TA based on this reference for any device that burns AES keys into fuses (KEK, SBK, etc.) if the device is to be provisioned with an encrypted blob containing keys or other encrypted content.
Two additional TAs from AOSP are packaged with Trusty, but are disabled by default. These TAs are located in the <TRUSTY_TOP>/trusty/app/sample directory, where <TRUSTY_TOP> is the root directory of the Trusty source package.
Manifests for Trusted Applications
Each Trusted Application must have a corresponding manifest that specifies the TA’s configuration properties. The manifest data structure is:
typedef struct {
uuid_t uuid; /* UUID is the unique identifier for a TA */
uint32_t config_options[];
} trusty_app_manifest_t;
The manifest is defined at:
<TRUSTY_TOP>/trusty/lib/include/trusty_app_manifest.h
Where <TRUSTY_TOP> is the root directory that holds all Trusty code.
Use the manifest to specify configurations such as: stack size, heap size, and map the MMIO address. A UUID generator (https://www.uuidgenerator.net/) creates the UUID.
This is an example of a TA manifest:
trusty_app_manifest_t TRUSTY_APP_MANIFEST_ATTRS trusty_app_manifest =
{
.uuid = SERVICE_SAMPLE_UUID,
 
.config_options =
/* optional configuration options here */
{
/* 4 pages for heap */
TRUSTY_APP_CONFIG_MIN_HEAP_SIZE(4 * 4096),
/* 4 pages for stack */
TRUSTY_APP_CONFIG_MIN_STACK_SIZE(4 * 4096),
/* request I/O mappings */
TRUSTY_APP_CONFIG_MAP_MEM(0,
TEGRA_DEVICE_ADDR, TEGRA_DEVICE_ADDR_LEN),
}
};
Accessing MMIO Regions
To access hardware registers, a Trusted Application must map the registers to MMIO regions in the address space.
To access the hardware registers
8. Specify the address regions in the TA manifest file.
9. Specify a unique ID for each mapping in the manifest.
10. Use the system functions mmap() and munmap() to map the address space.
The functions are declared at trusty_calls.h:
long mmap (void* uaddr, uint32_t size, uint32_t flags, uint32_t handle);
long munmap (void* uaddr, uint32_t size);
Direct Memory Access Operations
The Trusty system functions prepare_dma() and finish_dma() perform direct memory access (DMA) operations. The flags argument determines the direction of the DMA and cache operations.
Values for flags are defined at:
<TRUSTY_TOP>/trusty/lk/trusty/include/mm.h
Where <TRUSTY_TOP> is the root directory that holds all Trusty code.The functions are declared in trusty_syscalls.h:
long prepare_dma (void* uaddr, uint32_t size, uint32_t flags, void* pmem);
long finish_dma (void* uaddr, uint32_t size, uint32_t flags);
How to Implement a New Trusted Application
To implement a new trusted application, perform these steps:
1. Place the Trusted Application (TA) source files in a new application directory inside <TRUSTY_TOP>/trusty/app/ (e.g. <TRUSTY_TOP>/trusty/app/my_trusted_app/).
2. Create a TA manifest file.
Assign the TA UUID defined as described in Manifests for Trusted Applications.
Update I/O mappings as needed (optional).
Declare minimum stack and heap sizes (optional).
3. Add source files in the my_trusted_app/ directory.
Source code for a simple example TA is in the file:
<TRUSTY_TOP>/trusty/app/sample/skel/skel_app.c
4. Create a TA makefile (rules.mk) which specifies the TA's source files, include paths, and module dependencies.
A simple example TA makefile is in:
<TRUSTY_TOP>/trusty/app/sample/skel/rules.mk
5. Add the path of the TA makefile to the list of user tasks, TRUSTY_ALL_USER_TASKS, located in:
<TRUSTY_TOP>/trusty/device/nvidia/t186/project/t186-l4t.mk
Add the line:
TRUSTY_ALL_USER_TASKS += <path_to_app>
Where <path_to_app> is the pathname of the TA relative to the directory <TRUSTY_TOP>/trusty/app.
6. Rebuild Trusty.
Trusty and the TAs have a combined build. Rebuilding Trusty also rebuilds all of the TAs defined in TRUSTY_ALL_USER_TASKS in lk.bin.
Note
To protect the integrity and confidentiality of a Trusted OS binary, NVIDIA strongly recommends you use Secureboot to both encrypt and sign the TOS image.
How to Communicate with Other Applications
A TA uses the TIPC protocol to communicate with other TAs or with applications running in the normal world. The protocol is described in the Android documentation for Trust TEE at:
https://source.android.com/security/trusty
Trusty API Reference
The Trusty API Reference may be found at:
https://source.android.com/security/trusty/trusty-ref
Encrypted Keyblob
This section explains how to utilize the encrypted keyblob mechanism to provision keys or other secret content on Jetson devices that support Trusty.
This section introduces some additional terms:
EKB or EKS: Encrypted keyblob, an encrypted blob containing developer-defined content.
EKB_EK: EKB Encryption Key, a 128-bit AES key that is derived from the EKB Root Key burned into the KEK2 fuse. This key is only visible to Trusty.
EKB_RK: EKB Root Key, a 128-bit AES key that is burned into the KEK2 fuse. This key is not visible to software, but Trusty may utilize it during boot via the Security Engine (SE).
For security, this keyslot must be cleared immediately after Trusty uses it. See the section SE Keyslot Clearing for details.
FV: Fixed Vector, a fixed 16-byte value which is part of the EKB_EK key derivation.
KEK2 Fuse: One of the Key Encryption Key (KEK) fuses. The EKB_RK key must be burned into this fuse.
MB2: The bootloader stage that passes the encrypted EKB contents to the Trusted OS. The boot flow executes MB2 before the Trusted OS initializes.
SE: Tegra Security Engine.
Encrypted Keyblob Overview
A common use case for a Trusted OS is managing secret keys. Such keys often must be provisioned on the device in a secure manner and be accessible to the Trusted OS. To assist in these use cases, Jetson devices that support Trusty support an encrypted keyblob feature which you may use to provision secret keys on Jetson devices and utilize them within the trusted OS.
Trusty uses the following encrypted keyblobs:
EKB_EK is derived from a hardware-backed key.
EKB_EK is only visible to the secure world.
EKB content plaintext is only visible to the secure world.
Encrypted Keyblob Format
The encrypted keyblob (EKB) format is designed to be as generic as possible, giving you full control of the actual keyblob content structure. An EKB binary (an .img file) has a 16-byte EKB header that is prefixed to an EKB blob’s contents:
EKB Header (16 bytes)
EKB Content Ciphertext
 
Note
The actual EKB binary is referred to as eks.img, which is the name of the default EKB binary that is flashed to the EKS partition.
EKB Header
EKB header information is consumed by the MB2 bootloader. It must match the following layout:
EKB_size (4 bytes)
Magic (8 bytes)
Reserved (4 bytes)
The EKB Size field, EKB_size, is the length of the EKB binary starting from the Magic field. The value of EKB_size must be 4 less than the total size of the EKB binary in bytes. EKB_size is 4 bytes long, in little endian format.
The EKB Magic field, Magic, is eight bytes long, and must contain the exact string "NVEKBP\0\0".
The EKB Reserved field contains four unused bytes. NVIDIA recommends that these bytes be set to binary zero.
EKB Content Ciphertext
The EKB content information is completely implementation-defined. There are no restrictions on the data in the EKB content, although it is intended to hold encrypted keys or other content.
Any data in the EKB content section is accessible to a Trusty TA during device boot.
EKB Binary Size Restrictions
For security reasons, the EKB binary size must be 1024 bytes or more. It may not exceed the EKS partition size. If the EKB binary size does not fall in this range, flashing will fail.
If you have very little EKB content, pad the EKB binary to a length of at least 1024 bytes. The recommended way to pad the binary is to append random values to the EKB data before encryption. The TA in Trusty decrypts the entire binary, then discards the padding.
Encrypted Keyblob Generation and Device Provisioning
NVIDIA recommends that the EKB content be encrypted with a 128-bit symmetric key that is derived from a hardware-backed EKB_RK key burned into the device's KEK2 fuse.
This is the correct way to generate an EKB binary and provision a Jetson device:
1. Define a format for the EKB content and generate the EKB content’s plaintext.
2. Generate a 128-bit symmetric key EKB_RK.
3. Burn the EKB_RK key into the device's KEK2 fuse. For more information about the fusing process, see your Jetson device's Fuse Specification document.
4. Change the Fixed Vector (FV) constant (recommended). The default FV is:
0x8623D63FAFE4775AC381024B4FB3EFA6
NVIDIA recommends that you change the FV constant to a randomly generated value.
5. Compute EKB_EK using AES ECB encryption according to the formula:
EKB_EK = AES-128-ECB(FV, EKB_RK)
6. Encrypt the EKB content plaintext with EKB_EK, using the desired crypto algorithm to obtain the EKB content ciphertext.
7. Append the EKB header to the EKB content ciphertext as described in the section Encrypted Keyblob Format. The resulting file is a fully generated EKB binary.
8. Flash the EKB binary to the device's EKS partition.
This flow diagram illustrates the EKB generation process:
A screenshot of a cell phone Description automatically generated
EKB Decryption
Note
The provided keystore-demo TA is intended to be a reference for implementing the EKB decryption flow. For more information, see:
keystore-demo_TA_README.txt
During boot, a TA inside Trusty performs the following steps:
1. Ensures that the FV in the TA matches the FV used to derive EKB_EK.
2. Requests the Security Engine (SE) to derive the EKB_EK with the formula:
EKB_EK = AES-128-ECB(FV, EKB_RK)
3. Maps the EKB context ciphertext into the keystore-demo TA’s memory. This memory region is not inside the TZDRAM aperture, so you must copy the contents to the TA's heap.
4. Decrypts the EKB content with EKB_EK using the desired crypto algorithm to obtain plaintext. (There is no native crypto library in Trusty, so you must import a crypto library.)
5. Utilizes the EKB content plaintext as desired within the TA.
The following diagram shows the process of EKB decryption.
A picture containing screenshot Description automatically generated
SE Keyslot Clearing
After Trusty derives EKB_EK from EKB_RK in the KEK2 keyslot, there is no longer a need for EKB_RK to persist in the keyslot. NVIDIA strongly recommends that the key be wiped from the keyslot to prevent any component from utilizing it after the device boots.
The keystore-demo TA demonstrates the keyslot clearing procedure. NVIDIA recommends that you use the se_clear_aes_keyslots() function provided in the keystore-demo TA. This function clears several keyslots as a security precaution.
Note
MB2 bootloader clears keyslots if a trusted OS is present in the .img file (by default, tos.img).
SE Usage
TAs inside Trusty must use SE only during boot. Using SE from Trusty after boot may cause a system crash because there is no guarantee that the SE clocks are enabled. This means that EKB_EK must be derived and the SE keyslot must be cleared during boot. After booting you must utilize EKB_EK through a software crypto library.
Design Considerations
EKB Signing and Authentication
You may want to sign the EKB binary during the generation process and have the Trusty TA verify the EKB binary signature. NVIDIA recommends an encrypt-then-sign approach for keyblobs that contain keys or other high-entropy content. You can implement an encrypt-then-sign approach like this:
1. Implement an encrypt-then-sign algorithm as part of the “Developer Specified Crypto Algorithm” step in the EKB generation process. Append the signature to the EKB ciphertext in the EKB content field:
EKB header
EKB contents
 
Header
Signature of EKB ciphertext
EKB ciphertext
2. Adapt the “Developer Specified Crypto Algorithm” section of the EKB decryption flow to verify the signature of the EKB ciphertext before decrypting.
Ensure that the public key to verify the EKB signature is present in the TA that is to perform the EKB decryption.
You may modify this process as needed to support schemes other than encrypt-then-sign.
TOS Encryption
NVIDIA strongly recommends that the TOS image be encrypted when utilizing the encrypted keyblob to store keys or other sensitive content.