Android FBE密钥存储与生命周期全解析
Android FBE密钥存储、来源与生命周期深度解析
这是Android加密最核心也最容易被误解的部分。我会用最清晰的方式拆解:所有密钥的精确存储位置、开机解密的完整链条、每个密钥的完整生命周期,以及TEE中真正永久不变的根密钥。
一、核心结论先览
- 没有任何用户密钥以明文形式永久存储,永久存储的只有加密后的密钥包裹(KeyBlob)
- 真正的根密钥(HUK)烧录在芯片硬件中,永远无法被读取或导出
- 所有明文密钥只存在于内存中,重启后立即彻底消失
- TEE是唯一能解密KeyBlob的地方,普通世界(Android系统)永远看不到明文主密钥
二、所有密钥的精确存储位置
密钥层次与存储位置对照表
密钥类型 | 明文存在位置 | 加密形式存储位置 | 能否被导出 |
硬件唯一密钥(HUK) | 仅存在于TEE硬件寄存器 | 无,烧录在芯片熔丝中 | 绝对不能 |
安全存储密钥(SSK) | 仅存在于TEE内部RAM | 加密存储在RPMB分区 | 不能 |
KeyMint根密钥 | 仅存在于TEE内部RAM | 加密存储在RPMB分区 | 不能 |
System DE主密钥 | 内核密钥环(内存) | /data/misc/vold/ 目录下的KeyBlob | 不能 |
User DE主密钥 | 内核密钥环(内存) | /data/misc/vold/ 目录下的KeyBlob | 不能 |
User CE主密钥 | 内核密钥环(内存) | /data/misc/vold/ 目录下的KeyBlob | 不能 |
每文件密钥(FEK) | 内核文件系统缓存 | 存储在文件扩展属性(xattr)中 | 不能 |
扇区密钥 | 内联加密引擎(ICE)寄存器 | 不存储,动态派生 | 不能 |
关键细节解释
KeyBlob是什么?
- KeyBlob是被KeyMint用硬件根密钥加密后的主密钥
- 本质是一个二进制文件,存储在普通世界的/data/misc/vold/目录
- 文件名格式:key_,大小约100-200字节
- 只能由生成它的设备的KeyMint解密,在其他任何设备上都是乱码
- 为什么KeyBlob可以安全地存储在普通世界?
- KeyBlob使用AES-GCM加密并带有完整性校验
- 解密密钥(HUK)永远不会离开TEE硬件
- 即使攻击者获取了整个eMMC的完整镜像,没有HUK也无法解密任何KeyBlob
- RPMB分区的作用
- RPMB是eMMC/UFS芯片中的一个特殊硬件分区
- 只有TEE可以访问,普通世界无法直接读写
- 存储KeyMint的根密钥和Weaver的防暴力破解计数器
- 提供防重放攻击保护,防止攻击者回滚到旧的密钥版本
三、每次开机解密密钥从哪里来?
完整的开机密钥解密流程图
eMMC芯片 ├─ RPMB分区 → 存储KeyMint根密钥(加密) └─ userdata分区 → 存储System DE/User DE/User CE KeyBlob ↓ 开机时TEE自动启动 ↓ TEE使用硬件熔丝中的HUK解密RPMB中的KeyMint根密钥 ↓ KeyMint根密钥加载到TEE内部RAM(永远不会离开) ↓ Android系统启动,vold读取userdata中的KeyBlob ↓ vold将System DE KeyBlob发送给KeyMint(TEE) ↓ KeyMint使用KeyMint根密钥解密System DE KeyBlob ↓ KeyMint将明文System DE主密钥返回给vold ↓ vold将System DE主密钥安装到内核密钥环(内存) ↓ 用户输入密码 ↓ Gatekeeper验证密码通过,返回签名的AuthToken ↓ vold将User CE KeyBlob + AuthToken发送给KeyMint ↓ KeyMint验证AuthToken签名有效 ↓ KeyMint解密User CE KeyBlob,返回明文主密钥给vold ↓ vold将User CE主密钥安装到内核密钥环 ↓ 加密完成,所有文件可访问最关键的安全设计
- 密钥解密完全在TEE内部完成:普通世界的vold进程只是一个"搬运工",它看不到解密过程,只能拿到最终的明文密钥
- AuthToken是一次性的:由Gatekeeper用TEE私钥签名,有效期只有10秒,无法伪造或重用
- 密钥传递通道是安全的:TEE和普通世界之间的通信使用共享内存,并且有严格的访问控制
四、每个密钥的完整生命周期
1. 硬件根密钥(HUK)
- 生成:芯片制造时由厂商烧录到一次性可编程(OTP)熔丝中
- 使用:仅用于解密RPMB中的KeyMint根密钥
- 销毁:永远不会被销毁,与芯片物理寿命相同
- 特性:每个芯片全球唯一,无法修改,无法读取
2. KeyMint根密钥
- 生成:设备首次启动时由KeyMint在TEE中生成
- 使用:用于加密/解密所有用户主密钥的KeyBlob
- 存储:加密后存储在RPMB分区,运行时存在于TEE内部RAM
- 销毁:恢复出厂设置时会被销毁并重新生成
- 特性:设备唯一,与HUK绑定,无法导出
3. System DE主密钥
- 生成:设备首次启动时由KeyMint生成
- 加载:每次系统启动时自动解密并加载到内核密钥环
- 使用:用于解密System DE和User DE目录下的所有文件
- 销毁:系统关机或重启时,内核密钥环被清空,密钥彻底消失
- 特性:不需要用户密码即可解密,系统启动后自动可用
4. User CE主密钥
- 生成:用户首次设置锁屏密码时由KeyMint生成
- 加载:用户输入正确密码并通过验证后,解密并加载到内核密钥环
- 使用:用于解密User CE目录下的所有文件(绝大多数应用数据)
- 销毁:系统关机或重启时销毁;锁屏不会销毁,只有重启才会
- 特性:与用户密码绑定,没有密码永远无法解密
5. 每文件密钥(FEK)
- 生成:创建新文件时由内核fscrypt子系统动态生成
- 派生:由主密钥+文件inode号+随机数通过HKDF派生
- 存储:加密后存储在文件的扩展属性(xattr)中
- 使用:文件被打开时派生,用于加密/解密文件内容
- 销毁:文件被关闭时从内核缓存中清除
- 特性:每个文件唯一,一个文件泄露不影响其他文件
五、TEE中哪些密钥是永远不变的?
绝对永久不变的密钥
只有硬件唯一密钥(HUK)是真正永远不变的。它被烧录在芯片的OTP熔丝中,一旦写入就无法修改或擦除,即使恢复出厂设置、重刷系统甚至更换主板上的eMMC芯片,HUK也不会改变。
不同芯片厂商对HUK的称呼略有不同:
- 高通:QFPROM(高通熔丝)中的Chip Unique Key
- 联发科:EFUSE中的Chip ID和Secure Root Key
- 三星:eFuse中的Unique ID和Root Key
设备生命周期内不变的密钥
KeyMint根密钥在设备首次启动时生成,之后在设备的整个生命周期内保持不变,除非执行了以下操作:
- 恢复出厂设置
- 重新刷写官方系统并清除所有数据
- 解锁Bootloader(大多数设备会自动触发恢复出厂设置)
会定期变化的密钥
- 用户主密钥(DE/CE):用户修改锁屏密码时会重新生成
- 每文件密钥(FEK):每次创建新文件时生成新的密钥
- AuthToken:每次用户解锁时生成一个新的,10秒后过期
六、常见误解澄清
误解1:"密钥存储在TEE中"
不准确。TEE中只存储根密钥(HUK和KeyMint根密钥),用户主密钥的加密版本(KeyBlob)存储在普通世界的/data/misc/vold/目录中。
这种设计的好处是:
- 可以支持无限多个用户和密钥
- 可以轻松添加或删除密钥槽
- 不需要占用TEE有限的存储空间
误解2:"Root后可以导出所有密钥"
部分正确但有前提。Root后确实可以读取内核密钥环中的明文主密钥,但:
- Root需要先解锁Bootloader
- 解锁Bootloader会自动触发恢复出厂设置,清除所有用户数据
- 因此,对于已经设置了锁屏密码的丢失设备,攻击者无法通过Root获取密钥
误解3:"更换eMMC芯片可以绕过加密"
不可能。因为KeyBlob是用原设备的HUK加密的,新eMMC芯片中的KeyBlob在原设备上可以解密,但原设备的KeyBlob在新设备上无法解密。
误解4:"厂商有后门可以解密用户数据"
对于符合Google安全标准的设备,没有。所有密钥都与用户密码和设备硬件绑定,即使是Google和设备厂商也无法解密用户数据。
七、总结
Android FBE的密钥体系设计遵循了最小权限原则和分层防御原则:
- 最核心的根密钥被硬件保护,永远无法被读取
- 所有用户密钥都被加密存储,只有在需要时才解密到内存
- 所有明文密钥都是临时的,重启后立即消失
- 任何环节被攻破都不会导致整个加密体系崩溃
这种设计使得Android 10及以上设备的加密强度达到了军事级别,在没有用户密码的情况下,即使拥有最先进的技术和设备,也无法解密用户数据。
