文章目录
- 前言
- 一、Constructing an Enclave
- 1.1 ECREATE
- 1.2 EADD and EEXTEND Interaction
- 1.3 EINIT Interaction
- 1.4 Intel® SGX Launch Control Configuration
- 二、Enclave Entry and Exiting
- 2.1 Controlled Entry and Exit
- 2.2 Asynchronous Enclave Exit (AEX)
- 2.3 Resuming Execution after AEX
- 2.3.1 ERESUME Interaction
- 三、Calling Enclave Procedures
- 3.1 Calling Convention
- 3.2 Register Preservation
- 3.3 Returning to Caller
- 四、Intel® SGX Key and Attestation
- 4.1 Enclave Measurement and Identification
- 4.1.1 MRENCLAVE
- 4.1.2 MRSIGNER
- 4.1.3 CONFIGID
- 4.2 Security Version Numbers (SVN)
- 4.2.1 Enclave Security Version
- 4.2.2 Hardware Security Version
- 4.2.3 CONFIGID Security Version
- 4.3 Keys
- 4.3.1 Sealing Enclave Data
- 4.3.2 Using REPORTs for Local Attestation
- 5 EPC and Management of EPC Pages
- 5.1 EPC Implementation
- 5.2 OS Management of EPC Pages
- 5.2.1 Enhancement to Managing EPC Pages
- 5.3 Eviction of Enclave Pages
- 5.4 Loading an Enclave Page
- 5.5 Eviction of an SECS Page
- 5.6 Eviction of a Version Array Page
- 5.7 Allocating a Regular Page
- 5.8 Allocating a TCS Page
- 5.9 Trimming a Page
- 5.10 Restricting the EPCM Permissions of a Page
- 5.11 Extending the EPCM Permissions of a Page
- 5.12 VMM Oversubscription of EPC
- 六、Changes to Instruction Behavior Inside an Enclave
- 6.1 Illegal Instructions
- 6.2 RDRAND and RDSEED Instructions
- 6.3 PAUSE Instruction
- 6.4 Executions of INT1 and INT3 Inside an Enclave
- 6.5 INVD Handling when Enclaves Are Enabled
- 参考资料
前言
本文来自于 Intel vol3 :Chapter 35 Enclave Operation
《Intel SGX开发者参考手册 vol3》的第35章涵盖了有关enclave的操作方面的内容。该章节包括准备enclave、将控制权转移到enclave代码以及为enclave代码和支持enclave执行的系统软件的编程考虑等方面的指导。
以下是该章节涵盖的主题的简要说明:
(1)Enclave准备:
该部分讨论了准备enclave的步骤,包括创建enclave映像、设置enclave的初始状态以及初始化enclave的安全内存。
(2)进入和退出enclave模式:
介绍了从应用程序的非enclave模式切换到enclave模式以及反之的过程。
该部分解释了用于进入enclave模式的指令和机制,例如EENTER、ERDRNG和ERESUME。
还讨论了退出enclave模式的指令和机制,如EEXIT和EEXITRNG。
(3)Enclave控制权转移:
该部分解释了将控制权从应用程序转移到enclave代码的过程。
讨论了EENTER指令,该指令启动将控制权转移到enclave的过程。
该部分还涵盖了在控制权转移期间通过堆栈传递给enclave的参数。
(4)Enclave编程考虑:
提供了编写enclave代码的考虑事项和最佳实践。
主题包括enclave内部的内存管理、处理异常和中断、堆栈管理以及enclave内部的线程同步。
该部分还涵盖了enclave特定指令及其用法。
(5)系统软件的支持:
该部分侧重讲解系统软件在支持enclave执行方面的作用。
包括enclave生命周期管理、安全内存分配和enclave认证等主题。
该部分讨论了系统软件在保护enclave和管理其资源方面的责任。
一、Constructing an Enclave
图35-1展示了一个典型的Enclave内存布局:
enclave的创建、内存资源的分配以及通过测量最终确定enclave的身份包含多个阶段。以下是该过程的示例步骤:
(1)应用程序将enclave内容与enclave创建API所需的其他信息一起交给运行在特权级0的enclave创建服务。
(2)运行在特权级0的enclave创建服务使用ECREATE叶函数来设置初始环境,指定enclave的基地址和大小。这个地址范围,即ELRANGE,是应用程序的地址空间的一部分。这将保留内存范围,enclave将驻留在此地址区域。ECREATE还为SGX Enclave Control Structure (SECS)分配了一个Enclave Page Cache (EPC)页面。需要注意的是,该页面不需要是enclave线性地址空间的一部分,也不需要映射到进程中。
(3)enclave创建服务使用EADD叶函数将EPC页面添加到enclave,并使用EEXTEND来测量enclave的已提交内存内容。对于要添加到enclave的每个页面:
使用EADD将新页面添加到enclave。
如果enclave开发者需要对页面的内容进行测量作为证明,使用EEXTEND为页面的256字节添加一个测量值。重复此操作,直到整个页面都被测量。
(4)enclave创建服务使用EINIT叶函数完成enclave创建过程,并最终确定enclave测量结果以建立enclave身份。在执行EINIT之前,enclave不允许执行任何enclave代码(即通过执行EENTER进入enclave会导致错误)。
这些步骤描述了enclave的创建过程,包括分配内存资源、测量内存内容以及最终确定enclave的身份。通过这些步骤,enclave能够在安全的环境中运行,并确保其完整性和真实性。
1.1 ECREATE
ECREATE叶函数通过读取包含enclave地址范围(ELRANGE)、属性(ATTRIBUTES)和MISCSELECT位图以及SSAFRAMESIZE的SGX Enclave Control Structure (SECS),为enclave设置初始环境。然后,它将这些信息安全地存储在一个Enclave Page Cache (EPC)页面中。ELRANGE是应用程序的地址空间的一部分。ECREATE还初始化了enclave构建过程的加密日志。
ECREATE叶函数的作用是根据SGX Enclave Control Structure (SECS)中的相关信息来设置enclave的初始环境。SECS包含了enclave的地址范围(ELRANGE),由BASEADDR和SIZE定义,以及属性和位图(ATTRIBUTES和MISCSELECT)以及SSAFRAMESIZE。ECREATE会将这些信息安全地存储在Enclave Page Cache (EPC)页面中。ELRANGE是应用程序的地址空间的一部分。此外,ECREATE还会初始化enclave构建过程的加密日志,用于记录enclave的构建过程。
通过ECREATE函数,enclave能够建立起初始的运行环境,并将相关信息安全地存储在EPC页面中,确保了enclave的可信性和安全性。构建过程的加密日志也可以用于后续的验证和审计。
1.2 EADD and EEXTEND Interaction
一旦SECS被创建,可以通过EADD将enclave页面添加到enclave中。这涉及将一个空闲的EPC页面转换为PT_REG或PT_TCS页面。
当调用EADD时,处理器会更新EPCM(Enclave Page Cache Map)条目,包括页面类型(PT_REG或PT_TCS)、enclave用于访问页面的线性地址以及页面的enclave访问权限。它将页面与作为输入提供的SECS关联起来。EPCM条目的信息由硬件用于管理对页面的访问控制。EADD会记录EPCM信息到存储在SECS中的加密日志,并将来自EPC之外的未受保护内存中的4KB数据复制到分配的EPC页面中。
系统软件负责选择一个空闲的EPC页面。系统软件还负责提供要添加的页面类型、页面的属性、页面的内容以及要将页面添加到的SECS(enclave),这些由应用程序请求提供。如果提供的数据不正确,将导致EADD失败、加密日志错误,并在EINIT时导致失败。
在将页面添加到enclave后,软件可以通过调用EEXTEND来测量开发者确定的256字节区域。因此,要测量整个4KB页面,系统软件必须执行16次EEXTEND。每次调用EEXTEND都会向加密日志中添加关于正在测量的区域以及该部分的测量结果的信息。
加密日志中的条目定义了enclave的测量结果,对于确保enclave由不可信任的系统软件正确构建至关重要。通过加密日志,可以获得对enclave正确性的确信。
1.3 EINIT Interaction
EINIT是一个enclave的叶函数,用于初始化enclave。在系统软件完成添加和测量页面的过程后,需要通过EINIT来初始化enclave。一旦enclave被初始化,对于该enclave,EADD和EEXTEND将被禁用(尝试对已初始化的enclave执行EADD/EEXTEND将导致错误)。初始化过程最终完成加密日志的处理,并建立了由EGETKEY和EREPORT使用的enclave identity和sealing identity。
加密日志的哈希值被存储为enclave identity。正确构建的enclave会导致加密日志的哈希值与enclave所有者构建的哈希值匹配,后者作为SIGSTRUCT的ENCLAVEHASH字段包含其中。EREPORT叶函数提供的enclave identity可以由远程方进行验证。EINIT叶函数检查EINIT令牌以验证enclave是否已在此平台上启用。如果enclave构建不正确,或EINIT令牌对该平台无效,或SIGSTRUCT没有正确签名,则EINIT将失败。有关错误报告的详细信息,请参阅EINIT叶函数。
enclave identity是一个加密哈希值,反映了enclave的属性和MISCSELECT值、enclave的内容、构建顺序、在内存中占用的地址、每个页面的安全属性和访问权限。enclave identity由EINIT叶函数建立。
sealing identity由密封机构管理,其表示通过EINIT处理的SIGSTRUCT结构使用的公钥的哈希值。密封机构为特定的enclave身份分配产品ID(ISVPRODID)和安全版本号(ISVSVN)。
EINIT使用以下步骤来建立密封身份:
(1)验证SIGSTRUCT是否使用SIGSTRUCT中的公钥进行了正确签名。
(2)检查enclave的测量结果是否与SIGSTRUCT中指定的测量结果匹配。
(3)检查enclave的属性和MISCSELECT值是否与SIGSTRUCT中指定的值兼容。
(4)最终确定enclave的测量结果,并记录sealing identity(密封机构、产品ID和安全版本号)和enclave identity在SECS中。
(5)设置enclave的ATTRIBUTES.INIT位。
通过这些步骤,EINIT建立了enclave的sealing identity,并将其与enclave identity进行关联,确保了enclave的正确性和安全性。
1.4 Intel® SGX Launch Control Configuration
Intel® SGX Launch Control是一组控制机制,用于管理enclave的创建。在EINIT叶函数成功初始化一个enclave之前,指定的Launch Enclave必须为该enclave创建一个EINITTOKEN。Launch Enclave具有SECS.ATTRIBUTES.EINITTOKEN_KEY = 1,使其能够从EGETKEY叶函数中访问EINITTOKEN_KEY。Launch Enclave在计算EINITTOKEN的消息认证码(MAC)时必须使用EINITTOKEN_KEY。
用于签署Launch Enclave的SIGSTRUCT的公钥的哈希值必须等于IA32_SGXLEPUBKEYHASH MSR中的值。只有Launch Enclave允许在没有有效令牌的情况下启动。
IA32_SGXLEPUBKEYHASH MSR用于指定平台的Launch Enclave。IA32_SGXLEPUBKEYHASH在复位后默认为Intel的启动enclave签名密钥的摘要。
IA32_FEATURE_CONTROL的第17位控制IA32_SGXLEPUBKEYHASH MSR的权限,当CPUID.(EAX=12H, ECX=00H):EAX[0] = 1时。如果IA32_FEATURE_CONTROL被锁定,并且第17位设置为1,则可以重新配置(可写入)IA32_SGXLEPUBKEYHASH MSR。如果IA32_FEATURE_CONTROL没有被锁定或第17位清零,则MSR为只读。通过将这些MSR保持可写状态,系统软件或虚拟机监视器可以支持多个Launch Enclave,用于托管多个执行环境。更多详细信息请参阅 Intel vo3 表39.2.2。
总之,Intel® SGX Launch Control是用于管理enclave创建的一组控制机制。Launch Enclave是唯一可以在没有有效令牌的情况下启动的enclave。IA32_SGXLEPUBKEYHASH MSR用于指定平台的Launch Enclave,并且通过IA32_FEATURE_CONTROL进行权限控制。
二、Enclave Entry and Exiting
2.1 Controlled Entry and Exit
EENTER叶函数是以程序控制方式进入enclave的方法。要执行EENTER,软件必须提供一个属于要进入的enclave的TCS(线程控制结构)的地址。TCS保存了将控制转移至enclave内部的位置,以及AEX应该将寄存器状态存储到的enclave内部的SSA帧的指针。
当逻辑处理器进入enclave时,TCS被视为繁忙,直到逻辑处理器退出enclave。尝试通过繁忙的TCS进入enclave将导致错误。Intel® SGX允许enclave构建者定义多个TCS,从而支持多线程enclave。
软件还必须向EENTER提供异步退出指针(Asynchronous Exit Pointer – AEP)参数。AEP是enclave外部的一个地址,异常处理程序将使用IRET指令返回到该地址。通常,该位置包含ERESUME指令,该指令将控制传递回enclave,到从enclave线程的保存状态中检索到的地址。
EENTER执行以下操作:
(1)检查TCS是否空闲,并刷新所有缓存的线性到物理映射。
(2)将操作模式更改为enclave模式。
(3)保存旧的RSP(栈指针)和RBP(基指针),以便在AEX时进行恢复(软件负责设置enclave内部要使用的新RSP和RBP)。
(4)保存XCR0寄存器,并用enclave的XFRM(XSAVE特性请求掩码)值替换它。
(5)检查软件是否希望启用调试(适用于可调试的enclave):
如果不进行调试,则配置硬件使enclave看起来像一个单一指令。
如果进行调试,则配置硬件以允许在enclave内部触发陷阱、断点和单步执行。
(6)将TCS设置为繁忙状态。
(7)将控制从enclave外部转移到由TCS指定的enclave内部的预定位置。
EEXIT叶函数是以程序控制方式离开enclave的方法。EEXIT接收enclave希望转移控制的enclave外部目标地址。enclave软件有责任在调用EEXIT之前从寄存器中清除任何机密信息。为了方便enclave软件执行外部函数调用并重新进入enclave(使用EEXIT和EENTER叶函数),EEXIT返回进入enclave时使用的AEP的值。
EEXIT执行以下操作:
(1)清除enclave模式并刷新所有缓存的线性到物理映射。
(2)将TCS标记为非繁忙状态。
(3)将控制从enclave内部转移到EEXIT叶函数的参数指定的外部位置。
2.2 Asynchronous Enclave Exit (AEX)
在enclave内执行期间,可能会发生异步和同步的事件,如异常、中断、陷阱、SMI(System Management Interrupt)和VM退出。这些事件被称为Enclave Exiting Events(EEE)。在发生EEE时,处理器状态会被安全地保存在enclave内部(在线程的当前SSA帧中),然后被一个合成状态所替代,以防止机密信息泄露。安全保存状态并建立合成状态的过程称为异步enclave退出(AEX)。AEX的详细信息在《Intel vo3 第36章:Enclave Exiting Events》中有描述。
在大多数EEE中,AEP被推入堆栈作为事件地址的位置。这是在执行IRET后控制将返回的位置。从该点执行ERESUME叶函数可以重新进入enclave并从中断点恢复执行。
完成AEX后,逻辑处理器不再处于enclave模式,退出事件会被正常处理。AEX完成后发生的任何新事件都被视为在enclave外部发生的事件(例如,在调度中分派到中断处理程序时的页面故障)。
2.3 Resuming Execution after AEX
在系统软件处理导致逻辑处理器退出enclave的事件后,逻辑处理器可以使用ERESUME继续enclave执行。ERESUME恢复处理器状态并将控制返回到中断执行的位置。
如果导致退出的原因是异常或故障,并且未解决,如果使用ERESUME重新进入enclave,事件将再次触发。例如,如果一个enclave执行了除以0的操作,执行ERESUME将导致enclave尝试重新执行导致故障的指令,并导致另一个除以0异常。Intel® SGX提供了一种让enclave开发者从enclave内部处理enclave异常的方法。软件可以在不同的位置进入enclave,并通过执行EENTER叶函数在enclave内部调用异常处理程序。enclave内部的异常处理程序可以从SSA帧中读取故障信息,并尝试解决故障条件,或者简单地返回并指示软件终止enclave(例如,使用EEXIT)。
2.3.1 ERESUME Interaction
根据enclave的模式(32位或64位),ERESUME会恢复寄存器的值。
(1)在32位模式下(IA32_EFER.LMA = 0 || CS.L = 0),将从当前SSA帧的线程GPR区域中恢复传统寄存器(EAX、EBX、ECX、EDX、ESP、EBP、ESI、EDI、EIP和EFLAGS)的低32位。传统寄存器的高32位以及64位寄存器(R8…R15)不会加载。
(2)在64位模式下(IA32_EFER.LMA = 1 && CS.L = 1),将加载所有通用处理器寄存器(RAX、RBX、RCX、RDX、RSP、RBP、RSI、RDI、R8…R15、RIP和RFLAGS)的64位。
根据SECS.ATTRIBUTES.XFRM定义的扩展特性,将从当前SSA帧的XSAVE区域中恢复。x87区域的布局取决于IA32_EFER.LMA和CS.L的当前值:
(1)IA32_EFER.LMA = 0 || CS.L = 0:以与XSAVE/FXSAVE使用相同格式的32位加载方式。
(2)IA32_EFER.LMA = 1 && CS.L = 1:以与XSAVE/FXSAVE使用相同格式的64位加载方式,就像REX.W = 1一样。
三、Calling Enclave Procedures
3.1 Calling Convention
在标准的调用约定中,子例程的参数通常被推入堆栈。被调用的例程,由于了解自己的堆栈布局,可以根据编译时可计算的偏移量从SP或BP寄存器(取决于编译器使用的运行时约定)找到参数。
由于调用enclave时发生了堆栈切换,无法以这种方式找到位于堆栈中的参数。进入enclave需要修改的参数传递约定。
例如,调用者可以将参数推入不可信的堆栈,然后通过RAX将指向这些参数的指针传递给enclave软件。具体的调用约定选择由边缘例程的编写者决定,无论这些例程是手工编码还是由编译器生成的。
3.2 Register Preservation
与大多数系统类似,被调用方(callee)有责任保存除用于返回值的寄存器之外的所有寄存器。这与传统用法一致,并且倾向于优化需要执行的寄存器保存/恢复操作的数量。这还具有额外的安全效果,可以确保将数据从enclave使用的任何寄存器中清除,这些寄存器被用于临时存储机密信息。
3.3 Returning to Caller
在执行EEXIT期间,不会修改任何寄存器的值。在执行EEXIT之前,软件有责任清除寄存器中的机密信息。
四、Intel® SGX Key and Attestation
4.1 Enclave Measurement and Identification
在enclave构建过程中,对每个enclave进行了两次“measurements - 测量”,并将其存储在两个256位的测量寄存器(Measurement Registers,MR)中:MRENCLAVE和MRSIGNER。MRENCLAVE代表enclave的内容和构建过程,而MRSIGNER代表对enclave的SIGSTRUCT进行签名的实体。测量寄存器的值包含在认证中,以便将enclave标识给远程方。这些MR也包含在大多数密钥中,将密钥与具有特定MR的enclave绑定在一起。
4.1.1 MRENCLAVE
MRENCLAVE是一个唯一的256位值,用于标识在初始启动期间加载到enclave中的代码和数据。它是通过SHA256哈希计算得出的,由ECREATE leaf函数进行初始化。EADD和EEXTEND leaf函数记录了关于每个页面和这些页面内容的信息。EINIT leaf函数完成哈希的最终计算,并将其存储在SECS.MRENCLAVE中。如果对构建过程、页面内容、页面权限等进行任何篡改,都将导致不同的MRENCLAVE值。
图35-2展示了在构建enclave时MRENCLAVE寄存器的变化简化流程:
(1)使用ECREATE进行enclave创建。
(2)使用EADD将非enclave源页面复制到未初始化的enclave的EPC中。
(3)在修改enclave的页面内容后,通过两次EEXTEND更新MRENCLAVE。
(4)使用EINIT完成enclave的构建。
有关插入哈希中的特定值的详细信息,请参阅各个指令的定义。
4.1.2 MRSIGNER
每个enclave都使用一个3072位的RSA密钥进行签名。签名存储在SIGSTRUCT中。在SIGSTRUCT中,enclave的签名者还为enclave分配了产品ID(ISVPRODID)和安全版本号(ISVSVN)。MRSIGNER是签名者公钥的SHA-256哈希值。对于支持键分离和共享(CPUID.(EAX=12H, ECX=1).EAX.KSS[7])的平台,SIGSTRUCT还可以指定一个16字节的扩展产品ID(ISVEXTPRODID)和一个16字节的家族ID(ISVFAMILYID)。
在认证中,可以使用MRSIGNER来基于作者来批准enclave,而无需维护MRENCLAVE的列表。它在密钥派生中使用,以便软件可以创建应用程序的血统。通过使用相同的密钥对多个enclave进行签名,这些enclave将共享相同的密钥和数据。结合安全版本编号,作者可以发布应用程序的多个版本,这些版本可以访问先前版本的密钥,但不能访问该应用程序的未来版本的密钥。
4.1.3 CONFIGID
对于支持键分离和共享增强功能(CPUID.(EAX=12H, ECX=1).EAX.KSS[7])的平台,在创建enclave时,平台可以额外提供一个32字节的配置标识符(CONFIGID)。这个值的使用取决于enclave的具体情况,但其目的是允许enclave创建者指示在初始化后enclave可能接受的其他内容。
4.2 Security Version Numbers (SVN)
Intel® SGX支持一种版本系统,允许签名者标识同一作者发布的软件的不同版本。安全版本与作者使用的功能版本无关,旨在指定安全等效性。如果多个具有功能增强的发布版本具有相同的安全属性或状态,则它们可以共享相同的安全版本号(SVN)。每个enclave都有一个SVN,底层硬件也有一个SVN。
SVN在EREPORT中进行认证,并包含在大多数密钥的派生中,从而在较旧/较新版本之间提供数据分离。
4.2.1 Enclave Security Version
在SIGSTRUCT中,MRSIGNER与一个16位的产品ID(ISVPRODID)和一个16位整数的安全版本号(ISVSVN)相关联。它们共同定义了一个特定产品的一组特定版本。大多数密钥,包括密封密钥(Seal Key),可以与这对值绑定。
为了支持从一个版本升级到另一个版本,EGETKEY将返回与软件的ISVSVN小于或等于的任何值对应的密钥。
4.2.2 Hardware Security Version
CPUSVN是一个128位的值,反映了处理器支持的微码更新版本和经过身份验证的代码模块。与ISVSVN不同,CPUSVN不是整数,不能进行数学比较。并非所有的值都是有效的CPUSVN。
软件必须确保提供给EGETKEY的CPUSVN是有效的。EREPORT将返回当前环境的CPUSVN。软件可以执行将TARGETINFO设置为零的EREPORT,以从REPORTDATA中检索CPUSVN。只要CPUSVN中反映的每个元素相同或已升级,软件就可以访问先前记录的CPUSVN对应的密钥。
4.2.3 CONFIGID Security Version
CONFIGID字段可以用于包含用于验证附加内容的签名密钥的哈希值。在这种情况下,类似于MRSIGNER和ISVSVN之间的关系,CONFIGID需要一个CONFIGID安全版本号(CONFIGIDSVN)。CONFIGIDSVN可以同时指定。
4.3 Keys
Intel® SGX提供了软件访问每个处理器独有的密钥,并且这些密钥以在制造过程中插入处理器的硬件密钥为根。
每个enclave使用EGETKEY叶函数请求密钥。密钥基于enclave的参数,如度量值、enclave签名密钥、enclave的安全属性以及处理器的硬件安全版本。KEYREQUEST结构中指定了参数选项的完整列表,详细信息请参阅Intel vo3第34.18节。
通过使用enclave属性推导密钥,SGX确保如果两个enclave调用EGETKEY,它们将接收到仅对各自enclave可访问的唯一密钥。它还保证在每次未来执行EGETKEY时,enclave将接收到相同的密钥。某些参数是可选的或可由软件配置。例如,Seal密钥可以基于enclave的签名者,从而生成一个对多个由同一方签名的enclave可用的密钥。
EGETKEY叶函数提供了多种密钥类型。每个密钥都是特定于处理器、CPUSVN和执行EGETKEY的enclave的。EGETKEY指令定义了如何推导这些密钥,详见37-64表。此外,
(1)SEAL密钥:Seal密钥是enclave用于保护密钥的通用密钥。Seal密钥的典型用途是加密和计算磁盘上的密钥的MAC。第4.3.1节中描述了两种类型的Seal密钥。
(2)REPORT密钥:该密钥用于计算REPORT结构的MAC。EREPORT叶函数用于计算此MAC,并且目的enclave使用Report密钥来验证MAC。软件使用流程的详细信息请参阅第4.3.2节。
(3)EINITTOKEN_KEY:此密钥由Launch Enclave用于计算EINITTOKEN的MAC。然后在EINIT叶函数中验证这些令牌。只有将ATTRIBUTE.EINITTOKEN_KEY设置为1的enclave才能使用该密钥。
(4)PROVISIONING Key和PROVISIONING SEAL密钥:这些密钥由认证密钥配置软件用于向远程方证明处理器的真实性,并标识当前执行的TCB。只有将ATTRIBUTE.PROVISIONKEY设置为1的enclave才能使用这些密钥。
4.3.1 Sealing Enclave Data
Enclaves可以使用Seal密钥来保护持久数据,提供加密和/或完整性保护。EGETKEY提供了两种类型的Seal密钥,可以在KEYREQUEST.KEYPOLICY字段中指定:基于MRENCLAVE的密钥和基于MRSIGNER的密钥。
基于MRENCLAVE的密钥仅对共享相同MRENCLAVE的enclave实例可用。如果发布了enclave的新版本,Seal密钥将会不同。检索先前的数据需要额外的软件支持。
基于MRSIGNER的密钥与3元组(MRSIGNER,ISVPRODID,ISVSVN)绑定。只要具有相同的MRSIGNER和ISVPRODID,并且ISVSVN等于或大于所需密钥的enclave,就可以使用这些密钥。这对于允许同一软件的新版本检索升级前创建的密钥非常有价值。
对于支持密钥分离和共享增强功能的平台(CPUID.(EAX=12H, ECX=1).EAX.KSS[7]),提供了四个额外的密钥派生策略用于Seal密钥的派生。这些策略增加了ISVEXTPRODID、ISVFAMILYID以及CONFIGID/CONFIGSVN到密钥派生中。此外,还有一种策略可以从密钥派生中删除ISVPRODID,以创建在共享相同MRSIGNER的不同产品之间共享的密钥。
4.3.2 Using REPORTs for Local Attestation
SGX提供了一种让enclave安全地互相识别的方法,称为"本地认证"(Local Attestation)。SGX提供了一个硬件断言,即REPORT,其中包含调用enclave的属性、度量值和用户提供的数据(在Intel vol3第34.16节中详细描述)。图35-3显示了信息的基本流程:
(1)源enclave确定目标enclave的身份以填充TARGETINFO。
(2)源enclave调用EREPORT指令生成一个REPORT结构。EREPORT指令执行以下操作:
填充REPORT中有关调用enclave的身份信息。
派生Report密钥,在目标enclave执行EGETKEY时返回该密钥。TARGETINFO提供有关目标的信息。
使用派生的目标enclave Report密钥对REPORT进行MAC计算。
(3)非enclave软件将REPORT从源复制到目标。
(4)目标enclave执行EGETKEY指令请求其REPORT密钥,该密钥与源处的EREPORT使用的密钥相同。
(5)目标enclave验证MAC,然后可以检查REPORT以识别源。
5 EPC and Management of EPC Pages
EPC(Enclave Page Cache)布局是特定实现的,并通过CPUID进行枚举(请参阅表33-7以获取EPC布局)。EPC通常在系统启动时由BIOS进行配置。
5.1 EPC Implementation
为了保护EPC(Enclave Page Cache)免受攻击,必须采取适当的安全措施。其中一种EPC实现的例子是使用内存加密引擎(Memory Encryption Engine,MEE)。MEE提供了一种经济高效的机制,可以使用平台的DRAM(动态随机存取存储器)创建具有密码保护的易失性存储。这些单元提供完整性、重播和机密性保护。具体细节取决于实现方式。
内存加密引擎是一种硬件组件,用于保护EPC中的数据。它通过加密EPC中存储的数据来确保数据的完整性、重播保护和机密性。
5.2 OS Management of EPC Pages
EPC(Enclave Page Cache)是一种有限的资源。SGX1(即CPUID.(EAX=12H, ECX=0):EAX.SGX1 = 1,但CPUID.(EAX=12H, ECX=0):EAX.SGX2 = 0)为EPC管理器提供了叶函数来管理这个资源,并正确地将页面从EPC中换出和换入。为此,EPC管理器需要跟踪所有的EPC条目,包括类型和状态、上下文归属以及SECS(Secure Enclave Control Structure)归属。
作为可能被驱逐的enclave页面,应使用EBLOCK指令将其移动到BLOCKED状态,确保任何尝试引用BLOCKED页面的操作都无法创建新的虚拟地址到物理地址的映射。
在驱逐被阻塞页面之前,EPC管理器应对该enclave执行ETRACK叶函数,并确保任何线程上的平台中的所有阻塞页面的缓存的虚拟地址到物理地址的映射都是最新的。
在从阻塞页面中删除所有陈旧的映射后,系统软件应使用EWB叶函数安全地将页面从EPC中驱逐。EWB对EPC中的页面进行加密,将其写入非受保护的内存,并使EPC中的副本无效。此外,EWB还创建页面的加密MAC(PCMD.MAC)并将其存储在非受保护的内存中。只有数据和MAC匹配时,页面才能重新加载到处理器中。为确保只能加载回被驱逐页面的最新版本,被驱逐页面的版本被安全地存储在EPC中的版本数组(Version Array,VA)中。
SGX1包括两个指令用于重新加载被系统软件驱逐的页面:ELDU和ELDB。这两个指令之间的区别在于指令结束时的分页状态的值。ELDU导致页面重新加载并设置为UNBLOCKED状态,而ELDB导致页面加载到BLOCKED状态。ELDB用于虚拟机监视器(Virtual Machine Monitor,VMM)。当VMM重新加载被驱逐页面时,它需要将其恢复到页面在被驱逐时的正确状态(BLOCKED vs. UNBLOCKED)。根据页面在驱逐时的状态,VMM选择使用ELDB或ELDU。
5.2.1 Enhancement to Managing EPC Pages
在支持SGX2(即CPUID.(EAX=12H, ECX=0):EAX.SGX2 = 1)的处理器上,EPC管理器可以通过SGX2叶函数更灵活地管理EPC资源(在enclave运行时)。关于额外的灵活性,具体描述在第5.7节到第5.11节。
5.3 Eviction of Enclave Pages
Intel SGX分页经过优化,允许操作系统(OS)在一次同步下将多个页面逐出EPC。
驱逐一组页面从EPC的建议流程如下:
(1)对于要从EPC中驱逐的每个页面:
a. 在Version Array(VA)页面中选择一个空的插槽。
如果没有空的VA页面插槽存在,则使用EPA叶函数创建一个新的VA页面。
b. 从enclave上下文的映射表(页表和EPT表)中移除线性地址到物理地址的映射。
c. 执行EBLOCK叶函数来将目标页面状态设置为BLOCKED。此时,页面不会创建新的映射。因此,任何未在TLB缓存中具有映射的访问都将生成#PF(页面故障)。
(2)对于包含在步骤1中选择的页面的每个enclave:
执行ETRACK叶函数,指向该enclave的SECS(Secure Enclave Control Structure)。这会启动跟踪过程,确保清除对被阻塞页面的线性地址到物理地址转换的所有缓存。
(3)对于包含在步骤1中选择的enclave中执行的所有逻辑处理器(操作系统或虚拟机监视器):
向这些线程发出IPI(跨处理器中断)。这将导致逻辑处理器异步退出可能存在的任何enclave,并刷新可能包含对被阻塞页面的过时转换的缓存。无需额外措施,如执行"TLB shootdown"。
(4)enclave退出后,允许逻辑处理器恢复正常操作,包括重新进入enclave,因为跟踪逻辑会跟踪活动情况。
(5)对于要驱逐的每个页面:
使用EWB叶函数进行页面驱逐,参数包括指向EPC页面的有效地址指针、VA插槽、用于保存加密页面内容的4K字节缓冲区和用于保存页面元数据的128字节缓冲区。最后三个元素在加密上是加密关联的,稍后必须用于重新加载页面。
此时,系统软件在主存中具有每个页面数据的唯一副本,以加密形式存储,并附带页面元数据。
5.4 Loading an Enclave Page
要重新加载先前驱逐的页面,系统软件需要四个要素:页面被驱逐时使用的VA插槽、包含加密页面内容的缓冲区、包含页面元数据的缓冲区以及要关联该页面的父SECS。如果VA页面或父SECS尚未在EPC中,必须首先重新加载它们。
(1)执行ELDB/ELDU指令(取决于页面所需的BLOCKED状态),并传递以下参数:EPC页面线性地址、VA插槽、加密页面和页面元数据。
(2)在enclave上下文的映射表(页表和EPT表)中创建映射,以允许应用程序访问该页面(操作系统:系统页表;虚拟机监视器:EPT)。
ELDB/ELDU指令将标记VA插槽为空,以防止以后重播该页面。
5.5 Eviction of an SECS Page
SECS页面的驱逐与enclave页面的驱逐类似。唯一的区别在于,直到该enclave的所有其他页面被驱逐之前,无法驱逐SECS页面。由于所有其他页面已被驱逐,不会有线程在enclave内执行,因此不需要使用ETRACK进行跟踪。在重新加载enclave时,必须先重新加载SECS页面,然后再重新加载所有其他组成页面。
(1)确保从enclave中驱逐所有页面。
(2)在Version Array(VA)页面中选择一个空的插槽。
如果没有具有空插槽的VA页面存在,则使用EPA函数叶创建一个新的VA页面。
(3)使用EWB叶函数进行页面驱逐,参数包括指向EPC页面的有效地址指针、VA插槽、用于保存加密页面内容的4K字节缓冲区和用于保存页面元数据的128字节缓冲区。最后三个元素在加密上是加密关联的,并且稍后必须用于重新加载页面。
5.6 Eviction of a Version Array Page
VA页面不属于任何enclave,因此不需要使用ETRACK进行跟踪。在驱逐VA页面时,必须指定不同的VA页面中的插槽,以提供对被驱逐的VA页面的版本控制。
(1)在要驱逐的VA页面之外的另一个VA页面中选择一个插槽。
如果没有具有空插槽的VA页面存在,则使用EPA函数叶创建一个新的VA页面。
(2)使用EWB叶函数进行页面驱逐,参数包括指向EPC页面的有效地址指针、VA插槽、用于保存加密页面内容的4K字节缓冲区和用于保存页面元数据的128字节缓冲区。最后三个元素在加密上是加密关联的,并且稍后必须用于重新加载页面。
第5.7节到第5.12节可跳过:
第5.7节到第5.11节都是在支持SGX2的处理器的扩展功能。
第5.12是VMM Oversubscription功能
5.7 Allocating a Regular Page
在支持SGX2的处理器上,为已初始化的enclave分配新页面是通过调用EAUG函数叶来完成的。通常,enclave请求操作系统在enclave地址空间的特定位置分配新页面。一旦分配,页面将保持在待处理状态,直到enclave执行相应的EACCEPT函数叶将新页面接受到enclave中。页面分配操作可以批量处理以提高效率。
分配常规页面的典型过程如下:
(1)当当前分配的内存不足时,enclave向操作系统请求额外的内存。
(2)操作系统调用EAUG函数叶将新内存页添加到enclave中。
a. 只能在空闲的EPC页面上调用EAUG。
b. EAUG指令成功完成后,将目标页面置于有效(VALID)和待处理(PENDING)状态。
c. 所有动态创建的页面的类型为PT_REG,并且内容全为零。
(3)操作系统在enclave上下文的映射表中映射该页面。
(4)enclave发出EACCEPT指令,该指令验证页面的属性并清除待处理状态。此时,页面变为可供enclave正常使用的状态。
5.8 Allocating a TCS Page
在支持SGX2的处理器上,为已初始化的enclave分配新的TCS页面是一个两步的过程。首先,操作系统通过调用EAUG函数分配一个常规页面。然后,该页面必须由所属的enclave接受和初始化。一旦页面以适当的TCS页面值进行初始化,enclave会请求操作系统将页面的类型更改为PT_TCS。这个更改也必须被接受。与分配常规页面一样,TCS分配操作可以批处理。
分配TCS页面的典型过程如下:
(1)Enclave请求操作系统提供额外的页面。
(2)操作系统调用EAUG函数将一个新的常规内存页面添加到enclave中。
a. 只能在空闲的EPC页面上调用EAUG。
b. EAUG指令成功完成后,将目标页面置于有效(VALID)和待处理(PENDING)状态。
(3)操作系统在enclave上下文的映射表中映射该页面。
(4)enclave发出EACCEPT指令,此时页面变为可供enclave正常使用的状态。
(5)enclave初始化新页面的内容。
(6)enclave请求操作系统将页面从PT_REG类型转换为PT_TCS类型。
(7)操作系统在页面上发出EMODT指令。
a. EMODT的参数指示将常规页面转换为TCS页面。
b. EMODT强制删除对页面的所有访问权限,因为TCS页面不允许enclave代码访问。
(8)enclave发出EACCEPT指令以确认所请求的修改。
5.9 Trimming a Page
在支持SGX2的处理器上,Intel SGX支持将enclave页面回收(解分配)作为EMODT的一种特殊情况。回收允许enclave积极参与从enclave中删除页面的过程,该过程将分为首先从enclave的访问中删除页面,然后使用EREMOVE函数从EPC中删除页面。页面类型PT_TRIM表示页面已从enclave的地址空间中删除,并且页面不再对enclave软件可访问。不允许对PT_TRIM状态的页面进行修改;在enclave可以再次使用页面之前,必须将页面从enclave中删除,然后由操作系统重新分配。页面解分配操作可以批处理以提高效率。
从enclave中回收页面的典型过程如下:
(1)Enclave向操作系统发出信号,指示某个页面不再使用。
(2)操作系统调用EMODT函数叶,请求更改页面的类型为PT_TRIM。
a. SECS和VA页面不能以此方式进行回收,因此页面的初始类型必须是PT_REG或PT_TCS。
b. EMODT只能在有效的enclave页面上调用。
(3)操作系统在包含页面的enclave上调用ETRACK函数叶,以跟踪从所有处理器中删除TLB地址的过程。
(4)向执行包含enclave的进程的所有逻辑处理器发出IPI(跨处理器中断),以刷新过时的线性地址到物理地址的转换。
(5)Enclave发出EACCEPT函数叶。
(6)现在,操作系统可以永久地从EPC中删除页面(通过发出EREMOVE函数)。
5.10 Restricting the EPCM Permissions of a Page
在支持SGX2的处理器上,通过使用EMODPR函数叶来限制与enclave页面关联的EPCM权限。此操作需要操作系统的协作,以刷新页面的陈旧条目并更新页面表权限以匹配。权限限制操作可以进行批处理。
限制enclave页面权限的典型过程如下:
(1)Enclave请求操作系统限制EPC页面的权限。
(2)操作系统执行权限限制操作,刷新缓存的线性地址到物理地址的转换,并修改页面表。
a. 调用EMODPR函数叶来限制权限(EMODPR只能在有效页面上调用)。
b. 在包含页面的enclave上调用ETRACK函数叶,以跟踪从所有处理器中删除TLB地址的过程。
c. 向执行包含enclave的进程的所有逻辑处理器发出IPI(跨处理器中断),以刷新过时的线性地址到物理地址的转换。
d. 发送IPI以触发enclave线程退出和TLB清除。
e. 操作系统通知enclave,所有逻辑处理器现在应该看到新的受限权限。
(3)Enclave调用EACCEPT函数叶。
a. 在整个过程中,enclave可以访问页面。
b. 成功调用EACCEPT确保没有陈旧的缓存的线性地址到物理地址的转换。
5.11 Extending the EPCM Permissions of a Page
在支持SGX2的处理器上,enclave直接使用EMODPE函数叶来扩展与enclave页面关联的EPCM权限。在执行EPCM权限扩展后,enclave请求操作系统更新页面表权限以匹配扩展的权限。从安全角度来看,权限扩展不需要enclave线程离开enclave,因为具有对更严格权限的陈旧引用的TLB将按需刷新,但为了允许前进,操作系统需要知道应用程序可能会发出页面错误信号。
扩展enclave页面权限的典型过程如下:
(1)Enclave调用EMODPE函数叶,扩展与EPC页面关联的EPCM权限(EMODPE只能在有效页面上调用)。
(2)Enclave请求操作系统更新页面表以匹配新的EPCM权限。
(3)Enclave代码继续执行。
a. 如果存在对更严格权限的缓存的线性地址到物理地址的转换,则enclave线程将发生页面错误。SGX2感知的操作系统将看到页面表允许访问并恢复线程,此时线程可以成功访问页面,因为退出操作已清除了TLB。
b. 如果不存在缓存的线性地址到物理地址的转换,则使用新权限访问页面将成功而无需enclave退出。
5.12 VMM Oversubscription of EPC
在支持oversubscription增强功能的处理器上(即CPUID.(EAX=12H, ECX=0):EAX[5]=1 & EAX[6]=1),虚拟机监视器(VMM)或其他执行程序可以更有效地管理平台上可用的EPC空间,以在虚拟化实体之间进行oversubscription。支持oversubscription物理EPC空间的典型过程如下:
(1)VMM创建SECS跟踪的数据结构,包括子页面计数。
(2)VMM选择可能的EPC受害者页面。
(3)VMM使受害者页面老化。选择的一些页面将由客户机访问。在这种情况下,VMM将从受害者池中移除这些页面并将其返回给客户机。
(4)VMM将其余页面设置为EPT中不存在。然后,对每个页面发出IPI以删除TLB映射。
(5)对于每个EPC受害者页面,VMM使用ERDINFO获取受害者的SECS页面信息。
a. RDINFO结构中的ENCLAVECONTEXT字段将指示SECS的位置,PAGE_TYPE字段将指示页面类型。
b. SECS的子页面可以被驱逐。
c. 如果子计数为零,可以驱逐SECS页面。
d. 根据页面类型或子计数等条件,某些页面可能会返回到活动状态。
(6)VMM为每个页面的SECS增加驱逐页面计数(存储在第1步创建的数据结构中)。
(7)如果这是该SECS的第一个被驱逐的页面,则在受害者页面的SECS上设置标记(EINCVIRTCHILD)。这将锁定客户机中的SECS。客户机无法将SECS页面换出。
(8)对页面执行EBLOCK、ETRACK、EWB驱逐序列。
(9)在将SECS页面加载回来后,VMM将使用ESETCONTEXT指令为客户机设置正确的ENCLAVECONTEXT。
六、Changes to Instruction Behavior Inside an Enclave
本节介绍在enclave模式下执行时行为发生变化的指令。
6.1 Illegal Instructions
表格35-1中列出的指令是在ring 3执行时合法的指令,但在enclave内执行时会变成非法指令。
在enclave内执行这些指令会引发异常。
表格35-1的第一行列举了可能导致VMM仿真出口的指令。由于VMM无法模拟enclave的执行,因此在enclave内执行任何这些指令都会导致无效操作码异常(#UD)而没有VM退出。
表格35-1的第二行列举了可能导致故障或VM退出的I/O指令。同样,enclave执行无法被仿真,因此在enclave内执行任何这些指令都会导致#UD异常。
表格35-1的第三行列举了从GDT或LDT加载描述符或更改特权级的指令。前者被禁止,因为enclave软件不应依赖于描述符表的内容,而后者被禁止,因为enclave执行必须完全在CPL = 3下进行。同样,在enclave内执行任何这些指令都会导致#UD异常。
表格35-1的第四行列举了从用户模式访问内核信息的指令,这些指令可以用于在enclave内部进行内核利用。在enclave内执行任何这些指令都会导致#UD异常。
对于支持SGX2的处理器(取决于CR4.TSD的值),在enclave内部可以合法地使用RDTSC和RDTSCP指令。
对于支持SGX1但不支持SGX2的处理器,RDTSC和RDTSCP指令会引发#UD异常。
在enclave内部使用RDTSC和RDTSCP指令可能会导致VM退出。
软件开发人员应该意识到从RDTSC/RDTSCP指令获取的结果可能受到系统上其他软件的影响。时间戳计数器(TSC)可以被enclave外的软件进行操纵,这可能会影响从这些指令获取的计时信息的准确性和可靠性。
TSC是一个高分辨率计数器,以恒定速率递增,通常基于处理器的时钟频率。它被设计用于测量时间间隔,并经常用于性能分析、基准测试和对时间敏感的操作。然而,需要注意的是,TSC并不是防篡改的,可以受到CPU频率缩放、电源管理策略和软件交互等因素的影响。
在enclave的上下文中,重要的是要考虑外部软件操纵TSC可能带来的潜在影响。这种操纵可能导致计时测量的不准确或暴露基于计时的侧信道攻击。开发人员应采取适当的对策,例如使用专门的enclave特定计时机制(例如带TSC缩放的RDTSC/IA32_TSC_AUX)或依赖于受硬件保护的时间源(例如Intel Secure Key),以减轻这些风险并增强其enclave应用程序的安全性。
6.2 RDRAND and RDSEED Instructions
如果“RDRAND exiting” VM执行控制为1,这些指令可能会导致虚拟机退出。与可能导致虚拟机退出的其他指令不同,这些指令在enclave内是合法的。正如《Intel® 64和IA-32体系结构软件开发人员手册第3C卷》第27.1节中所述,任何在enclave内部的指令边界上发生的虚拟机退出会将VMCS的退出原因字段的第27位设置为1。如果VMM接收到由于尝试执行这两个指令而导致的虚拟机退出,并通过该位确定执行是在enclave内部,它可以执行以下两种操作之一。它可以清除“RDRAND exiting” VM执行控制并执行VMRESUME;这将导致enclave再次执行RDRAND或RDSEED,并且这次不会发生虚拟机退出。另外,VMM也可以选择停止执行该虚拟机。
注意:
预期虚拟化Intel SGX的VMM不会将“RDRAND exiting”设置为1。
6.3 PAUSE Instruction
如果“PAUSE exiting” VM执行控制为1,PAUSE指令可能会导致enclave发生虚拟机退出。与可能导致虚拟机退出的其他指令不同,PAUSE指令在enclave内是合法的。如果VMM接收到由于“PAUSE exiting”设置为1而导致的虚拟机退出,它可以执行以下两种操作之一。它可以清除“PAUSE exiting” VM执行控制并执行VMRESUME;这将导致enclave再次执行PAUSE指令,但这次不会发生虚拟机退出。另外,VMM也可以选择停止执行该虚拟机。
如果“PAUSE-loop exiting” VM执行控制为1,PAUSE指令也可能导致在enclave外部发生虚拟机退出,但是由于在CPL > 0时“PAUSE-loop exiting”控制被忽略(参见Intel vol3第25.1.3节),因此由于“PAUSE-LOOP exiting”设置为1而导致enclave发生虚拟机退出将永远不会发生。
注意:
预期虚拟化Intel SGX的VMM不会将“PAUSE exiting”设置为1。
6.4 Executions of INT1 and INT3 Inside an Enclave
INT1和INT3指令在enclave内部是合法的,但是它们在enclave内部的行为与在enclave外部的行为不同。有关详细信息,请参阅Intel vol3第39.4.1节。
6.5 INVD Handling when Enclaves Are Enabled
一旦激活处理器保留的内存保护(参见第5节),执行INVD指令将导致#GP(0)异常。
参考资料
Intel v3 Chapter 35