Ubuntu 16.04下Intel SGX应用程序程序开发——OCALL参数字符串拷贝

来源:互联网 发布:拍照英文翻译软件 编辑:程序博客网 时间:2024/06/04 01:04

本文作者:邱朋飞

本文中,我们介绍在Enclave函数中调用不可信OCALL函数,并向OCALL函数传递参数。

安装完SGX SDK后,我们可以在输入的安装目录下的/sgxsdk/SampleCode文件夹下找到Intel提供的SGX应用程序示例,共有6个例子,根据名字可以大概判断是做什么的,每个示例中的README.txt文件给出了示例的详细信息。6个示例如下所示:


1. 复制SampleEnclave示例并建立自己的OcallMemCpy项目
SampleEnclave示例实现了安全printf函数,可以被用来安全打印我们需要打印的字符串。我们使用OCALL进行字符串复制,并调用printf函数打印复制的目的字符串。我们把SampleEnclave示例复制到自己的文件夹中,基于该示例,我们开发一个在Enclave函数中调用OCALL函数复制源字符串到目的字符串中。我们把复制得到的SampleEnclave文件夹名称改成OcallMemCpy文件夹。下左1图展示了项目的目录结构:

   

2. 删除一些不需要的文件

其中.settings是隐藏文件夹,里面的language.settings.xml定义了一些与语言相关的信息,我们不用管它。.cproject和.project是隐藏文件,我们也不用管它们。README.txt没有用,我们可以删除README.txt。最后项目的目录结构如上左2图所示。

3. 项目各个部分内容简介

3.1 App文件夹

该文件夹存放应用程序中的不可信代码部分,共有2个文件和2个文件夹,App.cpp文件、App.h文件、Edger8rSyntax文件夹和TrustedLibrary文件夹

3.1.1 App.cpp文件:该文件是应用程序中的不可信部分代码,其中包括了创建Enclave及销毁Enclave的代码,也定义了一些相关的返回码供使用者查看Enclave程序的执行状态。其中的main函数是整个项目的入口函数。是我们要修改的文件。

3.1.2 App.h文件:该文件是应用程序中的不可信部分代码的头文件,定义了一些宏常量和函数声明。我们不用进行更改。

3.1.3 Edger8rSyntax文件夹:该文件夹提供了一些工具,我们不用进行更改。

3.1.4 TrustedLibrary文件夹:该文件夹提供了一些函数库,我们不用进行更改。

3.2 Enclave文件夹

该文件夹存放应用程序中的可信代码部分和可信与不可信代码接口文件,共有6个文件和2个文件夹,Enclave.config.xml文件、Enclave.cpp文件、Enclave.h文件、Enclave.edl文件、Enclave.lds文件、Enclave_private.pem文件、Edger8rSyntax文件夹和TrustedLibrary文件夹

3.2.1 Enclave.config.xml文件:该文件是Enclave的配置文件,定义了Enclave的元数据信息,我们可以不用更改。

3.2.2 Enclave.cpp文件:该文件是应用程序中的可信部分代码,包括了可信函数的实现,是我们要修改的文件。

3.2.3 Enclave.h文件:该文件是应用程序中的可信部分代码的头文件,定义了一些宏常量和函数声明。是我们要修改的文件。

3.2.4 Enclave.edl文件:该文件是Enclave的接口定义文件,定义了不可信代码调用可信代码的ECALL函数接口和可信代码调用不可信代码的OECALL函数接口,trusted{}中定义了ECALL函数接口,untrusted{}中定义了OECALL函数接口是我们要修改的文件。

3.2.5 Enclave.lds文件:该文件定义了一些Enclave可执行文件信息,我们不用更改。

3.2.6 Enclave_private.pem文件:该文件是SGX生成的私钥,我们不用更改。

3.2.7 Edger8rSyntax文件夹:该文件夹提供了一些工具,我们不用进行更改。

3.2.8 TrustedLibrary文件夹:该文件夹提供了一些函数库,我们不用进行更改。

3.3 Include文件夹

该文件夹存放被Enclave接口定义文件Enclave.edl使用的头文件,包括一些宏定义,我们不用管它。共有一个文件,user_types.h文件。

3.3.1 user_types.h文件:该文件定义了用户自定义的类型。

3.4 Makefile文件

该文件是项目的编译文件,定义了项目的编译信息,详细说明还请参考http://blog.csdn.net/daichunkai123/article/details/78027895。是需要修改的部分。

4 编写我们的代码

我们要修改的文件包括:Enclave.edl文件、Enclave.cpp文件、Enclave.h文件、App.cpp文件和Makefile文件。

4.1 Enclave.edl文件修改:

我们要在Enclave.edl文件中定义不可信代码调用可信函数的ECALL接口,比如我们定义的可信函数是ecall_mymemcpy,在该函数中我们调用OCALL函数ocall_strcpy复制源字符串到目的字符串中,该函数没有参数也没有返回值。我们也需要在Enclave.edl文件中定义不可信代码调用可信函数的OCALL接口,比如我们定义的可信函数是ocall_strcpy,该函数复制源字符串到目的字符串中,该函数有四个参数:目的字符串DeStr、源字符串SoStr、目地字符串长度DeLen和源字符串长度SoLen,该函数没有返回值。

4.1.1 我们添加我们的ECALL函数ecall_mymemcpy,我们将以下代码添加到Enclave.edl文件中的untrusted{}之前。

trusted{    public void ecall_mymemcpy();};

4.1.2 我们添加我们的OCALL函数ocall_strcpy,由于DeStr和SoStr是指针类型,故我们需要指出这两个指针的方向,由于要把源字符串复制到目的字符串中,故DeStr定义为out方向,代表输出,SoStr定义为in方向,代表输入。我们将以下代码添加到Enclave.edl文件中的untrusted{}之中。

void ocall_strcpy([out,size=DeLen] char *DeStr,[in,size=SoLen] char *SoStr,size_t DeLen,size_t SoLen);

4.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 ecall_mymemcpy();    };    untrusted {        void ocall_print_string([in, string] const char *str);        void ocall_strcpy([out,size=DeLen] char *DeStr,[in,size=SoLen] char *SoStr,size_t DeLen,size_t SoLen);    };};

4.2 Enclave.cpp文件修改

我们在Enclave.cpp文件中实现ecall_mymemcpy函数,该函数比较简单,就是定义两个源字符串和目的字符串,并调用OCALL函数ocall_strcpy进行字符串拷贝,然后调用printf函数打印拷贝的字符串。

4.2.1 我们定义两个宏常量DeLen和SoLen,DeLen表示目的字符串的长度,SoLen表示源字符串的长度,如下所示

#define DeLen 50#define SoLen 100

4.2.2 将以下代码添加到Enclave.cpp文件中

void ecall_mymemcpy(){    char DeStr[DeLen]="";    char SoStr[SoLen]="邱朋飞大神";    ocall_strcpy(DeStr,SoStr,DeLen,SoLen);    printf("%s\n", DeStr);}

4.2.2 修改后的Enclave.cpp文件如下所示

#include <stdarg.h>#include <stdio.h>      /* vsnprintf */#include "Enclave.h"#include "Enclave_t.h"  /* print_string */#define DeLen 50#define SoLen 100void printf(const char *fmt, ...){    char buf[BUFSIZ] = {'\0'};    va_list ap;    va_start(ap, fmt);    vsnprintf(buf, BUFSIZ, fmt, ap);    va_end(ap);    ocall_print_string(buf);}void ecall_mymemcpy(){    char DeStr[DeLen]="";    char SoStr[SoLen]="邱朋飞大神";    ocall_strcpy(DeStr,SoStr,DeLen,SoLen);    printf("%s\n", DeStr);}

4.3 Enclave.h文件修改

我们在Enclave.h文件中添加ecall_mymemcpy函数声明,该文件修改比较简单。

4.3.1将以下代码添加到Enclave.h文件中

void ecall_mymemcpy();

4.3.2 修改后的Enclave.h文件如下所示

#ifndef _ENCLAVE_H_#define _ENCLAVE_H_#include <stdlib.h>#include <assert.h>#if defined(__cplusplus)extern "C" {#endifvoid printf(const char *fmt, ...);void ecall_mymemcpy();#if defined(__cplusplus)}#endif#endif /* !_ENCLAVE_H_ */

4.4 App.cpp文件修改

我们在该文件中实现OCALL函数ocall_strcpy并调用自定义的ECALL函数ecall_mymemcpy。该文件修改比较简单

4.4.1 由于我们不需要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();

4.4.2 我们在main函数之前插入OCALL函数ocall_strcpy的实现,该函数首先选择DeLen和SoLen中的较小值,然后使用memcpy函数复制源字符串到目的字符串中,复制的最大长度就是DeLen和SoLen中的较小值。即将以下代码插入到main函数之前

void ocall_strcpy(char *DeStr,char *SoStr,size_t DeLen,size_t SoLen){    if (DeLen > SoLen)        DeLen = SoLen;    if (DeLen)        memcpy(DeStr,SoStr,DeLen);}

4.4.3 我们在main函数中的Enclave创建和销毁之间插入我们定义的ecall_mymemcpy函数的调用代码,也就是把以下代码放到”sgx_destroy_enclave(global_eid);“之前。global_eid参数是必须的,是enclave的id。

ecall_mymemcpy(global_eid);

4.4.2 我们也可以将main函数后面的无关代码给删了,也就是删除以下代码。

printf("Info: SampleEnclave successfully returned.\n");    printf("Enter a character before exit ...\n");    getchar();

4.4.3 修改后的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 ...\n");        getchar();        return -1;     }     ecall_mymemcpyglobal_eid);    /* Destroy the enclave */    sgx_destroy_enclave(global_eid);    return 0;}

4.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)“

4.5.1 修改SGX SDK路径

如果我们的SGX SDK路径不是/opt/intel/sgxsdk,我们要进行修改,我的是/home/SGXSDK/sgxsdk,所以要将其改成/home/SGXSDK/sgxsdk,结果如下

SGX_SDK ?= /home/SGXSDK/sgxsdk

4.5.2 修改不可信代码编译的源文件

由于我们的不可信代码可能是多个文件,因此,我们最好在App_Cpp_Files中包括App文件夹中的所有cpp文件,更改后的结果如下。当然在我们的项目中App_Cpp_Files可以不用更改。

App_Cpp_Files := $(wildcard App/*.cpp) $(wildcard App/Edger8rSyntax/*.cpp) $(wildcard App/TrustedLibrary/*.cpp)

4.5.3 修改可信代码编译的源文件

由于我们的可信代码可能是多个文件,因此,我们最好在Enclave_Cpp_Files中包括App文件夹中的所有cpp文件,更改后的结果如下。当然在我们的项目中Enclave_Cpp_Files可以不用更改。

Enclave_Cpp_Files := $(wildcard Enclave/*.cpp) $(wildcard Enclave/Edger8rSyntax/*.cpp) $(wildcard Enclave/TrustedLibrary/*.cpp)

5. 编译修改后的项目文件

打开终端,进入到项目文件夹中,输入make进行编译,如下所示


6. 执行程序

在终端中输入./app,可以看到输出了”邱朋飞大神“,说明我们正确编写了程序。


原创粉丝点击