ec_dh.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. /*
  2. * Copyright (C) 2011-2017 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 <limits.h>
  32. #include "stdlib.h"
  33. #include "string.h"
  34. #include "sgx.h"
  35. #include "sgx_defs.h"
  36. #include "sgx_utils.h"
  37. #include "sgx_ecp_types.h"
  38. #include "sgx_key.h"
  39. #include "sgx_report.h"
  40. #include "sgx_attributes.h"
  41. #include "sgx_trts.h"
  42. #include "ecp_interface.h"
  43. #include "sgx_dh_internal.h"
  44. #define NONCE_SIZE 16
  45. #define MSG_BUF_LEN (static_cast<uint32_t>(sizeof(sgx_ec256_public_t)*2))
  46. #define MSG_HASH_SZ 32
  47. #ifndef SAFE_FREE
  48. #define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}}
  49. #endif
  50. static sgx_status_t verify_cmac128(
  51. const sgx_ec_key_128bit_t mac_key,
  52. const uint8_t* data_buf,
  53. uint32_t buf_size,
  54. const uint8_t* mac_buf)
  55. {
  56. uint8_t data_mac[SGX_CMAC_MAC_SIZE];
  57. sgx_status_t se_ret = SGX_SUCCESS;
  58. if(!data_buf || !mac_buf || !mac_key)
  59. {
  60. return SGX_ERROR_INVALID_PARAMETER;
  61. }
  62. se_ret = sgx_rijndael128_cmac_msg((const sgx_cmac_128bit_key_t*)mac_key,
  63. data_buf,
  64. buf_size,
  65. (sgx_cmac_128bit_tag_t *)data_mac);
  66. if(SGX_SUCCESS != se_ret)
  67. {
  68. return se_ret;
  69. }
  70. if(consttime_memequal(mac_buf, data_mac, SGX_CMAC_MAC_SIZE) == 0)
  71. {
  72. return SGX_ERROR_MAC_MISMATCH;
  73. }
  74. return se_ret;
  75. }
  76. static sgx_status_t dh_generate_message1(sgx_dh_msg1_t *msg1, sgx_internal_dh_session_t *context)
  77. {
  78. sgx_report_t temp_report;
  79. sgx_report_data_t report_data = {{0}};
  80. sgx_target_info_t target;
  81. sgx_status_t se_ret;
  82. sgx_ecc_state_handle_t ecc_state = NULL;
  83. if(!msg1 || !context)
  84. {
  85. return SGX_ERROR_INVALID_PARAMETER;
  86. }
  87. memset(&temp_report, 0, sizeof(temp_report));
  88. memset(&target, 0, sizeof(target));
  89. //Create Report to get target info which targeted towards the initiator of the session
  90. se_ret = sgx_create_report(&target, &report_data,&temp_report);
  91. if(se_ret != SGX_SUCCESS)
  92. {
  93. return se_ret;
  94. }
  95. memcpy(&msg1->target.mr_enclave,
  96. &temp_report.body.mr_enclave,
  97. sizeof(sgx_measurement_t));
  98. memcpy(&msg1->target.attributes,
  99. &temp_report.body.attributes,
  100. sizeof(sgx_attributes_t));
  101. msg1->target.misc_select = temp_report.body.misc_select;
  102. //Initialize ECC context to prepare for creating key pair
  103. se_ret = sgx_ecc256_open_context(&ecc_state);
  104. if(se_ret != SGX_SUCCESS)
  105. {
  106. return se_ret;
  107. }
  108. //Generate the public key private key pair for Session Responder
  109. se_ret = sgx_ecc256_create_key_pair((sgx_ec256_private_t*)&context->responder.prv_key,
  110. (sgx_ec256_public_t*)&context->responder.pub_key,
  111. ecc_state);
  112. if(se_ret != SGX_SUCCESS)
  113. {
  114. sgx_ecc256_close_context(ecc_state);
  115. return se_ret;
  116. }
  117. //Copying public key to g^a
  118. memcpy(&msg1->g_a,
  119. &context->responder.pub_key,
  120. sizeof(sgx_ec256_public_t));
  121. se_ret = sgx_ecc256_close_context(ecc_state);
  122. if(SGX_SUCCESS != se_ret)
  123. {
  124. return se_ret;
  125. }
  126. return SGX_SUCCESS;
  127. }
  128. static sgx_status_t dh_generate_message2(const sgx_dh_msg1_t *msg1,
  129. const sgx_ec256_public_t *g_b,
  130. const sgx_key_128bit_t *dh_smk,
  131. sgx_dh_msg2_t *msg2)
  132. {
  133. sgx_report_t temp_report;
  134. sgx_report_data_t report_data;
  135. sgx_status_t se_ret;
  136. uint8_t msg_buf[MSG_BUF_LEN] = {0};
  137. uint8_t msg_hash[MSG_HASH_SZ] = {0};
  138. if(!msg1 || !g_b || !dh_smk || !msg2)
  139. {
  140. return SGX_ERROR_INVALID_PARAMETER;
  141. }
  142. memset(msg2, 0, sizeof(sgx_dh_msg2_t));
  143. memcpy(&msg2->g_b, g_b, sizeof(sgx_ec256_public_t));
  144. memcpy(msg_buf,
  145. &msg1->g_a,
  146. sizeof(sgx_ec256_public_t));
  147. memcpy(msg_buf + sizeof(sgx_ec256_public_t),
  148. &msg2->g_b,
  149. sizeof(sgx_ec256_public_t));
  150. se_ret = sgx_sha256_msg(msg_buf,
  151. MSG_BUF_LEN,
  152. (sgx_sha256_hash_t *)msg_hash);
  153. if(SGX_SUCCESS != se_ret)
  154. {
  155. return se_ret;
  156. }
  157. // Get REPORT with sha256(msg1->g_a | msg2->g_b) || kdf_id as user data
  158. // 2-byte little-endian KDF-ID: 0x0001 AES-CMAC Entropy Extraction and Key Derivation
  159. memset(&report_data, 0, sizeof(sgx_report_data_t));
  160. memcpy(&report_data, &msg_hash, sizeof(msg_hash));
  161. uint16_t *kdf_id = (uint16_t *)&report_data.d[sizeof(msg_hash)];
  162. *kdf_id = AES_CMAC_KDF_ID;
  163. // Generate Report targeted towards Session Responder
  164. se_ret = sgx_create_report(&msg1->target, &report_data, &temp_report);
  165. if(SGX_SUCCESS != se_ret)
  166. {
  167. return se_ret;
  168. }
  169. memcpy(&msg2->report, &temp_report, sizeof(sgx_report_t));
  170. //Calculate the MAC for Message 2
  171. se_ret = sgx_rijndael128_cmac_msg(dh_smk,
  172. (uint8_t *)(&msg2->report),
  173. sizeof(sgx_report_t),
  174. (sgx_cmac_128bit_tag_t *)msg2->cmac);
  175. if(SGX_SUCCESS != se_ret)
  176. {
  177. return se_ret;
  178. }
  179. return SGX_SUCCESS;
  180. }
  181. static sgx_status_t dh_verify_message2(const sgx_dh_msg2_t *msg2,
  182. const sgx_ec256_public_t *g_a,
  183. const sgx_key_128bit_t *dh_smk)
  184. {
  185. sgx_report_t temp_report;
  186. sgx_status_t se_ret;
  187. uint8_t msg_buf[MSG_BUF_LEN] = {0};
  188. uint8_t msg_hash[MSG_HASH_SZ] = {0};
  189. if(!msg2 || !g_a || !dh_smk)
  190. {
  191. return SGX_ERROR_INVALID_PARAMETER;
  192. }
  193. /* report_data = SHA256(g_a || g_b) || kdf_id
  194. * Verify kdf_id first.
  195. * 2-byte little-endian KDF-ID: 0x0001 AES-CMAC Entropy Extraction and Key Derivation
  196. */
  197. uint16_t *kdf_id = (uint16_t *)&msg2->report.body.report_data.d[sizeof(msg_hash)];
  198. if (*kdf_id != AES_CMAC_KDF_ID)
  199. {
  200. return SGX_ERROR_KDF_MISMATCH;
  201. }
  202. //Verify the MAC of message 2 obtained from the Session Initiator
  203. se_ret = verify_cmac128((const uint8_t*)dh_smk, (const uint8_t*)(&msg2->report), sizeof(sgx_report_t), msg2->cmac);
  204. if(SGX_SUCCESS != se_ret)
  205. {
  206. return se_ret;
  207. }
  208. memcpy(&temp_report,&msg2->report,sizeof(sgx_report_t));
  209. // Verify message 2 report obtained from the Session Initiator
  210. se_ret = sgx_verify_report(&temp_report);
  211. if(SGX_SUCCESS != se_ret)
  212. {
  213. return se_ret;
  214. }
  215. memcpy(msg_buf, g_a, sizeof(sgx_ec256_public_t));
  216. memcpy(msg_buf + sizeof(sgx_ec256_public_t), &msg2->g_b, sizeof(sgx_ec256_public_t));
  217. se_ret = sgx_sha256_msg(msg_buf,
  218. MSG_BUF_LEN,
  219. (sgx_sha256_hash_t *)msg_hash);
  220. if(SGX_SUCCESS != se_ret)
  221. {
  222. return se_ret;
  223. }
  224. // report_data = SHA256(g_a || g_b) || kdf_id
  225. // Verify SHA256(g_a || g_b)
  226. if (0 != memcmp(msg_hash,
  227. &msg2->report.body.report_data,
  228. sizeof(msg_hash)))
  229. {
  230. return SGX_ERROR_MAC_MISMATCH;
  231. }
  232. return SGX_SUCCESS;
  233. }
  234. static sgx_status_t dh_generate_message3(const sgx_dh_msg2_t *msg2,
  235. const sgx_ec256_public_t *g_a,
  236. const sgx_key_128bit_t *dh_smk,
  237. sgx_dh_msg3_t *msg3,
  238. uint32_t msg3_additional_prop_len)
  239. {
  240. sgx_report_t temp_report;
  241. sgx_report_data_t report_data;
  242. sgx_status_t se_ret = SGX_SUCCESS;
  243. uint32_t maced_size;
  244. uint8_t msg_buf[MSG_BUF_LEN] = {0};
  245. uint8_t msg_hash[MSG_HASH_SZ] = {0};
  246. sgx_target_info_t target;
  247. if(!msg2 || !g_a || !dh_smk || !msg3)
  248. {
  249. return SGX_ERROR_INVALID_PARAMETER;
  250. }
  251. maced_size = static_cast<uint32_t>(sizeof(sgx_dh_msg3_body_t)) + msg3_additional_prop_len;
  252. memset(msg3, 0, sizeof(sgx_dh_msg3_t)); // Don't clear the additional property since the content of the property is provided by caller.
  253. memcpy(msg_buf, &msg2->g_b, sizeof(sgx_ec256_public_t));
  254. memcpy(msg_buf + sizeof(sgx_ec256_public_t), g_a, sizeof(sgx_ec256_public_t));
  255. se_ret = sgx_sha256_msg(msg_buf,
  256. MSG_BUF_LEN,
  257. (sgx_sha256_hash_t *)msg_hash);
  258. if(se_ret != SGX_SUCCESS)
  259. {
  260. return se_ret;
  261. }
  262. memset(&target, 0, sizeof(sgx_target_info_t));
  263. // Get REPORT with SHA256(g_b||g_a) as user data
  264. memset(&report_data, 0, sizeof(sgx_report_data_t));
  265. memcpy(&report_data, &msg_hash, sizeof(msg_hash));
  266. memcpy(&target.attributes,
  267. &msg2->report.body.attributes,
  268. sizeof(sgx_attributes_t));
  269. memcpy(&target.mr_enclave,
  270. &msg2->report.body.mr_enclave,
  271. sizeof(sgx_measurement_t));
  272. target.misc_select = msg2->report.body.misc_select;
  273. // Generate Report targeted towards Session Initiator
  274. se_ret = sgx_create_report(&target, &report_data, &temp_report);
  275. if(se_ret != SGX_SUCCESS)
  276. {
  277. return se_ret;
  278. }
  279. memcpy(&msg3->msg3_body.report,
  280. &temp_report,
  281. sizeof(sgx_report_t));
  282. msg3->msg3_body.additional_prop_length = msg3_additional_prop_len;
  283. //Calculate the MAC for Message 3
  284. se_ret = sgx_rijndael128_cmac_msg(dh_smk,
  285. (uint8_t *)&msg3->msg3_body,
  286. maced_size,
  287. (sgx_cmac_128bit_tag_t *)msg3->cmac);
  288. if(se_ret != SGX_SUCCESS)
  289. {
  290. return se_ret;
  291. }
  292. return SGX_SUCCESS;
  293. }
  294. static sgx_status_t dh_verify_message3(const sgx_dh_msg3_t *msg3,
  295. const sgx_ec256_public_t *g_a,
  296. const sgx_ec256_public_t *g_b,
  297. const sgx_key_128bit_t *dh_smk)
  298. {
  299. sgx_report_t temp_report;
  300. uint32_t maced_size;
  301. sgx_status_t se_ret;
  302. uint8_t msg_buf[MSG_BUF_LEN] = {0};
  303. uint8_t msg_hash[MSG_HASH_SZ] = {0};
  304. if(!msg3 || !g_a || !g_b || !dh_smk)
  305. {
  306. return SGX_ERROR_INVALID_PARAMETER;
  307. }
  308. maced_size = static_cast<uint32_t>(sizeof(sgx_dh_msg3_body_t)) + msg3->msg3_body.additional_prop_length;
  309. //Verify the MAC of message 3 obtained from the Session Responder
  310. se_ret = verify_cmac128((const uint8_t*)dh_smk, (const uint8_t*)&msg3->msg3_body, maced_size, msg3->cmac);
  311. if(SGX_SUCCESS != se_ret)
  312. {
  313. return se_ret;
  314. }
  315. memcpy(&temp_report, &msg3->msg3_body.report, sizeof(sgx_report_t));
  316. // Verify message 3 report
  317. se_ret = sgx_verify_report(&temp_report);
  318. if(SGX_SUCCESS != se_ret)
  319. {
  320. return se_ret;
  321. }
  322. memcpy(msg_buf,
  323. g_b,
  324. sizeof(sgx_ec256_public_t));
  325. memcpy(msg_buf + sizeof(sgx_ec256_public_t),
  326. g_a,
  327. sizeof(sgx_ec256_public_t));
  328. se_ret = sgx_sha256_msg(msg_buf,
  329. MSG_BUF_LEN,
  330. (sgx_sha256_hash_t *)msg_hash);
  331. if(SGX_SUCCESS != se_ret)
  332. {
  333. return se_ret;
  334. }
  335. // Verify message 3 report data
  336. if (0 != memcmp(msg_hash,
  337. &msg3->msg3_body.report.body.report_data,
  338. sizeof(msg_hash)))
  339. {
  340. return SGX_ERROR_MAC_MISMATCH;
  341. }
  342. return SGX_SUCCESS;
  343. }
  344. // sgx_status_t sgx_dh_init_session()
  345. // @role indicates whether the caller is a Initiator (starting the session negotiation) or a Responder (responding to the intial session negotiation request).
  346. // @sgx_dh_session is the context of the session.
  347. sgx_status_t sgx_dh_init_session(sgx_dh_session_role_t role, sgx_dh_session_t* sgx_dh_session)
  348. {
  349. sgx_internal_dh_session_t* session = (sgx_internal_dh_session_t*)sgx_dh_session;
  350. if(!session || 0 == sgx_is_within_enclave(session, sizeof(sgx_internal_dh_session_t)))
  351. {
  352. return SGX_ERROR_INVALID_PARAMETER;
  353. }
  354. if(SGX_DH_SESSION_INITIATOR != role && SGX_DH_SESSION_RESPONDER != role)
  355. {
  356. return SGX_ERROR_INVALID_PARAMETER;
  357. }
  358. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  359. if(SGX_DH_SESSION_INITIATOR == role)
  360. {
  361. session->initiator.state = SGX_DH_SESSION_INITIATOR_WAIT_M1;
  362. }
  363. else
  364. {
  365. session->responder.state = SGX_DH_SESSION_STATE_RESET;
  366. }
  367. session->role = role;
  368. return SGX_SUCCESS;
  369. }
  370. // Function sgx_dh_responder_gen_msg1 generates M1 message and makes update to the context of the session.
  371. sgx_status_t sgx_dh_responder_gen_msg1(sgx_dh_msg1_t* msg1, sgx_dh_session_t* sgx_dh_session)
  372. {
  373. sgx_status_t se_ret;
  374. sgx_internal_dh_session_t* session = (sgx_internal_dh_session_t*)sgx_dh_session;
  375. // validate session
  376. if(!session ||
  377. 0 == sgx_is_within_enclave(session, sizeof(sgx_internal_dh_session_t))) // session must be in enclave
  378. {
  379. return SGX_ERROR_INVALID_PARAMETER;
  380. }
  381. if(!msg1 ||
  382. 0 == sgx_is_within_enclave(msg1, sizeof(sgx_dh_msg1_t)) ||
  383. SGX_DH_SESSION_RESPONDER != session->role)
  384. {
  385. se_ret = SGX_ERROR_INVALID_PARAMETER;
  386. goto error;
  387. }
  388. if(SGX_DH_SESSION_STATE_RESET != session->responder.state)
  389. {
  390. se_ret = SGX_ERROR_INVALID_STATE;
  391. goto error;
  392. }
  393. se_ret = dh_generate_message1(msg1, session);
  394. if(SGX_SUCCESS != se_ret)
  395. {
  396. // return selected error to upper layer
  397. INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret)
  398. goto error;
  399. }
  400. session->responder.state = SGX_DH_SESSION_RESPONDER_WAIT_M2;
  401. return SGX_SUCCESS;
  402. error:
  403. // clear session
  404. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  405. session->responder.state = SGX_DH_SESSION_STATE_ERROR;
  406. return se_ret;
  407. }
  408. //sgx_dh_initiator_proc_msg1 processes M1 message, generates M2 message and makes update to the context of the session.
  409. sgx_status_t sgx_dh_initiator_proc_msg1(const sgx_dh_msg1_t* msg1, sgx_dh_msg2_t* msg2, sgx_dh_session_t* sgx_dh_session)
  410. {
  411. sgx_status_t se_ret;
  412. sgx_ec256_public_t pub_key;
  413. sgx_ec256_private_t priv_key;
  414. sgx_ec256_dh_shared_t shared_key;
  415. sgx_key_128bit_t dh_smk;
  416. sgx_internal_dh_session_t* session = (sgx_internal_dh_session_t*) sgx_dh_session;
  417. // validate session
  418. if(!session ||
  419. 0 == sgx_is_within_enclave(session, sizeof(sgx_internal_dh_session_t))) // session must be in enclave
  420. {
  421. return SGX_ERROR_INVALID_PARAMETER;
  422. }
  423. if( !msg1 ||
  424. !msg2 ||
  425. 0 == sgx_is_within_enclave(msg1, sizeof(sgx_dh_msg1_t)) ||
  426. 0 == sgx_is_within_enclave(msg2, sizeof(sgx_dh_msg2_t)) ||
  427. SGX_DH_SESSION_INITIATOR != session->role)
  428. {
  429. // clear secret when encounter error
  430. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  431. session->initiator.state = SGX_DH_SESSION_STATE_ERROR;
  432. return SGX_ERROR_INVALID_PARAMETER;
  433. }
  434. if(SGX_DH_SESSION_INITIATOR_WAIT_M1 != session->initiator.state)
  435. {
  436. // clear secret
  437. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  438. session->initiator.state = SGX_DH_SESSION_STATE_ERROR;
  439. return SGX_ERROR_INVALID_STATE;
  440. }
  441. //create ECC context
  442. sgx_ecc_state_handle_t ecc_state = NULL;
  443. se_ret = sgx_ecc256_open_context(&ecc_state);
  444. if(SGX_SUCCESS != se_ret)
  445. {
  446. goto error;
  447. }
  448. // generate private key and public key
  449. se_ret = sgx_ecc256_create_key_pair((sgx_ec256_private_t*)&priv_key,
  450. (sgx_ec256_public_t*)&pub_key,
  451. ecc_state);
  452. if(SGX_SUCCESS != se_ret)
  453. {
  454. goto error;
  455. }
  456. //generate shared_key
  457. se_ret = sgx_ecc256_compute_shared_dhkey(
  458. (sgx_ec256_private_t *)const_cast<sgx_ec256_private_t*>(&priv_key),
  459. (sgx_ec256_public_t *)const_cast<sgx_ec256_public_t*>(&msg1->g_a),
  460. (sgx_ec256_dh_shared_t *)&shared_key,
  461. ecc_state);
  462. // clear private key for defense in depth
  463. memset_s(&priv_key, sizeof(sgx_ec256_private_t), 0, sizeof(sgx_ec256_private_t));
  464. if(SGX_SUCCESS != se_ret)
  465. {
  466. goto error;
  467. }
  468. se_ret = derive_key(&shared_key, "SMK", (uint32_t)(sizeof("SMK") -1), &dh_smk);
  469. if(SGX_SUCCESS != se_ret)
  470. {
  471. goto error;
  472. }
  473. se_ret = dh_generate_message2(msg1, &pub_key, &dh_smk, msg2);
  474. if(SGX_SUCCESS != se_ret)
  475. {
  476. goto error;
  477. }
  478. memcpy(&session->initiator.pub_key, &pub_key, sizeof(sgx_ec256_public_t));
  479. memcpy(&session->initiator.peer_pub_key, &msg1->g_a, sizeof(sgx_ec256_public_t));
  480. memcpy(&session->initiator.smk_aek, &dh_smk, sizeof(sgx_key_128bit_t));
  481. memcpy(&session->initiator.shared_key, &shared_key, sizeof(sgx_ec256_dh_shared_t));
  482. // clear shared key and SMK
  483. memset_s(&shared_key, sizeof(sgx_ec256_dh_shared_t), 0, sizeof(sgx_ec256_dh_shared_t));
  484. memset_s(&dh_smk, sizeof(sgx_key_128bit_t), 0, sizeof(sgx_key_128bit_t));
  485. if(SGX_SUCCESS != sgx_ecc256_close_context(ecc_state))
  486. {
  487. // clear session
  488. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  489. // set error state
  490. session->initiator.state = SGX_DH_SESSION_STATE_ERROR;
  491. return SGX_ERROR_UNEXPECTED;
  492. }
  493. session->initiator.state = SGX_DH_SESSION_INITIATOR_WAIT_M3;
  494. return SGX_SUCCESS;
  495. error:
  496. sgx_ecc256_close_context(ecc_state);
  497. // clear shared key and SMK
  498. memset_s(&shared_key, sizeof(sgx_ec256_dh_shared_t), 0, sizeof(sgx_ec256_dh_shared_t));
  499. memset_s(&dh_smk, sizeof(sgx_key_128bit_t), 0, sizeof(sgx_key_128bit_t));
  500. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  501. session->initiator.state = SGX_DH_SESSION_STATE_ERROR;
  502. // return selected error to upper layer
  503. INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret)
  504. return se_ret;
  505. }
  506. //sgx_dh_responder_proc_msg2 processes M2 message, generates M3 message, and returns the session key AEK.
  507. sgx_status_t sgx_dh_responder_proc_msg2(const sgx_dh_msg2_t* msg2,
  508. sgx_dh_msg3_t* msg3,
  509. sgx_dh_session_t* sgx_dh_session,
  510. sgx_key_128bit_t* aek,
  511. sgx_dh_session_enclave_identity_t* initiator_identity)
  512. {
  513. sgx_status_t se_ret;
  514. sgx_ec256_dh_shared_t shared_key;
  515. sgx_key_128bit_t dh_smk;
  516. sgx_internal_dh_session_t* session = (sgx_internal_dh_session_t*)sgx_dh_session;
  517. // validate session
  518. if(!session ||
  519. 0 == sgx_is_within_enclave(session, sizeof(sgx_internal_dh_session_t))) // session must be in enclave
  520. {
  521. return SGX_ERROR_INVALID_PARAMETER;
  522. }
  523. if(!msg3 ||
  524. msg3->msg3_body.additional_prop_length > (UINT_MAX - sizeof(sgx_dh_msg3_t)) || // check msg3 length overflow
  525. 0 == sgx_is_within_enclave(msg3, (sizeof(sgx_dh_msg3_t)+msg3->msg3_body.additional_prop_length)) || // must be in enclave
  526. !msg2 ||
  527. 0 == sgx_is_within_enclave(msg2, sizeof(sgx_dh_msg2_t)) || // must be in enclave
  528. !aek ||
  529. 0 == sgx_is_within_enclave(aek, sizeof(sgx_key_128bit_t)) || // must be in enclave
  530. !initiator_identity ||
  531. 0 == sgx_is_within_enclave(initiator_identity, sizeof(sgx_dh_session_enclave_identity_t)) || // must be in enclave
  532. SGX_DH_SESSION_RESPONDER != session->role)
  533. {
  534. // clear secret when encounter error
  535. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  536. session->responder.state = SGX_DH_SESSION_STATE_ERROR;
  537. return SGX_ERROR_INVALID_PARAMETER;
  538. }
  539. if(SGX_DH_SESSION_RESPONDER_WAIT_M2 != session->responder.state) // protocol state must be SGX_DH_SESSION_RESPONDER_WAIT_M2
  540. {
  541. // clear secret
  542. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  543. session->responder.state = SGX_DH_SESSION_STATE_ERROR;
  544. return SGX_ERROR_INVALID_STATE;
  545. }
  546. //create ECC context, and the ECC parameter is
  547. //NIST standard P-256 elliptic curve.
  548. sgx_ecc_state_handle_t ecc_state = NULL;
  549. se_ret = sgx_ecc256_open_context(&ecc_state);
  550. if(SGX_SUCCESS != se_ret)
  551. {
  552. goto error;
  553. }
  554. //generate shared key, which should be identical with enclave side,
  555. //from PSE private key and enclave public key
  556. se_ret = sgx_ecc256_compute_shared_dhkey((sgx_ec256_private_t *)&session->responder.prv_key,
  557. (sgx_ec256_public_t *)const_cast<sgx_ec256_public_t*>(&msg2->g_b),
  558. (sgx_ec256_dh_shared_t *)&shared_key,
  559. ecc_state);
  560. // For defense-in-depth purpose, responder clears its private key from its enclave memory, as it's not needed anymore.
  561. memset_s(&session->responder.prv_key, sizeof(sgx_ec256_private_t), 0, sizeof(sgx_ec256_private_t));
  562. if(se_ret != SGX_SUCCESS)
  563. {
  564. goto error;
  565. }
  566. //derive keys from session shared key
  567. se_ret = derive_key(&shared_key, "SMK", (uint32_t)(sizeof("SMK") -1), &dh_smk);
  568. if(se_ret != SGX_SUCCESS)
  569. {
  570. goto error;
  571. }
  572. // Verify message 2 from Session Initiator and also Session Initiator's identity
  573. se_ret = dh_verify_message2(msg2, &session->responder.pub_key, &dh_smk);
  574. if(SGX_SUCCESS != se_ret)
  575. {
  576. goto error;
  577. }
  578. initiator_identity->isv_svn = msg2->report.body.isv_svn;
  579. initiator_identity->isv_prod_id = msg2->report.body.isv_prod_id;
  580. memcpy(&initiator_identity->attributes, &msg2->report.body.attributes, sizeof(sgx_attributes_t));
  581. memcpy(&initiator_identity->mr_signer, &msg2->report.body.mr_signer, sizeof(sgx_measurement_t));
  582. memcpy(&initiator_identity->mr_enclave, &msg2->report.body.mr_enclave, sizeof(sgx_measurement_t));
  583. // Generate message 3 to send back to initiator
  584. se_ret = dh_generate_message3(msg2,
  585. &session->responder.pub_key,
  586. &dh_smk,
  587. msg3,
  588. msg3->msg3_body.additional_prop_length);
  589. if(SGX_SUCCESS != se_ret)
  590. {
  591. goto error;
  592. }
  593. // derive session key
  594. se_ret = derive_key(&shared_key, "AEK", (uint32_t)(sizeof("AEK") -1), aek);
  595. if(se_ret != SGX_SUCCESS)
  596. {
  597. goto error;
  598. }
  599. // clear secret
  600. memset_s(&shared_key, sizeof(sgx_ec256_dh_shared_t), 0, sizeof(sgx_ec256_dh_shared_t));
  601. memset_s(&dh_smk, sizeof(sgx_key_128bit_t), 0, sizeof(sgx_key_128bit_t));
  602. // clear session
  603. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  604. se_ret = sgx_ecc256_close_context(ecc_state);
  605. if(SGX_SUCCESS != se_ret)
  606. {
  607. // set error state
  608. session->responder.state = SGX_DH_SESSION_STATE_ERROR;
  609. return SGX_ERROR_UNEXPECTED;
  610. }
  611. // set state
  612. session->responder.state = SGX_DH_SESSION_ACTIVE;
  613. return SGX_SUCCESS;
  614. error:
  615. sgx_ecc256_close_context(ecc_state);
  616. // clear secret
  617. memset_s(&shared_key, sizeof(sgx_ec256_dh_shared_t), 0, sizeof(sgx_ec256_dh_shared_t));
  618. memset_s(&dh_smk, sizeof(sgx_key_128bit_t), 0, sizeof(sgx_key_128bit_t));
  619. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  620. // set error state
  621. session->responder.state = SGX_DH_SESSION_STATE_ERROR;
  622. // return selected error to upper layer
  623. if (se_ret != SGX_ERROR_OUT_OF_MEMORY &&
  624. se_ret != SGX_ERROR_KDF_MISMATCH)
  625. {
  626. se_ret = SGX_ERROR_UNEXPECTED;
  627. }
  628. return se_ret;
  629. }
  630. //sgx_dh_initiator_proc_msg3 processes M3 message, and returns the session key AEK.
  631. sgx_status_t sgx_dh_initiator_proc_msg3(const sgx_dh_msg3_t* msg3,
  632. sgx_dh_session_t* sgx_dh_session,
  633. sgx_key_128bit_t* aek,
  634. sgx_dh_session_enclave_identity_t* responder_identity)
  635. {
  636. sgx_status_t se_ret;
  637. sgx_internal_dh_session_t* session = (sgx_internal_dh_session_t*)sgx_dh_session;
  638. // validate session
  639. if(!session ||
  640. 0 == sgx_is_within_enclave(session, sizeof(sgx_internal_dh_session_t))) // session must be in enclave
  641. {
  642. return SGX_ERROR_INVALID_PARAMETER;
  643. }
  644. if(!msg3 ||
  645. msg3->msg3_body.additional_prop_length > (UINT_MAX - sizeof(sgx_dh_msg3_t)) || // check msg3 length overflow
  646. 0 == sgx_is_within_enclave(msg3, (sizeof(sgx_dh_msg3_t)+msg3->msg3_body.additional_prop_length)) || // msg3 buffer must be in enclave
  647. !aek ||
  648. 0 == sgx_is_within_enclave(aek, sizeof(sgx_key_128bit_t)) || // aek buffer must be in enclave
  649. !responder_identity ||
  650. 0 == sgx_is_within_enclave(responder_identity, sizeof(sgx_dh_session_enclave_identity_t)) || // responder_identity buffer must be in enclave
  651. SGX_DH_SESSION_INITIATOR != session->role) // role must be SGX_DH_SESSION_INITIATOR
  652. {
  653. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  654. session->initiator.state = SGX_DH_SESSION_STATE_ERROR;
  655. return SGX_ERROR_INVALID_PARAMETER;
  656. }
  657. if(SGX_DH_SESSION_INITIATOR_WAIT_M3 != session->initiator.state) // protocol state must be SGX_DH_SESSION_INITIATOR_WAIT_M3
  658. {
  659. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  660. session->initiator.state = SGX_DH_SESSION_STATE_ERROR;
  661. return SGX_ERROR_INVALID_STATE;
  662. }
  663. se_ret = dh_verify_message3(msg3,
  664. &session->initiator.peer_pub_key,
  665. &session->initiator.pub_key,
  666. &session->initiator.smk_aek);
  667. if(SGX_SUCCESS != se_ret)
  668. {
  669. goto error;
  670. }
  671. // derive AEK
  672. se_ret = derive_key(&session->initiator.shared_key, "AEK", (uint32_t)(sizeof("AEK") -1), aek);
  673. if(SGX_SUCCESS != se_ret)
  674. {
  675. goto error;
  676. }
  677. // clear session
  678. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  679. session->initiator.state = SGX_DH_SESSION_ACTIVE;
  680. // copy the common fields between REPORT and the responder enclave identity
  681. memcpy(responder_identity, &msg3->msg3_body.report.body, sizeof(sgx_dh_session_enclave_identity_t));
  682. return SGX_SUCCESS;
  683. error:
  684. memset_s(session, sizeof(sgx_internal_dh_session_t), 0, sizeof(sgx_internal_dh_session_t));
  685. session->initiator.state = SGX_DH_SESSION_STATE_ERROR;
  686. INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret)
  687. return se_ret;
  688. }