了解采用SGX可信任环境后对应用和目标主机产生的性能影响有多少。
(资料图片仅供参考)
Microsoft Window10 21H2版本主机一台,
处理器:Intel Core(TM)i5-9500F CPU@3.00GHZ
64位操作系统,内存16GB
代码编译环境:vs2015专业版或者Clion2021
SGX插件相关版本
Intel ME版本:ME_SW_1909.12.0.1237
SDK版本:Intel SGX SDK for Windows v2.12.100.4
PSW版本:Intel SGX PSW for Windows v2.12.100.4
小程序:计算一万以内的素数,(循环10000次)
程序源码:
//// Created by hudengfeng on 2023/1/9.//#include正常情况cpu使用率:20%(均值)
运行程序cpu使用率:70%(均值)
代码运行结果(10次)
11.732s、13.635s、16.017s、12.544s、14.327s
11.515s、14.301s、12.988s、15.251s、12.677s
均值:13.499s
基本原理:
SGX程序分为两部分,一部分是app应用,也就是不可信区,一部分是enclave应用,也就是可信区,非可信区只能通过 ECALL 函数调用可信区内的函数,可信区只能通过 OCALL 函数调用非可信区的函数,ECALL 函数和 OCALL 函数通过 EDL 文件声明。
程序目录结构:
App 目录内为不可信区域代码,包括 main 入口、OCALL 函数内具体逻辑代码等等。
Enclave 目录为可信区域代码,包括 ECALL 函数内具体逻辑代码实现。
Enclave.lds:EDL(Enclave Description Language) 文件。
Enclave_private.pem:enclave.so 的签名私钥。
Enclave.config.xml:Enclave 配置文件,如堆栈大小、是否可等。
Enclave.h & Enclave.cpp:应用安全区代码实现。
Include目录是不可信代码和可信代码共享的头文件。
在app程序中通过ecall函数调用enclave程序的calculate函数来计算结果,然后把计算的结果通过ocall函数返回给app程序,然后app程序把结果打印出来。
编译运行:
1.通过 sgx_edger8r 工具在 App/ 目录下生成不可信代码(Enclave_u.c 和 Enclave_u.h),这部分生成代码主要会调用 ECALL (sgx_ecall);
2.编译不可信部分 Binary: app;
3.通过sgx_edger8r 工具在 Enclave/ 目录下生成可信代码(Enclave_t.c 和 Enclave_t.h);
4.编译可信动态链接库(enclave.so);
5.通过sgx_sing工具签名可信动态链接库(enclave.signed.so);
6.结束。
编译后的代码目录结构:
实验结果:
正常情况cpu使用率:20%(均值)
运行程序cpu使用率:80%(均值)
代码运行结果(10次)
17.496s、12.854s、14.327s、15.635s、14.324s
12.432s、11.543s、15.398s、18.534s、13.264s
均值:14.580s
核心程序源码:
App.cpp
#includeEnclave.cpp
void ecall_calculate_from_enclave(){ for (int j = 0; j < 1000; ++j) { calculate_prime(); }}由以上App.cpp(51-53行)程序可以看出,还是计算10000以内的素数(10000次),但是Enclave.cpp当中只计算了1000次。app.cpp当中有10次循环调用ecall函数
实验结果:
正常情况cpu使用率:20%(均值)
运行程序cpu使用率:84%(均值)
代码运行结果(10次)
22.065s、24.905s、25.687s、21.522s、18.417s
21.592s、20.666s、21.845s、21.499s、18.457s
均值:21.666s
首先修改编译器设置,默认堆栈区大小是1M,如果不想使用堆栈,可在全局区使用大数组,前面加上static即可。需要在图形化界面修改堆栈保留大小这个字段。单位是bit,这里改成256MB,也就是256*1024*1024*8。也可在CMakeLists.txt添加下面2行,就可以达到修改堆栈内存大小的效果。
MATH(EXPR stack_size "256*1024*1024")单位是字节
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--stack,${stack_size}")
也可通过图形化界面修改,在vs2015在项目的属性,找到链接器的系统这一栏,
在3.4.1执行函数中新增代码(5-10行)
void exe(){ clock_t start, finish; double duration; start = clock(); int a[4096][4096] = {0}; int b[4096][4096] = {1}; a[0][0] = 1; size_t num = sizeof(a); a[0][1] = num; b[0][0] = a[0][1]; for (int j = 0; j < 10000; ++j) { calculate_prime(); } finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; cout<实验结果:
正常情况cpu使用率:20%(均值)
运行代码程序后cpu使用率:84%(均值)
代码运行结果(10次)
17.744s、16.946s、20.974s、17.409s、17.022s
20.746s、16.785s、21.114s、18.742s、18.965s
均值:18.645s
将上述带有大数组的代码复制到Enclave.cpp当中(写在循环外面),
核心代码:
void ecall_calculate_from_enclave(){ int a[4096][4096] = {0}; int b[4096][4096] = {1}; a[0][0] = 1; size_t num = sizeof(a); a[0][1] = num; b[0][0] = a[0][1]; for (int j = 0; j < 10000; ++j) { calculate_prime(); }}实验结果:
正常情况cpu使用率:20%(均值)
运行代码程序后cpu使用率:90%(均值)
代码运行结果(10次)
26.264s、26.043s、24.434s、28.206s、23.204s
22.236s、26.238s、25.232s、23.364s、24.652s
均值:24.987s
通过上述实验可以发现使用SGX安全插件的app应用来计算10000以内的素数(10000次)用的时间比不使用插件要多,cpu使用率也要高一些,但是性能损耗在5%到10%之间,性能损耗可以接受。如果频繁使用ecall函数或者ocall函数,在可信区和非可信区之间进行切换,会有比较明显的性能消耗,性能损耗在20%以上。当epc内存过大也会明显影响主机的性能。性能损耗20%以上。