/* * Copyright (C) 2011-2018 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 "arch.h" #include "PSEClass.h" #include "pse_op_u.h" #include "pse_op_u.c" #include "pse_op_psda_ocall.cpp" #include "pse_op_vmc_sqlite_ocall.cpp" #include "sgx_tseal.h" #include "pairing_blob.h" #include "oal/oal.h" #include "byte_order.h" #include "LEClass.h" #include "ae_ipp.h" #include "PSDAService.h" #include "se_wrapper.h" #include "PSEPRClass.h" #include "sgx_profile.h" #include "sgx_uae_service.h" #include "aesm_pse_status.h" #include "interface_psda.h" #define PSDA_CAP_PRTC 0x1 #define PSDA_CAP_RPDATA 0x8 #define CHECK_ECALL_RET(status,ret) \ if((status) == SGX_ERROR_ENCLAVE_LOST) \ {retry++;continue;} \ else if ((status) == SGX_ERROR_OUT_OF_MEMORY) { \ (ret) = AE_OUT_OF_MEMORY_ERROR; break; } \ else if ((status) != SGX_SUCCESS) { \ (ret) = AE_FAILURE; break; } \ else if ((ret) != 0) { break; } extern uint32_t upse_iclsInit(); ae_error_t CPSEClass::init_ps(void) { // Try to establish PSDA session during startup PROFILE_START("PSDAService::start_service()"); bool psda_started = PSDAService::instance().start_service(); PROFILE_END("PSDAService::start_service()"); if (!psda_started) { AESM_DBG_ERROR("Psda not available"); AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_START]); // This is logged as a WARNING here, since the system may not require PS capability AESM_LOG_WARN_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_FAIL_DAL]); // Set state to UNAVAILABLE m_status = PSE_STATUS_UNAVAILABLE; PlatformServiceStatus::instance().set_platform_service_status(PLATFORM_SERVICE_NOT_AVAILABLE); return AESM_PSDA_NOT_AVAILABLE; } //Logic here is that ME FW mode is used(Emulator is not running) //provisioning is attempted using iclsclient and the return code is not verified //In case of emulator the emulator provisioning tool is used to provision for epid 1.1 and if not long term pairing will return not provisioned error. // Always call upse_iclsInit because TCB recovery may occur // Ignore the return value because the ME may still be working uint32_t status_provision = upse_iclsInit(); if (status_provision != 0) { // Provisioning failed , maybe caused by missing of iCls client, etc. AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_START]); // This is logged as a WARNING here, since the system may not require PS capability AESM_LOG_WARN_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_FAIL_DAL]); } pse_pr_interface_psda* pPSDA = new(std::nothrow) pse_pr_interface_psda(); if (pPSDA == NULL) { return AE_OUT_OF_MEMORY_ERROR; } // Will fail if CSME is not provisioned ae_error_t ret = pPSDA->get_csme_gid(&PSDAService::instance().csme_gid); delete pPSDA; pPSDA = NULL; if (ret != AE_SUCCESS) { // Failed to get CSME GID AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_START]); // This is logged as a WARNING here, since the system may not require PS capability AESM_LOG_WARN_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_FAIL_DAL]); return ret; } // Set state to PROVISIONED m_status = PSE_STATUS_CSE_PROVISIONED; // Get platform service capbility PROFILE_START("get_ps_cap"); ret = get_ps_cap(&m_ps_cap); PROFILE_END("get_ps_cap"); if (ret != AE_SUCCESS){ AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_START]); // This is logged as a WARNING here, since the system may not require PS capability AESM_LOG_WARN_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_FAIL_DAL]); AESM_DBG_ERROR("get_ps_cap failed:%d",ret); return ret; } // Try to establish ephemeral session PROFILE_START("create_ephemeral_session_pse_cse"); ret = create_ephemeral_session_pse_cse(false, false); PROFILE_END("create_ephemeral_session_pse_cse"); if(ret != AE_SUCCESS) { AESM_DBG_ERROR("creatfe_ephemeral_session_pse_cse failed:%d", ret); if (ret == PSE_OP_LTPB_SEALING_OUT_OF_DATE) { AESM_DBG_ERROR("TCB update casued ephemeral session failure, reseal LTP blob now"); // Try to reseal LTP blob bool is_new_pairing = false; ae_error_t ltpStatus = CPSEPRClass::instance().long_term_pairing(&is_new_pairing); if (ltpStatus == AE_SUCCESS) { AESM_DBG_INFO("Reseal LTP blob succeeded. Try ephermeal session again."); ret = create_ephemeral_session_pse_cse(is_new_pairing, false); if (ret != AE_SUCCESS){ AESM_DBG_ERROR("creatfe_ephemeral_session_pse_cse after ltp blob resealing failed:%d", ret); } } } } else { // If this succeeds we should log PS Init start/success, simply because it won't be repeated and // logged later. We don't log the error flows here, because we don't consider this the "real" // PS Init. That will happen the first time create_session(), etc is invoked. AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_START]); AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_PS_INIT_SUCCESS]); } return ret; } void CPSEClass::before_enclave_load() { // always unload pse_pr enclave before loading pse_op enclave CPSEPRClass::instance().unload_enclave(); } ae_error_t CPSEClass::create_session( uint32_t* session_id, uint8_t* se_dh_msg1, uint32_t se_dh_msg1_size ) { sgx_status_t status = SGX_SUCCESS; ae_error_t ret = AE_SUCCESS; ae_error_t ret2 = AE_SUCCESS; // check enclave ID if(!m_enclave_id) return AE_FAILURE; if(sizeof(pse_dh_msg1_t) != se_dh_msg1_size) return PSE_OP_PARAMETER_ERROR; uint64_t milliseconds = static_cast(static_cast(se_get_tick_count()) * 1000.0 / static_cast(m_freq) + 0.5); status = create_session_wrapper(m_enclave_id,&ret,milliseconds,session_id,(pse_dh_msg1_t*)se_dh_msg1); if (status == SGX_ERROR_ENCLAVE_LOST) { // unload pse-op enclave unload_enclave(); // Return PSE_OP_EPHEMERAL_SESSION_INVALID to trigger ephemeral session re-establishment return PSE_OP_EPHEMERAL_SESSION_INVALID; } if(AE_SUCCESS != (ret2=sgx_error_to_ae_error(status))) return ret2; return ret; } //if ok return 0 ae_error_t CPSEClass::exchange_report( uint32_t session_id, uint8_t* se_dh_msg2, uint32_t se_dh_msg2_size, uint8_t* se_dh_msg3, uint32_t se_dh_msg3_size ) { sgx_status_t status = SGX_SUCCESS; ae_error_t ret = AE_SUCCESS; ae_error_t ret2 = AE_SUCCESS; if(!m_enclave_id) return AE_FAILURE; if(sizeof(sgx_dh_msg2_t) != se_dh_msg2_size) return PSE_OP_PARAMETER_ERROR; if(sizeof(pse_dh_msg3_t) != se_dh_msg3_size) return PSE_OP_PARAMETER_ERROR; uint64_t sys_tick = se_get_tick_count(); uint64_t milliseconds = static_cast(static_cast(sys_tick) * 1000.0 / static_cast(m_freq) + 0.5); //ECall status = exchange_report_wrapper(m_enclave_id, &ret, milliseconds, session_id, (sgx_dh_msg2_t*)se_dh_msg2, (pse_dh_msg3_t*)se_dh_msg3); if (status == SGX_ERROR_ENCLAVE_LOST) { // unload pse-op enclave unload_enclave(); // Return PSE_OP_EPHEMERAL_SESSION_INVALID to trigger ephemeral session re-establishment return PSE_OP_EPHEMERAL_SESSION_INVALID; } if(AE_SUCCESS != (ret2 = sgx_error_to_ae_error(status))) return ret2; return ret; } //if ok return 0 ae_error_t CPSEClass::close_session(uint32_t session_id) { sgx_status_t status = SGX_SUCCESS; ae_error_t ret = AE_SUCCESS; ae_error_t ret2 = AE_SUCCESS; if(!m_enclave_id) return AE_FAILURE; // ECall status = close_session_wrapper(m_enclave_id,&ret,session_id); if (status == SGX_ERROR_ENCLAVE_LOST) { // unload pse-op enclave unload_enclave(); // Return PSE_OP_EPHEMERAL_SESSION_INVALID to trigger ephemeral session re-establishment return PSE_OP_EPHEMERAL_SESSION_INVALID; } if(AE_SUCCESS != (ret2=sgx_error_to_ae_error(status))) return ret2; return ret; } //if ok return 0 ae_error_t CPSEClass::invoke_service( uint8_t* pse_message_req, size_t pse_message_req_size, uint8_t* pse_message_resp, size_t pse_message_resp_size) { sgx_status_t status = SGX_SUCCESS; ae_error_t ret = AE_SUCCESS; ae_error_t ret2= AE_SUCCESS; if(!m_enclave_id) return AE_FAILURE; uint64_t sys_tick = se_get_tick_count(); uint64_t milliseconds = static_cast(static_cast(sys_tick) * 1000.0 / static_cast(m_freq) + 0.5); // ECall PROFILE_START("invoke_service_wrapper"); status = invoke_service_wrapper(m_enclave_id, &ret, milliseconds, pse_message_req, (uint32_t)pse_message_req_size, pse_message_resp, (uint32_t)pse_message_resp_size); if (status == SGX_ERROR_ENCLAVE_LOST) { // unload pse-op enclave unload_enclave(); // Return PSE_OP_EPHEMERAL_SESSION_INVALID to trigger ephemeral session re-establishment return PSE_OP_EPHEMERAL_SESSION_INVALID; } PROFILE_END("invoke_service_wrapper"); if(AE_SUCCESS != (ret2=sgx_error_to_ae_error(status))) return ret2; return ret; } ae_error_t CPSEClass::get_ps_cap(uint64_t* ps_cap) { if (ps_cap == NULL) { AESM_DBG_ERROR("input ps_cap is NULL"); return AE_FAILURE; } if (m_ps_cap != PS_CAP_NOT_AVAILABLE) { AESM_DBG_TRACE("ps_cap is available:%llu", m_ps_cap); *ps_cap = m_ps_cap; return AE_SUCCESS; } psda_info_query_msg_t psda_cap_query_msg; psda_cap_query_msg.msg_hdr.msg_type = _htonl(PSDA_MSG_TYPE_CAP_QUERY); psda_cap_query_msg.msg_hdr.msg_len = 0; psda_cap_result_msg_t psda_cap_result_msg; memset(&psda_cap_result_msg, 0, sizeof(psda_cap_result_msg_t)); JVM_COMM_BUFFER commBuf; commBuf.TxBuf->buffer = &psda_cap_query_msg; commBuf.TxBuf->length = sizeof(psda_info_query_msg_t); commBuf.RxBuf->buffer = &psda_cap_result_msg; commBuf.RxBuf->length = sizeof(psda_cap_result_msg_t); int response_code; ae_error_t ret; ret = PSDAService::instance().send_and_recv( PSDA_COMMAND_INFO, &commBuf, &response_code, AUTO_RETRY_ON_SESSION_LOSS); if (ret != AE_SUCCESS) { AESM_DBG_ERROR("JHI_SendAndRecv2 returned (ae%d)",ret); AESM_LOG_ERROR_UNICODE("%s", g_event_string_table[SGX_EVENT_DAL_COMM_FAILURE]); return ret; } if (response_code != PSDA_SUCCESS) { AESM_DBG_ERROR("JHI_SendAndRecv2 response_code is %d", response_code); return AE_FAILURE; } if (_ntohl(psda_cap_result_msg.msg_hdr.msg_type) != PSDA_MSG_TYPE_CAP_RESULT || _ntohl(psda_cap_result_msg.msg_hdr.msg_len) != PSDA_CAP_RESULT_MSG_LEN) { AESM_DBG_ERROR("msg_type %d, msg_len %d while expected value type %d, len %d", _ntohl(psda_cap_result_msg.msg_hdr.msg_type), _ntohl(psda_cap_result_msg.msg_hdr.msg_len), PSDA_MSG_TYPE_CAP_RESULT, PSDA_CAP_RESULT_MSG_LEN); return AE_FAILURE; } if (_ntohl(psda_cap_result_msg.cap_descriptor_version) != 1) { return AE_FAILURE; } m_ps_cap = 0; uint32_t psda_cap0 = _ntohl(psda_cap_result_msg.cap_descriptor0); if (psda_cap0 & PSDA_CAP_PRTC) m_ps_cap |= PS_CAP_TRUSTED_TIME; // Trusted time service if (psda_cap0 & PSDA_CAP_RPDATA) // RPDATA capbility is available m_ps_cap |= PS_CAP_MONOTONIC_COUNTER; // Monotonic counter service *ps_cap = m_ps_cap; return AE_SUCCESS; } /** * @brief Establish an ephemeral session between PSE and CSE if not established yet. * * @param is_new_pairing * @param redo * * @return SGX_SUCCESS for success. Other values indicate an error. */ ae_error_t CPSEClass::create_ephemeral_session_pse_cse(bool is_new_pairing, bool redo) { ae_error_t ret = AE_FAILURE; pse_cse_msg2_t msg2; pse_cse_msg3_t msg3; pse_cse_msg4_t msg4; uint32_t blob_size; uint8_t* p_sealed_buffer = NULL; sgx_status_t status = SGX_SUCCESS; sgx_status_t stat_initdb = SGX_SUCCESS; int retry = 0; if (m_status == PSE_STATUS_INIT || m_status == PSE_STATUS_UNAVAILABLE) { // CSE provisioning failed during initialization. PlatformServiceStatus::instance().set_platform_service_status(PLATFORM_SERVICE_NOT_AVAILABLE); return AE_FAILURE; } if (!redo) { if (m_status == PSE_STATUS_SERVICE_READY) { PlatformServiceStatus::instance().set_platform_service_status(PLATFORM_SERVICE_READY); return AE_SUCCESS; } } else { // invalidate current session m_status = PSE_STATUS_CSE_PROVISIONED; } // Set to NOT_READY at the beginning. PlatformServiceStatus::instance().set_platform_service_status(PLATFORM_SERVICE_NOT_READY); do { AESM_DBG_INFO("PSDA started"); // Check LT pairing blob first blob_size = sizeof(pairing_blob_t); p_sealed_buffer = (uint8_t*)malloc(blob_size); if (p_sealed_buffer == NULL) { return AE_FAILURE; } PROFILE_START("aesm_read_data"); // read sealed blob from persistent storage ret = aesm_read_data(FT_PERSISTENT_STORAGE, PSE_PR_LT_PAIRING_FID, p_sealed_buffer, &blob_size); PROFILE_END("aesm_read_data"); if (ret != AE_SUCCESS||blob_size!=sizeof(pairing_blob_t)) { // Failed to load LT sealed blob ret = PSE_PAIRING_BLOB_INVALID_ERROR; // unload pse_op enclave unload_enclave(); // load pse_pr enclave CPSEPRClass::instance().load_enclave(); break; } AESM_DBG_INFO("LT Paring Blob read"); // load pse-op enclave if it's not loaded yet if ((ret = load_enclave()) != AE_SUCCESS) break; do { // create PSDA session if not available if (!PSDAService::instance().start_service()) { PlatformServiceStatus::instance().set_platform_service_status(PLATFORM_SERVICE_NOT_AVAILABLE); ret = AE_FAILURE; break; } if(status == SGX_ERROR_ENCLAVE_LOST) { unload_enclave(); // Reload an AE will not fail because of out of EPC, so AESM_AE_OUT_OF_EPC is not checked here if(AE_SUCCESS != load_enclave()) { ret = AE_FAILURE; break; } } AESM_DBG_INFO("PSDA Start Ephemral Session"); // PSE --- M1:StartSession ---> CSE memset(&msg2, 0, sizeof(msg2)); PROFILE_START("psda_start_ephemeral_session"); ret = psda_start_ephemeral_session(((pairing_blob_t*)p_sealed_buffer)->plaintext.pse_instance_id, &msg2); PROFILE_END("psda_start_ephemeral_session"); if (ret != AE_SUCCESS) break; AESM_DBG_INFO("Ephemral Session M2/M3"); // PSE <--- M2 --- CSE memset(&msg3, 0, sizeof(msg3)); PROFILE_START("ephemeral_session_m2m3_wrapper"); status = ephemeral_session_m2m3_wrapper(m_enclave_id, &ret, (pairing_blob_t*)p_sealed_buffer, &msg2, &msg3); PROFILE_END("ephemeral_session_m2m3_wrapper"); CHECK_ECALL_RET(status, ret) AESM_DBG_INFO("PSDA Finalize Session"); // PSE --- M3 ---> CSE memset(&msg4, 0, sizeof(msg4)); PROFILE_START("psda_finalize_session"); ret = psda_finalize_session(((pairing_blob_t*)p_sealed_buffer)->plaintext.pse_instance_id, &msg3, &msg4); PROFILE_END("psda_finalize_session"); if (ret == AESM_PSDA_SESSION_LOST) { retry++; continue; } BREAK_IF_FAILED(ret); AESM_DBG_INFO("Ephemeral Session M4"); // PSE <--- M4 --- CSE PROFILE_START("ephemeral_session_m4_wrapper"); status = ephemeral_session_m4_wrapper(m_enclave_id, &ret, &msg4); PROFILE_END("ephemeral_session_m4_wrapper"); CHECK_ECALL_RET(status, ret) /* the return value of initialize_sqlite_database_file_wrapper is ignored unless it's SGX_ERROR_ENCLAVE_LOST */ AESM_DBG_INFO("initialize vmc database"); PROFILE_START("initialize_sqlite_database_file_wrapper"); ae_error_t ret2; stat_initdb = initialize_sqlite_database_file_wrapper(m_enclave_id, &ret2, is_new_pairing); PROFILE_END("initialize_sqlite_database_file_wrapper"); if (stat_initdb == SGX_ERROR_ENCLAVE_LOST) { retry++; continue; } else break; }while(retry < AESM_RETRY_COUNT); if (status == SGX_ERROR_ENCLAVE_LOST) { AESM_DBG_INFO("Enclave Lost"); // maximum retry times reached ret = AE_FAILURE; break; } else if(ret == AE_SUCCESS) { // Set status to READY m_status = PSE_STATUS_SERVICE_READY; // Successfully build the ephemeral session PlatformServiceStatus::instance().set_platform_service_status(PLATFORM_SERVICE_READY); } } while(0); free(p_sealed_buffer); return ret; } ae_error_t CPSEClass::psda_start_ephemeral_session(const uint8_t* pse_instance_id, pse_cse_msg2_t* cse_msg2) { assert(cse_msg2 != NULL); AESM_DBG_INFO("Enter psda_start_ephemeral_session ..."); eph_session_m1_t eph_session_m1; memcpy_s(eph_session_m1.msg_hdr.pse_instance_id, SW_INSTANCE_ID_SIZE, pse_instance_id, SW_INSTANCE_ID_SIZE); eph_session_m1.msg_hdr.msg_type = _htonl(PSDA_MSG_TYPE_EP_M1); eph_session_m1.msg_hdr.msg_len = 0; eph_session_m2_t eph_session_m2; memset(&eph_session_m2, 0, sizeof(eph_session_m2)); JVM_COMM_BUFFER commBuf; commBuf.TxBuf->buffer = &eph_session_m1; commBuf.TxBuf->length = sizeof(eph_session_m1_t); commBuf.RxBuf->buffer = &eph_session_m2; commBuf.RxBuf->length = sizeof(eph_session_m2_t); int response_code; ae_error_t ret; ret = PSDAService::instance().send_and_recv( PSDA_COMMAND_EP, &commBuf, &response_code, AUTO_RETRY_ON_SESSION_LOSS); if (ret != AE_SUCCESS ) { AESM_LOG_ERROR_UNICODE("%s", g_event_string_table[SGX_EVENT_DAL_COMM_FAILURE]); return ret; } if (response_code == PSDA_LT_PAIRING_NOT_EXIST || response_code == PSDA_INTEGRITY_ERROR) { return AESM_PSDA_NEED_REPAIRING; } else if (response_code != PSDA_SUCCESS || _ntohl(eph_session_m2.msg_hdr.msg_type) != PSDA_MSG_TYPE_EP_M2 || _ntohl(eph_session_m2.msg_hdr.msg_len) != sizeof(pse_cse_msg2_t)) { AESM_DBG_ERROR("JHI_SendAndRecv2 response_code is %d", response_code); return AE_FAILURE; } memcpy_s(cse_msg2, sizeof(pse_cse_msg2_t), &eph_session_m2.msg2, sizeof(pse_cse_msg2_t)); return AE_SUCCESS; } ae_error_t CPSEClass::psda_finalize_session(const uint8_t* pse_instance_id, const pse_cse_msg3_t* cse_msg3, pse_cse_msg4_t* cse_msg4) { assert(cse_msg3 != NULL && cse_msg4 != NULL); AESM_DBG_INFO("Enter psda_finalize_session ..."); eph_session_m3_t eph_session_m3; memcpy_s(eph_session_m3.msg_hdr.pse_instance_id, SW_INSTANCE_ID_SIZE, pse_instance_id, SW_INSTANCE_ID_SIZE); eph_session_m3.msg_hdr.msg_type = _htonl(PSDA_MSG_TYPE_EP_M3); eph_session_m3.msg_hdr.msg_len = _htonl(sizeof(pse_cse_msg3_t)); memcpy_s(&eph_session_m3.msg3, sizeof(eph_session_m3.msg3), cse_msg3, sizeof(pse_cse_msg3_t)); eph_session_m4_t eph_session_m4; memset(&eph_session_m4, 0, sizeof(eph_session_m4)); JVM_COMM_BUFFER commBuf; commBuf.TxBuf->buffer = &eph_session_m3; commBuf.TxBuf->length = sizeof(eph_session_m3_t); commBuf.RxBuf->buffer = &eph_session_m4; commBuf.RxBuf->length = sizeof(eph_session_m4_t); int response_code; ae_error_t ret; ret = PSDAService::instance().send_and_recv( PSDA_COMMAND_EP, &commBuf, &response_code, NO_RETRY_ON_SESSION_LOSS); if (ret != AE_SUCCESS) { AESM_LOG_ERROR_UNICODE("%s", g_event_string_table[SGX_EVENT_DAL_COMM_FAILURE]); return ret; } if (response_code == PSDA_INTEGRITY_ERROR) { return AESM_PSDA_NEED_REPAIRING; } else if (response_code != PSDA_SUCCESS || _ntohl(eph_session_m4.msg_hdr.msg_type) != PSDA_MSG_TYPE_EP_M4 || _ntohl(eph_session_m4.msg_hdr.msg_len) != sizeof(pse_cse_msg4_t)) { AESM_DBG_ERROR("JHI_SendAndRecv2 response_code is %d", response_code); return AE_FAILURE; } memcpy_s(cse_msg4, sizeof(pse_cse_msg4_t), &eph_session_m4.msg4, sizeof(pse_cse_msg4_t)); return AE_SUCCESS; } ae_error_t CPSEClass::psda_invoke_service(uint8_t* psda_req_msg, uint32_t psda_req_msg_size, uint8_t* psda_resp_msg, uint32_t psda_resp_msg_size) { AESM_DBG_INFO("Enter psda_invoke_service ..."); JVM_COMM_BUFFER commBuf; commBuf.TxBuf->buffer = psda_req_msg; commBuf.TxBuf->length = psda_req_msg_size; commBuf.RxBuf->buffer = psda_resp_msg; commBuf.RxBuf->length = psda_resp_msg_size; int response_code; ae_error_t ret; PROFILE_START("JHI_SendAndRecv2"); ret = PSDAService::instance().send_and_recv( PSDA_COMMAND_SERVICE, &commBuf, &response_code, NO_RETRY_ON_SESSION_LOSS); PROFILE_END("JHI_SendAndRecv2"); if (ret != AE_SUCCESS) { AESM_LOG_ERROR_UNICODE("%s", g_event_string_table[SGX_EVENT_DAL_COMM_FAILURE]); return ret; } if (PSDA_SUCCESS != response_code) { AESM_LOG_ERROR_UNICODE("%s", g_event_string_table[SGX_EVENT_DAL_SERVICE_ERROR]); } AESM_DBG_INFO("JHI_SendAndRecv2 response_code is %d", response_code); switch (response_code) { case PSDA_SUCCESS: // SGX Platform Service Message form PSE processed successfully return AE_SUCCESS; case PSDA_INTERNAL_ERROR: // Internal error, possibly due to unexpected error of the system return AESM_PSDA_INTERNAL_ERROR; case PSDA_INVALID_SESSION_STATE: // SGX Platform Service ephemeral session state is invalid case PSDA_SEQNO_CHECK_FAIL: // SGX Platform Service secure channel message sequence number check failure case PSDA_INTEGRITY_ERROR: // SGX Platform Service message crypto verification failure case PSDA_LT_PAIRING_NOT_EXIST: // SGX Platform Service long term pairing session doesn't exist return AESM_PSDA_NEED_REPAIRING; case PSDA_INVALID_COMMAND: // SGX Platform Service PS_COMMAND_ID provided by the transport layer is not recognized case PSDA_BAD_PARAMETER: // SGX Platform Service Message format error detected default: return AE_FAILURE; } }