mirror of
https://github.com/intel/linux-sgx
synced 2026-06-08 14:49:32 +00:00
c505e6129a
Added support for Reproducible Enclave Build using Docker file. Added support for Intel AVX-512 instructions and Intel SHA Extensions New Instructions (SHA-NI) in trusted libraries. Support both EPID and ECDSA based quote for quoting related interfaces in sgx_uae_service library. Updated key exchange library to support both EPID and ECDSA based remote attestation. Support new interface to check platform information blob from remote attestation response message. Fixed bugs. Signed-off-by: Li, Xun <xun.li@intel.com>
711 lines
24 KiB
C++
711 lines
24 KiB
C++
/*
|
|
* Copyright (C) 2011-2019 Intel Corporation. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
|
|
#include "sgx_trts.h"
|
|
#include "sgx_utils.h"
|
|
#include "EnclaveMessageExchange.h"
|
|
#include "sgx_eid.h"
|
|
#include "error_codes.h"
|
|
#include "sgx_ecp_types.h"
|
|
#include "sgx_thread.h"
|
|
#include <map>
|
|
#include "dh_session_protocol.h"
|
|
#include "sgx_dh.h"
|
|
#include "sgx_tcrypto.h"
|
|
#include "LocalAttestationCode_t.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
uint32_t enclave_to_enclave_call_dispatcher(char* decrypted_data, size_t decrypted_data_length, char** resp_buffer, size_t* resp_length);
|
|
uint32_t message_exchange_response_generator(char* decrypted_data, char** resp_buffer, size_t* resp_length);
|
|
uint32_t verify_peer_enclave_trust(sgx_dh_session_enclave_identity_t* peer_enclave_identity);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#define MAX_SESSION_COUNT 16
|
|
|
|
//number of open sessions
|
|
uint32_t g_session_count = 0;
|
|
|
|
ATTESTATION_STATUS generate_session_id(uint32_t *session_id);
|
|
|
|
//Array of open session ids
|
|
session_id_tracker_t *g_session_id_tracker[MAX_SESSION_COUNT];
|
|
|
|
//Map between the source enclave id and the session information associated with that particular session
|
|
std::map<sgx_enclave_id_t, dh_session_t>g_dest_session_info_map;
|
|
|
|
//Create a session with the destination enclave
|
|
ATTESTATION_STATUS create_session(sgx_enclave_id_t src_enclave_id,
|
|
sgx_enclave_id_t dest_enclave_id,
|
|
dh_session_t *session_info)
|
|
{
|
|
sgx_dh_msg1_t dh_msg1; //Diffie-Hellman Message 1
|
|
sgx_key_128bit_t dh_aek; // Session Key
|
|
sgx_dh_msg2_t dh_msg2; //Diffie-Hellman Message 2
|
|
sgx_dh_msg3_t dh_msg3; //Diffie-Hellman Message 3
|
|
uint32_t session_id;
|
|
uint32_t retstatus;
|
|
sgx_status_t status = SGX_SUCCESS;
|
|
sgx_dh_session_t sgx_dh_session;
|
|
sgx_dh_session_enclave_identity_t responder_identity;
|
|
|
|
if(!session_info)
|
|
{
|
|
return INVALID_PARAMETER_ERROR;
|
|
}
|
|
|
|
memset(&dh_aek,0, sizeof(sgx_key_128bit_t));
|
|
memset(&dh_msg1, 0, sizeof(sgx_dh_msg1_t));
|
|
memset(&dh_msg2, 0, sizeof(sgx_dh_msg2_t));
|
|
memset(&dh_msg3, 0, sizeof(sgx_dh_msg3_t));
|
|
memset(session_info, 0, sizeof(dh_session_t));
|
|
|
|
//Intialize the session as a session initiator
|
|
status = sgx_dh_init_session(SGX_DH_SESSION_INITIATOR, &sgx_dh_session);
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
//Ocall to request for a session with the destination enclave and obtain session id and Message 1 if successful
|
|
status = session_request_ocall(&retstatus, src_enclave_id, dest_enclave_id, &dh_msg1, &session_id);
|
|
if (status == SGX_SUCCESS)
|
|
{
|
|
if ((ATTESTATION_STATUS)retstatus != SUCCESS)
|
|
return ((ATTESTATION_STATUS)retstatus);
|
|
}
|
|
else
|
|
{
|
|
return ATTESTATION_SE_ERROR;
|
|
}
|
|
//Process the message 1 obtained from desination enclave and generate message 2
|
|
status = sgx_dh_initiator_proc_msg1(&dh_msg1, &dh_msg2, &sgx_dh_session);
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
//Send Message 2 to Destination Enclave and get Message 3 in return
|
|
status = exchange_report_ocall(&retstatus, src_enclave_id, dest_enclave_id, &dh_msg2, &dh_msg3, session_id);
|
|
if (status == SGX_SUCCESS)
|
|
{
|
|
if ((ATTESTATION_STATUS)retstatus != SUCCESS)
|
|
return ((ATTESTATION_STATUS)retstatus);
|
|
}
|
|
else
|
|
{
|
|
return ATTESTATION_SE_ERROR;
|
|
}
|
|
|
|
//Process Message 3 obtained from the destination enclave
|
|
status = sgx_dh_initiator_proc_msg3(&dh_msg3, &sgx_dh_session, &dh_aek, &responder_identity);
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
// Verify the identity of the destination enclave
|
|
if(verify_peer_enclave_trust(&responder_identity) != SUCCESS)
|
|
{
|
|
return INVALID_SESSION;
|
|
}
|
|
|
|
memcpy(session_info->active.AEK, &dh_aek, sizeof(sgx_key_128bit_t));
|
|
session_info->session_id = session_id;
|
|
session_info->active.counter = 0;
|
|
session_info->status = ACTIVE;
|
|
memset(&dh_aek,0, sizeof(sgx_key_128bit_t));
|
|
return status;
|
|
}
|
|
|
|
//Handle the request from Source Enclave for a session
|
|
ATTESTATION_STATUS session_request(sgx_enclave_id_t src_enclave_id,
|
|
sgx_dh_msg1_t *dh_msg1,
|
|
uint32_t *session_id )
|
|
{
|
|
dh_session_t session_info;
|
|
sgx_dh_session_t sgx_dh_session;
|
|
sgx_status_t status = SGX_SUCCESS;
|
|
|
|
if(!session_id || !dh_msg1)
|
|
{
|
|
return INVALID_PARAMETER_ERROR;
|
|
}
|
|
//Intialize the session as a session responder
|
|
status = sgx_dh_init_session(SGX_DH_SESSION_RESPONDER, &sgx_dh_session);
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
//get a new SessionID
|
|
if ((status = (sgx_status_t)generate_session_id(session_id)) != SUCCESS)
|
|
return status; //no more sessions available
|
|
|
|
//Allocate memory for the session id tracker
|
|
g_session_id_tracker[*session_id] = (session_id_tracker_t *)malloc(sizeof(session_id_tracker_t));
|
|
if(!g_session_id_tracker[*session_id])
|
|
{
|
|
return MALLOC_ERROR;
|
|
}
|
|
|
|
memset(g_session_id_tracker[*session_id], 0, sizeof(session_id_tracker_t));
|
|
g_session_id_tracker[*session_id]->session_id = *session_id;
|
|
session_info.status = IN_PROGRESS;
|
|
|
|
//Generate Message1 that will be returned to Source Enclave
|
|
status = sgx_dh_responder_gen_msg1((sgx_dh_msg1_t*)dh_msg1, &sgx_dh_session);
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
SAFE_FREE(g_session_id_tracker[*session_id]);
|
|
return status;
|
|
}
|
|
memcpy(&session_info.in_progress.dh_session, &sgx_dh_session, sizeof(sgx_dh_session_t));
|
|
//Store the session information under the correspoding source enlave id key
|
|
g_dest_session_info_map.insert(std::pair<sgx_enclave_id_t, dh_session_t>(src_enclave_id, session_info));
|
|
|
|
return status;
|
|
}
|
|
|
|
//Verify Message 2, generate Message3 and exchange Message 3 with Source Enclave
|
|
ATTESTATION_STATUS exchange_report(sgx_enclave_id_t src_enclave_id,
|
|
sgx_dh_msg2_t *dh_msg2,
|
|
sgx_dh_msg3_t *dh_msg3,
|
|
uint32_t session_id)
|
|
{
|
|
|
|
sgx_key_128bit_t dh_aek; // Session key
|
|
dh_session_t *session_info;
|
|
ATTESTATION_STATUS status = SUCCESS;
|
|
sgx_dh_session_t sgx_dh_session;
|
|
sgx_dh_session_enclave_identity_t initiator_identity;
|
|
|
|
if(!dh_msg2 || !dh_msg3)
|
|
{
|
|
return INVALID_PARAMETER_ERROR;
|
|
}
|
|
|
|
memset(&dh_aek,0, sizeof(sgx_key_128bit_t));
|
|
do
|
|
{
|
|
//Retreive the session information for the corresponding source enclave id
|
|
std::map<sgx_enclave_id_t, dh_session_t>::iterator it = g_dest_session_info_map.find(src_enclave_id);
|
|
if(it != g_dest_session_info_map.end())
|
|
{
|
|
session_info = &it->second;
|
|
}
|
|
else
|
|
{
|
|
status = INVALID_SESSION;
|
|
break;
|
|
}
|
|
|
|
if(session_info->status != IN_PROGRESS)
|
|
{
|
|
status = INVALID_SESSION;
|
|
break;
|
|
}
|
|
|
|
memcpy(&sgx_dh_session, &session_info->in_progress.dh_session, sizeof(sgx_dh_session_t));
|
|
|
|
dh_msg3->msg3_body.additional_prop_length = 0;
|
|
//Process message 2 from source enclave and obtain message 3
|
|
sgx_status_t se_ret = sgx_dh_responder_proc_msg2(dh_msg2,
|
|
dh_msg3,
|
|
&sgx_dh_session,
|
|
&dh_aek,
|
|
&initiator_identity);
|
|
if(SGX_SUCCESS != se_ret)
|
|
{
|
|
status = se_ret;
|
|
break;
|
|
}
|
|
|
|
//Verify source enclave's trust
|
|
if(verify_peer_enclave_trust(&initiator_identity) != SUCCESS)
|
|
{
|
|
return INVALID_SESSION;
|
|
}
|
|
|
|
//save the session ID, status and initialize the session nonce
|
|
session_info->session_id = session_id;
|
|
session_info->status = ACTIVE;
|
|
session_info->active.counter = 0;
|
|
memcpy(session_info->active.AEK, &dh_aek, sizeof(sgx_key_128bit_t));
|
|
memset(&dh_aek,0, sizeof(sgx_key_128bit_t));
|
|
g_session_count++;
|
|
}while(0);
|
|
|
|
if(status != SUCCESS)
|
|
{
|
|
end_session(src_enclave_id);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
//Request for the response size, send the request message to the destination enclave and receive the response message back
|
|
ATTESTATION_STATUS send_request_receive_response(sgx_enclave_id_t src_enclave_id,
|
|
sgx_enclave_id_t dest_enclave_id,
|
|
dh_session_t *session_info,
|
|
char *inp_buff,
|
|
size_t inp_buff_len,
|
|
size_t max_out_buff_size,
|
|
char **out_buff,
|
|
size_t* out_buff_len)
|
|
{
|
|
const uint8_t* plaintext;
|
|
uint32_t plaintext_length;
|
|
sgx_status_t status;
|
|
uint32_t retstatus;
|
|
secure_message_t* req_message;
|
|
secure_message_t* resp_message;
|
|
uint8_t *decrypted_data;
|
|
uint32_t decrypted_data_length;
|
|
uint32_t plain_text_offset;
|
|
uint8_t l_tag[TAG_SIZE];
|
|
plaintext = (const uint8_t*)(" ");
|
|
plaintext_length = 0;
|
|
|
|
if(!session_info || !inp_buff)
|
|
{
|
|
return INVALID_PARAMETER_ERROR;
|
|
}
|
|
//Check if the nonce for the session has not exceeded 2^32-2 if so end session and start a new session
|
|
if(session_info->active.counter == ((uint32_t) - 2))
|
|
{
|
|
close_session(src_enclave_id, dest_enclave_id);
|
|
create_session(src_enclave_id, dest_enclave_id, session_info);
|
|
}
|
|
|
|
//Allocate memory for the AES-GCM request message
|
|
req_message = (secure_message_t*)malloc(sizeof(secure_message_t)+ inp_buff_len);
|
|
if(!req_message)
|
|
{
|
|
return MALLOC_ERROR;
|
|
}
|
|
|
|
memset(req_message,0,sizeof(secure_message_t)+ inp_buff_len);
|
|
const uint32_t data2encrypt_length = (uint32_t)inp_buff_len;
|
|
//Set the payload size to data to encrypt length
|
|
req_message->message_aes_gcm_data.payload_size = data2encrypt_length;
|
|
|
|
//Use the session nonce as the payload IV
|
|
memcpy(req_message->message_aes_gcm_data.reserved,&session_info->active.counter,sizeof(session_info->active.counter));
|
|
|
|
//Set the session ID of the message to the current session id
|
|
req_message->session_id = session_info->session_id;
|
|
|
|
//Prepare the request message with the encrypted payload
|
|
status = sgx_rijndael128GCM_encrypt(&session_info->active.AEK, (uint8_t*)inp_buff, data2encrypt_length,
|
|
reinterpret_cast<uint8_t *>(&(req_message->message_aes_gcm_data.payload)),
|
|
reinterpret_cast<uint8_t *>(&(req_message->message_aes_gcm_data.reserved)),
|
|
sizeof(req_message->message_aes_gcm_data.reserved), plaintext, plaintext_length,
|
|
&(req_message->message_aes_gcm_data.payload_tag));
|
|
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
SAFE_FREE(req_message);
|
|
return status;
|
|
}
|
|
|
|
//Allocate memory for the response payload to be copied
|
|
*out_buff = (char*)malloc(max_out_buff_size);
|
|
if(!*out_buff)
|
|
{
|
|
SAFE_FREE(req_message);
|
|
return MALLOC_ERROR;
|
|
}
|
|
|
|
memset(*out_buff, 0, max_out_buff_size);
|
|
|
|
//Allocate memory for the response message
|
|
resp_message = (secure_message_t*)malloc(sizeof(secure_message_t)+ max_out_buff_size);
|
|
if(!resp_message)
|
|
{
|
|
SAFE_FREE(req_message);
|
|
return MALLOC_ERROR;
|
|
}
|
|
|
|
memset(resp_message, 0, sizeof(secure_message_t)+ max_out_buff_size);
|
|
|
|
//Ocall to send the request to the Destination Enclave and get the response message back
|
|
status = send_request_ocall(&retstatus, src_enclave_id, dest_enclave_id, req_message,
|
|
(sizeof(secure_message_t)+ inp_buff_len), max_out_buff_size,
|
|
resp_message, (sizeof(secure_message_t)+ max_out_buff_size));
|
|
if (status == SGX_SUCCESS)
|
|
{
|
|
if ((ATTESTATION_STATUS)retstatus != SUCCESS)
|
|
{
|
|
SAFE_FREE(req_message);
|
|
SAFE_FREE(resp_message);
|
|
return ((ATTESTATION_STATUS)retstatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SAFE_FREE(req_message);
|
|
SAFE_FREE(resp_message);
|
|
return ATTESTATION_SE_ERROR;
|
|
}
|
|
|
|
//Code to process the response message from the Destination Enclave
|
|
|
|
decrypted_data_length = resp_message->message_aes_gcm_data.payload_size;
|
|
plain_text_offset = decrypted_data_length;
|
|
decrypted_data = (uint8_t*)malloc(decrypted_data_length);
|
|
if(!decrypted_data)
|
|
{
|
|
SAFE_FREE(req_message);
|
|
SAFE_FREE(resp_message);
|
|
return MALLOC_ERROR;
|
|
}
|
|
memset(&l_tag, 0, 16);
|
|
|
|
memset(decrypted_data, 0, decrypted_data_length);
|
|
|
|
//Decrypt the response message payload
|
|
status = sgx_rijndael128GCM_decrypt(&session_info->active.AEK, resp_message->message_aes_gcm_data.payload,
|
|
decrypted_data_length, decrypted_data,
|
|
reinterpret_cast<uint8_t *>(&(resp_message->message_aes_gcm_data.reserved)),
|
|
sizeof(resp_message->message_aes_gcm_data.reserved), &(resp_message->message_aes_gcm_data.payload[plain_text_offset]), plaintext_length,
|
|
&resp_message->message_aes_gcm_data.payload_tag);
|
|
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
SAFE_FREE(req_message);
|
|
SAFE_FREE(decrypted_data);
|
|
SAFE_FREE(resp_message);
|
|
return status;
|
|
}
|
|
|
|
// Verify if the nonce obtained in the response is equal to the session nonce + 1 (Prevents replay attacks)
|
|
if(*(resp_message->message_aes_gcm_data.reserved) != (session_info->active.counter + 1 ))
|
|
{
|
|
SAFE_FREE(req_message);
|
|
SAFE_FREE(resp_message);
|
|
SAFE_FREE(decrypted_data);
|
|
return INVALID_PARAMETER_ERROR;
|
|
}
|
|
|
|
//Update the value of the session nonce in the source enclave
|
|
session_info->active.counter = session_info->active.counter + 1;
|
|
|
|
memcpy(out_buff_len, &decrypted_data_length, sizeof(decrypted_data_length));
|
|
memcpy(*out_buff, decrypted_data, decrypted_data_length);
|
|
|
|
SAFE_FREE(decrypted_data);
|
|
SAFE_FREE(req_message);
|
|
SAFE_FREE(resp_message);
|
|
return SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
//Process the request from the Source enclave and send the response message back to the Source enclave
|
|
ATTESTATION_STATUS generate_response(sgx_enclave_id_t src_enclave_id,
|
|
secure_message_t* req_message,
|
|
size_t req_message_size,
|
|
size_t max_payload_size,
|
|
secure_message_t* resp_message,
|
|
size_t resp_message_size)
|
|
{
|
|
const uint8_t* plaintext;
|
|
uint32_t plaintext_length;
|
|
uint8_t *decrypted_data;
|
|
uint32_t decrypted_data_length;
|
|
uint32_t plain_text_offset;
|
|
ms_in_msg_exchange_t * ms;
|
|
size_t resp_data_length;
|
|
size_t resp_message_calc_size;
|
|
char* resp_data;
|
|
uint8_t l_tag[TAG_SIZE];
|
|
size_t header_size, expected_payload_size;
|
|
dh_session_t *session_info;
|
|
secure_message_t* temp_resp_message;
|
|
uint32_t ret;
|
|
sgx_status_t status;
|
|
|
|
plaintext = (const uint8_t*)(" ");
|
|
plaintext_length = 0;
|
|
|
|
if(!req_message || !resp_message)
|
|
{
|
|
return INVALID_PARAMETER_ERROR;
|
|
}
|
|
|
|
//Get the session information from the map corresponding to the source enclave id
|
|
std::map<sgx_enclave_id_t, dh_session_t>::iterator it = g_dest_session_info_map.find(src_enclave_id);
|
|
if(it != g_dest_session_info_map.end())
|
|
{
|
|
session_info = &it->second;
|
|
}
|
|
else
|
|
{
|
|
return INVALID_SESSION;
|
|
}
|
|
|
|
if(session_info->status != ACTIVE)
|
|
{
|
|
return INVALID_SESSION;
|
|
}
|
|
|
|
//Set the decrypted data length to the payload size obtained from the message
|
|
decrypted_data_length = req_message->message_aes_gcm_data.payload_size;
|
|
|
|
header_size = sizeof(secure_message_t);
|
|
expected_payload_size = req_message_size - header_size;
|
|
|
|
//Verify the size of the payload
|
|
if(expected_payload_size != decrypted_data_length)
|
|
return INVALID_PARAMETER_ERROR;
|
|
|
|
memset(&l_tag, 0, 16);
|
|
plain_text_offset = decrypted_data_length;
|
|
decrypted_data = (uint8_t*)malloc(decrypted_data_length);
|
|
if(!decrypted_data)
|
|
{
|
|
return MALLOC_ERROR;
|
|
}
|
|
|
|
memset(decrypted_data, 0, decrypted_data_length);
|
|
|
|
//Decrypt the request message payload from source enclave
|
|
status = sgx_rijndael128GCM_decrypt(&session_info->active.AEK, req_message->message_aes_gcm_data.payload,
|
|
decrypted_data_length, decrypted_data,
|
|
reinterpret_cast<uint8_t *>(&(req_message->message_aes_gcm_data.reserved)),
|
|
sizeof(req_message->message_aes_gcm_data.reserved), &(req_message->message_aes_gcm_data.payload[plain_text_offset]), plaintext_length,
|
|
&req_message->message_aes_gcm_data.payload_tag);
|
|
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
SAFE_FREE(decrypted_data);
|
|
return status;
|
|
}
|
|
|
|
//Casting the decrypted data to the marshaling structure type to obtain type of request (generic message exchange/enclave to enclave call)
|
|
ms = (ms_in_msg_exchange_t *)decrypted_data;
|
|
|
|
|
|
// Verify if the nonce obtained in the request is equal to the session nonce
|
|
if((uint32_t)*(req_message->message_aes_gcm_data.reserved) != session_info->active.counter || *(req_message->message_aes_gcm_data.reserved) > ((2^32)-2))
|
|
{
|
|
SAFE_FREE(decrypted_data);
|
|
return INVALID_PARAMETER_ERROR;
|
|
}
|
|
|
|
if(ms->msg_type == MESSAGE_EXCHANGE)
|
|
{
|
|
//Call the generic secret response generator for message exchange
|
|
ret = message_exchange_response_generator((char*)decrypted_data, &resp_data, &resp_data_length);
|
|
if(ret !=0)
|
|
{
|
|
SAFE_FREE(decrypted_data);
|
|
SAFE_FREE(resp_data);
|
|
return INVALID_SESSION;
|
|
}
|
|
}
|
|
else if(ms->msg_type == ENCLAVE_TO_ENCLAVE_CALL)
|
|
{
|
|
//Call the destination enclave's dispatcher to call the appropriate function in the destination enclave
|
|
ret = enclave_to_enclave_call_dispatcher((char*)decrypted_data, decrypted_data_length, &resp_data, &resp_data_length);
|
|
if(ret !=0)
|
|
{
|
|
SAFE_FREE(decrypted_data);
|
|
SAFE_FREE(resp_data);
|
|
return INVALID_SESSION;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SAFE_FREE(decrypted_data);
|
|
return INVALID_REQUEST_TYPE_ERROR;
|
|
}
|
|
|
|
|
|
if(resp_data_length > max_payload_size)
|
|
{
|
|
SAFE_FREE(resp_data);
|
|
SAFE_FREE(decrypted_data);
|
|
return OUT_BUFFER_LENGTH_ERROR;
|
|
}
|
|
|
|
resp_message_calc_size = sizeof(secure_message_t)+ resp_data_length;
|
|
|
|
if(resp_message_calc_size > resp_message_size)
|
|
{
|
|
SAFE_FREE(resp_data);
|
|
SAFE_FREE(decrypted_data);
|
|
return OUT_BUFFER_LENGTH_ERROR;
|
|
}
|
|
|
|
//Code to build the response back to the Source Enclave
|
|
temp_resp_message = (secure_message_t*)malloc(resp_message_calc_size);
|
|
if(!temp_resp_message)
|
|
{
|
|
SAFE_FREE(resp_data);
|
|
SAFE_FREE(decrypted_data);
|
|
return MALLOC_ERROR;
|
|
}
|
|
|
|
memset(temp_resp_message,0,sizeof(secure_message_t)+ resp_data_length);
|
|
const uint32_t data2encrypt_length = (uint32_t)resp_data_length;
|
|
temp_resp_message->session_id = session_info->session_id;
|
|
temp_resp_message->message_aes_gcm_data.payload_size = data2encrypt_length;
|
|
|
|
//Increment the Session Nonce (Replay Protection)
|
|
session_info->active.counter = session_info->active.counter + 1;
|
|
|
|
//Set the response nonce as the session nonce
|
|
memcpy(&temp_resp_message->message_aes_gcm_data.reserved,&session_info->active.counter,sizeof(session_info->active.counter));
|
|
|
|
//Prepare the response message with the encrypted payload
|
|
status = sgx_rijndael128GCM_encrypt(&session_info->active.AEK, (uint8_t*)resp_data, data2encrypt_length,
|
|
reinterpret_cast<uint8_t *>(&(temp_resp_message->message_aes_gcm_data.payload)),
|
|
reinterpret_cast<uint8_t *>(&(temp_resp_message->message_aes_gcm_data.reserved)),
|
|
sizeof(temp_resp_message->message_aes_gcm_data.reserved), plaintext, plaintext_length,
|
|
&(temp_resp_message->message_aes_gcm_data.payload_tag));
|
|
|
|
if(SGX_SUCCESS != status)
|
|
{
|
|
SAFE_FREE(resp_data);
|
|
SAFE_FREE(decrypted_data);
|
|
SAFE_FREE(temp_resp_message);
|
|
return status;
|
|
}
|
|
|
|
memset(resp_message, 0, sizeof(secure_message_t)+ resp_data_length);
|
|
memcpy(resp_message, temp_resp_message, sizeof(secure_message_t)+ resp_data_length);
|
|
|
|
SAFE_FREE(decrypted_data);
|
|
SAFE_FREE(resp_data);
|
|
SAFE_FREE(temp_resp_message);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
//Close a current session
|
|
ATTESTATION_STATUS close_session(sgx_enclave_id_t src_enclave_id,
|
|
sgx_enclave_id_t dest_enclave_id)
|
|
{
|
|
sgx_status_t status;
|
|
|
|
uint32_t retstatus;
|
|
|
|
//Ocall to ask the destination enclave to end the session
|
|
status = end_session_ocall(&retstatus, src_enclave_id, dest_enclave_id);
|
|
if (status == SGX_SUCCESS)
|
|
{
|
|
if ((ATTESTATION_STATUS)retstatus != SUCCESS)
|
|
return ((ATTESTATION_STATUS)retstatus);
|
|
}
|
|
else
|
|
{
|
|
return ATTESTATION_SE_ERROR;
|
|
}
|
|
return SUCCESS;
|
|
}
|
|
|
|
//Respond to the request from the Source Enclave to close the session
|
|
ATTESTATION_STATUS end_session(sgx_enclave_id_t src_enclave_id)
|
|
{
|
|
ATTESTATION_STATUS status = SUCCESS;
|
|
int i;
|
|
dh_session_t session_info;
|
|
uint32_t session_id;
|
|
|
|
//Get the session information from the map corresponding to the source enclave id
|
|
std::map<sgx_enclave_id_t, dh_session_t>::iterator it = g_dest_session_info_map.find(src_enclave_id);
|
|
if(it != g_dest_session_info_map.end())
|
|
{
|
|
session_info = it->second;
|
|
}
|
|
else
|
|
{
|
|
return INVALID_SESSION;
|
|
}
|
|
|
|
session_id = session_info.session_id;
|
|
//Erase the session information for the current session
|
|
g_dest_session_info_map.erase(src_enclave_id);
|
|
|
|
//Update the session id tracker
|
|
if (g_session_count > 0)
|
|
{
|
|
//check if session exists
|
|
for (i=1; i <= MAX_SESSION_COUNT; i++)
|
|
{
|
|
if(g_session_id_tracker[i-1] != NULL && g_session_id_tracker[i-1]->session_id == session_id)
|
|
{
|
|
memset(g_session_id_tracker[i-1], 0, sizeof(session_id_tracker_t));
|
|
SAFE_FREE(g_session_id_tracker[i-1]);
|
|
g_session_count--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
//Returns a new sessionID for the source destination session
|
|
ATTESTATION_STATUS generate_session_id(uint32_t *session_id)
|
|
{
|
|
ATTESTATION_STATUS status = SUCCESS;
|
|
|
|
if(!session_id)
|
|
{
|
|
return INVALID_PARAMETER_ERROR;
|
|
}
|
|
//if the session structure is untintialized, set that as the next session ID
|
|
for (int i = 0; i < MAX_SESSION_COUNT; i++)
|
|
{
|
|
if (g_session_id_tracker[i] == NULL)
|
|
{
|
|
*session_id = i;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
status = NO_AVAILABLE_SESSION_ERROR;
|
|
|
|
return status;
|
|
|
|
}
|