📺B站:博主个人介绍
📘博主书籍-京东购买链接*:Yocto项目实战教程
📘加博主微信,进技术交流群:jerrydev
RK 系统安全(System-Verity / System-Encryption)原理与落地实战
关键词:Secure Boot、boot.img、Ramdisk(/init)、Device-Mapper、dm-verity、dm-crypt、luksmeta、vroot、switch_root、RPMB、security 分区
本文围绕 Rockchip Linux SDK 中“系统安全(System Security)”方案,系统讲清楚它到底保护什么、如何工作、如何在工程中配置与验证,并给出从 PC 侧打包到板端启动的完整落地路径。
本文关注点:
内核→rootfs 阶段的系统保护:通过 Ramdisk 调用 Device-Mapper,把系统分区映射成
vroot,再switch_root切换到最终系统。两条主线:
- System-Verity:完整性(防篡改,读到被改的块会 I/O error)。
- System-Encryption:保密性(系统分区为密文,离线无法解析;启动时映射成明文
vroot)。
重要定位:本文所述“系统安全”主要保护的是rootfs/system 分区承载的块数据(即根文件系统内容)。
boot.img/内核本体的保护属于Secure Boot / FIT 签名链路,它是系统安全方案能够成立的前提条件,两者分工不同但互相依赖。
1. 先把概念对齐:你到底在保护什么
在 Rockchip 文档语境中,“系统安全”并不等价于“Secure Boot”。它解决的是:
- rootfs 内容不能被静态篡改(完整性)——对应 System-Verity。
- rootfs 内容不能被离线读取/复制(保密性)——对应 System-Encryption。
它依赖一个“执行者”:
boot.img内的Kernel + Ramdisk。Ramdisk 里的
/init脚本在内核启动后第一时间运行,决定:- 是否启用 dm-verity(验签/校验);
- 是否启用 dm-crypt(解密);
- 最终把系统分区统一映射为
vroot,然后switch_root切换到真正的根文件系统。
1.1 为什么文档强调 boot.img 必须处于 Secure Boot 保护下
因为 Ramdisk 里的/init就是“系统安全的入口”。如果boot.img可被替换,攻击者可以:
- 修改
/init,直接跳过 verity/encryption,挂载原始分区; - 替换
root_hash或密钥处理逻辑; - 甚至把系统引导到攻击者准备的 rootfs。
因此:
- Secure Boot:解决“执行者可信”(boot.img 未被替换)。
- System Security(本文):解决“被保护对象可信/保密”(rootfs/system 分区)。
一句话总结:
Secure Boot 让“执行校验/解密的人”可信;System Security 让“最终被挂载的系统分区内容”可信或保密。
2. 总体架构:从 Security-System 到 vroot
系统安全方案的核心链路非常稳定,可以用一张文字化流程图记住:
eMMC/Flash ├── boot 分区:boot.img(kernel + ramdisk) ←(应由 Secure Boot 保护) └── system/rootfs 分区:Security-System ←(被保护对象) 启动: 1) kernel 启动 → 解压并挂载 ramdisk 2) ramdisk 执行 /init 3) /init 调用 device-mapper - verity:Security-System → dm-verity → /dev/mapper/vroot - encrypt:Security-System(密文) → dm-crypt → /dev/mapper/vroot 4) mount /dev/mapper/vroot 5) switch_root 切换到最终系统,释放 ramdisk 最终:用户态对 / 的读写 → /dev/mapper/vroot → device-mapper → Security-System这里有两个非常关键的“理解抓手”:
- vroot 是唯一入口:最终系统看到的根分区不是原始分区,而是
/dev/mapper/vroot。 - device-mapper 是枢纽:校验/解密都在块设备层完成,文件系统只是“挂载在 vroot 上的上层”。
3. 两条主线:System-Verity vs System-Encryption
3.1 System-Verity(dm-verity):完整性(防篡改)
目标:任何对系统分区的离线篡改都应在运行时被发现。
原理(块级完整性树):
- PC 侧对系统镜像生成 Hash Tree(文档中称 Hash-Map),并计算 Root-Hash。
- Root-Hash 作为“信任根”,放入
boot.img的 Ramdisk 中。 - 启动时,Ramdisk 使用 Root-Hash 建立 dm-verity 映射。
- 运行时读取某个 4K 块时,内核会在 dm-verity 中校验该块对应 hash;不一致则返回 I/O error。
关键点:
- verity 解决的是“是否被改过”,不解决“内容是否泄露”。
- 被篡改后通常表现为:系统读文件报错、服务异常、甚至无法继续启动。
3.2 System-Encryption(dm-crypt):保密性(防离线读取)
目标:系统分区为密文,拿到存储介质也无法解析 rootfs。
原理(块设备加密容器):
- PC 侧用 dmsetup 建立 dm-crypt 容器,把明文系统写入映射设备,输出为密文镜像。
- 启动时,Ramdisk 提供 cipher 与 key,通过 dmsetup 将密文分区映射成明文
vroot。
关键点:
- encryption 解决“内容不可见”,不天然等价于“不可篡改”。
- 量产方案中密钥不能明文放在 Ramdisk,需要结合RPMB 或 security 分区 + OP-TEE 安全存储。
3.3 两者能否同时存在
对同一份 rootfs:
- 文档默认脚本通常按
ENC_EN=true/false二选一。 - 理论上可以叠加:先 dm-crypt 解密得到
cryptroot,再对cryptroot做 dm-verity 映射得到verityroot,最终把verityroot作为vroot。
工程建议:
- 先跑通 verity 或 encryption 其中之一;
- 再考虑“叠加”方案(脚本复杂度、性能、异常处理都会提高)。
4. PC 侧打包:生成可被 Ramdisk 驱动的“保护对象”
系统安全不是只改 Ramdisk 就能生效。PC 侧必须先把系统镜像加工成 verity/encryption 需要的形态,并产出security.info供后续 Ramdisk/init配置使用。
4.1 System-Verity:对 rootfs 镜像附加 Hash-Map,并保存 Root-Hash
核心流程:
- 选择输入系统镜像(通常是
rootfs.img或 buildroot 输出的rootfs.ext2/ext4)。 - 计算
hash_offset(示例以 1MiB 对齐,并在镜像尾部预留空间)。 veritysetup format写入 Hash-Map,并输出 Root-Hash。- 生成
security.info:保存root_hash与hash_offset。
工程注意:
veritysetup format会修改镜像文件(写入 hash 区),建议对镜像副本操作。security.info是 Ramdisk 配置的输入之一,不存在就无法完成 init 配置。
4.2 System-Encryption:创建加密容器并输出密文系统镜像
核心流程:
- 读取明文系统镜像。
- 准备密钥
key.txt与 cipher 名称(如aes-cbc-plain)。 - 创建输出文件(密文镜像)并绑定 loop。
dmsetup create建立 crypt 映射。dd把明文写入/dev/mapper/<name>(写入即加密)。- 清理映射与 loop。
- 生成
security.info:保存cipher与key(开发阶段可用;量产阶段应改为安全存储)。
工程注意:
- 输出密文镜像无法直接 mount;必须通过 dmsetup 建立映射才能读出明文文件系统。
- cipher 与 key 长度必须匹配:例如 AES-256-CBC 需要 32 bytes(hex 64 字符);XTS 模式通常需要双倍 key。
5. Ramdisk 的角色:/init 做“校验/解密 + vroot 统一出口”
在 Rockchip Linux SDK 的实现中,Ramdisk 是由 Buildroot 生成的小系统,与 Kernel 一同打包进boot.img。
它在系统安全方案中的职责非常明确:
读取配置:
security.info、分区信息、工作模式(verity/encrypt)。准备内核能力:确保 device-mapper、dm-verity/dm-crypt 等内核模块或内建选项可用。
建立 vroot:
- verity:使用 Root-Hash 与 hash_offset 建立 dm-verity 映射。
- encrypt:使用 cipher 与 key 建立 dm-crypt 映射。
挂载与切根:挂载
/dev/mapper/vroot,执行switch_root。释放自身:切根后 ramdisk 不再作为根文件系统。
5.1 init.in → init:为什么需要“模板渲染”
文档中的做法是:
buildroot/board/rockchip/common/security-ramdisk-overlay/init.in作为模板。- 通过脚本
cp init.in init后,用sed把变量填充进去(ENC_EN、OFFSET、HASH、CIPHER、SECURITY_STORAGE 等)。
这样做的目的:
- 把“PC 侧产物”(
security.info)转化为“启动期可执行配置”。 - 保持同一份模板支持多种模式(verity/encrypt)。
5.2 关于SECURITY_STORAGE=RPMB/SECURITY
System-Encryption 在量产时通常要求:
- 密钥不能明文存放在 Ramdisk。
- 启动时由 Ramdisk 从某个临时介质(如 misc)取到密钥材料,转存到RPMB或security 分区,随后清理临时介质。
这是为了避免:攻击者只要读出boot.img就获得密钥。
6. 实战路径:从镜像加工到板端验证的完整步骤
本节给出一条“从 PC 到板端”的通用落地流程。你可以按自己的 SDK 结构替换路径。
说明:本流程刻意不展开 OTP 烧录等不可逆步骤;开发阶段重点先验证机制是否正确。
6.1 选择被保护对象(通常是 rootfs 分区镜像)
常见候选:
output/firmware/rootfs.img(打包输出)buildroot/output/<xxx>/images/rootfs.ext2(Buildroot 生成的 rootfs)
判断原则:
- 最终刷进 rootfs 分区的是什么镜像,就对那份镜像做 verity/encryption。
6.2 System-Verity 方案落地步骤
备份输入镜像(建议)
运行
veritysetup format生成 Root-Hash 与 hash_offset,写security.info配置 Ramdisk init(ENC_EN=false,填入 OFFSET/HASH)
重新打包 Ramdisk → 重新生成 boot.img
刷机或更新 boot/rootfs 分区
板端验证:
/dev/mapper/vroot是否存在- 根分区是否来自 vroot
- 篡改后是否出现 I/O error
6.3 System-Encryption 方案落地步骤
生成
key.txt(开发阶段可用 openssl rand;量产阶段应迁移到安全存储)PC 侧用 dmsetup 创建加密容器,输出密文
rootfs_enc.img生成
security.info(cipher/key)配置 Ramdisk init(ENC_EN=true,填入 CIPHER/SECURITY_STORAGE 等)
重新打包 Ramdisk → 重新生成 boot.img
刷机:rootfs 分区刷入密文镜像
板端验证:
- 直接挂载原始 rootfs 分区应无法解析(密文)
/dev/mapper/vroot可挂载并切根成功
7. 如何验证“真的生效”:最小检查清单
系统安全是否生效,最重要的是验证“最终根分区来自 vroot”。
7.1 运行时结构验证
在最终系统中执行:
查看根挂载来源:
mount | grep " on / "- 期望:
/来自/dev/mapper/vroot(或同等映射名)
查看 mapper 设备:
ls -l /dev/mapper- 期望存在
vroot
查看 dm 状态:
dmsetup status vroot
7.2 Verity 的行为验证(篡改触发 I/O error)
思路:
- 离线修改 rootfs 分区某个块内容。
- 再启动或在运行时访问该文件,期望出现 I/O error。
注意:
- 这属于破坏性验证,建议在测试介质上进行。
7.3 Encryption 的行为验证(密文不可直接 mount)
思路:
- 在 PC 上尝试直接挂载密文镜像,应失败。
- 用同样的 cipher/key 建立 dmsetup 映射后,才可以 mount 并看到正常目录结构。
8. 常见问题与定位方法
8.1security.info找不到
现象:source security.info: No such file or directory。
结论:
- PC 侧前置步骤未执行或路径不正确。
建议:
- 在生成脚本执行目录确认
security.info的存在与内容。 - 使用
find . -name security.info明确位置。
8.2sed报错、变量替换未生效
常见原因:
- 命令行复制时把两条
sed粘在同一行。 - 模板字段与替换字段不一致(例如模板是
ROOT_HASH=,但你替换HASH=)。
建议:
grep -n "ENC_EN\|OFFSET\|HASH\|CIPHER\|SECURITY_STORAGE" init.in init对比。
8.3 rootfs 镜像被 veritysetup 写入时 I/O error
常见原因:
- 目标镜像不可写(权限/只读/构建系统管理产物)。
- 宿主机磁盘空间不足。
- hash_offset 单位理解不一致(bytes vs sectors,具体依赖 veritysetup 版本)。
建议:
- 对镜像副本操作。
df -h检查空间。veritysetup --help查看 hash-offset 解释。
8.4 你看到 rootfs 镜像依然能被普通方式挂载,是否说明 verity 无效
不说明。
原因:
- verity 的 Hash-Map 附加在镜像尾部,不改变镜像前部的文件系统结构。
- 普通 mount 仍然会把它当作正常文件系统。
真正生效的标志:
- 运行时根分区必须来自
/dev/mapper/vroot,并且访问篡改块会 I/O error。
8.5 Yocto 能不能生成 Ramdisk:没有 Buildroot 是否无法做系统安全
不必拘泥于“Buildroot 还是 Yocto”。关键在于:
- 需要一个 initramfs/ramdisk,里面包含
/init、必要工具(dmsetup/veritysetup/luksmeta/busybox 等)以及配置文件。
因此:
- Yocto 完全可以生成 initramfs,也可以在 initramfs 中实现同样的
/init逻辑。 - Rockchip SDK 给的是 Buildroot 路线,属于“参考实现”;机制本身与发行构建系统无关。
8.6 开发阶段不烧 OTP,能不能先做系统安全
可以做“功能层面”的系统安全验证:
- verity/encryption 的链路能跑通、
vroot能建立、switch_root能切换。
但要明确边界:
- 未启用 Secure Boot 时,攻击者可替换 boot.img,从而绕过这套机制。
工程建议:
- 开发阶段先验证机制、验证脚本与镜像流程。
- 量产阶段再把 Secure Boot(含 boot.img 保护)纳入闭环。
9. 最佳实践:如何把“可运行”提升到“可量产”
9.1 把链路闭环:Secure Boot + System Security
建议的闭环目标:
- Secure Boot 确保 boot.img 不可被替换。
- verity/encryption 确保 rootfs/system 不可被篡改或不可被离线解析。
9.2 密钥管理:从开发明文到量产安全存储
开发阶段为了验证链路,常见做法是:
security.info里明文保存 cipher/key。
量产阶段应演进为:
- 密钥或密钥材料存入 RPMB 或 security 分区。
- Ramdisk 通过 OP-TEE 安全接口获取或解封密钥。
9.3 只读根文件系统与更新策略
verity 更适合“只读根系统”(例如 squashfs/erofs + verity)
- 更新时整体替换镜像,并重新生成 hash。
encryption 更关注“保密”,更新时需要考虑:
- 密钥轮换策略(是否每版本不同 key)。
- A/B 或 OTA 流程中密钥与元数据如何同步。
10. 总结:一张表记住核心差异
| 维度 | System-Verity (dm-verity) | System-Encryption (dm-crypt) |
|---|---|---|
| 主要目标 | 完整性(防篡改) | 保密性(防离线读取) |
| PC 侧处理 | 生成 hash tree + root_hash(Hash-Map 可附加镜像尾部) | 创建加密容器并写入明文,输出密文镜像 |
| Ramdisk 输入 | root_hash、hash_offset | cipher、key(量产应来自安全存储) |
| 启动时动作 | 建立 dm-verity 映射 →vroot | 建立 dm-crypt 映射 →vroot |
| 篡改表现 | 访问到被改块 → I/O error | 不一定立刻报错(取决于是否叠加完整性机制) |
| 是否能直接 mount 原镜像 | 可以(镜像仍是正常 FS) | 不可以(密文不可解析) |
| 量产关键点 | root_hash 必须可信(依赖 boot.img 可信) | 密钥必须安全存储(RPMB/security/OP-TEE) |
11. 附录:建议的“最小验证步骤”模板
11.1 Verity 的最小验证
启动后:
mount | grep " on / "→/dev/mapper/vrootdmsetup status vroot
篡改验证:
- 离线修改 rootfs 分区块 → 启动/访问文件 → I/O error
11.2 Encryption 的最小验证
PC 上:
- 直接 mount 密文镜像失败
- 用 dmsetup 映射后 mount 成功
启动后:
/dev/mapper/vroot存在/挂载来自 vroot
结语
Rockchip 的“系统安全”方案本质是:用 Ramdisk 把系统分区统一封装成 vroot,然后以 device-mapper 作为安全边界的执行层。理解了“谁是执行者(boot.img)”与“谁是被保护对象(rootfs/system)”,并掌握 PC 侧镜像加工 + Ramdisk/init配置 + 板端验证三件事,系统安全就能在工程中稳定落地。
📺B站:博主个人介绍
📘博主书籍-京东购买链接*:Yocto项目实战教程
📘加博主微信,进技术交流群:jerrydev