基于imx6ull+Yocto:如何用FitImage签名验证根文件系统?
基于Yocto的imx6ull根文件系统dm-verity验证实现方案
先明确核心问题:必须用initramfs
因为内核启动时,根文件系统还未挂载,无法直接读取哈希树和签名信息来完成dm-verity校验,必须依赖initramfs在根文件系统挂载前完成dm-verity设备的创建与校验逻辑。
1. Yocto环境配置(开启dm-verity相关支持)
在项目的local.conf中添加以下配置:
# 安装dm-verity用户空间工具 IMAGE_INSTALL:append = " device-mapper dm-verity" # 内核开启dm-verity及签名验证支持 KERNEL_FEATURES:append = " features/device-mapper/verity.scc" # 追加哈希算法内核配置(以SHA256为例) KERNEL_CONFIG_FRAGMENTS += "${WORKDIR}/verity-config.cfg"
在verity-config.cfg文件中补充内核开关:
CONFIG_CRYPTO_SHA256=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y # 开启根哈希的签名验证
2. 生成根文件系统的哈希树与根哈希签名
步骤1:构建根文件系统镜像
先通过Yocto构建出根文件系统镜像(比如rootfs.ext4),确保镜像为只读格式(后续挂载时设为ro)。
步骤2:生成dm-verity哈希树与根哈希
用veritysetup工具生成哈希树并导出根哈希:
# 生成哈希树文件rootfs_verity.hash veritysetup format rootfs.ext4 rootfs_verity.hash # 提取根哈希到文件 veritysetup verify rootfs.ext4 rootfs_verity.hash | grep "Root hash" | awk '{print $3}' > rootfs_roothash.txt
步骤3:签名根哈希
复用你之前用于FitImage签名的RSA密钥对,对根哈希进行签名:
openssl dgst -sha256 -sign private_key.pem -out rootfs_roothash.sig rootfs_roothash.txt
3. 将哈希树、签名整合到FitImage
修改FitImage的DTS配置文件,新增根文件系统哈希树、签名相关节点,并在启动参数中传递校验信息:
/ { images { rootfs { description = "Root Filesystem"; data = /incbin/("rootfs.ext4"); type = "filesystem"; arch = "arm"; os = "linux"; compression = "none"; hash-1 { algo = "sha256"; }; }; rootfs_verity_hash { description = "RootFS Verity Hash Tree"; data = /incbin/("rootfs_verity.hash"); type = "verity-hash"; arch = "arm"; os = "linux"; compression = "none"; hash-1 { algo = "sha256"; }; # 对哈希树本身做签名(复用FitImage的签名密钥) signature-1 { algo = "sha256,rsa2048"; key-name-hint = "your-signing-key-name"; signer = "your-signer-id"; }; }; }; configurations { default = "config-1"; config-1 { kernel = "kernel"; rootfs = "rootfs"; verity-hash = "rootfs_verity_hash"; # 传递dm-verity校验参数给内核 bootargs = "console=ttymxc0,115200 root=/dev/mapper/rootfs ro verity.rootdev=/dev/mmcblk1p2 verity.roothash=$(cat rootfs_roothash.txt) verity.signature=$(cat rootfs_roothash.sig | base64 -w0)"; }; }; };
注:
/dev/mmcblk1p2是根文件系统所在分区,需根据你的硬件实际分区调整;签名内容用base64编码避免命令行转义问题。
4. 配置initramfs完成dm-verity初始化
步骤1:Yocto启用initramfs
在local.conf中添加:
INITRAMFS_IMAGE = "core-image-minimal-initramfs" INITRAMFS_IMAGE_BUNDLE = "1"
步骤2:编写initramfs初始化脚本
在自定义meta层中添加init脚本(比如meta-custom/recipes-core/initramfsscripts/files/init),内容如下:
#!/bin/sh # 挂载基础文件系统 mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t tmpfs tmpfs /tmp # 从内核cmdline提取参数 ROOTDEV=$(cat /proc/cmdline | awk -F 'verity.rootdev=' '{print $2}' | awk '{print $1}') ROOTHASH=$(cat /proc/cmdline | awk -F 'verity.roothash=' '{print $2}' | awk '{print $1}') SIG=$(cat /proc/cmdline | awk -F 'verity.signature=' '{print $2}' | awk '{print $1}' | base64 -d) # 创建临时文件存储签名 echo "$SIG" > /tmp/roothash.sig # 初始化dm-verity设备 veritysetup create rootfs $ROOTDEV /dev/mmcblk1p3 --root-hash $ROOTHASH --signature /tmp/roothash.sig # 挂载dm-verity设备作为根文件系统 mount /dev/mapper/rootfs /rootmnt # 切换根文件系统 pivot_root /rootmnt /rootmnt/initramfs exec /sbin/init
注:
/dev/mmcblk1p3是哈希树镜像所在分区,若把哈希树打包进initramfs,可改用loop设备挂载。
5. 验证测试
- 用Yocto构建完整的签名FitImage,烧写到imx6ull的存储设备
- 启动设备,查看内核日志,确认
dm-verity: verified OK的输出 - 尝试修改根文件系统分区的内容,重启后会触发dm-verity校验失败,系统无法正常启动
内容的提问来源于stack exchange,提问作者cherry411
相关产品推荐
相关产品推荐

