嵌入式系统中的可信执行环境与TrustZone-M技术
1. 嵌入式操作系统与可信执行环境概述
在嵌入式系统领域,了解操作系统的内部机制以及如何为任务提供阻塞调用、驱动API和同步机制至关重要。通过从零开始实现嵌入式操作系统,我们可以深入探索其典型组件。同时,分析流行的开源实时操作系统,如FreeRTOS和Riot OS,能让我们了解不同的设计选择、实现方式以及为应用程序提供的线程和内存管理API。
近年来,微控制器硬件架构引入了域分离机制,这一机制在其他架构中通常被称为可信执行环境(Trusted Execution Environment,TEE)。TEE提供了两个或多个分离的执行域,即“世界”,每个域具有不同的能力和访问设备、资源及外设的权限。这种隔离执行环境的方式,也就是沙箱化(Sandboxing),可以限制软件组件对系统的访问范围,同时不影响其性能和正常运行。沙箱化不仅能提高嵌入式系统的安全性,也是计算机科学中许多用例和领域的需求。
在云计算服务器基础设施中,类似的硬件辅助隔离机制是其构建基础,例如虚拟化扩展和安全隔离机制,允许在同一硬件上同时运行多个“来宾”虚拟机或容器。
2. 技术要求
要运行相关示例,需要一个STM32L552微控制器。TrustZone-M技术仅由最新的ARM Cortex - M微控制器家族支持,而STM32L552是一款Cortex - M33微控制器,完全支持TrustZone-M,是学习该技术的便捷且经济的选择。示例代码文件可在https://github.com/PacktPublishing/Embedded-Systems-Architecture-Second-Edition/tree/main/Chapter11获取。
3. 沙箱化
沙箱化是计算机安全中的一个通用概念,指的是一组硬件和软件措施,用于限制系统中一个或多个组件对系统的“视图”,以限制意外故障或故意恶意攻击对系统的影响范围,并防止其扩散到整个系统。沙箱化有不同的形式和实现方式,可能会利用特定的硬件功能来提高安全性和有效性。
TEE是一种沙箱机制,它要求CPU始终跟踪运行代码的安全状态,同时不会显著影响运行应用程序的性能。由于TEE机制与CPU设计紧密相关,不同平台上的TEE行为、管理和通信模型差异很大,并且严重依赖于架构。此外,TEE通常与密码学结合使用,通过硬件信任根来保护软件的完整性和真实性。
在2005年,英特尔为x86处理器实现了第一个虚拟化指令(Intel VT),通过提供核心组件(CPU、RAM和外设)的硬件辅助虚拟化,实现了隔离虚拟机代码的本地运行。英特尔CPU使用现有的分层保护域(通常称为环)的扩展来限制来宾虚拟机对真实硬件的访问。
除了虚拟机,英特尔软件防护扩展(SGX)也是x86处理器上TEE的一个用例。SGX是许多x86 CPU中存在的一组安全相关指令,用于保护特定的内存区域(即飞地)免受未经授权的访问。虽然这些指令最近已从消费级英特尔CPU中移除,但在云服务器和企业硬件领域的特定微处理器中仍然存在。SGX可用于多种目的,如提供安全的密钥存储库,最初是为了在PC上实现数字版权管理(DRM)而引入的。
后来,AMD为其CPU添加了特定于供应商的架构扩展,形成了名为安全加密虚拟化(Secure Encrypted Virtualization,SEV)的技术。SEV除了为虚拟机提供沙箱外,还使用硬件辅助加密来确保内存页面和CPU寄存器内容的机密性。
ARM在2000年代初开始研究可信计算,并在2003年宣布支持TrustZone技术。现代ARM微处理器,如Cortex - A系列,支持TrustZone - A,实现了安全(S)和非安全(NS)两个独立的世界,非安全世界对实际系统的访问受到限制,而安全世界可以直接访问所有硬件资源。
RISC - V架构的微处理器和微控制器也提供了完整的沙箱,每个硬件辅助容器提供系统可用资源的子集并运行自己的固件。
最新的ARM微控制器家族ARMv8 - M引入了TrustZone - M,它基于现有的TrustZone技术设计,实现了安全和非安全执行域之间的隔离。ARMv8 - M是ARMv7 - M家族的直接演进,后续内容将重点介绍TrustZone - M以及如何在ARMv8 - M微控制器上配置和开发实现TEE的组件。
4. TrustZone - M概述
ARMv7 - M核心,如Cortex - M0+和Cortex - M4微控制器,在嵌入式市场占据主导地位数十年,至今仍是许多嵌入式系统设计的热门选择。新的Cortex - M23、Cortex - M33、M35P和M55核心继承并扩展了Cortex - M0、Cortex - M4和Cortex - M7微控制器的许多成功特性。
在典型的TrustZone用例中,软件开发的不同阶段可能涉及多个参与者。设备所有者可能提供一个基础系统,其中包含所有授权在安全世界运行的软件。系统集成商可以定制非安全部分,但对系统的访问受到安全域配置的限制。系统集成商收到的是一个部分锁定的系统,TrustZone已启用,并且闪存内存受到保护。安全软件监督非安全域中自定义软件的执行,同时保护安全世界中的资源并限制运行应用程序的访问。没有安全执行域授权访问的系统集成商仍然可以在非安全世界运行特权或非特权软件,包括操作系统和设备驱动程序。
相关示例基于引导加载程序示例,由于基于TrustZone的解决方案的软件为两个执行域分别提供二进制文件,因此引导加载程序在安全域执行,应用程序在非安全世界运行,这有助于我们理解构建、配置和运行组件的元素和工具。
5. 参考平台
示例中使用的参考微控制器是STM32L552,它是一款Cortex - M33 CPU,可在Nucleo - 144格式的开发板上找到。STM32L5系列微控制器是旧的STM32F4系列的演进,结合了低功耗模式和高性能,适合作为示例的参考平台。大多数TrustZone - M技术的概念和组件适用于ST Microelectronics和其他芯片制造商提供的ARMv8 - M家族微控制器。
STM32L552ZE的CPU时钟可配置为110 MHz,配备256 KB的SRAM,分为SRAM1和SRAM2两个存储体,映射到不同的区域。512 KB的闪存可以作为一个连续空间使用,也可以配置为两个独立的存储体。
ST微控制器提供了特定于平台的库和工具,但示例基于对文档的理解进行全新实现。唯一的例外是使用STM32编程命令行界面STM32_Programmer_CLI,通过USB电缆将开发板上的ST - Link调试器连接到PC,并运行以下命令可以显示可编程选项字节的当前值:
STM32_Programmer_CLI -c port=swd -ob displ
该工具可用于设置打开和关闭TrustZone所需的选项字节,以及设置分离闪存区域的其他选项。选项字节的值存储在非易失性存储器中,断电后仍会保留。
需要注意的是,修改某些选项字节可能是不可逆的,甚至可能导致设备损坏。在更改任何选项之前,请参考微控制器的参考手册和应用笔记。其中一个选项字节包含TZEN标志,出厂默认情况下应禁用该标志。只有在配置好TrustZone - M后,才能在目标设备上启用它以上传和运行示例。安全世界中的引导加载程序将负责为应用程序设置环境,并在非安全域中执行它。
6. 安全和非安全执行域
在ARMv8 - M家族微控制器中,TrustZone - M通常被称为安全扩展,它在现有线程分离的基础上增加了一层特权分离。类似于操作系统在没有这些扩展时通过MPU设置内存映射区域的访问边界,TrustZone - M增加了安全(S)和非安全(NS)执行域,由CPU控制对单个资源的访问。
在每个执行域内,仍然可以使用基于CONTROL位的现有机制实现特权/线程分离。每个安全世界都有自己的特权和非特权执行模式,在非安全世界运行的操作系统仍然可以使用从ARMv7 - M架构继承的经典特权分离。因此,CPU可以同时遵循四种不同的执行上下文,如下表所示:
| 安全世界 | 非安全世界 |
| — | — |
| 安全特权执行 | 非安全特权执行 |
| 安全线程执行 | 非安全线程执行 |
Cortex - M4提供两个单独的堆栈指针(MSP和PSP)来跟踪线程或内核代码执行时的不同上下文。而在Cortex - M33中,有四个不同的堆栈指针:MSP_S、PSP_S、MSP_NS和PSP_NS,每个堆栈指针在执行时根据当前域和上下文别名到实际的SP寄存器。
当CPU具有MAIN扩展时,ARMv8 - M架构为每个堆栈指针添加了一个对应的堆栈指针限制(SPLIM)寄存器,分别为MSPLIM_S、PSPLIM_S、MSPLIM_NS和PSPLIM_NS。这些寄存器指示四个情况下堆栈指针值的下限,可有效防止堆栈溢出。CPU在运行时会不断检查堆栈是否超过其下限,一旦超过就会生成异常。这种机制比之前在内存管理示例中引入的在堆和栈之间设置保护区域的方法更能有效保护内存。
我们已经了解了如何在执行模式之间切换,以及在系统调用返回时设置或清除CONTROL位在特权和线程执行模式转换中的作用。安全和非安全执行之间的切换通过特定的汇编指令实现,后续将在介绍安全和非安全世界之间的资源分离后进行详细解释。
7. 系统资源分离
当TrustZone - M启用时,内存中映射的所有区域,包括RAM、外设和闪存存储,都会获得新的安全属性。除了安全和非安全域,安全属性还可以是Non - Secure Callable(NSC)。NSC区域用于实现从非安全世界到安全世界的事务,安全域通过NSC区域提供安全API,类似于具有新功能的系统调用。
Cortex - M33微控制器提供了不同级别的保护,这些保护级别共同决定了系统中与资源关联的内存映射区域哪些可供两个执行域访问,哪些只能由安全世界访问。
启用TrustZone - M会复制一些系统资源的表示。例如,通常从地址0x08000000开始映射的闪存内存,在0x0C000000区域有一个别名,用于从安全世界访问相同的存储。许多系统寄存器也有安全和非安全版本,位于不同的内存位置。例如,GPIOA控制器在TrustZone禁用时映射到地址0x42020000,启用TrustZone后,如果非安全世界可以访问该控制器,则非安全域的软件使用该地址,而安全域的软件使用从地址0x52020000开始映射的控制器。
在被其他支持TrustZone的组件处理之前,每个内存访问由安全属性单元(Security Attribution Unit,SAU)和实现定义属性单元(Implementation - Defined Attribution Unit,IDAU)进行监控和过滤。SAU可通过一组寄存器进行配置,而IDAU包含芯片制造商强制执行的硬编码映射。IDAU和SAU的属性组合影响每个内存映射区域的可访问性,具体如下:
- IDAU映射为安全的区域不受SAU属性影响,始终保持安全映射。
- IDAU映射为NSC的区域可以是安全或NSC,取决于SAU属性。
- IDAU映射为非安全的区域将遵循SAU映射。
IDAU和SAU属性的组合及结果映射如下表所示:
| IDAU属性 | SAU属性 | 结果属性 |
| — | — | — |
| 安全 | 安全、NSC或非安全 | 安全 |
| NSC | 安全 | 安全 |
| 非安全 | 安全 | 安全 |
| 安全 | NSC | NSC或非安全 |
| NSC | 非安全 | NSC |
| 非安全 | 非安全 | 非安全 |
在STM32L552参考平台中,IDAU默认强制执行以下关键区域的安全/NSC映射:
- 从地址0x0C000000开始的安全空间中的闪存内存映射。
- 从地址0x30000000开始映射的第二个SRAM存储体SRAM2。
- 地址0x50000000到0x5FFFFFFF之间的内存,用于安全外设的控制和配置。
SAU在复位时将所有区域设置为安全,默认情况下禁用。要执行非安全代码,必须在IDAU配置允许的间隔内定义至少两个非安全区域。
在示例中,我们在启用SAU之前初始化一些内存区域以允许应用程序访问。SAU由四个主要的32位寄存器控制:
- SAU_CTRL(SAU控制):用于激活SAU,包含一个标志用于“反转”SAU过滤器的逻辑,将所有内存区域设置为非安全。
- SAU_RNR(SAU区域编号寄存器):包含在内存区域配置过程开始时要选择的区域编号,后续对SAU_RBAR和SAU_RLAR的写入将引用该编号区域。
- SAU_RBAR(SAU区域基地址寄存器):指示要配置的区域的基地址。
- SAU_RLAR(SAU区域限制地址寄存器):包含要配置区域的结束地址,最低5位保留用于标志。位1为1时表示该区域是安全或非安全可调用的,位0启用该区域并表示其配置完成。
以下是设置SAU区域的示例代码:
static void sau_init_region(uint32_t region,
uint32_t start_addr,
uint32_t end_addr,
int secure)
{
uint32_t secure_flag = 0;
if (secure)
secure_flag = SAU_REG_SECURE;
SAU_RNR = region & SAU_REGION_MASK;
SAU_RBAR = start_addr & SAU_ADDR_MASK;
SAU_RLAR = (end_addr & SAU_ADDR_MASK)
| secure_flag | SAU_REG_ENABLE;
}
在示例中,
secure_world_init
函数调用
sau_init_region
函数来映射四个SAU区域:
- 区域0:非安全可调用部分,存储可从非安全应用程序调用的安全API。在示例中,暴露了一个名为
nsc_blue_led_toggle
的函数,这是应用程序访问连接到Nucleo板上蓝色LED的安全GPIO的唯一方式。
- 区域1:闪存中的非安全区域,从地址0x08040000开始,存储非安全应用程序的代码。
- 区域2:SRAM1存储体中的非安全部分,供非安全应用程序用于堆栈和变量,确保应用程序可以访问RAM地址。
- 区域3:映射在地址0x40000000的非安全外设控制区域,包括非安全GPIO控制器,非安全应用程序可访问该区域来设置系统时钟和控制绿色LED。
以下是SAU初始化的代码:
static void secure_world_init(void)
{
/* Non-secure callable: NSC functions area */
sau_init_region(0, 0x0C001000, 0x0C001FFF, 1);
/* Non-secure: application flash area */
sau_init_region(1, 0x08040000, 0x0804FFFF, 0);
/* Non-secure RAM region in SRAM1 */
sau_init_region(2, 0x20018000, 0x2002FFFF, 0);
/* Non-secure: internal peripherals */
sau_init_region(3, 0x40000000, 0x4FFFFFFF, 0);
/* Enable SAU */
SAU_CTRL = SAU_INIT_CTRL_ENABLE;
/* Enable securefault handler */
SCB_SHCSR |= SCB_SHCSR_SECUREFAULT_EN;
}
通过以上步骤,我们可以在ARMv8 - M微控制器上配置TrustZone - M,实现安全和非安全执行域的分离,并对系统资源进行有效的管理和保护。
嵌入式系统中的可信执行环境与TrustZone - M技术
8. 构建和运行示例
在完成了对TrustZone - M的配置和系统资源的分离后,接下来我们将详细介绍如何构建和运行示例,以更好地理解整个流程。
8.1 示例基础
该示例基于之前提到的引导加载程序示例,软件为安全域和非安全域分别提供二进制文件。引导加载程序在安全域执行,负责为应用程序设置环境,并在非安全域中执行应用程序。
8.2 代码准备
首先,确保已经从指定的代码仓库(https://github.com/PacktPublishing/Embedded - Systems - Architecture - Second - Edition/tree/main/Chapter11)获取了示例代码。然后,根据参考平台(STM32L552)的要求进行必要的配置。
8.3 配置选项字节
使用STM32编程命令行界面STM32_Programmer_CLI来配置选项字节。具体步骤如下:
1. 通过USB电缆将开发板上的ST - Link调试器连接到PC。
2. 打开命令行终端,运行以下命令显示可编程选项字节的当前值:
STM32_Programmer_CLI -c port=swd -ob displ
- 确认其中一个选项字节包含的TZEN标志在出厂默认情况下是禁用的。在配置好TrustZone - M后,使用相应的命令启用该标志,以便上传和运行示例。但要注意,修改某些选项字节可能是不可逆的,甚至可能导致设备损坏,所以在操作前一定要参考微控制器的参考手册和应用笔记。
8.4 编译和上传代码
对安全域和非安全域的代码分别进行编译。编译完成后,使用合适的工具将编译好的二进制文件分别上传到开发板的相应存储区域。安全域的引导加载程序将负责加载和执行非安全域的应用程序。
8.5 运行示例
上传完成后,给开发板上电,系统将按照配置的流程运行。安全域的引导加载程序会进行初始化,为非安全域的应用程序设置环境,然后跳转到非安全域执行应用程序。在运行过程中,可以观察开发板上的LED等外设的状态变化,以验证示例的运行情况。
9. 总结
本文围绕嵌入式系统中的可信执行环境(TEE)和TrustZone - M技术展开了详细的介绍,以下是对关键内容的总结:
-
TEE概述
:TEE是一种提供分离执行域的抽象概念,通过沙箱化限制软件组件对系统的访问范围,提高系统的安全性和可靠性。不同架构的处理器都有各自的TEE实现,如英特尔的VT和SGX、AMD的SEV、ARM的TrustZone等。
-
TrustZone - M技术
:ARMv8 - M家族微控制器引入的TrustZone - M是一种安全扩展,实现了安全和非安全执行域的分离。它在现有线程分离的基础上增加了一层特权分离,为嵌入式系统提供了更高的安全保障。
-
参考平台
:以STM32L552为例,介绍了该平台的硬件特性和相关配置方法。包括CPU时钟、SRAM和闪存的分配,以及如何使用STM32_Programmer_CLI配置选项字节。
-
执行域和资源分离
:详细阐述了安全和非安全执行域的概念和执行模式,以及如何通过TrustZone - M实现系统资源的分离。通过SAU和IDAU对内存访问进行监控和过滤,为不同的内存区域分配安全属性。
-
构建和运行示例
:给出了构建和运行示例的具体步骤,包括代码准备、选项字节配置、编译上传和运行验证等。
通过本文的介绍,我们可以看到TrustZone - M技术在嵌入式系统安全方面的重要作用。在实际应用中,开发者可以根据具体需求,合理配置TrustZone - M,实现安全和非安全执行域的有效分离,保护系统资源免受恶意攻击和意外故障的影响。
为了更清晰地展示整个流程,以下是一个mermaid格式的流程图:
graph TD;
A[获取示例代码] --> B[配置选项字节];
B --> C[编译安全域代码];
B --> D[编译非安全域代码];
C --> E[上传安全域二进制文件];
D --> F[上传非安全域二进制文件];
E --> G[上电运行];
F --> G;
G --> H[观察运行结果];
同时,为了方便大家回顾关键知识点,以下是一个总结表格:
| 关键概念 | 描述 |
| — | — |
| TEE | 提供分离执行域,通过沙箱化提高系统安全性 |
| TrustZone - M | ARMv8 - M家族微控制器的安全扩展,实现安全和非安全执行域分离 |
| 参考平台(STM32L552) | 具有特定的硬件特性,可通过STM32_Programmer_CLI配置选项字节 |
| 执行域 | 包括安全和非安全执行域,每个域有特权和非特权执行模式 |
| 资源分离 | 通过SAU和IDAU监控和过滤内存访问,分配安全属性 |
| 示例流程 | 获取代码、配置选项字节、编译上传、运行验证 |
希望本文能帮助大家更好地理解嵌入式系统中的可信执行环境和TrustZone - M技术,并在实际开发中加以应用。
超级会员免费看
60

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



