Data-at-rest encryption

Hi,

I would like to implement the “Data-at-rest encryption” from toradex :
https://developer.toradex.com/torizon/security/encryption-on-torizon/

as you can see I’m using a “standard” torizon image : 7.0.0-build.1.

------------------------------------------------------------
Bootloader:               U-Boot
Kernel version:           6.6.23-7.0.0-g558ba3740880 #1-Torizon SMP PREEMPT Wed Sep 25 11:25:16 UTC 2024
Kernel command line:      root=LABEL=otaroot rootfstype=ext4 quiet logo.nologo vt.global_cursor_default=0 plymouth.ignore-serial-consoles splash fbcon=map:3 ostree=/ostree/boot.1/torizon/4af7c406269eb5dc7b89049a3adfced1ac4641115df55a148cee5387d730bbf1/0 loglevel=8
Distro name:              NAME="Torizon OS"
Distro version:           VERSION_ID=7.0.0-build.1
Hostname:                 verdin-imx8mm-xx
------------------------------------------------------------

Hardware info
------------------------------------------------------------
HW model:                 Toradex Verdin iMX8M Mini on Verdin Development Board
Toradex version:          0057 V1.1B
Serial number:            xx
Processor arch:           aarch64
------------------------------------------------------------

while I was reading this article meta-toradex-security/docs/README-encryption.md at scarthgap-7.x.y · toradex/meta-toradex-security · GitHub, I saw that it was possible to use a TPM, which is perfect for me as I have a TPM interfaced in I2C with my SoM.

However, I don’t understand this documentation: meta-toradex-security/docs/README-encryption.md at scarthgap-7.x.y · toradex/meta-toradex-security · GitHub

The chapter we’re interested in “Enabling and configuring encryption” asks you to inherit the “tdx-encrypted” class and add the line to an “OE” configuration file?

I think I’ve understood that I need to build a Torizon OS image from source with the yocto project, but I can’t understand with the documentation you’ve linked to: Build Torizon OS from Source With Yocto Project/OpenEmbedded | Toradex Developer Center
where / in which file I need to inherit the “tdx-encrypted” class?
is It the “conf/local.conf” one ?

Is it just a layer that I need to import into my image and that you’ve already developed (meta-toradex-security)? So I don’t need to touch the Linux kernel variables myself?

Also is this process compatible with the build process using CROPS ? the containerized torizon os build ?

Thank you !

Hi, I’m the Toradex AI Assistant. The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hello there!

Yes, you can implement data-at-rest encryption on your Verdin iMX8MM, as it is one of the supported System on Modules (SoMs) for this feature. To get started with encryption using a Trusted Platform Module (TPM), follow these steps:

  1. Build Torizon OS from Source: You will need to build TorizonCore from source using the meta-toradex-security layer. This layer provides the necessary configurations for encryption.

  2. Choose Your Build Environment: You can opt for either a native Linux build environment or a containerized build using CROPS. If you choose CROPS, use the following command to set up your build environment:

    docker run --rm -it --name=crops -v ~/yocto-workdir:/workdir --workdir=/workdir -e MACHINE=<machine> -e IMAGE=<image> torizon/crops:scarthgap-7.x.y startup-tdx.sh
    
  3. Configure the Build: Add the necessary configurations to the conf/local.conf file. This is where you will include class inheritance and any other build-specific settings.

  4. Execute the Build Process: To build the image, use the following command:

    bitbake torizon-docker
    

The meta-toradex-security layer will handle the Linux kernel configurations, so you won’t need to manually configure those variables. This process is compatible with both native and containerized (CROPS) build environments.

For more detailed guidance, you can refer to the Torizon Security Documentation and the TorizonCore Build Instructions.

I hope this helps you get started with implementing encryption on your device. If you have any more questions, feel free to ask!

Best regards,
Toradex AI Assistant

Greetings @autolab,

The chapter we’re interested in “Enabling and configuring encryption” asks you to inherit the “tdx-encrypted” class and add the line to an “OE” configuration file?

Basically add this to whatever top-level OE configuration file that affects the Yocto build. The most common file would of course be your local.conf.

Is it just a layer that I need to import into my image and that you’ve already developed (meta-toradex-security)? So I don’t need to touch the Linux kernel variables myself?

If you setup the Yocto build with our manifest, then it should automatically include the meta-toradex-security layer as part of the build. At least this is how it is in our latest versions.

Also is this process compatible with the build process using CROPS ? the containerized torizon os build ?

Yes, it should work. The CROPS container just provides a build environment it should not affect the actual build.

Best Regards,
Jeremias

1 Like

Hi thank you for the answer !!

Here is what I did :slight_smile:

Setup and Build yocto project container :

docker run --rm -it --name=crops \
-v ~/dev/yocto:/workdir \
--workdir=/workdir \
-e MACHINE=verdin-imx8mm \
-e IMAGE=torizon-docker \
torizon/crops:scarthgap-7.x.y startup-tdx.sh

I added those line inside of /conf/local.config

INHERIT += "tdx-encrypted"
TDX_ENC_STORAGE_LOCATION = "/dev/mmcblk0p1" #partion du disque que l'on souhaite chiffrer
TDX_ENC_KEY_BACKEND:forcevariable = "tpm"

Build the new image

bitbake torizon-docker

Which image should I use ?

/workdir/torizon/build-torizon/deploy/images/verdin-imx8mm$ grep *.tar
grep: torizon-docker-verdin-imx8mm-Tezi_7.2.0-devel-20250415135052+build.0.tar: binary file matches
grep: torizon-docker-verdin-imx8mm-Tezi.tar: binary file matches

I had used the TorizonCore Builder tool on my old image, which was a Toradex image, to add an overlay: in particular, to activate the TPM in I2C.

Should I use TorizonCore Builder on this new image I’ve just created to add my overlay and then use the same methods to deploy?

Like you mention here ?

Then, all you need from Yocto is the resulting image in the Toradex Easy Installer format, which you will use with the TorizonCore Builder Tool to unpack the image and then push it to Torizon Cloud.

Like this inside the file : tcbuild.yalm


input:
  easy-installer:
    local: images/torizon-docker-verdin-imx8mm-Tezi_7.2.0-devel-20250415135052+build.0.tar #the new image I juste created
customization:
  # >> Splash screen:
  splash-screen: he-arc-splash-screen.png
  device-tree:
    # >> Directories where to look for include files.
    include-dirs:
      - linux/include/
    # >> Custom device tree source:
    custom: linux/arch/arm64/boot/dts/freescale/imx8mm-verdin-nonwifi-dev.dts
    # >> Device-tree overlays configuration:
    overlays:
      add:
        - device-trees/overlays/verdin-imx8mm_spidev_overlay.dts #ajout de spidev
        #- device-trees/overlays/verdin-imx8mm_dsi-to-hdmi_overlay.dts
        - device-trees/overlays/verdin-imx8mm_disable_can1.dts
        - device-trees/overlays/verdin-imx8mm_extra_gpios_overlay.dts #custom device tree

output:

  easy-installer:
    # >> Output directory of the customized image (REQUIRED):
    local: torizon-core-docker-verdin-imx8mm-Tezi_7.0.0.CUSTOM_IMAGE1.0

Which image should I use ?

Both of those files are the same I’m pretty sure, as in one is a symlink to the other.

Should I use TorizonCore Builder on this new image I’ve just created to add my overlay and then use the same methods to deploy?
Like you mention here ?

Correct, the input image to TorizonCore Builder is the image that will be customized. Therefore if you want to customize this new image you should use it as the new input.

Best Regards,
Jeremias

1 Like

Thank you !

I was able to rebuild the image with my overlays with TorizonCore Builder and then to deploy It on my CoM ! Worked just fine :slight_smile:

I did the deployement this way :

torizoncore-builder images unpack torizon-core-docker-verdin-imx8mm-Tezi_7.2.0.YoctoBuild_v1
torizoncore-builder deploy --remote-host ipTargetCoM --remote-username usrname--remote-password pwd--reboot

However, I think I made a mistake by attempting to encrypt the whole system, including Linux itself, which is already in use (lol), and that’s why it can’t be done.

I believe I might have a general misunderstanding about what exactly I should encrypt.

Should I create a new partition, put all my application data (in my case, my containers) into it, and only encrypt this partition?

or does Toradex’s encryption functionality is designed to handle full disk encryption ?

tpm: Setting up partition with dm-crypt...
+ dmsetup -v create encdata --table '0 7512064                  crypt capi:cbc(aes)-plain :32:trusted:tdxenc                  0 /dev/mmcblk0p1 0 1 sector_size:512'
device-mapper: reload ioctl on encdata (251:0) failed: Device or resource busy
Command failed.
+ tdx_enc_exit_error 'Error setting up dm-crypt partition!'
+ tdx_enc_log 'ERROR: Error setting up dm-crypt partition!'
+ echo 'tpm: ERROR: Error setting up dm-crypt partition!'
tpm: ERROR: Error setting up dm-crypt partition!
+ exit 1
lsblk
NAME         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
mmcblk0      179:0    0  3.6G  0 disk
`-mmcblk0p1  179:1    0  3.6G  0 part /var
                                      /usr
                                      /boot
                                      /
                                      /sysroot
mmcblk0boot0 179:32   0   16M  1 disk
mmcblk0boot1 179:64   0   16M  1 disk
zram0        253:0    0    0B  0 disk

local.conf

# Add meta-toradex-security
INHERIT += "tdx-encrypted"
TDX_ENC_STORAGE_LOCATION = "/dev/mmcblk0p1"
TDX_ENC_KEY_BACKEND:forcevariable = "tpm"

or does Toradex’s encryption functionality is designed to handle full disk encryption ?

The current implementation of the data-at-rest encryption feature in meta-toradex-security is designed to just encrypt a single specific partition. This partition can’t be the main root partition where the root filesystem resides.

With our current security features we make use of ComposeFS to protect the filesystem as described here: Secure Boot | Toradex Developer Center

Should I create a new partition, put all my application data (in my case, my containers) into it, and only encrypt this partition?

If you’re interested in security protection for your containers this is something we have planned in the future with container image signing: Secure Boot | Toradex Developer Center

It might help to take a step back and describe if you could what exactly you want to achieve here regarding security use-cases. It sounds like you have a use-case/goal in mind, it would be useful feedback for us to understand what you have in mind.

Best Regards,
Jeremias

Thank you for your explanation.

To give more context on my use case:

I run a custom application inside a Docker container on the Toradex module. This application exposes an OPC-UA server, which uses a persistent volume to store its certificate and private key.

My goal is to protect this private key from being accessed if the device is physically stolen.

In addition, I would like to protect the intellectual property: the application running in the container is custom-developed, and I’d prefer to prevent anyone from accessing or copying it directly from the storage if they get physical access to the device.

Therefore, encrypting the storage (even just one partition that contains application data and volumes) seems like a good way to achieve this. On my custom carrier board I have a TPM which would enhance the overall security of this encrypted storage.

Regarding container signing: I understand it focuses on integrity and authenticity, which is also interesting for me , but it’s not the same as confidentiality, which is what I’m aiming for the moment.

I’m also interested in implementing the toradex secure boot later on and would like to know whether it’s possible to integrate my TPM with it.

So, if I understand correctly, I should :

  1. Create a new partition
  2. Move the Docker data (volumes, containers, images) into it
  3. User dm-crypt via the ‘meta-toradex-security’ layer in combination with the TPM to encrypt this partition

Also, I’m not entirely sure if the way I deployed my custom Yocto image is correct — is there a preferred or recommended method for image deployment when working with encrypted partitions?

Thank you again for your help.

I see, thank you for sharing your use-case with us. It’s quite helpful feedback, I also have a better picture now of what you are trying to achieve. Especially specifying your goal is confidentiality and not integrity, which is indeed an important distinction in security.

Create a new partition
Move the Docker data (volumes, containers, images) into it
User dm-crypt via the ‘meta-toradex-security’ layer in combination with the TPM to encrypt this partition

Your proposed process here seems sensible. Though I will say we’ve never tried putting the Docker data into the encrypted partition before so the results of this would be interesting.

Also, I’m not entirely sure if the way I deployed my custom Yocto image is correct — is there a preferred or recommended method for image deployment when working with encrypted partitions?

So it depends, you need some mechanism/process to create the partition that will be encrypted. Using the deployment method you used before will not automatically create this partition. One simple way to do this is to use another mechanism found in meta-toradex-security as described here: meta-toradex-security/docs/README-encryption.md at scarthgap-7.x.y · toradex/meta-toradex-security · GitHub

This creates an additional data partition in the OS image. This additional partition can then be a target for the encryption process. Though this does mean you have to use Toradex Easy Installer to deploy the image, as this is what will create the additional partition.

Best Regards,
Jeremias

Hi ,

Thank you again for the detailed response and for the documentation links — they’re very helpful.

I’ve been going through both documents:

From what I understand, the second document is meant to help create an additional data partition, which can then be encrypted as explained in the first document.

Just to clarify:

  1. Why does the encryption documentation not mention the creation of a new partition? Does it assume that multiple partitions already exist?
  2. In my current case with a Verdin iMX8M Mini and a custom TorizonCore-based image, I only have one partition (/), which currently takes the entire space of the eMMC. How is this handled when using the method in README-data-partition.md? Does the script resize the existing rootfs and create the new partition automatically, or do I need to adjust this manually?

To illustrate my intended setup before and after changes:

before :

Partition Role Access
mmcblk0boot0 imx-boot (bootloader) -
mmcblk0p1 / (rootfs) Read-Write 3.4Go (full disk)

after :

Partition Role Access
mmcblk0boot0 imx-boot (bootloader) -
mmcblk0p1 / (rootfs) Read-only
mmcblk0p2 /data (user data) Read-write, encrypted

Eventually, the /data partition would hold Docker data (volumes, images, containers), and my goal is to encrypt only that partition, not the full rootfs.

I’v read in your documentation about secure boot that it’s possible to change rootfs from read-write to read-only which is a good practice in my opinion. I will do It after the encryption “devloppment”.

Thanks again for your support and guidance.

Best regards

Why does the encryption documentation not mention the creation of a new partition? Does it assume that multiple partitions already exist?

So the encryption process just targets the specified partition for encryption. It assumes the partition already exists somehow. Either you make this partition somehow, or you use the data-partition feature to make it, or maybe the partition gets created via removeable media (i.e USB/SD).

How is this handled when using the method in README-data-partition.md? Does the script resize the existing rootfs and create the new partition automatically, or do I need to adjust this manually?

So in your case the rootfs is on mmcblk0p1 the data-partition feature will create a new partition at the next enumeration (i.e. mmcblk0p2).

As for the size it will automatically re-size/re-adjust the available flash storage on the device during the flashing process with Toradex Easy Installer. The size for the partition is set to 512MB default. Though this is just the minimal size, the flashing process will try to optimize the size for all partitions, so the exact size will be at least 512MB but probably not exactly. For the variables that affect the data partition you can see here: meta-toradex-bsp-common.git - Toradex BSP layer, recipes common to all modules

These variables can be overridden by setting them in your local.conf file.

Best Regards,
Jeremias