「隐语小课」可防御侧信道攻击的 TEE 运行时环境 DOVE 解读

简介: 「隐语小课」可防御侧信道攻击的 TEE 运行时环境 DOVE 解读


前言

DOVE(A Data-Oblivious Virtual Environment)关注的问题是如何让高级语言编写的应用程序在可信执行环境中运行时能够抵抗侧信道攻击。《DOVE: A Data-Oblivious Virtual Environment》 论文[1]发表在 NDSS’21 上,论文作者来自 UIUC 和 JHU。本文主要解读论文中的 TEE 侧信道攻击问题,以及针对高级语言 R 设计的、防御侧信道攻击的 TEE 运行时环境 DOVE。

后台回复关键词“DOVE”,可获取原论文!

一、背景

1.可信执行环境

可信执行环境(Trusted Execution Environment,TEE)是一种依赖于专用硬件的隐私计算技术。以具有代表性的 TEE 技术 Intel SGX 为例,其为开发者提供基于硬件实现的安全容器(被称为 Enclave)来保护数据机密性与完整性。Enclave 使用的内存(Enclave Page Cache,EPC)会被 CPU 加密,同时包括操作系统、Hypervisor 等在内的特权软件都无权限访问 EPC。此外,Intel SGX 提供了远程认证机制(Remote Attestation)让开发者可以验证一个已知程序运行在 Enclave 中。Intel SGX 的安全模型可以同时抵抗硬件和软件攻击,非常适合如云计算之类的应用场景:用户使用云厂商提供的硬件资源与操作系统,但将应用运行在 Enclave 中可以防止云厂商窃取用户数据。

2.侧信道攻击

Intel SGX 等 TEE 技术无法抵抗侧信道攻击(Side-channel attack)。侧信道攻击指的是攻击者使用运行程序时收集的额外信息而非安全协议漏洞或工程实现缺陷实施的攻击。这里的额外信息通常包括能耗、时间等。代码片段 1 展示了一个简单的可实施侧信道攻击的案例。






if (x1 && x2) {    y = 1;} else {    y = 0;}

这是一段简单的 C/C++ 代码,根据 x1、x2 的取值为变量 y 赋值。如果这段代码运行在 SGX Enclave 中,攻击者无法直接读取内存中 x1、x2、y 的值,但可以通过观测代码运行的行为推测这些变量的取值(或范围)。因为 x1、x2 不同的取值会导致不同的程序行为,对应着不同的机器指令(如下图所示)。需要注意的是,侧信道攻击并不是 TEE 独有的问题,它是传统计算机系统中就广泛存在的一种攻击形式,只是与 TEE 的安全模型非常契合。这里给出的是侧信道攻击的一个简单示例,读者如果想要对 TEE 侧信道攻击技术有更加详尽的了解,推荐阅读参考文献中的综述[2-4]

3.Data-Oblivious Programming

Data-Oblivious Programming 是一种常见的侧信道攻击防御技术,中文通常翻译为数据不经意编程。Oblivious 的本意是无感知,Data-Oblivious 指的是应用程序不感知其处理的具体数据。Data-Oblivious Programming 技术的思路就是通过专门的编程开发范式来编写应用程序,使得应用程序的行为与其处理的数据无关(即不感知数据),从而能够抵抗侧信道攻击。例如我们使用 Data-Oblivious Programming 方法对代码片段 1 进行改写便能得到代码片段 2。


y = x1 & x2;

这一行代码完成的功能与代码片段 1 相同,但其运行行为与 x1、x2 的取值无关,因此满足 Data-Oblivious 性质。但天下没有免费的午餐,Data-Oblivious Prgramming 对开发者能够正确开发符合规范的程序有着极高的要求,同时还会导致程序性能显著降低。在 DOVE 之前已经有一些工作使用 Data-Oblivious Programming 技术来提升 TEE 应用的安全性,抵抗侧信道攻击。例如隐语团队与 UC Berkeley 联合研发的 Secure XGBoost 项目[5]就使用该技术重构 XGBoost 来防御 TEE 侧信道攻击。相比之下,DOVE 的区别在于其面向的不是某一类特定应用,而是 R 这种高级语言。DOVE 的目标是构建一种虚拟环境,使 R 语言开发的应用可以自动地以 Data-Oblivious 的方式运行在 TEE 中。

二、DOVE

1.R 的侧信道攻击风险

为了阐述 DOVE 的设计动机及其挑战性,DOVE 作者首先分析了在 TEE 中直接运行 R 语言程序会产生的侧信道攻击风险。以下图为例,geno 是包含生物基因信息的敏感数据,它是一个 m 行、n 列的矩阵。每个矩阵的合法取值是 0、1、2。geno 矩阵存储的数据是需要保护的敏感数据,而 m、n 则是无需保护的非敏感数据。第 1 行代码是将 geno 中的不合法取值设置为 NA(Not Applicable,类似于 C 语言的 NULL)。第 3-5 行代码则是统计 geno 每一行中 0、1、2 的数量。仅通过这段 R 语言代码我们并不能发现太多问题。但 R 是解释性语言,R 解释器主要由 C 语言开发。上图第一行代码中的 & 运算对应如下的 C 语言代码。由之前的分析我们知道,这段代码存在侧信道攻击的风险。







if (x1 == 0 || x2 == 0)     pa[i] = 0;else if (x1 == NA_LOGICAL || x2 == NA_LOGICAL)     pa[i] = NA_LOGICAL;else    pa[i] = 1;

下图是 DOVE 作者给出的量化实验结果,当代码中 x1 与 x2 取值不同时,该段程序执行机器指令的数量也存在显著差异。这个结果是对上述结论的进一步验证。

2.DOVE 的整体设计

为了解决上述问题,DOVE 采用下图所示的系统结构。其核心组件包括前端(Front-End)和后端(Back-End)两个部分。前端负责将 R 语言程序翻译成一种专为 DOVE 设计的中间表示 DOT(Data Oblivious Transcript)。后端运行在 TEE 中,负责解释运行 DOT。DOVE 的设计具有如下的优势:

可信计算基 TCB(Trusted Computing Base)小。实际只有后端运行在 TEE 中,包含约 7000 行 C/C++ 代码。

易用性好。对于 R 开发者而言无需学习新的语言或 Data-Oblivious Programming 即可享受 DOVE 带来的侧信道攻击防御能力。

扩展性好。编译技术前后端分离的特性使得 DOVE 可以基于 DOT 中间表示方便地扩展支持其他高级语言前端。

3.DOT

DOT 是 DOVE 系统设计的核心,它作为一种中间表示,描述了 DOVE 支持的数据类型和运算。DOT 中有两种数据类型:

第一种是确定性值(fixed concrete value),例如表示矩阵行数与列数的常量;

第二种被称之为 pseudonym,用来表示代表敏感数据的矩阵或标量。

DOT 支持下图中的运算,具体又分为安全运算、非安全运算、补充运算三类。安全运算的输入可以是确定性值也可以是 pseudonymn。当一个运算有一个输入是 pseudonymn 时, 那么该运算的输出即是 pseudonymn,安全运算在 DOVE 后端都有相应的 Data-Oblivious 实现,包括基础的算数运算、逻辑运算以及主要的数学函数运算。而非安全计算的输入只能是确定性值。这些数据无法得到 DOVE 安全机制的保护,通常是非敏感数据,例如矩阵的维度、For 循环的迭代次数等。补充运算是构建在安全运算之上的复合运算,作为库函数补充 DOVE 支持的功能,因此它们也具备 Data-Oblivious 的性质。

3.1DOVE 前端与后端

前端

DOVE 前端的功能就是将 R 程序翻译成 DOT 中间表示。一方面,DOVE 前端会将 R 程序中需要保护的敏感数据转化为 DOT 支持的 pseudonymn 类型,R 程序中处理敏感数据的代码会转化为 DOT 中 pseudonymn 元素的访问、赋值以及使用 DOVE 支持的运算处理 pseudonymn。另一方面,通过之前的分析我们知道控制流是引发侧信道攻击的主要原因,因此 DOVE 前端的另一个核心功能是对 R 程序中控制流的转换。我们通过下图中的例子具体来看 DOVE 前端是如何将 R 程序转化为 DOT 的。上图中,右侧方框内的代码是一段 R 代码,该程序的功能是将矩阵 x 每一行第 1 列中小于 0 的元素置为 0,左侧方框内的代码是对应的 DOT。① 是声明一个 10 行、7 列的 pseudonymn($1 表示),代表受保护的数据,对应 R 程序的第 1 行代码。② 对应着 R 程序中的 for 循环,逐行处理 pseudonymn。进一步来看循环体内的代码,在 ④ 中,DOT 首先比较每行第 1 列元素与 0 的大小,结果保存在变量 %1 中,第 1 列元素的原始值保存在变量 %2 中。第 ⑤ 步通过 select 运算根据变量 %1 的结果在 #0(代表常量 0)和变量 %2 中做出选择,结果保存在变量 %3 中。最后第 ⑥ 步再将变量 %3 写回到第 1 列中。通过这个例子可以看到,DOVE 前端在处理 R 程序分支语句时,会执行每一个分支,然后使用 select 运算根据分支条件来选择正确的结果。Data-Oblivious 的 select 运算在后端通常基于条件转移 cmov 指令实现来防御侧信道攻击。

后端

在产生 DOT 之后,运行在 TEE 内的 DOVE 后端负责执行 DOT。DOT 支持的安全运算在 DOVE 后端都有对应的 Data-Oblivious 实现。这里所说的 Data-Oblivious 实现主要体现在两个方面。其一,因为浮点数计算并不是 Data-Oblivious 的,同一浮点运算对于不同的操作数在执行时间上有显著区别,所以 DOVE 后端使用定点数计算库 libfixedtimefixedpoint(libFTFP) 实现安全运算[6]。其二,DOVE 后端在实现时也需要灵活应用 cmov 指令来避免控制流引发的侧信道攻击风险。代码片段 4 中 BinaryOp::call() 函数是 DOVE 后端二元运算符处理输入是否为 NA 的一个例子,我们可以看到 DOVE 通过封装的 cmov64 函数来规避传统基于 if 实现的控制流。cmov64 函数的汇编实现依赖于底层 cmov 指令(第 7 行 cmovne)的支持。DOVE 的代码在 GitHub 开源,对 Data-Oblivious Programming 感兴趣的读者可以参考学习。 https://github.com/dove-project


void Primitives::cmov64(int cond, void* src_ptr, void* dst_ptr){    __asm__ __volatile__ (  "mov (%2), %%rax\n\t"
    "test %0, %0\n\t"
    "cmovne (%1), %%rax\n\t"
    "mov %%rax, (%2)"
    :
    : "b"(cond), "c"(src_ptr), "d"(dst_ptr)
        : "cc", "%rax", "memory"
        );}
void BinaryOp::call(fixed scalar1, fixed scalar2, fixed *result){    fixed na = Primitives::na_value();    int is_na = Primitives::is_na(scalar1) | Primitives::is_na(scalar2);    Primitives::cmov64(is_na, &na, result);}

4.性能评估

DOVE 作者使用 PageRank 以及基因分析应用评测了 DOVE 的性能。相较于原生的 R 程序,在 PageRank 上,DOVE 会带来 48.09-73.67x 的性能降低;在基因分析应用上,DOVE 会带来 12.74-341.62x 的性能降低。DOVE 的性能降低主要来自三个方面:

一是 Data-Oblivious Programming 与传统编程存在显著区别,例如前者需要运行控制流的所有条件分支;

二是使用定点数计算库 libFTFP 相较于传统浮点数计算会引入额外的性能开销;

三是使用 SGX 这类 TEE 技术本身所带来的性能开销。

DOVE 作者评估 DOVE 时使用的仍然是第一代的 SGX 设备,只有不超过 128MB 的内存可以使用,在处理内存需求较高的大规模数据时易产生频繁的 EPC Page Swapping 降低性能。当前第二代 SGX 技术最高已支持 TB 级的内存,相信由 TEE 本身引入的性能开销会进一步降低。

三、小结

凭借优秀的性能与良好的应用支撑能力,TEE 这种隐私计算技术在过去几年中受到了广泛关注,但侧信道攻击一直是 TEE 绕不开的一个话题。DOVE 目前仍然是以学术研究为主要目标的原型系统,其后端实现约 7000 行,相比于超过百万行代码的原生 R 解释器而言,DOVE 支持的 R 语言功能特性还十分有限,其意义更多在于验证技术可行性。DOVE 证明了基于编译器的技术路线,可以让高级语言程序员无需学习相关背景知识即可自动享受到 DOVE 的侧信道攻击防御能力,但将这类 Data-Oblivious Programming 技术应用于生产来防御侧信道攻击的最大挑战还是在于性能问题。针对 TEE 实施侧信道攻击的条件十分严苛,而使用 DOVE 此类技术会引入高达百倍的性能开销,如何在安全性与性能之中做出取舍最终还是需要用户自身来回答这个问题。

后台回复关键词“DOVE”,可获取原论文!

四、参考文献

1.Hyun Bin Lee, Tushar M. Jois, Christopher W. Fletcher, Carl A. Gunter: DOVE: A Data-Oblivious Virtual Environment. NDSS 20212.杨帆,张倩颖,施智平,关永.可信执行环境软件侧信道攻击研究综述.软件学报,2023,34(1):381-4033.Nilsson, Alexander, Pegah Nikbakht Bideh, and Joakim Brorsson. "A survey of published attacks on Intel SGX." arXiv preprint arXiv:2006.13598 (2020).4.Fei, Shufan, et al. "Security vulnerabilities of SGX and countermeasures: A survey." ACM Computing Surveys (CSUR) 54.6 (2021): 1-36.5.Law, Andrew, et al. "Secure collaborative training and inference for xgboost." Proceedings of the 2020 workshop on privacy-preserving machine learning in practice. 2020.6.Andrysco, Marc, et al. "On subnormal floating point and abnormal timing." 2015 IEEE Symposium on Security and Privacy. IEEE, 2015.

相关文章
|
存储 运维 云计算
深度解析云计算计费方式,看完这篇全懂了!
深度解析云计算计费方式,看完这篇全懂了! 随着科技的飞速发展,云计算已经成为了我们生活中不可或缺的一部分。然而,对于云计算的计费方式,你是否感到困惑呢?这篇文章将为你深度解析云计算的计费方式,让你看完之后全懂了!
1189 1
|
安全 物联网 API
TEE是什么?现有TEE解决方案
TEE是什么?现有TEE解决方案
2222 0
|
设计模式 JavaScript 开发者
Vue设计模式:工厂模式
Vue设计模式:工厂模式
|
消息中间件 运维 分布式计算
实时计算Flink版最佳实践测评
本文介绍了使用阿里云实时计算Flink版进行用户行为分析的实践,详细探讨了其在性能、稳定性和成本方面的优势,以及与自建Flink集群的对比。通过实时计算,能够快速发现用户行为模式,优化产品功能,提升用户体验和市场竞争力。文章还提到了产品的易用性、功能满足度及改进建议,并与其他Flink实时计算产品进行了对比,强调了Flink在实时处理方面的优势。
|
存储 缓存 NoSQL
深入解析Memcached:内部机制、存储结构及在大数据中的应用
深入解析Memcached:内部机制、存储结构及在大数据中的应用
|
存储 机器学习/深度学习 安全
隐私计算的硬件方案:「可信执行环境TEE」兼顾数据安全、隐私保护
隐私计算的硬件方案:「可信执行环境TEE」兼顾数据安全、隐私保护
1493 0
|
缓存 安全 应用服务中间件
Nginx的反向代理功能有哪些应用场景呢
【8月更文挑战第22天】Nginx的反向代理功能有哪些应用场景呢
920 0
|
Java 测试技术 Spring
MultipartFile介绍
MultipartFile介绍
690 0
|
网络协议 测试技术 网络安全
|
网络协议 调度 C语言
live555 RTSP服务器与客户端通信源码分析
live555已经发展了很多年,不过最新的live555版本,笔者没有编译通过,最终选择了2019.8.28的live555代码,如果有需要的同学,可以自行去Index of /pub/contrib/live555/ (videolan.org)去下载,不过需要自己去编译,我的编译环境是windows版本,网上有很多关于如何将其编译为VS版本的live555的,如果有需要的同学,可以在博客下留言,我会给你发一个(自己对一些代码进行了注释,不过都是自己的理解,不一定正确)。对于代码的分析:RTSP服务器使用的testOnDemandRTSPServer.cpp,RTSP客户端使用的testRT
1060 0