enclave_framework.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. #include <pal_linux.h>
  4. #include <pal_internal.h>
  5. #include <pal_debug.h>
  6. #include <pal_security.h>
  7. #include <api.h>
  8. #include <linux_list.h>
  9. #include "enclave_pages.h"
  10. struct pal_enclave_state pal_enclave_state;
  11. void * enclave_base, * enclave_top;
  12. struct pal_enclave_config pal_enclave_config;
  13. int sgx_is_within_enclave (const void * addr, size_t size)
  14. {
  15. return (addr >= enclave_base &&
  16. addr + size <= enclave_top) ? 1 : 0;
  17. }
  18. void * sgx_ocalloc (size_t size)
  19. {
  20. struct enclave_tls * tls = ENCLAVE_TLS_SELF();
  21. return (tls->urts_stack -= size);
  22. }
  23. void sgx_ocfree (void)
  24. {
  25. struct enclave_tls * tls = ENCLAVE_TLS_SELF();
  26. tls->urts_stack = tls->urts_initial_stack;
  27. }
  28. int sgx_get_report (sgx_arch_hash_t * mrenclave,
  29. sgx_arch_attributes_t * attributes,
  30. void * enclave_data,
  31. sgx_arch_report_t * report)
  32. {
  33. sgx_arch_targetinfo_t targetinfo;
  34. memset(&targetinfo, 0, sizeof(sgx_arch_targetinfo_t));
  35. memcpy(targetinfo.mrenclave, mrenclave, sizeof(sgx_arch_hash_t));
  36. memcpy(&targetinfo.attributes, attributes, sizeof(sgx_arch_attributes_t));
  37. struct pal_enclave_state state;
  38. memcpy(&state, &pal_enclave_state, sizeof(struct pal_enclave_state));
  39. memcpy(&state.data, enclave_data, PAL_ATTESTATION_DATA_SIZE);
  40. int ret = sgx_report(&targetinfo, &state, report);
  41. if (ret)
  42. return -PAL_ERROR_DENIED;
  43. SGX_DBG(DBG_S, "Generated report:\n");
  44. SGX_DBG(DBG_S, " cpusvn: %08x %08x\n", report->cpusvn[0],
  45. report->cpusvn[1]);
  46. SGX_DBG(DBG_S, " mrenclave: %s\n", hex2str(report->mrenclave));
  47. SGX_DBG(DBG_S, " mrsigner: %s\n", hex2str(report->mrsigner));
  48. SGX_DBG(DBG_S, " attributes.flags: %016lx\n", report->attributes.flags);
  49. SGX_DBG(DBG_S, " sttributes.xfrm: %016lx\n", report->attributes.xfrm);
  50. SGX_DBG(DBG_S, " isvprodid: %02x\n", report->isvprodid);
  51. SGX_DBG(DBG_S, " isvsvn: %02x\n", report->isvsvn);
  52. SGX_DBG(DBG_S, " keyid: %s\n", hex2str(report->keyid));
  53. SGX_DBG(DBG_S, " mac: %s\n", hex2str(report->mac));
  54. return 0;
  55. }
  56. #include "crypto/cmac.h"
  57. int sgx_verify_report (sgx_arch_report_t * report)
  58. {
  59. sgx_arch_keyrequest_t keyrequest;
  60. memset(&keyrequest, 0, sizeof(sgx_arch_keyrequest_t));
  61. keyrequest.keyname = REPORT_KEY;
  62. memcpy(keyrequest.keyid, report->keyid, sizeof(keyrequest.keyid));
  63. sgx_arch_key128_t key;
  64. int ret = sgx_getkey(&keyrequest, &key);
  65. if (ret) {
  66. SGX_DBG(DBG_S, "Can't get report key\n");
  67. return -PAL_ERROR_DENIED;
  68. }
  69. SGX_DBG(DBG_S, "Get report key for verification: %s\n", hex2str(key));
  70. sgx_arch_mac_t mac;
  71. AES_CMAC((void *) &key, (void *) report, SGX_REPORT_SIGNED_SIZE, mac);
  72. SGX_DBG(DBG_S, "Generated mac: %s\n", hex2str(mac));
  73. return memcmp(mac, report->mac, sizeof(sgx_arch_mac_t)) ? 1 : 0;
  74. }
  75. struct trusted_file {
  76. struct list_head list;
  77. int64_t index;
  78. uint64_t size;
  79. int uri_len;
  80. char uri[URI_MAX];
  81. sgx_checksum_t checksum, * stubs;
  82. };
  83. static LIST_HEAD(trusted_file_list);
  84. static struct spinlock trusted_file_lock = LOCK_INIT;
  85. static int trusted_file_indexes = 0;
  86. #include <crypto/sha256.h>
  87. int load_trusted_file (PAL_HANDLE file, sgx_checksum_t ** stubptr,
  88. uint64_t * sizeptr)
  89. {
  90. struct trusted_file * tf = NULL, * tmp;
  91. char uri[URI_MAX];
  92. int ret, fd = HANDLE_HDR(file)->fds[0], uri_len;
  93. if (!(HANDLE_HDR(file)->flags & RFD(0)))
  94. return -PAL_ERROR_DENIED;
  95. uri_len = _DkStreamGetName(file, uri, URI_MAX);
  96. if (uri_len < 0)
  97. return uri_len;
  98. _DkSpinLock(&trusted_file_lock);
  99. list_for_each_entry(tmp, &trusted_file_list, list)
  100. if (tmp->stubs) {
  101. /* trusted files: must be exactly the same URI */
  102. if (tmp->uri_len == uri_len && !memcmp(tmp->uri, uri, uri_len + 1)) {
  103. tf = tmp;
  104. break;
  105. }
  106. } else {
  107. /* allowed files: must be a subfolder or file */
  108. if (tmp->uri_len <= uri_len &&
  109. !memcmp(tmp->uri, uri, tmp->uri_len) &&
  110. (!uri[tmp->uri_len] || uri[tmp->uri_len] == '/')) {
  111. tf = tmp;
  112. break;
  113. }
  114. }
  115. _DkSpinUnlock(&trusted_file_lock);
  116. if (!tf)
  117. return -PAL_ERROR_DENIED;
  118. if (tf->index < 0)
  119. return tf->index;
  120. if (tf->index && tf->stubs) {
  121. *stubptr = tf->stubs;
  122. *sizeptr = tf->size;
  123. return 0;
  124. }
  125. if (!tf->index) {
  126. *stubptr = NULL;
  127. PAL_STREAM_ATTR attr;
  128. ret = _DkStreamAttributesQuery(uri, &attr);
  129. if (!ret)
  130. *sizeptr = attr.pending_size;
  131. else
  132. *sizeptr = 0;
  133. return 0;
  134. }
  135. int nstubs = tf->size / TRUSTED_STUB_SIZE +
  136. (tf->size % TRUSTED_STUB_SIZE ? 1 : 0);
  137. sgx_checksum_t * stubs = malloc(sizeof(sgx_checksum_t) * nstubs);
  138. if (!tf)
  139. return -PAL_ERROR_NOMEM;
  140. uint64_t offset = 0;
  141. SHA256 sha;
  142. void * umem;
  143. ret = SHA256Init(&sha);
  144. if (ret < 0)
  145. goto failed;
  146. for (; offset < tf->size ; offset += TRUSTED_STUB_SIZE) {
  147. uint64_t mapping_size = tf->size - offset;
  148. if (mapping_size > TRUSTED_STUB_SIZE)
  149. mapping_size = TRUSTED_STUB_SIZE;
  150. ret = ocall_map_untrusted(fd, offset, mapping_size, PROT_READ, &umem);
  151. if (ret < 0)
  152. goto unmap;
  153. /* calculate stub checksum */
  154. SHA256 stub_sha;
  155. ret = SHA256Init(&stub_sha);
  156. if (ret < 0)
  157. goto unmap;
  158. ret = SHA256Update(&stub_sha, umem, mapping_size);
  159. if (ret < 0)
  160. goto unmap;
  161. ret = SHA256Final(&stub_sha,
  162. (uint8_t *) stubs[offset / TRUSTED_STUB_SIZE].bytes);
  163. if (ret < 0)
  164. goto unmap;
  165. /* update the file checksum */
  166. ret = SHA256Update(&sha, umem, mapping_size);
  167. unmap:
  168. ocall_unmap_untrusted(umem, mapping_size);
  169. if (ret < 0)
  170. goto failed;
  171. }
  172. sgx_checksum_t hash;
  173. ret = SHA256Final(&sha, (uint8_t *) hash.bytes);
  174. if (ret < 0)
  175. goto failed;
  176. if (memcmp(&hash, &tf->checksum, sizeof(sgx_checksum_t))) {
  177. ret = -PAL_ERROR_DENIED;
  178. goto failed;
  179. }
  180. _DkSpinLock(&trusted_file_lock);
  181. if (tf->stubs || tf->index == -PAL_ERROR_DENIED) {
  182. free(stubs);
  183. *stubptr = tf->stubs;
  184. } else {
  185. *stubptr = tf->stubs = stubs;
  186. }
  187. *sizeptr = tf->size;
  188. ret = tf->index;
  189. _DkSpinUnlock(&trusted_file_lock);
  190. return ret;
  191. failed:
  192. free(stubs);
  193. _DkSpinLock(&trusted_file_lock);
  194. if (tf->stubs) {
  195. *stubptr = tf->stubs;
  196. *sizeptr = tf->size;
  197. ret = tf->index;
  198. } else {
  199. tf->index = -PAL_ERROR_DENIED;
  200. }
  201. _DkSpinUnlock(&trusted_file_lock);
  202. return ret;
  203. }
  204. int verify_trusted_file (const char * uri, void * mem,
  205. unsigned int offset, unsigned int size,
  206. sgx_checksum_t * stubs,
  207. unsigned int total_size)
  208. {
  209. unsigned long checking = offset;
  210. sgx_checksum_t * s = stubs + checking / TRUSTED_STUB_SIZE;
  211. char checksum_text[sizeof(sgx_checksum_t) * 2 + 1] = "\0";
  212. int ret;
  213. for (; checking < offset + size ; checking += TRUSTED_STUB_SIZE, s++) {
  214. unsigned long checking_size = TRUSTED_STUB_SIZE;
  215. if (checking_size > total_size - checking)
  216. checking_size = total_size - checking;
  217. /* calculate stub checksum */
  218. sgx_checksum_t checksum;
  219. SHA256 stub_sha;
  220. ret = SHA256Init(&stub_sha);
  221. if (ret < 0)
  222. return -PAL_ERROR_DENIED;
  223. ret = SHA256Update(&stub_sha, mem + checking - offset,
  224. checking_size);
  225. if (ret < 0)
  226. return -PAL_ERROR_DENIED;
  227. ret = SHA256Final(&stub_sha, (uint8_t *) checksum.bytes);
  228. if (ret < 0)
  229. return -PAL_ERROR_DENIED;
  230. for (int i = 0 ; i < sizeof(sgx_checksum_t) ; i++)
  231. snprintf(checksum_text + i * 2, 3, "%02x",
  232. checksum.bytes[i]);
  233. if (memcmp(s, &checksum, sizeof(sgx_checksum_t))) {
  234. SGX_DBG(DBG_E, "Accesing file:%s is denied. "
  235. "Does not match with its checksum.\n", uri);
  236. return -PAL_ERROR_DENIED;
  237. }
  238. }
  239. return 0;
  240. }
  241. static int register_trusted_file (const char * uri, const char * checksum_str)
  242. {
  243. struct trusted_file * tf = NULL, * new;
  244. int uri_len = strlen(uri);
  245. int ret;
  246. _DkSpinLock(&trusted_file_lock);
  247. list_for_each_entry(tf, &trusted_file_list, list) {
  248. if (tf->uri_len == uri_len && !memcmp(tf->uri, uri, uri_len)) {
  249. _DkSpinUnlock(&trusted_file_lock);
  250. return 0;
  251. }
  252. }
  253. _DkSpinUnlock(&trusted_file_lock);
  254. new = malloc(sizeof(struct trusted_file));
  255. if (!new)
  256. return -PAL_ERROR_NOMEM;
  257. INIT_LIST_HEAD(&new->list);
  258. new->uri_len = uri_len;
  259. memcpy(new->uri, uri, uri_len + 1);
  260. new->size = 0;
  261. new->stubs = NULL;
  262. if (checksum_str) {
  263. PAL_STREAM_ATTR attr;
  264. ret = _DkStreamAttributesQuery(uri, &attr);
  265. if (!ret)
  266. new->size = attr.pending_size;
  267. char checksum_text[sizeof(sgx_checksum_t) * 2 + 1] = "\0";
  268. int nbytes = 0;
  269. for (; nbytes < sizeof(sgx_checksum_t) ; nbytes++) {
  270. char byte1 = checksum_str[nbytes * 2];
  271. char byte2 = checksum_str[nbytes * 2 + 1];
  272. unsigned char val = 0;
  273. if (byte1 == 0 || byte2 == 0) {
  274. break;
  275. }
  276. if (!(byte1 >= '0' && byte1 <= '9') &&
  277. !(byte1 >= 'a' && byte1 <= 'f')) {
  278. break;
  279. }
  280. if (!(byte2 >= '0' && byte2 <= '9') &&
  281. !(byte2 >= 'a' && byte2 <= 'f')) {
  282. break;
  283. }
  284. if (byte1 >= '0' && byte1 <= '9')
  285. val = byte1 - '0';
  286. if (byte1 >= 'a' && byte1 <= 'f')
  287. val = byte1 - 'a' + 10;
  288. val *= 16;
  289. if (byte2 >= '0' && byte2 <= '9')
  290. val += byte2 - '0';
  291. if (byte2 >= 'a' && byte2 <= 'f')
  292. val += byte2 - 'a' + 10;
  293. new->checksum.bytes[nbytes] = val;
  294. snprintf(checksum_text + nbytes * 2, 3, "%02x", val);
  295. }
  296. if (nbytes < sizeof(sgx_checksum_t)) {
  297. free(new);
  298. return -PAL_ERROR_INVAL;
  299. }
  300. new->index = (++trusted_file_indexes);
  301. SGX_DBG(DBG_S, "trusted: [%d] %s %s\n", new->index,
  302. checksum_text, new->uri);
  303. } else {
  304. memset(&new->checksum, 0, sizeof(sgx_checksum_t));
  305. new->index = 0;
  306. SGX_DBG(DBG_S, "allowed: %s\n", new->uri);
  307. }
  308. _DkSpinLock(&trusted_file_lock);
  309. list_for_each_entry(tf, &trusted_file_list, list) {
  310. if (tf->uri_len == uri_len && !memcmp(tf->uri, uri, uri_len)) {
  311. _DkSpinUnlock(&trusted_file_lock);
  312. free(new);
  313. return 0;
  314. }
  315. }
  316. list_add_tail(&new->list, &trusted_file_list);
  317. _DkSpinUnlock(&trusted_file_lock);
  318. return 0;
  319. }
  320. static int init_trusted_file (const char * key, const char * uri)
  321. {
  322. char cskey[URI_MAX], * tmp;
  323. char checksum[URI_MAX];
  324. tmp = strcpy_static(cskey, "sgx.trusted_checksum.", URI_MAX);
  325. memcpy(tmp, key, strlen(key) + 1);
  326. int len = get_config(pal_state.root_config, cskey, checksum, CONFIG_MAX);
  327. if (len < 0)
  328. return 0;
  329. return register_trusted_file(uri, checksum);
  330. }
  331. int init_trusted_files (void)
  332. {
  333. char cfgbuf[CONFIG_MAX];
  334. int ret;
  335. if (pal_sec.exec_fd != PAL_IDX_POISON) {
  336. ret = init_trusted_file("exec", pal_sec.exec_name);
  337. if (ret < 0)
  338. return ret;
  339. }
  340. int len = get_config(pal_state.root_config, "loader.preload",
  341. cfgbuf, CONFIG_MAX);
  342. if (len) {
  343. int npreload = 0;
  344. char key[10];
  345. const char * start, * end;
  346. for (start = cfgbuf ; start < cfgbuf + len ; start = end + 1) {
  347. for (end = start ; end < cfgbuf + len && *end && *end != ',' ; end++);
  348. if (end > start) {
  349. char uri[end - start + 1];
  350. memcpy(uri, start, end - start);
  351. uri[end - start] = 0;
  352. snprintf(key, 10, "preload%d", npreload++);
  353. ret = init_trusted_file(key, uri);
  354. if (ret < 0)
  355. return ret;
  356. }
  357. }
  358. }
  359. int nuris = get_config_entries(pal_state.root_config, "sgx.trusted_files",
  360. cfgbuf, CONFIG_MAX);
  361. if (nuris) {
  362. char key[CONFIG_MAX], uri[CONFIG_MAX];
  363. char * k = cfgbuf, * tmp;
  364. tmp = strcpy_static(key, "sgx.trusted_files.", CONFIG_MAX);
  365. for (int i = 0 ; i < nuris ; i++) {
  366. len = strlen(k);
  367. memcpy(tmp, k, len + 1);
  368. k += len + 1;
  369. len = get_config(pal_state.root_config, key, uri, CONFIG_MAX);
  370. if (len > 0) {
  371. ret = init_trusted_file(key + 18, uri);
  372. if (ret < 0)
  373. return ret;
  374. }
  375. }
  376. }
  377. nuris = get_config_entries(pal_state.root_config, "sgx.allowed_files",
  378. cfgbuf, CONFIG_MAX);
  379. if (nuris > 0) {
  380. char key[CONFIG_MAX], uri[CONFIG_MAX];
  381. char * k = cfgbuf, * tmp;
  382. tmp = strcpy_static(key, "sgx.allowed_files.", CONFIG_MAX);
  383. for (int i = 0 ; i < nuris ; i++) {
  384. len = strlen(k);
  385. memcpy(tmp, k, len + 1);
  386. k += len + 1;
  387. len = get_config(pal_state.root_config, key, uri, CONFIG_MAX);
  388. if (len > 0)
  389. register_trusted_file(uri, NULL);
  390. }
  391. }
  392. return 0;
  393. }
  394. int init_trusted_children (void)
  395. {
  396. char cfgbuf[CONFIG_MAX];
  397. char key[CONFIG_MAX], mrkey[CONFIG_MAX];
  398. char uri[CONFIG_MAX], mrenclave[CONFIG_MAX];
  399. char * tmp1 = strcpy_static(key, "sgx.trusted_children.", CONFIG_MAX);
  400. char * tmp2 = strcpy_static(mrkey, "sgx.trusted_mrenclave.", CONFIG_MAX);
  401. int nuris = get_config_entries(pal_state.root_config,
  402. "sgx.trusted_mrenclave", cfgbuf, CONFIG_MAX);
  403. if (nuris > 0) {
  404. char * k = cfgbuf;
  405. for (int i = 0 ; i < nuris ; i++) {
  406. int len = strlen(k);
  407. memcpy(tmp1, k, len + 1);
  408. memcpy(tmp2, k, len + 1);
  409. k += len + 1;
  410. int ret = get_config(pal_state.root_config, key, uri, CONFIG_MAX);
  411. if (ret < 0)
  412. continue;
  413. ret = get_config(pal_state.root_config, mrkey, mrenclave,
  414. CONFIG_MAX);
  415. if (ret > 0)
  416. register_trusted_child(uri, mrenclave);
  417. }
  418. }
  419. return 0;
  420. }
  421. #include "crypto/dh.h"
  422. static struct {
  423. uint8_t p[128], q[20], g[128];
  424. } dh_param = {
  425. {
  426. 0xfd, 0x7f, 0x53, 0x81, 0x1d, 0x75, 0x12, 0x29,
  427. 0x52, 0xdf, 0x4a, 0x9c, 0x2e, 0xec, 0xe4, 0xe7,
  428. 0xf6, 0x11, 0xb7, 0x52, 0x3c, 0xef, 0x44, 0x00,
  429. 0xc3, 0x1e, 0x3f, 0x80, 0xb6, 0x51, 0x26, 0x69,
  430. 0x45, 0x5d, 0x40, 0x22, 0x51, 0xfb, 0x59, 0x3d,
  431. 0x8d, 0x58, 0xfa, 0xbf, 0xc5, 0xf5, 0xba, 0x30,
  432. 0xf6, 0xcb, 0x9b, 0x55, 0x6c, 0xd7, 0x81, 0x3b,
  433. 0x80, 0x1d, 0x34, 0x6f, 0xf2, 0x66, 0x60, 0xb7,
  434. 0x6b, 0x99, 0x50, 0xa5, 0xa4, 0x9f, 0x9f, 0xe8,
  435. 0x04, 0x7b, 0x10, 0x22, 0xc2, 0x4f, 0xbb, 0xa9,
  436. 0xd7, 0xfe, 0xb7, 0xc6, 0x1b, 0xf8, 0x3b, 0x57,
  437. 0xe7, 0xc6, 0xa8, 0xa6, 0x15, 0x0f, 0x04, 0xfb,
  438. 0x83, 0xf6, 0xd3, 0xc5, 0x1e, 0xc3, 0x02, 0x35,
  439. 0x54, 0x13, 0x5a, 0x16, 0x91, 0x32, 0xf6, 0x75,
  440. 0xf3, 0xae, 0x2b, 0x61, 0xd7, 0x2a, 0xef, 0xf2,
  441. 0x22, 0x03, 0x19, 0x9d, 0xd1, 0x48, 0x01, 0xc7,
  442. },
  443. {
  444. 0x97, 0x60, 0x50, 0x8f, 0x15, 0x23, 0x0b, 0xcc,
  445. 0xb2, 0x92, 0xb9, 0x82, 0xa2, 0xeb, 0x84, 0x0b,
  446. 0xf0, 0x58, 0x1c, 0xf5,
  447. },
  448. {
  449. 0xf7, 0xe1, 0xa0, 0x85, 0xd6, 0x9b, 0x3d, 0xde,
  450. 0xcb, 0xbc, 0xab, 0x5c, 0x36, 0xb8, 0x57, 0xb9,
  451. 0x79, 0x94, 0xaf, 0xbb, 0xfa, 0x3a, 0xea, 0x82,
  452. 0xf9, 0x57, 0x4c, 0x0b, 0x3d, 0x07, 0x82, 0x67,
  453. 0x51, 0x59, 0x57, 0x8e, 0xba, 0xd4, 0x59, 0x4f,
  454. 0xe6, 0x71, 0x07, 0x10, 0x81, 0x80, 0xb4, 0x49,
  455. 0x16, 0x71, 0x23, 0xe8, 0x4c, 0x28, 0x16, 0x13,
  456. 0xb7, 0xcf, 0x09, 0x32, 0x8c, 0xc8, 0xa6, 0xe1,
  457. 0x3c, 0x16, 0x7a, 0x8b, 0x54, 0x7c, 0x8d, 0x28,
  458. 0xe0, 0xa3, 0xae, 0x1e, 0x2b, 0xb3, 0xa6, 0x75,
  459. 0x91, 0x6e, 0xa3, 0x7f, 0x0b, 0xfa, 0x21, 0x35,
  460. 0x62, 0xf1, 0xfb, 0x62, 0x7a, 0x01, 0x24, 0x3b,
  461. 0xcc, 0xa4, 0xf1, 0xbe, 0xa8, 0x51, 0x90, 0x89,
  462. 0xa8, 0x83, 0xdf, 0xe1, 0x5a, 0xe5, 0x9f, 0x06,
  463. 0x92, 0x8b, 0x66, 0x5e, 0x80, 0x7b, 0x55, 0x25,
  464. 0x64, 0x01, 0x4c, 0x3b, 0xfe, 0xcf, 0x49, 0x2a,
  465. },
  466. };
  467. void test_dh (void)
  468. {
  469. int ret;
  470. DhKey key1, key2;
  471. uint32_t privsz1, privsz2, pubsz1, pubsz2, agreesz1, agreesz2;
  472. unsigned char priv1[128], pub1[128], priv2[128], pub2[128], agree1[128],
  473. agree2[128];
  474. InitDhKey(&key1);
  475. InitDhKey(&key2);
  476. ret = DhSetKey(&key1, dh_param.p, sizeof(dh_param.p), dh_param.g,
  477. sizeof(dh_param.g));
  478. if (ret < 0) {
  479. SGX_DBG(DBG_S, "DhSetKey for key 1 failed: %d\n", ret);
  480. return;
  481. }
  482. ret = DhSetKey(&key2, dh_param.p, sizeof(dh_param.p), dh_param.g,
  483. sizeof(dh_param.g));
  484. if (ret < 0) {
  485. SGX_DBG(DBG_S, "DhSetKey for key 2 failed: %d\n", ret);
  486. return;
  487. }
  488. ret = DhGenerateKeyPair(&key1, priv1, &privsz1, pub1, &pubsz1);
  489. if (ret < 0) {
  490. SGX_DBG(DBG_S, "DhGenerateKeyPair for key 1 failed: %d\n", ret);
  491. return;
  492. }
  493. ret = DhGenerateKeyPair(&key2, priv2, &privsz2, pub2, &pubsz2);
  494. if (ret < 0) {
  495. SGX_DBG(DBG_S, "DhGenerateKeyPair for key 2 failed: %d\n", ret);
  496. return;
  497. }
  498. ret = DhAgree(&key1, agree1, &agreesz1, priv1, privsz1, pub2, pubsz2);
  499. if (ret < 0) {
  500. SGX_DBG(DBG_S, "DhAgree for key 1 failed: %d\n", ret);
  501. return;
  502. }
  503. ret = DhAgree(&key2, agree2, &agreesz2, priv2, privsz2, pub1, pubsz1);
  504. if (ret < 0) {
  505. SGX_DBG(DBG_S, "DhAgree for key 1 failed: %d\n", ret);
  506. return;
  507. }
  508. FreeDhKey(&key1);
  509. FreeDhKey(&key2);
  510. SGX_DBG(DBG_S, "key exchange(side A): %s (%d)\n", __hex2str(agree1, agreesz1),
  511. agreesz1);
  512. SGX_DBG(DBG_S, "key exchange(side B): %s (%d)\n", __hex2str(agree2, agreesz2),
  513. agreesz2);
  514. }
  515. #include "crypto/rsa.h"
  516. #define RSA_KEY_SIZE 2048
  517. #define RSA_E 3
  518. int init_enclave (void)
  519. {
  520. int ret;
  521. RSAKey *rsa = malloc(sizeof(RSAKey));
  522. InitRSAKey(rsa);
  523. ret = MakeRSAKey(rsa, RSA_KEY_SIZE, RSA_E);
  524. if (ret < 0) {
  525. SGX_DBG(DBG_S, "MakeRSAKey failed: %d\n", ret);
  526. return ret;
  527. }
  528. uint32_t nsz = RSA_KEY_SIZE / 8, esz = 1;
  529. uint8_t n[nsz], e[esz];
  530. ret = RSAFlattenPublicKey(rsa, e, &esz, n, &nsz);
  531. if (ret < 0) {
  532. SGX_DBG(DBG_S, "RSAFlattenPublicKey failed: %d\n", ret);
  533. goto out_free;
  534. }
  535. SHA256 sha256;
  536. ret = SHA256Init(&sha256);
  537. if (ret < 0)
  538. goto out_free;
  539. ret = SHA256Update(&sha256, n, nsz);
  540. if (ret < 0)
  541. goto out_free;
  542. ret = SHA256Final(&sha256, (uint8_t *) pal_enclave_state.enclave_keyhash);
  543. if (ret < 0)
  544. goto out_free;
  545. pal_enclave_config.enclave_key = rsa;
  546. SGX_DBG(DBG_S, "enclave (software) key hash: %s\n",
  547. hex2str(pal_enclave_state.enclave_keyhash));
  548. return 0;
  549. out_free:
  550. FreeRSAKey(rsa);
  551. free(rsa);
  552. return ret;
  553. }
  554. int _DkStreamKeyExchange (PAL_HANDLE stream, PAL_SESSION_KEY * keyptr)
  555. {
  556. unsigned char session_key[32] __attribute__((aligned(32)));
  557. unsigned char priv[128] __attribute__((aligned(128))),
  558. pub[128] __attribute__((aligned(128))),
  559. agree[128] __attribute__((aligned(128)));
  560. uint32_t privsz, pubsz, agreesz;
  561. DhKey dh;
  562. int ret;
  563. InitDhKey(&dh);
  564. ret = DhSetKey(&dh, dh_param.p, sizeof(dh_param.p), dh_param.g,
  565. sizeof(dh_param.g));
  566. if (ret < 0) {
  567. SGX_DBG(DBG_S, "Key Exchange: DhSetKey failed: %d\n", ret);
  568. goto out;
  569. }
  570. ret = DhGenerateKeyPair(&dh, priv, &privsz, pub, &pubsz);
  571. if (ret < 0) {
  572. SGX_DBG(DBG_S, "Key Exchange: DhGenerateKeyPair failed: %d\n", ret);
  573. goto out;
  574. }
  575. ret = _DkStreamWrite(stream, 0, pubsz, pub, NULL, 0);
  576. if (ret < pubsz) {
  577. SGX_DBG(DBG_S, "Key Exchange: DkStreamWrite failed: %d\n", ret);
  578. goto out;
  579. }
  580. ret = _DkStreamRead(stream, 0, pubsz, pub, NULL, 0);
  581. if (ret < pubsz) {
  582. SGX_DBG(DBG_S, "Key Exchange: DkStreamRead failed: %d\n", ret);
  583. goto out;
  584. }
  585. ret = DhAgree(&dh, agree, &agreesz, priv, privsz, pub, pubsz);
  586. if (ret < 0) {
  587. SGX_DBG(DBG_S, "Key Exchange: DhAgree failed: %d\n", ret);
  588. goto out;
  589. }
  590. memset(session_key, 0, sizeof(session_key));
  591. for (int i = 0 ; i < agreesz ; i++)
  592. session_key[i % sizeof(session_key)] ^= agree[i];
  593. SGX_DBG(DBG_S, "key exchange: (%p) %s\n", session_key, hex2str(session_key));
  594. if (keyptr)
  595. memcpy(keyptr, session_key, sizeof(PAL_SESSION_KEY));
  596. ret = 0;
  597. out:
  598. FreeDhKey(&dh);
  599. return ret;
  600. }
  601. struct attestation_request {
  602. sgx_arch_hash_t mrenclave;
  603. sgx_arch_attributes_t attributes;
  604. };
  605. struct attestation {
  606. sgx_arch_hash_t mrenclave;
  607. sgx_arch_attributes_t attributes;
  608. sgx_arch_report_t report;
  609. };
  610. int _DkStreamAttestationRequest (PAL_HANDLE stream, void * data,
  611. int (*check_mrenclave) (sgx_arch_hash_t *,
  612. void *, void *),
  613. void * check_param)
  614. {
  615. struct attestation_request req;
  616. struct attestation att;
  617. int bytes, ret;
  618. memcpy(req.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
  619. memcpy(&req.attributes, &pal_sec.enclave_attributes,
  620. sizeof(sgx_arch_attributes_t));
  621. SGX_DBG(DBG_S, "Sending attestation request ... (mrenclave = %s)\n",\
  622. hex2str(req.mrenclave));
  623. for (bytes = 0, ret = 0 ; bytes < sizeof(req) ; bytes += ret) {
  624. ret = _DkStreamWrite(stream, 0, sizeof(req) - bytes,
  625. ((void *) &req) + bytes, NULL, 0);
  626. if (ret < 0) {
  627. SGX_DBG(DBG_S, "Attestation Request: DkStreamWrite failed: %d\n", ret);
  628. goto out;
  629. }
  630. }
  631. for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
  632. ret = _DkStreamRead(stream, 0, sizeof(att) - bytes,
  633. ((void *) &att) + bytes, NULL, 0);
  634. if (ret < 0) {
  635. SGX_DBG(DBG_S, "Attestation Request: DkStreamRead failed: %d\n", ret);
  636. goto out;
  637. }
  638. }
  639. SGX_DBG(DBG_S, "Received attestation (mrenclave = %s)\n",
  640. hex2str(att.mrenclave));
  641. ret = sgx_verify_report(&att.report);
  642. if (ret < 0) {
  643. SGX_DBG(DBG_S, "Attestation Request: sgx_verify_report failed: %d\n", ret);
  644. goto out;
  645. }
  646. if (ret == 1) {
  647. SGX_DBG(DBG_S, "Remote attestation not signed by SGX!\n");
  648. ret = -PAL_ERROR_DENIED;
  649. goto out;
  650. }
  651. ret = check_mrenclave(&att.report.mrenclave, &att.report.report_data,
  652. check_param);
  653. if (ret < 0) {
  654. SGX_DBG(DBG_S, "Attestation Request: check_mrenclave failed: %d\n", ret);
  655. goto out;
  656. }
  657. if (ret == 1) {
  658. SGX_DBG(DBG_S, "Not an allowed encalve (mrenclave = %s)\n",
  659. hex2str(att.mrenclave));
  660. ret = -PAL_ERROR_DENIED;
  661. goto out;
  662. }
  663. SGX_DBG(DBG_S, "Remote attestation succeed!\n");
  664. ret = sgx_get_report(&att.mrenclave, &att.attributes, data, &att.report);
  665. if (ret < 0) {
  666. SGX_DBG(DBG_S, "Attestation Request: sgx_get_report failed: %d\n", ret);
  667. goto out;
  668. }
  669. memcpy(att.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
  670. memcpy(&att.attributes, &pal_sec.enclave_attributes,
  671. sizeof(sgx_arch_attributes_t));
  672. SGX_DBG(DBG_S, "Sending attestation ... (mrenclave = %s)\n",
  673. hex2str(att.mrenclave));
  674. for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
  675. ret = _DkStreamWrite(stream, 0, sizeof(att) - bytes,
  676. ((void *) &att) + bytes, NULL, 0);
  677. if (ret < 0) {
  678. SGX_DBG(DBG_S, "Attestation Request: DkStreamWrite failed: %d\n", ret);
  679. goto out;
  680. }
  681. }
  682. return 0;
  683. out:
  684. DkStreamDelete(stream, 0);
  685. return ret;
  686. }
  687. int _DkStreamAttestationRespond (PAL_HANDLE stream, void * data,
  688. int (*check_mrenclave) (sgx_arch_hash_t *,
  689. void *, void *),
  690. void * check_param)
  691. {
  692. struct attestation_request req;
  693. struct attestation att;
  694. int bytes, ret;
  695. for (bytes = 0, ret = 0 ; bytes < sizeof(req) ; bytes += ret) {
  696. ret = _DkStreamRead(stream, 0, sizeof(req) - bytes,
  697. ((void *) &req) + bytes, NULL, 0);
  698. if (ret < 0) {
  699. SGX_DBG(DBG_S, "Attestation Respond: DkStreamRead failed: %d\n", ret);
  700. goto out;
  701. }
  702. }
  703. SGX_DBG(DBG_S, "Received attestation request ... (mrenclave = %s)\n",
  704. hex2str(req.mrenclave));
  705. ret = sgx_get_report(&req.mrenclave, &req.attributes, data, &att.report);
  706. if (ret < 0) {
  707. SGX_DBG(DBG_S, "Attestation Respond: sgx_get_report failed: %d\n", ret);
  708. goto out;
  709. }
  710. memcpy(att.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
  711. memcpy(&att.attributes, &pal_sec.enclave_attributes,
  712. sizeof(sgx_arch_attributes_t));
  713. SGX_DBG(DBG_S, "Sending attestation ... (mrenclave = %s)\n",
  714. hex2str(att.mrenclave));
  715. for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
  716. ret = _DkStreamWrite(stream, 0, sizeof(att) - bytes,
  717. ((void *) &att) + bytes, NULL, 0);
  718. if (ret < 0) {
  719. SGX_DBG(DBG_S, "Attestation Respond: DkStreamWrite failed: %d\n", ret);
  720. goto out;
  721. }
  722. }
  723. for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
  724. ret = _DkStreamRead(stream, 0, sizeof(att) - bytes,
  725. ((void *) &att) + bytes, NULL, 0);
  726. if (ret < 0) {
  727. SGX_DBG(DBG_S, "Attestation Respond: DkStreamRead failed: %d\n", ret);
  728. goto out;
  729. }
  730. }
  731. SGX_DBG(DBG_S, "Received attestation (mrenclave = %s)\n",
  732. hex2str(att.mrenclave));
  733. ret = sgx_verify_report(&att.report);
  734. if (ret < 0) {
  735. SGX_DBG(DBG_S, "Attestation Respond: sgx_verify_report failed: %d\n", ret);
  736. goto out;
  737. }
  738. if (ret == 1) {
  739. SGX_DBG(DBG_S, "Remote attestation not signed by SGX!\n");
  740. goto out;
  741. }
  742. ret = check_mrenclave(&att.report.mrenclave, &att.report.report_data,
  743. check_param);
  744. if (ret < 0) {
  745. SGX_DBG(DBG_S, "Attestation Request: check_mrenclave failed: %d\n", ret);
  746. goto out;
  747. }
  748. if (ret == 1) {
  749. SGX_DBG(DBG_S, "Not an allowed encalve (mrenclave = %s)\n",
  750. hex2str(att.mrenclave));
  751. ret = -PAL_ERROR_DENIED;
  752. goto out;
  753. }
  754. SGX_DBG(DBG_S, "Remote attestation succeed!\n");
  755. return 0;
  756. out:
  757. DkStreamDelete(stream, 0);
  758. return ret;
  759. }