Attribute: sizefunc

ID 672321
Updated 9/4/2016
Version Latest
Public

author-image

By

Attribute: sizefunc

The Intel® Software Guard Extensions  sizefunc attribute modifier depends on a user defined trusted function which is called by the edge-routines to get the number of bytes to be copied. The sizefunc has similar functionality as the sizeof() operator. An example of where sizefunc can be used is for marshaling variable-length structures, which are buffers whose total size is specified by a combination of values stored at well-defined locations inside the buffer (although typically it is at a single location). To prevent “check first, use later” type of attacks, sizefunc is called twice. In the first call, sizefunc operates in untrusted memory. The second time, sizefunc operates in the data copied into trusted memory. If the sizes returned by the two sizefunc calls do not match, the trusted bridge will cancel the ECALL and will report an error to the untrusted application. Note that sizefunc must not be combined with the size attribute. sizefunc cannot be used with out alone, however sizefunc with both in and out is accepted. Additionally, users cannot define sizefunc as strlen or wcslen. In all these scenarios, the sgx_edger8r will throw an error. Strings should not be passed with the sizefunc modifier, but with the string or wstring keyword. sizefunc can be used with the count attribute which gives the total length to be equal to sizefunc * count. The following items are the prototype of the trusted sizefunc that you need to define inside the enclave:

size_t sizefunc_function_name(const parameter_type * p);

Where parameter_type is the data type of the parameter annotated with the sizefunc attribute. If you do not provide the definition of the sizefunc function, the linker will report an error.

Note

The function implementing a sizefunc should validate the input pointer carefully, before really using it. Since the function is called before the pointer is checked by the generated code.

Example

enclave{


trusted {


// Copies '100' bytes


public void test_size1([in, size=100] void* ptr, size_t len);


// Copies ‘len’ bytes


public void test_size2([in, size=len] void* ptr, size_t len);


// Copies cnt * sizeof(int) bytes


public void test_count([in, count=cnt] int* ptr, unsigned cnt);


// Copies cnt * len bytes


public void test_count_size([in, count=cnt, size=len] int* ptr,

unsigned cnt, size_t len);


// Copies get_packet_size bytes

// User must provide a function definition that matches

// size_t get_packet_size(const void* ptr);


void test_sizefunc([in, sizefunc=get_packet_size] void* ptr);


// Copies (get_packet_size * cnt) bytes


void test_sizefunc2(

[in, sizefunc=get_packet_size, count=cnt] void* ptr,

unsigned cnt);

};

};

 

Illegal Syntax:

 

enclave{


include "user_types.h"


trusted {


// size/count/sizefunc attributes must be used with

// pointer direction ([in, out])


void test_attribute_cant([size=len] void* ptr, size_t len);


// Cannot use sizefunc and size together


void test_sizefunc_size(

[in, size=100, sizefunc=packet_len] header* h);


// Cannot use strlen or wcslen as sizefunc


void test_sizefunc_strlen([in, sizefunc=strlen] header* h);

void test_sizefunc_wcslen([in, sizefunc=wcslen] header* h);

};

};
]]>

Arrays

The Enclave Definition Language (EDL) supports multidimensional, fixed-size arrays to be used in data structure definition and parameter declaration. Zero-length array and flexible array member, however, are not supported. The special attribute isary is used to designate function parameters that are of a user defined type array.

Example

enclave {

 

include "user_types.h" //for uArray - typedef int uArray[10];

 

trusted {

 

public void test_array([in] int arr[4]);

 

public void test_array_multi([in] int arr[4][4]);

 

public void test_isary([in, isary, size=len] uArray arr,

size_tlen);

};

};

Illegal Syntax:

enclave {

 

include "user_types.h" //for uArray - typedef int uArray[10];

 

trusted {

 

// Flexible array is not supported

public void test_flexible(int arr[][4]);

 

// Zero-length array is not supported.

public void test_zero(int arr[0]);

 

// User-defined array types need "isary"

public void test_miss_isary([in, size=len] uArray arr,

size_t len);

 

};

};

Support for arrays also includes attributes [in], [out] and [user_check], which are similar in usage to the pointers.

]]>

Allowing Untrusted Functions to Call Trusted Functions

The default behavior is that the untrusted functions (specified in the untrusted section in the EDL file) of an enclave cannot call any of the trusted functions of this enclave.

If you want to grant an untrusted function access to an enclave exported function, specify this access using the allow keyword.

Syntax

untrusted {
                        <function prototype> allow (func_name, func2_name, …);
       };

Example

enclave {
                        trusted {
                                public void get_secret([out] secret_t* secret);
                                void set_secret([in] secret_t* secret);
                        };
                        untrusted {
                                void replace_secret(
                                        [in] secret_t* new_secret,
                                        [out] secret_t* old_secret)
                                        allow (set_secret);
                        };
       };
]]>