Hi,
I am using yocto to build a custom layer on top of tdx-reference-minimal-image on an imx8mp verdin module. We also use the meta-traded-security layer.
I currently have a service that depends on a partition being mounted.
However, due to caam keys changing after the secure boot fuse is blown, I would like my “setup script” to determine when this is the case and perform initial encryption of the partition and subsequently decrypt the partition thereafter.
In addition to this, if the fuse has not been blown I have another systemd mount unit that should mount the bare partition.
Also, we are looking into u-boot hardening and dm-verity for rootfs to ensure a full chain of trust.
Due to the read-only requirements and the signatures, we can’t really have the tdx-enc-handler disabled by default and then enable it later.
I am hoping there is some way I can update the script the tdx-enc-handler uses so it checks if the secure boot fuse is blown before encrypting the partition.
Is this at all possible?
My other alternative would be to make and overlayfs with rootfs as the base and my encfs (with relevant changes for existing recipe paths) as the top writable layer.
Am I even on the right track or is there a better approach?
Hi, I’m the Toradex AI Assistant. I’m in early beta, and I would appreciate your feedback.
The Toradex Support team will follow up with you shortly!
Did you like my answer?
Hello,
To address your requirements for handling partition encryption based on the state of the secure boot fuse, you can indeed interrogate the fuse state from a Linux script. On i.MX8M platforms, such as your Verdin iMX8M Plus module, the fuse state can be read through the sysfs interface provided by the Linux kernel. Specifically, you can read the secure boot fuse state by accessing a certain file within the /sys/fuses/ directory. The exact path can vary, but it typically involves reading from a file that represents the OTP (One-Time Programmable) memory bank where the secure boot fuse is located.
Here’s a simplified approach to check the secure boot fuse state:
Identify the Fuse Location: First, identify the correct file in /sys/fuses/ that corresponds to the secure boot configuration. This might require consulting the i.MX8M Plus reference manual for the exact OTP bank and word that represents the secure boot fuse.
Read the Fuse State in Your Script: Incorporate a command in your setup script to read the value of this fuse. For example:
secure_boot_enabled=$(cat /sys/fuses/secure_boot_bank/secure_boot_word)
if [ "$secure_boot_enabled" -eq 1 ]; then
echo "Secure boot is enabled."
# Proceed with encryption
else
echo "Secure boot is not enabled."
# Handle the non-encrypted case
fi
Replace secure_boot_bank and secure_boot_word with the actual path and filename.
Regarding your approach to handling encryption and the use of tdx-enc-handler, updating the script to include a check for the secure boot fuse state before proceeding with encryption is feasible. This conditional check ensures that encryption operations are only performed when secure boot is enabled, aligning with your requirements.
For the scenario where the secure boot fuse has not been blown, your idea of using a systemd mount unit to handle the bare partition is sound. Systemd’s flexibility allows you to conditionally execute services or mount units based on various criteria, including the presence or absence of a file, which could be the output of your fuse check script.
Regarding the full chain of trust and the use of dm-verity for a read-only root filesystem, your consideration for an overlay filesystem makes sense. Using an overlayfs allows you to maintain a read-only base layer while applying changes to a writable top layer. This approach is compatible with the requirements
Please, also check if these links can help you solve your problem:
Based on the info above then, I could do the following….
tdx-enc-handler.service:
checks fuse;
if blown; performs encryption of partition if needed and then mounts the decrypted partition
if not writes file /run/insecure-boot and leaves raw partition mounted instead
I am guessing I could add a “TDX_ENC_DELAY_FUSE” variable to the recipe and populate it only for caam implementations with relevant machine overrides.
If that has a value then the script does the check.
This would be my initial thoughts given the handler script currently supports multiple backends.
I have had a look today and for some reason I don’t see any ‘/sys/fuses’ directory available.
I am wondering if I have removed a kernel config that provides this.
Is it possible to confirm and if so which config values need to be enabled to get these fuse maps?
I couldn’t find a clear response from NXP on how to accomplish this from Linux userspace.
That said we can kind of workaround this in a way. As stated you can use the fuse utility in U-Boot to read the fuse values. You could have a boot script or have it as part of the boot command where you read the value of the fuse you want and store it in an environment variable in U-Boot.
Then from Linux userspace you could use the fw-utils to read the value from this environment variable in U-Boot. Then you can proceed from there.
Also just so I understand your use-case your situation is basically like so:
In my opinion the ‘answers’ given by the AI are at best trivial and/or off topic and at worst misleading… I pretty much ignore them and wait for a real person to answer.
You should be able to read the fuse values for imx8m mini or plus at the path:
/sys/devices/platform/soc@0/30000000.bus/30350000.efuse/imx-ocotp0/nvmem
You can use hexdump to read the values. For example, to read the fuse register containing secure boot enable on imx8m mini or plus you could do:
hexdump -e ‘“0x%08x”’ -s 28 -n 4 /sys/devices/platform/soc@0/30000000.bus/30350000.efuse/imx-ocotp0/nvmem
You should be able to read the fuse values for imx8m mini or plus at the path:
/sys/devices/platform/soc@0/30000000.bus/30350000.efuse/imx-ocotp0/nvmem
That’s good to know. Thank you for sharing this information @andyha! It’s very helpful.
Brilliant, i will have to look at this tomorrow when I’m back at work but that will make life so much easier for the things i need to do.
I usually ignore the AI too, but I find if I reply to it I get a quicker response from a real person.
Also, I have a very tight deadline to deliver a product and it needs to meet certain security criteria which I was beginning to think was impossible.
Essentially i have various services that use caam keys for encryption, but apparently all the keys change once that fuse is blown to the real ones.
Now I can make the encryption conditional on the fuse.
Once I verify it and get it working I will mark the answer as a solution.
Essentially i have various services that use caam keys for encryption
Out of curiosity what else are you using CAAM keys to encrypt? It can be helpful for us to know about all the kinds of security use-cases our customers are interested in.
Hi,
The main things are user home directories which are currently configured as separate partitions.
We also have some application specific files that we will use CAAM to encrypt and decrypt as required at runtime (based on authenticated users).
The main things are user home directories which are currently configured as separate partitions.
We also have some application specific files that we will use CAAM to encrypt and decrypt as required at runtime
I see, that makes sense given the right use-case. Well thank you for sharing it’s always helpful for us to hear about our customer’s various uses-cases.
By the way let us know if you got a chance to try this fuse value interface at /sys/devices/*, and whether it works for you or not.
I can confirm there is certainly something here that looks like it could be useful.
However the example hexdump command errors for me.
Not sure how to read the values of nvmem but I am wondering if some of the values are inaccessible (possibly for security reasons).
Am digging further into this to see what I can find out.
An example of what I can see when looking at this nvmem location:
0000000 a9eb ffaf aaff 0002 ca45 e87c 3800 0b29
0000010 47d1 0002 0000 0100 007f 0000 2000 9800
0000020 0000 0000 00e6 0000 0001 0000 0000 0000
0000030 0000 0000 0000 0000 0000 0000 0000 0000
0000040 bada bada bada bada bada bada bada bada
*
0000060 0000 0000 0000 0000 0000 0000 0000 0000
*
0000080 0000 0000 0000 0000 0000 0000 0004 0000
0000090 0000 0000 0000 0000 0000 0000 0000 0000
00000a0 bada bada bada bada bada bada bada bada
*
00000c0 f672 b8ff 506f c061 f92b 55df 48d5 9552
00000d0 b347 d7ff 1239 8d8e f73a 19a6 3ef5 a09f
00000e0 0000 0000 0000 0000 0000 0000 0000 0000
00000f0 bada bada 0000 0000 0000 0000 bada bada
0000100 bada bada bada bada bada bada bada bada
*
0000250 bada bada bada bada bada bada 1118 0001
0000260 2100 0000 0000 a800 6919 b271 0561 27cb
0000270 c620 00b0 0000 0000 0000 0000 0000 0000
0000280 1926 84b3 770d 4696 0000 0000 0000 0000
0000290 0000 0000 0000 0000 0000 0000 0000 0000
*
00002d0 bada bada bada bada bada bada bada bada
*
00002f0 0801 5500 73a8 0001 201f d503 0000 0000
0000300 0000 0000 0000 0000 0000 0000 0000 0000
*
00005f0 0000 0000 0000 0000 0001 0001 5bb6 8002
0000600
My untrained observations would suggest the first block is the offset identifier and the rest are the value.
Looking at the manual the SEC_CONFIG[1] (aka SEC_BOOT) fuse is at 0x470[25].
NOTE: the block above is from a brand new unmodified verdin-imx8mp SoM.
Latest update….
So I think I have figured out how to read it.
Each line output by hexdump tool is a ‘Bank’ which in turn contains 4 ‘words’ (as per the bank mappings in the processor manuals).
The lines that read BADABADA are addresses that you cannot read from.
These are also bit swapped.
So if I do:
fuse prog -y 42 0 0x04030201
Then in the output on line 43 (0x29 I think it was):
01 02 03 04
When using:
hexdump -C -v {fuse-path}
Sorry for horrible formatting but my phone won’t let me do the code blocks.