news 2026/3/27 1:30:35

KeyBox 深度解析与实战:Rockchip 系统加密的密钥保险箱

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
KeyBox 深度解析与实战:Rockchip 系统加密的密钥保险箱

📺B站:博主个人介绍

📘博主书籍-京东购买链接*:Yocto项目实战教程

📘加博主微信,进技术交流群jerrydev


KeyBox 深度解析与实战:Rockchip 系统加密的密钥保险箱

目标:把 KeyBox 的“用途、机制、代码细节、在 System-Encryption 中的位置、不同平台差异”一次讲清楚。读完后,你应该能回答三件事:

  1. KeyBox 存的到底是什么 key

  2. 为什么它必须放在 OP-TEE 里存,并且要在 Ramdisk 里读

  3. 换成别的平台或别的 SoC 时,哪些能力是“概念通用”,哪些是“实现不通用”


1. 先把场景讲透

在“系统加密”这类方案里,真正棘手的不是 dm-crypt 或 dmsetup 本身,而是密钥放哪里、谁能拿到、什么时候拿到

典型矛盾是:

  • 系统加密要在早期启动阶段解锁(挂载 rootfs 前),否则系统根本起不来。

  • 早期启动通常发生在Ramdisk/initramfs,这部分代码与环境越小越好,但又必须完成解密。

  • 如果把密钥放在普通文件系统(REE)里:

    • 密钥可能被直接读取、复制、离线分析。
    • 密钥文件被回滚或替换,会影响加密系统的可信性。

因此,行业通用的设计方向是:

  • 密钥长期保存放到可信执行环境(TEE)或专用安全硬件里。
  • 密钥短暂使用发生在早期启动阶段,并且严格控制暴露范围与生命周期。

在 Rockchip 的 Linux Secure Boot / System-Encryption 方案中,KeyBox 就是为了解决这件事:

KeyBox = “系统加密密钥的安全落盘 + 启动期取用”的示例实现(CA + TA)。

它的定位不是“算法库”,也不是“加密框架”,而是:

  • 一个密钥保险箱服务(KeyBox)
  • 服务背后使用OP-TEE Secure Storage(RPMB 或 Security 分区或 REE 文件系统后端)
  • 服务前端通过CA/TA接口给 Ramdisk 的解密流程提供密钥

2. KeyBox 到底存的是什么

从你提供的源码可以直接确定:

  • KeyBox 在 TA 中持久化保存的对象 ID 是:"enc_key"
  • CA 默认读写的数据长度是:KEY_SIZE = 32字节

也就是说,KeyBox 这个示例主要管理一把32 字节对称密钥材料(256-bit)。

这把 key 在“系统加密”里通常有两种用法:

  1. 直接作为 dm-crypt/LUKS 的解锁 key(主密钥或口令材料)
  2. 作为 master key 的原材料,再派生出多个子密钥(例如 rootfs、userdata、model 分区各用一把)

注意:KeyBox 示例只展示了“安全存取”,不负责规划“派生体系”。如果你的产品有多分区、多用途密钥需求,通常需要重构:引入 key-id、版本、用途、派生策略。


3. KeyBox 的整体架构

KeyBox 由两部分组成:

  • CA(Client Application):运行在 Linux 用户空间(REE)
  • TA(Trusted Application):运行在 OP-TEE 安全世界(TEE)

它们通过 GlobalPlatform TEE Client API(TEEC_*)通信。

下面是一张“读者友好”的总览图:

┌─────────────────────────────────────┐ │ Boot 流程 │ └─────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ Ramdisk /init 早期启动环境 │ │ │ │ 1) 设置 SECURITY_STORAGE=RPMB 或 SECURITY │ │ 2) 运行 keybox_app(CA) │ │ 3) keybox_app 通过 /dev/tee* 调用 TA │ │ 4) TA 从安全存储读取 enc_key │ │ 5) keybox_app 将 key 输出为 /tmp/syspw(hex) │ │ 6) 解密脚本用 dmsetup/dm-crypt 等完成解锁 │ │ 7) switch_root 进入真实系统 │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ OP-TEE Secure Storage │ │ - RPMB:eMMC 受保护分区 │ │ - Security 分区:用于无 RPMB 的替代方案 │ │ - REE FS:/metadata/tee 或 /data/vendor/tee 等目录 │ │ enc_key 以持久化对象方式保存 │ └──────────────────────────────────────────────────────────────┘

关键点:

  • KeyBox 本质是“把 enc_key 变成一个 TA 持久化对象”
  • CA 只是“搬运工”,TA 才是“保险箱”。

4. 关键概念速查

为了读懂 KeyBox,你只需要掌握这些概念(按重要性排序):

概念你需要记住的结论和 KeyBox 的关系
OP-TEETrustZone 上的 TEE 实现,支持 TA 与安全存储KeyBox 的 TA 跑在这里
CA/TACA 在 REE,TA 在 TEE,通过 TEEC 调用KeyBox 由 CA+TA 组成
Secure StorageTA 可把数据加密后持久化保存enc_key 的落盘位置
RPMBeMMC 的受保护区域,通常安全性更强KeyBox 可把 enc_key 存到 RPMB
Security 分区无 RPMB 场景下的替代安全分区KeyBox 也能使用它
REE FS 后端由 tee-supplicant 在普通文件系统落盘KeyBox 代码里映射为 TEE_STORAGE_PRIVATE_REE
Ramdisk早期启动环境,负责解密/验签KeyBox “读 key”主要在这里发生

5. 读懂接口:UUID 与四个命令

ta_keybox.h定义了这套 TA 的标识与命令号:

  • TA UUID:8c6cf810-685d-4654-ae71-8031beee467e

  • 命令:

    • TA_KEY_READ= 1
    • TA_KEY_WRITE= 2
    • TA_KEY_RNG= 3
    • TA_KEY_VER= 4

你可以把它理解为:

  • READ/WRITE:真正的“保险箱读写”
  • RNG/VER:一个简化的“握手校验”流程

下面表格把 CA 与 TA 的参数类型也对应起来:

命令CA 调用方式TA 期望参数作用
TA_KEY_RNG申请共享内存输出MEMREF_OUTPUTTA 返回随机数,同时在 TA 内部计算 g_hash
TA_KEY_VERVALUE_INPUTVALUE_INPUTCA 回传 hash,TA 校验后置位 g_ver
TA_KEY_READMEMREF_OUTPUT + storage typeMEMREF_OUTPUT + VALUE_INPUT读取 enc_key 输出到共享内存
TA_KEY_WRITETEMP_INPUT + storage typeMEMREF_INPUT + VALUE_INPUT写入 enc_key 到安全存储

这个设计的逻辑是:TA_KEY_READ 默认要求先通过 RNG/VER,否则会走“返回随机数”的分支。


6. TA 侧实现详解

TA 源码keybox.c是理解 KeyBox 的核心,因为真正的“安全存储”都在这里发生。

6.1 持久化对象的名字与句柄

TA 里固定了对象 ID:

  • uint8_t id[] = "enc_key";

这意味着它在 secure storage 中保存的是一个名为 enc_key 的对象。

写入时通过TA_TouchtHandle()

  • TEE_OpenPersistentObject()
  • 失败则TEE_CreatePersistentObject()

这是一种典型的“存在则打开,不存在则创建”的逻辑。

6.2 存储后端由 CA 传入

TA 并不硬编码使用 RPMB 还是 Security,而是用params[1].value.a作为 storage type。

CA 侧通过环境变量决定:

  • SECURITY_STORAGE=RPMBTEE_STORAGE_PRIVATE_RPMB
  • SECURITY_STORAGE=SECURITYTEE_STORAGE_PRIVATE_REE

这也是为什么 Rockchip 文档里会强调:init 脚本会根据设备与方案替换 SECURITY_STORAGE。

6.3 RNG 与回退策略

TA 获取随机数使用:

  • 优先:rk_get_trng(buf, size)
  • 若硬件不支持 TRNG:用rk_derive_ta_unique_key()做回退

这说明两个事实:

  1. KeyBox 依赖平台的 TRNG 能力(最好有)。
  2. 回退策略并不等价于强随机,只是为了“有一个可用的随机源”。

6.4 g_hash 与 g_ver 的意义

TA 中有两个全局变量:

  • static uint32_t g_hash = 0;
  • static uint32_t g_ver = 0;

流程是:

  1. CA 调用 TA_KEY_RNG,TA 返回随机数,同时计算g_hash
  2. CA 把随机数做js_hash()(同一算法)得到值 A。
  3. CA 调用 TA_KEY_VER 把 A 传回,TA 对比是否等于 g_hash。
  4. 通过则g_ver = 1

然后 TA_KEY_READ 会判断:

  • 如果g_ver == 0:直接返回随机数(不读持久化对象)
  • 如果g_ver == 1:才去打开enc_key并读出数据

这是一种“握手后才能读”的最小化示例,但它不是强安全认证。

6.5 TA 的读写逻辑

  • 写入:不依赖 g_ver,任何能打开会话的 CA 都可以写 enc_key。
  • 读取:依赖 g_ver,且依赖对象存在。

这与 Rockchip 文档中的“建议重构”一致:示例代码为了易用性留了空间,但产品级方案需要加强。


7. CA 侧实现详解

CA 源码main.c看起来很长,核心其实只有两件事:

  • 通过 TEEC 调 TA 完成 READ/WRITE
  • 把 32 字节 key 与/tmp/syspw(64 字节 hex 字符串)互相转换

7.1 运行模式:ramfs 模式与 recovery 模式

CA 在 main 里用两个条件分支区分运行场景:

  • ramfs 模式:用于启动阶段“读取密钥并输出”
  • recovery 模式:用于“从 /tmp/syspw 导入密钥并写入安全存储”

判断逻辑:

  • 如果不是 init 的子进程getppid() != 1)或者带参数:走 recovery
  • 否则:尝试确认当前根是否来自 ramdisk,再走 ramfs

可以把它抽象成:

if (早期启动环境) { key = KeyBox_Read_From_TEE(); /tmp/syspw = hex(key); } else { key = unhex(/tmp/syspw); KeyBox_Write_To_TEE(key); }

7.2 /tmp/syspw 的作用

为什么不是把二进制 key 直接写到文件?

因为 early boot 脚本与工具链更容易处理“可打印字符串”,所以 CA 把 key 写成:

  • 32 字节二进制 → 64 字节 ASCII hex

这样 shell 脚本或解密工具可以更容易接入。

但这同时意味着:密钥会以可见字符串形式在 Ramdisk 中短暂存在,所以生命周期控制很关键。

7.3 storage type 的选择

CA 通过环境变量决定后端:

  • SECURITY_STORAGE=RPMB:走 RPMB
  • SECURITY_STORAGE=SECURITY:走 REE private storage(在 Rockchip 方案里常映射到 Security 分区或 REE FS)

这也是为什么文档中 init 脚本会用 sed 替换该变量。


8. KeyBox 在 System-Encryption 的位置

Rockchip 的安全方案通常把“验签/解密”放到 Ramdisk 的/init中完成,之后 switch_root 进入真实系统。

KeyBox 的位置就在“系统解密”的关键一步:

[boot.img] = Kernel + Ramdisk Ramdisk /init: 1) 挂载 /proc /sys 等 2) 判断 A/B 槽位 3) 运行 KeyBox(读出 enc_key → /tmp/syspw) 4) 使用 dmsetup/dm-crypt 解密目标分区,生成 vroot 5) switch_root 进入 vroot

你可以把 KeyBox 理解为:

  • 系统加密链路中的“密钥供给点”
  • 它不负责加密算法,也不负责 dmsetup 参数
  • 它只负责在正确时机,把正确密钥送到正确地方

9. 安全存储后端怎么选

Rockchip 的 OP-TEE 安全存储在实践中大致分三类(本质上是“TA 的 storageID + 平台能力”组合):

  1. RPMBTEE_STORAGE_PRIVATE_RPMB
  2. Security 分区:通常通过TEE_STORAGE_PRIVATE_REE+ 特定配置映射到 security 分区
  3. REE 文件系统后端:同样是TEE_STORAGE_PRIVATE_REE,但落到 /metadata/tee 或 /data/vendor/tee 等路径

下面用一张表把差异讲清楚:

后端典型硬件前提优点代价与风险适用建议
RPMBeMMC 且启用 RPMB 驱动抗篡改能力更强、断电鲁棒性通常更好容量小,依赖 eMMC 与 RPMB key 绑定机制重要密钥优先选 RPMB
Security 分区无 RPMB 或方案要求可在 NAND/非 eMMC 场景实现“类似安全区”可能被强制擦除,依赖分区规划作为无 RPMB 的替代
REE FS 后端tee-supplicant 可访问目录容量不受限,调试方便易被删除/回滚,强依赖上层完整性策略适合开发调试或低安全级产品

关键结论:KeyBox 的“接口”统一,但“安全强度”由后端决定。产品化必须把“后端选择 + 完整性策略 + 反回滚”作为整体设计。


10. 不同 Rockchip 平台是否都有 KeyBox

这里要区分两个层面:

  • 概念层面:只要有 OP-TEE + Secure Storage,就可以实现 KeyBox 类服务。
  • SDK 提供层面:Rockchip 在某些 Linux Secure Boot / System-Encryption 方案里提供了 KeyBox 示例代码,但它不是所有产品默认必选项。

从 OP-TEE 资源与平台列表看,Rockchip 在多个 SoC 上都有 OP-TEE 支持(不同 SoC 的 TEE 内存配置不同)。

因此可以给出一个更贴近工程的结论:

  • 如果该平台的 SDK 安全方案包含 System-Encryption,并启用了 OP-TEE 环境,通常就会带上或可集成 KeyBox。
  • 如果只做 System-Verity(验签)而不做加密,KeyBox 不一定需要。
  • 如果没有 eMMC RPMB,也并不等于不能用 KeyBox,只是后端会落到 Security 分区或 REE FS。

建议你在具体 SDK 中用三步判断“你的平台是否具备 KeyBox 运行条件”:

  1. Kernel DTS 是否启用 OP-TEE 节点
  2. 用户空间是否有 tee-supplicant 与 /dev/tee* 节点
  3. 分区表是否具备 RPMB 或 security 分区(或 REE FS 后端目录是否可用)

11. 不同厂商平台是否都有 KeyBox

如果把视角扩大到“不同 SoC 厂商”,答案是:

  • KeyBox 这个名字不是通用标准
  • “安全保存系统加密密钥”这个需求是通用的

也就是说:

其他平台通常会提供“相同目的”的组件,但名称与接口完全不同。

下面用对比表让结论更直观:

平台生态常见做法与 KeyBox 的关系
Rockchip Linux + OP-TEE提供 KeyBox 示例 CA/TA,结合 System-Encryption名称与代码直接对应
Android 生态使用 Keystore/KeyMint/Keymaster 类服务目标一致,接口体系不同
其他 Linux SoC自研 CA/TA 或使用 TPM/Sealed Storage目标一致,组件形式不同
安全硬件导向平台TPM/SE/HSM 保存密钥,OS 通过标准接口取用“保险箱”在外设或芯片内安全模块

把它抽象到最高层,你会发现 KeyBox 解决的问题可以归纳成一个公式:

系统加密可用性 = 早期启动能拿到 key 系统加密安全性 = key 长期保存不暴露 + 取用过程可控

只要一个平台能满足这两点,就“有 KeyBox 这件事”;只是它不一定叫 KeyBox。


12. 必须讲清楚的安全边界

KeyBox 是示例代码,它的默认实现有一些“可用性优先”的取舍。产品化时必须补齐边界。

12.1 默认实现的风险点

风险点源码表现影响
写入不受控TA_KEY_WRITE 不依赖 g_ver,且会话为 PUBLIC可能被非预期程序写入错误 key
读取握手较弱js_hash 不是强认证机制不适合对抗强攻击者
/tmp/syspw 暴露早期启动阶段把 key 明文 hex 落到 /tmpRamdisk 环境泄露会导致 key 泄露
失败处理不够“严格”文档提到交互出错时可能输出随机 key容易让系统进入不可预测状态

12.2 产品化改造建议

可以按优先级做增强:

  1. 对 TA 文件做签名,阻止第三方加载自定义 TA。

  2. 限制 CA 运行环境:只允许在 Ramdisk + PID=1 + 已验证启动链条件下读取。

  3. CA/TA 加强认证:用设备唯一身份、会话上下文、nonce、计数器等替代简化 hash。

  4. 把 key 的生命周期缩到最短

    • 使用后立即清理 /tmp/syspw
    • 尽量避免把 key 变成可打印字符串
    • 能否改为通过管道/内存传递给解密工具
  5. 引入版本与反回滚策略:当你使用 REE FS 或 security 分区时,必须考虑“回滚旧对象”的风险。


13. 编译集成与调试要点

这一节的目标是给你一个“工程师视角的检查清单”。

13.1 代码位置与构建关系

KeyBox 的示例目录结构通常类似:

  • buildroot/package/rockchip/tee-user-app/extra_app/host:CA
  • buildroot/package/rockchip/tee-user-app/extra_app/ta:TA

构建时要注意两条编译链:

  • CA 跟随用户空间架构(常见为 aarch64)
  • TA 跟随 BL32/OP-TEE 架构(常见为 aarch32)

13.2 内核与设备树

  • Kernel 需要启用 OP-TEE 支持
  • DTS 中要有 optee 节点,并且状态为 okay

13.3 运行时检查

在板端按顺序检查:

  1. /dev/tee0/dev/teepriv0是否存在
  2. tee-supplicant是否可运行
  3. 如果使用 RPMB:/dev/mmcblkXrpmb是否存在
  4. 如果使用 Security 分区:是否有对应 by-name 节点
  5. 环境变量SECURITY_STORAGE是否在 Ramdisk /init 中正确设置

14. 最后用两张流程图收束全篇

14.1 密钥灌装与启动取用流程

┌──────────────┐ ┌──────────────┐ │ Recovery/工厂 │ │ Ramdisk 启动 │ └──────┬───────┘ └──────┬───────┘ │ │ │ 1) 准备 /tmp/syspw │ │ (64字节hex) │ │ │ ▼ │ ┌──────────────┐ │ │ keybox_app │ │ │ 写入模式 │ │ └──────┬───────┘ │ │ 2) TEEC -> TA_KEY_WRITE │ ▼ │ ┌──────────────┐ │ │ OP-TEE TA │ │ │ 保存 enc_key │ │ └──────────────┘ │ │ │ 3) TEEC -> RNG/VER/READ ▼ ┌────────────────┐ │ keybox_app │ │ 读取模式 │ └───────┬────────┘ │ 4) 输出 /tmp/syspw ▼ ┌────────────────┐ │ dmsetup/dm-crypt│ │ 解锁 rootfs │ └────────────────┘

14.2 CA 与 TA 的交互时序

CA(keybox_app) TA(keybox TA) | | | TEEC_OpenSession(UUID) | |---------------------------------------->| | | | TA_KEY_RNG (MEMREF_OUTPUT) | |---------------------------------------->| |<----------------------------------------| | rng bytes + TA 内部计算 g_hash | | | | TA_KEY_VER (VALUE_INPUT=hash(rng)) | |---------------------------------------->| | TA 校验通过,置 g_ver=1 | | | | TA_KEY_READ (MEMREF_OUTPUT, storageID) | |---------------------------------------->| | OpenPersistentObject("enc_key") | | ReadObjectData -> key | |<----------------------------------------| | key bytes | | | | hex(key) -> /tmp/syspw |

15. 结语与落地建议

如果你要把 KeyBox 真正用到产品里,可以用三句话作为设计准绳:

  1. KeyBox 管的不是“加密算法”,而是“系统加密密钥的生命周期”。
  2. 选择 RPMB/Security/REE FS 的本质是在选“安全强度与工程代价”。
  3. 示例能跑不等于能上量产,必须按威胁模型重构访问控制与失败策略。

如果你希望下一步把这篇文章进一步“落到可复现”,我建议你把你 Ramdisk 的/init解密流程片段(含 dmsetup 参数、A/B 判断、SECURITY_STORAGE 设置)贴出来,我们可以把 KeyBox 与 System-Encryption 的拼装点逐行对齐,形成一套“从刷机灌装到启动解锁”的完整闭环笔记。


📺B站:博主个人介绍

📘博主书籍-京东购买链接*:Yocto项目实战教程

📘加博主微信,进技术交流群jerrydev


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/24 6:23:31

<span class=“js_title_inner“>SegGISv3 添加后处理功能,视屏教程</span>

GIS数据栈编辑&#xff1a;GIS数据栈【导读】SegGIS无人机遥感影像识别系统是一款专业级遥感影像AI识别与分析工具&#xff0c;集成了最先进的深度学习技术、多源地图服务和地理大模型智能分析功能&#xff0c;为测绘、规划、环保、农业等各行业提供一站式遥感影像解决方案。所…

作者头像 李华
网站建设 2026/3/26 15:52:49

百考通「降重+降AI」双效优化功能:智能化解查重与AI检测双重风险

在高校论文审核日趋严格的今天&#xff0c;学生面临的不仅是传统查重系统的重复率限制&#xff0c;还有新兴AI内容检测工具对“生成痕迹”的严苛筛查。许多同学即便亲手撰写&#xff0c;也可能因语言规范、逻辑清晰而被误判为AI代写&#xff1b;而借助AI辅助写作后&#xff0c;…

作者头像 李华