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

Passing c++ class/struct as void* to enclave and casting it back

kh__Naveen
Beginner
6,154 Views

I am stuck with a problem. I have a class(called SkipList) with a struct(called node) inside it. I am trying to pass this struct as a void* with [user_check] attribute into the enclave.

    struct node {
        size_t key;
        T2 value;
        vector<size_t> hashlabel;
        vector<node*> forward;
    };
Once I receive this inside the enclave I cast this into the struct type as below. 

SkipList<int,string>::node* head = static_cast<SkipList<int,string>::node*>(Node);

I see that the address of "head" after casting is correct ( I checked this address on application side too) and also the address of the "forward" member also is correct. But when I try to see the elements of "forward", I can see only 1 element. Actually there should be more 15 elements.

Can someone please tell me if this is an issue with SGX STL implementation of vectors? Why am I not able to see it as expected ?

0 Kudos
4 Replies
kh__Naveen
Beginner
6,154 Views

My question took 4 days to get approved and be posted here !!!!

0 Kudos
you_w_
New Contributor III
6,154 Views

Hi Naveen:

Can I see your enclave's edl file?If you want to pass something into an enclave through pointer,you need to specify the length of that pointer.  I think you had passed a wrong value to pointer length.

Regards

You

0 Kudos
kh__Naveen
Beginner
6,154 Views

you w. wrote:

Hi Naveen:

Can I see your enclave's edl file?If you want to pass something into an enclave through pointer,you need to specify the length of that pointer.  I think you had passed a wrong value to pointer length.

Regards

You

Hello,

Right now I have modified the code. But its still isn't working :(.

I have a simple node structure as below

    struct SkipNode {
        size_t key;
        T2 value;
        unsigned int currnodemaxlevel;
        std::array<size_t,17> hashlabel;
        std::array<SkipNode*,17> forward;
        SkipNode(T1 k, T2 v, unsigned int level): key(k), value(v), currnodemaxlevel(level), hashlabel({0}), forward({NULL}) {};
    };

In my untrusted application file, the code is as follows.

    auto nodesize = sizeof(SkipList<int, std::string>::SkipNode); //in debug mode size is "320"
    
    std::vector<SkipList<int, std::string>::SkipNode*> predlistserialized;
    ...
    //Filled the predlistserialized with 17 pointers of SkipNode* type.
    ...
    ...
    ret = server_enclave_generate_response(req->dest_enclave_id, &status, req->src_enclave_id, &req->msg, req->req_message_size, res, sizeof(skiplist_response_t) + sizeof(secure_message_t), (void*)(&predlistserialized));

 

And this is my enclave.edl file
 

enclave {
    include "sgx_eid.h"
    include "../App/datatypes.h"
    include "../Include/dh_session_protocol.h"
    from "sgx_tstdc.edl" import *;
    trusted{
            public uint32_t session_request(sgx_enclave_id_t src_enclave_id, [out] sgx_dh_msg1_t *dh_msg1, [out] uint32_t *session_id);
            public uint32_t exchange_report(sgx_enclave_id_t src_enclave_id, [in] sgx_dh_msg2_t *dh_msg2, [out] sgx_dh_msg3_t *dh_msg3, uint32_t session_id);
            public uint32_t generate_response(sgx_enclave_id_t src_enclave_id, [in, size = req_message_size] secure_message_t* req_message, size_t req_message_size, [out, size=resp_message_size] secure_message_t* resp_message, size_t resp_message_size, [user_check] void* predlistmap);
            public uint32_t end_session(sgx_enclave_id_t src_enclave_id);
            public uint32_t dummy(sgx_enclave_id_t sgx_enclave_id);
    };
    untrusted{
            uint32_t send_skiplist_operation_ocall([out] skiplist_response_t* res, [in] skiplist_request_t* req);
    };
};

And this is my Enclave.cpp file

ATTESTATION_STATUS generate_response(sgx_enclave_id_t src_enclave_id,
                                     secure_message_t* req_message,
                                     size_t req_message_size,
                                     secure_message_t* resp_message,
                                     size_t resp_message_size,
                                     void *snd)
{
    ...
    ...
   
    auto nodesize = sizeof(SkipList<int, std::string>::SkipNode); // Printed as 312 !!!
    std::vector<SkipList<int, std::string>::SkipNode*> *predlistserialized = static_cast<std::vector<SkipList<int, std::string>::SkipNode*>*>(snd);
    auto ptr1 = predlistserialized[0];
    auto ptr2 = predlistserialized[1];
    auto ptr3 = predlistserialized[2];

1. The first problem I see is that the SkipNode size is different in untrusted code(320 bytes) and inside the enclave(312 bytes). I dont understand why different size for the same structure ?
2. What I am trying to do is - In my untrusted file, I have some nodes of SkipNode* types. I am making a new variable of type Vector to pointers of SkipNode. That is, the vector predlistserialized holds the pointers to SkipNode.

3. I am trying to send this Predlistserialized to the enclave. I am passing it as void pointer with [user_check] attribute.

4. Inside the enclave I am typecasting it back to Predlistserialized type and trying to read the SkipNodes, but these nodes contain junk value.

Can anyone suggest me how to pass the address of list of SkipNodes into the enclave? The nodes are in thousands so I dont want to copy to inside enclave. Instead my SKipNodes are allocated in untrusted memory as the enclaves can also read the untrusted memory, I should see the same data. But this isnt working :(

0 Kudos
kh__Naveen
Beginner
6,154 Views

Guys, I got this sorted out. Actually the problem was that the size of the 2nd element in the structure was unknown at compile time and hence we cannot type cast it correctly.

0 Kudos
Reply