CCS20 TRUSTORE论文解读

2021/05/30

TRUSTORE: Side-Channel Resistant Storage for SGX using Intel Hybrid CPU-FPGA

TRUSTORE发表于CCS20的Session 6C Side Channels上,是一篇针对于现有SGX技术很容易遭到Side Channel攻击这一问题来进行研究的文章,其中应用了FPGA,将可信区从SGX本身拓展到了FPGA,实现了一个可信的存储模块。

摘要

现有的SGX容易遭受到侧信道攻击(页错误、缓存、分支预测、推测式执行等),虽然ORAM技术从理论上保证了SGX可以免除侧信道的危害,但是其具有严重的性能问题。这篇文章介绍了一个新成果:TRUSTORE,利用FPGA这一外设,实现了一个可信的存储服务,并且保证该存储服务与侧信道完全隔绝。TRUSTORE主要解决了以下三个问题:

  1. 在不改变系统架构的前提下,将可信范围从SGX拓展到FPGA上;
  2. 为SGX应用与FPGA之间提供一个可验证的安全连接通道;
  3. 为SGX应用提供无缝的多重操作支持(怎样理解无缝?)。

SGX中的侧信道攻击以及常规ORAM方法的局限性

目前,常见的针对SGX的侧信道攻击大都基于存储结构,例如基于页错误的攻击,基于缓存的攻击(flush+reload,evict+reload,evict+time等等),基于分支预测的攻击以及基于推测执行的攻击等等。通过这些侧信道攻击,攻击者可以获取到本应被SGX保护的敏感信息。

针对这一系列攻击,许多基于ORAM的方法被提出并应用于侧信道的保护上。但由于对于每次内存访问,ORAM都需要访问整个访问路径树(对大小为N的数据,需要额外O(LogN)的内存访问次数),这使得ORAM的性能受到了极大的限制。实验结果表明,ORAM的额外开销相较于原生enclave执行缓慢了两个数量级。此外,当访问的数据大小变大时,ORAM的速度呈指数级衰减。

正因常规ORAM方法在解决SGX的侧信道攻击时具有很大的局限性,如何高效地预防SGX中的侧信道攻击成为了亟待解决的问题。事实上,与SGX相关的基于存储的侧信道攻击,大都因为相应的存储单元(内存,缓存,页表,分支预测单元等)是被计算机上不同应用(不管被信任与否)所共享的。在这篇文章中,作者提出了一个观点:如果我们将SGX所利用的存储单元与这些共享存储单元隔绝开,其相应的侧信道是否在很大程度上会被隔绝?

TRUSTORE简介

基于上文中的观点,作者设计了TRUSTORE,也即一个在与其他存储设备相隔离的FPGA中的可信存储模块。由于TRUSTORE有着独立的内存单元,故其从设计上阻断了存储单元相关的侧信道。在设计TRUSTORE并将其与SGX相结合的过程中,作者遇到并解决了以下三个挑战:

  1. 在不改变系统架构的前提下,将可信范围从SGX拓展到FPGA上;
  2. 为SGX应用与FPGA之间提供一个高速的可验证安全连接通道;
  3. 为SGX应用提供无缝的多重操作支持(怎样理解无缝?)。

本文的威胁模型

Enclave的假设

假定用户想要在一台远程机器上里用SGX安全地运行一个应用。攻击者了解这个应用的内容和源代码,所以代码本身并不是敏感信息。但,用户向enclave提供的数据是敏感的,因此这些数据需要被保护以免受到侧信道攻击。在TRUSTORE中,作者假设单一一方(如enclave应用开发者)会将TRUSTORE服务引入FPGA设备中。但对于某些服务,开发者可以在一台设备中运行多个enclave,并且这些enclave可以同时访问同一块FPGA。

硬件假设

TRUSTORE的有效性基于以下硬件层面的假设:CPU与FPGA芯片不会被篡改且其功能被正确实现。此外,作者假设攻击者不能从芯片封装内直接获取到秘密信息或者使当前状态混乱。温度与功耗侧信道不在TRUSTORE的考虑范围中。

攻击者的能力

攻击者拥有控制全部软件组成(如BIOS,OS,VMM以及设备驱动程序)的特权。此外,攻击者可以控制除FPGA之外的所有外设,所有的非EPC内存也都可以被攻击者控制(例如DMA与MMIO缓冲区)。与EPC类似,尽管攻击者不能直接访问被TRUSTORE保护的FPGA DRAM,他们也可以发起相关的侧信道攻击。

TRUSTORE的设计

TRUSTORE分为两部分,TRUSTLIB和TRUSTMOD。

在介绍完这两个模块之后,文章讨论了如何利用MMIO与DMA来高效的将这辆各模块进行连接与组合。

名词解读:

TRUSTMOD的加载与验证

TRUSTMOD需要被编译成比特流并加载进FPGA开发板上,因此,如何保证其在加载到板上之后的保密性和完整性是这部分主要解决的问题。

比特流的加载

通过FPGA的安全启动流程,TRUSTMOD可以保证比特流在加载到板上之后,其中内容不会被窃取。具体来说,开发者首先准备好TRUSTMOD的比特流,并将该比特流上传到FPGA厂商来进行签名和加密(假设FPGA厂商可信),最后将正确加密并签名比特流烧入FPGA中,FPGA自身解密并写入自身逻辑模块。但显然,这一过程只能保证烧入的比特流的内容不被外界知晓,并不能保证FPGA始终运行正确可靠的比特流。因此,TRUSTMOD借鉴了SGX中的remote attestation过程,并借助TRUSTLIB实现了一套自身的验证流程。

密钥管理与验证过程

在介绍如何验证之前,我们先来介绍密钥管理方法,其过程如下图所示: TRUSTMOD加载过程中的密钥管理 图1:TRUSTMOD加载过程中的密钥管理

步骤⓪指出,FPGA厂商在出厂前会为每块开发板准备好相应的三个密钥\(k_{Pub}^{bitstr},k_{Priv}^{bitstr},k_{AES}^{bitstr}\)来用作安全启动的保证。为了实现验证操作,如步骤①所示,TRUSTMOD也会在每次编译之前(来保证不同TRUSTMOD设备的密钥不同)生成一对密钥\(k_{Pub}^{attest},k_{Priv}^{attest}\),并把私钥\(k_{Priv}^{attest}\)附加在编译好的比特流中,公钥则会被提供给TRUSTLIB以便进行后续操作,这是图示中的步骤②。当FPGA接收到加密并签名过的TRUSTMOD比特流之后,其就会进行相应的验证操作,如果验证无误,则将解密之后的TRUSTMOD模块载入逻辑阵列中,如步骤③。 接下来,为了在CPU与FPGA之间建立起一条可靠的信道,TRUSTLIB将会发起对TRUSTMOD的验证。其过程如下图所示: TRUSTMOD与TRUSTLIB的验证过程 图2:TRUSTMOD与TRUSTLIB的验证过程

为了保证验证消息的新鲜性,在发起验证的最初,TRUSTLIB首先要产生一个随机nonce并发给TRUSTMOD,TRUSTMOD接受到这个nonce之后,利用\(k_{Priv}^{attest}\)对其进行签名并发回至TRUSTLIB供其进行验证。若验证通过,则开始发起Diffie–Hellman密钥交换,最终得到一个公共密钥,至此安全信道建立成功。这个机制保证了,只要\(k_{Priv}^{attest}\)不被泄露,即使攻击者改写了FPGA的比特流内容,也会在进行验证时被TRUSTLIB发现。

TRUSTMOD的存储模型

关于存储模型,主要考虑三个问题,第一:怎么存,也既存储内容在存储器中的物理和逻辑组织结构是什么;第二:怎么管,也既内容可以被谁访问,可以被怎样访问。对于怎么存这个问题,从概念出发,我们要考虑内容以什么格式组织在存储器中,并通过怎样的方式寻址。对于怎么管这个问题,我们主要考虑访问控制以及如何响应相应的存储操作请求。此外,可能存在的内存碎片问题也是TRUSTMOD需要解决的问题之一。

怎么存

怎么管

TRUSTMOD维护一个FIFO队列来记录每个enclave的内存操作请求,因此这些请求将会以先来先服务的形式被响应。如果队列满无法再接受新请求,TRUSTMOD将会通过推迟发送ACK信号的方式来让总线暂停接受新请求。

内存碎片管理

由于不同的应用以及不同的enclave对于内存的需求不尽相同,随着内存碎片的积累,很大一部分空间会被浪费。因此,TRUSTMOD定期运行一个内存整理算法来保证内存碎片的存留时间不会超过一个确定的时长。更具体地,在处理了一定数量的内存回收请求之后,TRUSTMOD同样会对内存进行整理。整理之后,相应的OCMAT也会被更新。

TRUSTLIB与TRUSTMOD的连接

连接具有两层含义,第一层是逻辑上的连接,也既怎样建立一个安全的通信信道,第二层是物理的含义,也既通过什么协议和方式建立连接。

安全通信信道的建立

安全信道的建立基于Diffie-Hellman密钥交换机制,图二详细地描述了这一过程。为了获取真正的随机数(硬件随机数),作者分别利用了rdrand指令(TRUSTLIB中)与一种FPGA真随机数生成器(TRUSTMOD中)来作为DHKE中的RNG。在生成DHKE所需的秘密信息这一过程中,为了避免运行时间的差异所招致的基于时间的侧信道攻击,作者在实现中,将乘法的次数固定(通过引入一些虚假的乘法,例如乘以1),并且让数据的宽度保持一致,这样,不同的密钥交换过程的运行时间均可以保持一致。在密钥交换完并获得共享密钥之后,作者利用了SGX库内已经实现好的AES-GCM-128算法,来进行数据的加解密,这一实现基于Intel的AES-NI指令集,该指令集可以有效的防止基于时间的侧信道攻击。由于AES-GCM算法本身的性质,freshness和完整性也可以得到保证。

I/O协议

TRUSTORE支持两种I/O协议,一种是MMIO,另一种为DMA。

MMIO

MMIO信道由设备驱动建立,具体来说,驱动被安装在不可信OS中,其将FPGA设备注册到Linux设备文件系统devfs中(原文如此,实际上在Linux内核4.16中,devfs已经被弃用,取而代之的是devtmpfs,相较于devfs其性能更好)。由于信道都是加密的,驱动至多能发起DDoS攻击,但这并不在SGX的保护范畴之内。在访问时,TRUSTLIB要求驱动将TRUSTMOD的内存映射到非EPC区域,此后,TRUSTLIB即可直接访问该区域,无须退出enclave。

DMA

对于大文件的传输,DMA是更为高效的选择。在TRUSTMOD中,DMA由两部分组成:1)一个MIMO区域,用来传递DMA请求;2)一个DMA缓冲区,用来传输与请求相关的实际内存区域。由于DMA支持在IO总线上的burst模式传输,因此在块大小较大时,DMA的传输效率相较于MIMO更高一些。

MIMO/DMA中侧信道的防护

在TRUSTMOD中,所有的MIMO访问都被固定在同一地址中,因此,内存访问路径不会泄露任何信息。此外,数据块的大小在运行过程中也都保持一致,因此,不管请求内容如何,TRUSTORE都会读写相同大小的数据区域,这防止了体积信息的泄露(volume-hiding)。

支持的编程接口

为了让enclave能够方便的访问TRUSTMOD中的内存,TRUSTMOD会暴露如下接口(原型)给TRUSTLIB:

OUT ID alloc();
OUT STATUS dealloc(IN ID id);
OUT STATUS access(IN type, IN id, IN SIZE_T offset, IN void* dat_in, OUT void* dat_out, IN SIZE_T size);

其中,IN和OUT为类型修饰符:IN表示TRUSTLIB需要给这个参数提供一个值,OUT表示TRUSTMOD需要提供这个值或者填充这片区域。ID是数据对象的id类型,STATUS则为记录本次调用是否成功的数据类型。接口的具体语义通过名称和参数很容易理解,故不再赘述。需要注意的既是对于读和写,其用一个统一接口access来避免了不同函数调用对信息的额外泄露。其通信包的格式见图3。 TRUSTORE中通信数据包的格式 图3:TRUSTORE中通信数据包的格式