pse_op.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. /**
  32. * File: pse_op.cpp
  33. * Description: Definition for interfaces provided by platform service enclave..
  34. *
  35. * Definition for interfaces provided by platform service enclave.
  36. */
  37. #include "utility.h"
  38. #include "session_mgr.h"
  39. #include "monotonic_counter.h"
  40. #include "trusted_time.h"
  41. #include "pse_op_t.c"
  42. #include "dh.h"
  43. #include "pairing_blob.h"
  44. #include "monotonic_counter_database_sqlite_bin_hash_tree_utility.h"
  45. #define BREAK_ON_MALLOC_FAIL(ptr,ret_val) if (!(ptr)) {ret_val=PSE_OP_INTERNAL_ERROR;break;}
  46. typedef pse_op_error_t (*srv_pfn_t)(const isv_attributes_t &, const uint8_t*, uint8_t *);
  47. static const struct service_handler_t
  48. {
  49. uint16_t service_id;
  50. uint16_t service_cmd;
  51. uint16_t req_size;
  52. uint16_t resp_size;
  53. srv_pfn_t srv_pfn;
  54. } service_handler[] = {
  55. {PSE_MC_SERVICE, PSE_MC_CREATE, sizeof(pse_mc_create_req_t), sizeof(pse_mc_create_resp_t), pse_mc_create},
  56. {PSE_MC_SERVICE, PSE_MC_READ, sizeof(pse_mc_read_req_t), sizeof(pse_mc_read_resp_t), pse_mc_read },
  57. {PSE_MC_SERVICE, PSE_MC_INC, sizeof(pse_mc_inc_req_t), sizeof(pse_mc_inc_resp_t), pse_mc_inc },
  58. {PSE_MC_SERVICE, PSE_MC_DEL, sizeof(pse_mc_del_req_t), sizeof(pse_mc_del_resp_t), pse_mc_del },
  59. {PSE_TRUSTED_TIME_SERVICE, PSE_TIMER_READ, sizeof(pse_timer_read_req_t), sizeof(pse_timer_read_resp_t), pse_read_timer},
  60. };
  61. /*******************************************************************
  62. ** Function name: create_session_wrapper
  63. ** Descrption:
  64. ** This function will initialize the AppEnclave<->Pse-Op session establishment process.
  65. ** Parameters:
  66. ** tick - the number of milliseconds that have elapsed since the system was started,
  67. ** used to detect which session is idle for the longest time.
  68. ** sid - session id
  69. ** Returns: ae_error_t
  70. *******************************************************************/
  71. ae_error_t create_session_wrapper(
  72. /* IN */ uint64_t tick,
  73. /* OUT */ uint32_t* sid,
  74. /* OUT */ pse_dh_msg1_t* dh_msg1)
  75. {
  76. pse_op_error_t op_ret = OP_SUCCESS;
  77. if (!sid || !dh_msg1)
  78. {
  79. return PSE_OP_PARAMETER_ERROR;
  80. }
  81. // ephemeral session must have been established
  82. if(!is_eph_session_active())
  83. {
  84. // the ephemeral session is not active
  85. return PSE_OP_EPHEMERAL_SESSION_INVALID;
  86. }
  87. op_ret = pse_create_session(tick, *sid, *dh_msg1);
  88. return error_reinterpret(op_ret);
  89. }
  90. /*******************************************************************
  91. ** Function name: exchange_report_wrapper
  92. ** Descrption:
  93. ** This function is used to exchange report between AppEnclave and Pse-Op, if success,
  94. ** a session will be established.
  95. ** Parameters:
  96. ** tick - the number of milliseconds that have elapsed since the system was started,
  97. ** used to detect which session is idle for the longest time.
  98. ** sid - session id
  99. ** dh_msg2 - DH message2
  100. ** dh_msg3 - DH message3
  101. ** Returns: ae_error_t
  102. *******************************************************************/
  103. ae_error_t exchange_report_wrapper(
  104. /* IN */ uint64_t tick,
  105. /* IN */ uint32_t sid,
  106. /* IN */ sgx_dh_msg2_t* dh_msg2,
  107. /* OUT */ pse_dh_msg3_t* dh_msg3)
  108. {
  109. pse_op_error_t op_ret = OP_SUCCESS;
  110. if(!dh_msg2 || !dh_msg3)
  111. {
  112. return PSE_OP_PARAMETER_ERROR;
  113. }
  114. // ephemeral session must have been established
  115. if(!is_eph_session_active()) // the ephemeral session is not active
  116. {
  117. return PSE_OP_EPHEMERAL_SESSION_INVALID;
  118. }
  119. op_ret = pse_exchange_report(tick, sid, *dh_msg2, *dh_msg3);
  120. return error_reinterpret(op_ret);
  121. }
  122. /*******************************************************************
  123. ** Function name: close_session_wrapper
  124. ** Descrption:
  125. ** This function is used to close a session
  126. ** Parameters:
  127. ** sid - session id
  128. ** Returns: ae_error_t
  129. *******************************************************************/
  130. ae_error_t close_session_wrapper(
  131. /* IN */ uint32_t sid
  132. )
  133. {
  134. return error_reinterpret(pse_close_session(sid));
  135. }
  136. /*******************************************************************
  137. ** Function name: invoke_service_wrapper
  138. ** Descrption:
  139. ** This function is used to invoke a service call
  140. ** Parameters:
  141. ** tick - the number of milliseconds that have elapsed since the system was started,
  142. ** used to detect which session is idle for the longest time.
  143. ** req_msg - service request message
  144. ** req_msg_size - size of request message
  145. ** resp_msg - service response message
  146. ** resp_msg_size - size of response message
  147. ** Returns: ae_error_t
  148. *******************************************************************/
  149. ae_error_t invoke_service_wrapper (
  150. /* IN */ uint64_t tick,
  151. /* IN */ uint8_t* req_msg,
  152. /* IN */ uint32_t req_msg_size,
  153. /* OUT */ uint8_t* resp_msg,
  154. /* IN */ uint32_t resp_msg_size)
  155. {
  156. // check parameter
  157. ae_error_t ae_ret = AE_SUCCESS;
  158. pse_message_t* pse_req_msg = (pse_message_t*)req_msg;
  159. pse_message_t* pse_resp_msg = (pse_message_t*)resp_msg;
  160. pse_op_error_t op_ret;
  161. if (!req_msg || !resp_msg)
  162. {
  163. return PSE_OP_PARAMETER_ERROR;
  164. }
  165. if (req_msg_size < sizeof(pse_message_t) // make sure the header is inside enclave
  166. || pse_req_msg->payload_size > UINT32_MAX - sizeof(pse_message_t) // check potential overflow
  167. || req_msg_size != sizeof(pse_message_t) + pse_req_msg->payload_size)
  168. {
  169. return PSE_OP_PARAMETER_ERROR;
  170. }
  171. if (resp_msg_size < sizeof(pse_message_t) // make sure the header is inside enclave
  172. || pse_req_msg->exp_resp_size > UINT32_MAX - sizeof(pse_message_t) // check potential overflow
  173. || resp_msg_size < sizeof(pse_message_t) + pse_req_msg->exp_resp_size)
  174. {
  175. return PSE_OP_PARAMETER_ERROR;
  176. }
  177. pse_session_t* session = sid2session(pse_req_msg->session_id);
  178. // ephemeral session must have been established
  179. if(!is_eph_session_active())
  180. {
  181. // the ephemeral session is not active
  182. return PSE_OP_EPHEMERAL_SESSION_INVALID;
  183. }
  184. //if session is invalid (session not exists or established, or sequence num overflow)
  185. if (!is_isv_session_valid(session))
  186. {
  187. return PSE_OP_SESSION_INVALID;
  188. }
  189. // update session tick
  190. update_session_tick_count(session, tick);
  191. //clear response message
  192. memset(resp_msg, 0, resp_msg_size);
  193. uint8_t* req = (uint8_t*)malloc(pse_req_msg->payload_size);
  194. uint8_t* resp= NULL;
  195. uint32_t session_seq_num = get_session_seq_num(session);
  196. do
  197. {
  198. BREAK_ON_MALLOC_FAIL(req, ae_ret)
  199. // decrypt service request message using session key
  200. if(false == decrypt_msg(pse_req_msg, req, (sgx_key_128bit_t*)session->active.AEK))
  201. {
  202. ae_ret = PSE_OP_SERVICE_MSG_ERROR;
  203. break;
  204. }
  205. pse_req_hdr_t* req_hdr = (pse_req_hdr_t*)req;
  206. // check session sequence number
  207. if(req_hdr->seq_num != session_seq_num)
  208. {
  209. ae_ret = PSE_OP_SESSION_INVALID;
  210. //close session
  211. free_session(session);
  212. break;
  213. }
  214. // Dispatch the service request to the proper handler
  215. int i;
  216. int service_count = static_cast<int>(sizeof(service_handler) / sizeof(service_handler_t));
  217. for (i = 0; i < service_count; i++)
  218. {
  219. if (req_hdr->service_id == service_handler[i].service_id &&
  220. req_hdr->service_cmd == service_handler[i].service_cmd)
  221. {
  222. if (pse_req_msg->payload_size != service_handler[i].req_size ||
  223. pse_req_msg->exp_resp_size < service_handler[i].resp_size) // response message buffer must be large enough to hold response data
  224. {
  225. ae_ret = PSE_OP_SERVICE_MSG_ERROR;
  226. goto clean_up;
  227. }
  228. resp = (uint8_t*)malloc(service_handler[i].resp_size);
  229. if (resp == NULL)
  230. {
  231. ae_ret = PSE_OP_INTERNAL_ERROR;
  232. goto clean_up;
  233. }
  234. // serve the request
  235. op_ret = service_handler[i].srv_pfn(session->isv_attributes, req, resp);
  236. if(op_ret != OP_SUCCESS)
  237. {
  238. ae_ret = error_reinterpret(op_ret);
  239. goto clean_up;
  240. }
  241. // set payload size for valid requests
  242. pse_resp_msg->payload_size = service_handler[i].resp_size;
  243. break;
  244. }
  245. }
  246. if (i == service_count)
  247. {
  248. // service_id or service_cmd mismatch
  249. resp = (uint8_t*)malloc(sizeof(pse_resp_hdr_t));
  250. BREAK_ON_MALLOC_FAIL(resp, ae_ret)
  251. // for unknown requests, payload data only includes response header
  252. pse_resp_msg->payload_size = sizeof(pse_resp_hdr_t);
  253. // set error status
  254. ((pse_resp_hdr_t*)resp)->status = PSE_ERROR_UNKNOWN_REQ;
  255. }
  256. // prepare the response message
  257. pse_resp_hdr_t* resp_hdr = (pse_resp_hdr_t*)resp;
  258. pse_resp_msg->exp_resp_size = 0;
  259. pse_resp_msg->session_id = pse_req_msg->session_id;
  260. //set response header, status code is already set in service functions
  261. resp_hdr->seq_num = session_seq_num + 1; // addition overflow already checked in is_isv_session_valid()
  262. resp_hdr->service_id = req_hdr->service_id;
  263. resp_hdr->service_cmd = req_hdr->service_cmd;
  264. // update sequence number for current session
  265. set_session_seq_num(session, resp_hdr->seq_num + 1);
  266. // encrypt the response message
  267. if(false == encrypt_msg((pse_message_t*)pse_resp_msg,
  268. (uint8_t*)resp,
  269. (sgx_key_128bit_t*)session->active.AEK))
  270. {
  271. ae_ret = PSE_OP_INTERNAL_ERROR;
  272. break;
  273. }
  274. } while (0);
  275. clean_up:
  276. SAFE_FREE(req);
  277. SAFE_FREE(resp);
  278. return ae_ret;
  279. }
  280. /*******************************************************************
  281. ** Function name: initialize_sqlite_database_file_wrapper
  282. ** Descrption:
  283. ** Initialize the vmc database
  284. ** Parameters:
  285. ** is_for_empty_db_creation - if true, always create a new database
  286. ** Returns: ae_error_t
  287. *******************************************************************/
  288. ae_error_t initialize_sqlite_database_file_wrapper(bool is_for_empty_db_creation)
  289. {
  290. // ephemeral session must have been established.
  291. if(!is_eph_session_active())
  292. {
  293. return PSE_OP_EPHEMERAL_SESSION_INVALID;
  294. }
  295. return error_reinterpret(initialize_sqlite_database_file(is_for_empty_db_creation));
  296. }
  297. /*******************************************************************
  298. ** Function name: ephemeral_session_m2m3_wrapper
  299. ** Descrption:
  300. ** Exchange M2 and M3 between CSE and PSE-Op
  301. ** Parameters:
  302. ** sealed_blob - Long term pairing blob
  303. ** pse_cse_msg2 - Message2 from CSE
  304. ** pse_cse_msg3 - Message3 generated by PSE-Op
  305. ** Returns: ae_error_t
  306. *******************************************************************/
  307. ae_error_t ephemeral_session_m2m3_wrapper(
  308. /* IN */ pairing_blob_t* sealed_blob,
  309. /* IN */ pse_cse_msg2_t* pse_cse_msg2,
  310. /* OUT */ pse_cse_msg3_t* pse_cse_msg3)
  311. {
  312. pse_op_error_t op_ret = OP_SUCCESS;
  313. // check parameters
  314. if (!sealed_blob || !pse_cse_msg2 || !pse_cse_msg3)
  315. {
  316. return PSE_OP_PARAMETER_ERROR;
  317. }
  318. op_ret = ephemeral_session_m2m3(sealed_blob, *pse_cse_msg2, *pse_cse_msg3);
  319. return error_reinterpret(op_ret);
  320. }
  321. /*******************************************************************
  322. ** Function name: ephemeral_session_m4_wrapper
  323. ** Descrption:
  324. ** Handle Msg4 from CSE, if successful, an ephemeral session will be established
  325. ** Parameters:
  326. ** pse_cse_msg4 - Message4 from CSE
  327. ** Returns: ae_error_t
  328. *******************************************************************/
  329. ae_error_t ephemeral_session_m4_wrapper(
  330. /* IN */ pse_cse_msg4_t* pse_cse_msg4)
  331. {
  332. pse_op_error_t op_ret = OP_SUCCESS;
  333. if (!pse_cse_msg4)
  334. {
  335. return PSE_OP_PARAMETER_ERROR;
  336. }
  337. op_ret = ephemeral_session_m4(*pse_cse_msg4);
  338. return error_reinterpret(op_ret);
  339. }