[译] 安全引导与镜像验证技术概览
免责声明
本文是对原文档《Secure Boot and Image Authentication Technical Overview》的无授权翻译,不享受任何著作权利,不用于任何商业目的,不以任何许可证进行授权,不对任何转载行为尤其是商业转载行为负责。一切权利均由原著作权所有者高通公司(QTI,Qualcomm Technologies, Inc.)保有。
本文中出现的所有第一人称均指代高通公司。本文中对一些术语会额外附加英文原文注释,以帮助读者搜索相关概念。
高通公司原免责声明如下:
Qualcomm Snapdragon, Qualcomm Trusted Execution Environment and Qualcomm Hypervisor Execution Environment are products of Qualcomm Technologies, Inc. and/or its subsidiaries.
Qualcomm and Snapdragon are trademarks of Qualcomm Incorporated, registered in the United States and other countries. Other products and brand names may be trademarks or registered trademarks of their respective owners. The contents of this document are provided on an “as-is” basis without warranty of any kind. Qualcomm Technologies, Inc. specifically disclaims the implied warranties of merchantability and fitness for a particular purpose.
Qualcomm Technologies, Inc.
5775 Morehouse Drive
San Diego, CA 92121
U.S.A.
©2019 Qualcomm Technologies, Inc. and/or its affiliated companies.
All Rights Reserved.
概览
安全引导(Secure Boot)为设备的安全架构奠定基础。从技术上讲,安全引导被定义为一个引导序列,每一个在设备上加载和执行的软件镜像,都使用上一个由该系统验证的软件镜像来验证。这一序列被设计为通过确保所有代码在执行之前都要被检查来防止执行未经验证的或修改过的代码。
此“信任链(Chain of Trust)”中的第一个镜像称为主引导加载程序(PBL,Primary Boot Loader)。主引导加载程序存储在不可变的只读存储器中;它实际上是每个芯片结构的一部分。用户可以信任该镜像没有被改变,因为它不能被物理修改。此初始软件镜像以加密方式验证它所加载的镜像上的数字签名,这些镜像以加密方式验证它们加载的下一组镜像上的数字签名,以此类推。因此,用户可以确信这些镜像没有被更改,因为在任何情况下,一个受信任的软件都会在新镜像可以被执行之前对其进行检查。
在最新版本的 QTI 的安全引导功能中,PBL 会加载如图 1 所示的两个镜像:
- 一个用于协调加载富执行环境(REE,Rich Execution Environment)的扩展引导加载程序(XBL,eXtensible Boot Loader)。其包含操作系统内核和外围固件镜像。该软件镜像链运行在与操作系统内核相同的异常等级上。
- 一个用于协调加载可信执行环境(TEE,Trusted Execution Environment)的高度可信的安全扩展引导加载程序(XBL_SEC)。这包括 Qualcomm® 可信执行环境(Qualcomm TEE)镜像和相关镜像。
在加载过程中隔离 TEE 镜像的目的是通过缩短在 Qualcomm TEE 镜像运行之前必须加载、验证和执行的镜像链来提高安全性。从本质上讲,它减少了 Qualcomm TEE 镜像被破坏的机会。TEE 中的镜像可能由 Qualcomm Technologies 和设备制造商同时进行数字签名,这种“双重签名”旨在提高所有依赖方对所执行的 Qualcomm TEE 镜像的信任。我们的目标是保障受 Qualcomm TEE 保护的关键资产,例如用户数据加密密钥和支付应用程序身份验证密钥,即使在低可信环境中遭到破坏的情况下也是如此。
所有镜像都使用标准 ELF(Executable and Linkable Format)。 一个 ELF 镜像由一些单独的 ELF 段组成,这些段可能包含有关镜像的代码、数据或元数据(Metadata)。用于验证该镜像的数据包含在 ELF 文件中的一个特殊段中,称为哈希段(Hash Segment)。
哈希段包含加密哈希值表和有关镜像的元数据集合。表中的加密哈希值是由 ELF 镜像中的其余段计算出来的,用于在将这些段加载到内存时验证这些段的正确性。元数据包含有关镜像类型和用于执行镜像而设计的硬件类型的信息。
哈希段还包含 X509 证书(Certificate)链和验证哈希表和镜像元数据的数字签名。链中的第一个 X509 证书(称为根证书)根据烧录到硬件中的值进行验证,并且每个后续证书都根据先前的证书进行验证。这个 X509 证书链最终验证了一个用于验证数字签名的公钥(Public Key),这证明了哈希表和镜像元数据的正确性。
因此,验证启用了安全引导的 ELF 镜像的过程是:
- 根据硬件中的值验证根 X509 证书。
- 使用链中的前一个证书验证证书链中的每个 X509 证书。
- 使用证书链中最后的 X509 证书中的公钥验证镜像元数据和哈希表上的数字签名。
- 使用镜像元数据验证正在加载的镜像具有正确的镜像类型,并且在指定的硬件上运行。
- 根据哈希表中相应的加密哈希值验证每个 ELF 段。
此过程完成后,设备应该信任镜像,这可能意味着依赖镜像中的数据或将执行控制权传递给该镜像提供的入口点。
数字签名是在哈希表和镜像元数据上计算的,而不是在整个 ELF 镜像上计算的,因为这放宽了内存大小要求并提高了加载过程的灵活性。
与早期版本的 QTI 的安全引导功能不同,镜像元数据包含在哈希段的单独区域中,而不是在 X509 证书链中编码。这旨在简化镜像元数据解析,降低出错可能性,并使标准行业工具更容易分析 X509 证书链。
本文档的以下部分讨论了加载 TEE 镜像的方式、签名 ELF 镜像的结构、哈希段的结构以及镜像元数据区域内签名者可用的选项。
TEE 加载
QTI 安全引导架构旨在保持作为设备可信核心的可信执行环境(TEE)与提供用户所需的海量服务的富执行环境(REE)之间的分离。
我们通过让初始引导加载程序——基于 ROM 的主引导加载程序——加载两个镜像来实现这种分离。第一个镜像是 REE 引导加载程序镜像,它负责验证和执行操作系统镜像,最终验证和执行设备内的固件,它运行在与 OS 内核相同的异常级别(EL1)。第二个镜像是 TEE 引导加载程序镜像,它负责验证和执行 TEE 镜像,此镜像在 ARM 安全监控(ARM Secure Monitor)执行环境(EL3)中运行。
安全引导架构从芯片上软件的初始执行开始保持 REE 和 TEE 环境的分离。这些镜像旨在防止在 ARM TrustZone 环境之外运行的任何软件危及在 ARM TrustZone 环境内运行的软件,即使在安全引导过程中也是如此。
在基于 ROM 的主引导加载程序之后将执行的第一个镜像是基于 TrustZone 的 XBL_SEC 镜像。此镜像以一种将 ARM TrustZone 使用的内存跟芯片上的所有其他执行环境相隔离,然后在权限较低的异常级别执行 XBL 镜像的方式来配置访问控制系统(Access Control System)。XBL 镜像和 XBL_SEC 镜像之间的通信采用为了方便 REE 和 TEE 之间通信而设计的标准 ARM SMC 机制。
XBL_SEC 映像作为所有 TrustZone 镜像,尤其是 Qualcomm TEE 的信任根(Root of Trust)。由于 XBL_SEC 镜像无法直接访问存储设备,因此它依赖 XBL 镜像将 Qualcomm TEE 镜像从存储复制到芯片的内存中。XBL_SEC 镜像将隔离 Qualcomm TEE 镜像,以使它在被验证和执行之前只能由 XBL_SEC 访问。
XBL 镜像作为将在芯片上运行的所有非 TrustZone 镜像的信任根,包括 Qualcomm® Hypervisor 执行环境(QHEE)、操作系统引导加载程序(例如 UEFI)、操作系统内核(例如 Android 内核) 以及外围镜像(例如蓝牙和 WLAN 镜像)。XBL 镜像将直接加载这些镜像,或者负责加载将要加载这些镜像的中间软件(参见图 2)。
QTI 和设备制造商可以在被称作双重签名的过程中对 Qualcomm TEE 镜像进行签名。这是为了确保该安全关键镜像只有在获得 QTI 和设备制造商的批准后才能执行。
签名镜像格式
如前所述,Qualcomm Technologies 固件镜像使用标准 ELF 格式,因此每个镜像都包含标准 ELF 标头(Header)和程序标头,同时支持 32 位和 64 位 ELF 类。图 3 展示了一个 32 位 ELF 文件的示例:
ELF 标头主要用于定位 ELF 镜像文件中的程序标头。程序标头包含 ELF 镜像文件中所有段的位置,特别是用于定位 ELF 文件中的哈希段,其中包含用于验证 ELF 镜像的验证信息。
哈希段按顺序包含以下信息:
- 哈希段标头(元数据)是一个 48 字节的字段(Field),其中包含有关哈希段其他部分大小的信息。这允许在哈希段内识别字段。
- QTI 和设备制造商元数据字段都是 128 字节的字段,其中包含有关镜像的信息,例如镜像的类型和设计用于运行镜像的硬件。 QTI 元数据仅在镜像由 QTI 和设备制造商双重签名时才存在。
- 哈希表字段包含 ELF 文件中每个段(Segment)的哈希值。第一个条目(Entry)始终是 ELF 标头和程序标头的哈希值。这是为了确保标头段中的重要信息也得到验证(包括 ELF 标头中包含的镜像入口点地址)。
- QTI签名和证书链。数字签名是根据哈希段标头、镜像元数据和哈希表计算的。可以使用叶证书(Leaf Certificate)中的公钥对其进行验证。证书链最终由一个根证书验证,该根证书根据硬件中保存的 QTI 特定值进行验证。仅当镜像由 QTI 和设备制造商双重签名时,才应存在 QTI 签名和证书链。
- 设备制造商签名和证书链。与 QTI 签名和证书链一样,数字签名是根据哈希段标头、图像元数据和哈希表计算的,它可以使用证书链叶节点中的公钥进行验证,该公钥可以最终通过根证书进行验证,根证书根据硬件中的 OEM 特定值进行验证。
也就是说,哈希段的格式如图 4 所示:
请务必注意,QTI 和 OEM 证书链/签名位于同一个哈希表上。由于验证镜像所需的时间主要用在检查哈希表中的值,因此向镜像添加 QTI 证书链和签名不会显着增加验证镜像所需的时间。
如果段中有任何空隙,则在代码检查时会使用 0xFF 字节来填充它们。不正确的填充值将使镜像无效。在以下情况下可能会出现这些填充字节:
- 程序标头声明的哈希段大小大于哈希段中包含的所有数据。
- 哈希段的 MBN 标头字段声明的 QTI 或 OEM 证书链字段大小大于该字段中包含的所有数据。
镜像元数据
镜像元数据描述了镜像的意图。最重要的是,它描述了镜像的意图(以便在要加载 Qualcomm TEE 镜像时系统不会加载 WLAN 镜像)和用于执行镜像的硬件(以便系统不会在 Qualcomm® Snapdragon™ 845 设备上加载 Snapdragon 835 的 Modem 镜像)。
在旧版本的 QTI 安全启动架构中,此信息已被编码到证书链中叶证书的组织单位(OU,Organizational Unit)字段中。新版本的安全引导格式将此信息移动到独立的元数据字段中。这旨在通过降低解析或证书创建错误的可能性来提高安全性,这些错误可能导致镜像不具有设备制造商预期的属性。
元数据字段允许签名者指定有关镜像的信息,包括以下内容:
- 镜像的软件标识(SW_ID)。每种不同的镜像类型都有不同的软件标识。这是为了确保在引导过程中正确的时间点加载正确的镜像。
- 设备的硬件标识(HW_ID)。每个 QTI 芯片组都有不同的硬件标识。这是为了确保只有那些被设计为在该硬件上执行的镜像才能在该硬件上执行。
- 设备制造商标识(OEM_ID)。这是为了确保由一个设备制造商签名的软件不能在另一个制造商的设备上运行,即使它们共享一个公共根证书。
- 设备的调试功能。某些镜像允许签名者在设备上启用调试功能;但是,签名者只能在特定设备(必须在镜像签名时标识)上使用这些功能。
- 镜像是绑定到单个设备还是可以在所有设备上使用。出于开发和调试目的,可以通过指定设备的序列号并在镜像元数据字段中设置标志来将镜像绑定到单个设备。每个设备都有一个不同的序列号,该序列号在制造过程中被烧入芯片中。
- 镜像的防回滚版本号。如果启用,则防回滚系统将防止已知存在错误的镜像在设备上运行。该架构旨在防止设备在成功加载具有更大防回滚版本号的镜像时接受镜像。
如果镜像由 QTI 和设备制造商签署,则 QTI 和设备制造商都将提供镜像元数据字段。两个元数据字段中的所有条件都必须有效才能加载镜像。
证书链和数字签名
设备仅支持有限数量的签名算法。所有支持新安全引导格式的设备都使用 RSA-PSS 算法进行数字签名,有些设备还支持使用 NIST P384 曲线的 ECDSA 签名。
旧版本的 QTI 安全引导架构支持 RSA PKCS#1 v1.5 签名格式和其专有变体。新的安全引导架构不支持这些签名格式。
证书链用于验证用于验证哈希表和镜像元数据字段上的签名的公钥。证书链可能包含两个或三个证书。在安全引导架构的早期版本中,我们建议使用三证书链,因为链中的最终(叶)证书包含镜像元数据,因此必须在镜像签名过程中重新生成。由于镜像元数据现在已转移到哈希段中的专属字段,我们目前看不到使用三证书链的优势。
证书链的验证流程如图 5 所示:
根 CA 证书根据存储在 QTI 的 QFPROM eFuse 或硬件 ROM 代码中的哈希值进行验证。
如果镜像由 QTI 和设备制造商签名,则必须独立验证每个证书链。必须成功验证两个证书链,才能验证和执行镜像。QTI 根 CA 证书根据 QTI 哈希值进行验证,而设备制造商根证书根据设备制造商哈希值进行验证。这是为了防止 QTI 代表设备制造商签名,反之亦然。该系统旨在确保在需要双重签名镜像的情况下,设备制造商和 QTI 都可以认证该镜像。
镜像加载
所有镜像加载都遵循相同的通用过程。在本节中,我们将加载镜像的软件称为“加载程序”(Loader)。流程如下:
- 加载程序分配一个安全的内存区域来加载 ELF 标头,该内存将被映射以防止它被设备中的其他执行环境篡改,加载程序将 ELF 标头从(不受信任的)存储复制到此内存中。如果因 ELF 标头太大而无法放入此内存区域,则镜像将被拒绝。
- 加载程序分配一个安全的内存区域来加载程序标头,该内存将被映射以防止它被设备中的其他执行环境篡改,加载程序将程序标头从(不受信任的)存储复制到此内存中。如果因程序标头太大而无法放入此内存区域,则镜像将被拒绝。
- 加载程序分配一个安全的内存区域来加载哈希段,该内存将被映射以防止它被设备中的其他执行环境篡改,加载程序将哈希段从(不受信任的)存储复制到此内存中。如果因哈希段太大而无法放入此内存区域,则镜像将被拒绝。
- 加载程序通过验证根证书、证书链、镜像元数据和哈希表来验证哈希段。
- 加载程序通过计算(已加载的)ELF 标头和程序标头的哈希值并将哈希值与哈希表中的第一个条目进行比较来验证它们。如果哈希值不匹配,则镜像将被拒绝。
- 然后加载程序将尝试加载镜像中的其他每个 ELF 段。对于每个段,加载程序检查整个段是否可以加载到其已批准(列入白名单)的安全且适合该镜像的内存区域中,如果无法加载段到内存的白名单区域,则镜像将被拒绝。
- 加载程序通过计算它们的哈希值并将哈希值与哈希表中的相应条目进行比较来验证每一个加载的 ELF 段。如果任何计算的哈希值与哈希表中的值不同,则镜像将被拒绝。
- 如果合适,加载程序使用在(已经加载和验证的)ELF 标头中定义的入口点将执行传递给镜像。
此过程旨在确保加载程序永远不会意外覆盖包含从不受信任的存储中加载的镜像数据的内存中的重要数据(包括加载程序自己的代码和数据)。
总结
软件镜像从不受信任的存储加载到内部存储器并进行解析。加载和解析阶段包括针对白名单内存范围的地址和大小验证,以及执行算术/指针计算时的整数溢出检查。首先,加载并解析镜像的 ELF 标头和程序标头,然后加载并解析哈希段。
哈希段可能包含来自 QTI 和设备制造商的身份验证信息。每个签名者提供镜像元数据,元数据和哈希表上的数字签名,以及证书链。证书链可能包含两个或三个证书。根证书根据硬件中保存的值进行验证,链中的每个证书都用于验证该链中的下一个证书。叶证书中的公钥用于验证数字签名,从而验证镜像元数据和哈希表。
镜像元数据用于验证镜像是否适合在引导过程中的这一时刻加载,并且是否是为此硬件所设计的。它也可以通过其他方式限制镜像,例如通过序列号绑定并确保镜像只能在一个特定设备上使用。
哈希表用于验证 ELF 字段中的其他段。如果段的哈希与哈希表中的相应值不匹配,则镜像将被拒绝。
QTI 的新安全引导架构旨在通过允许 TEE 从启动链开始时分离、简化元数据格式、降低意外错误的可能性以及减少标准工具可能难以解析的专有加密技术来提高安全性。