Writing Enclave Functions

  • Describe each function that may be called from outside of the enclave in the .edl file.

  • The functions can use special versions of the C/C++ runtime libraries (available in the SDK).

  • System calls are not allowed (use ocalls instead; C linkage only!).

  • Not all C/C++ language features are available!

  • The sgx_edger8r tool will take care of the details of making the execution flow enter or leave an enclave.

    • Pointer arguments in ecall functions must point to untrusted memory.

    • Pointer arguments in ocall functions must point to trusted memory.

    • You may need to copy the buffer from untrusted memory to trusted memory.

  • Keep in mind that the enclave will be statically linked.

Some available trusted libraries

  • libsgx_tstdc.a (standard C library, math, strings, etc.).

  • libsgx_tcxx.a (standard C++ libraries, STL)

  • libsgx_tservice.a (seal/unseal, EC DH library, etc.)

  • libsgx_tcrypto.a

  • libsgx_tkey_exchange.a

  • libsgx_tpcl.a (Protected Code Loader, for enclave code confidentiality).

One enclave function printf_helloworld prints the text "Hello World".

It cannot do this directly, so it calls an untrusted function, ocall_printf_string to do the actual printing.

In this example, for the enclave code, the printf function is re-implemented so that its output goes to a string.

In the untrusted part, the enclave is loaded and the printf_helloworld function is called.

List of files.

  • Makefile

  • App/App.cpp

  • App/App.h

  • Enclave/Enclave.config.xml

  • Enclave/Enclave.cpp

  • Enclave/Enclave.edl

  • Enclave/Enclave.h

  • Enclave/Enclave.lds

  • Enclave/Enclave_private.pem

Relevant parts of the Makefile:

  • SGX_SDK ?= /opt/intel/sgxsdk

  • SGX_MODE ?= HW

  • SGX_ARCH ?= x64

  • SGX_DEBUG ?= 1

You can also add:

  • SGX_PRERELEASE ?= 0

List your untrusted source code files (the application) in the ######## App Settings ######## section.

List your trusted source code files (the SGX enclave) in the ######## Enclave Settings ######## section.

Relevant parts of

App/App.h

#include "sgx_error.h"      /* sgx_status_t */
#include "sgx_eid.h"        /* sgx_enclave_id_t */

# define TOKEN_FILENAME      "enclave.token"
# define ENCLAVE_FILENAME    "enclave.signed.so"

extern sgx_enclave_id_t global_eid;     /* global enclave id */

App/App.cpp

int initialize_enclave(void) { /*...*/ }

void ocall_print_string(const char *str){ printf("%s",str); }

int SGX_CDECL main(int argc, char *argv[])
{
    if(initialize_enclave() < 0) return -1;
    printf_helloworld(global_eid);
    sgx_destroy_enclave(global_eid);
}

Enclave/Enclave_config.xml

<EnclaveConfiguration>
    <ProdID>0</ProdID>
    <ISVSVN>0</ISVSVN>
    <StackMaxSize>0x40000</StackMaxSize>
    <HeapMaxSize>0x100000</HeapMaxSize>
    <TCSNum>10</TCSNum>
    <TCSPolicy>1</TCSPolicy>
    <DisableDebug>0</DisableDebug>
    <MiscSelect>0</MiscSelect>
    <MiscMask>0xFFFFFFFF</MiscMask>
</EnclaveConfiguration>

Enclave/Enclave.edl

enclave {
    trusted {
        public void printf_helloworld();
    };
    untrusted {
        void ocall_print_string([in,string] const char *str);
    };
};

Enclave/Enclave.h

#include <stdlib.h>
#include <assert.h>

#if defined(__cplusplus)
extern "C" {
    #endif
    void printf(const char *fmt, ...);
    void printf_helloworld();
    #if defined(__cplusplus)
}
#endif

Enclave/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_helloworld() { printf("Hello World\n"); }

Last updated