从rust-sgx-sdk开始
阅读
https://github.com/dingelish/SGXfail/blob/master/01.md
摘要:
关键字:可信 + 保密
sgx运行环境的结构
intel sgx程序分成untrusted和trusted两部分, trusted 包括了用户自己写的SGX enclave。 用户自己的untrusted app需要和Intel提供的untrusted runtime等运行时库配合使用。
支持Intel SGX程序执行,需要
- untrusted部分的守护进程aesmd,提供application enclave service manager.
- 官方Enclave:
- Launch Enclave(le)
- Quoting Enclave(qe)
- Platform Service Enclave(pse)
- Provisioning Enclave (pve)
- Provisioning Certification Enclave(pce)
- Reference Launch Enclave
- 和一些配套的untrusted AE接口
图中可以知道:
- SGX的内核驱动暴露一个/dev/isgx的misc device 给用户态,用户态的AESM守护进程和uae service等经过这个misc device为用户进程的untrusted部分提供create/destroy enclave等能力
- AESM的守护进程aesmd会打开一个domain socket:aesm.socket给用户态程序的urts(untrusted runtime service)库和uae_service库提供支持。asem对于用户就是一个黑盒子。 用户只需要通过urts和uae_service提供的接口来实现业务逻辑就可以了。
运行一个SGX程序的前提
- 包括平台提供isgx设备
- 全套的aesm服务
- urts/uae_service的动态库
- 提供了一套软件模拟环境,编译时指定SGX_MODE=SE打开。启用SW环境之后,编译时会链接所有库的模拟执行版本。例如libsgx_trts_sim.a, libsgx_tservice_sim.a等。对于untrusted部分也有模拟环境:libsgx_uae_service_sim.so, libsgx_urts_sim.so。所以,在没有SGX硬件的支持下,也是可以通过软件模拟的方式来操作SGX。
rust-sgx-sdk
hello-rust
-
untrusted 和 trust 都是rust编写的
-
app 目录下的untrusted 部分
- sgx_types是数据结构定义
- sgx_urts是函数接口定义;untrusted runtime service的接口
- 对于一个untrused端app,不考虑PSE、unprotected_fs等情况下,这两个依赖项就是足够创建和关闭enclave了
-
app/build.rs
- 这个文件会把编译选项输出给rustc,主要的事情是:
- 帮助rustc找到SGX SDK的位置
- 帮助rustc找到enclave EDL所生成的Enclave_u的位置
- 帮助rustc link 到正确的urts库(HW or SW)
- EDL
- Intel给定的文件格式,接近C的header file写法,规定了Enclave 的边界 ECALL/OCALL的定义。
- Intel提供了一个由Ocaml编写的EDL编译器edger8r
- 将每一个输入的EDL转化为
- Enclave_u.c+ Enclave_u.h
- Enclave_t.c+Enclave_t.h
- 这四个文件包含了ECALL/OCALL中所引入的必要的"额外proxy function 和marshling数据结构",用于完成ECALL/OCALL操作,
- app调用导出的ECALL函数时,控制流会转到这个自动生成的stub中,完成必要的操作,再把控制权交给sgx_ecall函数,它负责状态转换到sgx模式,进入enclave。
- 进入enclave之后胡县到enclave_t.c中实现bridge function的另一端,进行另一些参数包装之后最后才会执行到Enclave函数的实现
- 上面的过程时不可见的,但是是程序员理解SGX的关键,
细节:
https://software.intel.com/sites/default/files/managed/e1/ec/SGX_SDK_Developer_Guidance-CVE-2017-5753.pdf;
https://software.intel.com/sites/default/files/managed/e1/ec/180309_SGX_SDK_Developer_Guidance_Edger8r.pdf
中文:
https://github.com/dingelish/SGXfail/blob/master/02.md
https://github.com/dingelish/SGXfail/blob/master/03.md
- hello-rust源码阅读
hello-rust/enclave/Enclave.edl
enclave {
from "sgx_tstd.edl" import *;
from "sgx_stdio.edl" import *;
from "sgx_backtrace.edl" import *;
from "sgx_tstdc.edl" import *;
trusted {
/* define ECALLs here. */
public sgx_status_t say_something([in, size=len] const uint8_t* some_string, size_t len);
};
};
- 唯一一个用户定义的ECALL函数是say_something,其参数包括一个uint8_t *的指针和一个长度len。在EDL里利用size=len来告诉SGX要把多少个字节的参数拷贝到Enclave里。
- 在Enclave里的say_something看来,这个指针是指向Enclave内存的,而不是指向untrusted部分的内存。所以,ECall会把这样的参数连续的按字节拷贝到Enclave的加密内存中,因此需要个长度。
app/src/main.rs
let result = unsafe {
say_something(enclave.geteid(),
&mut retval,
input_string.as_ptr() as * const u8,
input_string.len())
};
- ECALL传递参数的时候是包括两个“隐参数”的,即enclave id和"返回值所存的地址&retval。并且这个ECALL会具有另外一个返回值result。这里result代表的含义是:ECALL执行是否成功。ret代表的含义是:ECALL函数的返回值。
enclave部分
- Cargo.toml:staticlib
- 会被编译成一个.a文件,和intel其他库文件连接一起成为enclave.so,
- sgx_sign工具配合Enclave.config.xml配置文件、签名私钥一起做签名和属性刻画,生成enclave.signed.so,成为Enclave
- dependency包含sgx_types,sgx_tstd,后者是标准库,
- lib.rs是Enclave源代码,
// Ocall to normal world for output
println!("{}", &hello_string);
- 如果做print打印需要syscall的,而SCX内不可以作syscall,这里要进行OCALL。但在该例子EDL里面没有直接出现OCALL打印函数,这是因为我们在实现pringln!的过程中加入了内置的OCALL,并定义了对应的EDL,并且在Enclave.edl中做了import.
enclave {
from "sgx_tstd.edl" import *;
from "sgx_stdio.edl" import *;
from "sgx_backtrace.edl" import *;
from "sgx_tstdc.edl" import *;
- printf实现复杂,需要在超长的调用过程中的某一点进行切割,将控制流从Enclave内转到Enclave外,在untrusted部分完成write,判断在哪里进行切割需要partition.
Partition
- 意味着划分可信/不可信的边界。
- partition是一个“业务逻辑”层面的事情,对于一个业务,partition可以有无数种方式。
- 让我们拿Scone-python做例子。Scone(和Graphene SGX)是一类试图将”任意程序“跑在SGX内的解决方案。他们甚至可以直接跑python解释器。看上去很美。但是在SGX的威胁模型下,只有Enclave内是可信的,这导致,在Enclave内执行的python解释器在执行到import numpy的时候,会从磁盘中读取numpy的python文件并进行解释,而读进来的文件是不可信的!这时相当于:在可信环境中执行了不可信的代码,然而——用户依然认为它是可信的!这是一个典型的错误可信计算基的实例。攻击者可以简单的替换磁盘中的numpy,下次用户再次import numpy的时候,就会使用植入了恶意逻辑(比如发送secret)的numpy在Enclave内执行,导致秘密泄露。