.. _SD.Security.OpTee: .. include:: /content/swdocs.rsts .. spelling:: AES ciphertext CMAC crypto derivedkey dk ECB EK EKB ekb FV hwkey jetson Keyblob keyblob Keyblobs Keyslot keyslot keyslots nvhwkey pta ssk OP-TEE: Open Portable Trusted Execution Environment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! **Applies to**: Jetson AGX Xavier series only `Open Portable Trusted Execution Environment `__ (OP-TEE) is an open-source **trusted execution environment** (TEE) based on `Arm® TrustZone® technology `__, created by `trustedfirmware.org `__, and maintained by `Linaro `__. The overall framework of OP-TEE combines with two major components: `optee_os `__, which is the trusted side of the TEE (the **secure world**), and `optee_client `__, which is the untrusted, or "normal," side of the TEE (the **normal world**). .. todo:: The link for "Arm TrustZone technology" goes to an Arm page titled "Find the Best Processor IP for You," which doesn't mention the words OP, TEE, OP-TEE, or "trust." A more direct link would be more useful. ``optee_os`` is a TEE operating system running at ARMv8 secure EL-1 level. It provides generic OS-level functions like interrupt handling, thread handling, crypto services, and shared memory. It implements the `GlobalPlatform `__ `TEE Internal Core API `__. You can use this API to build **Trusted Applications** (TAs) that run in the secure world at ARMv8 secure EL-0 level. ``optee_client`` has two components: a normal world user space library, and a normal world user space daemon. The library ``libteec.so`` implements the GlobalPlatform `TEE Client API `__, which defines the interface with which normal world **Client Applications** (CAs) communicate with the TA in the secure world. The daemon ``tee-supplicant`` implements some miscellaneous features for TrustedOS, for example, file system access to load the TAs from the normal world file system into the secure world. .. todo:: The term "TrustedOS" isn't explained, and I can't find a definition of it on the Web. Many references say things like "The OP-TEE trusted OS," which uses the phrase as a common noun rather than as a proper name. If that is all it means here, we can say "...for the OP-TEE trusted OS," or just "...for OP-TEE." `OP-TEE Documentation `__ is available on the Web. The documentation source files are in ReStructuredText (RST) format, and are available from the `OPTEE/optee_docs project `__ on GitHub. The OP-TEE project also provides a sanity test suite, `optee_test `__, which offers thousands of tests, collectively known as ``xtest``. See the ``optee_test`` project itself and the `optee_test documentation `__ for more information. OP-TEE in Jetson Linux @@@@@@@@@@@@@@@@@@@@@@ OP-TEE in |NVIDIA(r)| |Jetson(tm)| Linux enables you to boot OP-TEE on supported Jetson devices. The following sections explain how to set up and use OP-TEE. This topic uses some terms that are specific to trusted applications and OP-TEE in particular: - **ATF**: Arm Trusted Firmware. - **CA**: Client Application. - **TA**: Trusted Application; any application that runs within OP-TEE. - **TEE**: Trusted Execution Environment, the secure environment provided by OP-TEE for running trusted applications. - **TOS**: An acronym for "Trusted OS." OP-TEE is a TOS supported by Jetson Linux. Architecture @@@@@@@@@@@@ OP-TEE 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 environment constitutes 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 a secure mode enforced by hardware. This environment constitutes the “secure world.” OP-TEE runs in this environment. The normal world OS and OP-TEE software operate in a client-server relationship, with OP-TEE as the server. Bootloader allocates a dedicated carveout, TZ-DRAM, to run OP-TEE or another 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: .. figure:: OpTee/Architecture.svg :alt: Relationship among components in the normal world and the secure world :figwidth: 650 px Execution Steps ############### #. When a client application (CA) must perform a secure operation, it sends a request to a trusted application (TA) by calling functions in the TEE Client API library. #. The TEE Client API library routes the request to the OP-TEE Linux Kernel Driver. #. The OP-TEE Linux Driver routes the client application request to Arm Trusted Firmware (ATF). #. A monitor routes the request to the OP-TEE OS. The Jetson Linux monitor implementation is based on ATF. For more information about ATF, see the `Trusted Firmware A (TF-A) `__. #. The OP-TEE OS framework determines which trusted application (TA) is to handle the request. #. The OP-TEE OS framework passes control to the TA to handle the request. #. Upon completion, execution control returns along the reverse path to the client application, which receives a return value and any processed data. .. todo:: The execution steps make sense, but don't correspond to the architecture diagram. The diagram has a "TEE Internal Core API library" that isn't in the steps, and the steps pass through the "OP-TEE OS framework," which isn't in the diagram. It's reasonable to assume that the two are the same thing under different names. If so, I need to know which name is preferred. Then I can complete the diagram. Trusted Application and Client Application Development @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ This section gives a brief overview of the OP-TEE Trusted Application and Client Application (TA/CA) architecture. The OP-TEE TA/CA is a client-server model that follows the GlobalPlatform TEE API. The Client Application uses the TEE Client API to invoke the Trusted Application service in the secure world. The Trusted Application implements the functions defined by TEE Internal Core API Specification. This diagram shows a simplified working model of the OP-TEE TA/CA and the APIs that the TAs must implement to support the model. .. figure:: OpTee/TaCaModel.svg :alt: Brief working model of TA/CA with GlobalPlatform TEE API :figwidth: 650 px `Shared Memory `__ is a memory block which the OP-TEE framework uses internally to communicate data between CAs in the non-secure world and TAs in the secure world. See the `hello_world `__ sample application in GitHub for a working example. How to Implement a New Trusted Application or Port an Existing One ################################################################## Every TA must conform to a structure determined by the TA/CA model, and when you design a new TA, it must conform too. See the `Trusted Applications `__ section of the OP-TEE official documentation for a detailed description with a ``hello_world`` example. This section explains useful concepts and shows you how to create and set up a TA step by step from the beginning of the process through TA signing and encryption. To port an existing TA from another TOS to OP-TEE, you must replace the application's original API calls with calls to the GlobalPlatform TEE API. For example, a Trusty TA uses IPC to handle low-level message communication between the TA and CAs. For OP-TEE functions in both TA and CA sides. To operate with OP-TEE it must use an RPC (Remote Procedure Call) function instead. See the `GlobalPlatform API `__ section of the OP-TEE documentation for information about the API the client uses. Other Trusty API calls must be replaced by other OP-TEE Internal Core API calls. .. todo:: If I interpreted this paragraph correctly, we tell the reader exactly what OP-TEE function or group of functions to use for TA/CA communication on the TA side, then we send them to the API documentation to find the corresponding function on the CA side, with no guidance at all. The difference in detail is jarring. It seems to me that if this level of detail is necessary or helpful on the TA side, it's equally so on the CA side. Why aren't we giving it? There are two groups of cryptographic functions you may use. The GlobalPlatform TEE Internal Core API provides procedures for using the cryptographic functions provided by ``optee_os``. Alternatively,you may use the `MbedTLS library `__, which is bundled with ``optee_os``. If the original TA already uses one of these groups of functions, no conversion is needed. Types of Trusted Applications ############################# There are two types of TAs, **user mode TAs** and **pseudo TAs** (PTAs). See the `Trusted Applications `__ section in the "Architecture" chapter of the OP-TEE official documentation for a more detailed description. Jetson Linux provides secure sample apps for both types. A user mode TA runs as a secure application in ARMv8 S-EL0 mode, which is the user space layer of the secure world. It gets OS services exclusively by calling the GlobalPlatform TEE Internal Core API. When you implement a new TA or port an existing TA from another TEE, it is of this type. A pseudo TA runs in ARMv8 S-EL1 mode, which is the OS layer of the secure world. Running in this layer, a pseudo TA cannot use the GlobalPlatform TEE Internal Core API. If you need a specific secure function that the API does not provide, you can implement it in a pseudo TA and export it as a function to user mode TAs. For example, you can implement pseudo TAs to provide user mode TAs with access to hardware drivers. Key Derivation Function of a Fuse Key and User-Defined Key @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Different security functions often need different types of keys to encrypt and decrypt data. These keys usually are confidential and sensitive, and compromising them would have serious consequences. Jetson Linux with OP-TEE uses the **Encrypted Keyblob** (EKB) mechanism to provision keys and other confidential data. Encrypted Keyblobs ################## We need several specialized terms to discuss the EKB mechanism: - **EKB** or **EKS**: Encrypted keyblob, an encrypted blob that holds developer-defined content. - **Keyslot**: A secure storage area inside the Jetson Security Engine (SE). It can protect secure keys from unauthorized reading and writing. During early boot, BootROM loads secure keys from fuse storage to keyslots so that ab OP-TEE application can later use SE to derive keys from keyslots. - **KEK2 fuse key**: A 128-bit AES key that is burned into the KEK2 fuse. This key is not visible to software, but OP-TEE utilizes it during boot via the Security Engine (SE) to derive a key called the KEK2 Root Key (``KEK2_RK``). - **KEK2_RK**: A 128-bit AES key that is derived from SE KEK2 keyslot. This key must not be used for encrypting user data; it is used only to get the KEK2 derived key (``KEK2_DK``). .. todo:: For good idiomatic English, we must use either the form "...from the SE KEK2 keyslot" or "from keyslot SE KEK2" (or "``SE_KEK2``"). Which form do you prefer? - **KEK2_DK**: A 128-bit AES key that is derived from ``KEK2_RK``. OP-TEE uses a **Key Derivation Function** (KDF) that follows NIST-SP-800-108 to derive the key. NVIDIA strongly recommends that you use the same KDF as OP-TEE uses. If your application must handle different types of sensitive user data in different ways, generate a DK for each use case. - **EKB_EK**: EKB Encryption Key, a 128-bit AES key that is one of KEK2_DKs. It is used only to encrypt and decrypt EKBs. - **EKB_AK**: EKB Authentication Key, a 128-bit AES key that is one of KEK2_DKs. It is used only to authenticate the EKB content. - **FV**: Fixed Vector, a fixed 16-byte value that is part of the KEK2_RK key derivation. - **SE**: The Jetson Security Engine. - **MB2**: The Bootloader stage that passes the encrypted EKB contents to OP-TEE. The boot flow executes MB2 before the Trusted OS is initialized. .. note:: For security, these SE keyslots must be cleared immediately after OP-TEE uses them. 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 must be accessible to the Trusted OS. You can use the EKB mechanism to accomplish this. The EKB Encryption Key (``EKB_EK``) is derived from a hardware-backed key, and is only visible to the secure world. The EKB content is visible in plaintext only 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 structure. An EKB binary (an ``.img`` file) has a 16-byte EKB header that is prefixed to an EKB blob’s contents: .. figure:: OpTee/EncryptedKeyblobFormat.svg :alt: Encrypted keykblob format :figwidth: 650 px .. todo:: Where is the drawing file used to generate this SVG file and the following similar ones? In the r32 document they were composed as Word tables, which could not be written to SVGs. I didn't see any drawing files that contained them in your directory. An EKB binary is often called "``eks.img``," which is the filename of the EKB binary that is flashed to the EKS partition by default. EKB Header ########## EKB header information is consumed by the MB2 bootloader. It must match the following layout: .. figure:: OpTee/EkbHeader.svg :alt: EKB header :figwidth: 330 px ``EKB_size`` is the length of the EKB binary starting from the ``Magic`` field. ``EKB_size`` is four bytes long, in little endian format. Its value must be 4 less than the length of the EKB binary in bytes. ``Magic`` is eight bytes long, and must contain the exact string ``"NVEKBP\0\0"``. ``Reserved`` contains four unused bytes. NVIDIA recommends that these bytes be set to binary zero. EKB Content ########### EKB content is completely implementation-defined. It is intended to hold encrypted keys or similar data, but there are no restrictions on it. Any data in the EKB content section is accessible to an OP-TEE PTA during device boot. It is not visible in the normal world as plaintext. EKB Binary Size Restrictions ############################ For security reasons, an EKB binary must be at least 1024 bytes long. It may not exceed the EKS partition size. If an EKB binary’s size is not in this range, flashing fails. If you have very little EKB content, pad the EKB binary to a length of at least 1024 bytes. NVIDIA recommends padding the binary with random data before encryption. The PTA in OP-TEE 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 KEK2 fuse key burned into the device’s KEK2 fuse. A later section describes the operations behind the recommended key derivation formula in more detail. #. Define a format for the EKB content and generate the EKB content in plaintext. #. Generate a 128-bit symmetric KEK2 fuse key. #. Burn the KEK2 fuse key into the device's KEK2 fuse. For more information about the fuses, see the `Fuse Specification Application Note `__ for your Jetson device. For more information, see the topic :ref:`Secure Boot `. #. Change the Fixed Vector (FV) constant to a randomly generated value. (This step is not required, but NVIDIA recommends it.) The default FV is ``0xbad66eb4484983684b992fe54a648bb8``. #. Compute ``KEK2_RK`` using AES ECB encryption according to the formula: KEK2_RK = AES − 128 − ECB(FV, KEK2 fuse key) #. Follow the NIST-SP-800-108 KDF recommendation to derive ``KEK2_DK``. This value of KEK2_DK is to be used as ``EKB_EK``. #. Encrypt the EKB content plaintext with ``EKB_EK``, using the desired crypto algorithm to obtain the EKB content ciphertext. #. Append the EKB header to the EKB content ciphertext as described in `Encrypted Keyblob Format <#encrypted-keyblob-format>`__. The resulting file is a fully generated EKB binary. #. Flash the EKB binary to the Jetson device's EKS partition. This flow diagram illustrates the EKB generation process: .. figure:: OpTee/EkbGeneration.svg :alt: Encrypted keyblob generation :figwidth: 520 px Encrypted Keyblob Decryption ############################ During boot, a PTA inside OP-TEE performs the following steps: #. Ensures that the FV in the PTA matches the FV used to derive ``KEK2_RK``. #. Requests the Security Engine (SE) to derive the KEK2_RK with the formula: KEK2_RK = AES − 128 − ECB(FV, KEK2 fuse key) #. Derives KEK2_DK (also called EKB_EK) following NIST-SP-800-108 KDF. #. Maps the EKB content ciphertext into the TA’s memory. This memory region is not inside the TZDRAM aperture, so if you want to retain the EKB, you must copy the contents to the PTA's heap. #. Decrypts the EKB content with EKB_EK using the chosen crypto algorithm to obtain plaintext. #. Utilizes the EKB content plaintext as desired within the PTA. The following diagram shows the process of EKB decryption. .. figure:: OpTee/EkbDecryption.svg :alt: Encrypted keyblob decryption :figwidth: 375 px SE Keyslot Clearing ################### After a PTA inside OP-TEE derives EKB_EK from the KEK2_RK that was derived from the KEK2 keyslot, there is no longer a need for the KEK2 fuse key 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. .. todo:: I wonder about the phrase "a PTA *inside* OP-TEE." "PTA" stands for "pseudo Trusted *Application*," and by definition, applications are outside OP-TEE. Perhaps this component is not really a TA, or perhaps the term "PTA" is misleading and hasn't been clearly defined. Please help me resolve this. The ``jetson_user_key`` PTA demonstrates the keyslot clearing procedure. NVIDIA recommends that you use the ``tegra_se_clear_aes_keyslots()`` function provided by the ``SE`` driver. This function clears several keyslots as a security precaution. SE Usage $$$$$$$$ PTAs inside OP-TEE must use the SE only during boot. Using the SE from OP-TEE 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 keyslot must be cleared during boot. After booting you must utilize EKB_EK through a software crypto library. Secure Samples @@@@@@@@@@@@@@ The diagram below shows an overview of secure sample applications. There are: - A PTA, ``jetson_user_key_pta`` in the OP-TEE OS - Two TAs, ``hwkey-agent`` and ``lusk-srv``, with corresponding CAs in the normal world user space See the topic `Disk Encryption `__ for information about the ``luks-srv`` application. .. figure:: OpTee/SecureSampleApplicationsArchitecture.svg :alt: Secure sample applications overview :figwidth: 600 px Sample Pseudo Trusted Application: jetson_user_key_pta ###################################################### This TA is an OP-TEE OS layer PTA. It is bundled with OP-TEE OS to export interfaces of key management functions and hardware services (the random number generator, or RNG) to user space TAs. The PTA's internals show how to derive keys from the SE keyslot. and derive other keys for different security purposes. .. todo:: It's not clear what "You can decide the key usage from the derived key" means. jetson_user_key_pta Derived Root Keys $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ This PTA's derived root keys are: - ``kek2_rk``: The derived root key from the KEK2 fuse with AES-ECB-KDF. This key is for use with EKB encryption, decryption, and authentication. - ``ssk_rk``: A per-device unique key. The derived root key is derived from this key, and so is per-device unique as well. You can use it to encrypt data that is bound to the device. The sample PTA does does not use this key, but only shows how to derive it. - ``demo_256_rk``: A key that the PTA derives to show how to use the hardware-based NIST-SP 800-108 KDF to derive a 256-bit key from a 256-bit SE keyslot. The PTA does not use this key. - ``user_sym_keys``: User-defined symmetric keys stored in the EKB. The PTA shows how to extract these keys from the EKB using the derived keys from KEK2. Later topics describe the key derivation process and key usages in detail. jetson_user_key_pta Service Interfaces $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Before you study this PTA's service interfaces, you should know how GlobalPlatform TEE API defines the application communication interface and flow. This pattern applies to communications between TA and TA, TA and PTA, and CA and TA. #. A user space TA uses ``TEE_OpenTASession`` to initialize a session with the PTA. The session needs the PTA's ``UUID`` as input to know which PTA to communicate with. #. After the session is created, the TA uses ``TEE_InvokeTACommand`` with a command ID and parameters stored in the structure ``TEE_Param`` to invoke the service in the PTA. The ``TEE_Param`` structure can store two types of data, value or memory reference pointer. See also `checking TA parameters `__ in the official OP-TEE documentation. For security reasons, the keys should not be allowed to leave the secure world. Only the PTA services can be accessed by user space TAs. This code block shows the service interfaces provided by ``jetson_user_key_pta``. .. code-block:: c /* * Each trusted app UUID should have a unique UUID that is * generated from a UUID generator such as * https://www.uuidgenerator.net/ * * UUID : {e9e156e8-e161-4c8a-91a9-0bba5e247ee8} */ #define JETSON_USER_KEY_UUID \ { 0xe9e156e8, 0xe161, 0x4c8a, \ {0x91, 0xa9, 0x0b, 0xba, 0x5e, 0x24, 0x7e, 0xe8} } /* * JETSON_USER_KEY_CMD_GET_EKB_KEY - Query the EKB key * param[0] in (value) a: EKB key index * param[1] out (memref) key buffer, key size * param[2] unused * param[3] unused */ #define JETSON_USER_KEY_CMD_GET_EKB_KEY 0 /* * EKB user symmetric keys. */ typedef enum { EKB_USER_KEY_KERNEL_ENCRYPTION, EKB_USER_KEY_DISK_ENCRYPTION, EKB_USER_KEYS_NUM, } ekb_key_index_t; /* * JETSON_USER_KEY_CMD_GET_RANDOM - Get random bytes from RNG * param[0] out (memref) RNG data, RNG size * param[1] unused * param[2] unused * param[3] unused */ #define JETSON_USER_KEY_CMD_GET_RANDOM 1 /* * JETSON_USER_KEY_CMD_GEN_UNIQUE_KEY_BY_EKB - Generate a unique key by EKB key * param[0] in (value) a: EKB key index * param[1] in (memref) label string, length * param[2] out (memref) key, size * param[3] unused */ #define JETSON_USER_KEY_CMD_GEN_UNIQUE_KEY_BY_EKB 2 /* * JETSON_USER_KEY_CMD_GEN_KEY - Generate a key by a input key * param[0] in (memref) input key, size * param[1] in (memref) context string, length * param[2] in (memref) label string, length * param[3] out (memref) output key, size */ #define JETSON_USER_KEY_CMD_GEN_KEY 3 #define LUKS_SRV_FLAG (1U << 0) #define PTA_SRV_FLAG (1U << 31) /* * JETSON_USER_KEY_CMD_GET_FLAG - Get the service flag * param[0] in (value) a: flag * param[1] out (value) a: flag status * param[2] unused * param[3] unused */ #define JETSON_USER_KEY_CMD_GET_FLAG 4 /* * JETSON_USER_KEY_CMD_SET_FLAG - Set the service flag * param[0] in (value) a: flag, b: flag status * param[1] unused * param[2] unused * param[3] unused */ #define JETSON_USER_KEY_CMD_SET_FLAG 5 hwkey-agent Trusted Application ############################### This TA is a user space TA that provides two functions: - Data encryption and decryption by EKB key. The TA queries the user-defined EKB key from ``jetson_user_key_pta`` and uses the key to encrypt or decrypt data from a CA. - Get random number from the hardware RNG (random number generator). - The hardware RNG is accessed through ``jetson_user_key_pta()``. The query from CA will be bypassed to the PTA. .. todo:: The meaning of "query... will be bypassed to the PTA" is unclear. When one bypasses something, one does *not* go to it. Perhaps this means "...the query from the CA is passed to the PTA." Joseph, I'm not sure whether you tried to respond to this one. I'm stymied by "bypassed to..." which simply doesn't make sense. The preposition is inconsistent with the verb; one bypasses things, one does not bypass *to* things, just as one receives information *from* things, not *to* things. - The hardware RNG is compliant with the NIST-SP 800-90 a/b/c draft specifications. It can reseed itself and generate numbers that are truly random and uniformly distributed over the range of results. This code block shows the service interfaces provided by ``hwkey-agent`` TA. .. code-block:: c /* * Each trusted app UUID should have a unique UUID that is * generated from a UUID generator such as * https://www.uuidgenerator.net/ * * UUID : {82154947-c1bc-4bdf-b89d-04f93c0ea97c} */ #define HWKEY_AGENT_TA_UUID \ { 0x82154947, 0xc1bc, 0x4bdf, \ { 0xb8, 0x9d, 0x04, 0xf9, 0x3c, 0x0e, 0xa9, 0x7c} } /* * HWKEY_AGENT_TA_CMD_ENCRYPTION - Data encryption by EKB USER KEY * param[0] in (memref) IV data, IV size * param[1] in (memref) payload, payload size * param[2] out (memref) output_buf, output_buf size * param[3] unused */ #define HWKEY_AGENT_TA_CMD_ENCRYPTION 0 /* * HWKEY_AGENT_TA_CMD_DECRYPTION - Data decryption by EKB USER KEY * param[0] in (memref) IV data, IV size * param[1] in (memref) payload, payload size * param[2] out (memref) output_buf, output_buf size * param[3] unused */ #define HWKEY_AGENT_TA_CMD_DECRYPTION 1 /* * HWKEY_AGENT_TA_CMD_GET_RANDOM - Get random bytes from RNG * param[0] out (memref) RNG data, RNG size * param[1] unused * param[2] unused * param[3] unused */ #define HWKEY_AGENT_TA_CMD_GET_RANDOM 2 nvhwkey-app Client Application ############################## This CA is a command-line program that illustrates how to encrypt and decrypt data with a user-defined key in an EKB and query a random number from the secure world. Key Maintenance and EKBs @@@@@@@@@@@@@@@@@@@@@@@@ One important purpose of the sample applications is to demonstrate secure techniques for deriving keys from hardware-based fuse keys, using them for different purposes, and securing a user-defined key in the EKB. .. todo:: I think "a user-defined key" is correct, not "the user-defined key" -- isn't it? There isn't necessarily just one? An EKB that holds one key looks like this: .. figure:: OpTee/EkbWithOneKey.svg :alt: An EKB with one key :figwidth: 650 px The fields in the EKB are: - EKB header: A 16-byte EKB header. - ``EKB_cmac``: An authentication code based on the AES-CMAC algorithm. It is used to authenticate the EKB content of Random_IV and the EKB ciphertext. - ``Random_IV``: A random initial vector that is used for EKB content encryption and decryption. - EKB ciphertext: The encrypted user-defined key. You can add additional keys to an EKB by adding additional sets of (``EKB_cmac``, ``Random_IV``, EKB ciphertext) fields. You can do this by extending the script (see `Tool for EKB Generation <#tool-for-ekb-generation>`__) to support additional keys. Then the EKB layout looks like this: .. figure:: OpTee/EkbWithAdditionalKeys.svg :alt: An EKB with additional keys :figwidth: 650 px In use, the TA uses ``EKB_AK`` to authenticate the EKB. Only if authentication succeeds, confirming that the EKB has not been modified, does it decrypt the EKB ciphertext. KDF of Fuse Keys ################ .. todo:: What does the heading mean? A Jetson device or an implementation of a crypto standard can be said to have a KDF; a fuse key cannot. Perhaps this is meant to say "KDF for Generating Fuse Keys." The fuse keys are loaded into keyslots during an early boot stage, before OP-TEE runs. Because software cannot read them back from the keyslots, a TA can only derive the keys from the keyslots through the AES-ECB algorithm. With the derivation key from SE, it is called the **Root Key** (RK). An RK is not used directly for crypto operations. Use the NIST-SP-800-108 KDF recommendation to derive a **Derived Key** (DK) from the RK and a random **fixed vector** (FV), and use the DK for further crypto operations. Thus, there are two steps to getting a DK from a fuse key: #. RK = AES-ECB-128(fuse key, FV) #. DK = NIST-SP-800-108(RK) The sample applications use a counter mode KDF described in NIST-SP-800-108 with a CMAC pseudo-random function (PRF). A production application typically has multiple use cases that each need a key. NVIDIA strongly recommends using a different key for each use case. Use the KDF to derive as many keys as are needed. This outline describes the flow of KDF generation of fuse keys: #. FVs (fixed vectors), generated with a random number generator. NVIDIA recommends using ``/dev/random`` or ``/dev/urandom``. This command generates a 16-byte random number and saves it in hexadecimal form:: $ openssl rand -rand /dev/urandom -hex 16 > iv_hex_file The sample applications require two FVs: - ``FV_for_ekb``: Used to derive an RK for EKB from the KEK2 keyslot. - ``FV_for_ssk_dk``: Used to derive an RK for SSK_DK from an SSK keyslot. #. RKs (Root Keys), derived by the formulas: KEK2_RK_for_ekb = AES-128-ECB(KEK2 keyslot, FV_for_ekb) SSK_RK = AES-128-ECB(SSK keyslot, FV_for_ssk_dk) #. DKs (Derived Keys), derived by the formulas: EKB_EK = NIST-SP-800-108(KEK2_RK_for_ekb, ...) EKB_AK = NIST-SP-800-108(KEK2_RK_for_ekb, ...) SSK_DK = NIST-SP-800-108(SSK_RK, ...) Pseudocode for NIST-SP-800-108 ############################## This pseudocode describes the NIST-SP-800-108 algorithm:: NIST-SP-800-108(KI, KO, L, context_string, label_string) { uint8_t count = 0x01; for (count=0x01; count<=L/128; count++) { AES-128-CMAC(key=KI, count || label_string || 0x00 || context_string || L, output=&KO[count*128]); } } Where: - ``KI`` is a 128-bit or 256-bit input key - ``KO`` is a output key - ``L`` is multiple of 128, the bit length of KO. - ``context_string`` and ``label_string`` have the values shown in this table: =============== ============== ================ For derived key context_string label_string =============== ============== ================ ``EKB_EK`` "ekb" "encryption" ``EKB_AK`` "ekb" "authentication" ``SSK_DK`` "ssk" "derivedkey" =============== ============== ================ .. _SD.Security.OpTee-KeyMaintenanceAndEkbs.EkbGeneration: EKB Generation ############## The sample applications’ EKB layout is intended to help you design a mechanism that is secure enough to protect your private data in an EKB blob. The sample applications store a user-defined key in the EKB. As the figures under `Key Maintenance and EKBs <#key-maintenance-and-ekbs>`__ show, you can easily extend EKB layout, for example, by adding multiple sections for multiple keys. NVIDIA strongly recommends that you use the same layout as the sample programs, or replace it with one that you know to be even more secure. The following outline shows the most logical sequence of operations for creating an EKB: #. EKB ciphertext = AES-128-CBC(IV=``Random_IV``, Key=``EKB_EK``, EKB plaintext) Where: - ``Random_IV`` is the initial vector to be used to generate a new EKB blob. - "EKB plaintext" is a user-defined key in plaintext. #. ``EKB_cmac`` is the authentication code to be used to determine whether the message had been changed. Compute ``EKB_content`` (an intermediate result) as: ``EKB_content`` = ``Random_IV`` + ``EKB_ciphertext`` Then compute ``EKB_cmac`` as: ``EKB_cmac`` = AES-CMAC(Key=``EKB_AK``, ``EKB_content``) #. EKB blob = EKB Header + ``EKB_cmac`` + ``EKB_content`` EKB Extraction ############## The following outline shows the most logical sequence of operations for extracting information from an EKB. It is essentially the reverse of the process for EKB generation. #. Compute the CMAC: AES-CMAC_verify(``EKB_cmac``, Key=``EKB_AK``, ``EKB_content``) #. Compare the computed CMAC to the CMAC in the EKB. If they match, proceed. #. Compute the EKB plaintext: EKB plaintext = AES-128-CBC_decrypt(IV=``Random_IV``, Key=``EKB_EK``, ``EKB_ciphertext``) Tool for EKB Generation ####################### Before you generate the EKB blob, see the `Secure Boot `__ topic for information about burning keys into fuses, including the KEK2 fuse, and the Secure Boot requirements for using OP-TEE on Jetson devices. As `KDF of Fuse Keys <#kdf-of-fuse-keys>`__ explains, you can generate the fixed vector (FV) or the user-defined key by running the ``openssl`` tool from the command line. You can generate these items separately and store them in different files. Note that you must use the same FVs for EKB extraction as for EKB generation. Exercise due caution to keep the FVs confidential. This example shows how to run the EKB generation tool:: $ python3 gen_ekb.py -kek2_key -fv -in_sym_key \ -in sym_key2 -out Where: - ```` is the key that is stored in the KEK2 fuse. - ```` is a fixed vector (FV) for deriving an RK from the KEK2 fuse. It must be the same as the FV used in ``jetson_user_key_pta`` to derive the KEK2 RK for EKB encryption and decryption. - ```` is the kernel encryption key. The key must be the same as the user key used in the flash command. (See :ref:`To sign and flash in one step using the user, SBK, and PKC keys ` in the topic :ref:`Secure Boot `.) The encryption key must be the same as the one used to encrypt custom-built kernel images. (See the same topic.) .. todo:: There used to be a reference to "SD.Security.SecureBoot-SigningAndEncryptingKernelKernelDtbInitrdAndExtlinuxConfFiles" here, but we gutted SecureBoot.rst and have a placeholder there now. Restore this reference when SecureBoot.rst is fleshed out. - ```` is the disk encryption key. This key is used in two reference implementations. One is the secure sample implemented by hwkey-agent and hwkey-app. This sample uses the key for data encryption and decryption. In another case, the key is the source key of the key generation of the LUKS key in the disk encryption reference implementation. - ```` is an image file generated from the Encrypted Binary Blob (EKB) file by the EKB generation tool. The output binary blob file is intended to be flashed onto the EKS partition of the device. .. todo:: Long variable names are hard to read, and even harder to distinguish from one another. Can we shorten these? I propose ````, ````, ````, ````, and ````. The definitions would remain the same. EKB Extraction Sample ##################### For an example of how to perform EKB extraction, see the source code for the ``jetson_user_key_pta`` trusted application. AES-256 Hardware Key Derivation Function in jetson_user_key_pta @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ A Jetson Linux trusted OS (TOS) has a hardware-based key derivation function (KDF), which you can use to generate derived keys from the Key Encryption Key (ODM KEK) fuses. Flow of the AES-256 Hardware KDF ################################ This diagram shows the flow of key derivation from the ODM KEK fuse. .. figure:: OpTee/FlowOfTheAes256HardwareKdf.svg :alt: The random number generator's service model :figwidth: 650 px You can address and load the ODM KEK fuses KEK0 and KEK1 as separate 128-bit fuses or as a single 256-bit fuse, as shown in this table: +----------------------------------------------------------------------------------+ | ODM KEK fuses related to Secure Boot | +------------+--------+----------+-------------------------------------------------+ | Bit size | Name | Key slot | Default value set by ``odmfuse.sh``. | +============+========+==========+=================================================+ | 128 | KEK0 | 13 | Four 32-bit registers named KEK00 through KEK03.| +------------+--------+----------+-------------------------------------------------+ | 128 | KEK1 | 12 | Four 32-bit registers named KEK10 through KEK13.| | | | | | +------------+--------+----------+-------------------------------------------------+ | 256 | KEK256 | 13 | Not a distinct fuse; addresses KEK0 and KEK1 as | | | | | a single 256-bit fuse. | | | | | | +------------+--------+----------+-------------------------------------------------+ | 128 | KEK2 | 11 | Four 32-bit registers named KEK20 through KEK23.| +------------+--------+----------+-------------------------------------------------+ .. todo:: All r34-supported devices support OP-TEE; do all of them conform to this table? I have assumed that they do, and have dropped the device names from the caption. If not, we need an additional table for Jetson AGX Orin. The ``BctKEKKeySelect`` flag in the BootROM Boot Configuration Table (BR BCT) determines how BootROM loads KEK0 and KEK1 into the Security Engine (SE) keyslot(s): - If the flag is set to 0, BootROM loads the KEK0 and KEK1 fuses as two 128-bit keys. - If the flag is set to 1, BootROM loads the fuses as a single 256-bit key. BootROM loads the BR BCT from a configuration file that is stored in the directory at ``${Linux_for_Tegra_folder}/‌bootloader/‌t186ref/‌BCT/``. The file’s name is: - For Jetson Xavier NX series: ``tegra194-br-bct-qspi.cfg`` - For Jetson AGX Xavier series: ``tegra194-br-bct-sdmmc.cfg`` .. todo:: For Jetson AGX Orin, what is it? To set the flag to 1, for example:: BctKEKKeySelect = 1; After BootROM identifies the key provision source from a setting in BR BCT, you can use the hardware-based NIST-SP 800-108 KDF to derive keys from the ODM KEK fuse. The KDF generates the derived keys. The ``odmfuse.sh`` script can use the options ``--KEK0`` and ``--KEK1`` to burn KEK0 and KEK1 as separate 128-bit keys, or the option ``--KEK256`` to burn them as a single 256-bit key. API Functions ############# Jetson OP-TEE OS provides API functions for you to use with your TAs. These APIs are provided in the OS layer and exported to user space TAs via the interface from a PTA. The Jetson platform provides several API functions for calling the hardware random number generator (RNG). Hardware Random Number Generator Calls $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ - To call from the hardware RNG driver: .. code-block:: c /* * Get random bytes from the SE RNG module * * *data_buf [out] the output of the random data buffer * data_len [in] the length of the random bytes */ TEE_Result tegra_se_rng_get_random(void *data_buf, uint32_t data_len); You can use this function in the OS layer. .. todo:: I'm not sure how "from the hardware RNG driver" and "in the OS layer" fit together, but it seems to me that these two conditions, taken together, must be either duplicative or contradictory. If so, one or the other should be dropped, or both should be replaced with a single different condition. - To call via OP-TEE OS hooks to the hardware RNG driver: .. code-block:: c /* * crypto_rng_read() - read cryptograhically secure RNG * @buf: Buffer to hold the data * @len: Length of buffer. * * Eventual queued events are also added to their pools during this * function call. */ TEE_Result crypto_rng_read(void *buf, size_t len); You can also use this function in the OS layer. - The TEE API for a user space TA to query random numbers from the TOS. This hooks to HW RNG as well. .. code-block:: c /* Cryptographic Operations API - Random Number Generation Functions */ void TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen); - The user space TA can access the hardware RNG via the interface of command IDs ``JETSON_USER_KEY_CMD_GET_RANDOM`` through ``jetson_user_key_pta``. Key Definition Function Calls $$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Key definition function calls implemented by OP-TEE in Jetson Linux are: - The hardware-based NIST-SP 800-108 KDF for OS-layer PTA. This function implements counter-mode KDF with AES-CMAC as the PRF. .. code-block:: c /* * A hardware-based NIST-SP 800-108 KDF; * derives keys from the SE keyslot. * * Use this function only during OP-TEE initialization at boot time * (the device boot stage). To derive keys from a key buffer at runtime, * use nist_sp_800_108_cmac_kdf(). * * keyslot [in] the SE keyslot where the key stores. * key_len [in] length in bytes of the input key. * *context [in] a pointer to a NIST-SP 800-108 context string. * *label [in] a pointer to a NIST-SP 800-108 label string. * dk_len [in] length of the derived key in bytes; * may be 16 (128 bits) or any multiple of 16. * *out_dk [out] a pointer to the derived key. The function stores * its result in this location. */ TEE_Result tegra_se_nist_sp_800_108_cmac_kdf(se_aes_keyslot_t keyslot, uint32_t key_len, char const *context, char const *label, uint32_t dk_len, uint8_t *out_dk); - The software-based NIST-SP 800-108 KDF for OS-layer PTA. This function implements counter-mode KDF with AES-CMAC as the PRF. .. code-block:: c /* * A software-based NIST-SP 800-108 KDF. * derives keys from a key in a key buffer. * * *key [in] input key for derivation. * key_len [in] length in bytes of the input key. * *context [in] a pointer to a NIST-SP 800-108 context string. * *label [in] a pointer to a NIST-SP 800-108 label string. * dk_len [in] length of the derived key in bytes; * may be 16 (128 bits) or any multiple of 16. * *out_dk [out] a pointer to the derived key. The function stores * its result in this location. */ TEE_Result nist_sp_800_108_cmac_kdf(uint8_t *key, uint32_t key_len, char const *context, char const *label, uint32_t dk_len, uint8_t *out_dk); - The user space TA can access the software-based NIST 800-108 KDF via the interface of command IDs ``JETSON_USER_KEY_CMD_GEN_KEY`` through ``jetson_user_key_pta``. - The HW AES-ECB KDF. .. code-block:: c /* * SE AES ECB KDF - Derives root key from SE keyslot. * * derived_key [out] pointer of the output buffer of the derived_key. * derived_key_len [in] the length of the derived_key. * iv [in] pointer of the initial vector. * iv_len [in] the length of the initial vector. * keyslot [in] SE keyslot. */ TEE_Result tegra_se_aes_ecb_kdf(uint8_t *derived_key, size_t derived_key_len, uint8_t *iv, size_t iv_len, uint32_t keyslot);