Intel® Software Guard Extensions (Intel® SGX)
Discussion board focused on hardware-based isolation and memory encryption to provide extended code protection in solutions.

how to use ocalls in SGX enclaves?

asd_a_1
Beginner
1,470 Views

We are trying to use system calls inside an enclave.

For this, we defined a ocall functions, since sys-calls cannot be invoked directly from the Enclave.

Under the Application project(i.e. Non-Enclave code), we have ocalls.h/cpp. Also, under the Enclave, we got ocallsWrappers.h/cpp.

For the design, we followed this Link

When rebuilding the solution, we get 2 errors:

error LNK1120: 1 unresolved externals   
error LNK2019: unresolved external symbol _ocall_read referenced in function _EnclaveExecBat_ocall_read   

Which we couldn't resolve, as we worked according to the code example provided with the SDK by Intel.

We need a direction to implement the ocalls functions such that we can invoke them from within the enclave (even  they are declared as 'untrusted' in the EDL - see bellow)

here is the content of our project (with code snippets):

tree.PNG

======================= EDL: =======================

enclave {
    trusted {
        /* define ECALLs here. */
		 public void trusted_foo([in, size=len] char* password, size_t len);
    };
    untrusted {
        /* define OCALLs here. */
		void ocall_read([in, size=len] char* str, size_t len);
    };
};

=======================  App.cpp:  =======================
 

#include "stdafx.h"
#include "sgx_urts.h"
#include "EnclaveExecBat_u.h"
#define ENCLAVE_FILE _T("EnclaveExecBat.signed.dll")

using namespace std;

int main(int argc, _TCHAR* argv[])
{
	sgx_enclave_id_t	eid;
	sgx_status_t		ret   = SGX_SUCCESS;
	sgx_launch_token_t	token = {0};
	int					updated = 0;
	// Create the Enclave with above launch token.
	ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &token, &updated, &eid, NULL);
	if (ret != SGX_SUCCESS) {
		printf("App: error %#x, failed to create enclave.\n", ret);
		return -1;
	}

	trusted_foo(eid, NULL, 0);

	// Destroy the enclave when all Enclave calls finished.
	if(SGX_SUCCESS != sgx_destroy_enclave(eid))
		return -1;
	getchar();
	return 0;
}

=======================  ocalls.h (under App project)  =======================

//untrusted
#ifndef __OCALLS
#define __OCALLS

void ocall_read(char* str, size_t len);
#endif //__OCALLS

=======================  ocalls.cpp (under App project)  =======================

#include "stdafx.h"
#include <stdio.h>
#include "ocalls.h"
void ocall_read(char* str, size_t len) {
	printf("in ocall_read\n");
}

=======================  EnclaveExecBat.cpp:  =======================

#include "EnclaveExecBat_t.h"
#include "sgx_trts.h"
#include "ocallsWrapper.h"
void trusted_foo(char* password, size_t len) {
	read(NULL , 0);
}

=======================  ocallsWrapper.cpp:  =======================

#include "ocallsWrapper.h"
#include "EnclaveExecBat_t.h"
#include "sgx_trts.h"
void read(char* str, size_t len) {
	ocall_read(str, len);
	
}

=======================  ocallsWrapper.h  =======================

#ifndef __OCALL_WRAPPER
#define __OCALL_WRAPPER

void read(char* str, size_t len);
#endif //__OCALL_WRAPPER

----------------------------------

How can we adjust our untrusted code to be invoke-able from the enclave?

Thanks in advance.

0 Kudos
1 Solution
Juan_d_Intel
Employee
1,470 Views

In the App project: delete ocalls.h and in ocalls.cpp replace #include "ocalls.h" with #include "EnclaveExecBat_u.h"

View solution in original post

0 Kudos
2 Replies
Juan_d_Intel
Employee
1,471 Views

In the App project: delete ocalls.h and in ocalls.cpp replace #include "ocalls.h" with #include "EnclaveExecBat_u.h"

0 Kudos
JohnMechalas
Employee
1,470 Views

You need to wrap the ocall_read function prototype in an extern "C" stanza:

 

//untrusted
#ifndef __OCALLS
#define __OCALLS


extern "C" {
    void ocall_read(char* str, size_t len);
};


#endif //__OCALLS

Otherwise C++'s name mangling prevents the linker from finding the symbol. Enclaves have to have pure C linkages.


These prototypes are automagically generated by edger8r, though, and should be in the _u.h file imported into your project. It doesn't look like it, but the SGX_UBRIDGE definition is a macro that expands to the right prototype definition:
 

void SGX_UBRIDGE(SGX_NOCONVENTION, ocall_read, (char* str, size_t len));

 

0 Kudos
Reply