NVIDIA Tegra
NVIDIA Tegra Linux Driver Package

Development Guide
28.3 Release


 
Secureboot on Jetson TX1 and TX2 Devices
 
Fuses and Security
Overall Fusing and Signing Binaries
Installing the L4T Secureboot Package
Generating the RSA Key Pair
Preparing the DK(KEK)/SBK/ODM Fuses
Burning PKC [DK(KEK), SBK] Fuses using a Private Key File
Signing Boot Files
Preparing Uboot
Flashing with Signed Boot File Binaries
Accessing the Fuse from the Target
Example: Burning the Fuse in a Factory Environment
Example: Flashing Signed Images in a Factory Environment
Secure PMC Scratch Register Configurations for BootROM
The NVIDIA® Tegra® Linux Driver Package provides boot security using the Secureboot package. Secureboot prevents execution of unauthorized boot codes through chain of trust. The root-of-trust is on-die bootROM code that authenticates boot codes such as BCT, bootloader, and warmboot vector using Public Key Cryptography (PKC) stored in write-once-read-multiple fuse devices.
Fuses and Security
Tegra devices contain multiple fuses that control different items for security and boot. Programming a fuse, such as changing the value of a fuse bit from 0 to 1, is non-reversible. Once a fuse bit is programmed by setting to 1, you cannot change the fuse value from 1 to 0. For example, a value of 1 (0x01) can be changed to 3 (0x03) or 5 (0x05), but not to 4 (0x4) because the bit 0 is already programmed to 1.
Once odm_production_mode is fused with a value of 0x1, all further fuse write requests are blocked and the fused values are available through the provided Tegra API. However, the odm_reserved and odm_lock fields are still writable until odm_lock bit is programmed by changing the value of the bit from 0 to 1.
Although Tegra fuses are writable, you must use the odmfuse.sh script to perform the fuse for: public_key_hash, pkc_disable, secure_boot_key, and odm_production_mode.
Example fuses handled by L4T secureboot are as follows:
Bitsize
Name
Default value set by odmfuse.sh
1
odm_production_mode
0x1
256
public_key_hash
RSA Public Key Hash
1
pkc_disable
PKC - 0x1, NS - 0x1
128
secure_boot_key
Secure Boot Key (SBK) AES encryption key for other security applications. If no other security applications are used, leave it untouched.
32
device_key
Device key (DK) Device key for other security applications. If no other security applicationa are used, leave it untouched.
 
Fuses that are handled by the user are as follows:
Bitsize
Name
Default value set by odmfuse.sh
1
jtag_disable
0x1 - disable JTAG
256
odm_reserved
Programmable fuses at the users direction. However, 32 MSB are reserved for NVIDIA use.
4
odm_lock
Each bit set disables the write for the corresponding 32-bit ODM fuses.
For example: 0x2 locks B32-b63 of odm_reserved.
14
sec_boot_dev_cfg
Depending on sec_boot_dev_sel, each bit has a different meaning.
8
sw_reserved
2-0: sec_boot_dev_sel. Valid if ON and if the ignore_dev_sel_straps is enabled:
0=eMMC, 1=SPI
3: ignore_dev_sel_straps. Ignores boot strap.
4: enable_charger_detect
5: enable_watchdog
7-6: reserved
For details on hardware fuses and fuse names, consult the following documents:
NVIDIA Tegra K1 Fuse Specification Application Note DA-08571-001_v2.0
NVIDIA Jetson TX1 Fuse Specification Application Note DA-08191-001_v04
NVIDIA Jetson TX2 Fuse Specification Application Note DA-08415-001_v1.1
The fuse name aliases recognized by tegraflash are as follows:
Name
Tegraflash Alias
odm_production_mode
SecurityMode
public_key_hash
PublicKeyHash
pkc_disable
PkcDisable
secure_boot_key
SecureBootKey
device_key
DeviceKey
jtag_disable
JtagDisable
odm_reserved
ReservedOdm
odm_lock
OdmLock
sec_boot_dev_cfg
SecBootDeviceSelect
sw_reserved
SwReserved
Overall Fusing and Signing Binaries
The secureboot process with PKC requires:
Install the L4T secureboot package.
If necessary, prepare the DK(KEK), SBK, and ODM fuse values.
Generate the RSA key-pair.
Burn the PKC/odm_production fuses and set the ODM_PRODUCTION_MODE.
Sign the boot image files with PKC.
Flash the signed boot image files.
The process of protecting the ODM production fuses without securing boot:
Installs the L4T secureboot package.
If necessary, burns the ODM fuses.
Sets the ODM_PRODUCTION_MODE.
Flashes the clear boot files.
Note:
This process blocks ODM production fuse burning and protects the Tegra device from erroneous ODM production fuse burning.
ODM_RESERVED and ODM_LOCK fuses are still writable until the ODM_LOCK bit is burned.
Installing the L4T Secureboot Package
Prerequisites
X86 host running Ubuntu 14.04 LTS
libftdi-dev for USB debug port support
openssh-server package for OpenSSL
Full installation of the latest L4T release on the host
Download the latest L4T release at:
https://developer.nvidia.com/embedded/linux-tegra-archive
Tegra device is connected to the host with Type-B micro USB cable
Debug serial port is connected to the host, if necessary
To install secureboot
1. Download the secureboot_<release_version>.tbz2 tarball from:
https://developer.nvidia.com/embedded/downloads
Where <release_version> is identified in the Release Notes.
2. Untar the file by executing the command:
tar xvjf secureboot_<release_version>.tbz2
The tarball includes:
secureboot.tbz2
README.secureboot.txt that is also provided as a PDF on the L4T downloads site.
3. Untar the secureboot.tbz2 by overlaying on the L4T Board Support Package (BSP).
Extract the file secureboot.tbz2 onto the directory that is one level up from the Linux_for_Tegra/ directory on your Linux host.
The Linux_for_Tegra/ directory must be present from installing the L4T Board Support Package as a prerequisite.
You must be in the same directory where the Linux_for_Tegra/ directory is located before executing the command:
tar xvjf secureboot.tbz2
Generating the RSA Key Pair
If you wish to lock the fuse without PKC encryption, skip this topic. L4T secureboot requires 2048-bit RSA key-pair.
To generate a key-pair
1. Execute the command:
openssl genrsa -out rsa_priv.pem 2048
Upon successful execution, OpenSSL generates the key file named rsa_priv.pem file.
2. Rename and save the key file securely and safely.
The key file is used to burn fuse and sign boot files for Tegra devices. The security of your Tegra device depends on how securely you keep the key file.
To ensure the security of the key file, restrict access permission to a minimum number of personnel.
Note:
To generate a truly random number key, use the Hardware Security Module (HSM).
Consult the Hardware Security Module User Guide for output format and private key conversion to PEM format.
 
Preparing the DK(KEK)/SBK/ODM Fuses
If you wish to use another security application, you must prepare the DK(KEK), SBK, and other ODM fuse bits as described in the user guide for the other security application.
Name
Description
DK
Applies to: Jetson TX1 and Jetson TK1 devices
A 32-bit number stored in a file in big endian HEX format.
For example: 0xddccbbaa
KEK [0-2]
Applies to: Jetson TX2 devices
A 128-bit number stored in a file in big endian HEX format.
KEK256
Applies to: Jetson TX2 devices
A 256-bit number stored in a file in big endian HEX format.
For example: 0x67452301efcdab8967452301efcdab89
SBK
A 128-bit number stored in a file in big endian HEX format.
For example: 0x67452301efcdab8967452301efcdab89
ODM Fuse Bits
To use applications other than Secureboot, additional ODM fuse bits may be required. The specific fuse information differs depending on the application being used. Consult the user guide for the application being used.
 
Note:
HEX numbers must be presented in BigEndian format. The leading 0x or 0X can be omitted. The L4T SecureBoot software converts the BigEndian HEX format to the format that the Tegra device expects. All standard OpenSSL utilities output in BigEndian format.
Burning PKC [DK(KEK), SBK] Fuses using a Private Key File
 
odmfuse.sh Extra Options
The steps for burning PKC, DK, and SBK fuses using a private key file PEM format are as follows.
To burn PKC fuses
1. Navigate to the directory where you installed L4T.
2. Put the Tegra device into Forced Recovery Mode.
3. Burn the fuse using the odmfuse.sh script. For example:
To fuse PKC HASH from the .pem file with JTAG enabled:
sudo ./odmfuse.sh -j -i <chip_id> -c PKC -p -k <key.pem> [-D <DK_file> | --KEK{0-2} <KEK file>] [-S <SBK_file>]
To fuse PKC HASH from the .pem file with JTAG disabled:
sudo ./odmfuse.sh -i <chip_id> -c PKC -p -k <key.pem> [-D <DK_file> | --KEK{0-2} <KEK file>] [-S <SBK_file>]
To protect ODM production fuse with JTAG enabled:
sudo ./odmfuse.sh -j -i <chip_id> -c NS -p
To protect ODM production fuse with JTAG disabled:
sudo ./odmfuse.sh -i <chip_id> -c NS -p
Where <chip_id> is:
Jetson TK1: 0x40
Jetson TX1: 0x21
Jetson TX2: 0x18
odmfuse.sh Extra Options
For odmfuse.sh, other than PKC key and ODM_PRODUCTION_MODE fuses, odmfuse.sh allows you to program ODM fuses that are completely under your discretion. Skip this topic if you do not plan to modify these fuses.
The odmfuse.sh options that blow some ODM fuses are as follows:
Option
Description
-d 0xXXXX
Sets sec_boot_dev_cfg=<value>&0x3fff. For detail, refer to TRM.
-j
Sets JTAG enabled. Unless this option is specified, the usage of the JTAG debugger is blocked by default.
-l 0xX
Sets odm_lock=0xX. Setting each bit locks corresponding 32-bits in odm_reserved.
For example, setting odmlock=0x1 locks the first 32-bit of the odm_reserved read only.
Setting odmlock=0x5 locks the first and third 32-bits of the odm_reserved field read only and so on.
-o <value>
Sets odm_reserved=<value>. The value must be quoted series of 8 32-bit HEX numbers such as:
"0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0x00000000"
The last 32-bit HEX number must be 0x00000000 because these fuses are reserved for NVIDIA use.
-p
Sets production mode.
-r 0xXX
Sets sw_reserved=0xXX. The name of this fuse field is confusing, but the meaning is as follows:
bit[7-6] reserved
bit[5 ] enable_watchdog
bit[4 ] enable_charger_detect
bit[3 ] ignore_dev_sel_straps - Ignore "boot strap"
bit[2-0] sec_boot_dev_sel - 0:eMMC 2:SPI
-D <DK_file>
Applies to: Jetson TX1 and
Jetson TK1
Sets the Device Key that will be used by the high level security application to generate the application encryption keys. The content of <DK_file> must be a single 32-bit big endian HASH in HEX format.
-S <SBK_file>
Sets the Secure Boot Key that will be used by the high level security application to encrypt the application keys. The content of <SBK_file> must be a single 128-bit big endian HASH in HEX format.
--no-burn
Prepares the fuse blob to be used repeatedly on the factory floor where the private PKC key is not available.
This option generates <L4T path>.../Linux_for_Tegra/fuseblob.tbz2 which is downloaded and untarred in <L4T path>.../Linux_for_Tegra directory of a factory host.
Once the fuseblob.tbz2 is untarred in Linux_for_Tegra directory, then "fusecmd.sh" in Linux_for_Tegra/booloader directory is used to burn fuses repeatedly instead of the standard "odmfuse.sh".
--KEK[0-2] <KEK[0-2] file>
Applies to: Jetson TX2
Sets the Key Encryption Key that will be used by the high level security application to encrypt the application keys. The content of <KEK[0-2] file> must be a single 128-bit big endian HASH in HEX format.
--KEK256 <KEK256 file>
Applies to: Jetson TX2
Sets the 256-bit Key Encryption Key that will be used by the high level security application to encrypt the application keys. The content of <KEK256 file> must be a single 256-bit big endian HASH in HEX format.
Signing Boot Files
The boot file signing process is integrated into the flashing process. No other requirements are necessary to sign the boot files.
Preparing Uboot
Jetson TX1 and Jetson TX2 users can skip this topic.
By default, the odmfuse.sh script blocks JTAG access. Additionally, by default Uboot initializes the JTAG interface even when the JTAG usage is blocked by not specifying the -j option, and Tegra finds that the activity is illegal and quietly halts.
To properly enable Uboot when JTAG usage is blocked
Rebuild Uboot with the following workaround applied in the source code:
--- a/arch/arm/cpu/arm720t/tegra-common/cpu.c
+++ b/arch/arm/cpu/arm720t/tegra-common/cpu.c
@@ -348,6 +348,7 @@ void reset_A9_cpu(int reset)
 
void clock_enable_coresight(int enable)
{
+#ifdef CONFIG_ENABLE_CORESIGHT
u32 rst, src = 2;
 
debug("clock_enable_coresight entry\n");
@@ -373,6 +374,7 @@ void clock_enable_coresight(int enable)
writel(rst, CSITE_CPU_DBG3_LAR);
}
}
+#endif /* CONFIG_ENABLE_CORESIGHT */
}
To enable LP0 sleep/wakeup
To enable LP0 for PKC protected Jetson TK1:
The Uboot must be rebuilt with the provided source code patch
WB0 portion of the Uboot must be signed prior to flashing.
1. Copy the 0001-warmboot-change-wb-prepare-code-for-t1x4.patch to <top of u-boot source tree> from <top>.../Linux_for_Tegra/pkc.
2. Navigate to <top of u-boot source tree>.
3. Execute the command.
patch -p1 < 0001-warmboot-change-wb-prepare-code-for-t1x4.patch
4. Build Uboot. In L4T SDK, the command is tmp.
5. Locate the Uboot build path. For example:
<top>/out/l4t-ardbeg-release-hard/nvidia/u-boot
6. Copy the following file.
<u-boot-built-path>/u-boot-dtb-tegra.bin
<top>.../Linux_for_Tegra/bootloader/ardbeg/u-boot.bin
7. Copy the following:
<u-boot-built-path>/u-boot
<top>.../Linux_for_Tegra/bootloader/ardbeg
8. Copy the following file.
<u-boot-built-path>/spl/u-boot-spl
<top>.../Linux_for_Tegra/bootloader/ardbeg
9. Navigate to the following directory.
<top>.../Linux_for_Tegra/bootloader/ardbeg
../../wb_sign.sh u-boot.bin <KEY FILE> u-boot u-boot-spl
Now, Uboot is ready to support LP0 for PKC protected on Jetson TK1.
Flashing with Signed Boot File Binaries
1. Navigate to the directory where you installed L4T.
2. Place the Tegra device into force recovery mode.
To flash the Tegra device with PKC signed binaries, execute:
sudo ./flash.sh -x <chipid> -y PKC -u <keyfile> <device name> mmcblk0p1
To flash the Tegra device with clear binaries, execute:
sudo ./flash.sh <device name> mmcblk0p1
Where <device name> is:
Jetson TK1: jetson-tk1
Jetson TX1: jetson-tx1
Jetson TX2: jetson-tx2
Note:
Ensure the recovery button is pressed and reset. Even if the Tegra device is still in recovery mode after fusing.
Accessing the Fuse from the Target
The L4T secureboot package provides a means to access fuses from the target board after it boots up.
To access the fuse from the target board
1. Copy the <top>.../Linux_for_Tegra/pkc/tegrafuse.sh script to the ubuntu@<target IP address>.
2. To access the target’s fuses from the target board, login to the target board.
To display all fuses:
sudo ./tegrafuse.sh
To set or amend a specific fuse:
sudo ./tegrafuse.sh <fuse name> <fuse value>
 
Example: Burning the Fuse in a Factory Environment
 
Building the Fuse in a Trusted Environment
Burning the Fuse Blob in a Factory Environment
This topic provides an example reference implementation for burning fuses in a factory environment.
Building the Fuse in a Trusted Environment
Building a fuse blob in a factory environment requires:
Set up the preparation of the key host in a safe location
Generate the RSA key-pair
If necessary, prepare the DK/KEK/SBK/ODM fuses
To generate the fuse blob fuseblob.tbz2
For Jetson TX2:
1. Navigate to the directory where you installed L4T.
2. Execute the command.
sudo ./odmfuse.sh --noburn -i 0x18 -c PKC -p -k <key.pem> [--KEK0 <KEK0 file> --KEK1 <KEK1 file> --KEK2 <KEK2 file> --KEK256 <KEK256 file> -S <SBK file>] jetson-tx2
This standard Jetson TX2 fuse command requires an actual target device connected to the host and placed in force recovery mode.
To generate the fuse blob without actual Jetson target device attached to the host
add FAB=C04 in front of ./odmfuse.sh as follows:
sudo FAB=C04 ./odmfuse.sh --noburn -i 0x18 -c PKC -p -k <key.pem> [--KEK0 <KEK0 file> --KEK1 <KEK1 file> --KEK2 <KEK2 file> --KEK256 <KEK256 file> -S <SBK file>] jetson-tx2
For Jetson TX1 and Jetson TK1
1. Navigate to the directory where you installed L4T.
2. Execute the command.
sudo ./odmfuse.sh --noburn -i <chipid> -c PKC -p -k <key.pem> [-D <DK file> -S <SBK file>]
Burning the Fuse Blob in a Factory Environment
Burning the fuse blob in a factory environment requires:
Set up an X86 Linux host system as the factory fuse host.
The factory fuse host does not require the L4T BSP installation.
Download the fuseblob.tbz2 to the factory fuse host with the command:
sudo tar xvjf <download path>.../fuseblob.tbz2
Navigate to the bootloader directory.
Use the following procedure to burn the fuse.
To burn the fuse
1. Put the Tegra device into force recovery mode.
2. Execute the command:
sudo ./fusecmd.sh
Note:
This procedure can be used and repeated on multiple Tegra boards. All the boards are burned with the same fuseblob and have exactly the same fuse configurations.
 
Example: Flashing Signed Images in a Factory Environment
This topic provides an example reference implementation for flashing signed images in a factory environment and requires:
Setup the signing host in a safe location.
Use the following procedure to prepare the signed image blob.
To prepare the signed image blob
1. Navigate to the directory where you installed L4T.
cd <your_local_L4T_path>.../Linux_for_Tegra
2. If you are using a different security application, prepare the files using the user guide for that application.
3. Clean up the stale and unwanted content inside flashcmd.txt:
sudo rm -f bootloader/flashcmd.txt
4. Generate the signed binary image, signedimage.tbz2, as follows:
For Jetson TX2
sudo ./flash.sh --no-flash -x 0x18 -y PKC -u <keyfile> jetson-tx2 mmcblk0p1
This standard Jetson TX2 fuse command requires an actual target device connected to the host and placed in force recovery mode.
To sign binaries without an actual Jetson target device attached to the host, add FAB=C04 and FUSELEVEL=fuselevel_production in front of ./flash.sh as follows:
sudo FAB=C04 FUSELEVEL=fuselevel_production ./flash.sh --no-flash -x 0x18 -y PKC -u <keyfile> jetson-tx2 mmcblk0p12
For Jetson TX1:
sudo ./flash.sh --no-flash -x 0x21 -y PKC -u <keyfile> jetson-tx1 mmcblk0p1
For Jetson TK1:
sudo NOFLASH=1 ./flash.sh -x 0x40 -y PKC -u <keyfile> jetson-tk1 mmcblk0p1
sudo rm bootloader/*.raw
sudo tar cvjf signedimage.tbz2 bootloader
Note:
For security purposes, this signing host must be a separate machine from the key host.
To flash signed images in a factory environment
1. Setup an X86 Linux host as the factory flash host.
The factory flash host does not require the L4T BSP installation.
2. Download the signedimage.tbz2 to the factory flash host with the command:
sudo tar xvjf <download path>.../signedimage.tbz2
3. Navigate to the bootloader directory.
4. Flash the signed images as follows:
Put the Tegra device into force recovery mode.
Execute the command:
sudo bash flashcmd.txt
Note:
This procedure can be used and repeated on multiple properly fused Tegra boards. All the boards are burned with the same fuseblob and have exactly the same signed images flashed.