Firmware TPM

Applies to the Jetson AGX Orin series, Jetson Orin NX series, and Jetson Orin Nano series.

Before you begin, please reference the TCG website to get familiar with the Trusted Platform Module (TPM) specification and knowledge.

The Firmware TPM (fTPM) implementation is done by leveraging the official TCG reference implementation of the TPM 2.0 specification. The reference implementation includes a sample fTPM Trusted Application (TA) and is designed to be executed with OP-TEE.

Software Architecture

The TPM component, either fTPM or a hardware-based discrete TPM (DTPM), relies on the TPM Software Stack (TSS) to talk with the TPM. The fTPM software architecture includes a fTPM TA running in OP-TEE with the TSS support in the non-secure world.

fTPM SW Architecture

Non-secure World

The SW modules in the non-secure world:

  • TPM Software Stack (TSS): The user space applications depend on TSS to utilize the secure functionalities of the TPM. The open source implementation tpm2-software/tpm2-tss is available on GitHub and consists of three types of APIs:

  • TPM2 Tools: This is a set of TPM2 command tools that you can use it to control the TPM via command line interface (CLI). The open source implementation tpm2-tools is available on GitHub.

  • fTPM driver: The fTPM driver is a client application (CA) that receives the TPM command byte stream or Command Response Buffer (CRB) and bypasses the data to the fTPM TA in the secure world.

  • OP-TEE driver: The OP-TEE driver provides the TA/CA communication interface.

Secure World

The SW modules in the secure world:

  • Secure Monitor: This is an S-EL3 firmware that helps handle the communication between secure and non-secure worlds.

  • OP-TEE OS: A Trusted OS (TOS) running in S-EL1 to provide security service in the TrustZone.

  • fTPM Helper PTA: The fTPM Helper PTA provides two major functions to support fTPM provisioning, EPS generation and EK certificate provisioning.

  • fTPM TA: The TA should implement TPM command functions and platform-dependent functions that meet the TCG TPM2 specification. The ms-tpm-20-ref reference implementation is available on GitHub.

  • MB2: The secure bootloader that helps derive the fTPM seed from the hardware fuse. The fTPM seed is a per-device, unique, secure value used for EPS generation.

  • EKB: The Encrypted Keyblob (EKB) packages the per-device unique properties for fTPM provisioning support.

The fTPM Boot Flow

fTPM Boot Flow

The fTPM boot flow is a process that verifies and measures the integrity of firmware components during the boot process.

fTPM Secure Boot

Secure boot is an essential part of the fTPM boot flow. It ensures that only authorized firmware components are loaded during the boot process and establishes Hardware Root of Trust (HROT), Root of Trust for Reporting (RTR), and Root of Trust for Measurement (RTM). The purple line in the diagram shows the secure boot flow, which indicates that the boot components load and verify the next stage boot components.

The fTPM relies on secure boot to support a key derivation process to derive fTPM related secure values. You can refer to Key Derivation Process and Silicon ID Provisioning Flow.

fTPM Measured Boot

Measured boot is another critical component of the fTPM boot flow. This involves measuring the code and data used at boot time, such as bootloaders, firmwares, and the kernel, to ensure they have not been tampered with.

Measured boot uses a TPM to store measurements of firmware components, which can be later verified to ensure the system has not been compromised.

The Measured Boot support of fTPM is based on the Platform Configuration Register (PCR). The PCR is a component of the TPM that plays a crucial role in ensuring the integrity and trustworthiness of a platform. A PCR is essentially a secure, tamper-proof storage location for hash values, which are used to verify the authenticity and consistency of various components within the boot chain.

The green line shows the boot components measuring the measurements of the next stage boot components. Before the fTPM is ready, the measurements can be stored in the format of TPM event log, which is a standard data structure to indicate the PCR and measurement you want to extend. During the fTPM boot process, it needs to handle the TPM event log to extend the PCR with the measurements. After fTPM brings up, all the measurements should go through the TPM2 PCR extend command only.

The fTPM Provisioning

A fundamental difference exists between a DTPM and fTPM. A DTPM or a TPM chip has been provisioned by the TPM vendor or manufacturer with the Endorsement Key (EK) certificate, which is the TPM identification that can be used for TPM attestation. Without this certificate, the trust between the TPM user and the services that relies on TPM cannot be constructed.

To create a trustworthy fTPM entity on different devices, you need to provision it with a per-device unique ID, the EK certificate, and this needs to be done during the device manufacturing process.

The fTPM provisioning refers to the process of configuring and initializing a firmware-based TPM on a Jetson device.

fTPM provisioning involves three main steps:

  1. Initialization: The fTPM TA is initialized by the Trusted OS (OP-TEE) during the early secure boot stage.

  2. Configuration: The fTPM is configured with the settings such as Endorsement Primary Seed (EPS), EK certificate, owner password, and other parameters.

  3. Key generation: The fTPM generates a unique EK and storage root key (SRK), which are used to secure sensitive data.

The fTPM provisioning process we designed to make the Jetson device deal with the fTPM manufacturer Certificate Authority (CA) server. This process needs the fTPM manufacturer to pre-generate the EK certificates and encode it into the Encrypted Keyblob (EKB). It needs to be completed during the device manufacturing process. When the device boots up, you need to run the provisioning tool to query the EK certificates from EKB and store them in the fTPM non-volatile (NV) memory.

There are two methods of provisioning methods: offline provisioning and online provisioning.

  • Offline provisioning method

  • The offline provisioning method needs the fTPM manufacturer to pre-generate the EK certificates and encode it into the Encrypted Keyblob (EKB). This process needs to be completed during the device manufacturing process. When the device boots up, you need to run the provisioning tool to query the EK certificates from EKB and store them in the fTPM non-volatile (NV) memory.

  • Online provisioning method

  • The online provisioning method depends on a three-way handshake protocol between the CA and the device, which validates the device’s identity in order to sign the EK Certificate Signing Request (CSR) and issue the EK certificate.

  • Note: For this release, only the offline provisioning method is supported. The online provisioning method will be available in the future fTPM release.

Preparation Before The fTPM Provisioning Process (Offline Method)

The Prerequisites of the fTPM Vendor

  • The fTPM vendor can be an ODM/OEM who manufactures a Jetson-based device and enables fTPM, or an end-customer who deploys the product and enables fTPM. Typically, the fTPM vendor does the following:

  • This role is identical to the DTPM vendor or manufacturer and is the Original Design Manufacturer (ODM) of the fTPM provisioning support.

  • It should be a third-party service provider with expertise in fTPM production. (Assuming that the Jetson device builder prefers to use a third-party service to sign and issue the fTPM EK certificates.)

  • It should be able to set up a secure environment to work with the fTPM provisioning process.

  • The CA server held by the fTPM vendor should be acknowledged by the popular cloud service provider with which devices are designed to be enrolled.

  • It should meet the requirements for preparing and generating materials for fusing the devices and keeping them secure.

  • It should support multiple Original Equipment Manufacturers (OEMs) which means that the fTPM vendor should work with multiple OEMs and maintain and isolate the materials for different OEMs.

  • The requirements of the material preparation and the generation work.

  • The per-device basis KDK0, Device_SN, Silicon_ID, and Silicon_ID public key generation.

  • This can be done by running the kdk_gen.py KDK Gen tool, where:

  • KDK0 is a secret per-device unique 256-bit random value.

  • SN is a per-device unique serial number.

  • OEM_ID is an OEM_ID number for different OEMs.

  • Device_SN is the concatenation of OEM_ID and SN where OEM_ID and SN are in the big-endian form.

  • The public key of Silicon_ID

  • This public key can be used for the fTPM provisioning tool to verify the materials signed by the Silicon_ID private key.

  • The public key is generated by Silicon_ID where:

  • Silicon_ID is KDF(key=KDK0, Device_SN).

  • The asymmetric key pair of Silicon_ID is ECC_P256_key_gen(seed=Silicon_ID).

  • The private key should be dropped immediately.

  • Note: The KDK0 should be discarded after the corresponding fuseblob, the EK, and the EK-associated certificate are generated. The purpose of not keeping it in storage is to avoid potential leaks.

  • The per-device basis fuseblob generation.

  • This task can be completed by running the FSKP tool (fskp_fuseburn.py).

  • Here is a list of the properties that are related to the fTPM:

  • Fuse_ODM_INFO is ${OEM_ID}.

  • Fuse_ODMID0/1 is ${SN}.

  • Fuse_KDK0 is ${KDK0}.

  • The per-device basis fTPM EKB generation, which is a task that can be completed by running the odm_ekb_gen.py ODM EKB Gen tool. These are the fTPM EKB properties:

    • Device_SN

    • EPS Seed: A 256-bit random number that will be used for the EPS deriving process.

    • EK Certificates (RSA and EC): The tool generates the EK Certificate Signing Request (CSR) and sends it to the CA server. The certificate will then be issued by the CA server after signing the EK CSR.

  • The database generated by the fTPM manufacturer:

  • ${Device_SN}

  • $(Silicon_ID_PUB_KEY)

  • ${EPS_Seed}

  • ${EK_Cert}

The preparation work of the fTPM Vendor

Signing the EK CSRs

After the per-device EK CSR has been generated, the EK CSR needs to be signed by the fTPM manufacturer CA, and the CA returns the EK certificate. The EK should support two algorithms RSA and EC. During the preparation period, the fTPM vendor should prepare two EK CSRs for the two algorithms and store the two certificates in the storage.

This file name format is ek_${CERT_TYPE}_${KEY_TYPE}-${OEM_ID}-${SN}.der.

  • CERT_TYPE: csr or cert.

  • KEY_TYPE: rsa or ec.

  • OEM_ID and SN: same as the definition above.

Signing the EK CSRs
EK CSR Customization

The EK Certificate layout should conform to the specification of TCG EK Credential Profile. To customize the EK CSR, we should comply with the specification. You can modify the contents defined in the script ftpm_manufacturer_gen_ek_csr_tool.py to update accordingly.

Here is the default layout of the EK CSR with EC key type.

Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = US, O = ftpm corp, CN = 0000-0000000000000000_ftpm-ek-cert
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:45:41:66:45:ef:5e:fb:fd:a0:50:50:14:95:30:
                    0c:05:d2:97:71:d5:41:25:86:91:8d:52:ac:e7:f1:
                    60:0a:8e:b8:92:b7:29:e1:e8:20:cc:84:02:ab:bf:
                    24:57:db:2c:00:12:69:15:a3:cc:49:d9:69:06:35:
                    83:c3:77:62:56
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        Attributes:
            Requested Extensions:
                X509v3 Key Usage: critical
                    Digital Signature, Key Agreement
                X509v3 Basic Constraints: critical
                    CA:FALSE
                X509v3 Subject Alternative Name:
                    DirName:/2.23.133.2.1=id:4D534654/2.23.133.2.2=SSE fTPM/2.23.133.2.3=id:20180710
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:44:02:20:6f:40:a6:0a:d2:84:8d:45:26:2c:14:4a:be:59:
        7a:30:3c:7f:1e:92:70:25:10:40:00:f2:72:2a:89:0b:0c:ba:
        02:20:61:68:58:8a:21:2a:c4:8d:0b:d7:8d:76:c2:d4:c0:ee:
        50:61:c1:1e:dd:a0:6b:3c:cc:f6:24:77:62:38:75:53

Field Name

Value

Subject

Must assign a unique common name (CN). The default format of CN is ${OEM_ID}-${SN}_${FTPM_VENDOR_DEFINED_STR}. Organization Name (ON): The fTPM manufacturer name. Country Name (CN): Country name.

Key Usage

Follow the specification to define key usage according to the EK type.

Basic Constraints

Must be critical and set the CA property to FALSE.

Subject Alternative Name

This field contains the value of TPM Manufacturer, TPM Model, and TPM Version. You must update this field according to the documentation TCG TPM Vendor ID Registry. And rebuild fTPM TA after updating ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/VendorString.h.

Using fTPM Manufacturer CA

To sign the fTPM EK CSR by fTPM manufacture CA, you need to replace the script ftpm_manufacturer_ca_simulator.sh to engage with the CA CSR signing interface.

Here is the reference layout of the fTPM EK certificate.

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            75:88:3f:e9:34:86:fb:d3:6c:fc:b2:92:23:84:c1:02:c3:8d:92:5e
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O = fTPM CA Sim C01, OU = fTPM Manufacturer CA Sim I01, CN = fTPM Sim Intermediate CA, C = US
        Validity
            Not Before: Jun  1 00:00:00 2023 GMT
            Not After : Dec 31 23:59:59 2033 GMT
        Subject: C = US, O = ftpm corp, CN = 0000-0000000000000000_ftpm-ek-cert
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:45:41:66:45:ef:5e:fb:fd:a0:50:50:14:95:30:
                    0c:05:d2:97:71:d5:41:25:86:91:8d:52:ac:e7:f1:
                    60:0a:8e:b8:92:b7:29:e1:e8:20:cc:84:02:ab:bf:
                    24:57:db:2c:00:12:69:15:a3:cc:49:d9:69:06:35:
                    83:c3:77:62:56
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Agreement
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name:
                DirName:/2.23.133.2.1=id:4D534654/2.23.133.2.2=SSE fTPM/2.23.133.2.3=id:20180710
            X509v3 Authority Key Identifier:
                9E:8C:19:9A:4D:20:6B:75:D5:87:64:86:8F:5D:96:89:7B:F1:B8:65
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        1c:0c:00:84:ec:fa:c8:29:3d:62:5c:1e:34:26:85:cf:3f:64:
        41:a7:b4:0c:86:67:f6:04:a3:32:69:4d:79:b2:ed:c9:d9:0f:
        b4:79:71:76:92:5e:8d:dc:d0:4f:43:bb:ef:d9:f4:aa:ab:36:
        98:7d:bd:a6:ce:e7:9b:a6:8b:53:ee:7b:95:d9:10:9d:b8:02:
        e6:62:58:55:b9:38:32:9c:57:7c:2d:0d:87:0f:b7:e2:11:3b:
        64:ae:47:29:ca:b9:cc:b0:1c:a1:54:4c:75:4f:17:eb:aa:8c:
        40:eb:31:71:a6:e8:52:ad:dd:9b:4b:f0:f7:a6:7a:27:6f:80:
        e1:04:86:8b:38:e9:3f:f7:c8:a4:a8:b6:ee:38:5b:8d:c0:33:
        73:10:94:92:63:25:8e:f4:ae:93:4b:d2:4a:9a:50:88:cc:ae:
        47:8c:ad:f9:41:b2:a7:9d:d5:85:4a:9e:1b:70:a7:99:c2:e9:
        10:b7:74:1a:df:b2:8b:c7:6f:a8:9e:37:d4:65:9f:70:ec:eb:
        3d:4c:48:90:7c:73:1c:fb:cc:c1:c3:29:3c:39:7d:cd:9a:68:
        29:43:47:7b:c3:8c:0f:22:1a:fb:38:23:d1:cc:1e:78:f0:ed:
        e4:92:51:14:ec:d4:87:34:3f:2f:c9:df:b3:39:81:7e:af:9e:
        34:74:b4:0f

Generating Per-device EKB

The offline provision method aims to create a per-device EKB image with the device’s fTPM properties:

  • Device_SN

  • EPS Seed

  • Two EK Certificates (RSA and EC).

The ODM EKB Gen Tool encodes the fTPM properties into the EKB image and the output of the per-device EKB images is saved as an unencrypted binary file with the OEM_ID and SN as the filename index.

Generation per-device EKB

Here is some important information about the EKB contents:

EKB also contains device manufacturer (OEM) defined keys such as the UEFI payloads encryption key, the UEFI variable authentication key, and the disk encryption key (called user keys in general). After the per-device-based fTPM property EKB, which is called fTPM_EKB, is generated in plain binary form by the fTPM manufacturer (by running odm_ekb_gen.py), the ftpm_EKB is sent to the device manufacturer so that the user keys can be added by running oem_ekb_gen.py by the device manufacturer.

The final result EKB that contains the fTPM_EKB, and user keys is encrypted and signed by K1-derived keys. K1 is owned by the device manufacturer and is burned to OEM_K1 fuse through OEM_fuseblob.

Note

The fTPM Production Flow section provides more information about fuseblob generation and burning by using the FSKP tool.

The Key Derivation Process to Support fTPM

This section provides a list of the prerequisites to use Jetson Secure Bootloaders. The fTPM provisioning process relies on the secure boot support on the Jetson platform. The secure boot function should construct Hardware Root of Trust (HROT), Root of Trust for Reporting (RTR), and Root of Trust for Measurement (RTM) because they are needed for the device attestation in the fTPM provisioning process.

The Trusted Computing Base (TCB) of the Jetson platform consists of the security-relevant components that have been loaded at the stage of the secure boot chain.

The secure boot chain
  • The role in the secure boot chain

  • The hardware and ROM are the HROT of secure boot and also the RTR and RTM of the secure boot on the device.

  • FUSE

  • KDK0: A secure fuse slot on Jetson Orin. It will be used to derive the Silicon_ID.

  • ROM

  • This includes the ROM and ROM extension code.

  • PSCROM and BootROM are the static and fixed codes stored in the ROM.

  • PSCBL and MB1 are the ROM extension code to execute the bottom half of the initial boot.

  • First Mutable Code (FMC)

  • MB2 is the boot loader that handles the construction of the components for fTPM provisioning support.

  • Firmware

  • Trusted OS (TOS) is the trusted firmware that includes ARM Trusted Firmware (ATF), OP-TEE OS with the fTPM, and fTPM helper TAs.

Silicon ID Provisioning Flow in Secure Boot

The Silicon ID provisioning flow along the TCBs in the secure boot chain. There are three layers:

  • Hardware and ROM (PSCROM, BootROM, PSCBL, and MB1).

  • FMC (MB2).

  • Firmware (TOS).

The purpose of this flow is to generate a Silicon ID and fTPM seed. The security mechanism of the key generation flow uses the TZ-SE, which is the hardware Security Engine in the TrustZone, but the keyslot is not accessible by the CPU. The fTPM Seed is passed to OP-TEE using encrypted TZ memory and is used to derive the EPS during the fTPM provisioning process.

The Silicon ID generation flow:

  • In the PSCBL layer:

  • Silicon_ID is the KDF(key=KDK0, Device_SN)

  • The Device_SN is a unique number that comprises an OEM_ID and a unique SN.

  • In the MB2 layer:

  • fTPM Seed

  • The fTPM Seed is KDF(key=Silicon_ID, constant str1).

  • Silicon ID Key Seed

  • The Silicon ID Key Seed is KDF(key=Silicon_ID, constant str2).

  • The Silicon_ID key pair

  • The Silicon_IDkey pairis f(ECC, NIST P256)KEYGEN(seed=Silicon_ID_Key_Seed).

EPS Derivation Flow in the OP-TEE OS Layer

The Endorsement Primary Seed (EPS) is the ROT of the fTPM entity and is tied with the EK, which can be used to attest the TPM identity and the keys generated by the TPM. The EPS is derived from the TOS layer of TCB in the Jetson device. The fTPM helper PTA in the OP-TEE OS implements the EPS derivation process by using the fTPM Seed from the bootloader and the fTPM property EPS_Seed in the EKB.

The EPS will be injected into fTPM TA during the TA’s first start-up time and stored in NV memory.

  • In the fTPM helper PTA layer:

  • Here is the EPS derivation flow:

  1. Device_SN is fuse_read(ODMID, ODM_INFO).

  2. fTPM Root Seed

  • The fTPM Root Seed is KDF(key=fTPM_Seed, constant str).

  1. EPS

  • The EPS is KDF(key=fTPM_Root_Seed, info=Device_SN, salt=EPS_Seed).

Note

  • The EPS Seed is a random number that is generated by odm_ekb_gen.py and stored in EKB.

The fTPM Production Flow

The fTPM production flow is the design of provisioning an EK certificate by the fTPM manufacturer who owns the CA and fTPM manufacturing server and is qualified to issue the certificate. This should be done in a secure environment during the fTPM manufacturing process.

Here are the requirements of the fTPM Manufacturer Server:

  • This server should be a secure environment and have Hardware Secure Module (HSM) support.

  • This server is responsible for generating the materials for fTPM production.

Here are the requirements of the fTPM Manufacturer CA:

  • The CA MUST verify fTPM residency of a key before signing a certificate. This can be done by verifying the signature of the EK CSR.

  • The CA SHOULD support a standard certificate transport protocol that provides protection from replay attacks and provides confidentiality and integrity.

fTPM Production Flow

The diagram shows the fTPM production flow.

Here are the roles in the diagram:

  • The fTPM Design Manufacturer (aka ODM):

    • Is the owner of the fTPM manufacturer server and the fTPM manufacturer CA.

    • Delivers the fTPM packages to OEM.

  • The OEM Manufacturer:

    • Owns the OEM defined fuse keys.

    • Owns the user-defined keys in EKB.

    • Owns the OS bootloader e.g. UEFI and UEFI payloads such as L4TLauncher.

    • Owns Platform Vendor (PV) keys that encrypt and sign UEFI image.

    • Generates the packages for production.

  • The OEM Manufacturer Factory assembles, fuses, and flashes the devices.

Here is the fTPM production flow:

  • ODM Fuseblob Generation

    • The keys and materials, such as ODM_KDK0, SN, PKC, and SBK keys, which are owned by ODM are generated.

  • The ODM fuseblob is generated.

    • Run the “KDK Gen Tool” (kdk_gen.py) to generate ODM_KDK_db (db refers to database).

    • Run the fuse burn tool (fskp_fuseburn.py) with ODM_KDK_db and PKC, SBK keys as input.

      • The ODM FSKP key will be used as the signing and encryption key to generate the ODM signed ODM_fuseblob_db.

  • The fuseblobs are stored in the database.

    • The fuseblob database (ODM_fuseblob_db) is a list of individual files, such as odm_fuseblob-${Device_SN}.bin.

  • OEM Fuseblob Generation

    • The fuse keys owned by OEM such as OEM_K1 and OEM_K2.

      • The PSC_ODM_STATIC fuse is owned by OEM as well.

      • The OEM fuseblob is generated.

        • Run the fuse burn tool (fskp_fuseburn.py) with the OEM fuse configuration XML file.

          • The field such as OEM_K1, OEM_K2, PSC_ODM_STATIC, etc, should be filled in the configuration file.

          • The OEM FSKP key will be used as the signing and encryption key to generate the OEM signed OEM_fuseblob.

  • The ODM EKB Generation Phase 1

    • The EPS Seed and EK Certificates are generated.

      • This will use the fTPM Gen CSR tool to generate the fTPM EK CSRs.

      • The EK CSRs should be delivered to the CA and signed by the CA.

      • The CA returns the EK certificates.

    • The EKB_ftpm_db is generated.

      • Run the ODM EKB Gen tool (odm_ekb_gen.py) with the ODM_KDK_db as the input.

    • Send the EKB_ftpm_db to OEM.

  • OEM EKB Generation

    • The user-defined keys that will be encoded into EKB are generated.

    • Run the OEM EKB Gen tool (oem_ekb_gen.py) to merge the EKB_ftpm_db and user-defined keys.

      • Use the OEM_K1 key as the encryption key to generate OEM encrypted EKB_final_db.

    • Send the EKB_final_db to ODM for signing, using the ODM owned PKC key.

  • ODM EKB Generation Phase 2

    • Receiving and storing the EKB_final_db.

  • ODM Packages Generation

    • Generating the QSPI image, for example, you can run the flashing tool with PKC and SBK keys to generate, sign, and encrypt images for all partitions on QSPI.

    Note

    The generated UEFI and EKB are used only as placeholders. The final UEFI is generated and signed by OEM, and the final EKB is loaded from EKB_final_db.

    • Sign and encrypt the EKB_final_db by using PKC and SBK keys and output EKB_db.signed.

    • Generate the per-OEM packages.

      • ODM_fuseblob_db, QSPI image, and EKB_db.signed

    • Send the packages to OEM.

Note

ODM_fuseblob_db contains a list of encrypted and signed fuseblobs including odm_fuseblob-<OEM_ID>-<SN>, odm_fuseblob-<OEM_ID>-<SN+1>, and so on. EKB_db.signed contains a list of PKC and SBK signed and encrypted EKB such as ekb-<OEM_ID>-<SN>.signed, ekb-<OEM_ID>-<SN+1>.signed, and so on. It is a one-to-one mapping between odm_fuseblob-<OEM_ID>-<SN> and ekb-<OEM_ID>-<SN>, and the flashing tool ensures ekb-<OEM_ID>-<SN> is only flashed to the device with fuseblob-<OEM_ID>-<SN> burned.

  • OEM Packages Generation

    • Generate the complete QSPI image package.

    • Generate the mass storage (eMMC or NVMe) image package.

    • Deliver the package to the factory.

  • OEM Factory

    • Burn the OEM fuseblob.

    • Burn the per-device basis ODM fuseblob.

    • Flash the device.

      • Flash the QSPI and the mass storage.

      • Flash the per-device basis EKB image.

The fTPM Production Flow When ODM and OEM Are in the Same Entity

The fTPM production flow involves collaboration between ODMs and OEMs to create and generate per-device basis fuse blobs and images. However, there is a case where the same entity is capable of playing both ODM and OEM roles, which means, it can handle the fTPM functional design, EK certificate signing, device image signing, and device manufacturing. In such cases, the UEFI PV key feature can be skipped, simplifying the fTPM production flow. The same PKC key used to sign low-level firmwares is also used to sign the UEFI image. For detailed flow and command samples, please refer to Appendix B.

The Software Architecture to Support fTPM Provisioning

The SW Architecture of fTPM Provisioning

The Software Components:

  • fTPM provisioning script

    • This sample script handles the fTPM provisioning process on the Jetson device.

    • The provisioning process on the device:

      • Querying the EK certificates from the EKB.

      • Storing the EK certificate to the fTPM NV memory.

      • Taking ownership of the fTPM.

      • Creating EK accordingly with the default EK handles.

    • The provisioning process only needs to be activated once.

    • This script should be bundled with the fTPM support package provided by the fTPM design manufacturer (ODM).

  • The fTPM helper TA/CA and PTA

    • They are the applications designed for fTPM provisioning support.

    • fTPM helper CA

      • The fTPM helper CA provides the command line interface (CLI) for the script to query the EK certificates from the EKB.

    • fTPM helper TA

      • The fTPM helper TA provides the interfaces to support the fTPM helper CA.

      • It helps to query SN and EK certificates.

  • fTPM helper PTA

  • The fTPM helper PTA helps to gather the fTPM properties from MB2 and EKB.

  • The fTPM helper PTA retrieves Device SN from the fuse and makes sure it matches with the Device SN in EKB.

  • The EPS derivation function is executed by the PTA.

  • fTPM TA

    • The fTPM TA should support the TPM2 functionalities defined by TCG.

    • The TPM2 function in the fTPM TA should be a black box. It should NOT provide any interface other than TCG defined to access the TPM internal functions.

    • The fTPM TA gets the EPS from the fTPM helper PTA during the first startup time and stores the EPS in the NV memory.

The fTPM Provisioning and Activation Flow

The fTPM Provisioning and Activation Flow

Cheat Sheet

Jetson BSP Installation

  1. Download the latest BSP from Jetson Linux Archive.

    • The Jetson BSP: jetson_linux_${rel_ver}_aarch64.tbz2

    • The sample root filesystem: tegra_linux_sample-root-filesystem_${rel_ver}_aarch64.tbz2

    • The public source tarball: public_sources.tbz2

    • The toolchain (Optional): aarch64--glibc--stable-${rel_date}.tar.gz

  2. Download the FSKP package. This is a partner release package. Please download it separately.

  3. Create a ${BSP_TOP} folder.

    mkdir ${BSP_TOP}
    cd ${BSP_TOP}
    
  4. Install the BSP.

    1. Untar the BSP package.

      tar jvxf ~/Downloads/jetson_linux_${rel_ver}_aarch64.tbz2
      
    2. Untar the BSP source package.

      tar jvxf ~/Downloads/public_sources.tbz2
      
    3. Untar the sample RootFS.

      cd Linux_for_Tegra/rootfs
      sudo tar jvxpf ~/Downloads/tegra_linux_sample-root-filesystem_${rel_ver}_aarch64.tbz2
      
    4. Apply the BSP packages.

      cd ${BSP_TOP}/Linux_for_Tegra
      sudo ./apply_binaries.sh
      
    5. Install the FSKP packages.

      cd ${BSP_TOP}
      tar jvxf ~/Downloads/fskp_partner_t234_${rel_ver}_aarch64.tbz2
      
    6. Untar the ATF and OP-TEE source tarball.

      cd Linux_for_Tegra/source/
      tar jvxf atf_src.tbz2
      tar jvxf nvidia-jetson-optee-source.tbz2
      cd ../
      

Set up the Server to Run the fTPM Production Scripts

  1. Install the required Python modules:

sudo apt-get update
sudo apt-get install python3-pip
sudo apt-get remove python3-cryptography
sudo pip3 install asn1crypto
sudo pip3 install cryptography
sudo pip3 install ecdsa
sudo pip3 install numpy
sudo pip3 install oscrypto
sudo pip3 install pyaes
sudo pip3 install pycryptodome
sudo pip3 install pycryptodomex
  1. Fix the issue of asn1crypto manually (Ref link). Apply the fix below into /usr/local/lib/python<PYTHON3_VERSION>/dist-packages/asn1crypto/x509.py.

diff --git a/asn1crypto/x509.py b/asn1crypto/x509.py
index 8cfb2c78be27..761594e1a77d 100644
--- a/asn1crypto/x509.py
+++ b/asn1crypto/x509.py
@@ -686,12 +686,12 @@ class NameTypeAndValue(Sequence):
         'domain_component': DNSName,
         'name_distinguisher': DirectoryString,
         'organization_identifier': DirectoryString,
-        'tpm_manufacturer': UTF8String,
-        'tpm_model': UTF8String,
-        'tpm_version': UTF8String,
-        'platform_manufacturer': UTF8String,
-        'platform_model': UTF8String,
-        'platform_version': UTF8String,
+        'tpm_manufacturer': DirectoryString,
+        'tpm_model': DirectoryString,
+        'tpm_version': DirectoryString,
+        'platform_manufacturer': DirectoryString,
+        'platform_model': DirectoryString,
+        'platform_version': DirectoryString,
         'user_id': DirectoryString,
     }

Supporting Production with fTPM

This section provides information about supporting production with fTPM.

Here are the prerequisites to Enabling fTPM with HW Silicon ID support:

  • The KDK0 is the root key and must be burned with a 256-bit per-device unique secret value.

  • The FUSE_BOOT_SECURITY_INFO must be burned with the following bits:

Bits

Description

[2:0]

The authentication scheme field cannot be zero or over 011b. It must be a valid PKC authentication scheme.

[9]

OEM key valid. This bit must be 1.

[11]

OEM key function. This bit must be 1 to enable the KDF of the OEM fuse key.

[13]

OEM key function. This bit must be 1 to enable the KDF of the Silicon ID generation.

KDK Database and Fuseblobs Generation

This section provides information about generating the KDK database (DB) and fuseblobs.

Generating kdk-db and the Corresponding Silicon ID Public Keys

To generate kdk-db and the corresponding Silicon ID Public Keys, run kdk_gen.py.

# Command line interface of "kdk_gen.py"
kdk_gen.py [-h] [--oem_id ${OEM_ID}] [--sn ${SN}] [--num_devices ${NUM_OF_DEVICES}]

For example, to generate five kdk entries, run the following command.

kdk_gen.py --oem_id 0x102 --sn 0x100000002 --num_devices 5

The above example will generate the following files:

  • kdk_db_0102-0000000100000002-5.csv

  • pubkey_db_0102-0000000100000002-5.csv

Important

Here is some important information:

  • The KDK database will be used to generate fuseblobs.

  • Here is the content of the KDK database:

cat kdk_db_0102-0000000100000002-5.csv
0102 0000000100000002 681a8d62bffb803e9b1068eb4e14af3e440b5a73d0e81d161d2817c24dac41a6
0102 0000000100000003 bfec6db0ddab599b2a34d01ab9e641e3b735d7ead9649579689ed535c73d2053
0102 0000000100000004 801575a8ecd51955f8efcc840af0b6f94a4a0d1e2745f97122d46873c83bd751
0102 0000000100000005 a8d49348cbbf34814b387c7189187a1c98fe03a254503e879232765651dcf0ee
0102 0000000100000006 a8e20c2e0309a6564d0c694c75fcce9b21b846c54dc3b6343a8c276bbbd2dca5
# where the first two columns are oem-id and SN, and the last column is the randomly generated KDK value.

Important

Here are the corresponding Silicon ID public keys:

  • The Silicon ID public key database can be used by the fTPM manufacturer CA to verify the device identity during the fTPM provisioning process.

  • The content of the Silicon ID public key database:

cat pubkey_db_0102-0000000100000002-5.csv
0102 0000000100000002 435ec556a1e23e9a676b8471ff2b2c25ca262bbc7f581abd69de025198cb56d157882fc257c4f544b206796dadf8257d5c4638e70bf8a2f13d9a2b7a30b57c0a
0102 0000000100000003 c25aef9b683cc4a2579bf634e35d42ee40b5e31dccef5dad7a16ab8b860dc2ec25a20ed6391edd8aa871cfa999acf57af1f81f1226e74569b2f3fff549bc0809
0102 0000000100000004 b603792a8d28ed60d5b7a6ac604fb56dfbff475cd225665253c58670c19d9b27ea1e0ec21de9ade7d798d0ada7a180c9625b72c6ec5b6074a265e4e8a90b0f6a
0102 0000000100000005 7c43b790f97769f86839be2ceaedbbba244d727c311d28c21a8f8ff9a911173d53753cb207ee5f7e11298fed41d603731fe709255f17b2fdf0c7113f15d97e11
0102 0000000100000006 ddc67040dbf78afd4a05581dacef51cd2c8cf0554c532b5ffda54f398f98f1136170fcd39ade40ba04db3ece703e0414eb6060cb10de0d7373e2b3a6c1b251ac
# where the first two columns are oem-id and SN, and the last column is the corresponding silicon-id public key.

Generate the Corresponding Fuseblobs

Create a template fuse configuration XML file called fuse_temp.xml like the following template file. Note that ODM and OEM should follow the different template files.

The ODM Fuse Configuration Template
<genericfuse MagicId="0x45535546" version="1.0.0">
   <fuse name="OdmInfo" size="4" value="0xFFFF"/>
   <fuse name="OdmId" size="8" value="0xFFFFFFFFFFFFFFFF"/>
   <fuse name="Kdk0" size="32" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/>
   <fuse name="PublicKeyhash" size="64" value="0x<64-byte-value-PubKeyHash>"/>
   <fuse name="PkcPubKeyHash1" size="64" value="0x<64-byte_value-PubKeyHash1>"/>
   <fuse name="PkcPubKeyHash2" size="64" value="0x<64-byte_value-PubKeyHash2>"/>
   <fuse name="OptInEnable" size="4" value="0x1"/>
   <fuse name="SecureBootKey" size="32" value="0x<32-byte-value-SBK>"/>
   <fuse name="ArmJtagDisable" size="4" value="0x1"/>
   <fuse name="BootSecurityInfo" size="4" value="0x<4-byte_value-SECURITY_INFO>"/>
   <fuse name="SecurityMode" size="4" value="0x1"/>
</genericfuse>
The OEM Fuse Configuration Template
<genericfuse MagicId="0x45535546" version="1.0.0">
   <fuse name="OemK1" size="32" value="0x<32-byte-value-key>"/>
   <fuse name="OemK2" size="32" value="0x<32-byte-value-key>"/>
   <fuse name="PscOdmStatic" size="4" value="0x00000060"/>
</genericfuse>

Note

The field 0x<...> must be replaced with proper values before running fskp_fuseburn.py.

To generate fuseblobs, run fskp_fuseburn.py.

  • For example, you can use the kdk db generated above to create five fuseblobs for AGX Orin.

  • Example for ODM:

sudo ./fskp_fuseburn.py -f fuse_temp_odm.xml \
                        --test \
                        --skipfskpkey \
                        --multi-blob ftpm_kdk/kdk_db_0102-0000000100000002-5.csv \
                        -g odm_out/ \
                        -c 0x23 \
                        --board-spec orin-agx-board-spec.txt \
                        -B ../../../../jetson-agx-orin-devkit.conf

# Create a tarball to send to the FACTORY.
tar cf odm_out_0102-0000000100000002-5.tar odm_out/
  • Example for OEM:

sudo ./fskp_fuseburn.py -f fuse_temp_oem.xml \
                        --test \
                        --skipfskpkey \
                        -g oem_out/ \
                        -c 0x23 \
                        --board-spec orin-agx-board-spec.txt \
                        -B ../../../../jetson-agx-orin-devkit.conf

# Create a tarball to send to the FACTORY.
tar cf oem_out.tar oem_out/

Here are the command-line interface options:

  • -f <fuse_temp.xml>

    • With the fuse template file, a list of corresponding fuse configurations will be generated and stored in the ftpm_kdk directory. In this example, a file list like the following is generated:

    • fusexml_0102-0000000100000002.xml

    • ...

    • fusexml_0102-0000000100000006.xml

  • \-\-test

    • This indicates the generated fuseblob will only do a dry run. To actually burn the fuses, replace –test with -b.

  • \-\-skipfskpkey

    • This indicates that no FSKP key is used, which means the fuseblobs generated are not encrypted. As a result, this option is used only for testing.

    • To generate encrypted fuseblobs for securely burning fuses at the factory, replace --skipfskpkey with the following:

    • -i <key index> \-\-key <fskpkey> or with

    • \-\-key-exp <fskp_ak.bin> <fskp_ek.bin> \-\-fskpcfg <fskp_conf.txt>

  • \-\-multi-blob <kdk_db>

    • Use the content from the pre-generated kdk db to fill in the template fuse configuration XML file.

  • \-\-g <out_dir>/<fuse_blob_prefix>

    • This indicates the generated fuseblob folder. At the factory, the fuseblob are the only binaries needed to burn fuses.

    • For example, you can specify “-g fuse/out”. The fuseblob folders generated will be:

    • fuse/out_<OEM_ID>-<SN>

    • fuse/out_0102-0000000100000002

    • ...

    • fuse/out_0102-0000000100000006

  • -c <chip ID>

    • This indicates the NVIDIA Tegra SoC chip ID.

  • \-\-board-spec <board_spec>

    • This defines the board spec such as BOARDID, SKU, and so on.

  • -B <board_conf>

    • This specifies the low-level boot components, configs, and dtbs that are used for the board to burn the fuses.

Generating ODM EKB

The following scripts are hooked by the ODM EKB Gen tool to generate the EK CSR and sign the EK certificate:

  • ftpm_manufacturer_gen_ek_csr.sh

  • ftpm_manufacturer_ca_simulator.sh

  • This is the script for signing the EK CSR. The fTPM manufacturer should customize the script to meet the requirements of the CA server.

    Run odm_ekb_gen.py

    # Command line interface of "odm_ekb_gen.py"
    odm_ekb_gen.py [-h] [--kdk_db ${KDK_DB}]
    
    # For example, to generate the EKB_ftpm_db, run the following command.
    odm_ekb_gen.py --kdk_db ftpm_kdk/kdk_db_0102-0000000100000002-5.csv
    

By default, the output of the ODM EKB DB will be stored in the “odm_out” folder. The ODM should package them and deliver them to the OEM.

Generating OEM EKB

The OEM unpacks the ODM EKB DB and generates the EKB final DB. This will generate per-device basis EKS images that are authenticated and encrypted by the OEM K1 derivation keys.

The OEM EKB Gen tool is a wrapper of the Gen EKB script (gen_ekb.py) from the hwkey-agent sample application.

  1. Move the Gen EKB script to the same folder as the OEM EKB Gen tool.

  2. Run oem_ekb_gen.py

    oem_ekb_gen.py -oem_k1_key oem_k1.key \
                   -in_sym_key sym_t234.key \
                   -in_sym_key2 sym2_t234.key \
                   -in_auth_key auth_t234.key \
                   -in_ftpm_odm_ekb odm_out
    

Here are the command-line interface options:

  • -oem_k1_key <oem_k1.key>: The root key of the EKB encryption and authentication key.

  • -in_sym_key <sym_t234.key>: The user-defined key for UEFI payloads (such as kernel, kernel-dtb) encryption.

  • -in_sym_key2 <sym2_t234.key>: The user-defined key for disk encryption support.

  • -in_auth_key <auth_t234.key>: The user-defined key for UEFI variable authentication.

  • -in_ftpm_odm_ekb <IN_FTPM_ODM_EKB>: The path where the EKB_ftpm_db is located.

The generated per-device EKS images are stored in the oem_out folder. The OEM should package them and deliver them back to ODM.

ODM Packages Generation

Signing and Encrypting the EKB_final_db

  1. Run l4t_sign_image.sh. Refer to the help option for detailed usage.

  2. Unpack the EKB_final_db to the oem_out folder.

  3. The encrypted and signed EKB_final_db are in oem_out/signed folder. These encrypted/signed eks_<OEM_ID>-<SN>.signed files are packaged to deliver to the OEM.

cd Linux_for_Tegra
./l4t_sign_image.sh --chip <CHIP_ID> \
                     --key <PKC_KEY> \
                     --encrypt_key <SBK_KEY> \
                     --mass-ekb oem_out \
                     --type data \
                     --split False

# Packaging the encrypted/signed eks files.
tar cf eks_<OEM_ID>-<SN>-<num_of_devices>.tar --directory=oem_out/signed/ .

Generating the ODM QSPI Image

Run l4t_initrd_flash.sh with --odm-image-gen, using PKC and SBK as the signing and encryption keys, and pv.crt as the UEFI signing public key to generate lbc_odm.tar.gz (lower boot components).

Refer to the README file (${BSP_TOP}/Linux_for_Tegra/tools/kernel_flash/README_initrd_flash.txt) and the help option for detailed usage.

cd Linux_for_Tegra
sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
./tools/kernel_flash/l4t_initrd_flash.sh \
                     --odm-image-gen \
                     --showlogs \
                     --network usb0 \
                     --no-flash \
                     -u <PKC_KEY> \
                     -v <SBK_KEY> \
                     --pv-crt <PV_CERT> \
                     <BOARD_NAME> \
                     internal

OEM Packages Generation

Generating the OEM QSPI Image

UPI (User Partition Image)

Using UEFI keys to generate the UPI. This will output upi_odm.tar.gz. Refer to the README file (${BSP_TOP}/Linux_for_Tegra/tools/README_uefi_secureboot.txt) to generate the UEFI key configuration file.

cd Linux_for_Tegra
sudo ./tools/gen_uefi_default_keys_dts.sh <UEFI_KEYS_CONF_FILE>
sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
./tools/kernel_flash/l4t_initrd_flash.sh \
                     --mass-storage-only
                     --showlogs \
                     --network usb0 \
                     --no-flash \
                     --uefi-keys <UEFI_KEYS_CONF_FILE> \
                     --uefi-enc <UEFI_PAYLOAD_ENCRYPTION_KEY> \
                     <BOARD_NAME> \
                     internal
UEFI Image

Using flash.sh with PV signing key (-u), PV encryption key (–pv-enc), and UEFI payload signing key (–uefi-keys) to generate the PV signed and encrypted UEFI image.

cd Linux_for_Tegra
sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
                     ./flash.sh \
                     -k A_cpu-bootloader \
                     --no-flash \
                     -u <PV_SIGNING_PRIVATE_KEY> \
                     --pv-enc <PV_ENCRYPTION_KEY> \
                     --uefi-keys <UEFI_KEYS_CONF_FILE> \
                     --uefi-enc <UEFI_PAYLOAD_ENCRYPTION_KEY> \
                     <BOARD_NAME> \
                     internal

Generating the Factory Package

Generating the factory tarball

cd Linux_for_tegra

# Untar the LBC tarball
sudo tar xvzf lbc_odm.tar.gz

# Untar the UPI tarball
sudo tar xvzf upi_oem.tar.gz

cd tools/kernel_flash/images/internal/

# Copy the PV signed/encrypted UEFI image to the same folder
sudo cp ${BSP_TOP}/Linux_for_Tegra/bootloader/uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed ./

# Record the UEFI image file size
ls -l uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed

# Record the sha1sum
sha1sum uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed

# Edit the A/B_cpu-bootloader with PV signed/encrypted file size and sha1Sum
sudo vim flash.idx

# Untar EKB_final_db received from ODM (e.g., eks_0102-0000000100000002-5.tar)
sudo mkdir ekb_db
cd ekb_db
sudo tar xf ${ODM}/eks_0102-0000000100000002-5.tar

# Package the factory tarball
cd ${BSP_TOP}/Linux_for_Tegra
sudo tar zvcf factory.tar.gz \
               tools/kernel_flash/initrdflashparam.txt \
               tools/kernel_flash/initrdflashimgmap.txt \
               tools/kernel_flash/images/

# Send the factory image to the factory

Factory Burning Fuses and Flashing Devices Flow

Burning Fuseblob on a Device

  1. Install L4T BSP and FSKP package on the fuse burning host at the factory.

  2. Untar the fuseblob.

  3. Burn the OEM fuseblob.

  4. Burn the ODM fuseblob.

Refer to the Fuse Burning section for the command example in a real use case.

# Ex. Burn the OEM fuseblob:
sudo ./fskp_fuseburn.py -P ./oem_out \
                        -c 0x23 \
                        --board-spec orin-agx-board-spec.txt \
                        -B ../../../../jetson-agx-orin-devkit.conf

# Ex. Burn the ODM fuseblob:
sudo ./fskp_fuseburn.py -P ./odm_out \
                        -c 0x23 \
                        --board-spec orin-agx-board-spec.txt \
                        -B ../../../../jetson-agx-orin-devkit.conf

# Note:
#   1. In this case, it is a dry run. No fuses are actually burned.
#   2. Make sure the ODM fuseblob is burned after the OEM fuseblob is burned.
#      This is because the ODM fuseblob contains Security Mode fuse bit. Once burned, no other fuses can be burned.

Burning Fuseblobs to Multiple Devices

  1. Run fskp_massfuseburn.py and fskp_multiblobfuse.py respectively.

  2. Repeat the same steps as burning a single device.

# Ex. Burn the OEM mass fuseblobs:
# Untar the tarball, oem_out.tar, received from the OEM.
sudo ./fskp_massfuseburn.py --skipconfirmation \
                              --burnfuse \
                              -P ./oem_out \
                              -c 0x23 \
                              --board-spec orin-agx-board-spec.txt \
                              -B ../../../../jetson-agx-orin-devkit.conf

# Ex. Burn the ODM mass fuseblobs:
# Untar the tarball, odm_out_0102-0000000100000002-5.tar, received from the ODM.
sudo ./fskp_multiblobfuse.py --out ./odm_out \
                              --oem_id 0x0102 \
                              --sn 0x0000000100000002 \
                              --num_devices 5 \
                              --board-spec orin-agx-board-spec.txt \
                              -B ../../../../jetson-agx-orin-devkit.conf

Flashing the Devices

  1. Install L4T BSP on the host to flash the devices.

  2. Untar the factory package.

  3. Flash the devices.

cd ${BSP_TOP}/Linux_for_Tegra

# Untar the factory tarball
sudo tar zvxf factory.tar.gz
cp tools/kernel_flash/images/rcmboot/* bootloader/

# Flash the devices
sudo ./tools/kernel_flash/l4t_initrd_flash.sh \
                        --flash-only \
                        --showlogs \
                        --network usb0 \
                        --ekb-pair \
                        <BOARD_NAME> \
                        internal

Running the fTPM Provisioning Script on the Jetson Device

The fTPM provisioning script handles the process of provisioning the fTPM on the Jetson device. This involves querying EK certificates from the Encrypted Key Block (EKB), storing the EK certificate in the fTPM Non-Volatile (NV) memory, taking ownership of the fTPM, and creating EK accordingly with default EK handles.

The fTPM helper TA/CA and PTA are applications designed to support fTPM provisioning. These components provide interfaces for querying SN and EK certificates.

The fTPM TA supports TPM2 functionalities defined by the Trusted Computing Group (TCG). It receives EPS from the fTPM helper PTA during the first startup time and stores it in NV memory with the provisioning process.

Optionally Rebuilding and Updating the TOS Image for fTPM Support

To customize the fTPM function on your Jetson device, you may need to rebuild and update the Trusted Operation System (TOS) image. Follow these steps to ensure a secure environment for your application.

  1. Download the source package from Jetson Linux Archive.

  2. To rebuild the TOS image, refer to the README file in the OP-TEE or ATF source package. Additionally, manually add the “-t” option to enable fTPM feature.

./optee_src_build.sh -p t234 -t

# Update the TOS image after rebuild.
cp tos.img ${ODM_BSP_TOP}/Linux_for_Tegra/bootloader/tos-optee_t234.img
  1. Re-flash the device with the new TOS image.

  2. Preparing the fTPM provisioning folder. If you need to use fTPM, create a provisioning folder and copy the necessary file into it.

# Create a "ftpm_prov" folder.
mkdir -p ftpm_prov

# Run the command from the host to copy the provisioning script into the folder.
scp optee/samples/ftpm-helper/host/tool/ftpm_device_provision.sh ${REMOTE_DEVICE}:${DEST_PROV_DIR}/ftpm_prov

..note:

The ``${REMOTE_DEVICE}`` and ``${DEST_PROV_DIR}`` variables should be replaced with the actual device's IP address and
provisioning directory, respectively.

Running the fTPM Provisioning Script

  1. Load the fTPM driver module.

sudo modprobe tpm_ftpm_tee
  1. Provision and activate the fTPM by running the ftpm_device_provision.sh script.

This script completes the following tasks: - Queries the EK Certificates (RSA and EC) and stores them in the fTPM NV memory. - Sets up the fTPM authorization.

cd ftpm_prov
sudo ./ftpm_device_provision.sh -r ek_cert_rsa.der -e ek_cert_ec.der -p owner

Here are the command-line arguments:

  • -r <file name of RSA EK certificate>: This is the RSA EK certificate saved after querying from EKB.

  • -e <file name of EC EK certificate>: This is the EC EK certificate saved after querying from EKB.

  • -p <authorization value of fTPM>: - This is the fTPM authorization value. Please refer to the tpm2_changeauth man page.

Verifying the fTPM EK

With the offline provision method, the fTPM EKs are pre-generated by the fTPM production scripts. The ODM EKB Gen Tool provides a verify mode, which can help the fTPM manufacturer validate the fTPM EKs before shipping the EKB images to the OEM. The mode is to compare the fTPM EK public keys generated by fTPM production script with the EK public keys generated by the fTPM TA.

Before you verify the fTPM EK, ensure that you have the following:

  • A dedicated Jetson device with custom fTPM helper TA and the CA to verify the fTPM EK .

  • A secure environment to keep the intermediate data for fTPM EK verification in. You need to remove the data after the verification is complete.

Generating the fTPM EK Verification Data

The intermediate data for fTPM EK verification can be generated by running the ODM EKB Gen Tool with the --verify option. The output data is only for fTPM EK verification:

odm_ekb_gen.py --kdk_db ftpm_kdk/kdk_db-01020000000100000002-5.csv --verify

When --verify is set, odm_ekb_gen.py creates the ftpm_keys.txt file in the output folder.

This file contains the following components:

  • Device SN

  • EPS

  • RSA EK public key

  • EC EK public key

Setting up a Dedicated Jetson Device

Caution

To enable the fTPM EK verification function on Jetson device, you need to rebuild OP-TEE with the CFG_JETSON_FTPM_HELPER_INJECT_EPS configuration. This is a custom configuration only for fTPM EK verification, and this configuration should not be enabled in the OP-TEE production build.

To enable the fTPM EK verification function, change the optee_src_build.sh script:

diff --git a/optee_src_build.sh b/optee_src_build.sh
index 383a4d3d9df4..c99500da89f4 100755
--- a/optee_src_build.sh
+++ b/optee_src_build.sh
@@ -94,7 +94,8 @@ function build_optee_sources {
                if [ "${ENABLE_FTPM_BUILD}" == "yes" ]; then
                        optee_config="CFG_CORE_TPM_EVENT_LOG=y \
                                CFG_REE_STATE=y \
-                               CFG_JETSON_FTPM_HELPER_PTA=y"
+                               CFG_JETSON_FTPM_HELPER_PTA=y \
+                               CFG_JETSON_FTPM_HELPER_INJECT_EPS=y"
                        early_tas="${build_dir}/early_ta/cpubl-payload-dec/0e35e2c9-b329-4ad9-a2f5-8ca9bbbd7713.stripped.elf \
                                ${build_dir}/early_ta/ftpm-helper/a6a3a74a-77cb-433a-990c-1dfb8a3fbc4c.stripped.elf \
                                ${build_dir}/early_ta/luks-srv/b83d14a8-7128-49df-9624-35f14f65ca6c.stripped.elf \

After this process is complete, rebuild OP-TEE, generate the TOS image again, and flash the TOS image to the board.

Verifying the fTPM EKs

To verify the RSA and EC EK public keys on a Jetson Orin device, run the ftpm_offline_provisioning_verify.sh script:

  1. Copy the ftpm_keys.txt to the Jetson Orin device.

scp ${SRC_VERIFY_DIR}/ftpm_keys.txt ${REMOTE_DEVICE}:${DEST_VERIFY_DIR}/ftpm_prov
  1. Copy the ftpm_offline_provisioning_verify.sh script from in the optee source directory to the Jetson Orin device.

scp optee/samples/ftpm-helper/host/tool/ftpm_offline_provisioning_verify.sh ${REMOTE_DEVICE}:${DEST_VERIFY_DIR}/ftpm_prov
  1. Copy the custom nvftpm-helper-app to the Jetson Orin device.

scp optee/build/t234/ca/ftpm-helper/nvftpm-helper-app ${REMOTE_DEVICE}:${DEST_VERIFY_DIR}/ftpm_prov
  1. Run ftpm_offline_provisioning_verify.sh on the Jetson Orin device.

cd ${DEST_VERIFY_DIR}/ftpm_prov
sudo ./ftpm_offline_provisioning_verify.sh

Appendix A: The Overall Command Reference Flow for fTPM Manufacturing Support

The ODM Workflow

ODM Preparation Work
  1. Jetson BSP Installation

  2. Retrieve the OEM’s pv_key.crt and store at “~/oem_keys/uefi_keys/pv_key.crt”.

  3. Assume that the ODM’s own keys are stored at:

~/odm_keys/rsa3k.pem
~/odm_keys/sbk-32.key
ODM EKB Generation
  1. Generate the ODM EKB DB

cd ${BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool
./kdk_gen.py --oem_id 0x21 --sn 0x1000218000 --num_devices 2
./odm_ekb_gen.py --kdk_db ftpm_kdk/kdk_db_0021-0000001000218000-2.csv
tar cf odm_out_0021-0000001000218000-2.tar odm_out/
  1. The ODM sends the odm_out_0021-0000001000218000-2.tar to the OEM.

    The OEM will then add OEM/user_defined keys into EKB. Further details can be found in the section “OEM EKB Generation” under The OEM Workflow.)

    • Encrypt the updated EKB.

    • Generate the EKB tarball.

    • And then send the tarball back to ODM

  2. The ODM waits to receive the oem_out_0021-0000001000218000-2.tar from the OEM.

cd ${BSP_TOP}/Linux_for_Tegra/
tar xvf oem_out_0021-0000001000218000-2.tar
# The tarball is untared at the "oem_out" folder.

# Signing and generating the final ekb_db.
./l4t_sign_image.sh --chip 0x23 \
                     --key ~/odm_keys/rsa3k.pem \
                     --encrypt_key ~/odm_keys/sbk-32.key \
                     --mass-ekb oem_out \
                     --type data \
                     --split False
tar cf eks_0021-0000001000218000-2.tar --directory=oem_out/signed .
  1. The ODM sends the eks_0021-0000001000218000-2.tar to the OEM.

ODM Fuseblob Generation

The ODM sends fuseblob_odm_out_0021-0000001000218000-2.tar to the OEM.

Note

The parameters used in this command are for reference only. They should be replaced with the user’s specific FSKP keys and board.

cd ${BSP_TOP}/Linux_for_Tegra
cd l4t/tools/flashtools/fuseburn/
sudo ./fskp_fuseburn.py -f odm_fuse_template.xml \
                        --multi-blob ${ODM_BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool/ftpm_kdk/kdk_db_0021-0000001000218000-2.csv
                        --test \
                        -i 63 \
                        --key-exp fskp_ak.bin fskp_ek.bin \
                        --fskpcfg fskp_conf.txt \
                        -g fuseblob/odm_out \
                        -c 0x23 \
                        --board-spec orin-agx-board-spec.txt \
                        -B ../../../../jetson-agx-orin-devkit.conf
tar cf fuseblob_odm_out_0021-0000001000218000-2.tar fuseblob/
QSPI Image Generation (aka lower boot components: lbc)
  • AGX Orin with eMMC as the RootFS storage

    cd ${BSP_TOP}/Linux_for_Tegra
    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --odm-image-gen \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            -u ~/odm_keys/rsa3k.pem \
                            -v ~/odm_keys/sbk-32.key \
                            --pv-crt ~/oem_keys/uefi_keys/pv_key.crt \
                            jetson-agx-orin-devkit \
                            internal
    
  • AGX Orin with NVMe as the RootFS storage

    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --odm-image-gen \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            -c bootloader/t186ref/cfg/flash_t234_qspi.xml \
                            -u ~/odm_keys/rsa3k.pem \
                            -v ~/odm_keys/sbk-32.key \
                            --pv-crt ~/oem_keys/uefi_keys/pv_key.crt \
                            jetson-agx-orin-devkit \
                            internal
    
  • Orin Nano with NVMe as the RootFS storage

    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --odm-image-gen \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            -p "-c bootloader/t186ref/cfg/flash_t234_qspi.xml" \
                            -u ~/odm_keys/rsa3k.pem \
                            -v ~/odm_keys/sbk-32.key \
                            --pv-crt ~/oem_keys/uefi_keys/pv_key.crt \
                            jetson-orin-nano-devkit \
                            internal
    

The output from the above command is lbc_odm.tar.gz. The ODM sends it to the OEM.

The OEM Workflow

The OEM Preparation Work
  1. Jetson BSP Installation

  2. Assume that the OEM’s user defined keys (for ekb generation) are stored at:

~/oem_keys/oem_k1.key
~/oem_keys/sym_t234.key
~/oem_keys/sym2_t234.key
~/oem_keys/auth_t234.key
  1. OEM’s PV keys (for UEFI/cpu-bootloader image signing and encryption) are stored at:

~/oem_keys/pv_keys/rsa_priv-3k-pv.pem
~/oem_keys/pv_keys/pv_key.crt (This public key is shared with the ODM.)
~/oem_keys/pv_keys/pv_enc_k2.key (This is OEM_K2 fuse value.)
  1. OEM’s uefi keys (for UEFI payloads such as kernel/kernel-dtb signing and encryption) are stored at:

~/oem_keys/uefi_keys/uefi_keys.conf
~/odm_keys/uefi_keys/uefi_enc.key
OEM Fuseblob Generation
  1. Generating the OEM fuseblob

cd ${BSP_TOP}/Linux_for_Tegra
cd l4t/tools/flashtools/fuseburn/
sudo ./fskp_fuseburn.py --skipfskpkey \
                        -c 0x23 \
                        -g fuseblob/oem_out \
                        --test \
                        -f oem_fuse_template.xml \
                        --board-spec orin-agx-board-spec.txt \
                        -B ../../../../jetson-agx-orin-devkit.conf
tar cf fuseblob_oem_out.tar fuseblob/oem_out
  1. The OEM sends “fuseblob_oem_out.tar” to the FACTORY.

  2. The OEM receives ODM fuseblob db from the ODM.

  3. The OEM sends “fuseblob_odm_out_0021-0000001000218000-2.tar” to the FACTORY.

OEM EKB Generation
  1. Receiving and untar “odm_out_0021-0000001000218000-2.tar” from the ODM.

cd ${BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool/
cp ${BSP_TOP}/odm_out_0021-0000001000218000-2.tar ./
tar xf odm_out_0021-0000001000218000-2.tar
  1. Adding the OEM user defined keys into ekb.

cp ../../../hwkey-agent/host/tool/gen_ekb/gen_ekb.py ./
./oem_ekb_gen.py -oem_k1 ~/oem_keys/oem_k1.key \
                  -in_sym_key ~/oem_keys/sym_t234.key \
                  -in_sym_key2 ~/oem_keys/sym2_t234.key \
                  -in_auth_key ~/oem_keys/auth_t234.key \
                  -in_ftpm_odm_ekb odm_out
tar cf oem_out_0021-0000001000218000-2.tar oem_out/
  1. Sending “oem_out_0021-0000001000218000-2.tar” to the ODM.

    Note

    The result from Step 3 here is the image that ODM awaits at Step 3 in the “ODM EKB Generation” flow.

UPI Image Generation (aka User Partition Image: UPI)
cd ${BSP_TOP}/Linux_for_Tegra
sudo ./tools/gen_uefi_default_keys_dts.sh ~/oem_keys/uefi_keys/uefi_keys.conf

Note

In the commands below, the key in --uefi-enc <key> option is used for UEFI payload encryption. This key value is the sym_t234.key defined and added into the EKB by the OEM.

  • AGX Orin with eMMC as the RootFS storage

    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --mass-storage-only \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \
                            jetson-agx-orin-devkit \
                            internal
    
  • AGX Orin with NVMe as the RootFS storage

    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --mass-storage-only \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            --external-device nvme0n1p1 \
                            --external-only \
                            -c ./tools/kernel_flash/flash_l4t_t234_nvme.xml \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \
                            jetson-agx-orin-devkit \
                            nvme0n1p1
    
  • Orin Nano with NVMe as the RootFS storage

    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --mass-storage-only \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            --external-device nvme0n1p1 \
                            --external-only \
                            -c ./tools/kernel_flash/flash_l4t_t234_nvme.xml \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \
                            jetson-orin-nano-devkit \
                            nvme0n1p1
    

The output from the above command is upi_oem.tar.gz.

UEFI Image Generation
cd ${OEM_BSP_TOP}/Linux_for_Tegra
sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
./flash.sh  -k A_cpu-bootloader \
            --no-flash \
            -u ~/oem_keys/pv_keys/rsa_priv-3k-pv.pem \
            --pv-enc ~/oem_keys/pv_keys/pv_enc_k2.key \
            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
            --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \
            jetson-agx-orin-devkit \
            internal

The output from the above command is uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed.

Final Factory Tarball Generation
cd ${BSP_TOP}/Linux_for_Tegra
sudo tar zvxf lbc_odm.tar.gz
sudo tar zvxf upi_oem.tar.gz
cd tools/kernel_flash/images/internal/
sudo cp ${BSP_TOP}/Linux_for_Tegra/bootloader/uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed ./

# Record the UEFI image file size
ls -l uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed

# Record the sha1sum
sha1sum uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed

# Edit the A/B_cpu-bootloader with PV signed/encrypted file size and sha1Sum
sudo vim flash.idx

# Untar EKB_final_db received from ODM (i.e., eks_0021-0000001000218000-2.tar)
sudo mkdir ekb_db
cd ekb_db
sudo tar xf ${OEM_BSP_TOP}/eks_0021-0000001000218000-2.tar

# Package the factory tarball
cd ${BSP_TOP}/Linux_for_Tegra
sudo tar zvcf factory.tar.gz \
                  tools/kernel_flash/initrdflashparam.txt \
                  tools/kernel_flash/initrdflashimgmap.txt \
                  tools/kernel_flash/images/

Send factory.tar.gz to the factory.

The Factory Workflow

The factory preparation work can be found at Jetson BSP Installation

Fuse Burning
  1. Receiving the OEM and ODM fuseblob from the OEM.

    cd ${BSP_TOP}/Linux_for_Tegra
    cp fuseblob_oem_out.tar l4t/tools/flashtools/fuseburn/
    cp fuseblob_odm_out_0021-0000001000218000-2.tar l4t/tools/flashtools/fuseburn/
    cd l4t/tools/flashtools/fuseburn
    tar xf fuseblob_oem_out.tar
    tar xf fuseblob_odm_out_0021-0000001000218000-2.tar
    

    Caution

    • Burn the OEM fuseblob first, then burn the ODM fuseblob.

    • There are two examples here, fusing the fuses to each target one by one or fusing fuses to multiple targets in one command. Please choose one of them to apply.

  2. Fusing the fuses to each target.

    • Fusing the OEM fuses to each target.

    sudo ./fskp_fuseburn.py -c 0x23 \
                            -P fuseblob/oem_out/ \
                            --board-spec orin-agx-board-spec.txt \
                            -B ../../../../jetson-agx-orin-devkit.conf
    
    • The command above burns the OEM fuses on device 1.

    • Repeating the same command on device 2.

    • Fusing the ODM fuses to each target.

    sudo ./fskp_fuseburn.py -c 0x23 \
                            -P fuseblob/odm_out_0021-0000001000218000/ \
                            --board-spec orin-agx-board-spec.txt \
                            -B ../../../../jetson-agx-orin-devkit.conf
    # The command above burns the ODM fuses on device 1.
    
    sudo ./fskp_fuseburn.py -c 0x23 \
                            -P fuseblob/odm_out_0021-0000001000218001/ \
                            --board-spec orin-agx-board-spec.txt \
                            -B ../../../../jetson-agx-orin-devkit.conf
    # The command above burns the ODM fuses on device 2.
    
  3. Fusing the fuses to multiple targets in one command.

Note

You need to make sure all the devices are connected to the same host and are in recovery mode.

  • Fusing the OEM fuses to multiple targets in one command.

    sudo ./fskp_massfuseburn.py --skipconfirmation \
                               --burnfuse \
                               --board-spec orin-agx-board-spec.txt \
                               -P fuseblob/oem_out \
                               -c 0x23 \
                               -B ../../../../jetson-agx-orin-devkit.conf
    
  • Fusing the ODM fuses to multiple targets in one command.

    sudo ./fskp_multiblobfuse.py --out fuseblob/odm_out \
                               --oem_id 0x0021 \
                               --sn 0x0000001000218000 \
                               --num_devices 2 \
                               --board-spec orin-agx-board-spec.txt \
                               -B ../../../../jetson-agx-orin-devkit.conf
    
Flashing Images
cd ${BSP_TOP}/Linux_for_Tegra
sudo tar zvxf factory.tar.gz
cp tools/kernel_flash/images/rcmboot/* bootloader/
  • AGX Orin with eMMC as the RootFS storage

    sudo ./tools/kernel_flash/l4t_initrd_flash.sh \
                                --flash-only \
                                --showlogs \
                                --network usb0 \
                                --ekb-pair \
                                jetson-agx-orin-devkit \
                                internal
    
  • AGX Orin with NVMe as the RootFS storage

    sudo ./tools/kernel_flash/l4t_initrd_flash.sh \
                                --flash-only \
                                --showlogs \
                                --network usb0 \
                                --ekb-pair \
                                jetson-agx-orin-devkit \
                                nvme0n1p1
    
  • Orin Nano with NVMe as the RootFS storage

    sudo ./tools/kernel_flash/l4t_initrd_flash.sh \
                                --flash-only \
                                --showlogs \
                                --network usb0 \
                                --ekb-pair \
                                jetson-orin-nano-devkit \
                                nvme0n1p1
    

Appendix B: Handle The fTPM Manufacturing Flow In One Entity

The following steps work for an entity that behaves as both ODM and OEM.

The Preparation Work

  1. Jetson BSP Installation

  2. Assume that the ODM’s own keys are stored at:

~/odm_keys/rsa3k.pem
~/odm_keys/sbk-32.key
  1. Assume that the ODM’s FSKP fusing files are stored at:

~/odm_fskp/odm_fuse_template.xml
~/odm_fskp/fskp_ak.bin
~/odm_fskp/fskp_ek.bin
~/odm_fskp/fskp_conf.txt
  1. Assume that the OEM’s user defined keys (for EKB generation) are stored at:

~/oem_keys/oem_k1.key
~/oem_keys/sym_t234.key
~/oem_keys/sym2_t234.key
~/oem_keys/auth_t234.key
  1. Assume that the OEM’s UEFI keys (for UEFI payloads such as kernel/kernel-dtb signing and encryption) are store at:

~/oem_keys/uefi_keys/uefi_keys.conf
~/oem_keys/uefi_keys/uefi_enc.key
  1. Assume that the OEM’s fuse template are stored at:

~/oem_keys/oem_fuse_template.xml

EKB Generation

  1. Generate the EKB DB with KDK-based EK certificates.

cd ${BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool
./kdk_gen.py --oem_id 0x21 --sn 0x1000218000 --num_devices 2
./odm_ekb_gen.py --kdk_db ftpm_kdk/kdk_db_0021-0000001000218000-2.csv
  1. Add user keys to EKB.

cp ../../../hwkey-agent/host/tool/gen_ekb/gen_ekb.py ./
./oem_ekb_gen.py -oem_k1_key ~/oem_keys/oem_k1.key \
                  -in_sym_key ~/oem_keys/sym_t234.key \
                  -in_sym_key2 ~/oem_keys/sym2_t234.key \
                  -in_auth_key ~/oem_keys/auth_t234.key \
                  -in_ftpm_odm_ekb odm_out
# The outputs from the above command are stored at the oem_out folder.
cp -r oem_out/ ${BSP_TOP}

- ``oem_k1.key``: ``OemK1`` value in the OEM fuse template xml
- ``sym_t234.key``: UEFI payloads (such as kernel, kernel-dtb) encryption key
- ``sym2_t234.key``: disk encryption key
- ``auth_t234.key``: UEFI variables authentication key
  1. Signing and generating the final ekb_db.

cd ${BSP_TOP}/Linux_for_Tegra
./l4t_sign_image.sh --chip 0x23 \
                     --key ~/odm_keys/rsa3k.pem \
                     --encrypt_key ~/odm_keys/sbk-32.key \
                     --mass-ekb ${BSP_TOP}/oem_out \
                     --type data \
                     --split False

The encrypted/signed final ekb_db images are stored at the ${BSP_TOP}/oem_out/signed folder.

Fuseblob Generation

To create a new fuse template, merge the contents of odm_fuse_template.xml and oem_fuse_template.xml, naming the resulting file as odem_fuse_template.xml.

When merging these templates, place the content from oem_fust_template.xml before that of odm_fuse_template.xml. This ensures that the fuse named “SecurityMode” remains the last entry in the merged template.

<genericfuse MagicId="0x45535546" version="1.0.0">
      <fuse name="OdmInfo" size="4" value="0xFFFF"/>
      <fuse name="OdmId" size="8" value="0xFFFFFFFFFFFFFFFF"/>
      <fuse name="Kdk0" size="32" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/>
      <fuse name="PublicKeyhash" size="64" value="0x<64-byte-value-PubKeyHash>"/>
      <fuse name="PkcPubKeyHash1" size="64" value="0x<64-byte_value-PubKeyHash1>"/>
      <fuse name="PkcPubKeyHash2" size="64" value="0x<64-byte_value-PubKeyHash2>"/>
      <fuse name="OptInEnable" size="4" value="0x1"/>
      <fuse name="SecureBootKey" size="32" value="0x<32-byte-value-SBK>"/>
      <fuse name="ArmJtagDisable" size="4" value="0x1"/>
      <fuse name="OemK1" size="32" value="0x<32-byte-value-key>"/>
      <fuse name="OemK2" size="32" value="0x<32-byte-value-key>"/>
      <fuse name="PscOdmStatic" size="4" value="0x00000060"/>
      <fuse name="BootSecurityInfo" size="4" value="0x<4-byte_value-SECURITY_INFO>"/>
      <fuse name="SecurityMode" size="4" value="0x1"/>
</genericfuse>
cd ${BSP_TOP}/Linux_for_Tegra
cd l4t/tools/flashtools/fuseburn/
sudo ./fskp_fuseburn.py -f ~/odm_fskp/odem_fuse_template.xml \
                        --multi-blob ${BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool/ftpm_kdk/kdk_db_0021-0000001000218000-2.csv
                        --test \
                        -i 63 \
                        --key-exp ~/odm_fskp/fskp_ak.bin ~/odm_fskp/fskp_ek.bin \
                        --fskpcfg ~/odm_fskp/fskp_conf.txt \
                        -g fuseblob/odm_out \
                        -c 0x23 \
                        --board-spec orin-agx-board-spec.txt \
                        -B ../../../../jetson-agx-orin-devkit.conf
# The outputs generated by the above command are stored at the "fuseblob/odm_out" folder.
tar cf fuseblob_odm_out_0021-0000001000218000-2.tar fuseblob/

Note

The parameters used in this command are for reference only. They should be replaced with the user’s specific fskp keys and board.

The --test option indicates the generated fuse blob will only do a dry run. To actually burn the fuses, replace --test with --burnfuse. Follow the Fusing the ODM Fuses of the Fuse Burning process in Appendix A.

Flash Image Generation

The following are example commands to generate flash images (LBC + UPI) for different target configurations: - AGX Orin with eMMC as rootfs - AGX Orin with NVMe as rootfs - Orin Nano with NVMe as rootfs

  1. Unlike ODM and OEM are separate entities where the UEFI image generated by ODM is only a placeholder. Here, the UEFI image generated by the LBC generating command (with --odm-image-gen option) is the final UEFI image. In order to enable UEFI Secureboot feature at flashing time, option --uefi-keys must be provided in the command line so that all keys required by UEFI can be built in along with the UEFI image.

  2. The UEFI image is encrypted and signed by the sbk key (-v option) and pkc key (-u option).

  3. In the commands to generate upi_oem.tar.gz, the key in --uefi-enc option is used for UEFI payload encryption. This key value is the sym_t234.key used in the EKB generation.

  4. Enable UEFI secure boot feature:

cd ${BSP_TOP}/Linux_for_Tegra
sudo ./tools/gen_uefi_default_keys_dts.sh ~/oem_keys/uefi_keys/uefi_keys.conf
AGX Orin with eMMC as the RootFS storage
  • QSPI image generation (aka lower boot components: lbc)

    cd ${BSP_TOP}/Linux_for_Tegra
    sudo rm -rf tools/kernel_flash/images/
    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --odm-image-gen \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            -u ~/odm_keys/rsa3k.pem \
                            -v ~/odm_keys/sbk-32.key \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            -p "-c bootloader/generic/cfg/flash_t234_qspi.xml" \
                            jetson-agx-orin-devkit \
                            internal
    
  • UPI image generation (aka User Partition Image: UPI)

    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --mass-storage-only \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \
                            jetson-agx-orin-devkit \
                            internal
    

The output from the above commands are lbc_odm.tar.gz and upi_oem.tar.gz.

AGX Orin with NVMe as the RootFS Storage
  • QSPI image generation (aka lower boot components: lbc)

    cd ${BSP_TOP}/Linux_for_Tegra
    sudo rm -rf tools/kernel_flash/images/
    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --odm-image-gen \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            -u ~/odm_keys/rsa3k.pem \
                            -v ~/odm_keys/sbk-32.key \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            -p "-c bootloader/generic/cfg/flash_t234_qspi.xml" \
                            jetson-agx-orin-devkit \
                            internal
    
  • UPI image generation (aka User Partition Image: UPI)

    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --mass-storage-only \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            --external-device nvme0n1p1 \
                            --external-only \
                            -c ./tools/kernel_flash/flash_l4t_t234_nvme.xml \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \
                            jetson-agx-orin-devkit \
                            nvme0n1p1
    

The output from the above commands are lbc_odm.tar.gz and upi_oem.tar.gz.

Orin Nano with NVMe as the RootFS Storage
  • QSPI image generation (aka lower boot components: lbc)

    cd ${BSP_TOP}/Linux_for_Tegra
    sudo rm -rf tools/kernel_flash/images/
    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --odm-image-gen \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            -u ~/odm_keys/rsa3k.pem \
                            -v ~/odm_keys/sbk-32.key \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            -p "-c bootloader/generic/cfg/flash_t234_qspi.xml" \
                            jetson-orin-nano-devkit \
                            internal
    
  • UPI image generation (aka User Partition Image: UPI)

    sudo BOARDID=<BOARDID> FAB=<FAB> BOARDSKU=<BOARDSKU> CHIP_SKU=<CHIP_SKU> RAMCODE_ID=<RAMCODE_ID> \
    ./tools/kernel_flash/l4t_initrd_flash.sh \
                            --mass-storage-only \
                            --showlogs \
                            --network usb0 \
                            --no-flash \
                            --external-device nvme0n1p1 \
                            --external-only \
                            -c ./tools/kernel_flash/flash_l4t_t234_nvme.xml \
                            --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \
                            --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \
                            jetson-orin-nano-devkit \
                            nvme0n1p1
    

The output from the above commands are lbc_odm.tar.gz and upi_oem.tar.gz.

Factory Tarball Generation

cd ${BSP_TOP}/Linux_for_Tegra

sudo tar zvxf lbc_odm.tar.gz

sudo tar zvxf upi_oem.tar.gz

sudo mkdir -p tools/kernel_flash/images/internal/ekb_db

sudo cp ${BSP_TOP}/oem_out/signed/* tools/kernel_flash/images/internal/ekb_db

sudo tar zvcf factory.tar.gz \
               tools/kernel_flash/initrdflashparam.txt \
               tools/kernel_flash/initrdflashimgmap.txt \
               tools/kernel_flash/images/

Send the factory.tar.gz to FACTORY. Follow the Flashing Images process in Appendix A for more details.

The fTPM Turnkey Solution for Ecosystem Partners

To streamline your fTPM provisioning process during the manufacturing flow, we understand the importance of secure and efficient work flow and environment for our ecosystem partners and customers. That’s why we’re excited to introduce a turnkey fTPM provisioning solution, designed to simplify the process and reduce the burden on your manufacturing flow.

SecEdge has collaborated with NVIDIA to develop a firmware Trusted Platform Module (fTPM) solution, called SEC-TPM, which provides in-field trust provisioning and management for the NVIDIA JetPack SDK. This industry-first solution offers a secure root-of-trust in an NVIDIA System-on-Chip hardware-secure execution enclosure.

Benefits of SecEdge fTPM turnkey solution:

  • The SEC-TPM solution is based on TCG 2.0-compliant firmware TPM, providing a crypto-agile and managed solution for cybersecurity applications.

  • The solution allows device makers to meet industry compliance specifications, including TCG, NIST, CRA for the IoT, and Azure Edge Secured Core Certification.

  • SEC-TPM is available today supporting JetPack 6.1 releases, with a post-assembly Trust Provisioning service provided.