SampleEnclave Analysis

Enclave.edl

import Edger8rSyntax/Types.edl



/* Enclave.edl - Top EDL file. */

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 *;

    /* 
     * ocall_print_string - invokes OCALL to display string buffer inside the enclave.
     *  [in]: copy the string buffer to App outside.
     *  [string]: specifies 'str' is a NULL terminated buffer.
     */
    untrusted {
        void ocall_print_string([in, string] const char *str);
    };

};

Types.edl defines ecalls with different parameter type

trusted {

        public void ecall_type_char(char val);
        public void ecall_type_int(int val);
        // other functions omitted

Use sgx_edger8r generate App/Enclave_u.c App/Enclave_u.h

cd App && /opt/intel/sgxsdk/bin/x64/sgx_edger8r --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path /opt/intel/sgxsdk/include
Enclave_u.c

We can find that all trusted functions compiled to the function with same name, but add parameter sgx_enclave_id_t eid .
All trusted functions call sgx_ecall with first parameter indicates the enclave id, the second parameter is generated function id. Other parameters will be interpreted soon.

sgx_status_t ecall_type_char(sgx_enclave_id_t eid, char val)
{
	sgx_status_t status;
	ms_ecall_type_char_t ms;
	ms.ms_val = val;
	status = sgx_ecall(eid, 0, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_type_enum_union(sgx_enclave_id_t eid, enum enum_foo_t val1, union union_foo_t* val2)
{
	sgx_status_t status;
	ms_ecall_type_enum_union_t ms;
	ms.ms_val1 = val1;
	ms.ms_val2 = val2;
	status = sgx_ecall(eid, 7, &ocall_table_Enclave, &ms);
	return status;
}

The third parameter of sgx_ecall is ocall_table_Enclave, which include all the functions untrusted, for example Enclave_ocall_print_string in Enclave.edl, added prefix Enclave_.

ocall_table_Enclave = {
	11,
	{
		(void*)Enclave_ocall_print_string,
		(void*)Enclave_ocall_pointer_user_check,
		(void*)Enclave_ocall_pointer_in,
		(void*)Enclave_ocall_pointer_out,
		(void*)Enclave_ocall_pointer_in_out,
		(void*)Enclave_ocall_function_allow,
		(void*)Enclave_sgx_oc_cpuidex,
		(void*)Enclave_sgx_thread_wait_untrusted_event_ocall,
		(void*)Enclave_sgx_thread_set_untrusted_event_ocall,
		(void*)Enclave_sgx_thread_setwait_untrusted_events_ocall,
		(void*)Enclave_sgx_thread_set_multiple_untrusted_events_ocall,
	}
};

The forth and last parameter is ms. Every trusted function has a struct to encapsulate all the parameters, for exmaple, function ecall_type_char has struct ms_ecall_type_char_t.

typedef struct ms_ecall_type_char_t {
	char ms_val;
} ms_ecall_type_char_t;

Parameters in and out

Pointers

   /* 
     * Following keywords/attributes are supported for pointers in Edger8r: 
     *      in, out, user_check, 
     *      string, wstring,
     *      const, size, count, isptr, readonly
     */

[user_check]

  • EDL Definition
  /*
         * [user_check]:
         *      the pointer won't be validated, and the buffer pointed by
         *      'val' is not copied into the enclave either. But Enclave 
         *      can modify the memory pointed by 'val'.
         */
        
        public size_t ecall_pointer_user_check([user_check] void *val, size_t sz);
  • Enclave Definition

size_t ecall_pointer_user_check(void* val, size_t sz)
{
    /* check if the buffer is allocated outside */
    if (sgx_is_outside_enclave(val, sz) != 1)
        abort();

    /*fence after sgx_is_outside_enclave check*/
    sgx_lfence();

    char tmp[100] = { 0 };
    size_t len = sz > 100 ? 100 : sz;

    /* copy the memory into the enclave to make sure 'val' 
     * is not being changed in checksum_internal() */
    memcpy(tmp, val, len);

    int32_t sum = checksum_internal((char*)tmp, len);
    printf("Checksum(0x%p, %zu) = 0x%x\n",
        val, len, (unsigned int)sum);

    /* modify outside memory directly */
    memcpy(val, "SGX_SUCCESS", len > 12 ? 12 : len);

    return len;
}
  • App Definition
 char c[128] = {0};
    size_t len = 0;
    memset(c, 0xe, 128);
    ret = ecall_pointer_user_check(global_eid, &len, &c, 128);
    if (ret != SGX_SUCCESS)
        abort();
    assert(strcmp(c, "SGX_SUCCESS") == 0);

[in]

  • EDL Definition
        /*
         * [in]:
         *      buffer with the same size will be allocated inside the enclave,
         *      content pointed by 'val' will be copied into the new allocated
         *      memory inside. Any changes performed inside the enclave will not 
         *      affect the buffer outside.
         */
        
        public void ecall_pointer_in([in] int *val);
  • Enclave Definition
/* ecall_pointer_in:
 *   the buffer of val is copied to the enclave.
 */

void ecall_pointer_in(int* val)
{
    if (sgx_is_within_enclave(val, sizeof(int)) != 1)
        abort();
    *val = 1234;
}
  • App Definition
	val = 0;
    ret = ecall_pointer_in(global_eid, &val);
    if (ret != SGX_SUCCESS)
        abort();
    assert(val == 0);

[out]

  • EDL Definition
   /*
         * [out]:
         *      buffer with the same size will be allocated inside the enclave,
         *      but the content pointed by 'val' won't be copied. But after return, 
         *      the buffer inside the enclave will copied into outside 'val'.
         */
        
        public void ecall_pointer_out([out] int *val);
  • Enclave Definition
/* ecall_pointer_out:
 *   the buffer of val is copied to the untrusted side.
 */
void ecall_pointer_out(int* val)
{
    if (sgx_is_within_enclave(val, sizeof(int)) != 1)
        abort();
    assert(*val == 0);
    *val = 1234;
}
  • App Definition
	val = 0;
    ret = ecall_pointer_out(global_eid, &val);
    if (ret != SGX_SUCCESS)
        abort();
    assert(val == 1234);

[in, out]

  • EDL Definition
 /*
         * [in, out]:
         *      buffer with the same size will be allocated inside the enclave,
         *      the content pointed by 'val' will be copied either. After return, 
         *      the buffer inside the enclave will by copied into outside 'val' again.
         */
        
        public void ecall_pointer_in_out([in, out] int *val);
        
  • Enclave Definition
/* ecall_pointer_in_out:
 * the buffer of val is double-copied.
 */
void ecall_pointer_in_out(int* val)
{
    if (sgx_is_within_enclave(val, sizeof(int)) != 1)
        abort();
    *val = 1234;
}
  • App Definition
    val = 0;
    ret = ecall_pointer_in_out(global_eid, &val);
    if (ret != SGX_SUCCESS)
        abort();
    assert(val == 1234);

[string]

  • EDL Definition
  /*
         * [string]:
         *      the attribute tells Edger8r 'str' is NULL terminated string, so strlen 
         *      will be used to count the length of buffer pointed by 'str'.
         */
        
        public void ecall_pointer_string([in, out, string] char *str);
  • Enclave Definition

/* ecall_pointer_string:
 *   [string] defines a string.
 */
void ecall_pointer_string(char* str)
{
    strncpy(str, "0987654321", strlen(str));
}
  • App Definition

    char str1[] = "1234567890";
    ret = ecall_pointer_string(global_eid, str1);
    if (ret != SGX_SUCCESS)
        abort();
    assert(strlen(str1) == 10 && memcmp(str1, "0987654321", strlen(str1)) == 0);

[const]

  • EDL Definition
  /*
         * [const]:
         *      the attribute tells Edger8r the buffer pointed by 'str' cannot be modified,
         *      so users cannot decorate 'str' with [out] attribute anymore.
         */
        
        public void ecall_pointer_string_const([in, string] const char *str);

  • Enclave Definition
/* ecall_pointer_string_const:
 *   const [string] defines a string that cannot be modified.
 */
void ecall_pointer_string_const(const char* str)
{
    char* temp = new char[strlen(str)];
    strncpy(temp, str, strlen(str));
    delete[] temp;
}
  • App Definition
	const char str2[] = "1234567890";
    ret = ecall_pointer_string_const(global_eid, str2);
    if (ret != SGX_SUCCESS)
        abort();
    assert(strlen(str2) == 10 && memcmp(str2, "1234567890", strlen(str2)) == 0);

[size]

  • EDL Definition
 /*
         * [size]:
         *      the attribute tells Edger8r the length of buffer in byte pointed by 'ptr' 
         *      (shall be copied or not). 
         * Note: Users shall not specify [size] on [string] parameters.
         */
        
        public void ecall_pointer_size([in, out, size=len] void *ptr, size_t len);
  • Enclave Definition
/* ecall_pointer_size:
 *   'len' needs to be specified to tell Edger8r the length of 'str'.
 */
void ecall_pointer_size(void* ptr, size_t len)
{
    strncpy((char*)ptr, "0987654321", len);
}
  • App Definition
char str3[] = "1234567890";
    ret = ecall_pointer_size(global_eid, (void*)str3, strlen(str3));
    if (ret != SGX_SUCCESS)
        abort();
    assert(strlen(str3) == 10 && memcmp(str3, "0987654321", strlen(str3)) == 0);

[count]

  • EDL Definition
 /*
         * [count]:
         *      the attribute tells Edger8r the number of integers to be copied from 'arr'.
         */
        
        public void ecall_pointer_count([in, out, count=cnt] int *arr, size_t cnt);
  • Enclave Definition
/* ecall_pointer_count:
 *   'cnt' needs to be specified to tell Edger8r the number of elements in 'arr'.
 */
void ecall_pointer_count(int* arr, size_t count)
{
    int cnt = (int)count;
    for (int i = (cnt - 1); i >= 0; i--)
        arr[i] = (cnt - 1 - i);
}
  • App Definition
    int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    ret = ecall_pointer_count(global_eid, arr, 10);
    if (ret != SGX_SUCCESS)
        abort();
    for (int i = 0; i < 10; i++)
        assert(arr[i] == (9 - i));

[isptr]

  • EDL Definition
/*
         * [isptr]:
         *      tells Edger8r the user defined type is a pointer; 
         * [readonly]:
         *      forbids the buffer allocated inside the enclave to be copied back to App
         *      (cannot use with [out]).
         */
        
        public void ecall_pointer_isptr_readonly([in, isptr, readonly, size=len] buffer_t buf, size_t len);
  • Enclave Definition
/* ecall_pointer_isptr_readonly:
 *   'buf' is user defined type, shall be tagged with [isptr].
 *   if it's not writable, [readonly] shall be specified. 
 */
void ecall_pointer_isptr_readonly(buffer_t buf, size_t len)
{
    strncpy((char*)buf, "0987654321", len);
}
  • App Definition
char str4[] = "1234567890";
    ret = ecall_pointer_isptr_readonly(global_eid, (buffer_t)str4, strlen(str4));
    if (ret != SGX_SUCCESS)
        abort();
    assert(strlen(str4) == 10 && memcmp(str4, "1234567890", strlen(str4)) == 0);

public functions and private function in edl

Edl Definition

trusted {

        /*
         * [public]:
         *      public ECALL can be called directly in App.
         */
        
        public void ecall_function_public(void);

        /*
         * [private]:
         *      private ECALL cannot be called directly in App.
         */
        
        int ecall_function_private(void);
    
    };

Enclave Definition

/* ecall_function_public:
 *   The public ECALL that invokes the OCALL 'ocall_function_allow'.
 */
void ecall_function_public(void)
{
    sgx_status_t ret = SGX_ERROR_UNEXPECTED;

    ret = ocall_function_allow();
    if (ret != SGX_SUCCESS)
        abort();
    
    return;
}

/* ecall_function_private:
 *   The private ECALL that only can be invoked in the OCALL 'ocall_function_allow'.
 */
int ecall_function_private(void)
{
    return 1;
}

App Definition

/* No need to implement memccpy here! */

/* edger8r_function_attributes:
 *   Invokes ECALL declared with calling convention attributes.
 *   Invokes ECALL declared with [public].
 */
void edger8r_function_attributes(void)
{
    sgx_status_t ret = SGX_ERROR_UNEXPECTED;

    ret = ecall_function_public(global_eid);
    if (ret != SGX_SUCCESS)
        abort();
    
    /* user shall not invoke private function here */
    int runned = 0;
    ret = ecall_function_private(global_eid, &runned);
    if (ret != SGX_ERROR_ECALL_NOT_ALLOWED || runned != 0)
        abort();
}

/* ocall_function_allow:
 *   The OCALL invokes the [allow]ed ECALL 'edger8r_private'.
 */
void ocall_function_allow(void)
{
    int runned = 0;
    sgx_status_t ret = SGX_ERROR_UNEXPECTED;
    
    ret = ecall_function_private(global_eid, &runned);
    if (ret != SGX_SUCCESS || runned != 1)
        abort();
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值