Device Mapper User Guide


Device Mapper provides a mapping framework from logical devices to physical devices for the Linux kernel, through which users can customize resource management strategies.

Device Mapper has Device Mapper Verity and Device Mapper Crypt

  1. DM-Verity (Device Mapper Verity) and DM-Crypt (Device Mapper Crypt) are two different device mapper modules in the Linux kernel, which are used to provide different functions.

  2. DM-Crypt (Device Mapping Encryption): DM-Crypt is used to encrypt block devices. It works by creating a cryptographic mapping on a block device. The cryptographic mapping stores data encrypted on the underlying device and decrypts it when the data is read. DM-Crypt uses various encryption algorithms and ciphers to protect the confidentiality of data. DM-Crypt can be used to protect sensitive data on storage devices such as hard drives, partitions, or files. It can be used to create encrypted file systems or encrypted storage volumes to ensure the security of data during storage and transmission.

1. veritysetup and cryptsetup

veritysetup and cryptsetup are command-line tools used to configure and manage device integrity verification (dm-verity) and block device encryption (dm-crypt) in Linux systems.

veritysetup: is a tool for configuring and managing dm-verity (device integrity verification). dm-verity is a feature provided by the Linux kernel that can be used to verify the integrity of data on block devices. The veritysetup tool can be used to create and manage dm-verity volumes, including creating root hashes and verifying data blocks.

cryptsetup: is a tool for configuring and managing dm-crypt (block device encryption). dm-crypt is a function provided by the Linux kernel for data encryption at the block device level. The cryptsetup tool can be used to create and manage encrypted volumes, including creating encrypted volumes, setting keys, opening and closing encrypted volumes, and performing other operations related to block device encryption.

If you don't have the above two apps, please contact FAE to obtain them, or compile and generate them yourself.

2. Device Mapper Verity

dm-verity is a target device type under the Device mapper architecture. It is a virtual block device that is specifically used for file system verification. When fs is mounted, it directly specifies the dm-verity device, that is, the device that fs directly interacts with is dm-verity. dm-verity calls the real block driver to read the corresponding block, and calculates the hash value and compares it with the corresponding hash value in the hash-tree. If they are equal, it means that the block has not been tampered with, and the block data is returned to fs. If they are not equal, it means that the block has been tampered with and the system halts.

Dm-verity stipulates that there can only be two target devices, one is the data device (Data Device) and the other is the hash device (Hash Device)

There is a one-to-one relationship between the mapped device and the target device. The read operation on the mapped device is mapped to the read operation on the target device. In the target device, dm-verity maps the read operation to the read operation of the data device.

However, at the end of the read operation, dm-verity adds an additional verification operation to calculate a hash value for the read data and compare this hash value with the value stored in the hash device. If they are different, the read operation is marked as an error.

Assuming that the size of each block in the data device and the hash device is 4KB, and assuming that the hash algorithm SHA256 is used, that is, the hash value of each block of data is 32B (256 bits), then each block (4KB) in the hash device stores 4096/32=128 hash values. Therefore, in layer0, one block of the hash device corresponds to 128 blocks of the data device.

When reading data, dm-verity also needs to prevent the hash value stored in the hash device from being tampered with. Therefore, layer1 is added, and each block of data in layer1 corresponds to 128 blocks of layer0.

The data in layer1 is the hash value calculated for the data in layer0 (the data in the hash device and the data device). If there is only one piece in layer1, then stop there, otherwise continue to increase the layer until layer_n has only one piece. Finally, the hash value is calculated for layer n again, and this hash value is called the root hash. This root hash can reflect the changes in the data device and the hash device. By verifying the root hash, you can check whether the data has been tampered with.

dm-verify supports most file systems. As long as the file system is on a block device, dm-verify can be used.

2.1 < span id = jump1 > kernel config

  1. DM_verity related config

  1. SSTAR AES driver configuration

2.2 Manually test dm-verity

Veritysetup lib library path declaration

export LD_LIBRARY_PATH=/xxx/yyy/lib:$LD_LIBRARY_PATH

Test the following command. If there is no error, it means that dm_verity functions normally.

  1. Format the hash device and obtain the root hash value

./veritysetup format /dev/mmcblk0p1 /dev/mmcblk0p2 --data-block-size=512 --hash-block-size=512 --debug

  1. Activate the verity device

./veritysetup create /dev/mmcblk0p1 /dev/mmcblk0p2 --debug

or:

./veritysetup open /dev/mmcblk0p1 /dev/mmcblk0p2 --debug

  1. Read:

dd if=/dev/mapper/ < name > of=test.bin bs=16 count=1

2.3 Implementing dm-verity on the same partition

2.3.1 Generate files with hash devices

The PC generates a rootfs.sqfs with a hash device. The location of the hash device is determined by the value of --data-block-size and needs to be changed according to the actual rootfs.sqfs.

The new rootfs.sqfs will have hash device information at the end. Be sure to back up the old rootfs to prevent parameter errors from damaging the data device.

2.3.2 rootfs partition size

Check whether the rootfs patition size is greater than or equal to the newly generated rootfs.sqfs size. If it is less, you need to manually modify the patition to increase the length of the rootfs. The checking process is as follows:

The modified size must meet the requirements, update the newly generated rootfs.sqfs to the partition, (network update cmd in uboot: estar scripts/[[rootfs.es)

2.3.3 Modify bootargs

Original bootargs: ubi.mtd=ubia,2048 root=/dev/mtdblock5 rootfstype=squashfs ro init=/linuxrc LX_MEM=0x1000000000,0x40000000 mma_heap=mma_heap_name0,miu=0,sz=0x10000000 mma_memblock_remove=1 cma=2M mm a_heap=mma_heap_fb,miu=0,sz=0x1CF0000 mmap_reserved=fb,miu=0,sz=0x800000,max_start_off=0x3f600000,max_end_off=0x3fe00000 mtdparts=nand0:1792k@1280k(BOOT),1792k(BOOT_BAK),256k(ENV),5m(KERNEL),5m(RECOVERY),6m(rootfs),768k(vendor_storage),1m(MISC),1m(DM-V),106752k(ubia) nohz=off

New bootargs: ubi.mtd=ubia,2048 mtdparts=nand0:1792k@1280k(BOOT),1792k(BOOT_BAK),256k(ENV),5m(KERNEL),5m(RECOVERY),6m(rootfs),768k(vendor_storage),1m( MISC),1m(DM-V),106752k(ubia) console=ttyS0,115200 root=/dev/dm-0 dm-mod.create="dm-verity,,,ro,0 7720 verity 1 /dev /mtdblock5 /dev/mtdblock5 1024 4096 3860 966 sha256 da0c74d6a90ee7aaacc120e3a96a70c68b93ec792549263e25a4b7512c707e44 39745c09881ad80ad6c55da863b06f2f6f16dedc753fde8d073285ca652e275e" LX_ MEM=0x1000000000,0x40000000 mma_heap=mma_heap_name0,miu=0,sz=0x10000000 mma_memblock_remove=1 cma=2M mma_heap=mma_heap_fb,miu=0,sz=0x1CF0000 mmap_reserved=fb,miu=0,sz=0x800000,max_start_off=0x3f600000,max_end_off=0x3fe00000 nohz=off

Note that mtdparts needs to be placed before dm-0. If it is placed after dm-0, the node has not been generated when verifying dm-verity, resulting in an error.

Parameter explanation:

dm-mod.create=,,,,

[,
+][;,,,,
[,
+]+]

Parameter name Value set in command line Remarks
name dm-verity Customizable
uuid None Optional, see 5.1 Generate files and burn them, uuid in the screenshot
minor none none
flags ro ro=read only rw=read and write
start_sector 0 From which block does rootfs.sqfs start calculating hash
num_sectors 7720 refers to the number of blocks calculated by rootfs.sqfs. The original rootfs length is 3952640/512=7720. The length of sectors is fixed to 512.
target_type verity verity = 验证digest link: https://www.kernel.org/doc/html/next/admin-guide/device-mapper/verity.html
version 1 版本号,当前有0 和1。

This is the type of the on-disk hash format.
This is the type of the on-disk hash format.br>0 is the original format used in the Chromium OS.
The salt is appended when hashing, digests are stored continuously and the rest of the block is padded with zeroes.
1 is the current format that should be used for new devices.
The salt is prepended when hashing and each digest is padded with zeroes to the power of two.
dev /dev/mtdblock5 data device 的节点
hash_dev /dev/mtdblock5 hash device 的节点
data_block_size 1024 data block 设置的长度,固定为512的倍数
hash_block_size 4096 The length of the hash block setting, fixed to a multiple of 512
num_data_blocks 3860 = actual file length/data_block_size = 3952640/1024=3860
hash_start_block 966 The current hash is inserted at the end of rootfs, so =3952640/4096 = 965, this is the first block of hash, the first bolck is the hash header, so the real hash block needs +1
algorithm sha256 Which hash algorithm to use
digest da0c74d6a90ee7aaacc120e3a96a70c68b93ec792549263e25a4b7512c707e44 See 5.1 Generate and burn files, the key information in the screenshot is root hash
salt 39745c09881ad80ad6c55da863b06f2f6f16dedc753fde8d073285ca652e275e See 5.1 Generate and burn files, key information in the screenshot

2.3.4 Restart test

If kernel/rootfs.sqfs has been updated and bootargs has been set correctly, reboot. If everything goes well, the kernel will be entered normally, as shown below.

2.4 Implementing dm-verity in different partitions

2.4.1 Adding a partition

2.4.2 Execution on PC

veritysetup --data-block-size=1024 format rootfs.sqfs dm_v.bin //rootfs.sqfs is the original binary

2.4.3 Update dm_v.bin to dm_v partition – estar scripts/[[dmv.es

2.4.4 Modify bootargs

ubi.mtd=ubia,2048 mtdparts=nand0:1792k@1280k(BOOT),1792k(BOOT_BAK),256k(ENV),5m(KERNEL),5m(RECOVERY),6m(rootfs),768k(vendor_storage),1m(MISC),1m(DM-V),106752k(ub ia) console=ttyS0,115200 root=/dev/dm-0 dm-mod.create="dm-verity,,,ro,0 7720 verity 1 /dev/mtdblock5 /dev/mtdblock8 1024 4096 3860 1 sha256 da0c74d6a90ee7aaacc120e3a96a70c68b93ec792549263e25a4b7512c707e44 39745c09881ad80ad6c55da863b06f2f6f16dedc753fde8d073285ca652e275e" LX_ MEM=0x1000000000,0x40000000 mma_heap=mma_heap_name0,miu=0,sz bootcmd=dcache on; loados nand 0x23000000 KERNEL by_header; bootm 0x23000000; dcache on; loados nand 0x23000000 RECOVERY by_header; bootm 0x23000000;

2.4.5 Restart

Restart verification, if successful, enter the kernel normally

2.5 Automatic signature script deployment dm-verity

2.5.1 dm-verity packaging method and signature verification process

Currently, there are two ways to package the append data of dm-verity, namely packaging it in the middle of the rootfs partition (rootfs_middle) or storing it in the misc partition (misc_partition).

The distribution of rootfs partition in rootfs_middle mode is as follows:

During the verification of append data, because the complete rootfs is not needed, loading the complete rootfs will take extra time. If the rootfs magic is not found in the rootfs addr, 512 bytes will be loaded from the pattern, the rootfs size in the header will be read, the size length will be skipped to load the append data, and then the append data signature verification process will be performed and the bootcmd will be rebuilt. The purpose of this step is to ensure the credibility of data such as roothash.

In addition, the distribution in misc_partition mode is as follows:

The append data will be stored in the misc partition in the form of files. The distribution of append data is the same in both modes. In the misc_partition mode, the Uboot stage will read directly according to the file name.

2.5.2 rootfs dm-verity function configuration

  1. Modify kernel config to support dm-verity. For details, refer to 2.1 kernel config .

  2. Go to project/image/config/general and add BOOTCMD_ENV to generate automatic signature verification instructions.

In the Uboot stage, environment variables will be set to verify the rootfs in dm-verity mode. The principle is to verify the signature of Binary through the sigauth_fs command. BOOTCMD parameter explanation:

sigauth_fs ;

EX:

sigauth_fs rootfs mid 0x21000000

2.5.3 dm-verity automatic signature script

rootfs supports automatic signing in dm-verity mode, and will automatically generate a signed Image. Its automatic signing supports two methods, namely the full-process automatic generation method and the rootfs separate generation method.

2.5.3.1 dm-verity full process automatic generation

The full process automatic generation method under dm-verity relies on makefile. The actual operation steps are as follows:

  1. Enter the project directory, make xxx_defconfig; make clean -j32; make image-nocheck -j32;

  2. Go to project/image/security_boot_tools/ and modify the dm_verity.config file.

Parameter description in the dm_verity.config file (whether to use dm-verity to verify rootfs depends on this file):

Name Description
rootfs_dm_verity Choose whether to open the dm-verify process. When rootfs_dm_verity=enable, it means it is on. At this time, rootfs does not go through the secure boot process.
rootfs_UUID Automatically filled with the UUID of the hash device, empty if special_cmd contains "--debug --no-superblock"
rootfs_Start_sector indicates the starting sector of rootfs. According to the rootfs partition, rootfs is usually placed in the first block of the partition, i.e. 0
rootfs_Num_sectors Automatically filled, indicating the number of rootfs sectors, each sector contains 512 bytes
rootfs_Data_block_size Automatically filled, indicating the rootfs data block size, the default is 4kb, fixed to a multiple of 512
rootfs_Hash_block_size Automatically filled, indicating the rootfs hash block size, the default is 4kb, fixed to a multiple of 512
rootfs_Data_blocks Automatically filled, indicating the number of rootfs data blocks
rootfs_Hash_start_block Automatically filled, indicating the rootfs hash device start data block
rootfs_Hash_algorithm Automatically filled, hash algorithm type, sha256 is used by default
rootfs_Salt Automatically filled, hashed Salt value
rootfs_Root_hash Automatically fill in the root hash value. When the value is empty, the veritysetup format action will be repeated. If it is not empty, the action will be skipped.
**(Note: If you want to re-perform the veritysetup operation, such as modifying the hash device or changing the rootfs size, be sure to delete the root hash value and then compile!)**

Currently, the packaging method of dm-verity's append data can be modified in project/image/security_boot_tools/Makefile by modifying the ROOTFS_PACKET_TYPE keyword (optional misc_partition/rootfs_middle):

After all modifications are completed, in project/image/security_boot_tools/, run make clean;make; to generate the image_secure directory, which contains all the Image files in the boot process (the Images in the directory have been signed).

2.5.3.2 dm-verity rootfs generated separately

The separate generation of rootfs under dm-verity relies on sh scripts. The actual operation steps are as follows:

  1. Enter the project directory, make xxx_defconfig; make clean -j32; make image-nocheck -j32;

  2. Go to the project/image/security_boot_tools/tools path and execute commands through the auto_generate_dmverity.sh script. Explanation of the command execution:

./auto_generate_dmverity.sh [origin rootfs binary] [private key]

EX:

./auto_generate_dmverity.sh ../../output/images/rootfs.sqfs ../rsa2048/private-image.pem rootfs.sqfs

Finally, you can get the signed rootfs image:

2.5.4 Burn

Burn the image file. If everything goes well, enter the kernel normally.

3. Device Mapper crypt

Dm-crypt is a transparent block device encryption subsystem in the Linux kernel 2.6 and later. It is part of the device mapper (dm) infrastructure and uses encryption routines from the kernel Crypto API. dm-crypt is implemented as a device mapper target and can be stacked on top of other device mapper transformations. Thus, it can encrypt entire disks (including removable media), partitions, software RAID volumes, logical volumes, and files. Device Mapper crypt uses the LUKS standard for hard disk encryption.

LUKS (Linux Unified Key Setup) is a standard for Linux hard disk encryption. By providing a standard disk format, it not only promotes compatibility between distributions, but also provides secure management of multiple user passwords. Compared with existing solutions, LUKS stores all necessary setup information in the partition information header, allowing users to seamlessly transfer or migrate their data. That is, LUKS is a disk format

3.1 luks format

AES-CBC-ESSIV: Luks header screenshot of SHA256 encryption

Payload-offset is the location where the encrypted plaintext data is stored. The figure shows 0x800. Note that payload-offset is in units of 512 bytes, so the location where the encrypted plaintext data is stored is 0x800*0x200.

3.2 kernel config

3.2.2 SSTAR AES driver configuration

3.2.3 Partitioning

Create a new partition to simulate the crypto scenario. Select one of the following:

  1. SD card partition

  2. nand partition

3.3 cryptsetup implements dm-crypt

The following takes aes-cbc-essiv:sha256 as an example.

3.3.1 Cryptsetup lib library path declaration

export LD_LIBRARY_PATH=/xxx/yyy/lib:$LD_LIBRARY_PATH

3.3.2 Create LUKS1 disk format - This step can be done on L3, and can be done on the demo board during testing.

SD card (ARM demo board):

/mnt/dm_test/cryptsetup/v2.4.1/sbin/cryptsetup -v -c aes-cbc-ess iv:sha256 --key-size 128 luksFormat --type luks1 /dev/mmcblk0p1 --debug

nand(PC):

cryptsetup -v -c aes-cbc-essiv:sha256 --key-size 128 luksFormat --type luks1 dmcrypt.bin --debug

If there is no error, the command is successful. As shown in the following figure (partial):

3.3.3 File key for decryption (optional)

Add keyfile to luks key-slot

  1. Generate keyfile

dd if=/dev/random of=/customer/keyfile bs=1024 count=4

  1. Add leyfile to luks key-slot

cryptsetup luksAddKey /dev/mmcblk0p1 /customer/keyfile

  1. Specify key for decryption

cryptsetup -d /customer/keyfile -s 128 -c aes-cbc-essiv:sha256 create luks /dev/mmcblk0p1

The keyfile needs to be kept strictly confidential. The following are only examples of possible storage locations. Users need to choose an appropriate storage location based on actual scenarios.

  1. Generally, it is placed in the root directory, /etc/directory, and you need to ensure that the file permissions are set correctly (such as root access only)

  2. In the USB flash drive, it is necessary to meet the customer's scenario.

3.3.4 Mapping Luks Volume

This operation requires the password entered when creating:

SD: /mnt/dm_test/cryptsetup/v2.4.1/sbin/cryptsetup luksOpen /dev/mmcblk0p1 luks

Nand: /mnt/dm_test/cryptsetup/v2.4.1/sbin/cryptsetup luksOpen /dev/mtdblock8 luks

3.3.5 Creating a file system

Create a vfat file system on the Luks disk. This step is only required for the first time.

mkfs.vfat /dev/mapper/luks

3.3.6 Mounting the file system

mount -t vfat /dev/mapper/luks /tmp

At this point, you can read and write data normally in the tmp directory

The written file will be encrypted with CBC and written to SD/Nand. When reading data, it will be decrypted with CBC and then displayed. The SD card sector number is encrypted with ECB and used as the IV value used by CBC.

  1. Test the basic encryption model

cryptsetup benchmark

  1. Specify the test encryption model

cryptsetup benchmark --cipher aes-cbc

  1. Format the disk into Luks and specify the encryption method

aes-xts-plain64:

cryptsetup -v -c aes-xts-plain64 --key-size 512 --hash sha512 luksFormat --type luks1 /dev/mmcblk0p1

aes-cbc-essiv:sha256:

cryptsetup -v -c aes-cbc-essiv:sha256 --key-size 128 luksFormat --type luks1 /dev/mmcblk0p1

  1. Check luks status:

cryptsetup -v status luks

  1. View luks information:

cryptsetup luksDump /dev/mmcblk0p1

  1. Test whether the volume is luks:

cryptsetup -v isLuks /dev/mmcblk0p1

  1. Add a password

cryptsetup luksAddKey --key-slot 7 /dev/mmcblk0p1 keyfile

  1. Back up the luks header

cryptsetup luksHeaderBackup /dev/mmcblk0p1 --header-backup-file /tmp/header.bin

  1. Restore luks header

cryptsetup luksHeaderRestore /dev/mmcblk0p1 --header-backup-file /mnt/header.bin

  1. Overwrite luks header

head -c /dev/zero > /dev/mmcblk0p1

  1. Turn off mapping

cryptsetup close /dev/mmcblk0p1