引导加载程序与系统组件的安全级别分析
1. 概述
本文档详细分析了ARM架构下,从系统加电到应用程序运行的各个阶段所运行的异常级别(Exception Levels, EL)。包括Trusted Firmware-A (TF-A) 的各个引导阶段、U-Boot、操作系统内核以及应用程序。
2. ARM 异常级别回顾
ARMv8-A 架构定义了四个异常级别,从 EL0 到 EL3,数字越大表示特权级别越高:
| 异常级别 | 描述 | 安全状态 |
|---|---|---|
| EL0 | 应用程序级别 | 非安全世界 |
| EL1 | 操作系统级别 | 非安全世界 |
| EL2 | 虚拟化级别 | 非安全世界 |
| EL3 | 安全监控级别 | 安全世界 (始终) |
3. Trusted Firmware-A 各阶段的安全级别
3.1 BL1 (Boot Loader Stage 1)
- 运行异常级别: EL3(安全世界)
- 功能: 初始启动、基本硬件初始化、加载验证BL2
- 说明: BL1是系统加电后执行的第一个软件,从ROM或引导ROM执行,始终运行在最高特权级别EL3,确保初始引导的安全性。
3.2 BL2 (Boot Loader Stage 2)
- 运行异常级别: EL3(安全世界)
- 功能: 加载后续阶段、更全面的硬件初始化、镜像管理
- 说明: BL2由BL1加载并验证,继续在EL3执行,负责加载和验证BL31、BL32等后续阶段。
3.3 BL2U (Boot Loader Stage 2 Unsecure)
- 运行异常级别: EL2(非安全世界)
- 功能: 加载非安全镜像、为非安全世界初始化做准备
- 说明: BL2U是第一个运行在非安全世界的引导阶段,在EL2执行,主要负责加载非安全的引导镜像,如U-Boot。
3.4 BL31 (Boot Loader Stage 3-1)
- 运行异常级别: EL3(安全世界)
- 功能: 实现安全监视器、提供运行时服务、处理异常和SMC调用
- 说明: BL31是安全监视器的实现,始终运行在EL3,负责处理来自非安全世界的SMC调用,并管理系统的电源状态。
3.5 BL32 (Boot Loader Stage 3-2)
- 运行异常级别: EL1(安全世界)
- 功能: 实现可信执行环境(TEE)、提供安全服务
- 说明: BL32运行在安全世界的EL1,作为可信执行环境,提供各种安全服务,如安全存储、密码学操作等。
4. U-Boot 的安全级别
- 运行异常级别: EL2(非安全世界)
- 功能: 加载操作系统内核、设备初始化、环境配置
- 说明: U-Boot作为非安全世界的引导加载程序,运行在EL2,负责加载和启动操作系统内核。
5. 操作系统内核的安全级别
- 运行异常级别: EL1(非安全世界)
- 功能: 管理系统资源、提供系统调用、运行应用程序
- 说明: 操作系统内核运行在EL1,是应用程序的运行环境,负责管理系统资源和提供各种服务。
6. 应用程序的安全级别
- 运行异常级别: EL0(非安全世界)
- 功能: 执行用户代码、提供用户功能
- 说明: 应用程序运行在最低特权级别EL0,受到操作系统的保护和限制,无法直接访问硬件资源。
7. 启动流程与安全级别切换
7.1 启动流程
- 系统加电→BL1 (EL3)→BL2 (EL3)→BL31 (EL3)
- BL31初始化后:
- 加载并初始化BL32 (EL1 安全世界)
- 跳转到BL2U (EL2 非安全世界)或直接加载U-Boot (EL2 非安全世界)
- U-Boot (EL2)加载并启动操作系统内核 (EL1)
- 操作系统内核 (EL1)启动应用程序 (EL0)
7.2 安全级别切换机制
- 从非安全世界到安全世界: 通过SMC指令陷阱到EL3
- 从安全世界到非安全世界: 通过ERET指令返回
- 从EL0到EL1: 通过系统调用陷阱
- 从EL1到EL2: 通过HVC指令陷阱
8. 安全考虑
- 安全隔离: 不同异常级别之间的隔离确保了系统的安全性
- 权限控制: 高特权级别可以访问低特权级别的资源,反之则不行
- 安全监控: EL3作为安全监视器,确保安全策略的执行
- 链式验证: 引导过程中的链式验证确保了系统的完整性
9. 总结
| 组件 | 运行异常级别 | 安全状态 | 主要功能 |
|---|---|---|---|
| BL1 | EL3 | 安全世界 | 初始启动、硬件初始化、加载BL2 |
| BL2 | EL3 | 安全世界 | 加载后续阶段、硬件初始化、镜像管理 |
| BL2U | EL2 | 非安全世界 | 加载非安全镜像 |
| BL31 | EL3 | 安全世界 | 安全监视器、运行时服务、异常处理 |
| BL32 | EL1 | 安全世界 | 可信执行环境、安全服务 |
| U-Boot | EL2 | 非安全世界 | 加载操作系统内核、设备初始化 |
| 操作系统内核 | EL1 | 非安全世界 | 系统资源管理、提供系统调用 |
| 应用程序 | EL0 | 非安全世界 | 执行用户代码、提供用户功能 |
ARM的异常级别机制为系统提供了多层次的安全架构,通过不同特权级别的隔离和控制,确保了系统的安全性和稳定性。Trusted Firmware-A作为EL3的参考实现,为ARM系统提供了标准化的安全固件,是现代ARM系统安全的基础。
10. 异常级别与安全状态的关系说明
10.1 异常级别与安全状态的区别
需要明确的是,异常级别(EL)和安全状态是两个不同的概念:
- 异常级别(EL): 定义了软件的特权级别,数字越大特权越高
- 安全状态: 定义了软件运行的安全域,分为安全世界和非安全世界
10.2 安全状态与异常级别的组合
ARM架构中,除了EL3始终运行在安全世界外,其他异常级别(EL0-EL2)都可以在安全世界或非安全世界中运行:
| 异常级别 | 安全状态 | 描述 |
|---|---|---|
| EL0 | 非安全世界 | 普通应用程序 |
| EL0 | 安全世界 | 可信执行环境中的应用 |
| EL1 | 非安全世界 | 操作系统内核 |
| EL1 | 安全世界 | 可信执行环境(TEE)内核 |
| EL2 | 非安全世界 | 虚拟化hypervisor |
| EL2 | 安全世界 | 安全世界的hypervisor(较少使用) |
| EL3 | 安全世界 | 安全监视器(始终) |
10.3 为什么BL32运行在EL1安全世界而U-Boot运行在EL2非安全世界
这种设计是合理的,原因如下:
BL32 (TEE) 的设计目标:
- BL32作为可信执行环境(TEE),需要在安全世界中运行
- 但它不需要EL3的最高特权,只需要EL1级别的特权来提供安全服务
- 这样可以在安全隔离的同时,避免过度使用最高特权
U-Boot 的设计目标:
- U-Boot作为非安全世界的引导加载程序
- 运行在EL2可以更好地支持虚拟化功能
- 同时为操作系统内核(EL1)的启动做准备
安全隔离的实现:
- 安全世界和非安全世界的隔离是通过硬件机制实现的
- 即使U-Boot运行在更高的EL2,也无法访问安全世界的资源
- 安全世界的BL32(EL1)受到EL3的保护,不受非安全世界的影响
启动流程的合理性:
- BL31(EL3)作为安全监视器,控制安全状态的切换
- 从安全世界的EL3切换到非安全世界的EL2,符合从高安全级到低安全级的过渡
- U-Boot在EL2准备好环境后,再加载运行在EL1的操作系统内核
10.4 安全状态切换的实现
安全状态的切换主要通过以下机制实现:
- SMC指令: 从非安全世界切换到安全世界(EL3)
- 安全配置寄存器(SCR_EL3): 控制安全状态的访问权限
- 异常向量表: 为不同安全状态和异常级别提供不同的处理程序
这种设计使得系统能够在保持安全隔离的同时,实现不同组件的合理分工和特权管理。
11. 安全世界与非安全世界的区分机制
11.1 硬件基础:ARM TrustZone技术
安全世界与非安全世界的区分主要基于ARM的TrustZone技术,这是一种硬件级别的安全隔离机制:
- 硬件分区:处理器核心、内存系统和外设都支持安全状态的区分
- 安全总线:系统总线支持安全状态的标记和隔离
- 安全外设:某些外设可以被配置为只能由安全世界访问
11.2 寄存器控制机制
安全状态的切换和控制主要通过以下关键寄存器实现:
SCR_EL3 (Secure Configuration Register):
- 控制安全状态的访问权限
- 管理安全和非安全世界之间的切换
- 配置安全中断的处理方式
SPSR_EL3 (Saved Program Status Register):
- 保存从安全世界切换到非安全世界时的状态
- 包含安全状态位,指示返回时的安全状态
ELR_EL3 (Exception Link Register):
- 保存返回地址,用于从安全世界返回非安全世界
HCR_EL2 (Hypervisor Configuration Register):
- 控制EL2和EL1之间的交互
- 影响非安全世界中虚拟化的行为
11.3 内存隔离机制
安全世界和非安全世界拥有独立的内存空间:
- 安全内存:只能由安全世界访问的内存区域
- 非安全内存:可以由非安全世界访问的内存区域
- 内存属性:通过内存管理单元(MMU)设置内存的安全属性
- 地址空间:安全世界和非安全世界可以使用相同的物理地址,但访问权限由安全状态决定
11.4 镜像编译与加载
虽然安全世界和非安全世界的区分主要是硬件和寄存器控制的,但软件层面也需要相应的支持:
独立编译:
- 安全世界的软件(如BL1、BL2、BL31、BL32)需要单独编译
- 非安全世界的软件(如U-Boot、操作系统)也需要单独编译
镜像验证:
- 安全世界的镜像需要经过验证,确保其完整性和真实性
- 非安全世界的镜像也可能需要安全世界的验证
加载位置:
- 安全世界的镜像加载到安全内存区域
- 非安全世界的镜像加载到非安全内存区域
11.5 安全状态切换流程
从非安全世界到安全世界:
- 执行SMC指令
- 处理器自动切换到EL3安全状态
- 安全监视器(BL31)处理请求
从安全世界到非安全世界:
- 设置SPSR_EL3和ELR_EL3寄存器
- 执行ERET指令
- 处理器切换到指定的安全状态和异常级别
11.6 实际实现示例
以Trusted Firmware-A为例:
BL1 (EL3安全世界):
- 初始启动时运行在EL3安全状态
- 加载并验证BL2镜像
BL2 (EL3安全世界):
- 继续在EL3安全状态运行
- 加载并验证BL31、BL32和非安全镜像
BL31 (EL3安全世界):
- 作为安全监视器运行
- 通过设置SCR_EL3等寄存器控制安全状态切换
BL32 (EL1安全世界):
- 由BL31加载到安全内存
- 运行在安全世界的EL1级别
U-Boot (EL2非安全世界):
- 由BL31或BL2U加载到非安全内存
- 运行在非安全世界的EL2级别
11.7 总结
安全世界与非安全世界的区分是通过以下机制实现的:
- 硬件支持:ARM TrustZone技术提供硬件级别的安全隔离
- 寄存器控制:通过SCR_EL3等寄存器控制安全状态
- 内存隔离:安全内存和非安全内存的分离
- 软件配合:独立编译和验证的镜像
- 状态切换:通过SMC指令和ERET指令实现状态切换
这种多层次的安全机制确保了系统的安全性和可靠性,是现代ARM系统安全的基础。