文章目录
- 前言
- 可信计算环境TEE
- 嵌入式安全现状
- 现有的TEE分类
- TEE的应用场景
- TEE存在必要性
- TrustZone
- 移动端数据隔离
- 安全/非安全世界
- CPU的特权等级
- TrustZone的结构
- CA与TA通信流程
- TEE安全设计
- 系统总线设计
- 内存隔离机制
- 安全启动机制
- 安全通信机制
- 总结
前言
先引用 《可信计算(Trusted Computing)技术理论与应用研究概述》 一文中的几张图片认识下什么是“可信计算”:
可信计算环境TEE
嵌入式安全现状
多年来,将操作系统分为用户空间和内核空间的传统架构已经取得了许多安全改进。然而,这似乎还不够。开发人员试图尽可能减少内核的攻击面,加强对所有用户控制的数据的验证,但仍然可以发现漏洞,并且利用这些漏洞可以危害整个系统。通过这些观察,研究人员和开发人员想知道如何更好地保护系统,即使内核在启动时或运行时被损坏。
为了解决启动时内核损坏的问题,一个可能的解决方案是安全启动机制,它可以防止在启动加载过程(例如启动加载阶段、操作系统等)期间执行未经授权的代码。安全启动使用不同的阶段来启动系统,每个阶段负责加载、执行和验证下一个阶段的加密签名。但是,使用此过程需要隐式信任第一阶段。通常,供应商将第一组指令直接写入 片上系统(SoC) 芯片 中,使其几乎无法修改。
【SOC】即 System-On-Chip 片上系统,在手机中一般指的是集成了多种功能的一块芯片。我们熟知的骁龙855、麒麟990就是 SOC。骁龙855、麒麟990这样的 SOC,一般集成了很多不同的功能:1)CPU,负责处理计算任务;2)GPU,负责图像渲染;3)基带,负责通信能力;4)ISP,负责处理相机数据;5)DSP,负责解码等功能……你可以看到无论是骁龙855还是麒麟990都集成了非常多的功能,因此一般我们不叫它“CPU”而是叫它“SOC”。
可以使用能够监视同时运行的多个操作系统的虚拟机管理程序(Hypervisor)来减轻运行时损坏,如下图所示。虚拟机管理程序可以检测危害并确保在其监督下运行的系统受到保护。
然而,管理程序(Hypervisor)和客户操作系统都共享相同的物理内存。这些环境之间的分离仅通过软件机制来实现。在这种范式下,无法防止虚拟机逃逸、虚拟机管理程序损坏等安全问题。考虑到这些限制,系统的可能增强是在硬件级别隔离所有组件,从而创建 可信执行环境 TEE(Trusted Execution Environment)。这些安全可信的环境使用系统范围的硬件隔离机制来分离 CPU 和其他外设的资源。TrustZone 是 ARM 架构实现的 TEE,下面将详细介绍。与此同时,下图概述了全系统保护的演变。
Hypervisor 是一种运行在物理服务器和操作系统之间的中间软件层,在 Guest 机器和 Host 机器中间加一层 Hypervisor,可允许多个操作系统和应用共享一套基础物理硬件。它主要是在 Guest OS 和硬件之间捕捉和处理那些对虚拟化敏感的 CPU 特权指令。更多信息参见:虚拟化技术介绍 & hypervisor简介。
现有的TEE分类
市场上可以找到多种 TEE,但它们可以分为以下两类:
- 用于桌面平台的 TEE,例如 Intel SGX。由于桌面不是本文的主要主题,因此不会详细介绍这些实现。
- 移动平台上使用的 TEE,例如 TrustZone、SEP、Titan M 等。
其中移动平台上的 TEE 可以细分为几种实现选择:
- 虚拟处理器实现,例如 ARM TrustZone,其中 CPU 和硬件资源在安全状态和非安全状态之间共享;
- On-Soc 处理器实现,例如 Apple SEP,其中两个 CPU(一个安全,一个非安全)共享硬件资源;
- 外部协处理器实现,例如 Google Titan M,位于 SoC 外部,无法访问 SoC 内的硬件资源。
以上引用自:A Deep Dive Into Samsung’s TrustZone (Part 1)。本文将仅关注 ARM TrustZone 技术。
TEE的应用场景
以下介绍 TrustZone 架构下的移动端 TEE 技术应用场景。TEE 支持很多用途,例如移动支付、数字版本保护 DRM、安全银行、多重身份验证、设备重置保护、抗重放攻击的持久存储、安全 PIN 和指纹处理、人脸识别,甚至还能用于恶意软件检测。
指纹安全识别场景
如下图是 Android上 的指纹软件框架,REE 环境下主要分为APP,Framework,HAL 和 Linux kernel。APP主要负责指纹录入解锁调用逻辑,Framework 主要负责回调 HAL 层相关函数,HAl 层负责和硬件以及指纹 TA 交互。而 TEE 主要是指纹 TA,指纹 TA 负责控制指纹 sensor 和执行指纹算法相关函数。
- Fingerprint TA:主要进行基本操作,比如控制 finger sensor 采图,特征提取,指纹算法处理等操作;
- Finger CA:负责与 Fingerprint TA 进行通信,发送指令,向 Fingerprint HAL 提供 REE 与 TEE 的通信接口;
- Secure SPI driver:TEE 与指纹 sensor 通信的 SPI 安全驱动;
- Finger lib:指纹算法库,主要是对指纹图像特征提取比对等算法实现;
- Fingerprint HAL:指纹 Hal,调用 CA 的接口向 TA 下发指令,同时通过Fingerprint Device Driver 实现对 GPIO、Power、INT 等管脚和功能控制;
- Fingerprint service:指纹 Framework,回调 Hal 层相关函数,控制指纹录入解锁等流程;
- App:指纹最上层的代码,主要是负责指纹录入解锁调用逻辑。
Hal 中指纹的录入流程为:指纹 sensor 初始化(begin enroll)-> 采图(do capture) -> 录入(do enroll) -> 结束录入(do enroll) -> 指纹模板存储(store template)。
对应 TA 的录入流程为:指纹sensor init(begin enroll)-> 采图(capture image)-> 将采集的指纹数据传输回TA -> 录入(do enroll) -> 结束录入(end enroll) -> 模板加密存储到secure memory(encrypt)。
HAL 中主要进行的是与 TA 交互,给 TA 发送指令,同时还会对指纹硬件进行操作,比如指纹 sensor 上下电等。TA 收到 CA 的command,则需要处理敏感数据和一些安全性要求高的动作,如 TA 通过 secure spi 控制指纹 sensor 采图,图像传输,图像处理,图像比对,模板存储等。这些都是在 TEE 环境下进行操作的,所以指纹解锁是一种相对比较安全的解锁方式。
指纹传感器和 TEE 之间建立安全通道,指纹信息通过安全通道传递到 TEE 中,REE 侧无法获取。指纹图像信息采集、特征提取、活体检测、特征比对等处理完全在TEE中,基于 TrustZone 进行安全隔离,REE 的指纹框架只负责指纹的认证发起和认证结果等数据,不涉及指纹数据本身。指纹特征数据通过 TEE 的安全存储进行存储,采用高强度的密码算法进行数据加密和完整性保护。同时具备以下特点:
- 外部无法获取到加密指纹数据的密钥,保证用户的指纹数据不会泄露;
- 外部第三方应用无法获取到指纹数据,也不能将指纹数据传出TEE;
- 系统不会将任何指纹数据发送或备份到包括云端在内的任何外部存储介质。
人脸识别场景
系统在摄像头和 TEE 之间建立安全通道,人脸图像信息通过安全通道传递到 TEE 中,REE 侧无法获取。系统对人脸图像采集、特征提取、活体检测、特征比对等处理完全在TEE 中,基于 TrustZone 进行安全隔离,外部的人脸框架只负责人脸的认证发起和认证结果等数据,不涉及人脸数据本身。
人脸特征数据通过TEE 的安全存储进行存储,采用高强度的密码算法对人脸特征数据进行加解密和完整性保护。外部无法获取到加密人脸特征数据的密钥,保证用户的人脸特征数据不会泄露。同样的具备以下特点:
- 外部无法获取到加密指纹数据的密钥,保证用户的指纹数据不会泄露;
- 外部第三方应用无法获取到指纹数据,也不能将指纹数据传出TEE;
- 系统不会将任何指纹数据发送或备份到包括云端在内的任何外部存储介质。
安全支付场景
为保证支付安全,在硬件层面,系统提供支付指纹信息的硬件加密与银行卡信息的安全存储,实现支付信息的物理隔离;在系统软件层面,发起支付时系统,会自动检测支付环境是否安全可靠。同时,付款交易过程只在用户、商户和发卡机构之间发生,云端服务在支付过程中并不会收集用户的任何交易信息。
安全元件(Secure Element,SE) :是业内公认的、运行 Java Card 平台的认证芯片,它符合金融行业对电子支付的强制要求。
TEE存在必要性
以指纹识别为例:在未被 Root 的设备上,应用开发只能接触到 Framework 的生物识别认证 API 层级。在一个被 Root 的设备上,威胁来自于 REE 所有的方面。实现 Framework API 的系统底层实现服务不能确保安全,Android Kernel 层的内核驱动也不能确保安全,即右侧红色部分。
Android 系统被 Root 后,只有 TEE 环境可信,相关关键、敏感数据、密钥数据等都在 TEE 环境安全加密存储。相关涉及 TEE 的业务在和 TEE 中 TA 交互时,TA 可检测到 Android 环境被 Root 从而决定是否继续执行逻辑。
因此我们可以认为,即使是 Android 设备被 root 的情况下,存储在 TEE 中的数据也不应该被访问到!换句话讲,TEE 的安全研究、攻击测试均可以基于 Root 前提下进行!
TrustZone
随着 Face ID、指纹识别、5G、AI 等技术的发展,移动互联网已经悄然根植于现代生活中,伴随着日常生活的移动化,移动终端中存储的各种敏感信息日益增多,移动终端自身的安全性面临着巨大的挑战。
移动端系统运行的环境叫做 REE(Rich Execution Environment),在其中运行的系统叫做 Rich OS(Operating System),比如最常见的 Android、IOS 等通用 OS 系统,但是 REE 是一个开放的环境,容易受到恶意软件的攻击,基于 OS 实现的 App 隔离极易被绕过且漏洞频发,比如敏感数据被窃取、数字版权被滥用、移动支付被盗用等。
因此在2010年7月,GP(Global Platform,全球平台组织)提出了 TEE(Trusted Execution Environment) 可信执行环境的设计。TEE 是一个与 REE 并存运行的独立执行环境,它具有其自身的执行空间,比 Rich OS 的安全级别更高,为 Rich OS 提供安全服务,如指纹的录入比对、支付校验认证等操作。TrustZone 是移动端 ARM 架构实现的 TEE。
移动端数据隔离
在介绍 TrustZone 前有必要简单回顾下目前的一些安全手段。
CPU 通过内存映射手段给每个进程营造一个单独的地址空间来隔离多个进程的代码和数据,通过内核空间和用户空间不同的特权级来隔离操作系统和用户进程的代码和数据。但由于内存中的代码和数据都是明文,容易被同处于内存中的其它应用偷窥,因此出现了扩展的安全模块,应用将加密数据送往安全模块,由安全模块处理完后再返回结果给相应的应用。
很多消费电子设备都使用扩展的安全模块来确保数据安全,目前常见的方式有:
- 外部挂接硬件安全模块
数据的处理交由外部的安全模块实现,这些模块能够保护自己的资源和密钥等数据的安全,如SIM卡、各种智能卡或连接到外部的硬件加解密模块等,但其同主芯片的通信线路暴露在外部,容易被监听破解。另外,通信的速率比较低。 - 内部集成硬件安全模块
将外部安全模块的功能集成到芯片内,因此一个芯片上至少有两个核:一个普通核和一个安全核。优点是核与核之间的通信在芯片内部实现,不再暴露在外面。缺点是核之间的通信速度仍然较低,而且单独的安全核性能有限,还会会占用 SoC 面积,成本较高。
【说明】下文讨论的 TEE 均指的是 ARM 架构下的 TrustZone。
安全/非安全世界
TrustZone 是通过将 CPU 分为 安全世界(Secure World) 和 非安全世界(Normal World) 来实现的系统范围的硬件隔离。
- 正常世界:也称为 Rich OS(例如 Android、GNU/Linux 等),用户主要与之交互并执行所有非敏感任务。该操作系统在设计上是不可信的,因此从正常世界传递的所有数据在使用前都应进行彻底检查。
- 安全世界:它运行可信代码并存储/处理敏感数据,所有需要保密的操作在安全世界执行,如指纹识别、密码处理、数据加解密、安全认证等。
简单而言,TrustZone 的工作原理是引入一种 “安全” 模式,CPU 可以在该模式下运行。当在这种新模式下运行时,CPU 可以访问设备的所有硬件和内存。当在非 TrustZone(“正常” )模式下运行时,只能访问外设的子集和特定范围的物理内存。TEE 可以利用这项技术将自己的代码和数据放入这个“安全内存”中,防止任何在“正常模式”下运行的代码访问或修改它,即使该代码正在内核中运行。虽然内核无法访问 TEE 内存,但 TEE 中运行的代码可以读取、修改和选择处理正常世界中的数据。
为了让 CPU 知道它是运行在安全状态还是非安全状态,ARM 架构使用 安全配置寄存器(SCR) 的最低有效位。由于分离是有效的,系统现在需要在两个世界之间建立安全的通信方式。为了满足这个要求,ARM 引入了Monitor Mode,负责安全世界和非安全世界之间的切换。它以最高 ARM 执行级别在安全状态下运行。
进入监控模式有多种方法。从非安全世界中,可以使用 SMC (Secure Monitor Call )指令、通过中断或引发外部中止异常来输入它,如下图所示。
在处理器架构上,TrustZone 将每个物理核虚拟为两个核,一个非安全核(Non-secure Core, NS Core),运行非安全世界的代码;和另一个安全核(Secure Core),运行安全世界的代码。两个虚拟的核以基于时间片的方式运行,根据需要实时占用物理核,并通过 Monitor Mode 在安全世界和非安全世界之间切换。
CPU的特权等级
TrustZone 还扩展了 CPU 的标准“异常级别”权限模型。在 TrustZone 之前,存在三个级别:EL0(用户模式)、EL1(内核模式)和 EL2(管理程序模式)。
- 在 REE 中,我们的 Android 应用程序在 EL0 上运行,而 Linux 内核则在 EL1 上运行;
- EL2 仅以非安全模式存在(在 ARMv8.4-A 版本之前),称之为管理程序(Hypervisor)。它最初被设计为一种处理以较低特权级别并行运行的多个虚拟环境的方法,但是在 Android 环境中,通常将其用作内核加固机制,它还限制了内核可以访问的内存,并将某些内核结构设置为只读,从而增加了内核漏洞利用的难度。
TrustZone 添加了新的 EL3(安全监控模式),这是最高特权级别并控制整个系统。但 TrustZone 还允许 CPU 以较低权限运行在安全模式下,从而允许 TEE 本身内部进行权限隔离。因此,CPU 还可以在 S-EL0(安全用户模式)和 S-EL1(安全内核模式)下运行。
- S-EL3 运行安全监视器的代码,这是 CPU 的最高权限级别。安全监视器运行设备制造商提供的 Arm 可信固件 (ATF)中的代码。此代码在丰富执行环境 (REE) 和 TEE 内核之间执行上下文切换,并通过安全监视器调用 (SMC) 处理程序向两者提供基本服务,REE 和 TEE 操作系统可以通过 SMC 指令请求该处理程序。
- S-EL1 运行可信执行环境操作系统的代码。根据 TEE 实现,可信驱动程序也可以作为 S-EL1 运行。Secure World (SWd) 中不存在 EL2 等效项,因此不可能在 SWd 内的虚拟机管理程序中运行多个虚拟 TEE 操作系统。
- S-EL0 运行非特权的“可信应用程序”(TA),在某些 TEE 实现中甚至运行 TEE 内的可信驱动程序 (TD)。默认情况下,除非 TEE 操作系统明确允许,否则 TA 不能在其他 TA 的上下文中运行、直接与设备外设通信或与正常世界 (NWd) 或安全世界 (SWd) 中的其他进程交互。
虽然完全隔离的环境非常安全,但要使其实用,它需要与 Android 中运行的其他不受信任的组件进行通信。REE 和 TEE 之间的通信是使用名为 “安全监控调用” (SMC) 的专用指令触发的。该指令可以在 EL > 0 时被两个世界调用,这意味着 Android 应用程序无法直接发起与安全 TEE 的通信。通常发生的情况是,Linux 内核充当代理并公开可供应用程序用来与 TEE 交互的驱动程序。这种设计的优点是可以应用访问限制策略(例如使用SELinux)来访问驱动程序,以便只有一部分应用程序可以与TEE通信,从而限制了攻击面。
一旦执行了 SMC 指令,EL3 中运行的安全监视器就会生成中断。SMC处理机制将 SMC 路由到组件来处理它。如果监视器可以直接处理 SMC,它会直接处理并立即返回。否则,它将请求转发到 TEE 内核(在 S-EL1 上运行),然后 TEE 内核可以在内部处理该请求或进一步将其转发到在 S-EL0 上运行的 TA。
TrustZone的结构
TrustZone 的组成结构如下图所示:
REE中的系统结构:
组成结构 | 作用 |
---|---|
CA(Client APP) | 对应一些上层应用,比如指纹采集、支付应用等,通过调用 TEE Client API 实现与 TEE 环境的交互 |
REE Communication Agent | 为 TA 和 CA 之间的消息传递提供了 REE 支持 |
TEE Client API | 是 REE中 的 TEE 驱动程序提供给外部的接口,可以使运行在 REE 中的 CA 能够与运行在 TEE 中的 TA 交换数据 |
TEE中的系统结构:
组成结构 | 作用 |
---|---|
TA(Trusted Application) | 是TEE中完成特定功能的应用。由于 TEE 中完成计算因此具有较高的安全性。每一个 TA 在 REE 中有一个或者多个对应的 CA,在 REE 环境中可以通过调用 CA 的接口,将信息传送到 TEE 环境中执行 TA,完成对应功能然后返回计算结果 |
TEE Communication Agent | 是可信操作系统的特殊组成部分,它与 REE Communication Agent 一起工作,使 TA 与 CA 之间安全地传输消息 |
TEE Internal Core API | 是TEE操作系统提供给 TA 调用的内部接口,包括密码学算法,内存管理等功能 |
Trusted Device Drivers | 可信设备驱动程序,为专用于 TEE 的可信外设提供通信接口 |
Shared Memory | 是一块只有CA和TA可以访问的一块安全内存,CA和TA通过共享内存来快速有效传输指令和数据 |
注意,TA 应相互隔离并与 TEE 内核隔离,以便受感染的应用程序无法危及其他应用程序或 TEE 内核。简而言之,稳健的 TEE 有望实现三种类型的隔离:
- TA 之间的隔离;
- TEE 和 REE 之间的隔离;
- TA 和 TEE 内核之间的隔离。
系统总线 AMBA3 AXI (AMBA3 Advanced eXtensible Interface) 作为 TrustZone 的基础架构设施,提供了安全世界和非安全世界的隔离机制,确保非安全核只能访问非安全世界的系统资源,而安全核能访问所有资源,因此安全世界的资源不会被非安全世界(或普通世界)所访问。
从设计上,TrustZone 并不是采用一刀切的方式让每个芯片厂家都使用同样的实现。总体上以 AMBA3 AXI 总线为基础,针对不同的应用场景设计了各种安全组件,芯片厂商根据具体的安全需求,选择不同的安全组件来构建他们的 TrustZone 实现。其中主要的组件有:
必选组件 | 可选组件 |
---|---|
AMBA3 AXI总线,安全机制的基础设施 | TZMA (TrustZone Memory Adapter),片上ROM或RAM安全区域和非安全区域的划分和保护 |
虚拟化的ARM Core,虚拟安全和非安全核 | AXI-to-APB bridge,桥接APB总线,配合TZPC使APB总线外设支持TrustZone安全特性 |
TZPC (TrustZone Protection Controller),根据需要控制外设的安全特性 | 除了以上列出的组件外,还有诸如 Level 2 Cache Controller, DMA Controller, Generic Interrupt Controller等 |
TZASC (TrustZone Address Space Controller),对内存进行安全和非安全区域划分和保护 | N/A |
CA与TA通信流程
CA 与 TA 交互的整体流程如下:
- CA 首先调用 TEE Client API 触发系统调用,进入 REE 的操作系统内核态,根据 CA 调用的参数找到对应的 REE 驱动程序;
- REE 驱动程序通过调用 SMC 汇编指令进入 Monitor 模式,并将处理器切换到安全内核状态,进入安全模式;
- 切换进入 TEE 以后,CA 的服务请求通过总线传到 TEE 侧,然后 TEE OS 通过 TEE Internal API 调用对应的 TA;
- 最后 TA 运行结束后将运行结果和数据返回给 CA,执行完以后回到
TEE 内核态调用 SMC 汇编指令进入 Monitor 切回 REE 环境。
CA 与 TA 通信需要使用下列接口完成整个会话流程:
CA侧接口如下:
CA接口 | 作用 |
---|---|
TEEC_InitializeContext | 对变量 Context 进行初始化配置,用来建立 CA 和 TEE 的联系,向 TEE 申请共享内存地址用于存放数据 |
TEEC_OpenSession | 建立一个 CA 和 TA 间的 session,用于 CA 和 UUID 指定的 TA 进行通信,是 CA 连接 TA 的起始点 |
TEEC_InvokeCommand | 依靠打开的session,将传送命令请求给TA,并将必要的指令执行参数一并发送给TA |
TEEC_CloseSession | 关闭session,关闭CA和TA之间的通道 |
TEEC_FinalizeContext | 释放Context,结束CA与TEE的连接 |
TA侧接口:
TA接口 | 作用 |
---|---|
TA_CreateEntryPoint | 为 CA 建立接入点,使得 TA 可以被 CA 调用 |
TA_DestroyEntryPoint | 移除 CA 的接入点,结束 TA 的功能 |
TA_OpenSessionEntryPoint | 建立 CA 与 TA 之间的通讯通道,作为 CA 连接 TA 的起点 |
TA_InvokeCommandEntryPoint | 接收CA传送的指令和参数,并在这TEE侧执行 |
TA_CloseSessionEntryPoint | 关闭CA与TA的通讯通道 |
在 GP 标准中,CA 要与 TA 进行通信,需要建立如下所示的软件逻辑流程:
- 首先 CA 需要与 Trusted OS 之间建立一个 Context,以后此 CA 与 TEE 环境的所有通信均基于此 Context;
- 然后 CA 会向 Trusted OS 申请与请求的 TA 建立一个 Session;
- CA 与 TA 之间的 Session 建立完成后,CA 就可以向 TA 发送 Command;
- Command 及其参数会通过共享内存的方式传递,TA 从共享内存中获取到 CA 的请求以及请求参数;
- TA 在 TEE 环境下执行处理,得到的处理结果重新填充到共享内存中,CA 通过共享内存就可以获取到处理结果;
- 获得处理结果后,如不需要进一步请求,则由 CA 发起关闭 Session 的请求,Trusted OS 回收 TA 相关资源,最后 CA 发起销毁 Context 的请求,完成一次完整交互。
整个通信流程如下图所示:
TEE安全设计
了解完 TrustZone 的基本架构后,下面来看看 TrustZone 的相关安全机制和设计。
系统总线设计
设计上,TrustZone 在系统总线上针对每一个信道的读写增加了一个额外的控制信号位,这个控制位叫做 Non-Secure 或者 NS 位,是 AMBA3 AXI 总线针对 TrustZone 作出的最重要、最核心的扩展设计。
这个控制信号针对读和写分别叫做 ARPORT[1] 和 AWPORT[1]:
- ARPROT[1]: 用于读操作(Read transaction),低表示 Secure, 高表示 Non-Secure
- AWPROT[1]: 用于写操作(Write transaction),低表示 Secure,高表示 Non-Secure
总线上的所有主设备 (master) 在发起新的操作 (transaction) 时会设置这些信号,总线或从设备 (slave) 上解析模块会对主设备发起的信号进行辨识,来确保主设备发起的操作在安全上没有违规。
例如:硬件设计上,所有非安全世界的主设备(Non-Secure masters)在操作时必须将信号的 NS 位置高,而 NS 位置高又使得其无法访问总线上安全世界的从设备(Secure Slaves),简单来说就是对非安全世界主设备发出的地址信号进行解码时在安全世界中找不到对应的从设备,从而导致操作失败。
内存隔离机制
除了 CPU 执行时实行安全世界和非安全世界的隔离外,AMBA3 AXI 总线提供了外设隔离的基础。
内存隔离机制
-
TZASC
为了严格限制来自不受信任代码和外设的受 TrustZone 保护的代码和数据,TrustZone 访问空间控制器 (TZASC) 硬件允许将物理内存的特定区域标记为“仅安全”。这些 TrustZone 域是通过TZASC 寄存器设置的,这些寄存器由设备上的Arm 可信固件(ATF)配置。更改访问表内的起始或结束地址是一项特权操作,必须小心执行;错误配置可能允许不受信任的内存访问 TrustZone 内使用的物理内存区域。 -
页表
与 NWd 中一样,SWd 内核和程序可以拥有自己的地址空间,这些地址空间通过称为页表的稀疏查找表进行管理。这些页表使 MMU 能够在 CPU 使用的虚拟地址与其相应的物理页之间执行快速转换,并在访问内存时执行权限检查。 -
虚拟 MMU
在 TrustZone 架构中,每个 CPU 都有两个虚拟 MMU,一个管理 SWd 地址空间,另一个管理 NWd 地址空间,每个虚拟 MMU 都有自己相应的TTBRx 寄存器。这意味着两个世界的操作系统都可以独立创建和管理自己的一组虚拟页表以供其自身及其各自的进程使用。 -
非安全内存
TrustZone 页表可以将特定虚拟地址标记为“非安全”。这是通过设置相应虚拟地址页表项 (PTE) 中的 NS 位来完成的。SWd 代码可以使用它来将 NWd 内存的视图映射到它自己的(或 TA 的)地址空间,该地址空间可用于监视 NWd 或与 NWd 通信。在NWd中,PTE中的NS标志被忽略;来自 NWd 的所有内存访问都被视为不安全。
外设隔离机制
外设上,基于 APB 总线的设备不支持 AXI 总线的 NS 控制信号,所以 AXI 到 APB 总线需要 AXI-to-APB bridge 设备连接,除此之外,还需要TZPC (TrustZone Protection Controller) 来向 APB 总线上的设备提供类似 AXI 上的 NS 控制信号。
由于 TZPC 可以在运行时动态设置,这就决定了外设的安全特性是动态变化的,例如键盘平时可以作为非安全的输入设备,在输入密码时可以配置为安全设备,只允许安全世界访问。
安全启动机制
AMBA3 AXI 总线机制隔离出安全世界和非安全世界,但这是系统启动之后的事情。如何确保系统本身是安全的呢?这就涉及到系统启动的过程。
系统上电复位后,先从安全世界开始执行。安全世界会对非安全世界的 bootloader 进行验证,确保非安全世界执行的代码经过授权而没有被篡改过。然后非安全世界的 bootloader 会加载非安全世界的 OS,完成整个系统的启动。在非安全系统的 bootloader 加载 OS 时,仍然需要安全世界对 OS 的代码进行验证,确保没有被篡改。下图是典型的 TrustZone 芯片的启动流程:
简单来说,安全启动是防止在启动过程中加载并运行未经授权应用的安全机制。启动程序通过签名公钥验证软件的数字签名,确保软件的可信性和完整性。只有通过签名校验的镜像文件才可以加载运行,这些文件包括启动引导程序、内核镜像、基带固件等镜像文件。在启动过程的任何阶段,如果签名验证失败,则启动过程会被终止。
片内引导程序(ROM SoC Bootloader)执行基本的系统初始化,从 Flash 存储芯片中加载二级引导程序(Flash Device Bootloader)。使用保存在主芯片内部 Fuse 空间(熔丝工艺,一旦熔断不可更改)的公钥哈希对公钥进行验证后,片内引导程序再利用公钥对二级引导程序镜像的数字签名进行校验,成功后运行二级引导程序。二级引导程序加载、验证和执行下一个镜像文件。以此类推,直到整个系统启动完成,从而保证启动过程的信任链传递,防止未授权程序被恶意加载运行。
安全通信机制
使用 TA 的应用程序(例如移动支付应用程序)需要一种机制来在 REE 中的 NWd 应用程序和 TEE 中的 TA 之间进行通信。为此,REE 中的应用程序会经历一个加载过程,通过 REE 和 TEE 可用的特定通信通道和 API 与 TEE 内的 TA 进行通信。
-
基于 SMC 的通信
TEE 中的可信代码和 REE 中的代码之间的通信必须通过两种机制之一进行。第一种机制是使用SMC 接口。在 EL1(或 EL2,如果正在使用虚拟机管理程序)上运行的 REE 操作系统可以使用安全监视器调用(SMC) 指令从 S-EL3 内运行的安全监视器请求系统服务,然后将其转发到 TEE操作系统。 -
特定于硬件的服务
除了提供允许 EL0 应用程序加载并与 S-EL0 可信应用程序通信的服务之外,TEE 通常还会提供特定于硬件和 TEE 的服务,这些服务可以直接由 EL1 中的 NWd 操作系统代码使用。例如,TEE 可能提供创建看门狗定时器的机制,以便在设备无响应时重新启动设备、与板载 SoC 交互或在 NWd 和 SWd 之间共享内存。在 S-EL3 和 S-EL1 中运行的安全代码提供可以使用 SMC 指令请求的这些服务。该指令具有特权,必须从 EL1 调用,并由安全监视器的 SMC 调度处理程序处理。 -
共享内存通信
第二种通信方法是利用共享内存,即在 NWd 中运行的代码将一些物理内存映射到它的地址空间,而 TEE 内部的代码将相同的物理内存地址映射到它自己的地址空间,注意将内存标记为“不安全”。从任一世界写入此共享内存缓冲区的内存对于两个进程都是可见的。共享内存是一种有效的通信形式,因为它允许在 TrustZone 之间快速传输大量数据,而无需上下文切换。
最后,请思考一个问题:为什么安全模式和非安全模式不能直接切换?
答案:非安全世界无权访问 CP15 的 SCR 寄存器,所以无法通过设置 NS 来直接切换到安全世界,只能先转换到 Monitor Mode,再到安全世界。但如果软件运行在安全世界 (非Monitor Mode) 下,通过将 CP15 的 NS 位置1,安全世界可以直接跳转到非安全世界,由于此时 CPU 的流水线和寄存器还遗留了安全世界的数据和设置,非安全模式下的应用可以获取到这些数据,会有极大的安全风险。因此,只建议在 Monitor Mode 下通过设置 NS 位来切换到非安全模式。
综上,安全世界和非安全世界不存在直接的切换,所有切换操作都通过 Monitor Mode 来执行。
总结
本文介绍了可信计算的基本概念、可信计算环境(TEE)的产生和应用,并详细介绍了 Android 移动端基于 TrustZone 架构实现的 TEE 的框架设计、安全机制等。显然仅了解这些信息是不足以支撑对 TEE 进行漏洞挖掘的理论基础的,本文的目标也仅仅是从一个小白的角度了解 TEE 的基础知识。后续如果想深入挖掘、研究 TEE 安全漏洞的话,需进一步参照业界已有的案例和材料。
本文参考文章与更多资源:
- 一篇了解TrustZone;
- TEE安全攻防之内存隔离;
- TEE原理及应用举例(内核工匠);
- Android可信执行环境TEE最全介绍;
- Github上对TEE各种网络资源的整合汇总;
- BlackHat:Breaking Samsung’s ARM TrustZone;
- Shedding Light on Huawei’s Security Hypervisor;
- trusted-execution-environments-tee-and-trustzone;
- 《手机安全与可信应用开发指南:TrustZone和OP-TEE技术详解》读书笔记。