Intel® SGX 数据密封
2022-06-16
最后更新于
2022-06-16
最后更新于
By Gavin
Intel® Software Guard Extensions(Intel® SGX)是实现在第六代 CPU 之后的一组扩展指令集,诣于为用户态的应用程序提供一个可信执行环境。为此,Intel® SGX 提供了一个安全的内存容器 Enclave。Enclave 为其内部运行的应用程序提供一段安全的内存空间,在这段受保护空间中实行严格的访问控制和加密操作来实现对敏感数据机密性和完整性的保护,从而使得即使是 Hypervisor、BIOS、操作系统等特权应用都不能随意访问这段地址空间。
SGX 硬件加密的基础是 CPU 通过微码 (ucode) 添加 17 条指令, 连同 Intel® ME(Intel® CPU 上的安全处理器 ) 一起处理 Enclave 的根私钥等关键数据。
Intel® SGX 定义了 17 条新指令:12 条由 Supervisor 使用,5 条由用户使用。
请参考下图:
SGX 扩展指令集包含 17 条新指令,其中 5 条是用户指令,包括:
EENTER 进入飞地
EEXIT 退出飞地
ERESUME 重进飞地
EGETKEY 生成密钥
EREPORT 获得飞地测度报告
在 Enclave 中编写程序时可以直接调用用户指令。简单的操作背后是通过多条系统指令实现。由于 Enclave 的创建必须在内核空间中进行,且 Enclave 的交互仅限于用户空间应用程序,因此特权代码不能进入 Enclave,而非特权代码不能创建 Enclave。
每个支持 SGX 的 CPU 都包含两个存储在电子熔丝的根密钥:根供应密钥(RPK)和根密封密钥(RSK)。RPK 为 Intel® 所知,以实现远程验证过程;RSK 只为平台所知,以实现数据的密封。尽管 SGX 的攻击者模型中不包括物理攻击,但处理器架构的设计仍努力避免此类攻击,或者至少使提取密钥成为一个非常昂贵的操作,攻击者即使拥有足够的硬件读取电子熔丝,也只能使用破坏性的方式操作。这就是为什么只有加密版本的密钥被存储在电子熔丝中。
下图展示了 SGX 中的密钥结构
英特尔在制造过程中创建的第一个密钥是根供应密钥(RPK)。这个密钥是在一个名为 “Intel®密钥生成设施”(iKGF)的设施内部专用硬件安全模块(HSM)上随机生成的。英特尔公司负责维护一个包含 HSM 产生的所有密钥的数据库,因为它们是后续 SGX 相关服务实现认证的基础。RPK 被发送到多个生产设施,以嵌入处理器的电子熔丝内。
位于电子熔丝内部的第二把钥匙被称为根密封密钥(RSK)。它的生成是随机地且保证每把都是独一无二的。与 RSK 相反,英特尔宣布从他们的生产链中清除这些密钥的所有痕迹,从而保证平台对密钥的唯一拥有权。
根据设计,Enclave 无法访问根密钥,但可以访问根密钥派生出来的密钥。 Enclave 使用 EGETKEY 指令基于不同的请求参数和请求生成的密钥类型结合根密钥来生成不同用途的密钥。在 EGETKEY 请求中有几个较为重要的参数:
Security Version Number(SVN):CPU SVN 用来表示处理器的微指令更新版本,ISV SVN 用来代表 Enclave 代码版本。版本号可以自上而下兼容,但是无法通过老的版本号访问新的版本内容。
KeyName:EGETKEY 设置 KEYREQUEST 中的 KEYNAME 值来生成不同类型密钥。
MRENCLAVE:Enclave 身份标志,一种用于检测飞地正直性(integrity)的测度,包含属性以及页面位置、内容的哈希。
MRSIGNER:Enclave 身份标志,包含飞地作者的公钥哈希。
密钥派生有相关的密钥派生策略,这些策略允许使用可信的值,如 MRENCLAVE、MRSIGNER (关于 MRENCLAVE、MRSIGNER 会在后续进行讲解)、Enclave 的属性等。飞地不能派生属于另一个飞地的 MRENCLAVE 或 MRSIGNER 的相关密钥。
如图所示,派生密钥有五种:
Provisioning Key:由 RPK 派生,用于远程认证的信任根;
Provisioning Seal Key:由 RPK、RSK 共同派生,用于加密 Provisioning Key;
EINITTOKEN Key:Launch Key,由 RSK 派生,在飞地启动时生成一个令牌。未被Intel 签名的飞地若不获得此令牌则无法被处理器实例化;
Seal Key:由 RSK 派生,用于加密当前相关平台数据;
Report Key:由 RSK 派生,用于本地认证。
开发者只可使用 Seal Key 和 Report Key。
密封是对飞地的敏感数据进行加密的过程,以便持久地存储到磁盘。这样一来,即使飞地被关闭(由于电源事件或应用程序本身的原因),也可以检索到密封数据并随后重新启动。密封操作实质上是加密,是使用密封私钥进行的,该密钥对该特定平台和飞地来说是独一无二的,任何其他实体都不知道。
在制造过程中,一组独特的密钥被生成并存储在处理器的熔丝阵列中。其中有一把密钥不为英特尔所知,是用于派生后续密封密钥的关键组件之一。在关于派生的其他组件中,选择使用哪个飞地身份属性(密钥派生策略)是一个重要的决定。这个值由 sgx_seal_data_ex() 函数的 key_policy 参数或 EGETKEY 指令的 KEYREQUEST 策略参数指定。
有两个与飞地相关的身份需要我们了解。一个是飞地身份(Enclave identity),另一个是签名身份(Signing Identity)。飞地身份是由 MRENCLAVE 的值表示,它是飞地日志的加密哈希,经历了构建和初始化过程的每个步骤。MRENCLAVE 的值对应特定的飞地身份,因此使用飞地身份将限制对密封数据的访问,换而言之只限于该飞地的实例访问那些密封数据。如果该飞地构建了不同的版本,MRENCLAVE 的值也会变化。所以当使用飞地身份进行密封时,被密封的数据只对应相关飞地实例,而不会对应该飞地的多个版本。
当选择 SGX_KEYPOLICY_MRENCLAVE 策略时,飞地独享由当前飞地身份派生的 Seal Key 加密的数据。
签名身份是由授权机构提供,它在飞地构建时对飞地进行签名。这个值被称为 MRSIGNER,对所有由同一授权机构签署的飞地来说都是一样的。因此,它将允许一个 Seal Key 用于不同的飞地,包括同一飞地的不同版本。 开发者可以利用签名身份的特性在多个飞地中共享敏感数据。 当选择 SGX_KEYPOLICY_MRSIGNER 策略时,多个飞地共享由相同签名身份派生的 Seal Key 加密的数据。
Alon Jackson. Trust is in the Keys of the Beholder: Extending SGX Autonomy and Anonymity. Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3D
https://gramine.readthedocs.io/en/stable/sgx-intro.html
https://www.intel.com/content/www/us/en/developer/articles/technical/introduction-to-intel-sgx-sealing.html