pse_op.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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. #include "sgx_lfence.h"
  46. #define BREAK_ON_MALLOC_FAIL(ptr,ret_val) if (!(ptr)) {ret_val=PSE_OP_INTERNAL_ERROR;break;}
  47. typedef pse_op_error_t (*srv_pfn_t)(const isv_attributes_t &, const uint8_t*, uint8_t *);
  48. static const struct service_handler_t
  49. {
  50. uint16_t service_id;
  51. uint16_t service_cmd;
  52. uint16_t req_size;
  53. uint16_t resp_size;
  54. srv_pfn_t srv_pfn;
  55. } service_handler[] = {
  56. {PSE_MC_SERVICE, PSE_MC_CREATE, sizeof(pse_mc_create_req_t), sizeof(pse_mc_create_resp_t), pse_mc_create},
  57. {PSE_MC_SERVICE, PSE_MC_READ, sizeof(pse_mc_read_req_t), sizeof(pse_mc_read_resp_t), pse_mc_read },
  58. {PSE_MC_SERVICE, PSE_MC_INC, sizeof(pse_mc_inc_req_t), sizeof(pse_mc_inc_resp_t), pse_mc_inc },
  59. {PSE_MC_SERVICE, PSE_MC_DEL, sizeof(pse_mc_del_req_t), sizeof(pse_mc_del_resp_t), pse_mc_del },
  60. {PSE_TRUSTED_TIME_SERVICE, PSE_TIMER_READ, sizeof(pse_timer_read_req_t), sizeof(pse_timer_read_resp_t), pse_read_timer},
  61. };
  62. /*******************************************************************
  63. ** Function name: create_session_wrapper
  64. ** Descrption:
  65. ** This function will initialize the AppEnclave<->Pse-Op session establishment process.
  66. ** Parameters:
  67. ** tick - the number of milliseconds that have elapsed since the system was started,
  68. ** used to detect which session is idle for the longest time.
  69. ** sid - session id
  70. ** Returns: ae_error_t
  71. *******************************************************************/
  72. ae_error_t create_session_wrapper(
  73. /* IN */ uint64_t tick,
  74. /* OUT */ uint32_t* sid,
  75. /* OUT */ pse_dh_msg1_t* dh_msg1)
  76. {
  77. pse_op_error_t op_ret = OP_SUCCESS;
  78. if (!sid || !dh_msg1)
  79. {
  80. return PSE_OP_PARAMETER_ERROR;
  81. }
  82. // ephemeral session must have been established
  83. if(!is_eph_session_active())
  84. {
  85. // the ephemeral session is not active
  86. return PSE_OP_EPHEMERAL_SESSION_INVALID;
  87. }
  88. op_ret = pse_create_session(tick, *sid, *dh_msg1);
  89. return error_reinterpret(op_ret);
  90. }
  91. /*******************************************************************
  92. ** Function name: exchange_report_wrapper
  93. ** Descrption:
  94. ** This function is used to exchange report between AppEnclave and Pse-Op, if success,
  95. ** a session will be established.
  96. ** Parameters:
  97. ** tick - the number of milliseconds that have elapsed since the system was started,
  98. ** used to detect which session is idle for the longest time.
  99. ** sid - session id
  100. ** dh_msg2 - DH message2
  101. ** dh_msg3 - DH message3
  102. ** Returns: ae_error_t
  103. *******************************************************************/
  104. ae_error_t exchange_report_wrapper(
  105. /* IN */ uint64_t tick,
  106. /* IN */ uint32_t sid,
  107. /* IN */ sgx_dh_msg2_t* dh_msg2,
  108. /* OUT */ pse_dh_msg3_t* dh_msg3)
  109. {
  110. pse_op_error_t op_ret = OP_SUCCESS;
  111. if(!dh_msg2 || !dh_msg3)
  112. {
  113. return PSE_OP_PARAMETER_ERROR;
  114. }
  115. // ephemeral session must have been established
  116. if(!is_eph_session_active()) // the ephemeral session is not active
  117. {
  118. return PSE_OP_EPHEMERAL_SESSION_INVALID;
  119. }
  120. op_ret = pse_exchange_report(tick, sid, *dh_msg2, *dh_msg3);
  121. return error_reinterpret(op_ret);
  122. }
  123. /*******************************************************************
  124. ** Function name: close_session_wrapper
  125. ** Descrption:
  126. ** This function is used to close a session
  127. ** Parameters:
  128. ** sid - session id
  129. ** Returns: ae_error_t
  130. *******************************************************************/
  131. ae_error_t close_session_wrapper(
  132. /* IN */ uint32_t sid
  133. )
  134. {
  135. return error_reinterpret(pse_close_session(sid));
  136. }
  137. /*******************************************************************
  138. ** Function name: invoke_service_wrapper
  139. ** Descrption:
  140. ** This function is used to invoke a service call
  141. ** Parameters:
  142. ** tick - the number of milliseconds that have elapsed since the system was started,
  143. ** used to detect which session is idle for the longest time.
  144. ** req_msg - service request message
  145. ** req_msg_size - size of request message
  146. ** resp_msg - service response message
  147. ** resp_msg_size - size of response message
  148. ** Returns: ae_error_t
  149. *******************************************************************/
  150. ae_error_t invoke_service_wrapper (
  151. /* IN */ uint64_t tick,
  152. /* IN */ uint8_t* req_msg,
  153. /* IN */ uint32_t req_msg_size,
  154. /* OUT */ uint8_t* resp_msg,
  155. /* IN */ uint32_t resp_msg_size)
  156. {
  157. // check parameter
  158. ae_error_t ae_ret = AE_SUCCESS;
  159. pse_message_t* pse_req_msg = (pse_message_t*)req_msg;
  160. pse_message_t* pse_resp_msg = (pse_message_t*)resp_msg;
  161. pse_op_error_t op_ret;
  162. if (!req_msg || !resp_msg)
  163. {
  164. return PSE_OP_PARAMETER_ERROR;
  165. }
  166. //
  167. // make sure the header is inside enclave
  168. //
  169. if (req_msg_size < sizeof(pse_message_t))
  170. {
  171. return PSE_OP_PARAMETER_ERROR;
  172. }
  173. //
  174. // if this mispredicts, we might overflow below
  175. //
  176. sgx_lfence();
  177. if (pse_req_msg->payload_size > UINT32_MAX - sizeof(pse_message_t) // check potential overflow
  178. || req_msg_size != sizeof(pse_message_t) + pse_req_msg->payload_size)
  179. {
  180. return PSE_OP_PARAMETER_ERROR;
  181. }
  182. if (resp_msg_size < sizeof(pse_message_t) // make sure the header is inside enclave
  183. || pse_req_msg->exp_resp_size > UINT32_MAX - sizeof(pse_message_t) // check potential overflow
  184. || resp_msg_size < sizeof(pse_message_t) + pse_req_msg->exp_resp_size)
  185. {
  186. return PSE_OP_PARAMETER_ERROR;
  187. }
  188. //
  189. // put LFENCE here mostly for pse_req_msg->payload_size
  190. // check above. I don't think we use
  191. // pse_req_msg->exp_resp_size to calculate
  192. // any pointers.
  193. //
  194. sgx_lfence();
  195. pse_session_t* session = sid2session(pse_req_msg->session_id);
  196. // ephemeral session must have been established
  197. if(!is_eph_session_active())
  198. {
  199. // the ephemeral session is not active
  200. return PSE_OP_EPHEMERAL_SESSION_INVALID;
  201. }
  202. //if session is invalid (session not exists or established, or sequence num overflow)
  203. if (!is_isv_session_valid(session))
  204. {
  205. return PSE_OP_SESSION_INVALID;
  206. }
  207. // update session tick
  208. update_session_tick_count(session, tick);
  209. //clear response message
  210. memset(resp_msg, 0, resp_msg_size);
  211. uint8_t* req = (uint8_t*)malloc(pse_req_msg->payload_size);
  212. uint8_t* resp= NULL;
  213. uint32_t session_seq_num = get_session_seq_num(session);
  214. do
  215. {
  216. BREAK_ON_MALLOC_FAIL(req, ae_ret)
  217. // decrypt service request message using session key
  218. if(false == decrypt_msg(pse_req_msg, req, (sgx_key_128bit_t*)session->active.AEK))
  219. {
  220. ae_ret = PSE_OP_SERVICE_MSG_ERROR;
  221. break;
  222. }
  223. pse_req_hdr_t* req_hdr = (pse_req_hdr_t*)req;
  224. // check session sequence number
  225. if(req_hdr->seq_num != session_seq_num)
  226. {
  227. ae_ret = PSE_OP_SESSION_INVALID;
  228. //close session
  229. free_session(session);
  230. break;
  231. }
  232. // Dispatch the service request to the proper handler
  233. int i;
  234. int service_count = static_cast<int>(sizeof(service_handler) / sizeof(service_handler_t));
  235. for (i = 0; i < service_count; i++)
  236. {
  237. //
  238. // might mispredict the end of the loop
  239. //
  240. sgx_lfence();
  241. if (req_hdr->service_id == service_handler[i].service_id &&
  242. req_hdr->service_cmd == service_handler[i].service_cmd)
  243. {
  244. if (pse_req_msg->payload_size != service_handler[i].req_size ||
  245. pse_req_msg->exp_resp_size < service_handler[i].resp_size) // response message buffer must be large enough to hold response data
  246. {
  247. ae_ret = PSE_OP_SERVICE_MSG_ERROR;
  248. goto clean_up;
  249. }
  250. resp = (uint8_t*)malloc(service_handler[i].resp_size);
  251. if (resp == NULL)
  252. {
  253. ae_ret = PSE_OP_INTERNAL_ERROR;
  254. goto clean_up;
  255. }
  256. //
  257. // in case payload_size, req_size comparisons
  258. // mispredict
  259. //
  260. sgx_lfence();
  261. // serve the request
  262. op_ret = service_handler[i].srv_pfn(session->isv_attributes, req, resp);
  263. if(op_ret != OP_SUCCESS)
  264. {
  265. ae_ret = error_reinterpret(op_ret);
  266. goto clean_up;
  267. }
  268. // set payload size for valid requests
  269. pse_resp_msg->payload_size = service_handler[i].resp_size;
  270. break;
  271. }
  272. }
  273. if (i == service_count)
  274. {
  275. // service_id or service_cmd mismatch
  276. resp = (uint8_t*)malloc(sizeof(pse_resp_hdr_t));
  277. BREAK_ON_MALLOC_FAIL(resp, ae_ret)
  278. // for unknown requests, payload data only includes response header
  279. pse_resp_msg->payload_size = sizeof(pse_resp_hdr_t);
  280. // set error status
  281. ((pse_resp_hdr_t*)resp)->status = PSE_ERROR_UNKNOWN_REQ;
  282. }
  283. // prepare the response message
  284. pse_resp_hdr_t* resp_hdr = (pse_resp_hdr_t*)resp;
  285. pse_resp_msg->exp_resp_size = 0;
  286. pse_resp_msg->session_id = pse_req_msg->session_id;
  287. //set response header, status code is already set in service functions
  288. resp_hdr->seq_num = session_seq_num + 1; // addition overflow already checked in is_isv_session_valid()
  289. resp_hdr->service_id = req_hdr->service_id;
  290. resp_hdr->service_cmd = req_hdr->service_cmd;
  291. // update sequence number for current session
  292. set_session_seq_num(session, resp_hdr->seq_num + 1);
  293. // encrypt the response message
  294. if(false == encrypt_msg((pse_message_t*)pse_resp_msg,
  295. (uint8_t*)resp,
  296. (sgx_key_128bit_t*)session->active.AEK))
  297. {
  298. ae_ret = PSE_OP_INTERNAL_ERROR;
  299. break;
  300. }
  301. } while (0);
  302. clean_up:
  303. SAFE_FREE(req);
  304. SAFE_FREE(resp);
  305. return ae_ret;
  306. }
  307. /*******************************************************************
  308. ** Function name: initialize_sqlite_database_file_wrapper
  309. ** Descrption:
  310. ** Initialize the vmc database
  311. ** Parameters:
  312. ** is_for_empty_db_creation - if true, always create a new database
  313. ** Returns: ae_error_t
  314. *******************************************************************/
  315. ae_error_t initialize_sqlite_database_file_wrapper(bool is_for_empty_db_creation)
  316. {
  317. // ephemeral session must have been established.
  318. if(!is_eph_session_active())
  319. {
  320. return PSE_OP_EPHEMERAL_SESSION_INVALID;
  321. }
  322. return error_reinterpret(initialize_sqlite_database_file(is_for_empty_db_creation));
  323. }
  324. /*******************************************************************
  325. ** Function name: ephemeral_session_m2m3_wrapper
  326. ** Descrption:
  327. ** Exchange M2 and M3 between CSE and PSE-Op
  328. ** Parameters:
  329. ** sealed_blob - Long term pairing blob
  330. ** pse_cse_msg2 - Message2 from CSE
  331. ** pse_cse_msg3 - Message3 generated by PSE-Op
  332. ** Returns: ae_error_t
  333. *******************************************************************/
  334. ae_error_t ephemeral_session_m2m3_wrapper(
  335. /* IN */ pairing_blob_t* sealed_blob,
  336. /* IN */ pse_cse_msg2_t* pse_cse_msg2,
  337. /* OUT */ pse_cse_msg3_t* pse_cse_msg3)
  338. {
  339. pse_op_error_t op_ret = OP_SUCCESS;
  340. // check parameters
  341. if (!sealed_blob || !pse_cse_msg2 || !pse_cse_msg3)
  342. {
  343. return PSE_OP_PARAMETER_ERROR;
  344. }
  345. op_ret = ephemeral_session_m2m3(sealed_blob, *pse_cse_msg2, *pse_cse_msg3);
  346. return error_reinterpret(op_ret);
  347. }
  348. /*******************************************************************
  349. ** Function name: ephemeral_session_m4_wrapper
  350. ** Descrption:
  351. ** Handle Msg4 from CSE, if successful, an ephemeral session will be established
  352. ** Parameters:
  353. ** pse_cse_msg4 - Message4 from CSE
  354. ** Returns: ae_error_t
  355. *******************************************************************/
  356. ae_error_t ephemeral_session_m4_wrapper(
  357. /* IN */ pse_cse_msg4_t* pse_cse_msg4)
  358. {
  359. pse_op_error_t op_ret = OP_SUCCESS;
  360. if (!pse_cse_msg4)
  361. {
  362. return PSE_OP_PARAMETER_ERROR;
  363. }
  364. op_ret = ephemeral_session_m4(*pse_cse_msg4);
  365. return error_reinterpret(op_ret);
  366. }