基于Intel TDX的机密容器(CoCo)安全性分析

Overview

随着公有云的推广,云上的安全问题也越来越受到关注。在云上运行的应用,尤其是一些数据敏感的应用,对数据在计算过程中的机密性也越发重视。磁盘和网络的数据加密有较多的方案来处理,计算的机密性则强依赖硬件提供的安全能力。两大CPU厂商,Intel和AMD,都提供了一些硬件安全技术,如Intel的SGX和TDX,AMD的SEV等来解决此类问题。

本文将基于Intel TDX技术,来分析Confidential Contianers(简称CoCo)项目的安全性。CoCo项目是一个开源项目,它基于流行的Kata Containers项目做了增强,在其上增加了机密计算能力,安全性从单向保护(防止基础设施受到上层workload侵害),扩展到了双向保护(同时可以保护workload免受基础设施窥探)。

本文将介绍Intel TDX的可信启动流程,串联到CoCo的启动流程,进而通过信任链的传递角度来分析CoCo及TDX的安全性。

本文对阅读对象做了如下假设:

  1. 了解TDX是什么,应用于什么场景,对TDX有至少一定的了解。
  2. 听说过CoCo项目,大致知道CoCo是什么,应用于什么场景。
  3. 了解Kata Containers是什么,对Kata Containers有一定了解。

基于以上假设,本文不对CoCo和TDX做太多科普工作,前置知识的获得交给用户自己去完成。本文着重来分析CoCo的可信链条,对应的源码仓库在参考文档中有给出。

以下是正文。


TDX基本介绍

Intel给CPU加了个新的模式,叫SEAM (安全仲裁模式,Secure-Arbitration Mode, SEAM),执行 Intel 提供的、经过数字签名但未加密的安全服务模块,Intel TDX 模块位于由 SEAM-range 寄存器(SEAMRR)指定的保留内存空间中,CPU 仅允许访问SEAM模式的软件访问这段内容,其他所有软件和 DMA 都无法访问。SEAM 对其他受保护的区域如 SMM 和 SGX 保护的内存没有访问权限。

增加了SEAM mode之后,原先的VMM的模式从2个扩展到4个:

  • VMX-root
  • VMX-non-root
  • SEAM-VMX-root(新增)
  • SEAM-VMX-non-root(新增)

Intel TDX 为 TD 提供了以下功能:

  • 内存机密性和完整性(MKTME private key加密内存)
  • 地址转换完整性(secure EPT)
  • CPU 状态机密性和完整性(寄存器状态 & VMCS 保存与恢复)
  • 安全中断和异常传递(virtual APIC)
  • 远程认证(remote attestation)

具体参考whitepaper,不详细展开了。

加载SEAMLDR及TDX module

TDX功能的启用始于Intel TDX模块,信任根在于CPU。

Intel TDX module加载流程如下:

  1. 加载Intel TXTSEAM loader(SEAMLDR):
  • SEAM loader是由Intel TXT认证过的代码模块(Authenticated-Code Module, ACM)
  • SEAMLDR可以集成在UEFI里,也可以放在ESP或磁盘上,后面会展开
  1. VMM调用SEAMLDR ACM, 请求load TDX module。TDX module也可以在BIOS到kernel启动阶段完成。
  2. SEAMLDR 验证TDX module数字签名,加载TDX module到SEAM memory。
  3. TDX module的度量值(measurement)和安全版本号(security-version number, SVN)被SEAMLDR记录到硬件度量寄存器中,然后TDX module 被load到SEAM memory内。

原文来自whitepaper[1]:

In order to install the module for Intel TDX, a new, Intel® Trusted Execution Technology (Intel® TXT) authenticatedcode module (ACM), called the SEAM Loader (SEAMLDR), is provided to help verify the digital signature on the Intel TDX module and load it into the SEAM-memory range. By design, the measurement and security-version number (SVN) of the module are recorded into hardware-measurement registers by the SEAMLDR and then loaded into SEAM-memory range in response to the VMM invoking the SEAMLDR ACM in order to load the module, which has no persistence. The cloudservice provider can additionally apply its own security policies on the acceptable version of Intel TDX that should be loaded on its servers.

那第1步的SEAMLDR是怎么加载的呢?

SEAMLDR加载顺序:

  1. 如果BIOS使能了UEFI seam loader a. 从ESP(EFI System Partition) /boot/efi/EFI/TDX中探测和加载。 b. 如果ESP中不存在,则从IFWI binary中加载默认版本。
  2. HOST kernel检测是否TDX module在BIOS阶段被load,如果没有load,会从/lib/firmware/intel-seam中加载。

阿里云上一个装机示例

 1$ sudo tree /boot/efi/
 2/boot/efi/
 3├── EFI
 4│   ├── BOOT
 5│   │   ├── BOOTX64.EFI
 6│   │   └── fbx64.efi
 7│   ├── centos
 8│   │   ├── BOOTX64.CSV
 9│   │   ├── grub.cfg
10│   │   ├── grubx64.efi
11│   │   ├── mmx64.efi
12│   │   ├── shimx64-centos.efi
13│   │   └── shimx64.efi
14│   └── TDX
15│       ├── TDX-SEAM_SEAMLDR.bin
16│       ├── TDX-SEAM.so
17│       └── TDX-SEAM.so.sigstruct
18└── NvVars
19$ ls -l /lib/firmware/intel-seam
20total 1464
21-rw-rw-r-- 1 root root 589824 Oct 11 10:45 libtdx.bin.debug.1.5.01.02.595
22-rw-rw-r-- 1 root root 417792 Oct 11 10:45 libtdx.bin.production.1.5.01.02.595
23-rw-rw-r-- 1 root root   2048 Oct 11 10:45 libtdx.bin.sigstruct.debug.1.5.01.02.595
24-rw-rw-r-- 1 root root   2048 Oct 11 10:45 libtdx.bin.sigstruct.production.1.5.01.02.595
25-rw-rw-r-- 1 root root 262144 Oct 11 10:45 np-seamldr.acm.debug.1.5.01.02
26-rw-rw-r-- 1 root root 221184 Oct 11 10:45 np-seamldr.acm.production.1.5.01.02

SEAM-VMX-root模式下会hold两个经过cpu度量过的软件模块:Intel TDX模块,Intel P-SEAMLDR(P for Persistent)模块,这两个模块运行在由SEAM Range Register(SEAMRR)寄存器配置的受保护的内存区域,SEAMRR是在BIOS阶段设置的。

SEAMRR的范围可以细分为两段:

  • MODULE_RANGE
  • P_SEAMLDR_RANGE (只有P-SEAMLDR模块可以访问)

同时Intel还提供一个非持久化的SEAMLDR(non-persistent SEAMLDR, NP-SEAMLDR)ACM来将P-SEAMLDR加载到P_SEAMLDR_RANGE范围内。

加载流程:

  • NP-SEAMLDR安装P-SEAMLDR到P_SEAMLDR_RANGE内存范围。
  • P-SEAMLDR安装Intel TDX module到MODULE_RANGE内存范围。
    • At boot and at runtime:如果BIOS能找到就在boot阶段install,如果BIOS找不到则由kernel从initramfs中加载。或者是VMM主动触发加载。

整体都限定在SEAMRR保护的地址范围。

创建TD-VM

VMM 可以使用 SEAMCALL 指令将 CPU 置于 SEAM-VMX-root 模式后调用 TDX 模块,模块提供了创建、删除和调度 TD 执行的接口,充当可信媒介,帮助 TD 实施安全策略、操作和必要的缓解措施。 创建 TD 时,由 VMM 为 TD 代码、数据和相关元数据(VMCS 和 TD 的状态保存区)分配内存页。 参考以下图片

SEAMCALL指令使用RAX寄存器作为入参,RAX第63 bit为0时跳转到MODULE_RANGE(tdx-module)执行,64bit为1时跳转到P_SEAMLDR_RANGE(P-SEAMLDR module)执行。

以下图片很好的展示了TD-VM的创建流程[5]:

更完整的官方流程图如下:

这个流程展示的是Libvirt + qemu的,我们来改一个基于CoCo的架构。假设还是基于Bare Metal:

TDX本地度量&远程度量

参考:

  1. Intel TDX module 1.5 base spec: https://cdrdv2.intel.com/v1/dl/getContent/733575 12.1节

度量基于两类度量寄存器:

  1. MRTD: TD-build阶段,初始化内容的静态度量。
  • TDH.MNG.INIT 初始化digest
  • TDH.MEM.PAGE.ADD 添加private page。此时就可以把TDVF/TD-shim加进去了
  • TDH.MR.EXTEND 度量额外的内存相关数据
  • TDH.MR.FINALIZE 结束。设置了lock,在这之后TDH.MEM.PAGE.ADD 和 TDH.MR.EXTEND都不允许了,会失败。
  1. RTMR: 运行时的动态度量,TD-build之后初始化为0.
  • Guest TD可以使用TDCALL(TDG.MR.RTMR.EXTEND) 主动度量某些数据。公式:RTMR[i] = SHA384(RTMR[i] || x);

TD度量报告内容如下:

GuestTD里面可以通过TDG.MR.REPORT 主动初始化一份度量报告,创建一个TDREPORT_STRUCT结构体,包含:

  • TD度量(MRTD, RTMR寄存器信息,event log等)
  • TD初始化配置(通过TDH.MR.FINALIZE做了lock)
  • Intel TDX module度量
  • 自定义的REPORTDATA

大概的度量过程像这样:

有关于OVMF度量的图, 比较详细也很复杂:

对direct boot有 如下描述(没看懂),但可以看到度量的核心在于OVMF的实现。

Direct Boot

  1. In direct boot path, TryRunningQEMUKernel() starts and measures the kernel binary.
  2. In direct boot path, EFI stub of Linux kernel measures the kernel command and initrd. Refer to the measure log for direct boot for a sample of what the output should look like.

本地度量

远程度量

安全模型与威胁分析

参考: https://github.com/confidential-containers/td-shim/blob/main/doc/threat_model.md

 1                +--------------------------+  +================+  +----------------+
 2                | +----------------------+ |  |                |  |                |
 3                | |       td-payload     | |  |                |  |                |
 4                | +----------------------+ |  |                |  |                |
 5                |             ^            |  |   Legacy VM    |  |   Service TD   |
 6                |             |            |  | (or) other TD  |  |  (or) Arch TD  |
 7                | +----------------------+ |  |                |  |                |
 8                | |        td-shim       | |  |                |  |                |
 9                | +----------------------+ |  |                |  |                |
10   Guest        +--------------------------+  +================+  +----------------+
11   =====================================================================  ^  ==========
12   Host           +----------------------+                                |
13                  |      TDX-Module      |--------------------------------+
14                  +----------------------+
15                             ^
16                             |
17                  +======================+
18                  |         VMM          |
19                  +======================+
20
21                  +----------------------+     +==============+
22                  |       CPU SOC        |     |    Device    |
23                  +----------------------+     +==============+
24
25   Legend:
26                  +--------------+   +==============+
27                  |    In TCB    |   |  Out of TCB  |
28                  +--------------+   +==============+

核心:

  • secure boot:尽量使用secure boot,前一环节确保下一个环节组件可信,才会将控制权移交给下一个环节。secure boot可以确保组件由可信的机构提供,数字签名可验证。
  • remote attestation:保证TCB内的组件包括TDX module,td-shim,guestOS都是经过度量的,且度量值相符,否则kata-agent拒绝启动(pull image,startContainer)
  • CPU指令级别的安全保证:RTMR度量之后内存加锁,避免度量之后内存被篡改。

结论: 目前看起来可信链条还是很完整,只要远程证明的server在自己手里,且Intel的指令设计的没问题,基本上是安全的。

补充:TXT技术的简单介绍

SEAM Loader是一个ACM,靠Intel TXT技术保护,信任根在Intel CPU。TXT是一系列安全功能的组合,并不是单一的一种安全技术。可以参考:

Intel TXT引入了两个TCG概念 ------ 静态信任链(Static Chain of Trust)和动态信任链(Dynamic Chain of Trust),如下图所示。静态信任链度量平台配置,动态信任链度量系统软件、软件配置及策略。对于Intel TXT而言,信任根(Root of Trust)就是支持TXT技术的Intel CPU。

  • 静态信任链

静态信任链(Static Chain of Trust)在平台开机后度量,由硬件发起,度量值由TPM来防护免受篡改,代码在执行前都要被度量。

  1. 静态信任链由CPU中的uCode启动,度量由芯片厂商提供的BIOS ACM,即认证代码模块(Authenticated Code Module),可用来执行特定安全功能,度量之前需要验证该ACM的签名和完整性;
  2. BIOS ACM先度量一部分BIOS code,即Start BIOS code,然后,Start BIOS再去度量其它BIOS code和configuration,直到BIOS code度量结束BIOS才真正开始执行;
  3. 度量值被存储在TPM内特定的PCRs中,即平台配置寄存器(Platform Configuration Register);
  4. BIOS在执行过程中可调用BIOS ACM中的安全功能来进行安全检查;
  5. BIOS在执行任何附加code之前,如Option ROM,都需要先度量后执行;
  6. 引导OS时,BIOS也度量主引导记录(MBR)和OS Loader。 需要说明的是,静态度量只在平台开机后执行一次。
  • 动态信任链

动态信任链(Dynamic Chain of Trust)由OS的需求而来。

  1. 开启动态度量,通过特殊的CPU指令度量和验证SINIT ACM;
  2. SINIT ACM执行安全检查,包括确认BIOS已经通过安全检查以及平台配置已锁定;
  3. SINIT ACM度量可信OS,即TBoot,并调用启动控制策略(Launch Control Policy,LCP)引擎来判断平台配置和OS是否可信。

参考文档

  1. 白皮书:https://www.intel.com/content/dam/develop/external/us/en/documents/tdx-whitepaper-final9-17.pdf ,通用的介绍
  2. 白皮书中文版:https://notes.caijiqhx.top/ucas/tee/intel_tdx/intel_tdx/
  3. CoCo社区:https://github.com/confidential-containers
  4. Kata Containers: https://katacontainers.io/
  5. TDX官方各类文档:https://www.intel.com/content/www/us/en/developer/tools/trust-domain-extensions/documentation.html
  6. KVM: X86: TDX support:https://lkml.org/lkml/2020/11/16/1106 ,KVM社区相关patch
  7. Intel CPU Architectural Extensions Specification: https://cdrdv2.intel.com/v1/dl/getContent/733582 ,详细介绍CPU架构及指令集等.
  8. Linux stacks for Intel Trust Domain Extension 1.5: https://www.intel.com/content/www/us/en/content-details/790888/whitepaper-linux-stacks-for-intel-trust-domain-extensions-1-5.html
  9. td-shim spec,启动流程讲的比较细: https://github.com/confidential-containers/td-shim/blob/main/doc/tdshim_spec.md
  10. Intel TDX module 1.5 base spec: https://cdrdv2.intel.com/v1/dl/getContent/733575
  11. TXT的基本原理: https://www.cnblogs.com/chipsec/p/8409600.html
  12. TXT whitepaper:https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/trusted-execution-technology-security-paper.pdf