/* * Copyright (C) 2011-2016 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 "uae_service_sim.h" #ifdef __cplusplus extern "C" { #endif static const uint8_t TIME_SOURCE_NONCE_SIM[32] = { 0x9d, 0x7c, 0x25, 0x07, 0x38, 0x53, 0x23, 0xb1, 0x9f, 0xba, 0xc8, 0x7b, 0xc0, 0x89, 0xde, 0x2d, 0x2b, 0x5f, 0x34, 0x6d, 0x9c, 0x35, 0xf5, 0xbc, 0xcd, 0x34, 0x7f, 0x75, 0x96, 0xc8, 0x27, 0xcc}; sgx_status_t pse_mc_create_sim( uint8_t *p_req_payload, uint8_t *p_resp_payload) { UNUSED(p_req_payload); sgx_status_t ret = SGX_ERROR_UNEXPECTED; pse_mc_create_resp_t *p_create_resp = (pse_mc_create_resp_t *)p_resp_payload; //initial create_resp p_create_resp->resp_hdr.service_id = PSE_MC_SERVICE; p_create_resp->resp_hdr.service_cmd = PSE_MC_CREATE; p_create_resp->resp_hdr.status = PSE_ERROR_INTERNAL; memset(p_create_resp->counter_id, 0xFF, sizeof(p_create_resp->counter_id)); memset(p_create_resp->nonce, 0xFF, sizeof(p_create_resp->nonce)); vmc_sim_t temp_vmc = {{0}, {0}, 0}; ret = get_counter_id(&temp_vmc); if(SGX_SUCCESS != ret){ return ret; } ret = store_vmc_sim(&temp_vmc); if(SGX_SUCCESS != ret){ return ret; } p_create_resp->resp_hdr.status = PSE_SUCCESS; if(memcpy_s(p_create_resp->counter_id, sizeof(p_create_resp->counter_id), temp_vmc.counter_id, sizeof(temp_vmc.counter_id))){ return SGX_ERROR_UNEXPECTED; } if(memcpy_s(p_create_resp->nonce, sizeof(p_create_resp->nonce), temp_vmc.nonce, sizeof(temp_vmc.nonce))){ return SGX_ERROR_UNEXPECTED; } return ret; } sgx_status_t pse_mc_read_sim( uint8_t *p_req_payload, uint8_t *p_resp_payload) { sgx_status_t ret = SGX_ERROR_UNEXPECTED; pse_mc_read_req_t *p_read_req = (pse_mc_read_req_t *)p_req_payload; pse_mc_read_resp_t *p_read_resp = (pse_mc_read_resp_t *)p_resp_payload; //initial create_resp p_read_resp->counter_value = 0; p_read_resp->resp_hdr.service_id = PSE_MC_SERVICE; p_read_resp->resp_hdr.service_cmd = PSE_MC_READ; p_read_resp->resp_hdr.status = PSE_ERROR_INTERNAL; vmc_sim_t temp_vmc = {{0}, {0}, 0}; if(memcpy_s(&temp_vmc.counter_id, sizeof(temp_vmc.counter_id), p_read_req->counter_id, sizeof(p_read_req->counter_id))){ return SGX_ERROR_UNEXPECTED; } if(memcpy_s(&temp_vmc.nonce, sizeof(temp_vmc.nonce), p_read_req->nonce, sizeof(p_read_req->nonce))){ return SGX_ERROR_UNEXPECTED; } ret = load_vmc_sim(&temp_vmc); if(SGX_SUCCESS != ret){ memset(&p_read_resp->counter_value, 0xFF, sizeof(p_read_resp->counter_value)); return ret; } p_read_resp->resp_hdr.status = PSE_SUCCESS; if(memcpy_s(&p_read_resp->counter_value, sizeof(p_read_resp->counter_value), &temp_vmc.counter_value, sizeof(temp_vmc.counter_value))){ return SGX_ERROR_UNEXPECTED; } return ret; } sgx_status_t pse_mc_inc_sim( uint8_t *p_req_payload, uint8_t *p_resp_payload) { sgx_status_t ret = SGX_ERROR_UNEXPECTED; pse_mc_inc_req_t *p_inc_req = (pse_mc_inc_req_t *)p_req_payload; pse_mc_inc_resp_t *p_inc_resp = (pse_mc_inc_resp_t *)p_resp_payload; //initial create_resp p_inc_resp->counter_value = 0; p_inc_resp->resp_hdr.service_id = PSE_MC_SERVICE; p_inc_resp->resp_hdr.service_cmd = PSE_MC_INC; p_inc_resp->resp_hdr.status = PSE_ERROR_INTERNAL; vmc_sim_t temp_vmc = {{0}, {0}, 0}; if(memcpy_s(&temp_vmc.counter_id, sizeof(temp_vmc.counter_id), p_inc_req->counter_id, sizeof(p_inc_req->counter_id))){ return SGX_ERROR_UNEXPECTED; } if(memcpy_s(&temp_vmc.nonce, sizeof(temp_vmc.nonce), p_inc_req->nonce, sizeof(p_inc_req->nonce))){ return SGX_ERROR_UNEXPECTED; } ret = load_vmc_sim(&temp_vmc); if(SGX_SUCCESS != ret){ return ret; } temp_vmc.counter_value++; ret = store_vmc_sim(&temp_vmc); if(SGX_SUCCESS != ret){ return ret; } p_inc_resp->resp_hdr.status = PSE_SUCCESS; if(memcpy_s(&p_inc_resp->counter_value, sizeof(p_inc_resp->counter_value), &temp_vmc.counter_value, sizeof(temp_vmc.counter_value))){ return SGX_ERROR_UNEXPECTED; } return ret; } sgx_status_t pse_mc_del_sim( uint8_t *p_req_payload, uint8_t *p_resp_payload) { sgx_status_t ret = SGX_ERROR_UNEXPECTED; pse_mc_del_req_t *p_del_req = (pse_mc_del_req_t *)p_req_payload; pse_mc_del_resp_t *p_del_resp = (pse_mc_del_resp_t *)p_resp_payload; //initial create_resp p_del_resp->resp_hdr.service_id = PSE_MC_SERVICE; p_del_resp->resp_hdr.service_cmd = PSE_MC_DEL; p_del_resp->resp_hdr.status = PSE_ERROR_INTERNAL; vmc_sim_t temp_vmc = {{0}, {0}, 0}; if(memcpy_s(&temp_vmc.counter_id, sizeof(temp_vmc.counter_id), p_del_req->counter_id, sizeof(p_del_req->counter_id))){ return SGX_ERROR_UNEXPECTED; } if(memcpy_s(&temp_vmc.nonce, sizeof(temp_vmc.nonce), p_del_req->nonce, sizeof(p_del_req->nonce))){ return SGX_ERROR_UNEXPECTED; } ret = del_vmc_sim(&temp_vmc); if(SGX_SUCCESS != ret){ return ret; } p_del_resp->resp_hdr.status = PSE_SUCCESS; return ret; } sgx_status_t pse_read_timer_sim( uint8_t *p_req_payload, uint8_t *p_resp_payload) { UNUSED(p_req_payload); pse_timer_read_resp_t *p_time_resp = (pse_timer_read_resp_t *)p_resp_payload; time_t t = time(0); p_time_resp->resp_hdr.service_id = PSE_TRUSTED_TIME_SERVICE; p_time_resp->resp_hdr.service_cmd = PSE_TIMER_READ; p_time_resp->timestamp = (uint64_t)t; if(memcpy_s(p_time_resp->time_source_nonce, sizeof(p_time_resp->time_source_nonce), TIME_SOURCE_NONCE_SIM, sizeof(p_time_resp->time_source_nonce))){ return SGX_ERROR_UNEXPECTED; } p_time_resp->resp_hdr.status = PSE_SUCCESS; return SGX_SUCCESS; } typedef sgx_status_t (*srv_pfn_t)(uint8_t *, uint8_t *); static const struct service_handler_t { uint16_t service_id; uint16_t service_cmd; uint16_t req_msg_size; uint16_t resp_msg_size; srv_pfn_t srv_pfn; } SERVICE_HANDLER[] = { {PSE_MC_SERVICE, PSE_MC_CREATE, sizeof(pse_mc_create_req_t), sizeof(pse_mc_create_resp_t), pse_mc_create_sim}, {PSE_MC_SERVICE, PSE_MC_READ, sizeof(pse_mc_read_req_t), sizeof(pse_mc_read_resp_t), pse_mc_read_sim}, {PSE_MC_SERVICE, PSE_MC_INC, sizeof(pse_mc_inc_req_t), sizeof(pse_mc_inc_resp_t), pse_mc_inc_sim}, {PSE_MC_SERVICE, PSE_MC_DEL, sizeof(pse_mc_del_req_t), sizeof(pse_mc_del_resp_t), pse_mc_del_sim}, {PSE_TRUSTED_TIME_SERVICE, PSE_TIMER_READ, sizeof(pse_timer_read_req_t), sizeof(pse_timer_read_resp_t), pse_read_timer_sim} }; static sgx_status_t invoke_service( const uint8_t *p_pse_message_req, size_t pse_message_req_size, uint8_t *p_pse_message_resp, size_t pse_message_resp_size, unsigned long timeout) { UNUSED(timeout); sgx_status_t ret = SGX_SUCCESS; if(!p_pse_message_req || !p_pse_message_resp){ return SGX_ERROR_INVALID_PARAMETER; } const pse_message_t *p_req_msg = (const pse_message_t *)p_pse_message_req; pse_message_t *p_resp_msg = (pse_message_t *)p_pse_message_resp; if(pse_message_req_size != sizeof(pse_message_t) + p_req_msg->payload_size){ return SGX_ERROR_INVALID_PARAMETER; } if(pse_message_resp_size < sizeof(pse_message_t) + p_resp_msg->exp_resp_size){ return SGX_ERROR_INVALID_PARAMETER; } const uint8_t *p_req_payload = p_req_msg->payload; uint8_t *p_resp_payload = p_resp_msg->payload; const pse_req_hdr_t *p_req_hdr = (const pse_req_hdr_t *)p_req_payload; for(unsigned int i = 0; i < sizeof(SERVICE_HANDLER) / sizeof(service_handler_t); i++) { if(p_req_hdr->service_id == SERVICE_HANDLER[i].service_id && p_req_hdr->service_cmd == SERVICE_HANDLER[i].service_cmd){ if(p_req_msg->payload_size != SERVICE_HANDLER[i].req_msg_size || p_req_msg->exp_resp_size != SERVICE_HANDLER[i].resp_msg_size) { ret = SGX_ERROR_UNEXPECTED; break; } memset(p_resp_payload, 0, p_req_msg->exp_resp_size); ret = SERVICE_HANDLER[i].srv_pfn(const_cast(p_req_payload), p_resp_payload); p_resp_msg->payload_size = p_req_msg->exp_resp_size; break; } } return ret; } sgx_status_t create_session_ocall(uint32_t *p_sid, uint8_t *p_dh_msg1, uint32_t dh_msg1_size, uint32_t timeout) { UNUSED(p_sid); UNUSED(p_dh_msg1); UNUSED(dh_msg1_size); UNUSED(timeout); return SGX_SUCCESS; } sgx_status_t exchange_report_ocall(uint32_t sid, const uint8_t *p_dh_msg2, uint32_t dh_msg2_size, uint8_t *p_dh_msg3, uint32_t dh_msg3_size, uint32_t timeout) { UNUSED(sid); UNUSED(p_dh_msg2); UNUSED(dh_msg2_size); UNUSED(p_dh_msg3); UNUSED(dh_msg3_size); UNUSED(timeout); return SGX_SUCCESS; } sgx_status_t close_session_ocall(uint32_t sid, uint32_t timeout) { UNUSED(sid); UNUSED(timeout); return SGX_SUCCESS; } sgx_status_t invoke_service_ocall( const uint8_t* pse_message_req, uint32_t pse_message_req_size, uint8_t* pse_message_resp, uint32_t pse_message_resp_size, uint32_t timeout ) { return invoke_service(pse_message_req, pse_message_req_size, pse_message_resp, pse_message_resp_size, timeout); } sgx_status_t sgx_get_ps_cap( sgx_ps_cap_t* p_sgx_ps_cap) { if (!p_sgx_ps_cap) return SGX_ERROR_INVALID_PARAMETER; p_sgx_ps_cap->ps_cap0 = 0x7; p_sgx_ps_cap->ps_cap1 = 0; return SGX_SUCCESS; } #ifdef __cplusplus } #endif