Secureboot
The NVIDIA® Tegra® Linux Driver Package provides boot security via the Secureboot package, which prevents execution of unauthorized boot codes through chain of trusts. The root-of-trust is on-die bootrom code and authenticates boot codes such as BCT, bootloader, and warmboot vector using Public Key Cryptography (PKC) stored in write-once-read-multiple fuse devices.
Fuses
Tegra devices contain multiple fuses that control different items for security and boot. Programming a fuse (changing the value of a fuse bit from 0 to 1) is non-reversible. Once a fuse bit is programmed (set 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, then all further fuse write requests are blocked and the fused values are available only through the provided Tegra API. However, the odm_reserved and odm_lock fields are still writable (you can change bit 0 to 1).
Even though all Tegra fuses may be writable, NVIDIA strongly recommends that the following fuses are not set manually:
•public_key_hash
•pkc_disable
•secure_boot_key
•odm_production_mode
Fuses handled by L4T secureboot
The following table shows fuses handled by L4T secureboot:
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 - 0x0 NS - 0x1 |
128 | secure_boot_key | Reserved (must be kept at zero) |
32 | device_key | Reserved (Must be untouched) |
Fuses handled by the user
The following table shows writable fuses:
Bitsize | Name | Default value set by odmfuse.sh |
1 | jtag_disable | 0x1 - disable JTAG |
256 | odm_reserved | Programmable fuses at your discretion. However, 32 MSB is reserved for NVIDIA use. |
4 | odm_lock | Each bit set disables write for 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. Refer to TRM. |
8 | sw_reserved | [2-0] sec_boot_dev_sel Valid if and only if the ignore_dev_sel_straps is enabled: 0-eMMC 2-SPI [3 ] ignore_dev_sel_straps Ignores boot strap. [4 ] enable_charger_detect [5--] enable_watchdog [7-6] reserved |
Overall Fusing and Signing Binaries Process
The following outlines the secure boot process with PKC:
1. Install the L4T secureboot package.
2. If necessary, burn ODM fuses.
3. Generate the RSA key-pair.
4. Burn PKC fuses and set ODM_PRODUCTION_MODE.
5. Sign boot files with PKC.
6. Flash the signed boot files.
The following outlines the secure boot process without PKC:
1. Install the L4T secureboot package.
2. If necessary, burn ODM fuses.
3. Set ODM_PRODUCTION_MODE.
4. Flash the clear boot files.
Note: This activity blocks fuse activity and protects the Tegra device from erroneous fuse burning. ODM_RESERVED and ODM_LOCK fuses are still writable.
Installing Secureboot
The following steps describe how to install secureboot.
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
•Tegra device is connected to the host with Type-B micro USB cable
•Debug serial port is connected to the host, if necessary
1. Download partner_supplement.tbz2.
2. Execute:
cd <L4T path>
Where <L4T path> specifies the path to where you installed L4T.
3. Execute the following:
tar xvjf partner_supplement.tbz2
tar xvjf secureboot_R21.5.0_hard.tbz2
Generating the RSA Key-pair
To lock fuse without PKC encryption, skip this step.
L4T secureboot requires 2048 bit RSA key-pair. To generate a key-pair, execute:
openssl genrsa -out rsa_priv.pem 2048
OpenSSL generates the key file named rsa_priv.pem. You must 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. NVIDIA recommends that access permission is restricted to a minimum number of personnel.
Burning Encryption Key Fuses and Setting ODM_PRODUCTION_MODE
The following describes how to burn encryption key fuses and how to set ODM_PRODUCTION_MODE.
1. Execute:
cd <L4T path>…/Linux_for_Tegra
Where <L4T path> specifies the path to 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 with PKC encryption and JTAG enabled:
sudo ./odmfuse.sh -i 0x40 -c PKC -k <keyfile>
•To fuse with PKC encryption and JTAG disabled:
sudo ./odmfuse.sh -j -i 0x40 -c PKC -k <keyfile>
•To fuse without PCK encryption and JTAG enabled:
sudo ./odmfuse.sh -i 0x40 -c NS
•To fuse without PCK encryption and JTAG disabled:
sudo ./odmfuse.sh -j -i 0x40 -c NS
Note: Applies to: U-Boot only.The odmfuse.sh script blocks the JTAG access by default, and U-Boot initializes the JTAG interface by default even when the JTAG usage is blocked by not specifying the -j option, and Tegra finds the activity is illegal and quietly halts. To enable the U-Boot function properly when the JTAG usage is blocked, it must be rebuilt with 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 */
}
Once the odm_production_mode is programmed to 1, during boot up, the U-Boot prints out the following harmless message:
!! odm_production_mode is not supported !!
This is only a warning stating that L4T_SecureOS is not yet supported (L4T does not support SecureOS, which protect kernel and provide DRM.)
You can safely ignore the message.
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. Unless you have an absolute reason to modify these fuses, skip this section.
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_disable to 0x0. Unless this option is specified and jtag_disable fuse is set to 0x0, the usage of JTAG debugger is blocked by default. |
-l 0xX | Sets odm_lock=0xX. Setting each bit locks corresponding 32bits in odm_reserved (i.e., setting odmlock=0x1 locks the first 32bit of odm_reserved read only and setting odmlock=0x5 locks the first and third 32bits of odm_reserved field read only and so on). |
-o <value> | Sets odm_reserved=<value>. The value should be quoted series of 8 32bit HEX numbers such as following line: "0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0xXXXXXXXX 0x00000000" Note the last 32bit HEX number must be 0x00000000 because that fuses are reserved for NVIDIA use. |
-r 0xXX | Sets sw_reserved=0xXX. The name of this fuse field is somewhat confusing but the actual meanings are 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 |
Signing Boot Files
The boot file signing process is integrated into the flashing process. You are not required to do anything.
Flashing with Signed Boot File Binaries
To flash with signed boot file binaries:
1. Execute:
cd <L4T path>…/Linux_for_Tegra
Where <L4T path> specifies the path to where you installed L4T.
2. Put the Tegra device into Forced Recovery Mode.
3. To flash the Tegra device with PKC signed binaries, execute:
sudo ./flash.sh -x 0x40 -y PKC -u <keyfile> jetson-tk1 mmcblk0p1
4. To flash the Tegra device with clear binaries, execute:
sudo ./flash.sh jetson-tk1 mmcblk0p1
Note: Make sure you press the RECOVERY and RESET button, and release, even if the Tegra device is still in recovery mode after fusing.