打开/sgxsdk/SampleCode/
文件夹中的示例文件
1. 复制SampleEnclave示例 并建立自己的修改项目
SampleEnclave示例实现了安全printf函数,可以被用来安全打印我们需要打印的字符串。我们把SampleEnclave示例复制到自己的文件夹中,基于该示例,我们开发一个使用Enclave打印Hello Enclave的应用程序。我们把复制得到的SampleEnclave文件夹名称改成HelloEnclave文件夹。
2. 文件夹中文件介绍
2.1 App文件夹
该文件夹存放应用程序中的不可信代码部分,共有2个文件和2个文件夹,App.cpp文件、App.h文件、Edger8rSyntax文件夹和TrustedLibrary文件夹
-
App.cpp
文件:该文件是应用程序中的不可信部分代码,其中包括了创建Enclave及销毁Enclave的代码,也定义了一些相关的返回码供使用者查看Enclave程序的执行状态。其中的main函数是整个项目的入口函数。是我们要修改的文件。 -
App.h
文件:该文件是应用程序中的不可信部分代码的头文件,定义了一些宏常量和函数声明。我们不用进行更改。 -
Edger8rSyntax
文件夹:该文件夹提供了一些工具,我们不用进行更改。 -
TrustedLibrary
文件夹:该文件夹提供了一些函数库,我们不用进行更改。
2.2 Enclave文件夹
该文件夹存放应用程序中的可信代码部分和可信与不可信代码接口文件,共有6个文件和2个文件夹,Enclave.config.xml文件、Enclave.cpp文件、Enclave.h文件、Enclave.edl文件、Enclave.lds文件、Enclave_private.pem文件、Edger8rSyntax文件夹和TrustedLibrary文件夹
Enclave.config.xml
文件:该文件是Enclave的配置文件,定义了Enclave的元数据信息,我们可以不用更改。Enclave.cpp
文件:该文件是应用程序中的可信部分代码,包括了可信函数的实现,是我们要修改的文件。Enclave.h
文件:该文件是应用程序中的可信部分代码的头文件,定义了一些宏常量和函数声明。是我们要修改的文件。Enclave.edl
文件:该文件是Enclave的接口定义文件,定义了不可信代码调用可信代码的ECALL函数接口和可信代码调用不可信代码的OECALL函数接口,trusted{}
中定义了ECALL函数接口,untrusted{}
中定义了OECALL函数接口是我们要修改的文件。Enclave.lds
文件:该文件定义了一些Enclave可执行文件信息,我们不用更改。Enclave_private.pem
文件:该文件是SGX生成的私钥,我们不用更改。Edger8rSyntax
文件夹:该文件夹提供了一些工具,我们不用进行更改。TrustedLibrary
文件夹:该文件夹提供了一些函数库,我们不用进行更改。
2.3 Include文件夹
该文件夹存放被Enclave接口定义文件Enclave.edl使用的头文件,包括一些宏定义,我们不用管它。共只有一个user_types.h文件。
user_types.h
文件:该文件定义了用户自定义的类型。
2.4 Makefile文件
该文件是项目的编译文件,定义了项目的编译信息,详细说明还请参考http://blog.csdn.net/daichunkai123/article/details/78027895。是需要修改的部分。
3. 改写代码
需要修改的文件问为Enclave.edl文件、Enclave.cpp文件、Enclave.h文件、App.cpp文件和Makefile文件
3.1 Enclave.edl文件修改
我们要在Enclave.edl
文件中定义不可信代码调用可信函数的接口,比如我们定义的可信函数是printf_helloenclave
,在该函数中我们打印”Hello Enclave“,该函数没有参数也没有返回值。
3.1.1 我们添加ECALL,将以下代码添加到Enclave.edl文件中的untrusted{}
之前。
trusted{
public void printf_helloworld();
};
3.1.2 修改后的Enclave.edl文件如下所示
enclave {
include "user_types.h" /* buffer_t */
from "Edger8rSyntax/Types.edl" import *;
from "Edger8rSyntax/Pointers.edl" import *;
from "Edger8rSyntax/Arrays.edl" import *;
from "Edger8rSyntax/Functions.edl" import *;
from "TrustedLibrary/Libc.edl" import *;
from "TrustedLibrary/Libcxx.edl" import ecall_exception, ecall_map;
from "TrustedLibrary/Thread.edl" import *;
trusted{
public void printf_helloenclave();
};
untrusted {
void ocall_print_string([in, string] const char *str);
};
};
3.2 Enclave.cpp文件修改
我们在Enclave.cpp
文件中实现printf_helloenclave
函数,该函数比较简单,就是打印”Hello Enclave“。
3.2.1 将以下代码添加到Enclave.cpp文件中
void printf_helloworld(){
printf("Hello World
");
}
3.2.2 修改后的Enclave.cpp文件如下所示
#include <stdarg.h>
#include <stdio.h> /* vsnprintf */
#include "Enclave.h"
#include "Enclave_t.h" /* print_string */
void printf(const char *fmt, ...)
{
char buf[BUFSIZ] = {' '};
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, BUFSIZ, fmt, ap);
va_end(ap);
ocall_print_string(buf);
}
void printf_helloenclave()
{
printf("Hello enclave
");
}
3.3 Enclave.h文件修改
我们在Enclave.h
文件中添加printf_helloenclave
函数声明,该文件修改比较简单。
3.3.1将以下代码添加到Enclave.h文件中
void printf_helloenclave();
3.3.2 修改后的Enclave.h文件如下所示
#ifndef _ENCLAVE_H_
#define _ENCLAVE_H_
#include <stdlib.h>
#include <assert.h>
#if defined(__cplusplus)
extern "C" {
#endif
void printf(const char *fmt, ...);
void printf_helloenclave();
#if defined(__cplusplus)
}
#endif
#endif /* !_ENCLAVE_H_ */
3.4 App.cpp文件修改
我们在该文件中调用自定义的ECALL函数printf_helloenclave
打印”Hello Enclave“。该文件修改比较简单
3.4.1 修改main函数
由于我们不需要Edger8rSyntax和TrustedLibrary相关的函数调用,所以我们把main函数中与这两部分相关的函数调用删除,也就是把下面部分删除:
/* Utilize edger8r attributes */
edger8r_array_attributes();
edger8r_pointer_attributes();
edger8r_type_attributes();
edger8r_function_attributes();
/* Utilize trusted libraries */
ecall_libc_functions();
ecall_libcxx_functions();
ecall_thread_functions();
3.4.2 main函数中插入函数调用
在main函数中的Enclave创建和销毁之间插入我们定义的printf_helloenclave
函数的调用代码,也就是把以下代码放到sgx_destroy_enclave(global_eid);
之前。global_eid
参数是enclave的id。
printf_helloenclave(global_eid);
3.4.3 删除无关代码
我们也可以将main函数后面的无关代码给删了,也就是删除以下代码。
printf("Info: SampleEnclave successfully returned.
");
printf("Enter a character before exit ...
");
getchar();
修改后的main函数如下所示
int SGX_CDECL main(int argc, char *argv[])
{
(void)(argc);
(void)(argv);
/* Initialize the enclave */
if(initialize_enclave() < 0){
printf("Enter a character before exit ...
");
getchar();
return -1;
}
printf_helloworld(global_eid);
/* Destroy the enclave */
sgx_destroy_enclave(global_eid);
return 0;
}
3.5 Makefile文件修改
我们在Makefile文件中修改编译相关的信息。主要更改
SGX_SDK ?= /opt/intel/sgxsdk
App_Cpp_Files := App/App.cpp $(wildcard App/Edger8rSyntax/*.cpp) $(wildcard App/TrustedLibrary/*.cpp)
Enclave_Cpp_Files := Enclave/Enclave.cpp $(wildcard Enclave/Edger8rSyntax/*.cpp) $(wildcard Enclave/TrustedLibrary/*.cpp)
3.5.1 修改SGX SDK路径
如果SGX SDK路径不是/opt/intel/sgxsdk,要将其改成为所在目录下/home/zjz/sgxsdk,
3.5.2 修改不可信代码编译的源文件
由于我们的不可信代码可能是多个文件,因此,我们最好在App_Cpp_Files中包括App文件夹中的所有cpp文件,更改后的结果如下。本项目中App_Cpp_Files可以不用更改。
3.5.3 修改可信代码编译的源文件
由于我们的可信代码可能是多个文件,因此,我们最好在Enclave_Cpp_Files中包括App文件夹中的所有cpp文件,更改后的结果如下。本项目中Enclave_Cpp_Files可以不用更改。
4. 编译文件
打开文件下的终端输入make
5. 运行程序
执行 ./app
运行程序
其中遇到一个lib库的问题 使用export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zjz/sgxsdk/lib64
解决后重新运行
最终成功输出hello enclave!