I am working on an embedded Linux project that can run on multiple platforms. One uses e.MMC for storage and another NAND flash. I want to encrypt all the filesystems (mainly to protect against someone unsoldering the flash chips and putting them in a reader). I want to try and maintain a common approach across both hardware types as far as possible. One big difference between the two is the wear levelling is in the hardware for the e,MMC whereas for NAND I'll be using UBI.
For the root filesystem I am thinking of using squashfs which is protected using dm-crypt. For the NAND device I have tried this out and I can layer dm-crypt on top of ubiblock then use the device mapper to load the squashfs. This maps nicely to the e.MMC world with the only difference being that the device mapper is on a gpt partition rather than a ubiblock device.
My challenge is for other read/ write filesystems. I want to mount an overlay filesystem on top of the read-only root and a data partition. I want both of these to also be encrypted. I have been investigating how fscrypt can help me. (I believe dm-crypt won't work with ubifs).
For filesystems on the e.MMC I will be using ext4 and for NAND ubifs. The documentation says both of these support fscrypt. I've struggled a bit to find detailed documentation about how to use this with ubifs (there is a lot more for the ext4) but I think that there are some differences between how this has been implemented on each and I'd like those who know more to confirm this.
On the NAND side I have only been able to get it to work by using the fscryptctl tool (https://github.com/google/fscryptctl ) as opposed to the fuller featured fscrypt tool (https://github.com/google/fscrypt). This was following instructions I found in a patch to add fscrypt support to mkfs.ubifs here:
https://patchwork.ozlabs.org/project/linux-mtd/cover/[email protected]/
This appears to encrypt all the files on the partition using the supplied key. When I look at fscrypt on ext4 it seems here that you can't do this. The root directory cannot itself be encrypted, only sub-directories. Reading here: https://www.kernel.org/doc/html/v4.17/filesystems/fscrypt.html it says:
"Note that the ext4 filesystem does not allow the root directory to be encrypted, even if it is empty. Users who want to encrypt an entire filesystem with one key should consider using dm-crypt instead."
So this is different. It also seems that with ubifs I can't apply encryption to the subdirectories like I could in ext4. The README.md here https://github.com/google/fscryptctl gives an example using ext4. This encrypts a subdirectory called test. I don't see how to do the same thing using ubifs. Could someone help me?
I've been using the NANDSIM kernel module for testing. At the end of this post is a script for building an encrypted overlay ubifs filesystem. As you can see the mkfs.ubifs is taking the key directly and it appears to apply it to all the files on the partition. You can't then apply policies to any sub-directories as they are already encrypted.
I would like to use some of the other features that the userspace fscrypt tool provides e.g. protectors (so I don't need to use the master key directly). I can't however see any way to get the userspace fscrypt tool to setup encryption on a ubifs. The userspace fscrypt command creates a .fscrypt directory in the root of the partition to store information about policies and protectors. This seems to fit more with the ext4 implementation where the root itself isn't encrypted.
When I try to set-up an unencrypted ubifs with "fscrypt setup" I run into trouble as making a standard ubifs seems to create a v4 ubifs format version rather than the required v5. This means the "fscrypt encrypt" command fails. (Errors like this are seen in the dmesg output
[12022.576268] UBIFS error (ubi0:7 pid 6006): ubifs_enable_encryption
[ubifs]: on-flash format version 5 is needed for encryption).
Is there some way to get mkfs.ubifs to create an unencrypted v5 formatted filesystem? Or does v5 mean encrypted?
Here is my script to create an encrypted ubifs using the fscryptctl tool:
#!/bin/bash
MTD_UTILS_ROOT=../../mtd-utils
FSCRYPTCTL=../../fscryptctl/fscryptctl
MOUNTPOINT=./mnt
dd if=/dev/urandom of=overlay.keyfile count=64 bs=1 # XTS needs a 512bit key
descriptor=`$FSCRYPTCTL get_descriptor < overlay.keyfile`
$MTD_UTILS_ROOT/mkfs.ubifs --cipher AES-256-XTS --key overlay.keyfile
-m 2048 -e 129024 -c 32 -r ./overlay -o overlay.enc.img
$MTD_UTILS_ROOT/ubiupdatevol /dev/ubi0_6 overlay.enc.img
# Try it out
$FSCRYPTCTL insert_key < overlay.keyfile
key=`keyctl show | grep $descriptor | awk '{print $1}'`
mount -t ubifs /dev/ubi0_6 $MOUNTPOINT
ls $MOUNTPOINT
umount $MOUNTPOINT
keyctl unlink $key
NB I've been working with mtd-utils v2.1.2 on a 5.4 kernel.