Disk Encryption ¶
Applies to the Jetson AGX Xavier series, the Jetson Xavier NX series, and the Jetson AGX Orin.
Disk encryption encrypts a whole disk or partition to protect the data
it contains.
NVIDIA
®
Jetson™
Linux offers disk encryption that is based on
Linux Unified Key Setup
(LUKS)
Data-at-rest encryption
,
the standard for Linux disk encryption. It provides a standard disk
format that stores all necessary setup information on the disk itself,
in the partition header. The passphrase in the Jetson
OP-TEE
luks-srv
Trusted Application (TA) supports disk encryption functionality with one-time
passphrase generation during boot time to unlock the encrypted disk.
Setup Preparation ¶
Jetson Linux uses
cryptsetup
, a LUKS user space command line utility, to
set up and unlock an encrypted disk. It uses the
DMCrypt
kernel module
as its backend. The utility sets up the encrypted disk as a LUKS
partition and configures it with a passphrase.
The
DMCrypt
kernel module is the standard device-mapper interface for
encryption functionality in the Linux kernel. It sits between the disk
driver and the file system, where it encrypts and decrypts data blocks
transparently.
For more information about
cryptsetup
and
DMCrypt
, see the
cryptsetup project
and the
DMCrypt documentation
,
both hosted by GitLab.
Details of Operation ¶
Two types of keys are used for disk encryption:
-
The master key , also known as the Disk Encryption Key (DEK). This key is used for data encryption or decryption when data is transferred between the file system and the disk.
The master key is generated by
cryptsetup
. The default and recommended source for data used to generate the key is/dev/random
. The key resides in the LUKS header, and is encrypted by the key derived from the passphrase. -
The passphrase or password is an input string or pattern supplied by the user to set up disk encryption and lock the disk. The same input is used to decrypt and unlock data stored on the disk.
The passphrase is generated with help from two applications:
-
luks-srv
: A trusted application (TA) that utilizes the key generating service fromjetson_user_key_pta
. Using that service it can derive a LUKS key, which is the root key for deriving the passphrase.This block shows the service interfaces provided by
luks-srv
:/* * Each trusted app UUID should have a unique UUID that is * generated from a UUID generator such as * https://www.uuidgenerator.net/ * * UUID : {b83d14a8-7128-49df-9624-35f14f65ca6c} */ #define LUKS_SRV_TA_UUID \ { 0xb83d14a8, 0x7128, 0x49df, \ { 0x96, 0x24, 0x35, 0xf1, 0x4f, 0x65, 0xca, 0x6c } } #define LUKS_SRV_CONTEXT_STR_LEN 40 #define LUKS_SRV_PASSPHRASE_LEN 16 /* * LUKS_SRV_TA_CMD_GET_UNIQUE_PASS - Get unique passphrase * param[0] in (memref) context string, length * param[1] out (memref) passphrase, size * param[2] unused * param[3] unused */ #define LUKS_SRV_TA_CMD_GET_UNIQUE_PASS 0 /* * LUKS_SRV_TA_CMD_SRV_DOWN - Turn off the service * param[0] unused * param[1] unused * param[2] unused * param[3] unused */ #define LUKS_SRV_TA_CMD_SRV_DOWN 1
-
nvluks-srv-app
: A Client Application (CA) in the normal (non-secure) world that communicates withluks-srv
to retrieve the passphrase.cryptsetup
uses the passphrase to unlock the encrypted disk.
The cryptographic algorithm used for disk encryption is AES-XTS, with a key length of 256 bits. This mode of operation makes the encrypted data look completely random, minimizing the potential for attack. The entire key derivation process is performed in the secure world.
The following diagram outlines the overall process:
-
The
nvluks-srv-app
CA queries the per-device unique passphrase via the command interfaceLUKS_SRV_TA_CMD_GET_UNIQUE_PASS
. -
When the
luks-srv
TA receives the command, it sends a request tojetson_user_key_pta
to generate a per-device unique LUKS key.jetson_user_key_pta
uses the NIST-SP 800-108 KDF to derive a new key from the EKB disk encryption key.The KDF’s input parameters are the fixed label string
"luks-srv-ecid"
and the ECID as the context string. -
The TA uses the LUKS key to generate a passphrase. The passphrase is generated with the same KDF as the LUKS key.
The KDF’s context string parameter is the disk UUID, so no user interaction is needed to create the encrypted disk image or to unlock it at boot time. The fixed label string is
"luks-srv-passphrase-unique"
. -
The TA returns the output passphrase.
-
Send the
LUKS_SRV_TA_CMD_SRV_DOWN
command to shut the service down. This ensures that passphrase generation is done only once.
The generation process uses this key derivation function (KDF) to generate a per-device unique LUKS key or a generic key:
key = NIST-SP-800-108( inkey , labelstring , contextstring )
Where:
-
NIST-SP-800-108 is a key derivation function (KDF) recommended by the National Institute of Standards and Technology algorithm for key derivation using pseudorandom functions..
-
in-key is the key source used to derive a new key.
-
label-string identifies the purpose of the key to be generated. In the reference implementation label-string is a fixed value defined by the TA.
-
context-string is a string that contains information related to the derived key, and which the KDF uses as a parameter for key generation. In the reference implementation the default context string is the disk’s UUID, but you can change this by modifying the TA.
To unlock the encrypted disk with
nvluks-srv-app
, enter these commands:
#!/bin/bash
# Using "cryptsetup" and "nvluks-srv-app" to unlock the encrypted device:
nvluks-srv-app --context-string "${DISK_UUID}" --get-unique-pass | cryptsetup -c \
luksOpen
Where:
-
/dev/mmcblk1
. -
/dev/mapper/DM_name
.
See Basic Flashing Script Usage in the topic Flashing Support for more information.
Note
To prevent any form of attack from extracting the passphrase at boot time (e.g. in the initrd), use the command type
LUKS_SRV_TA_CMD_SRV_DOWN
. This command instructs
luks-srv
not to respond to a
LUKS_GET
command (to get the passphrase) until reboot. This step is crucial to ensure the security of your design.
The Threat Model ¶
The purpose of disk encryption is to prevent an attack from stealing or tampering with data on the disk. Even if the disk is physically unmounted (or, in the case of an internal device such as an eMMC, is removed from the device), the data cannot be exposed.
Disk encryption cannot protect against the following types of threat:
-
A background process or daemon that has a security hole. An attacker may be able to use the hole to gain control of the process and access the disk.
-
Theft or leakage of the login ID and password. An attacker can use these credentials to log in to the device and access the disk.
Disk Encryption Implementation in Jetson Linux ¶
Jetson Linux provides a reference implementation of disk encryption which fulfills the security requirements of many use cases. If your use case’s requirements are different, you can modify it or use it as a model for implementing your own.
Layout of an Encrypted Disk ¶
Because Bootloader cannot read encrypted files, disk encryption
requires Jetson Linux to divide a “naive” system’s
APP
partition in two:
-
The unencrypted
APP
partition contains the/boot
branch of the file system, including the kernel, DTB, and initrd images. -
A new, encrypted
APP_ENC
partition contains the rest of the file system.
Following is an example of the
APP
partition definition for a system on
which disk encryption is not enabled. You can find a definition like
this one in the Jetson Linux BSP partition configuration files, e.g.
Linux_for_Tegra/bootloader/t186ref/cfg/flash_t194_sdmmc.xml
for an
NVIDIA
®
Jetson AGX Xavier™
series device booting from SDMMC memory:
sequential
basic
APPSIZE
0
0x8
4096
0
APPFILE
APPUUID
**Required.** Contains the rootfs. This partition must be defined after
``primary_GPT`` so that it can be accessed as the fixed known special device
``/dev/mmcblk0p1``.
The following example shows how disk encryption separates
APP
into two partitions. (Each partition’s differences from the preceding example are highlighted in red type. The elements in the two definitions are the same.) You can find the file in the Jetson Linux BSP, e.g.
Linux_for_Tegra/bootloader/t186ref/cfg/flash_t194_sdmmc_enc_rfs.xml
for the same device as above:
sequential
basic
104857600
0
0x8
4096
0
system_boot.img
APPUUID
**Required.** Contains the boot partition. This partition must be
defined after ``primary_GPT`` so that it can be accessed as the fixed
known special device ``/dev/mmcblk0p1``.
APP_ENC" type="data" encrypted="true">
sequential
basic
APP_ENC_SIZE
0
0x8
4096
0
system_root_encrypted.img
APP_ENC_UUID
**Required.** Contains the encrypted root partition.
Notice that the
element of
APP
specifies an actual number, but
the
element of
APP_ENC
specifies a symbol,
APP_ENC_SIZE
. Later,
the value of
APP_ENC_SIZE
must be calculated by subtracting the size of
APP
from the total rootfs size.
Each partition’s
element specifies the actual file name of
the appropriate disk image (not a symbol that is resolved to the file
name during flashing).
The partitions’
elements specify the partitions’ UUIDs,
APPUUID
and
APP_ENC_UUID
respectively. Both symbols are translated to
real UUID numbers by the image generation process.
The
APP_ENC
partition’s encrypted attribute indicates that the partition
is encrypted.
With the new partition layout, new parameters are needed in the board
configuration file to enable disk encryption and apply the new partition
layout file. Use the appropriate board configuration file for your
device, e,g,
Linux_for_Tegra/p2972-0000.conf.common
for a Jetson AGX
Xavier module in a Jetson AGX Xavier Developer Kit. The
disk_enc_enable
setting indicates that disk encryption is enabled, and
EMMC_CFG
identifies the partition layout file to use:
disk_enc_enable=1;
EMMC_CFG=flash_l4t_t194_sdmmc_enc_rfs.xml;
The flash tool uses the board configuration file to generate file system images and flash them onto the device.
How to Create File System Images ¶
When you create file system images to support booting with an encrypted disk, keep the following points in mind:
-
The
bootarg
kernel command line’s root parameter must use the disk’s UUID (not the partition’s UUID specified in the partition definition) to identify the root disk if the device is to boot from an encrypted root disk. -
The
crypttab
file in initrd includes the mount point and the device name of the encrypted disk. It may be a real device name like/dev/mmcblk0p1
or the UUID of the disk. -
The
fstab
file in the rootfs is updated with the/boot
directory in theAPP
partition. This helps the automount process to mount the partition at boot time.
How to Create an Encrypted Rootfs on the Host ¶
The rootfs is generated on the host by
flash.sh
. The diagram below shows
the elements of the rootfs (in green), the utilities used to generate it
(in gray), and the input (in blue).
The input has two parts: the plain key file of the EKB key used for disk encryption, and an input string used to generate the passphrase. By default, the input string is the UUID of the encrypted disk. You can modify the script that generates the rootfs to let user to enter their own string. You must change the initrd accordingly to make it use the user-supplied string.
You must generate the rootfs on a secure system, that is, a secure host
computer equipped with a
Hardware Security Module
(HSM). The HSM is
used for key generation and management to secure key assets and safe
transport to the factory floor. This is necessary to ensure that the
keys cannot be leaked to an unsecure system on the production line.
flash.sh
invokes two helper scripts to generate the passphrase and the
disk images:
-
gen_luks_passphrase.py
follows the same process as thehwkey-agent
andluks-srv
TAs to derive the LUKS key, and uses the key to generate the passphrase. -
disk_encryption.sh
outputs the disk images for the initrd,system_boot.img
, andsystem_root_encrypted.img
.
The Jetson Linux reference implementation only generates per-device encrypted disk images. Use it as a starting point to develop a script that is suited to your use case and production environment.
To flash the encrypted rootfs on the host with
flash.sh
for the Jetson AGX Xavier series and the Jetson Xavier NX series:
# The disk encryption key in the EKB partition:
$ echo "00000000000000000000000000000000" > ekb.key
$ sudo ROOTFS_ENC=1 ./flash.sh -i "./ekb.key"
Flashing the encrypted rootfs on the host with flash.sh for the Jetson AGX Orin requires an update of the
Linux_for_Tegra/bootloader/eks.img
.
-
Decompress the OP-TEE source package and run
example.sh
in it to generate a test EKS image(In real production scenario, you must generate your own EKS image using your own keys):$ cd optee/samples/hwkey-agent/host/tool/gen_ekb/ # Take a look at example.sh and you can see the test keys $ ./example.sh
-
Copy the
eks_t234.img
generated by example.sh to theLinux_for_Tegra/bootloader
folder and overwrite theeks.img
file.
The
Tool for EKB Generation
chapter in OP-TEE has detailed descriptions about EKS image generation.NVIDIA strongly recommends you to generate your own keys and EKS image, the keys defined in
example.sh
and the EKS image it generates are only for test purpose.
-
Use
flash.sh
to generate and flash the encrypted rootfs:# The disk encryption key in the EKB partition: # This key is defined in example.sh too to generate the EKS image $ echo "f0e0d0c0b0a001020304050607080900" > ekb.key $ sudo ROOTFS_ENC=1 ./flash.sh -i "./ekb.key"
Where:
-
$(BOARD)
for your Jetson module and configuration, as shown in the table in the section Jetson Modules and Configurations in the topic Quick Start . -
The
flash.sh
command line option
-i
specifies the key to be used for
disk encryption. The reference implementation described above uses the
EKB key. NVIDIA recommends that you customize the script to use a
different key source for the sake of security. The keys in the example above
are only for reference and testing purposes so that you should not use them as
given. When you change the key, change the EKS partition accordingly,
and review the overall key and passphrase generation flow to be sure
that everything works correctly.
How to Flash an Encrypted Rootfs to an External Storage Device ¶
To flash an encrypted rootfs generated by flash.sh to an external
storage device, use
l4t_initrd_flash.sh
(also known as “the initrd
flashing tool”). (See the section
Flashing with initrd
in the topic
Flashing Support
).
Following is an example of commands that use
l4t_initrd_flash.sh
to
flash an encrypted rootfs to an NVMe SSD attached to a Jetson AGX Xavier
series device:
$ cd Linux_for_Tegra
$ sudo ROOTFS_ENC=1 ./tools/kernel_flash/l4t_initrd_flash.sh --external-device nvme0n1p1 \
-c ./tools/kernel_flash/flash_l4t_nvme_rootfs_enc.xml --external-only -S 8GiB \
jetson-xavier external
Tools and instructions for flashing an encrypted rootfs with initrd may
be found in the directory
/Linux_for_Tegra/tools/kernel_flash/
. For more
detailed information, see
README_initrd_flash.txt
in that directory.
To Enhance initrd to Unlock an Encrypted Rootfs ¶
To boot from an encrypted root file system, you need an initrd image
which includes the necessary utilities (e.g.
cryptsetup
) and scripts to
set up the root device after the kernel is initialized, but before the
rest of the operating system is booted. The image must contain the
APP
partition, which contains the
/boot
branch of the rootfs (unencrypted),
and the
APP_ENC
partition, which contains the rest of the rootfs
(encrypted).
The boot flow diagram below shows that by default the Bootloader (UEFI)
uses the
APP
partition as the boot partition.
The
init
script in the initrd follows these steps to check the encrypted
root device, unlock it, and mount it:
-
Verify that the
root
parameter specifies the same device as the root device setting in/etc/crypttab
. -
Verify that the root device is a LUKS device.
-
Unlock the encrypted root device with the per-device unique passphrase.
-
Mount the root device.
-
Command the
luks-srv
TA not to respond to further passphrase requests until reboot.
To modify initrd to unlock additional encrypted file systems ¶
The file
/etc/crypttab
, kept in initrd, describes encrypted block
devices that are set up during system boot. Each line of this file has
the form:
UUID=
Where:
-
/dev/mapper/
. -
Here are two examples of entries in
/etc/crypttab
:
crypt_root UUID=b5600ed6-69e7-42b8-bee3-ecfdd12649d1
crypt_UDA UUID=cf6fa01d-1127-4612-9992-2f6db77385e0
If your device has several encrypted file systems, you must add a line
to
/etc/crypttab
for each one you want Bootloader to unlock.
This is an example of how to unlock an encrypted file system:
-
Enter this command to find the UUID of the encrypted file system:
$ sudo blkid | grep TYPE="crypto_LUKS"
This command line displays a line of output for each encrypted disk that includes the disk’s UUID. Such a line looks like this:
/dev/mmcblk0p43: UUID="5096aa4d-6590-429b-9295-a1fe041b8fa3" TYPE="crypto_LUKS" PARTLABEL="UDA" PARTUUID="2b23da7f-2f18-44bf-9e1d-6e3a3a39ad21"
-
Unpack the initrd. For instructions, see the section Modifying Jetson RAM Disk in the topic Flashing Support .
-
Add a line to
/etc/crypttab
for each encrypted file system that you want to unlock at subsequent reboots. The line specifies the UUID of the file system to be unlocked, as in this example:crypt_fs UUID="5096aa4d-6590-429b-9295-a1fe041b8fa3"
-
Repackage the initrd and store it in
/boot
, replacing the initrd that was originally there. -
Create a subdirectory in
/mnt
in which initrd can mount each unlocked file system during the initialization process. For the sake of simplicity, NVIDIA recommends giving each subdirectory the same name as the volume to be mounted there. For the volume specified in step 3, the subdirectory would be namedcrypt_fs
:$ mkdir -p /mnt/crypt_fs
Bootloader unlocks your encrypted file system at each subsequent reboot.
Summary ¶
The following diagram shows the overall flow of the encrypted disk unlocking process.
The steps of the process are:
-
nvluks-srv-app
queries the hardware-based passphrase from the Trustyluks-srv
TA and pass it to thecryptsetup
utility. -
cryptsetup
unlocks the disk and decrypts the disk encryption key (DEK) with the passphrase. -
cryptsetup
invokes theDMCrypt
kernel module and loads the key into the kernel.DMCrypt
uses thetegra-crypto
driver, which uses Security Engine (SE) hardware for data encryption and decryption. -
Subsequent disk I/O is routed through
DMCrypt
, which decrypts and encrypts data as it reads and writes.
Manufacturing process ¶
The following diagram illustrates the post-development manufacturing process for a Jetson-based device.
All disk images and blobs to be flashed onto production devices must be generated on a secure system. The HSM holds all of the security keys needed in the manufacturing process. If more than one production device is to be flashed at a time, the security machine must be able to deploy images to other systems (flashing machines) for flashing devices.
If the device is designed to use per-device encrypted disk images, the images must be generated one at a time on the security machine.