这篇文档介绍了 Linux 中的 TEE(可信执行环境)子系统。
TEE 是在一些安全环境中运行的受信任操作系统,例如 ARM CPU 上的 TrustZone,或者一个单独的安全协处理器等。TEE 驱动程序处理与 TEE 通信所需的细节。
该子系统涉及以下内容:
- TEE 驱动程序的注册
- 在 Linux 和 TEE 之间管理共享内存
- 向 TEE 提供通用 API
TEE 接口
include/uapi/linux/tee.h 定义了与 TEE 通信的通用接口。
用户空间(客户端)通过打开 /dev/tee[0-9]* 或 /dev/teepriv[0-9]* 来连接到驱动程序。
- TEE_IOC_SHM_ALLOC 分配共享内存并返回一个文件描述符,用户空间可以使用 mmap 进行映射。当用户空间不再需要文件描述符时,应关闭它。当不再需要共享内存时,应使用 munmap() 取消映射以便重新使用内存。
- TEE_IOC_VERSION 通知用户空间该驱动程序处理的 TEE 及其功能。
- TEE_IOC_OPEN_SESSION 打开到受信任应用程序的新会话。
- TEE_IOC_INVOKE 调用受信任应用程序中的函数。
- TEE_IOC_CANCEL 可以取消正在进行的 TEE_IOC_OPEN_SESSION 或 TEE_IOC_INVOKE。
- TEE_IOC_CLOSE_SESSION 关闭到受信任应用程序的会话。
有两类客户端,普通客户端和辅助程序。后者是用于 TEE 访问 Linux 资源的辅助进程,例如文件系统访问。普通客户端打开 /dev/tee[0-9]*,而辅助程序打开 /dev/teepriv[0-9]。
客户端和 TEE 之间的大部分通信对于驱动程序来说是不透明的。驱动程序的主要工作是接收来自客户端的请求,将其转发到 TEE 并发送结果。对于辅助程序,通信方向相反,TEE 发送请求到辅助程序,然后辅助程序发送结果回去。
TEE 内核接口
内核提供了 TEE 总线基础设施,其中受信任应用程序被表示为通过通用唯一标识符(UUID)标识的设备,客户端驱动程序注册了支持的设备 UUID 表。
TEE 总线基础设施注册以下 API:
- match():遍历客户端驱动程序 UUID 表,以找到与设备 UUID 对应的匹配项。如果找到匹配项,则通过客户端驱动程序注册的相应探测 API 探测特定设备。每当设备或客户端驱动程序注册到 TEE 总线时,都会发生此过程。
- uevent():通知用户空间(udev),每当在 TEE 总线上注册新设备时,以便自动加载模块化的客户端驱动程序。
TEE 总线设备枚举特定于底层 TEE 实现,因此留给 TEE 驱动程序提供相应的实现。
然后 TEE 客户端驱动程序可以使用 include/linux/tee_drv.h 中列出的 API 与匹配的受信任应用程序进行通信。
TEE 客户端驱动程序示例
假设 TEE 客户端驱动程序需要与具有 UUID:ac6a4085-0e82-4c33-bf98-8eb8e118b6c2 的受信任应用程序通信,则驱动程序注册代码段如下:
static const struct tee_client_device_id client_id_table[] = {
{UUID_INIT(0xac6a4085, 0x0e82, 0x4c33,
0xbf, 0x98, 0x8e, 0xb8, 0xe1, 0x18, 0xb6, 0xc2)},
{}
};
MODULE_DEVICE_TABLE(tee, client_id_table);
static struct tee_client_driver client_driver = {
.id_table = client_id_table,
.driver = {
.name = DRIVER_NAME,
.bus = &tee_bus_type,
.probe = client_probe,
.remove = client_remove,
},
};
static int __init client_init(void)
{
return driver_register(&client_driver.driver);
}
static void __exit client_exit(void)
{
driver_unregister(&client_driver.driver);
}
module_init(client_init);
module_exit(client_exit);
OP-TEE 驱动程序
OP-TEE 驱动程序处理基于 OP-TEE 的 TEE。目前仅支持基于 ARM TrustZone 的 OP-TEE 解决方案。
与 OP-TEE 的最底层通信建立在 ARM SMC 调用约定(SMCCC)上,这是驱动程序内部使用的 OP-TEE 的 SMC 接口的基础。在此基础之上构建了 OP-TEE 消息协议[4]。
OP-TEE SMC 接口提供了 SMCCC 所需的基本功能以及一些特定于 OP-TEE 的附加功能。最有趣的功能包括:
- OPTEE_SMC_FUNCID_CALLS_UID(SMCCC 的一部分)返回版本信息,然后由 TEE_IOC_VERSION 返回。
- OPTEE_SMC_CALL_GET_OS_UUID 返回特定的 OP-TEE 实现,用于区分 TrustZone 上的 OP-TEE 和运行在单独安全协处理器上的 OP-TEE。
- OPTEE_SMC_CALL_WITH_ARG 驱动 OP-TEE 消息协议。
- OPTEE_SMC_GET_SHM_CONFIG 允许驱动程序和 OP-TEE 协商在 Linux 和 OP-TEE 之间使用的共享内存的内存范围。
全球平台 TEE 客户端 API 基于通用 TEE API 实现。
OP-TEE 架构中不同组件之间的关系如下图所示:
User space Kernel Secure world
~~~~~~~~~~ ~~~~~~ ~~~~~~~~~~~~
+--------+ +-------------+
| Client | | Trusted |
+--------+ | Application |
/\ +-------------+
|| +----------+ /\
|| |tee- | ||
|| |supplicant| \/
|| +----------+ +-------------+
\/ /\ | TEE Internal|
+-------+ || | API |
+ TEE | || +--------+--------+ +-------------+
| Client| || | TEE | OP-TEE | | OP-TEE |
| API | \/ | subsys | driver | | Trusted OS |
+-------+----------------+----+-------+----+-----------+-------------+
| Generic TEE API | | OP-TEE MSG |
| IOCTL (TEE_IOC_*) | | SMCCC (OPTEE_SMC_CALL_*) |
+-----------------------------+ +------------------------------+
RPC(远程过程调用)是从安全世界到内核驱动程序或 tee-supplicant 的请求。一个 RPC 由 OPTEE_SMC_CALL_WITH_ARG 的一组特殊的 SMCCC 返回值来标识。针对内核的 RPC 消息由内核驱动程序处理。其他 RPC 消息将被转发到 tee-supplicant,驱动程序除了切换共享内存缓冲区表示外不再参与。
OP-TEE 设备枚举
OP-TEE 提供一个伪受信任应用程序:drivers/tee/optee/device.c,以支持设备枚举。换句话说,OP-TEE 驱动程序调用此应用程序来检索可以注册为 TEE 总线上的设备的受信任应用程序列表。
OP-TEE 通知
安全世界可以使用两种类型的通知使正常世界意识到某些事件。
- 使用 OPTEE_RPC_CMD_NOTIFICATION 和 OPTEE_RPC_NOTIFICATION_SEND 参数传递的同步通知。
- 使用非安全边沿触发中断和非安全中断处理程序的快速调用的组合传递的异步通知。
同步通知受限于依赖于 RPC 进行传递,这仅在通过 OPTEE_SMC_CALL_WITH_ARG 进入安全世界时使用。这排除了安全世界中断处理程序之外的通知。
异步通知通过非安全边沿触发中断传递到 OP-TEE 驱动程序中注册的中断处理程序。实际通知值通过快速调用 OPTEE_SMC_GET_ASYNC_NOTIF_VALUE 检索。请注意,一个中断可以表示多个通知。
一个通知值 OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF 具有特殊含义。当接收到此值时,意味着正常世界应该进行一个 yielding 调用 OPTEE_MSG_CMD_DO_BOTTOM_HALF。这个调用是从协助中断处理程序的线程中进行的。这是用于在安全世界中实现设备驱动程序的上半部和下半部风格的构建块。
OPTEE_INSECURE_LOAD_IMAGE Kconfig 选项
OPTEE_INSECURE_LOAD_IMAGE Kconfig 选项允许在内核启动后从内核中加载 BL32 OP-TEE 镜像,而不是在内核启动之前从固件中加载。这还需要在 Arm 可信固件中启用相应的选项。Arm 可信固件文档 [8] 解释了启用此选项所涉及的安全威胁以及固件和平台级别的缓解措施。
在使用此选项时,应该解决内核的其他攻击向量/缓解措施。
-
引导链安全。
攻击向量:替换 rootfs 中的 OP-TEE OS 镜像以控制系统。
缓解措施:必须有引导链安全来验证内核和 rootfs,否则攻击者可以通过修改 rootfs 中的加载的 OP-TEE 二进制文件来修改它。
-
备用引导模式。
攻击向量:使用备用引导模式(例如恢复模式),OP-TEE 驱动程序未加载,留下了 SMC 漏洞。
缓解措施:如果有设备的备用引导方法,比如恢复模式,应确保在该模式下应用相同的缓解措施。
-
SMC 调用之前的攻击。
攻击向量:在发出 SMC 调用以加载 OP-TEE 之前执行的代码可能被利用来加载替代的 OS 镜像。
缓解措施:必须在打开任何潜在攻击向量之前加载 OP-TEE 驱动程序。这应包括挂载任何可修改的文件系统,打开网络端口或与外部设备通信(例如 USB)。
-
阻止 SMC 调用加载 OP-TEE。
攻击向量:阻止驱动程序被探测,因此在需要时无法执行 SMC 调用以加载 OP-TEE,从而使其可以在稍后执行并加载修改后的 OS。
缓解措施:建议将 OP-TEE 驱动程序构建为内置驱动程序,而不是作为模块,以防止可能导致模块不被加载的漏洞。
AMD-TEE 驱动程序
AMD-TEE 驱动程序处理与 AMD 的 TEE 环境的通信。TEE 环境由 AMD 安全处理器提供。
AMD 安全处理器(以前称为平台安全处理器或 PSP)是一款专用处理器,具有 ARM TrustZone 技术,以及一个旨在启用第三方可信应用程序的基于软件的可信执行环境(TEE)。此功能目前仅针对 APU 启用。
以下图片显示了 AMD-TEE 的高级概述:
|
x86 |
|
User space (Kernel space) | AMD Secure Processor (PSP)
~~~~~~~~~~ ~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
+--------+ | +-------------+
| Client | | | Trusted |
+--------+ | | Application |
/\ | +-------------+
|| | /\
|| | ||
|| | \/
|| | +----------+
|| | | TEE |
|| | | Internal |
\/ | | API |
+---------+ +-----------+---------+ +----------+
| TEE | | TEE | AMD-TEE | | AMD-TEE |
| Client | | subsystem | driver | | Trusted |
| API | | | | | OS |
+---------+-----------+----+------+---------+---------+----------+
| Generic TEE API | | ASP | Mailbox |
| IOCTL (TEE_IOC_*) | | driver | Register Protocol |
+--------------------------+ +---------+--------------------+
在 x86 的最低级别上,AMD 安全处理器(ASP)驱动程序使用 CPU 到 PSP 邮箱寄存器来向 PSP 提交命令。命令缓冲区的格式对 ASP 驱动程序是不透明的。它的作用是向安全处理器提交命令并将结果返回给 AMD-TEE 驱动程序。AMD-TEE 驱动程序与 AMD 安全处理器驱动程序之间的接口可以在 [6] 中找到。
AMD-TEE 驱动程序打包命令缓冲区有效载荷以在 TEE 中进行处理。不同 TEE 命令的命令缓冲区格式可以在 [7] 中找到。
AMD-TEE 受信任 OS 支持的 TEE 命令包括:
-
TEE_CMD_ID_LOAD_TA - 将受信任应用程序(TA)二进制文件加载到 TEE 环境中。
-
TEE_CMD_ID_UNLOAD_TA - 从 TEE 环境中卸载 TA 二进制文件。
-
TEE_CMD_ID_OPEN_SESSION - 与加载的 TA 打开会话。
-
TEE_CMD_ID_CLOSE_SESSION - 与加载的 TA 关闭会话。
-
TEE_CMD_ID_INVOKE_CMD - 与加载的 TA 调用命令。
-
TEE_CMD_ID_MAP_SHARED_MEM - 映射共享内存。
-
TEE_CMD_ID_UNMAP_SHARED_MEM - 取消映射共享内存。
AMD-TEE 受信任 OS 是在 AMD 安全处理器上运行的固件。
AMD-TEE 驱动程序向 TEE 子系统注册自身,并实现以下驱动程序函数回调:
-
get_version - 返回驱动程序实现 ID 和能力。
-
open - 设置驱动程序上下文数据结构。
-
release - 释放驱动程序资源。
-
open_session - 加载 TA 二进制文件并与加载的 TA 打开会话。
-
close_session - 与加载的 TA 关闭会话并卸载它。
-
invoke_func - 与加载的 TA 调用命令。
AMD-TEE 不支持 cancel_req 驱动程序回调。
全球平台 TEE 客户端 API [5] 可被用户空间(客户端)用于与 AMD 的 TEE 进行通信。AMD 的 TEE 提供了一个安全环境,用于加载、打开会话、调用命令和关闭 TA。
参考资料:
[1] https://github.com/OP-TEE/optee_os
[2] http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
[3] drivers/tee/optee/optee_smc.h
[4] drivers/tee/optee/optee_msg.h
[5] http://www.globalplatform.org/specificationsdevice.asp 寻找 "TEE Client API Specification v1.0" 并点击下载。
[6] include/linux/psp-tee.h
[7] drivers/tee/amdtee/amdtee_if.h
[8] https://trustedfirmware-a.readthedocs.io/en/latest/threat_model/threat_model.html
标签:subsystem,驱动程序,AMD,TEE,tee,ChatGPT,加载,OP From: https://www.cnblogs.com/pengdonglin137/p/17893522.html