抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

一、了解SGX

1.1SGX定义

  • Intel 软件防护扩展SGX(Software Guard Extension)是一项针对台式机和服务器平台的旨在满足可信计算需求的技术。Intel SGX是Intel架构新的扩展,在原有架构上增加了一组新的指令集和内存访问机制。

  • Intel在2015年从第6代Intel酷睿处理器平台开始引入了Intel软件防护扩展新指令集,使用特殊指令和软件可将应用程序代码放入一个enclave中执行。Enclave可以提供一个隔离的可信执行环境,可以在BIOS、虚拟机监控器、主操作系统和驱动程序均被恶意代码攻陷的情况下,仍对enclave内的代码和内存数据提供保护,防止恶意软件影响enclave内的代码和数据,从而保障用户的关键代码和数据的机密性和完整性。

1.2基本原理

  • SGX应用由两部分组成:
    untrusted 不可信区:代码和数据运行在普通非加密内存区域,程序main入口必须在非可信区。
    trusted 可信区:代码和数据运行在硬件加密内存区域,此区域由CPU创建的且只有CPU有权限访问。

6277797-c325c2fded33f003

  • 当一个安全区域函数被调用时,只有安全区域内的代码才能看到其数据,外部访问总是被拒绝;返回时,安全区数据将保留在受保护的内存中。

  • 非可信区只能通过ECALL函数调用可信区内的函数,可信区只能通过OCALL函数调用非可信区的函数,ECALL函数和OCALL函数通过EDL文件声明。

1.3两大机制

1.3.1保护机制

针对enclave的保护机制主要包括两个部分:一是enclave内存访问语义的变化,二是应用程序地址映射关系的保护。这两项功能共同完成对enclave的机密性和完整性的保护。

1.3.2 认证机制

SGX 提出了两种类型的身份认证方式:一种是平台内部 enclave 间的认证,用来认证进行报告的 enclave 和自己是否运行在同一个平台上;另一种是平台间的远程认证,用于远程的认证者认证 enclave 的身份信息。

  • 本地证明:同一平台的两个Enclave之间的证明过程。
  • 远程证明:Enclave和不在平台上的第三方之间的证明过程。

二、Linux下安装SGX

简介:我们需要安装几个东西。第一是驱动Drive,有了驱动才可以调用intel芯片里面的硬件部分。第二个是PSW(平台软件),其是允许支持SGX的应用程序在目标平台上执行的软件栈,包含四部分1.提供对硬件功能进行访问的驱动程序;2.为执行和认证提供多个支持库;3.运行所必需的架构型enclave;4.加载并与enclave进行通信的服务;。第三个是软件开发工具包(SDK)为开发人员提供了开发支持SGX的应用程序所需的一切,它由一个生成应用程序和enclave之间的接口函数的工具,一个在使用它之前对enclave进行签名的工具,一个调试它的工具以及一个性能检查的工具组成。另外,它还包含模板和样本参数,用于在Windows下使用Visual Studio开发enclave,或在Linux下使用Makefile。

有了这三样东西我们才可以进行代码开发

  • 以Ubuntu20.04 LTS为例
  • 硬件需求仅当安装sgx驱动和PSW时需要,安装sgx sdk并不需要硬件支持。
  • 硬件不支持的情况下,可以在模拟环境下编写测试SGX程序,其中makefile里SGX_MODE=SIM。(虽然 SGX是基于硬件的,但是依旧可以使用软件条件进行模拟)

先安装驱动、PSW、SDK所需依赖

1
2
3
sudo apt-get update
sudo apt-get install libssl-dev libcurl4-openssl-dev libprotobuf-dev
sudo apt-get install build-essential python

下载Intel SGX驱动并安装

1
2
3
4
wget https://download.01.org/intel-sgx/sgx-linux/2.7.1/distro/ubuntu18.04-server/sgx_linux_x64_driver_2.6.0_4f5bb63.bin
chmod +x sgx_linux_x64_driver_2.6.0_4f5bb63.bin
sudo ./sgx_linux_x64_driver_2.6.0_4f5bb63.bin
sudo reboot
  • 注意安装完重启才生效

下载Intel SGX PSW并安装

  • 注意:有的版本的没有PSW文件,也可以不装
1
2
wget https://download.01.org/intel-sgx/sgx-linux/2.7.1/distro/ubuntu18.04-server/libsgx-enclave-common_2.7.101.3-bionic1_amd64.deb
sudo dpkg -i ./libsgx-enclave-common_2.7.101.3-bionic1_amd64.deb

下载并安装Intel SGX SDK

  • 安装过程中可以手动输入SDK要安装到的目标位置
1
2
3
wget https://download.01.org/intel-sgx/sgx-linux/2.7.1/distro/ubuntu18.04-server/sgx_linux_x64_sdk_2.7.101.3.bin
chmod +x ./sgx_linux_x64_sdk_2.7.101.3.bin
./sgx_linux_x64_sdk_2.7.101.3.bin

添加环境变量,执行上一步结束时输出的命令

1
source /path/to/sgxsdk/environment

接下来进入到sgxsdk/SampleCode/SampleEnclave文件夹里

1
cd /path/to/sgxsdk/SampleCode/SampleEnclave

编辑一下Makefile

1
2
3
4
5
6
7
8
# Intel SGX SDK 的安装位置
SGX_SDK ?= /home/luoyhang003/SGX/sgxsdk
# 运行类型:HW 真实环境;SIM 模拟器环境
SGX_MODE ?= SIM
# 运行架构:仅支持 64 位
SGX_ARCH ?= x64
# 是否为:Debug 调试模式
SGX_DEBUG ?= 1

退出然后运行示例

1
2
3
4
# 编译
sudo make
# 运行
./app
  • 注意一定要添加环境变量source /path/to/sgxsdk/environment,这行命令是临时环境变量,即存活时间为一个终端的市场,一旦重启或开启新的终端环境变量即会失效,需要手动添加。也可以永久化环境变量。

成功运行截图

image-20230905153050489

三、文件结构与代码

目录结构

image-20230905153832469

编译&运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ make
GEN => App/Enclave_u.h
CC <= App/Enclave_u.c
CXX <= App/App.cpp
LINK => app
GEN => Enclave/Enclave_t.h
CC <= Enclave/Enclave_t.c
CXX <= Enclave/Enclave.cpp
LINK => enclave.so
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x40000</StackMaxSize>
<HeapMaxSize>0x100000</HeapMaxSize>
<TCSNum>10</TCSNum>
<TCSPolicy>1</TCSPolicy>
<!-- Recommend changing 'DisableDebug' to 1 to make the enclave undebuggable for enclave release -->
<DisableDebug>0</DisableDebug>
<MiscSelect>0</MiscSelect>
<MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>
tcs_num 10, tcs_max_num 10, tcs_min_pool 1
The required memory is 3960832B.
The required memory is 0x3c7000, 3868 KB.
Succeed.
SIGN => enclave.signed.so
The project has been built in debug hardware mode.

$ ./app
Hello world
Info: SampleEnclave successfully returned.
Enter a character before exit ...

编译流程(Makefile)

  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. 结束。

编译后目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
HelloWorld
├── app
├── App
│ ├── App.cpp
│ ├── App.h
│ ├── App.o #[generated]
│ ├── Enclave_u.c #[generated]
│ ├── Enclave_u.h #[generated]
│ └── Enclave_u.o #[generated]
├── Enclave
│ ├── Enclave.config.xml
│ ├── Enclave.cpp
│ ├── Enclave.edl
│ ├── Enclave.h
│ ├── Enclave.lds
│ ├── Enclave.o #[generated]
│ ├── Enclave_private.pem
│ ├── Enclave_t.c #[generated]
│ ├── Enclave_t.h #[generated]
│ └── Enclave_t.o #[generated]
├── enclave.signed.so #[generated]
├── enclave.so #[generated]
├── Include
└── Makefile

HelloWorld

  • 大概流程如下

图片1

  • 1.添加可信函数Encalve/Enclave.edl
1
2
3
4
5
enclave {
trusted {
public void ecall_hello_from_enclave([out, size=len] char* buf, size_t len);
};
};
  • 2.在可信区域定义可信函数Enclave/Enclave.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "Enclave.h"
#include "Enclave_t.h" /* print_string */
#include <string.h>

void ecall_hello_from_enclave(char *buf, size_t len)
{
const char *hello = "Hello world";

size_t size = len;
if(strlen(hello) < len)
{
size = strlen(hello) + 1;
}

memcpy(buf, hello, size - 1);
buf[size-1] = '\0';
}
  • 3.调用可信函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>
#include <string.h>
#include <assert.h>

# include <unistd.h>
# include <pwd.h>
# define MAX_PATH FILENAME_MAX

#include "sgx_urts.h"
#include "App.h"
#include "Enclave_u.h"

/* Global EID shared by multiple threads */
sgx_enclave_id_t global_eid = 0;

int initialize_enclave(void)
{
sgx_status_t ret = SGX_ERROR_UNEXPECTED;

/* 调用 sgx_create_enclave 创建一个 Enclave 实例 */
/* Debug Support: set 2nd parameter to 1 */
ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, NULL, NULL, &global_eid, NULL);
if (ret != SGX_SUCCESS) {
printf("Failed to create enclave, ret code: %d\n", ret);
return -1;
}

return 0;
}

/* 应用程序入口 */
int SGX_CDECL main(int argc, char *argv[])
{
(void)(argc);
(void)(argv);

const size_t max_buf_len = 100;
char buffer[max_buf_len] = {0};


/* 创建并初始化 Enclave */
if(initialize_enclave() < 0){
printf("Enter a character before exit ...\n");
getchar();
return -1;
}
//-------------------------添加代码区域------------------------------------
/* ECALL 调用 */
ecall_hello_from_enclave(global_eid, buffer, max_buf_len);
printf("%s\n", buffer);
//------------------------------------------------------------------------
/* 销毁 Enclave */
sgx_destroy_enclave(global_eid);

printf("Info: SampleEnclave successfully returned.\n");

printf("Enter a character before exit ...\n");
getchar();
return 0;
}

总结

即便最简单的 SGX HelloWold 也比较复杂,当然“安全性”和“成本”(技术壁垒门槛、开发成本、维护成本、物料成本等)总是成正比的,和“效率”成反比的。希望这篇文章对那些想入门开发 SGX 应用的用户有所帮助。

评论