必要的支持环境

1、CPU必须支持Intel SGX指令

2、系统BIOS必须支持Intel SGX

3、BIOS必须启用SGX

4、系统必须已安装Intel SGX Platform Software(PSW)

SGX应用程序检查顺序

(1) SGX应用安装程序的启动检查顺序

1、检查CPU和BISO是否支持Intel SGX

2、判断系统是否安装Intel SGX PSW,如果没安装则安装它

3、检查BIOS是否开启Intel SGX,如果没有,则尝试软件控制开启

(2) SGX应用程序本身的检查顺序

1、检查Intel SGX PSW是否安装

2、检查BIOS是否开启Intel SGX,如果没有,则尝试软件控制开启

SGX应用程序设计

设计一个Intel SGX程序需要你把代码划分成不同部分,需要判断将哪些代码(数据)放在enclave中,哪些不需要放在里面以及可信部分和不可信部分间的交互。

划分的关键步骤:

1、确定机密信息

2、确定机密信息的提供者和使用者,画出机密数据在应用各个组件之间的流程图

3、确定enclave的边界,包含尽量多的机密信息,但是要尽可能保持小的体积

4、精简安全区代码,使安全区体积尽可能小,尽可能高校的利用有限的安全区资源,减少系统开销

安全区enclave定义语言(EDL)

非安全区调用安全区函数(也是进去安全区的入口)称为E-Call(调用者在安全区外),安全区调用外部非安全区称为O-Call(调用者在安全区内)。这些ecall和ocall组成了安全区的接口。但是安全区的入口点和出口点都由CPU控制,即出入安全区需要执行特定的CPU指令。Intel SGX SDK对底层做了抽象来便于开发人员开发SGX程序。
工具Edger8r可以自动生成ecall和ocall的代理函数。Edger8r从EDL文件中读取安全区接口定义。EDL文件和C语言文件很类似,它分为两个部分,可信区和非可信区。E-call函数定义在可信区,O-call函数定义在非可信区。它包含了一些关键字,如:

public: 所有能被非可信程序调用的E-call都必须声明为public,每个安全区至少应有一个声明为public的E-call。不含public关键字的E-call只能被另一个O-call调用执行。

参数:传值,对应的封装处理应该是单向的;传引用,必须完整地描述数据的封装处理过程,即指针或者参数前用[]描述要封装处理的元素的传输方向以及数量等信息。in关键字意味着将数据封装送到e-call或者o-call和out关键字意味着数据从e-call或者o-call返回给调用函数。out关键字需要在调用e-call或者o-call前分配好数据缓冲区来存储返回的数据。inout关键字可以同时指定在一个调用中,代表要进行两个方向的封送处理。在数量信息缺省情况下,Edger8r假定数据缓冲区等于参数的size,若传输数组等含有多个元素的数据,可以用count关键字来指定元素个数,也可以传给count一个函数参数来指明元素长度。in可以和stringwstring关键字配合使用来传字符串,但是out不能和它们一起使用。

EDL进阶

有时,传送指针时需要提供更多额外的信息或者对指针进行直接控制。把void空指针传给e-call或者o-call,无法确定void类型对应的数据的具体大小,因此无法计算封送处理的数据缓冲区大小。为了结局这个问题,EDL提供了size关键字,来指定单个元素的大小,来配合inoutcount等关键字来确定数据缓冲区的大小。若是仅希望把指针指向的地址传给e-call或者o-call,则需要使用user_check,这种情况下传递的指针对进行边界安全检查和数据封送处理,e-call或者o-call直接作用于指针地址。

声明为public的e-call又被称为root e-call,不含public的e-call只能被另一个o-call调用。缺省情况下(即o-call前没有声明类型),o-call不能调用任何e-call,必须使用allow关键字来指明允许调用的e-call的名称列表,此时o-call只允许调用这个名称列表中的e-call。

SGX程序调试

Intel SGX安全区可以以debug模式或release模式构建。顾名思义,debug模式允许调试,你可以使用(只可以使用)Intel SGX debugger来进行调试。CPU允许运行任何以debug模式构建的安全区enclave,但是很显然,这些安全区都是不是安全的(因为SGX debugger可以控制)。所以生产环境下请不要部署debug模式的安全区enclave。相反,release模式的安全区无法进行调试。对安全区进行调试,需要CPU的指令支持,因此必须使用随Intel SGX SDK安装Intel SGX调试器。其他调试器只会跳过安全区代码,只有Intel SGX调试器才可以调试安全区代码,不同的编辑运行环境要对调试器进行相应的设置。

Intel SGX数据密封功能(data sealing)

当电脑进入睡眠、关机或者应用程序退出时,安全区enclave会被销毁,或者被应用程序显式销毁,从而丢失安全区中的数据。把安全区中的数据保存在非可信内存中并且保证数据的隐私性就需要Intel SGX的数据密封功能。数据密封使用从CPU得到的密钥在安全区内对数据进行加密,解密是只能在创建它的那台电脑上进行解密。当进行数据密封时,有两种密钥策略可被选择:

1、MRENCLAVE(安全区标识):将生成一个该安全区独有的密钥,即只有同一台电脑的同一个安全区可以解封数据。

2、MRSIGNER(密封标识):基于安全区密封授权方的密钥来生成一个密钥,这也使得一个安全区密封的数据可以被另一个安全区来解封,只要在同一台电脑上并且具有相同的密封授权方的密钥即可。MRSIGNER可以允许旧版本应用程序密封的数据被新版本应用程序或者其他版本的应用程序解封读取,也可以使用这种方法在两个不同的应用程序的两个不同的安全区中共享数据(只要在同一台电脑上)。

两种方法的相同点:

执行密封数据的电脑的指纹数据会作为密钥的一个输入,来保证只有在同一台电脑上才可以执行相应密封数据的解密。密钥的另一个数据则是安全区的debug模式或release模式。debug模式的安全区无法解封release模式构建的安全区密封的数据,反之亦然。这是为了防止Intel SGX调试器在调试debug模式的安全区时泄露来自release模式密封的安全区数据。

安全区enclave不会检查非可信应用程序的真实性,因此任何人任何程序都可以加载你的安全区,并且按照他们希望的顺序执行e-call。因此安全区的api不能因为数据密封和解封来泄露机密或者授予不该授予的权限。

Reference

Intel® Software Guard Extensions (Intel® SGX) | Intel Software


声明:
文章标题:SGX学习系列
文章作者:RookieHacker
文章链接:http://blog.rookiehacker.org/2020/02/21/SGXstudy/
文章版权属本博主所有,有问题或者建议欢迎在下方评论。欢迎转载、引用,但请标明作者和原文地址,谢谢。


喜欢,就支持我一下吧~