一、Keystore 与 TEE:为什么非它不可?
聊到 Android 安全,Keystore 是个绕不开的话题。但说实话,光靠 Keystore 本身是不够的——它只是个 API 层,真正干活的,是底层的 TEE(可信执行环境)。
我刚开始接触这块时,也以为 Keystore 就是个存密钥的地方。后来踩了坑才明白:密钥的安全,取决于它存在哪里。如果密钥直接暴露在 Android 系统(REE,Rich Execution Environment)里,那 root 过的设备基本等于裸奔。TEE 的作用,就是给密钥一个「独立的安全屋」。
1.1 主流 TEE 方案:Trusty、QSEE、OPTEE
目前 Android 生态里,主流的 TEE 方案有三个。我按接触频率排个序:
| TEE 方案 | 厂商 | 特点 | 我的评价 |
|---|---|---|---|
| Trusty TEE | 开源、AOSP 内置、与 Keystore 深度集成 | 干净、可控,但生态不够广 | |
| QSEE (Qualcomm Secure Execution Environment) | 高通 | 闭源、性能强、出货量最大 | 稳定,但调试起来很痛苦 |
| OPTEE | Linaro / 开源社区 | 开源、ARM TrustZone 标准实现 | 灵活,适合定制化需求 |
我个人习惯是:做原型验证用 Trusty,量产项目看芯片平台。高通平台基本绑定了 QSEE,联发科和海思则更倾向 OPTEE。你想想看,如果选错了 TEE 方案,后面适配 TA(Trusted Application)的工作量会翻倍。
1.2 TEE 内部密钥管理:密钥是怎么「藏」起来的?
密钥进了 TEE 就安全了吗?不一定。TEE 内部也有自己的密钥管理体系,我把它拆成三层:
- 根密钥(Root Key):烧录在芯片 eFuse 里,出厂即定,不可更改。这是整个信任链的起点。
- 设备密钥(Device Key):由根密钥派生,用于加密用户密钥。每个设备唯一。
- 用户密钥(User Key):Keystore 层看到的密钥,实际在 TEE 内以密文存储。
我在项目中遇到过一个问题:某款设备 root 后,攻击者通过内存 dump 拿到了 Keystore 的数据库文件。但密钥本身是加密存储的,攻击者拿不到 TEE 内的设备密钥,最终白忙一场。这就是分层密钥管理的好处——攻破一层,不等于攻破全部。
1.3 安全世界通信协议:REE 和 TEE 怎么「说话」?
REE(普通 Android 系统)和 TEE(安全世界)之间,不能直接共享内存。它们通过一套协议通信,我总结为三步:
- 步骤一: REE 发起 SMC(Secure Monitor Call)指令,触发 CPU 从普通世界切换到安全世界。
- 步骤二: TEE 内的 Monitor 层接收请求,路由到对应的 TA(Trusted Application)。
- 步骤三: TA 处理完后,通过共享内存(需加密)返回结果。
说白了,这就是一个「敲门-开门-递东西」的过程。但要注意:共享内存的大小和内容都有限制。我见过有人试图通过共享内存传 1MB 的数据,结果 TEE 直接崩溃——因为 TEE 的内存通常只有几十 MB,而且大部分被 TA 自身占用。
1.4 一张图看懂整体架构
下面这张 SVG 图,是我自己梳理的 Keystore + TEE 核心逻辑。你可以把它当作本章的「知识地图」:
从这张图可以清楚看到:Keystore 只是 TEE 的「前台接待」。真正的密钥操作,全部在 TEE 内部完成。REE 层只能看到加密后的密钥 blob,永远拿不到明文。
1.5 实际项目中的选择建议
如果你正在做安全模块选型,我的建议是:
- Google Pixel / 原生 AOSP 设备:直接用 Trusty,省心省力。
- 高通平台(骁龙系列):别挣扎,用 QSEE。高通对 QSEE 的优化很到位,性能最好。
- 需要开源可控:OPTEE 是唯一选择。但要做好自己写 TA 的心理准备。
嗯,这里要注意:不要试图在同一个设备上混用多个 TEE。我见过有人想在 QSEE 上跑 Trusty 的 TA,结果两个 TEE 互相抢占资源,设备直接变砖。TEE 是独占的,选一个就坚持到底。
公众号:蓝海资料掘金营,微信 deep3321