174
edits
Line 257: | Line 257: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Which as we can see has zeros in all of them because we have not write to them. Once a 1 has been written to one of the bits of the fuses, it cannot be reversed. The next step to activate secure boot is to generate the keys that are going to be stored in the fuses. For this example we are going to just use the PublicKeyHash fuse and SecureBootKey fuse. The Public key is use for boot code authentication and the secure boot key is used for boot codes encryption and decryption. | |||
Starting with the Public key used for authenticating the boot codes, it can be generated as an RSA 3K key, ECDSA P-256 or ECDSA P-521 key. For reference, these are two types of algorithms for genetring a PKC pair and the numbers are just the size of the keys. In terms of security RSA 3K and ECDSA P-256 provide a similar level of security but ECDSA is more efficient because it needs less storage. ECDSA P-521 provides a higher security level the the previous algorithms explained and has a lower size than RSA 3K. RSA 3K is a more known/applied/compatible algorithm. For this guide, an RSA 3K key is going to be used. To generated, create a keys folder inside the Linux for Tegra directory: | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
mkdir keys | |||
cd keys | |||
openssl genrsa -out rsa_priv.pem 3072 | |||
</syntaxhighlight> | |||
the output should look like the following: | |||
<syntaxhighlight lang="bash"> | |||
Generating RSA private key, 3072 bit long modulus (2 primes) | |||
.................................................................++++ | |||
...................................................................++++ | |||
e is 65537 (0x010001) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
A file named rsa_priv.pem should be in the directory. To generate the Public key hash, the tegrasign_v3.py script can be used to generate it, use this command from the keys directory: | |||
<syntaxhighlight lang="bash"> | |||
./tegrasign_v3.py --pubkeyhash rsa_priv.pubkey rsa_priv.hash --key rsa_priv.pem | |||
</syntaxhighlight> | |||
the output looks like the following: | |||
<syntaxhighlight lang="bash"> | |||
Key size is 384 bytes | |||
Saving pkc public key in rsa_priv.pubkey | |||
Sha saved in pcp.sha | |||
tegra-fuse format (big-endian): 0x513a1d8764dbd5d700932d18db4f48da4c13094b4986660c4525d69ef2307ceaba65ddec675bacc8bbeb2c91d31f1e7fb98be4472a354010ff7dea49510b7b48 | |||
</syntaxhighlight> | |||
make sure to save the result because it is going to be need on the fuse configuration file explained below. | |||
Now, the secure boot key is randomly generated with a size of 32 bits. Specifically, the Orin SoC requires an SBK key of eight 32-bit words. You can use the following commands to generate it: | |||
<syntaxhighlight lang="bash"> | |||
SBK_0=$(openssl rand -hex 4) | |||
SBK_1=$(openssl rand -hex 4) | |||
SBK_2=$(openssl rand -hex 4) | |||
SBK_3=$(openssl rand -hex 4) | |||
SBK_4=$(openssl rand -hex 4) | |||
SBK_5=$(openssl rand -hex 4) | |||
SBK_6=$(openssl rand -hex 4) | |||
SBK_7=$(openssl rand -hex 4) | |||
SBK_KEY=$(echo "0x${SBK_0} 0x${SBK_1} 0x${SBK_2} 0x${SBK_3} 0x${SBK_4} 0x${SBK_5} 0x${SBK_6} | |||
0x${SBK_7}") | |||
echo "${SBK_KEY}" > sbk.key | |||
SBK_KEY_XML=$(echo "0x${SBK_0}${SBK_1}${SBK_2}${SBK_3}${SBK_4}${SBK_5}${SBK_6}${SBK_7}") | |||
echo "${SBK_KEY_XML}" > sbk_xml.key | |||
</syntaxhighlight> | |||
A sbk.key and a sbk_xml.key file are now in the directory. the second one has the value that is going to be used in the fuse configuration file. | |||
In this case we use openssl to generate the 8 random 32 byte words. It is used because it's a widely adopted, open-source cryptographic toolkit that provides robust functionality for securing communications and data. But you can use the tool of your choice. | |||
The next step is to create the fuse configuration file. The fuse configuration file is a xml file that states that which fuse is burned with x value. It has three main tags which are name, size and value. In the same order, the tags are for the fuse name, its size in bytes and the value to be burned on to the fuse. There is a list of fuses on the Orin SoCs, but we are going to use only the PublicKeyHash, SecureBootKey and BootSecurityInfo fuses. For reference, below is the Jetson Orin reference configuration file for your reference: | |||
<syntaxhighlight lang="bash"> | |||
<genericfuse MagicId="0x45535546" version="1.0.0"> | |||
<!-- <fuse name="OdmId" size="8" value="0xFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="OdmInfo" size="4" value="0xFFFF"/> --> | |||
<!-- <fuse name="ArmJtagDisable" size="4" value="0x1"/> --> | |||
<!-- <fuse name="DebugAuthentication" size="4" value="0x1F"/> --> | |||
<!-- <fuse name="CcplexDfdAccessDisable" size="4" value="0x1"/> --> | |||
<!-- <fuse name="ReservedOdm0" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="ReservedOdm1" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="ReservedOdm2" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="ReservedOdm3" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="OdmLock" size="4" value="0xF"/> --> | |||
<!-- <fuse name="ReservedOdm4" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="ReservedOdm5" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="ReservedOdm6" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="ReservedOdm7" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="OptInEnable" size="4" value="0x1"/> --> | |||
<!-- <fuse name="SwReserved" size="4" value="0xFFFFFF"/> --> | |||
<!-- <fuse name="BootDevInfo" size="4" value="0xFFFFFF"/> --> | |||
<!-- <fuse name="ZeroizeDis" size="4" value="0x1"/> --> | |||
<!-- <fuse name="PublicKeyHash" size="64" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="PkcPubkeyHash1" size="64" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="PkcPubkeyHash2" size="64" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="EndorseKey" size="68" value="0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="SecureBootKey" size="32" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="Kdk0" size="32" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="PscOdmStatic" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="OemK1" size="32" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="OemK2" size="32" value="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"/> --> | |||
<!-- <fuse name="BootSecurityInfo" size="4" value="0xFFFFFFFF"/> --> | |||
<!-- <fuse name="SecurityMode" size="4" value="0x1"/> --> | |||
</genericfuse> | |||
</syntaxhighlight> | |||
It is also important to check the [https://developer.download.nvidia.com/assets/embedded/secure/jetson/agx_orin/Jetson-Orin-Fuse-Specification_DA-10877-001v1.4.pdf?__token__=exp=1742448417~hmac=d2e6139780a4fc1fed9eb010099f9002929c35437006cd2a532ce03d5c41cbfd&t=eyJscyI6ImdzZW8iLCJsc2QiOiJodHRwczovL3d3dy5nb29nbGUuY29tLyJ9 Jetson Orin Fuse Specification: Application Note] to get information of the fuses being burned. | |||
Create and open a fuse_config.xml file with your favourite text editor and add the fuse burning data. In our case it looks like the following. As a note MagicId of “0x45535546” is used by the target-binary and must not be changed.: | |||
<syntaxhighlight lang="bash"> | |||
<genericfuse MagicId="0x45535546" version="1.0.0"> | |||
<fuse name="PublicKeyHash" size="64" value="0x99a6b7d25ffd5d7cc49bf2612d01d7fe58b5121f9c473748728232bc114c25ae2415d56666157c79fc9bf0e3b4445344ff8af51a64f334289912cdff7414fa00"/> | |||
<fuse name="SecureBootKey" size="32" value="0xf4d8f0c3180f8b2b430d89e1eb0d600c01f99be7a3e9045d4b27d621de571d57"/> | |||
<fuse name="BootSecurityInfo" size="4" value="0x9"/> | |||
</genericfuse> | |||
</syntaxhighlight> | |||
With the fuse data generated, we can proceed with the encryption of it. In this process we will also activate the decryption of the fuse blob (fuse data encrypted) and the fuse burning in the board. | |||
<syntaxhighlight lang="bash"> | |||
sudo ./fskp_fuseburn.py -b -f ~/work/devdir/security-features-RnD/nvidia-jetson4/Linux_for_Tegra/keys/fuse_config.xml -i 63 --key-exp fskp_ak.bin fskp_ek.bin --fskpcfg fskp_conf.txt -g out/ -c 0x23 -B ~/work/devdir/security-features-RnD/nvidia-jetson4/Linux_for_Tegra/jetson-orin-nano-devkit.conf --board-spec orinnano-board-spec.txt -v | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="bash"> | |||
sudo ./fskp_fuseburn.py --board-spec orinnano-board-spec.txt -P ./out -b -c 0x23 -B ~/work/devdir/security-features-RnD/nvidia-jetson4/Linux_for_Tegra/jetson-orin-nano-devkit.conf | |||
</syntaxhighlight> | |||
=== UEFI Secure Boot === | === UEFI Secure Boot === |
edits