UEFI Platform Vendor Key Feature#

The UEFI platform vendor (PV) key feature allows PVs to deploy UEFI that is signed and encrypted by PV-owned keys without involving the solution providers.

NVIDIA® Jetson™ devices use a PKC key to verify the signature of boot component during device boot:
  • The component at stage N verifies the components at stage N+1.

  • The component at stage N+1 verifies the components at stage N+2, and so on.

With this feature, the UEFI owner, or the PV, can use a PV’s private key to sign UEFI, and can also deliver the public key to the solution provider, who was the owner of the boot components before UEFI. The public key is now built into the component (MB2) that loads in UEFI during boot.

During the secure boot process, the signature of the components before UEFI will be verified/authenticated by solution provider’s fused PKC. For UEFI, MB2 uses the built-in public key to verify PV authenticate key for key verification and signature authentication. As a result, the platform vendor, who does not own the fused PKC, can still independently sign and update the UEFI image.

Diagram showing how PV keys are used in Secure Boot

In Jetson devices that use the T234 processor (NVIDIA® Jetson Orin™ NX series and NVIDIA® Jetson AGX Orin™ series) and T264 processor (NVIDIA® Jetson Thor series), the PV key sign/authenticate UEFI is supported when Secure Boot is enabled.

Platform Vendor Key Sign/Authenticate UEFI#

This section describes how to use a tool to sign UEFI by the PV and to authenticate it by the solution provider.

The PV can sign UEFI by the key it owns. Here is a high-level overview of the process:

  1. The PV provides the PV authentication key file to the solution provider.

  2. The solution provider builds boot images with the PV authentication key that is built into MB2.

  3. The solution provider sends the results from step 2 to the PV.

  4. The PV creates the combined boot images and completes one of the following tasks:

    • Sends the images to the factory floor to build the device.

    • Sends the images to the OTA server for the update.

Before you enable UEFI PV key sign/authenticate feature, the RSA 3K authentication scheme fuse must be burned.

Note

  • RSA-3072, ECDSA-P256, ECDSA-P521 are supported for UEFI PV key signing.

  • The cryptography algorithm of the UEFI PV key should be aligned with the PKC key used for signing low-level boot components.

Platform Vendor Procedure#

Jetson AGX Orin#

To generate the PV authentication key and sign UEFI:

  1. Generate the PV key pair and call it pv_priv.pem:

    • To generate an ECDSA P-256 key:

      $ openssl ecparam -name prime256v1 -genkey -noout -out pv_priv.pem
      
    • To generate an ECDSA P-521 key:

      $ openssl ecparam -name secp521r1 -genkey -noout -out pv_priv.pem
      
    • To generate an RSA-3K key:

      $ openssl genrsa -out pv_priv.pem 3072
      
  2. Create a certificate signing request and call it pub_key.csr:

    $ openssl req -key pv_priv.pem -new -out pub_key.csr
    
  3. Create a self-signed certificate and call it pv_key.crt:

    $ openssl x509 -signkey pv_priv.pem -in pub_key.csr -req -days 3650 -out pv_key.crt
    
  4. Provide the pv_key.crt file to the solution provider.

  5. Get bootloader.tar.gz from the solution provider as described in the solution provider procedure for Jetson AGX Orin, place it in the Linux_for_Tegra/ folder, and untar it:

    $ tar -xzvf bootloader.tar.gz
    
  6. Gather the BOARDID, FAB, BOARDSKU, and BOARDREV environment information from the solution provider.

  7. Generate the signed UEFI image with the PV private key:

    $ sudo BOARDID=<board_id> FAB=<fab> BOARDSKU=<sku_number> BOARDREV=<reversion> ./flash.sh --no-flash -u pv_priv.pem -k A_cpu-bootloader jetson-agx-orin-devkit internal
    
  8. Flash the device with the following commands:

    $ boardctl -t topo recovery
    $ cd bootloader/
    $ sudo bash ./flashcmd.txt
    

Jetson AGX Thor#

To generate the PV authentication key and sign UEFI:

  1. Generate the PV key pair and call it pv_priv.pem:

    • To generate an ECDSA P-256 key:

      $ openssl ecparam -name prime256v1 -genkey -noout -out pv_priv.pem
      
    • To generate an ECDSA P-521 key:

      $ openssl ecparam -name secp521r1 -genkey -noout -out pv_priv.pem
      
    • To generate an RSA-3K key:

      $ openssl genrsa -out pv_priv.pem 3072
      
  2. Create a certificate signing request and call it pub_key.csr:

    $ openssl req -key pv_priv.pem -new -out pub_key.csr
    
  3. Create a self-signed certificate and call it pv_key.crt:

    $ openssl x509 -signkey pv_priv.pem -in pub_key.csr -req -days 3650 -out pv_key.crt
    
  4. Provide the pv_key.crt file to the solution provider.

  5. Gather the BOARDID, FAB, BOARDSKU, BOARDREV, RAMCODE_ID, and CHIP_SKU environment information from the solution provider.

  6. Generate the signed UEFI image with a PKC key list XML file such as t264_pv_key_list.xml. For the format of t264_pv_key_list.xml, refer to Generate a PKC Key List for Jetson Thor:

    $ sudo UNIFIED_FLASH=0 BOARDID=<board_id> FAB=<fab> BOARDSKU=<sku_number> BOARDREV=<reversion> RAMCODE_ID=<ramcode_id> CHIP_SKU=<chip_sku> ./tools/kernel_flash/l4t_initrd_flash.sh --no-flash -u t264_pv_key_list.xml -k A_cpu-bootloader jetson-agx-thor-devkit internal
    
  7. Back up the generated UEFI image bootloader/uefi_t26x_general_with_dtb_aligned_blob_w_bin_sigheader.bin.signed for later use.

  8. Get the package that contains output/ and unified_flash/ from the solution provider as described in the solution provider procedure for Jetson AGX Thor, place it in the Linux_for_Tegra/ folder, and untar it.

  9. Replace unified_flash/out/bsp_images/flash_workspace/flash-images/uefi_t26x_general_with_dtb_aligned_blob_w_bin_sigheader.bin.signed with the backed-up UEFI image uefi_t26x_general_with_dtb_aligned_blob_w_bin_sigheader.bin.signed.

  10. Use md5sum to obtain the MD5 value of the updated UEFI image, and update the MD5 field for the UEFI image entry in output/FileToFlash.txt.

  11. Flash the device:

    $ sudo UNIFIED_FLASH=1 ./l4t_initrd_flash.sh --flash-only
    

Solution Provider Procedure#

Jetson AGX Orin#

After the solution provider receives the PV authentication key, to enable the PV sign/authenticate UEFI feature, complete the following steps:

  1. Place the pv_key.crt file in the Linux_for_Tegra/ folder.

  2. Generate the signed boot images with the board-fused PKC key file (pkc.pem) and the PV key certificate (pv_key.crt):

    $ sudo BOARDID=<board_id> FAB=<fab> BOARDSKU=<sku_number> BOARDREV=<reversion> ./flash.sh --no-flash -u pkc.pem --pv-crt pv_key.crt jetson-agx-orin-devkit internal
    
  3. Package the Linux_for_Tegra/bootloader/ folder:

    $ tar -czvf bootloader.tar.gz ./bootloader
    
  4. Send the bootloader.tar.gz file to the PV.

Jetson AGX Thor#

After the solution provider receives the PV authentication key, to enable the PV sign/authenticate UEFI feature, complete the following steps:

  1. Place the pv_key.crt file in the Linux_for_Tegra/ folder.

  2. Generate the signed boot images with a PKC key list XML file such as t264_key_list.xml and the PV key certificate (pv_key.crt). For the format of t264_key_list.xml, refer to Generate a PKC Key List for Jetson Thor:

    $ sudo BOARDID=<board_id> FAB=<fab> BOARDSKU=<sku_number> BOARDREV=<reversion> RAMCODE_ID=<ramcode_id> CHIP_SKU=<chip_sku> ./l4t_initrd_flash.sh --no-flash -u t264_key_list.xml --pv-crt <pv_crt> jetson-agx-thor-devkit internal
    
  3. Package output/ and unified_flash/ and send them to the platform vendor.

PV Key Encrypt/Decrypt UEFI (Only for Jetson Orin Series)#

This section describes how to use the tool to encrypt UEFI by using a key owned by the PV and to decrypt it by the solution provider at MB2.

The mechanism is that the key encrypts UEFI is the PV-owned encryption key instead of the default SBK key. The PV will encrypt UEFI with its owned PV encryption key in one of the following ways:

  • The PV provides a fuse blob so that the PV encryption key can be burned into the fuse.

  • The PV provides the PV encryption key to the solution provider who can then inject the key into MB2 by using the tool.

Before enabling the UEFI PV key encrypt/decrypt feature, the SBK key and the encryption mode fuse must be burned. Refer to Fuse handling for more information.

Fuse Solution#

To provide a higher level of protection to the PV encryption key, the PV can burn the PV encryption key into the OEM_K2 fuse. Now, MB2 can decrypt PV encrypted UEFI by using OEM_K2 through Security Engine without knowing the actual key, and here are the decryption steps:

  1. The PV generates a fuse blob, which includes the PV encryption key, and that will be burned into OEM_K2 fuse.

  2. The PV encrypts the UEFI image with the PV encryption key.

  3. The solution provider generates its own fuse blob that includes the SBK key fuse and the encryption mode enable fuse.

  4. The solution provider builds the boot images with the SBK key.

  5. The solution provider sends the results from steps 3 and 4 to the PV.

  6. The PV generates UEFI image, combines the boot images generated by the solution provider and the encrypted UEFI image generated by PV, and completes one of the following tasks:

  • Sends the images to the factory floor to build the device.

  • Sends the images to the OTA server for the OTA update.

Note

To increase security level, the PV encryption key in this procedure is used to derive a final key for UEFI image encryption and decryption.

Platform Vendor Procedure#

This procedure generates the PV encryption key, generates the signing PV key, and encrypts and signs UEFI:

  1. Generate the AES-256 key and call it pv_enc.key:

    $ openssl rand -hex 32 > pv_enc.key
    
  2. Manually reformat pv_enc.key into eight 32-bit words big-endian hexadecimal.

    For example, original content of pv_enc.key is 112233445566778899aabbccddeeff00ffeeddccbbaa99887766554433221100, and after the reformat, it changes to 0x11223344 0x55667788 0x99aabbcc 0xddeeff00 0xffeeddcc 0xbbaa9988 0x77665544 0x33221100.

  3. Generate the PV private key and its certificate.

    Follow the same key generation steps as described in Platform Vendor Procedure (steps 1-4).

    Note

    If the PV signing key and its certificates have been previously generated, you can skip this step.

  4. Get bootloader.tar.gz from the solution provider, place it in the Linux_for_Tegra/, and untar it:

    $ tar -xzvf bootloader.tar.gz
    
  5. Gather the BOARDID, FAB, BOARDSKU, and BOARDREV environment information from the solution provider.

  6. Generate the signed and encrypted UEFI image with the PV private key (pv_priv.pem) and the PV encryption key (pv_enc.key):

    $ sudo BOARDID=<board_id> FAB=<fab> BOARDSKU=<sku_number> BOARDREV=<reversion> ./flash.sh --no-flash -u pv_priv.pem --pv-enc pv_enc.key -k A_cpu-bootloader jetson-agx-orin-devkit internal
    
  7. Get the fuse blob from the solution provider and provide the solution provider’s fuse blob and the PV’s fuse blob to the factory to burn fuses.

  8. Burn the fuse.

  9. Run the following commands to flash the device:

    $ boardctl -t topo recovery
    $ cd bootloader/
    $ sudo bash ./flashcmd.txt
    

Solution Provider Procedure#

After the solution provider receives the PV authentication key, complete the following steps:

  1. Place the pv_key.crt file in the same folder as the flash.sh script.

  2. Generate the signed and encrypted boot images by using the PKC key (pkc.pem), the SBK key, and the PV authentication key certificate (pv_key.crt):

    $ sudo BOARDID=<board_id> FAB=<fab> BOARDSKU=<sku_number> BOARDREV=<reversion> ./flash.sh --no-flash -u pkc.pem -v <sbk.key> --pv-crt pv_key.crt jetson-agx-orin-devkit internal
    
  3. Package the Linux_for_Tegra/bootloader/ folder:

    $ tar -czvf bootloader.tar.gz ./bootloader
    
  4. Send the bootloader.tar.gz file to the PV.

Fuse handling#

Before you execute the above flashing command, the device fuses must be burned with the fuse blobs that are provided by the PV and the solution provider.

  1. Here is an example of a fuse blob (1) provided by the PV:

    <genericfuse MagicId="0x45535546" version="1.0.0">
        <fuse name="PscOdmStatic" size="4" value="0x00000060"/>
        <fuse name="OemK2" size="32" value="0x112233445566778899aabbccddeeff00ffeeddccbbaa99887766554433221100"/>
    </genericfuse>
    
  2. Here is an example of a fuse blob (2) provided by the solution provider:

    <genericfuse MagicId="0x45535546" version="1.0.0">
        <fuse name="PscOdmStatic" size="4" value="0x00000060"/>
        <fuse name="OemK1" size="32" value="0xf3bedbff9cea44c05b08124e8242a71ec1871d55ef4841eb4e59a56b5f88fb2b"/>
        <fuse name="PublicKeyHash" size="64" value="0xdc6632e495c7976659a94668a98d6ba7e22a2d9438a555ec64c0c1cc59e533067bfe64f454c1f30c63ad7627fb0cfa2f556aff45818254387016745ccf713081"/>
        <fuse name="SecureBootKey" size="32" value="0x123456789abcdef0fedcba987654321023456789abcdef01edcba9876543210f"/>
        <fuse name="BootSecurityInfo" size="4" value="0x209"/>
        <fuse name="SecurityMode" size="4" value="0x1"/>
    </genericfuse>
    

You must ensure that in the fuse burning sequence, the fuse blob 1 is burned first.

Note

  • The fuses specified in the PV’s fuse blob and the fuses specified in solution provider cannot be overlapped.

  • The fuse blob provided by the PV must be burned first because, after the “SecurityMode” that is specified in the solution provider’s fuse blob is burned, fuse burning except ODM fuses is blocked.

  • The above fuse values in both PV and solution provider’s fuse blobs are for demonstrations only.