一、总论
TEE(Trusted Excution Enviroment)我一直没有学明白过,也是借着 recycle 学长的论文的机会,重新学习了一下。
我觉得我一直没有学明白的原因是,TEE 涉及的技术太繁多了(内存加密,安全世界,加密计数器,可信报告,……),而又缺少核心定义,以至于我对于到底啥是 TEE 一直没有具体的概念,反而被上面描述的技术或者概念牵着鼻子走。而实际上这些技术与概念,往往是为了应对某种具体的攻击场景,并不本质。以内存加密为例,难道它只能用在 TEE 中吗?显然不是的,这套加密算法可以被用于任何容易遭受物理攻击或者重放(replay)攻击的地方;同样的,也不是说 TEE 就一定需要内存加密,如果没有物理攻击(比如说手机,或者 HBM 这种天生对物理攻击防御能力强的硬件),也可以不需要内存加密。
二、硬件信任根
那么 TEE 的核心到底是什么?我觉得是它把信任根(Root of Trust)明确放在了硬件上(粗浅说应该就是 CPU 上),而且只有硬件上。这是什么意思呢?就是我们其实之前的信任根,往往是某个软件。比如说我们在跑一个进程的时候,不担心另一个进程看到这个进程内部的数据,这是因为我们相信 OS 会正确配置我们的页表,确保两个进程的虚拟地址空间的隔离性。
在这个过程中,其实同样也是有硬件参与的,比如说 MMU 进行地址翻译,也是硬件过程。但是我们依然说,我们信任的是 OS 而非硬件。这是因为比较常见的情境下,硬件一般就是“乙方”,而软件才是“甲方”,软件负责按照一定规则使用硬件,硬件基本上也不能抗拒。而这种方式下,如果软件是恶意的,就算硬件有心反抗,也是没有办法的事情。所以我们才说,一般情形下,我们其实信任的是一个高特权级的软件。
那么为什么我们无法再信任软件了呢?我觉得其实有两方面原因,一方面比较传统,那就是高特权级的软件可能被黑客攻击了,它自然可以窃取低特权级的信息了,比如说黑客拿到了 Root 权限,查看某个进程的虚拟地址空间的机密数据,这就非常容易了。但是我觉得这种场景,其实不太能够完全催生 TEE 的诞生,因为最直白的方法,是通过修复 bug 来阻止黑客拿到 Root 权限,而不是构建一个连 OS 都控制不了的 TEE,通过牺牲便捷性,来保证安全。另一个方面则是云服务时代的到来,用户开始向云厂商租赁服务器等资源,此时的 OS 或者 VM 这种高特权级软件,往往是云厂商提供的。都不需要黑客,只需要云厂商有一点恶意的念头,就可以把租户的数据窃取出来。这种不信任所涵盖的范围(OS,VM,Hypervisor)是之前的单点攻击所不具备的(Root 的危害性跟它们比起来弱爆了)。这个时候租户迫切需要一种完全不涉及任何高特权级软件的信任根,也就是由硬件去保证的信任根。当然了,第二点在智能手机来临以后,又变成了手机的生产厂商,对于手机用户的不信任了,手机用户可以获得手机的 Root 权限(故意的,或者无意的),进而将手机厂商或者用户的敏感数据泄露。
那是不是意味着我们只能信任硬件呢,顶多再加上上面的固件呢?并不是,因为信任根所能提供的功能实在是太有限了(无法管理设备,无法提供充足的编程抽象,……)。所以我们其实会使用一些软件的。但是我们该如何保证这些软件的可信性呢?我们使用信任链来保证,也就是如果我们信任这个硬件,而硬件信任软件,则我们信任软件。通过这种方式,我们从信任根(也就是信任链的头部)开始,构建出一整个信任基(Trusted Compute Base,TCB)。
当然这个时候就有一个疑问了,那就是如果我们可以使用信任链,那为什么我们不能把云厂商的 VM 也加入信任链中,这样不就可以避免云厂商的恶意了吗?我觉得有两个方面的原因:一方面是信任的成本是非常高的,我们为了验证软件是可信任的,通常需要用各种方式检验它是否被篡改,即使未被篡改,我们也需要保证它之前也是不含恶意或者 bug 的(这点就非常难了)。另一方面是,信任链越长,可信基越大,那么攻击面也就越广,反而不利于保证安全。
但是 TCB 如果较小,那么往往就对应着 TEE 较为受限的功能。那么 TEE 如何与普通计算环境的协作,如何在功能性和安全性上做 tradeoff,就成了 TEE 的一个重要的设计课题。
最后总结一下,为了建立信任,我们需要一个被信任的“上帝”,也就是信任根。而传统扮演信任根的高特权级软件,失去了我们的信任,因此我们选择信任硬件作为信任根。
三、组件
3.1 总论
依然先强调,这里出现的相关的组件,并不是一定会出现在每一个 TEE 机制中的。有些 TEE 是缺少部分组件的。
3.2 硬件隔离
这说的是,CPU 会提前准备一片物理内存区域,这片内存区域不会被 OS 看到,只有在 CPU 进入到特定模式的时候才可以看见。而 CPU 是否进入这个特定模式,也不由 OS 控制。
总的来说,这其实是相当于构建了一层更高级的特权级,这个特权级比 OS 或者 Hypervisor 的权限还要高。它的工程实现,就是某个寄存器上有个 bit 来指定它是否存在于这个特定模式(在 ARM 中就是是否在 EL3),然后 CPU 在访问这个隔离内存的时候,都会检查一下这个 bit,如果没有置位,就会触发异常。
硬件隔离机制确实是所有 TEE 必备的要素。因为隔离就是安全的最基础的机制。
3.3 远程校验
一般的 TEE 是信任硬件的,也就是信任硬件和其上的 TCB 是未被篡改的。但是能不能更进一步的,就是并不是无条件信任硬件,而是我们真的可以校验一下我们使用的硬件,这个硬件是否是可信的,这就是远程校验(remote attestation)的思路。
具体而言,就是硬件会在启动后生成一份安全报告,来表明目前自己的状况(应该是哈希吧)。我们只需要拿着这份报告去与官方的报告去比对是否相同,就可以确认 TCB 是否被篡改。
3.4 加密内存
如果只有硬件隔离机制,那么那片隔离内存中的数据,其实是明文存储的。但是这也没有关系,进程隔离的时候,虚拟地址空间的数据也是明文存储的,也没有见到有什么需要防范的必要。
但是如果我们考虑物理攻击手段,那就不一定了。也就是攻击者直接把内存拆下来,然后读取其中的内容。这个时候仅依靠硬件隔离就不行了。
所以我们可以用一个密钥把内存加密了,然后把密钥放在 CPU 上,进出 CPU 的都是密文,解密和重加密过程都发生在 CPU 的内部。
3.5 完整性保护
即使完全看不见机密的数据,攻击者依然可以展开一些攻击,比如说:
- 重放攻击
- 重排攻击
- 篡改攻击
为了应对这些攻击,我们引入了完整性保护技术。这个技术由两个部分组成,MAC(Message Authentication Code)和 Merkle Tree。
MAC 主要用于防御这上面的三种攻击。对于一个数据 data ,我们有:
MAC = func(data, key, address, counter)
简单来说,key 是避免伪造数据的密钥,address 是数据的地址,counter 是数据的版本号。当我们把这些数据都通过某个特定的函数生成一个 summary,也就是 MAC 后,我们只需要比较我们计算出来的 MAC,和内存中原本保存的 MAC 是否相同,就可以确定 data 是否是特定的 address 特定的版本的数据了。
此时篡改和重排彻底失效,但是重放没有完全失效。MAC 对于重放的防御,依赖于 counter:攻击者如果只重放了 data 的内容(相当于回退版本了),但是没有回退 counter,那么就可以被 MAC 检测出来。但是如果攻击者同时也回退了 counter 呢?那么 MAC 就无能为力了。
然后我们来说一下 MAC 的粒度。粒度可以是整个隔离内存吗?并不可以,这太大了,并不方便。我们需要将其分成多个 chunk 分别进行 MAC。那么 chunk 的大小应该是多少呢?答案是一个 cache line 的大小(L1 / L2 / L3 cache line 大小通常一致,访存粒度也是相同),这跟 cache 本身没有关系,而是说这个大小,是 CPU 访问 DRAM 的大小。相当于是 CPU 每次访问内存的时候,都会做一次 MAC 的校验。
那么我们该如何完整防御重放攻击呢?就是使用 Merkle Tree。我理解的是,相当于是 Merkle Tree 提供了一种控制整个内存在同一个版本的能力。至于为什么使用 Tree 结构,是因为直接 trival 的控制,成本太高了。根的版本号保存在 CPU 中,避免被篡改。
四、案例
4.1 ARM TrustZone
这个案例中,就是只有硬件隔离的 TEE,并没有内存加密等组件。相当于引入了 EL3, 通过设置 NS bit,来区分 Normal World 和 Secure World。在 Normal World 里跑 Normal OS,在 Secure World 里跑 Secure OS。总的来说 TCB 还是挺大的。
之所以只有一个硬件隔离机制,是因为 TrustZone 并不是专门为了云服务器开发的,而是为了端侧手机开发的。所以并不会有一个黑客采用物理攻击手段。主要用于防止软件攻击。
4.2 Intel SGX / AMD SEV
更小的可信基,只有一段代码,被成为 enclave,OS / hypervisor 都不可信。首次引入了远程验证的机制。在使用的时候,普通程序代码通过 icall 来调用 enclave 的代码,就像调用函数一样。enclave 的代码,用 ecall 调用普通函数。
虽然这样可信基确实小了,但是相当于要改写程序,专门为 enclave 写代码,所以并不是很方便。而且 enclave 可以使用的隔离内存的大小是有限的。
这种最细粒度的机制,同样不是为了云厂商开发的,而是为了保护敏感数据,进行机密计算,比如说进行视频解密,防盗版等。
4.3 Intel TDX / AMD SEV-SNP
将整个 VM 作为 TEE,也就是说,恶意的 Hypervisor 是看不到 VM 里的内容的,Hypervisor 只能调度,而不能修改。这种技术基本上就是为了云服务开发的。
相当于租户可以完全透明的使用 VM,不用担心云厂商的窃取,也不用引入额外的修改。
4.4 ARM CCA
也是为云场景开发的。我理解就是有多个 Realm,但是我也不知道 Realm 是什么,大概就是 VM 吧。不过它有一个自己运行在 EL2 的 Hypervisor,被叫作 RMM(Realm Management Monitor)。