session_mgr.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  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. #include "utility.h"
  32. #include "session_mgr.h"
  33. #include "pse_op_t.h"
  34. #include "sgx_dh.h"
  35. // ISV enclave <-> pse-op sessions
  36. static pse_session_t g_session[SESSION_CONNECTION];
  37. static uint32_t g_session_count = 0;
  38. // ephemeral session global variables
  39. static uint8_t g_nonce_r_pse[EPH_SESSION_NONCE_SIZE] = {0}; // nonce R(PSE) for ephemeral session establishment
  40. static uint8_t g_nonce_r_cse[EPH_SESSION_NONCE_SIZE] = {0}; // nonce R(CSE) for ephemeral session establishment
  41. static pairing_data_t g_pairing_data; // unsealed pairing data
  42. eph_session_t g_eph_session; // ephemeral session information
  43. /**
  44. * @brief Check the status of the ephemeral session
  45. *
  46. * @return true if the ephemeral session is active. Otherwise false.
  47. */
  48. bool is_eph_session_active()
  49. {
  50. if(SESSION_ACTIVE != g_eph_session.state)
  51. {
  52. return false;
  53. }
  54. return true;
  55. }
  56. /**
  57. * @brief Get session from session ID
  58. *
  59. * @param sid Session ID
  60. *
  61. * @return Session
  62. */
  63. pse_session_t* sid2session(uint32_t sid)
  64. {
  65. for(int index = 0; index < SESSION_CONNECTION; index++)
  66. {
  67. if(g_session[index].state != SESSION_CLOSE &&
  68. g_session[index].sid == sid)
  69. {
  70. return &g_session[index];
  71. }
  72. }
  73. return NULL;
  74. }
  75. /**
  76. * @brief Free the memory of a session
  77. *
  78. * @param session
  79. */
  80. void free_session(pse_session_t* session)
  81. {
  82. if (session) {
  83. memset_s(session, sizeof(pse_session_t), 0, sizeof(pse_session_t));
  84. }
  85. }
  86. /**
  87. * @brief Check active state of a session and its sequence number
  88. *
  89. * @param session
  90. *
  91. * @return true if the session is active and sequence number doesn't overflow
  92. */
  93. bool is_isv_session_valid(pse_session_t* session)
  94. {
  95. //if session not exists or established, return error
  96. if (!session || session->state != SESSION_ACTIVE)
  97. {
  98. return false;
  99. }
  100. // check sequence number
  101. if(session->active.counter >= (UINT32_MAX-2))
  102. {
  103. //close session which contains AEK
  104. memset_s(session, sizeof(pse_session_t), 0, sizeof(pse_session_t));
  105. return false;
  106. }
  107. return true;
  108. }
  109. /**
  110. * @brief Get the sequence number of a session
  111. *
  112. * @param session
  113. *
  114. * @return Sequence number
  115. */
  116. uint32_t get_session_seq_num(pse_session_t* session)
  117. {
  118. return session->active.counter;
  119. }
  120. /**
  121. * @brief Set the sequence number of a session
  122. *
  123. * @param session
  124. * @param seq_num Sequence number
  125. */
  126. void set_session_seq_num(pse_session_t* session, uint32_t seq_num)
  127. {
  128. session->active.counter = seq_num;
  129. }
  130. /**
  131. * @brief Update the tick counter of a session
  132. *
  133. * @param session
  134. * @param new_tick_count
  135. */
  136. void update_session_tick_count(pse_session_t* session, uint64_t new_tick_count)
  137. {
  138. session->isv_attributes.tick_count = new_tick_count;
  139. }
  140. ////////////////////////////////////////////////////////////////////////
  141. ////////////////////////////////////////////////////////////////////////
  142. /**
  143. * @brief
  144. * Here describe how to find the idle session
  145. * 1. find the one which exceed session quote, and if two enclave has
  146. * same instances number, find the one has idle for the longest time.
  147. * two arrays:
  148. * instances: record each enclave's instances number
  149. * time_stamp: for each enclave's instance, record the instance that
  150. * idle for the longest time, it's a index to g_session.
  151. * the two array items are corresponding to each other
  152. * for instance:
  153. * instances:
  154. * | 1 | 32 | 9 | 8 | 1 | 32 |....
  155. * ---------------------------....
  156. * time stamp
  157. * | 0 | 2 | 5 | 10 | 19 | 6 |....
  158. * ---------------------------....
  159. * [0]:
  160. * enclave has 1 instance, and the longest idle one is g_session[0]
  161. * [1]:
  162. * enclave has 32 instances, among them the g_session[2] is the longest
  163. * idle one.
  164. * [2]:
  165. * enclave has 9 instances, among them the g_session[5] is the longest
  166. * idle one.
  167. *
  168. * @param tick
  169. *
  170. * @return Session
  171. */
  172. pse_session_t* find_idle_session(uint64_t tick)
  173. {
  174. pse_session_t* session = NULL;
  175. uint8_t instances[SESSION_CONNECTION];
  176. uint8_t time_stamp[SESSION_CONNECTION];
  177. uint8_t end_index = 0;
  178. uint8_t max_instance = 0;
  179. memset(instances, 0, SESSION_CONNECTION);
  180. memset(time_stamp, 0, SESSION_CONNECTION);
  181. for(uint8_t i = 0; i < SESSION_CONNECTION; i++)
  182. {
  183. pse_session_t* s1 = &g_session[i];
  184. // if one session has not established, no need to calculate the quote
  185. // as no enclave information has obtain.
  186. if (s1->state != SESSION_ACTIVE)
  187. {
  188. continue;
  189. }
  190. uint8_t j = 0;
  191. for(; j < end_index; j++)
  192. {
  193. pse_session_t* s2 = &g_session[time_stamp[j]];
  194. if (!memcmp(&s1->isv_attributes.mr_enclave,
  195. &s2->isv_attributes.mr_enclave,
  196. sizeof(s1->isv_attributes.mr_enclave)) &&
  197. !memcmp(&s1->isv_attributes.mr_signer,
  198. &s2->isv_attributes.mr_signer,
  199. sizeof(s1->isv_attributes.mr_signer)) &&
  200. s1->isv_attributes.isv_prod_id == s2->isv_attributes.isv_prod_id)
  201. {
  202. if (s1->isv_attributes.tick_count < s2->isv_attributes.tick_count)
  203. {
  204. time_stamp[j] = i;
  205. }
  206. ++instances[j];
  207. if (instances[j] > max_instance)
  208. {
  209. max_instance = instances[j];
  210. }
  211. break;
  212. }
  213. }
  214. if (j == end_index)
  215. {
  216. time_stamp[end_index] = i;
  217. instances[end_index] = 1;
  218. if (instances[end_index] > max_instance)
  219. {
  220. max_instance = instances[end_index];
  221. }
  222. end_index++;
  223. }
  224. }
  225. if (max_instance > MAX_INST_PER_ENCLAVE)
  226. {
  227. for (uint8_t i = 0; i < end_index; i++)
  228. {
  229. if (instances[i] == max_instance)
  230. {
  231. pse_session_t* s1 = &g_session[time_stamp[i]];
  232. if (!session)
  233. {
  234. session = s1;
  235. }
  236. else if (session->isv_attributes.tick_count > s1->isv_attributes.tick_count)
  237. {
  238. session = s1;
  239. }
  240. }
  241. }
  242. }
  243. if(session)
  244. {
  245. return session;
  246. }
  247. //if no enclave instance exceed quote,
  248. //iterate all enclave to find the one no-active for long time
  249. uint64_t elapse = 0;
  250. //find the least active session
  251. for(uint8_t index = 0; index < SESSION_CONNECTION; index++)
  252. {
  253. uint64_t temp = tick - g_session[index].isv_attributes.tick_count;
  254. if(temp > tick)
  255. {
  256. // temp underflow
  257. return NULL;
  258. }
  259. if(temp > elapse)
  260. {
  261. elapse = temp;
  262. session = &g_session[index];
  263. }
  264. }
  265. //if the least active session is not exceed predefined time,
  266. // no idle session find
  267. if(elapse < SESSION_IDLE_TIME)
  268. {
  269. session = NULL;
  270. }
  271. return session;
  272. }
  273. /**
  274. * @brief Select a session slot based on the defined rules.
  275. *
  276. * @param tick
  277. *
  278. * @return
  279. */
  280. pse_session_t* open_session(uint64_t tick)
  281. {
  282. int index = 0;
  283. pse_session_t* session = NULL;
  284. //if the session id reached the limitation, reset all sessions
  285. if(g_session_count == SESSION_COUNTER_MAX)
  286. {
  287. for(index = 0; index < SESSION_CONNECTION; index++)
  288. {
  289. free_session(&g_session[index]);
  290. }
  291. g_session_count = 0;
  292. }
  293. for(index = 0; index < SESSION_CONNECTION; index++)
  294. {
  295. if(g_session[index].state == SESSION_CLOSE)
  296. {
  297. break;
  298. }
  299. }
  300. if(index == SESSION_CONNECTION)
  301. {
  302. //if no session slot available, find one idle session for reuse
  303. session = find_idle_session(tick);
  304. if (session)
  305. {
  306. free_session(session);
  307. }
  308. }
  309. else
  310. {
  311. session = &g_session[index];
  312. }
  313. return session;
  314. }
  315. /**
  316. * @brief Initialize a DH session.
  317. *
  318. * @param tick Tick counter
  319. * @param id Session ID
  320. * @param dh_msg1 DH Message1
  321. *
  322. * @return OP_SUCCESS
  323. */
  324. pse_op_error_t pse_create_session(uint64_t tick, uint32_t &id, pse_dh_msg1_t &dh_msg1)
  325. {
  326. pse_op_error_t status = OP_SUCCESS;
  327. pse_session_t* session = NULL;
  328. sgx_status_t se_ret;
  329. sgx_dh_session_t sgx_dh_session;
  330. se_ret = sgx_dh_init_session(SGX_DH_SESSION_RESPONDER, &sgx_dh_session);
  331. if(SGX_SUCCESS != se_ret)
  332. {
  333. return OP_ERROR_INTERNAL;
  334. }
  335. session = open_session(tick);
  336. if(!session)
  337. {
  338. //if no available session found, return error to ISV enclave
  339. id = INVADE_SESSION_ID;
  340. return OP_ERROR_MAX_NUM_SESSION_REACHED;
  341. }
  342. else
  343. {
  344. session->state = SESSION_IN_PROGRESS;
  345. session->sid = g_session_count++; // addition overflow already checked in open_session
  346. id = session->sid;
  347. }
  348. do
  349. {
  350. //Generate Message1
  351. se_ret = sgx_dh_responder_gen_msg1((sgx_dh_msg1_t*)&dh_msg1, &sgx_dh_session);
  352. if(SGX_SUCCESS != se_ret)
  353. {
  354. status = OP_ERROR_INTERNAL;
  355. break;
  356. }
  357. memcpy(&session->in_progress.dh_session, &sgx_dh_session, sizeof(sgx_dh_session_t));
  358. // clear secret
  359. memset_s(&sgx_dh_session, sizeof(sgx_dh_session_t), 0, sizeof(sgx_dh_session_t));
  360. //update tick count to record the last session activation tick count
  361. session->isv_attributes.tick_count = tick;
  362. session->isv_attributes_len = sizeof(isv_attributes_t);
  363. }while(0);
  364. if(status != OP_SUCCESS)
  365. {
  366. pse_close_session(id);
  367. id = INVADE_SESSION_ID;
  368. }
  369. return status;
  370. }
  371. /**
  372. * @brief Exchange M2 and M3
  373. *
  374. * @param tick
  375. * @param sid
  376. * @param dh_msg2
  377. * @param dh_msg3
  378. *
  379. * @return
  380. */
  381. pse_op_error_t pse_exchange_report(uint64_t tick,
  382. uint32_t sid,
  383. const sgx_dh_msg2_t &dh_msg2,
  384. pse_dh_msg3_t &dh_msg3)
  385. {
  386. pse_op_error_t status = OP_SUCCESS;
  387. sgx_dh_session_t sgx_dh_session;
  388. sgx_key_128bit_t aek;
  389. sgx_dh_session_enclave_identity_t initiator_identity;
  390. cse_sec_prop_t * pcse_sec = NULL;
  391. secu_info_t* psec_info = NULL;
  392. pse_session_t* session = sid2session(sid);
  393. if(!session || session->state != SESSION_IN_PROGRESS)
  394. {
  395. return OP_ERROR_INVALID_SESSION;
  396. }
  397. do
  398. {
  399. memcpy(&sgx_dh_session, &session->in_progress.dh_session, sizeof(sgx_dh_session_t));
  400. dh_msg3.additional_prop_length = sizeof(cse_sec_prop_t);
  401. // set secu_info_t
  402. pcse_sec = &dh_msg3.cse_sec_prop;
  403. pcse_sec->gid_cse = g_pairing_data.plaintext.cse_sec_prop.ps_hw_gid;
  404. pcse_sec->prvrl_version = g_pairing_data.plaintext.cse_sec_prop.ps_hw_privkey_rlversion;
  405. pcse_sec->sigrl_version = g_pairing_data.plaintext.cse_sec_prop.ps_hw_sig_rlversion;
  406. pcse_sec->sec_info_type = 0;
  407. memcpy(pcse_sec->ca_id_cse, g_pairing_data.plaintext.cse_sec_prop.ps_hw_CA_id, sizeof(pcse_sec->ca_id_cse));
  408. psec_info = (secu_info_t*)(pcse_sec->sec_info);
  409. psec_info->jom_task_id = 8;
  410. //psec_info->psda_svn = *(uint32_t*)&g_pairing_data.plaintext.cse_sec_prop.ps_hw_sec_info[12];
  411. psec_info->psda_svn = g_pairing_data.plaintext.cse_sec_prop.ps_hw_sec_info.psdaSvn;
  412. psec_info->psda_id = 1;
  413. psec_info->reserved = 0;
  414. memset_s(psec_info->reserved2, sizeof(psec_info->reserved2), 0, sizeof(psec_info->reserved2));
  415. sgx_status_t se_ret = sgx_dh_responder_proc_msg2(&dh_msg2,
  416. (sgx_dh_msg3_t*)&dh_msg3,
  417. &sgx_dh_session,
  418. &aek,
  419. &initiator_identity);
  420. // clear secret
  421. memset_s(&sgx_dh_session, sizeof(sgx_dh_session_t), 0, sizeof(sgx_dh_session_t));
  422. if (SGX_ERROR_KDF_MISMATCH == se_ret)
  423. {
  424. status = OP_ERROR_KDF_MISMATCH;
  425. break;
  426. }
  427. else if(SGX_SUCCESS != se_ret)
  428. {
  429. status = OP_ERROR_INTERNAL;
  430. break;
  431. }
  432. // clear secret before changing session status
  433. memset_s(&session->in_progress.dh_session, sizeof(sgx_dh_session_t), 0, sizeof(sgx_dh_session_t));
  434. session->state = SESSION_ACTIVE;
  435. memcpy(&session->active.AEK, &aek, sizeof(sgx_key_128bit_t));
  436. session->active.counter = 0;
  437. session->isv_attributes_len = sizeof(isv_attributes_t);
  438. memcpy(&session->isv_attributes.attribute, &initiator_identity.attributes, sizeof(sgx_attributes_t));
  439. memcpy(&session->isv_attributes.isv_prod_id, &initiator_identity.isv_prod_id, sizeof(sgx_prod_id_t));
  440. memcpy(&session->isv_attributes.isv_svn, &initiator_identity.isv_svn, sizeof(sgx_isv_svn_t));
  441. //record mr_signer
  442. memcpy(&session->isv_attributes.mr_signer, &initiator_identity.mr_signer, sizeof(sgx_measurement_t));
  443. //record mr_enclave
  444. memcpy(&session->isv_attributes.mr_enclave, &initiator_identity.mr_enclave, sizeof(sgx_measurement_t));
  445. //update tick count
  446. session->isv_attributes.tick_count = tick;
  447. }while(0);
  448. if(status != OP_SUCCESS)
  449. {
  450. pse_close_session(sid);
  451. }
  452. return status;
  453. }
  454. pse_op_error_t pse_close_session(uint32_t sid)
  455. {
  456. if (sid != (uint32_t)INVADE_SESSION_ID)
  457. {
  458. pse_session_t* session = sid2session(sid);
  459. if(session)
  460. {
  461. free_session(session);
  462. }
  463. return OP_SUCCESS;
  464. }
  465. return OP_ERROR_INVALID_SESSION;
  466. }
  467. /**
  468. * @brief Exchange message2 and message3 between CSE and PSE
  469. *
  470. * @param sealed_blob Sealed long term pairing blob.
  471. * @param pse_cse_msg2 Message2
  472. * @param pse_cse_msg3 Message3
  473. *
  474. * @return OP_SUCCESS for successful message exchange. All other values indicate FAIL.
  475. */
  476. pse_op_error_t ephemeral_session_m2m3(
  477. pairing_blob_t* sealed_blob,
  478. const pse_cse_msg2_t &pse_cse_msg2,
  479. pse_cse_msg3_t &pse_cse_msg3)
  480. {
  481. sgx_status_t se_ret = SGX_SUCCESS;
  482. uint32_t msg_len = 0;
  483. pse_op_error_t op_ret = OP_SUCCESS;
  484. Nonce128_t zero_nonce;
  485. sgx_report_t report;
  486. sgx_isv_svn_t sealed_isv_svn;
  487. sgx_cpu_svn_t* p_sealed_cpu_svn = NULL;
  488. // decrypt sealed blob
  489. if (UnsealPairingBlob(sealed_blob, &g_pairing_data) != AE_SUCCESS)
  490. {
  491. // unseal error
  492. op_ret = OP_ERROR_UNSEAL_PAIRING_BLOB;
  493. goto error;
  494. }
  495. // If the pairing blob was sealed by a different ISV SVN, we need to
  496. // tell AESM to redo long term pairing
  497. memset_s(&report, sizeof(report), 0, sizeof(report));
  498. se_ret = sgx_create_report(NULL, NULL, &report);
  499. if(SGX_SUCCESS != se_ret)
  500. {
  501. op_ret = OP_ERROR_INTERNAL;
  502. goto error;
  503. }
  504. sealed_isv_svn = ((sgx_sealed_data_t*)sealed_blob)->key_request.isv_svn;
  505. p_sealed_cpu_svn = &((sgx_sealed_data_t*)sealed_blob)->key_request.cpu_svn;
  506. if (sealed_isv_svn != report.body.isv_svn || memcmp(p_sealed_cpu_svn, &report.body.cpu_svn, sizeof(sgx_cpu_svn_t)) != 0)
  507. {
  508. op_ret = OP_ERROR_LTPB_SEALING_OUT_OF_DATE;
  509. goto error;
  510. }
  511. // Reset ephemeral session
  512. memset(&g_eph_session, 0 , sizeof(eph_session_t));
  513. // verify pairingNonce, must be non-zero.
  514. memset(&zero_nonce, 0, sizeof(zero_nonce));
  515. if(0 == memcmp(&g_pairing_data.secret_data.pairingNonce, &zero_nonce, sizeof(Nonce128_t)))
  516. {
  517. op_ret = OP_ERROR_INVALID_PAIRING_BLOB;
  518. goto error;
  519. }
  520. // clear secret data
  521. memset_s(&g_pairing_data.secret_data.VerifierPrivateKey, sizeof(EcDsaPrivKey), 0, sizeof(EcDsaPrivKey));
  522. memset_s(&g_pairing_data.secret_data.pairingID, sizeof(SIGMA_SECRET_KEY), 0, sizeof(SIGMA_SECRET_KEY));
  523. // verify IDcse
  524. if (memcmp(g_pairing_data.secret_data.Id_cse, pse_cse_msg2.id_cse, sizeof(pse_cse_msg2.id_cse)) != 0)
  525. {
  526. op_ret = OP_ERROR_EPH_SESSION_ESTABLISHMENT_INTEGRITY_ERROR;
  527. goto error;
  528. }
  529. // save nonce R_cse
  530. memcpy(g_nonce_r_cse, pse_cse_msg2.nonce_r_cse, sizeof(g_nonce_r_cse));
  531. // generate Message3
  532. se_ret = sgx_read_rand((uint8_t*)&g_nonce_r_pse, sizeof(g_nonce_r_pse));
  533. if (se_ret != SGX_SUCCESS)
  534. {
  535. op_ret = OP_ERROR_INTERNAL;
  536. goto error;
  537. }
  538. memcpy(pse_cse_msg3.id_cse, g_pairing_data.secret_data.Id_cse, sizeof(pse_cse_msg3.id_cse));
  539. memcpy(pse_cse_msg3.id_pse, g_pairing_data.secret_data.Id_pse, sizeof(pse_cse_msg3.id_pse));
  540. memcpy(pse_cse_msg3.nonce_r_pse, g_nonce_r_pse, sizeof(pse_cse_msg3.nonce_r_pse));
  541. memcpy(pse_cse_msg3.nonce_r_cse, pse_cse_msg2.nonce_r_cse, sizeof(pse_cse_msg3.nonce_r_cse));
  542. // compute HMAC over IDcse||IDpse||Rpse||Rcse
  543. msg_len = static_cast<uint32_t>(sizeof(pse_cse_msg3.id_cse) + sizeof(pse_cse_msg3.id_pse)
  544. + sizeof(pse_cse_msg3.nonce_r_pse) + sizeof(pse_cse_msg3.nonce_r_cse));
  545. if (ippsHMAC_Message((uint8_t*)&pse_cse_msg3, msg_len, g_pairing_data.secret_data.mk, sizeof(g_pairing_data.secret_data.mk),
  546. pse_cse_msg3.mac, SGX_SHA256_HASH_SIZE, IPP_ALG_HASH_SHA256) != ippStsNoErr)
  547. {
  548. op_ret = OP_ERROR_INTERNAL;
  549. goto error;
  550. }
  551. g_eph_session.state = SESSION_IN_PROGRESS;
  552. return OP_SUCCESS;
  553. error:
  554. memset_s(&g_pairing_data.secret_data, sizeof(se_secret_pairing_data_t), 0, sizeof(se_secret_pairing_data_t));
  555. return op_ret;
  556. }
  557. /**
  558. * @brief Verify message4 which is generated by CSE. If verification
  559. * is passed, ephemeral session will be established.
  560. *
  561. * @param pse_cse_msg4 Message4
  562. *
  563. * @return OP_SUCCESS for successful session establishment. All other values indicate FAIL.
  564. */
  565. pse_op_error_t ephemeral_session_m4(
  566. const pse_cse_msg4_t &pse_cse_msg4)
  567. {
  568. uint32_t msg_len;
  569. uint8_t* msg_buf = NULL;
  570. uint8_t mac_buf[SGX_SHA256_HASH_SIZE];
  571. pse_op_error_t op_ret = OP_SUCCESS;
  572. // check session state
  573. if (g_eph_session.state != SESSION_IN_PROGRESS)
  574. {
  575. op_ret = OP_ERROR_INVALID_EPH_SESSION;
  576. goto error;
  577. }
  578. // verify message4
  579. if (memcmp(g_nonce_r_pse, pse_cse_msg4.nonce_r_pse, sizeof(pse_cse_msg4.nonce_r_pse)) != 0
  580. || memcmp(g_pairing_data.secret_data.Id_cse, pse_cse_msg4.id_cse, sizeof(pse_cse_msg4.id_cse)) != 0)
  581. {
  582. op_ret = OP_ERROR_EPH_SESSION_ESTABLISHMENT_INTEGRITY_ERROR;
  583. goto error;
  584. }
  585. // verify MAC value
  586. if (!verify_hmac_sha256(g_pairing_data.secret_data.mk,
  587. sizeof(g_pairing_data.secret_data.mk),
  588. (const uint8_t*)&pse_cse_msg4,
  589. CSE_ID_SIZE + EPH_SESSION_NONCE_SIZE,
  590. pse_cse_msg4.mac))
  591. {
  592. op_ret = OP_ERROR_EPH_SESSION_ESTABLISHMENT_INTEGRITY_ERROR;
  593. goto error;
  594. }
  595. // Deriving Transient Session Key
  596. msg_len = EPH_SESSION_NONCE_SIZE * 2;
  597. msg_buf = (uint8_t*)malloc(msg_len);
  598. if (msg_buf == NULL)
  599. {
  600. op_ret = OP_ERROR_MALLOC;
  601. goto error;
  602. }
  603. // calculate session key
  604. memcpy(msg_buf, g_nonce_r_pse, EPH_SESSION_NONCE_SIZE);
  605. memcpy(msg_buf + EPH_SESSION_NONCE_SIZE, g_nonce_r_cse, EPH_SESSION_NONCE_SIZE);
  606. // TSK := HMAC-SHA256sk(Rpse || Rcse)
  607. if (ippsHMAC_Message(msg_buf,
  608. msg_len,
  609. g_pairing_data.secret_data.sk,
  610. sizeof(g_pairing_data.secret_data.sk),
  611. mac_buf,
  612. SGX_SHA256_HASH_SIZE, IPP_ALG_HASH_SHA256) != ippStsNoErr)
  613. {
  614. SAFE_FREE(msg_buf);
  615. op_ret = OP_ERROR_INTERNAL;
  616. goto error;
  617. }
  618. memcpy(g_eph_session.TSK, mac_buf, EPH_SESSION_TSK_SIZE);
  619. memcpy(g_eph_session.TMK, mac_buf + EPH_SESSION_TSK_SIZE, EPH_SESSION_TMK_SIZE);
  620. // free buffer
  621. SAFE_FREE(msg_buf);
  622. // mark ephemeral session as established
  623. g_eph_session.state = SESSION_ACTIVE;
  624. // reset global variables that will be never used anymore
  625. memset_s(g_nonce_r_cse, sizeof(g_nonce_r_cse), 0, sizeof(g_nonce_r_cse));
  626. memset_s(g_nonce_r_pse, sizeof(g_nonce_r_pse), 0, sizeof(g_nonce_r_pse));
  627. // keep the CSE security property information and the pairing nonce in the enclave memory
  628. memset_s(&g_pairing_data.secret_data.sk, sizeof(SIGMA_SECRET_KEY), 0, sizeof(SIGMA_SECRET_KEY));
  629. memset_s(&g_pairing_data.secret_data.mk, sizeof(SIGMA_MAC_KEY), 0, sizeof(SIGMA_MAC_KEY));
  630. memset_s(&g_pairing_data.secret_data.Id_pse, sizeof(SHA256_HASH), 0, sizeof(SHA256_HASH));
  631. memset_s(&g_pairing_data.secret_data.Id_cse, sizeof(SHA256_HASH), 0, sizeof(SHA256_HASH));
  632. return OP_SUCCESS;
  633. error:
  634. memset_s(&g_pairing_data.secret_data, sizeof(se_secret_pairing_data_t), 0, sizeof(se_secret_pairing_data_t));
  635. memset(&g_eph_session, 0, sizeof(g_eph_session));
  636. return op_ret;
  637. }
  638. bool copy_global_pairing_nonce(uint8_t* target_buffer)
  639. {
  640. // g_pairing_data availability is ensured by checking ephemeral session state at the ECALL layer
  641. // but we check again here
  642. if (!is_eph_session_active())
  643. {
  644. return false;
  645. }
  646. memcpy(target_buffer, g_pairing_data.secret_data.pairingNonce, sizeof(Nonce128_t));
  647. return true;
  648. }
  649. void copy_pse_instance_id(uint8_t* pse_instance_id)
  650. {
  651. memcpy(pse_instance_id, g_pairing_data.plaintext.pse_instance_id, SW_INSTANCE_ID_SIZE);
  652. }