123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- /*
- * 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.
- *
- */
- /**
- * File: pse_op.cpp
- * Description: Definition for interfaces provided by platform service enclave..
- *
- * Definition for interfaces provided by platform service enclave.
- */
- #include "utility.h"
- #include "session_mgr.h"
- #include "monotonic_counter.h"
- #include "trusted_time.h"
- #include "pse_op_t.c"
- #include "dh.h"
- #include "pairing_blob.h"
- #include "monotonic_counter_database_sqlite_bin_hash_tree_utility.h"
- #include "sgx_lfence.h"
- #define BREAK_ON_MALLOC_FAIL(ptr,ret_val) if (!(ptr)) {ret_val=PSE_OP_INTERNAL_ERROR;break;}
- typedef pse_op_error_t (*srv_pfn_t)(const isv_attributes_t &, const uint8_t*, uint8_t *);
- static const struct service_handler_t
- {
- uint16_t service_id;
- uint16_t service_cmd;
- uint16_t req_size;
- uint16_t resp_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},
- {PSE_MC_SERVICE, PSE_MC_READ, sizeof(pse_mc_read_req_t), sizeof(pse_mc_read_resp_t), pse_mc_read },
- {PSE_MC_SERVICE, PSE_MC_INC, sizeof(pse_mc_inc_req_t), sizeof(pse_mc_inc_resp_t), pse_mc_inc },
- {PSE_MC_SERVICE, PSE_MC_DEL, sizeof(pse_mc_del_req_t), sizeof(pse_mc_del_resp_t), pse_mc_del },
- {PSE_TRUSTED_TIME_SERVICE, PSE_TIMER_READ, sizeof(pse_timer_read_req_t), sizeof(pse_timer_read_resp_t), pse_read_timer},
- };
- /*******************************************************************
- ** Function name: create_session_wrapper
- ** Descrption:
- ** This function will initialize the AppEnclave<->Pse-Op session establishment process.
- ** Parameters:
- ** tick - the number of milliseconds that have elapsed since the system was started,
- ** used to detect which session is idle for the longest time.
- ** sid - session id
- ** Returns: ae_error_t
- *******************************************************************/
- ae_error_t create_session_wrapper(
- /* IN */ uint64_t tick,
- /* OUT */ uint32_t* sid,
- /* OUT */ pse_dh_msg1_t* dh_msg1)
- {
- pse_op_error_t op_ret = OP_SUCCESS;
- if (!sid || !dh_msg1)
- {
- return PSE_OP_PARAMETER_ERROR;
- }
- // ephemeral session must have been established
- if(!is_eph_session_active())
- {
- // the ephemeral session is not active
- return PSE_OP_EPHEMERAL_SESSION_INVALID;
- }
- op_ret = pse_create_session(tick, *sid, *dh_msg1);
- return error_reinterpret(op_ret);
- }
- /*******************************************************************
- ** Function name: exchange_report_wrapper
- ** Descrption:
- ** This function is used to exchange report between AppEnclave and Pse-Op, if success,
- ** a session will be established.
- ** Parameters:
- ** tick - the number of milliseconds that have elapsed since the system was started,
- ** used to detect which session is idle for the longest time.
- ** sid - session id
- ** dh_msg2 - DH message2
- ** dh_msg3 - DH message3
- ** Returns: ae_error_t
- *******************************************************************/
- ae_error_t exchange_report_wrapper(
- /* IN */ uint64_t tick,
- /* IN */ uint32_t sid,
- /* IN */ sgx_dh_msg2_t* dh_msg2,
- /* OUT */ pse_dh_msg3_t* dh_msg3)
- {
- pse_op_error_t op_ret = OP_SUCCESS;
- if(!dh_msg2 || !dh_msg3)
- {
- return PSE_OP_PARAMETER_ERROR;
- }
- // ephemeral session must have been established
- if(!is_eph_session_active()) // the ephemeral session is not active
- {
- return PSE_OP_EPHEMERAL_SESSION_INVALID;
- }
- op_ret = pse_exchange_report(tick, sid, *dh_msg2, *dh_msg3);
- return error_reinterpret(op_ret);
- }
- /*******************************************************************
- ** Function name: close_session_wrapper
- ** Descrption:
- ** This function is used to close a session
- ** Parameters:
- ** sid - session id
- ** Returns: ae_error_t
- *******************************************************************/
- ae_error_t close_session_wrapper(
- /* IN */ uint32_t sid
- )
- {
- return error_reinterpret(pse_close_session(sid));
- }
- /*******************************************************************
- ** Function name: invoke_service_wrapper
- ** Descrption:
- ** This function is used to invoke a service call
- ** Parameters:
- ** tick - the number of milliseconds that have elapsed since the system was started,
- ** used to detect which session is idle for the longest time.
- ** req_msg - service request message
- ** req_msg_size - size of request message
- ** resp_msg - service response message
- ** resp_msg_size - size of response message
- ** Returns: ae_error_t
- *******************************************************************/
- ae_error_t invoke_service_wrapper (
- /* IN */ uint64_t tick,
- /* IN */ uint8_t* req_msg,
- /* IN */ uint32_t req_msg_size,
- /* OUT */ uint8_t* resp_msg,
- /* IN */ uint32_t resp_msg_size)
- {
- // check parameter
- ae_error_t ae_ret = AE_SUCCESS;
- pse_message_t* pse_req_msg = (pse_message_t*)req_msg;
- pse_message_t* pse_resp_msg = (pse_message_t*)resp_msg;
- pse_op_error_t op_ret;
- if (!req_msg || !resp_msg)
- {
- return PSE_OP_PARAMETER_ERROR;
- }
- //
- // make sure the header is inside enclave
- //
- if (req_msg_size < sizeof(pse_message_t))
- {
- return PSE_OP_PARAMETER_ERROR;
- }
- //
- // if this mispredicts, we might overflow below
- //
- sgx_lfence();
- if (pse_req_msg->payload_size > UINT32_MAX - sizeof(pse_message_t) // check potential overflow
- || req_msg_size != sizeof(pse_message_t) + pse_req_msg->payload_size)
- {
- return PSE_OP_PARAMETER_ERROR;
- }
- if (resp_msg_size < sizeof(pse_message_t) // make sure the header is inside enclave
- || pse_req_msg->exp_resp_size > UINT32_MAX - sizeof(pse_message_t) // check potential overflow
- || resp_msg_size < sizeof(pse_message_t) + pse_req_msg->exp_resp_size)
- {
- return PSE_OP_PARAMETER_ERROR;
- }
- //
- // put LFENCE here mostly for pse_req_msg->payload_size
- // check above. I don't think we use
- // pse_req_msg->exp_resp_size to calculate
- // any pointers.
- //
- sgx_lfence();
- pse_session_t* session = sid2session(pse_req_msg->session_id);
- // ephemeral session must have been established
- if(!is_eph_session_active())
- {
- // the ephemeral session is not active
- return PSE_OP_EPHEMERAL_SESSION_INVALID;
- }
-
- //if session is invalid (session not exists or established, or sequence num overflow)
- if (!is_isv_session_valid(session))
- {
- return PSE_OP_SESSION_INVALID;
- }
- // update session tick
- update_session_tick_count(session, tick);
- //clear response message
- memset(resp_msg, 0, resp_msg_size);
- uint8_t* req = (uint8_t*)malloc(pse_req_msg->payload_size);
- uint8_t* resp= NULL;
- uint32_t session_seq_num = get_session_seq_num(session);
- do
- {
- BREAK_ON_MALLOC_FAIL(req, ae_ret)
- // decrypt service request message using session key
- if(false == decrypt_msg(pse_req_msg, req, (sgx_key_128bit_t*)session->active.AEK))
- {
- ae_ret = PSE_OP_SERVICE_MSG_ERROR;
- break;
- }
- pse_req_hdr_t* req_hdr = (pse_req_hdr_t*)req;
- // check session sequence number
- if(req_hdr->seq_num != session_seq_num)
- {
- ae_ret = PSE_OP_SESSION_INVALID;
- //close session
- free_session(session);
- break;
- }
- // Dispatch the service request to the proper handler
- int i;
- int service_count = static_cast<int>(sizeof(service_handler) / sizeof(service_handler_t));
- for (i = 0; i < service_count; i++)
- {
- //
- // might mispredict the end of the loop
- //
- sgx_lfence();
- if (req_hdr->service_id == service_handler[i].service_id &&
- req_hdr->service_cmd == service_handler[i].service_cmd)
- {
- if (pse_req_msg->payload_size != service_handler[i].req_size ||
- pse_req_msg->exp_resp_size < service_handler[i].resp_size) // response message buffer must be large enough to hold response data
- {
- ae_ret = PSE_OP_SERVICE_MSG_ERROR;
- goto clean_up;
- }
- resp = (uint8_t*)malloc(service_handler[i].resp_size);
- if (resp == NULL)
- {
- ae_ret = PSE_OP_INTERNAL_ERROR;
- goto clean_up;
- }
- //
- // in case payload_size, req_size comparisons
- // mispredict
- //
- sgx_lfence();
- // serve the request
- op_ret = service_handler[i].srv_pfn(session->isv_attributes, req, resp);
- if(op_ret != OP_SUCCESS)
- {
- ae_ret = error_reinterpret(op_ret);
- goto clean_up;
- }
- // set payload size for valid requests
- pse_resp_msg->payload_size = service_handler[i].resp_size;
-
- break;
- }
- }
- if (i == service_count)
- {
- // service_id or service_cmd mismatch
- resp = (uint8_t*)malloc(sizeof(pse_resp_hdr_t));
- BREAK_ON_MALLOC_FAIL(resp, ae_ret)
- // for unknown requests, payload data only includes response header
- pse_resp_msg->payload_size = sizeof(pse_resp_hdr_t);
- // set error status
- ((pse_resp_hdr_t*)resp)->status = PSE_ERROR_UNKNOWN_REQ;
- }
- // prepare the response message
- pse_resp_hdr_t* resp_hdr = (pse_resp_hdr_t*)resp;
- pse_resp_msg->exp_resp_size = 0;
- pse_resp_msg->session_id = pse_req_msg->session_id;
- //set response header, status code is already set in service functions
- resp_hdr->seq_num = session_seq_num + 1; // addition overflow already checked in is_isv_session_valid()
- resp_hdr->service_id = req_hdr->service_id;
- resp_hdr->service_cmd = req_hdr->service_cmd;
- // update sequence number for current session
- set_session_seq_num(session, resp_hdr->seq_num + 1);
- // encrypt the response message
- if(false == encrypt_msg((pse_message_t*)pse_resp_msg,
- (uint8_t*)resp,
- (sgx_key_128bit_t*)session->active.AEK))
- {
- ae_ret = PSE_OP_INTERNAL_ERROR;
- break;
- }
- } while (0);
- clean_up:
- SAFE_FREE(req);
- SAFE_FREE(resp);
- return ae_ret;
- }
- /*******************************************************************
- ** Function name: initialize_sqlite_database_file_wrapper
- ** Descrption:
- ** Initialize the vmc database
- ** Parameters:
- ** is_for_empty_db_creation - if true, always create a new database
- ** Returns: ae_error_t
- *******************************************************************/
- ae_error_t initialize_sqlite_database_file_wrapper(bool is_for_empty_db_creation)
- {
- // ephemeral session must have been established.
- if(!is_eph_session_active())
- {
- return PSE_OP_EPHEMERAL_SESSION_INVALID;
- }
- return error_reinterpret(initialize_sqlite_database_file(is_for_empty_db_creation));
- }
- /*******************************************************************
- ** Function name: ephemeral_session_m2m3_wrapper
- ** Descrption:
- ** Exchange M2 and M3 between CSE and PSE-Op
- ** Parameters:
- ** sealed_blob - Long term pairing blob
- ** pse_cse_msg2 - Message2 from CSE
- ** pse_cse_msg3 - Message3 generated by PSE-Op
- ** Returns: ae_error_t
- *******************************************************************/
- ae_error_t ephemeral_session_m2m3_wrapper(
- /* IN */ pairing_blob_t* sealed_blob,
- /* IN */ pse_cse_msg2_t* pse_cse_msg2,
- /* OUT */ pse_cse_msg3_t* pse_cse_msg3)
- {
- pse_op_error_t op_ret = OP_SUCCESS;
- // check parameters
- if (!sealed_blob || !pse_cse_msg2 || !pse_cse_msg3)
- {
- return PSE_OP_PARAMETER_ERROR;
- }
- op_ret = ephemeral_session_m2m3(sealed_blob, *pse_cse_msg2, *pse_cse_msg3);
- return error_reinterpret(op_ret);
- }
- /*******************************************************************
- ** Function name: ephemeral_session_m4_wrapper
- ** Descrption:
- ** Handle Msg4 from CSE, if successful, an ephemeral session will be established
- ** Parameters:
- ** pse_cse_msg4 - Message4 from CSE
- ** Returns: ae_error_t
- *******************************************************************/
- ae_error_t ephemeral_session_m4_wrapper(
- /* IN */ pse_cse_msg4_t* pse_cse_msg4)
- {
- pse_op_error_t op_ret = OP_SUCCESS;
- if (!pse_cse_msg4)
- {
- return PSE_OP_PARAMETER_ERROR;
- }
- op_ret = ephemeral_session_m4(*pse_cse_msg4);
- return error_reinterpret(op_ret);
- }
|