📺 B站视频讲解(Bilibili):https://www.bilibili.com/video/BV1k1C9BYEAB/
📘 《Yocto项目实战教程》京东购买链接:Yocto项目实战教程
读懂 NVIDIA Jetson OP-TEE 官方源码:从目录结构到 JetPack / Yocto 构建与运行的完整指南
本文以 NVIDIA 官方 nvidia-jetson-optee-source/optee 源码为核心,从目录结构 → 构建流程 → 产物形态 → 系统集成 → 运行与验证五个维度,系统讲清楚 Jetson 平台上 OP-TEE 的完整工程链路。内容同时覆盖 JetPack(L4T/Ubuntu) 与 Yocto(meta-tegra) 两种主流体系,帮助你在两套系统中都能正确编译、部署并运行 OP-TEE 相关组件。
一、整体架构速览:Jetson 上的 OP-TEE 是如何工作的
在 Jetson 平台,OP-TEE 并不是一个“单独的程序”,而是一整套**跨启动链、跨世界(Secure/Normal)**的工程体系,主要由以下部分组成:
- OP-TEE OS(Secure World):运行在 TrustZone Secure World 的可信操作系统
- TEE Client(Normal World):Linux 用户态与 Secure World 通信的标准接口库
- TEE Supplicant(Normal World 守护进程):辅助 OP-TEE OS 完成存储、文件、RPMB 等操作
- TA / PTA(Secure World 应用):在 Secure World 中执行的可信应用
- CA(Normal World 客户端):Linux 用户态程序,通过 TEE Client API 调用 TA/PTA
在 Jetson 启动链中:
- BootROM / MB1 / MB2 完成早期启动
- OP-TEE OS(tos-optee.img)* 被加载到 Secure World
- Linux Kernel 启动(Normal World)
- Linux 用户空间启动
tee-supplicant - 用户程序(CA)通过
/dev/tee*与 OP-TEE 通信
二、源码目录总览(以 nvidia-jetson-optee-source/optee 为准)
你当前看到的目录结构如下:
optee/
├── atf_and_optee_README.txt
├── optee_client/
├── optee_os/
├── optee_test/
├── samples/
└── tegra234-optee.dts
这是 Jetson 官方 OP-TEE 源码的完整工程形态,下面逐一拆解。
三、optee_os:Secure World 的核心(最关键)
1. 目录定位
optee_os/
├── core/
├── ldelf/
├── lib/
├── ta/
├── mk/
├── scripts/
├── keys/
└── prebuilt/
optee_os 是运行在 Secure World 的 OP-TEE 操作系统本体,最终会被编译成:
tos-optee_t234.img(或同类名称)
并在启动时由 Bootloader 加载。
2. 关键子目录说明
(1)core/
- OP-TEE 内核核心代码
- 包含线程调度、内存管理、TEE syscall 实现
- 与 Linux Kernel 类似的“内核态”部分
(2)ldelf/
- TA Loader(ELF 装载器)
- Secure World 中负责加载
.ta文件 - xtest / hwkey-agent 中大量日志都与 ldelf 有关
(3)ta/
- Secure World 中 TA / PTA 的公共支持代码
- PTA(Pseudo TA)通常以内建形式存在于 OP-TEE OS
(4)mk/
- 构建系统核心(Makefile 片段)
ta_dev_kit.mk就在这里- 所有 TA 的交叉编译都依赖这一套工具链定义
(5)keys/
- 测试密钥 / 示例密钥
- 量产中通常不会直接使用这里的 key
3. 构建 optee_os(生成 Secure OS 镜像)
JetPack(L4T)方式
在 NVIDIA 提供的 Driver Package 中:
cd Linux_for_Tegra/source/optee
make PLATFORM=tegra234
生成的核心产物包括:
out/arm-plat-tegra/core/tee.bin- 经过签名/封装后成为
tos-optee_t234.img
该镜像在刷机阶段写入 A_secure-os 分区。
Yocto(meta-tegra)方式
在 Yocto 中:
- recipe:
optee-os_%.bb - include:
optee-l4t.inc
Yocto 会:
- 拉取
nvidia-jetson-optee-source - 进入
optee_os/ - 使用交叉工具链构建
- 生成
tos-optee*.img - 集成进最终刷机镜像
关键点:Yocto 构建的 OP-TEE OS 与 JetPack 使用的是同一套源码,只是构建系统不同。
四、optee_client:Normal World 的通信桥梁
1. 目录定位
optee_client/
├── libteec/
├── tee-supplicant/
├── Makefile
└── README.md
optee_client 提供了 GlobalPlatform 标准定义的 TEE Client API。
2. 核心组件
libteec
-
libteec.so -
CA(Normal World 程序)必须链接的库
-
提供:
TEEC_InitializeContextTEEC_OpenSessionTEEC_InvokeCommand
tee-supplicant
-
Linux 用户态守护进程
-
OP-TEE OS 在 Secure World 中无法直接访问 Linux 文件系统
-
通过 RPC 请求,由 tee-supplicant 代为完成:
- 文件访问
- RPMB
- 安全存储
3. 构建与部署
JetPack
- NVIDIA 已预编译
- 默认安装在:
/usr/lib/libteec.so
/usr/sbin/tee-supplicant
Yocto
- recipe:
optee-client_%.bb - 构建后自动进入 rootfs
五、optee_test:验证 OP-TEE 是否正常工作的标准套件
1. 目录结构
optee_test/
├── host/
├── ta/
└── README.md
2. xtest 的意义
-
xtest是 OP-TEE 官方的回归测试程序 -
能系统性验证:
- Secure World 是否在跑
- TA 是否能加载
- 基本加密算法是否可用
你之前成功运行 xtest,已经证明:
OP-TEE OS + optee_client + tee-supplicant 整条链路是通的
六、samples:官方给你的“工程级示例”
1. 目录结构
samples/
├── hwkey-agent/
├── luks-srv/
├── ftpm-helper/
├── cpubl-payload-dec/
└── pkcs11-sample/
这些不是玩具示例,而是真实业务模型的参考实现。
2. hwkey-agent(与你当前工作最相关)
samples/hwkey-agent/
├── ta/ # Secure World TA
├── host/ # Normal World CA
└── README
- TA:运行在 Secure World
- CA:Linux 用户态程序(你已经在 Yocto 中构建并运行)
nvhwkey-app 就来自这里。
3. 构建方式(以 Yocto 为例)
Yocto 中:
- recipe:
optee-nvsamples - 构建产物路径示例:
build/ca/hwkey-agent/nvhwkey-app
build/ta/hwkey-agent/*.ta
这些文件在 rootfs 中的放置规则:
| 文件 | 位置 |
|---|---|
| CA | /usr/bin/ |
| TA | /lib/optee_armtz/ |
七、关键文件最终都放到哪里?(非常重要)
| 类型 | 文件 | 位置 |
|---|---|---|
| Secure OS | tos-optee_t234.img | A_secure-os 分区 |
| EKB | eks_t234.img | A_eks 分区 |
| TA | *.ta | /lib/optee_armtz/ |
| CA | 可执行文件 | /usr/bin/ |
| libteec | libteec.so | /usr/lib/ |
| supplicant | tee-supplicant | /usr/sbin/ |
八、JetPack 与 Yocto 的差异总结
| 维度 | JetPack | Yocto |
|---|---|---|
| 构建方式 | NVIDIA 预编译 + 手动 | bitbake 自动 |
| 灵活性 | 中 | 高 |
| 适合阶段 | 验证 / Demo | 产品化 |
| OP-TEE 修改 | 麻烦 | 非常自然 |
你现在走 Yocto 路线,是做安全产品的正确选择。
九、如何基于这套源码继续你的 HelloWorld 安全工程
在你已经完成的阶段基础上:
gen_ekb.py→ 把 hello_seed 放进 EKB- OP-TEE OS 启动 → Secure World 解析 EKB
- PTA → 从 EKB 读取 seed
- CA → 请求“加密/解密服务”,但永远拿不到 key
你现在理解的这套 目录结构 + 构建方式,正是你后续每一步安全设计的“地图”。
九、EKB(Encrypted Key Blob):Jetson OP-TEE 的密钥构建与运行时使用核心
在前面的章节中,我们已经完整走通了 OP-TEE 的源码结构、构建方式以及在 JetPack / Yocto 中的运行形态。但如果要真正把 OP-TEE 用于业务级安全,就绕不开一个核心机制:EKB(Encrypted Key Blob)。
这一节将把 EKB 的构建逻辑、生成流程、启动时解析路径以及运行时使用方式系统性地补齐,使整篇文章形成一个从“源码 → 构建 → 启动 → 业务”的完整闭环。

9.1 为什么需要 EKB?
在 Jetson 的安全设计中,有一个非常明确的目标:
业务密钥不能明文存在于 Linux 文件系统中,也不能在运行时被 Linux 直接读取。
但与此同时:
- OP-TEE 需要在启动后稳定地拿到这些密钥
- 密钥需要支持 OTA 更新
- 不同安全业务(磁盘加密、UEFI、应用加密)需要不同 key
EKB 正是为了解决这一组矛盾而设计的:
- EKB 是一个加密后的二进制密钥容器
- 存放在 EKS 分区
- 只能被 Secure World(OP-TEE) 解密和解析
- Linux 永远只能看到密文
9.2 EKB 在启动链中的位置
在 Jetson 平台,EKB 的使用路径是固定的:
Flash / OTA
↓
EKS 分区(eks_t234.img)
↓
MB2
↓
OP-TEE OS 启动
↓
jetson-user-key PTA 解析 EKB
↓
密钥进入 Secure World 内存
几个关键点:
- EKB 不在 rootfs 中
- EKB 不在 Linux 视角可读的分区中
- 只有 OP-TEE 在启动早期才能拿到它
9.3 EKB 的核心构建流程(工程视角)
9.3.1 构建输入材料
一个最小但完整的 EKB,至少包含:
| 输入 | 作用 |
|---|---|
| OEM_K1 | Root of Trust,烧录到 Fuse |
| FV | 随机向量,用于派生 EKB_RK |
| 用户密钥(如 hello_seed) | 业务真正使用的 seed |
这些输入不会直接以明文形式出现在设备上。
9.3.2 gen_ekb.py 的角色
在 nvidia-jetson-optee-source 中,EKB 是通过官方工具生成的:
optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py
这个脚本本质上做了 5 件事:
-
使用 OEM_K1 + FV 派生 EKB_RK
-
基于 NIST-SP-800-108 KDF 派生:
- EKB_EK(加密)
- EKB_AK(认证)
-
将用户密钥(如 hello_seed)按 tag 编码进 EKB 内容
-
使用 EKB_EK 对内容加密
-
使用 EKB_AK 生成 MAC
最终输出:
eks_t234.img
9.4 一个最小业务 EKB 的示例(HelloWorld 场景)
以最简单的业务为例:
我希望 Secure World 中持有一个 hello_seed,用它派生 AES key,对 Linux 文件进行加解密。
构建步骤概览:
- 生成 hello_seed(32 字节随机数)
- 修改 gen_ekb.py,增加
-in_hello_seed - 将 hello_seed 作为一个新的 key_tag 写入 EKB
- 生成 eks_t234.img
- 刷写到 A_eks 分区
在这个过程中:
- hello_seed 只在 生成阶段短暂存在
- 上板后设备中不再存在明文 seed
9.5 OP-TEE 启动时如何解析 EKB
在 OP-TEE OS 启动过程中:
- Secure Engine 从 Fuse 中加载 OEM_K1
- OP-TEE 计算 EKB_RK
- 验证 EKB 的 MAC
- 解密 EKB 内容
- 将 key_tag → key 的映射保存到 PTA 内部结构
这一逻辑主要位于:
optee_os/core/pta/jetson-user-key/
这也是为什么:
- Linux 永远无法直接访问这些 key
- CA 只能“请求服务”,而不能“请求密钥”
9.6 EKB 与 PTA / CA 的职责边界
| 组件 | 能看到什么 |
|---|---|
| Linux CA | 看不到任何明文 key |
| tee-supplicant | 看不到 key |
| PTA(Secure World) | 能看到并使用 key |
| OP-TEE Core | 负责生命周期与隔离 |
一个典型业务调用是:
Linux CA → PTA:请帮我加密这个 buffer
PTA:使用 EKB 中的 hello_seed 派生 key
PTA:完成加密,返回密文
Linux 全程:
- 不知道 key
- 不知道派生方式
- 只能看到结果
9.7 为什么 EKB 是“一次构建,多次使用”的机制
EKB 有几个重要特性:
- 不能在运行时修改
- 只能通过 OTA / 刷机更新
- 启动后,key 常驻 Secure World 内存
这意味着:
- 构建 EKB 是安全工程的“源头设计”
- 后续所有安全业务,都是围绕这个源头展开
十、结语:从源码理解,到安全能力落地
通过补齐 EKB 这一章,可以看到:
- OP-TEE 并不是一个“黑盒安全模块”
- EKB 不是魔法,而是可推导、可验证、可工程化的机制
当你理解了:
- OP-TEE 源码结构
- JetPack / Yocto 构建路径
- EKB 的构建与解析
你实际上已经具备了:
在 Jetson 平台上设计、实现并交付安全业务的能力
无论是文件保护、模型加密,还是 OTA / 设备身份,这套链路都已经在你手中。
📺 B站视频讲解(Bilibili):https://www.bilibili.com/video/BV1k1C9BYEAB/
📘 《Yocto项目实战教程》京东购买链接:Yocto项目实战教程
1693

被折叠的 条评论
为什么被折叠?



