enclave_framework.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  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 <pal_crypto.h>
  8. #include <api.h>
  9. #include <list.h>
  10. #include "enclave_pages.h"
  11. struct pal_enclave_state pal_enclave_state;
  12. void * enclave_base, * enclave_top;
  13. struct pal_enclave_config pal_enclave_config;
  14. bool sgx_is_within_enclave (const void * addr, uint64_t size)
  15. {
  16. return (addr >= enclave_base &&
  17. addr + size <= enclave_top) ? 1 : 0;
  18. }
  19. void * sgx_ocalloc (uint64_t size)
  20. {
  21. void * ustack = GET_ENCLAVE_TLS(ustack) - size;
  22. SET_ENCLAVE_TLS(ustack, ustack);
  23. return ustack;
  24. }
  25. void sgx_ocfree (void)
  26. {
  27. SET_ENCLAVE_TLS(ustack, GET_ENCLAVE_TLS(ustack_top));
  28. }
  29. int sgx_get_report (sgx_arch_hash_t * mrenclave,
  30. sgx_arch_attributes_t * attributes,
  31. void * enclave_data,
  32. sgx_arch_report_t * report)
  33. {
  34. sgx_arch_targetinfo_t targetinfo;
  35. memset(&targetinfo, 0, sizeof(sgx_arch_targetinfo_t));
  36. memcpy(targetinfo.mrenclave, mrenclave, sizeof(sgx_arch_hash_t));
  37. memcpy(&targetinfo.attributes, attributes, sizeof(sgx_arch_attributes_t));
  38. struct pal_enclave_state state;
  39. memcpy(&state, &pal_enclave_state, sizeof(struct pal_enclave_state));
  40. memcpy(&state.data, enclave_data, PAL_ATTESTATION_DATA_SIZE);
  41. int ret = sgx_report(&targetinfo, &state, report);
  42. if (ret)
  43. return -PAL_ERROR_DENIED;
  44. SGX_DBG(DBG_S, "Generated report:\n");
  45. SGX_DBG(DBG_S, " cpusvn: %08x %08x\n", report->cpusvn[0],
  46. report->cpusvn[1]);
  47. SGX_DBG(DBG_S, " mrenclave: %s\n", hex2str(report->mrenclave));
  48. SGX_DBG(DBG_S, " mrsigner: %s\n", hex2str(report->mrsigner));
  49. SGX_DBG(DBG_S, " attributes.flags: %016lx\n", report->attributes.flags);
  50. SGX_DBG(DBG_S, " sttributes.xfrm: %016lx\n", report->attributes.xfrm);
  51. SGX_DBG(DBG_S, " isvprodid: %02x\n", report->isvprodid);
  52. SGX_DBG(DBG_S, " isvsvn: %02x\n", report->isvsvn);
  53. SGX_DBG(DBG_S, " keyid: %s\n", hex2str(report->keyid));
  54. SGX_DBG(DBG_S, " mac: %s\n", hex2str(report->mac));
  55. return 0;
  56. }
  57. static sgx_arch_key128_t enclave_key;
  58. int sgx_verify_report (sgx_arch_report_t * report)
  59. {
  60. sgx_arch_keyrequest_t keyrequest;
  61. memset(&keyrequest, 0, sizeof(sgx_arch_keyrequest_t));
  62. keyrequest.keyname = REPORT_KEY;
  63. memcpy(keyrequest.keyid, report->keyid, sizeof(keyrequest.keyid));
  64. int ret = sgx_getkey(&keyrequest, &enclave_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(enclave_key));
  70. return 0;
  71. }
  72. int init_enclave_key (void)
  73. {
  74. sgx_arch_keyrequest_t keyrequest;
  75. memset(&keyrequest, 0, sizeof(sgx_arch_keyrequest_t));
  76. keyrequest.keyname = SEAL_KEY;
  77. int ret = sgx_getkey(&keyrequest, &enclave_key);
  78. if (ret) {
  79. SGX_DBG(DBG_S, "Can't get report key\n");
  80. return -PAL_ERROR_DENIED;
  81. }
  82. SGX_DBG(DBG_S, "Get sealing key: %s\n", hex2str(enclave_key));
  83. return 0;
  84. }
  85. DEFINE_LIST(trusted_file);
  86. struct trusted_file {
  87. LIST_TYPE(trusted_file) list;
  88. int64_t index;
  89. uint64_t size;
  90. int uri_len;
  91. char uri[URI_MAX];
  92. sgx_checksum_t checksum;
  93. sgx_stub_t * stubs;
  94. };
  95. DEFINE_LISTP(trusted_file);
  96. static LISTP_TYPE(trusted_file) trusted_file_list = LISTP_INIT;
  97. static struct spinlock trusted_file_lock = LOCK_INIT;
  98. static int trusted_file_indexes = 0;
  99. int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
  100. uint64_t * sizeptr)
  101. {
  102. struct trusted_file * tf = NULL, * tmp;
  103. char uri[URI_MAX];
  104. char normpath[URI_MAX];
  105. int ret, fd = file->file.fd, uri_len, len;
  106. if (!(HANDLE_HDR(file)->flags & RFD(0)))
  107. return -PAL_ERROR_DENIED;
  108. uri_len = _DkStreamGetName(file, uri, URI_MAX);
  109. if (uri_len < 0)
  110. return uri_len;
  111. /* Normalize the uri */
  112. if (!strpartcmp_static(uri, "file:")) {
  113. SGX_DBG(DBG_E, "Invalid URI [%s]: Trusted files must start with 'file:'\n", uri);;
  114. return -PAL_ERROR_INVAL;
  115. }
  116. normpath [0] = 'f';
  117. normpath [1] = 'i';
  118. normpath [2] = 'l';
  119. normpath [3] = 'e';
  120. normpath [4] = ':';
  121. len = get_norm_path(uri + 5, normpath + 5, 0, URI_MAX);
  122. uri_len = len + 5;
  123. _DkSpinLock(&trusted_file_lock);
  124. listp_for_each_entry(tmp, &trusted_file_list, list) {
  125. if (tmp->stubs) {
  126. /* trusted files: must be exactly the same URI */
  127. if (tmp->uri_len == uri_len && !memcmp(tmp->uri, normpath, uri_len + 1)) {
  128. tf = tmp;
  129. break;
  130. }
  131. } else {
  132. /* allowed files: must be a subfolder or file */
  133. if (tmp->uri_len <= uri_len &&
  134. !memcmp(tmp->uri, normpath, tmp->uri_len) &&
  135. (!normpath[tmp->uri_len] || normpath[tmp->uri_len] == '/')) {
  136. tf = tmp;
  137. break;
  138. }
  139. }
  140. }
  141. _DkSpinUnlock(&trusted_file_lock);
  142. if (!tf)
  143. return -PAL_ERROR_DENIED;
  144. if (tf->index < 0)
  145. return tf->index;
  146. #if CACHE_FILE_STUBS == 1
  147. if (tf->index && tf->stubs) {
  148. *stubptr = tf->stubs;
  149. *sizeptr = tf->size;
  150. return 0;
  151. }
  152. #endif
  153. if (!tf->index) {
  154. *stubptr = NULL;
  155. PAL_STREAM_ATTR attr;
  156. ret = _DkStreamAttributesQuery(normpath, &attr);
  157. if (!ret)
  158. *sizeptr = attr.pending_size;
  159. else
  160. *sizeptr = 0;
  161. return 0;
  162. }
  163. int nstubs = tf->size / TRUSTED_STUB_SIZE +
  164. (tf->size % TRUSTED_STUB_SIZE ? 1 : 0);
  165. sgx_stub_t * stubs = malloc(sizeof(sgx_stub_t) * nstubs);
  166. if (!stubs)
  167. return -PAL_ERROR_NOMEM;
  168. sgx_stub_t * s = stubs;
  169. uint64_t offset = 0;
  170. LIB_SHA256_CONTEXT sha;
  171. void * umem;
  172. ret = lib_SHA256Init(&sha);
  173. if (ret < 0)
  174. goto failed;
  175. for (; offset < tf->size ; offset += TRUSTED_STUB_SIZE, s++) {
  176. uint64_t mapping_size = tf->size - offset;
  177. if (mapping_size > TRUSTED_STUB_SIZE)
  178. mapping_size = TRUSTED_STUB_SIZE;
  179. ret = ocall_map_untrusted(fd, offset, mapping_size, PROT_READ, &umem);
  180. if (ret < 0)
  181. goto unmap;
  182. lib_AESCMAC((void *) &enclave_key, AES_CMAC_KEY_LEN, umem,
  183. mapping_size, (uint8_t *) s, sizeof *s);
  184. /* update the file checksum */
  185. ret = lib_SHA256Update(&sha, umem, mapping_size);
  186. unmap:
  187. ocall_unmap_untrusted(umem, mapping_size);
  188. if (ret < 0)
  189. goto failed;
  190. }
  191. sgx_checksum_t hash;
  192. ret = lib_SHA256Final(&sha, (uint8_t *) hash.bytes);
  193. if (ret < 0)
  194. goto failed;
  195. if (memcmp(&hash, &tf->checksum, sizeof(sgx_checksum_t))) {
  196. ret = -PAL_ERROR_DENIED;
  197. goto failed;
  198. }
  199. _DkSpinLock(&trusted_file_lock);
  200. if (tf->stubs || tf->index == -PAL_ERROR_DENIED)
  201. free(tf->stubs);
  202. *stubptr = tf->stubs = stubs;
  203. *sizeptr = tf->size;
  204. ret = tf->index;
  205. _DkSpinUnlock(&trusted_file_lock);
  206. return ret;
  207. failed:
  208. free(stubs);
  209. _DkSpinLock(&trusted_file_lock);
  210. if (tf->stubs) {
  211. *stubptr = tf->stubs;
  212. *sizeptr = tf->size;
  213. ret = tf->index;
  214. } else {
  215. tf->index = -PAL_ERROR_DENIED;
  216. }
  217. _DkSpinUnlock(&trusted_file_lock);
  218. #if PRINT_ENCLAVE_STAT
  219. if (!ret) {
  220. sgx_stub_t * loaded_stub;
  221. uint64_t loaded_size;
  222. PAL_HANDLE handle = NULL;
  223. if (!_DkStreamOpen(&handle, normpath, PAL_ACCESS_RDONLY, 0, 0, 0))
  224. load_trusted_file (handle, &loaded_stub, &loaded_size);
  225. }
  226. #endif
  227. return ret;
  228. }
  229. int verify_trusted_file (const char * uri, void * mem,
  230. uint64_t offset, uint64_t size,
  231. sgx_stub_t * stubs,
  232. uint64_t total_size)
  233. {
  234. uint64_t checking = offset;
  235. sgx_stub_t * s = stubs + checking / TRUSTED_STUB_SIZE;
  236. for (; checking < offset + size ; checking += TRUSTED_STUB_SIZE, s++) {
  237. uint64_t checking_size = TRUSTED_STUB_SIZE;
  238. if (checking_size > total_size - checking)
  239. checking_size = total_size - checking;
  240. uint8_t hash[AES_CMAC_DIGEST_LEN];
  241. lib_AESCMAC((void *) &enclave_key,
  242. AES_CMAC_KEY_LEN,
  243. mem + checking - offset, checking_size,
  244. hash, sizeof(hash));
  245. if (memcmp(s, hash, sizeof(sgx_stub_t))) {
  246. SGX_DBG(DBG_E, "Accesing file:%s is denied. "
  247. "Does not match with its MAC.\n", uri);
  248. return -PAL_ERROR_DENIED;
  249. }
  250. }
  251. return 0;
  252. }
  253. static int register_trusted_file (const char * uri, const char * checksum_str)
  254. {
  255. struct trusted_file * tf = NULL, * new;
  256. int uri_len = strlen(uri);
  257. int ret;
  258. _DkSpinLock(&trusted_file_lock);
  259. listp_for_each_entry(tf, &trusted_file_list, list) {
  260. if (tf->uri_len == uri_len && !memcmp(tf->uri, uri, uri_len)) {
  261. _DkSpinUnlock(&trusted_file_lock);
  262. return 0;
  263. }
  264. }
  265. _DkSpinUnlock(&trusted_file_lock);
  266. new = malloc(sizeof(struct trusted_file));
  267. if (!new)
  268. return -PAL_ERROR_NOMEM;
  269. INIT_LIST_HEAD(new, list);
  270. new->uri_len = uri_len;
  271. memcpy(new->uri, uri, uri_len + 1);
  272. new->size = 0;
  273. new->stubs = NULL;
  274. if (checksum_str) {
  275. PAL_STREAM_ATTR attr;
  276. ret = _DkStreamAttributesQuery(uri, &attr);
  277. if (!ret)
  278. new->size = attr.pending_size;
  279. char checksum_text[sizeof(sgx_checksum_t) * 2 + 1] = "\0";
  280. int nbytes = 0;
  281. for (; nbytes < sizeof(sgx_checksum_t) ; nbytes++) {
  282. char byte1 = checksum_str[nbytes * 2];
  283. char byte2 = checksum_str[nbytes * 2 + 1];
  284. unsigned char val = 0;
  285. if (byte1 == 0 || byte2 == 0) {
  286. break;
  287. }
  288. if (!(byte1 >= '0' && byte1 <= '9') &&
  289. !(byte1 >= 'a' && byte1 <= 'f')) {
  290. break;
  291. }
  292. if (!(byte2 >= '0' && byte2 <= '9') &&
  293. !(byte2 >= 'a' && byte2 <= 'f')) {
  294. break;
  295. }
  296. if (byte1 >= '0' && byte1 <= '9')
  297. val = byte1 - '0';
  298. if (byte1 >= 'a' && byte1 <= 'f')
  299. val = byte1 - 'a' + 10;
  300. val *= 16;
  301. if (byte2 >= '0' && byte2 <= '9')
  302. val += byte2 - '0';
  303. if (byte2 >= 'a' && byte2 <= 'f')
  304. val += byte2 - 'a' + 10;
  305. new->checksum.bytes[nbytes] = val;
  306. snprintf(checksum_text + nbytes * 2, 3, "%02x", val);
  307. }
  308. if (nbytes < sizeof(sgx_checksum_t)) {
  309. free(new);
  310. return -PAL_ERROR_INVAL;
  311. }
  312. new->index = (++trusted_file_indexes);
  313. SGX_DBG(DBG_S, "trusted: [%d] %s %s\n", new->index,
  314. checksum_text, new->uri);
  315. } else {
  316. memset(&new->checksum, 0, sizeof(sgx_checksum_t));
  317. new->index = 0;
  318. SGX_DBG(DBG_S, "allowed: %s\n", new->uri);
  319. }
  320. _DkSpinLock(&trusted_file_lock);
  321. listp_for_each_entry(tf, &trusted_file_list, list) {
  322. if (tf->uri_len == uri_len && !memcmp(tf->uri, uri, uri_len)) {
  323. _DkSpinUnlock(&trusted_file_lock);
  324. free(new);
  325. return 0;
  326. }
  327. }
  328. listp_add_tail(new, &trusted_file_list, list);
  329. _DkSpinUnlock(&trusted_file_lock);
  330. return 0;
  331. }
  332. static int init_trusted_file (const char * key, const char * uri)
  333. {
  334. char cskey[URI_MAX], * tmp;
  335. char checksum[URI_MAX];
  336. char normpath[URI_MAX];
  337. tmp = strcpy_static(cskey, "sgx.trusted_checksum.", URI_MAX);
  338. memcpy(tmp, key, strlen(key) + 1);
  339. ssize_t len = get_config(pal_state.root_config, cskey, checksum, CONFIG_MAX);
  340. if (len < 0)
  341. return 0;
  342. /* Normalize the uri */
  343. if (!strpartcmp_static(uri, "file:")) {
  344. SGX_DBG(DBG_E, "Invalid URI [%s]: Trusted files must start with 'file:'\n", uri);
  345. return -PAL_ERROR_INVAL;
  346. }
  347. normpath [0] = 'f';
  348. normpath [1] = 'i';
  349. normpath [2] = 'l';
  350. normpath [3] = 'e';
  351. normpath [4] = ':';
  352. len = get_norm_path(uri + 5, normpath + 5, 0, URI_MAX);
  353. return register_trusted_file(normpath, checksum);
  354. }
  355. int init_trusted_files (void)
  356. {
  357. struct config_store * store = pal_state.root_config;
  358. char * cfgbuf = NULL;
  359. ssize_t cfgsize;
  360. int nuris, ret;
  361. if (pal_sec.exec_fd != PAL_IDX_POISON) {
  362. ret = init_trusted_file("exec", pal_sec.exec_name);
  363. if (ret < 0)
  364. goto out;
  365. }
  366. cfgbuf = malloc(CONFIG_MAX);
  367. if (!cfgbuf) {
  368. ret = -PAL_ERROR_NOMEM;
  369. goto out;
  370. }
  371. ssize_t len = get_config(store, "loader.preload", cfgbuf, CONFIG_MAX);
  372. if (len > 0) {
  373. int npreload = 0;
  374. char key[10];
  375. const char * start, * end;
  376. for (start = cfgbuf ; start < cfgbuf + len ; start = end + 1) {
  377. for (end = start ; end < cfgbuf + len && *end && *end != ',' ; end++);
  378. if (end > start) {
  379. char uri[end - start + 1];
  380. memcpy(uri, start, end - start);
  381. uri[end - start] = 0;
  382. snprintf(key, 10, "preload%d", npreload++);
  383. ret = init_trusted_file(key, uri);
  384. if (ret < 0)
  385. goto out;
  386. }
  387. }
  388. }
  389. cfgsize = get_config_entries_size(store, "sgx.trusted_files");
  390. if (cfgsize <= 0)
  391. goto no_trusted;
  392. free(cfgbuf);
  393. cfgbuf = malloc(cfgsize);
  394. if (!cfgbuf) {
  395. ret = -PAL_ERROR_NOMEM;
  396. goto out;
  397. }
  398. nuris = get_config_entries(store, "sgx.trusted_files", cfgbuf, cfgsize);
  399. if (nuris <= 0)
  400. goto no_trusted;
  401. {
  402. char key[CONFIG_MAX], uri[CONFIG_MAX];
  403. char * k = cfgbuf, * tmp;
  404. tmp = strcpy_static(key, "sgx.trusted_files.", CONFIG_MAX);
  405. for (int i = 0 ; i < nuris ; i++) {
  406. len = strlen(k);
  407. memcpy(tmp, k, len + 1);
  408. k += len + 1;
  409. len = get_config(store, key, uri, CONFIG_MAX);
  410. if (len > 0) {
  411. ret = init_trusted_file(key + 18, uri);
  412. if (ret < 0)
  413. goto out;
  414. }
  415. }
  416. }
  417. no_trusted:
  418. cfgsize = get_config_entries_size(store, "sgx.allowed_files");
  419. if (cfgsize <= 0)
  420. goto no_allowed;
  421. free(cfgbuf);
  422. cfgbuf = malloc(cfgsize);
  423. if (!cfgbuf) {
  424. ret = -PAL_ERROR_NOMEM;
  425. goto out;
  426. }
  427. nuris = get_config_entries(store, "sgx.allowed_files", cfgbuf, cfgsize);
  428. if (nuris <= 0)
  429. goto no_allowed;
  430. {
  431. char key[CONFIG_MAX], uri[CONFIG_MAX];
  432. char * k = cfgbuf, * tmp;
  433. tmp = strcpy_static(key, "sgx.allowed_files.", CONFIG_MAX);
  434. for (int i = 0 ; i < nuris ; i++) {
  435. len = strlen(k);
  436. memcpy(tmp, k, len + 1);
  437. k += len + 1;
  438. len = get_config(store, key, uri, CONFIG_MAX);
  439. if (len > 0)
  440. register_trusted_file(uri, NULL);
  441. }
  442. }
  443. no_allowed:
  444. ret = 0;
  445. out:
  446. free(cfgbuf);
  447. return ret;
  448. }
  449. int init_trusted_children (void)
  450. {
  451. struct config_store * store = pal_state.root_config;
  452. char key[CONFIG_MAX], mrkey[CONFIG_MAX];
  453. char uri[CONFIG_MAX], mrenclave[CONFIG_MAX];
  454. char * tmp1 = strcpy_static(key, "sgx.trusted_children.", CONFIG_MAX);
  455. char * tmp2 = strcpy_static(mrkey, "sgx.trusted_mrenclave.", CONFIG_MAX);
  456. ssize_t cfgsize = get_config_entries_size(store, "sgx.trusted_mrenclave");
  457. if (cfgsize <= 0)
  458. return 0;
  459. char * cfgbuf = malloc(cfgsize);
  460. if (!cfgbuf)
  461. return -PAL_ERROR_NOMEM;
  462. int nuris = get_config_entries(store, "sgx.trusted_mrenclave",
  463. cfgbuf, cfgsize);
  464. if (nuris > 0) {
  465. char * k = cfgbuf;
  466. for (int i = 0 ; i < nuris ; i++) {
  467. int len = strlen(k);
  468. memcpy(tmp1, k, len + 1);
  469. memcpy(tmp2, k, len + 1);
  470. k += len + 1;
  471. ssize_t ret = get_config(store, key, uri, CONFIG_MAX);
  472. if (ret < 0)
  473. continue;
  474. ret = get_config(store, mrkey, mrenclave, CONFIG_MAX);
  475. if (ret > 0)
  476. register_trusted_child(uri, mrenclave);
  477. }
  478. }
  479. free(cfgbuf);
  480. return 0;
  481. }
  482. #if 0
  483. void test_dh (void)
  484. {
  485. int ret;
  486. DhKey key1, key2;
  487. uint32_t privsz1, privsz2, pubsz1, pubsz2, agreesz1, agreesz2;
  488. unsigned char priv1[128], pub1[128], priv2[128], pub2[128], agree1[128],
  489. agree2[128];
  490. InitDhKey(&key1);
  491. InitDhKey(&key2);
  492. ret = DhSetKey(&key1, dh_param.p, sizeof(dh_param.p), dh_param.g,
  493. sizeof(dh_param.g));
  494. if (ret < 0) {
  495. SGX_DBG(DBG_S, "DhSetKey for key 1 failed: %d\n", ret);
  496. return;
  497. }
  498. ret = DhSetKey(&key2, dh_param.p, sizeof(dh_param.p), dh_param.g,
  499. sizeof(dh_param.g));
  500. if (ret < 0) {
  501. SGX_DBG(DBG_S, "DhSetKey for key 2 failed: %d\n", ret);
  502. return;
  503. }
  504. ret = DhGenerateKeyPair(&key1, priv1, &privsz1, pub1, &pubsz1);
  505. if (ret < 0) {
  506. SGX_DBG(DBG_S, "DhGenerateKeyPair for key 1 failed: %d\n", ret);
  507. return;
  508. }
  509. ret = DhGenerateKeyPair(&key2, priv2, &privsz2, pub2, &pubsz2);
  510. if (ret < 0) {
  511. SGX_DBG(DBG_S, "DhGenerateKeyPair for key 2 failed: %d\n", ret);
  512. return;
  513. }
  514. ret = DhAgree(&key1, agree1, &agreesz1, priv1, privsz1, pub2, pubsz2);
  515. if (ret < 0) {
  516. SGX_DBG(DBG_S, "DhAgree for key 1 failed: %d\n", ret);
  517. return;
  518. }
  519. ret = DhAgree(&key2, agree2, &agreesz2, priv2, privsz2, pub1, pubsz1);
  520. if (ret < 0) {
  521. SGX_DBG(DBG_S, "DhAgree for key 1 failed: %d\n", ret);
  522. return;
  523. }
  524. FreeDhKey(&key1);
  525. FreeDhKey(&key2);
  526. SGX_DBG(DBG_S, "key exchange(side A): %s (%d)\n", __hex2str(agree1, agreesz1),
  527. agreesz1);
  528. SGX_DBG(DBG_S, "key exchange(side B): %s (%d)\n", __hex2str(agree2, agreesz2),
  529. agreesz2);
  530. }
  531. #endif
  532. #define RSA_KEY_SIZE 2048
  533. #define RSA_E 3
  534. int init_enclave (void)
  535. {
  536. int ret;
  537. LIB_RSA_KEY *rsa = malloc(sizeof(LIB_RSA_KEY));
  538. lib_RSAInitKey(rsa);
  539. ret = lib_RSAGenerateKey(rsa, RSA_KEY_SIZE, RSA_E);
  540. if (ret != 0) {
  541. SGX_DBG(DBG_S, "lib_RSAGenerateKey failed: %d\n", ret);
  542. return ret;
  543. }
  544. PAL_NUM nsz = RSA_KEY_SIZE / 8, esz = 1;
  545. uint8_t n[nsz], e[esz];
  546. ret = lib_RSAExportPublicKey(rsa, e, &esz, n, &nsz);
  547. if (ret != 0) {
  548. SGX_DBG(DBG_S, "lib_RSAExtractPublicKey failed: %d\n", ret);
  549. goto out_free;
  550. }
  551. LIB_SHA256_CONTEXT sha256;
  552. ret = lib_SHA256Init(&sha256);
  553. if (ret < 0)
  554. goto out_free;
  555. ret = lib_SHA256Update(&sha256, n, nsz);
  556. if (ret < 0)
  557. goto out_free;
  558. ret = lib_SHA256Final(&sha256, (uint8_t *) pal_enclave_state.enclave_keyhash);
  559. if (ret < 0)
  560. goto out_free;
  561. pal_enclave_config.enclave_key = rsa;
  562. SGX_DBG(DBG_S, "enclave (software) key hash: %s\n",
  563. hex2str(pal_enclave_state.enclave_keyhash));
  564. return 0;
  565. out_free:
  566. lib_RSAFreeKey(rsa);
  567. free(rsa);
  568. return ret;
  569. }
  570. int _DkStreamKeyExchange (PAL_HANDLE stream, PAL_SESSION_KEY * keyptr)
  571. {
  572. unsigned char session_key[32] __attribute__((aligned(32)));
  573. uint8_t pub[DH_SIZE] __attribute__((aligned(DH_SIZE)));
  574. uint8_t agree[DH_SIZE] __attribute__((aligned(DH_SIZE)));
  575. PAL_NUM pubsz, agreesz;
  576. LIB_DH_CONTEXT context;
  577. int ret;
  578. ret = lib_DhInit(&context);
  579. if (ret < 0) {
  580. SGX_DBG(DBG_S, "Key Exchange: DH Init failed: %d\n", ret);
  581. goto out_no_final;
  582. }
  583. pubsz = sizeof pub;
  584. ret = lib_DhCreatePublic(&context, pub, &pubsz);
  585. if (ret < 0) {
  586. SGX_DBG(DBG_S, "Key Exchange: DH CreatePublic failed: %d\n", ret);
  587. goto out;
  588. }
  589. assert(pubsz > 0 && pubsz <= DH_SIZE);
  590. if (pubsz < DH_SIZE) {
  591. /* Insert leading zero bytes if necessary. These values are big-
  592. * endian, so we either need to know the length of the bignum or
  593. * zero-pad at the beginning instead of the end. This code chooses
  594. * to do the latter. */
  595. memmove(pub + (DH_SIZE - pubsz), pub, pubsz);
  596. memset(pub, 0, DH_SIZE - pubsz);
  597. }
  598. ret = _DkStreamWrite(stream, 0, DH_SIZE, pub, NULL, 0);
  599. if (ret != DH_SIZE) {
  600. SGX_DBG(DBG_S, "Key Exchange: DkStreamWrite failed: %d\n", ret);
  601. goto out;
  602. }
  603. ret = _DkStreamRead(stream, 0, DH_SIZE, pub, NULL, 0);
  604. if (ret != DH_SIZE) {
  605. SGX_DBG(DBG_S, "Key Exchange: DkStreamRead failed: %d\n", ret);
  606. goto out;
  607. }
  608. agreesz = sizeof agree;
  609. ret = lib_DhCalcSecret(&context, pub, DH_SIZE, agree, &agreesz);
  610. if (ret < 0) {
  611. SGX_DBG(DBG_S, "Key Exchange: DH CalcSecret failed: %d\n", ret);
  612. goto out;
  613. }
  614. assert(agreesz > 0 && agreesz <= sizeof agree);
  615. // TODO(security): use a real KDF
  616. memset(session_key, 0, sizeof(session_key));
  617. for (int i = 0 ; i < agreesz ; i++)
  618. session_key[i % sizeof(session_key)] ^= agree[i];
  619. SGX_DBG(DBG_S, "key exchange: (%p) %s\n", session_key, hex2str(session_key));
  620. if (keyptr)
  621. memcpy(keyptr, session_key, sizeof(PAL_SESSION_KEY));
  622. ret = 0;
  623. out:
  624. lib_DhFinal(&context);
  625. out_no_final:
  626. return ret;
  627. }
  628. struct attestation_request {
  629. sgx_arch_hash_t mrenclave;
  630. sgx_arch_attributes_t attributes;
  631. };
  632. struct attestation {
  633. sgx_arch_hash_t mrenclave;
  634. sgx_arch_attributes_t attributes;
  635. sgx_arch_report_t report;
  636. };
  637. int _DkStreamAttestationRequest (PAL_HANDLE stream, void * data,
  638. int (*check_mrenclave) (sgx_arch_hash_t *,
  639. void *, void *),
  640. void * check_param)
  641. {
  642. struct attestation_request req;
  643. struct attestation att;
  644. int bytes, ret;
  645. memcpy(req.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
  646. memcpy(&req.attributes, &pal_sec.enclave_attributes,
  647. sizeof(sgx_arch_attributes_t));
  648. SGX_DBG(DBG_S, "Sending attestation request ... (mrenclave = %s)\n",\
  649. hex2str(req.mrenclave));
  650. for (bytes = 0, ret = 0 ; bytes < sizeof(req) ; bytes += ret) {
  651. ret = _DkStreamWrite(stream, 0, sizeof(req) - bytes,
  652. ((void *) &req) + bytes, NULL, 0);
  653. if (ret < 0) {
  654. SGX_DBG(DBG_S, "Attestation Request: DkStreamWrite failed: %d\n", ret);
  655. goto out;
  656. }
  657. }
  658. for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
  659. ret = _DkStreamRead(stream, 0, sizeof(att) - bytes,
  660. ((void *) &att) + bytes, NULL, 0);
  661. if (ret < 0) {
  662. SGX_DBG(DBG_S, "Attestation Request: DkStreamRead failed: %d\n", ret);
  663. goto out;
  664. }
  665. }
  666. SGX_DBG(DBG_S, "Received attestation (mrenclave = %s)\n",
  667. hex2str(att.mrenclave));
  668. ret = sgx_verify_report(&att.report);
  669. if (ret < 0) {
  670. SGX_DBG(DBG_S, "Attestation Request: sgx_verify_report failed: %d\n", ret);
  671. goto out;
  672. }
  673. if (ret == 1) {
  674. SGX_DBG(DBG_S, "Remote attestation not signed by SGX!\n");
  675. ret = -PAL_ERROR_DENIED;
  676. goto out;
  677. }
  678. ret = check_mrenclave(&att.report.mrenclave, &att.report.report_data,
  679. check_param);
  680. if (ret < 0) {
  681. SGX_DBG(DBG_S, "Attestation Request: check_mrenclave failed: %d\n", ret);
  682. goto out;
  683. }
  684. if (ret == 1) {
  685. SGX_DBG(DBG_S, "Not an allowed encalve (mrenclave = %s)\n",
  686. hex2str(att.mrenclave));
  687. ret = -PAL_ERROR_DENIED;
  688. goto out;
  689. }
  690. SGX_DBG(DBG_S, "Remote attestation succeed!\n");
  691. ret = sgx_get_report(&att.mrenclave, &att.attributes, data, &att.report);
  692. if (ret < 0) {
  693. SGX_DBG(DBG_S, "Attestation Request: sgx_get_report failed: %d\n", ret);
  694. goto out;
  695. }
  696. memcpy(att.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
  697. memcpy(&att.attributes, &pal_sec.enclave_attributes,
  698. sizeof(sgx_arch_attributes_t));
  699. SGX_DBG(DBG_S, "Sending attestation ... (mrenclave = %s)\n",
  700. hex2str(att.mrenclave));
  701. for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
  702. ret = _DkStreamWrite(stream, 0, sizeof(att) - bytes,
  703. ((void *) &att) + bytes, NULL, 0);
  704. if (ret < 0) {
  705. SGX_DBG(DBG_S, "Attestation Request: DkStreamWrite failed: %d\n", ret);
  706. goto out;
  707. }
  708. }
  709. return 0;
  710. out:
  711. DkStreamDelete(stream, 0);
  712. return ret;
  713. }
  714. int _DkStreamAttestationRespond (PAL_HANDLE stream, void * data,
  715. int (*check_mrenclave) (sgx_arch_hash_t *,
  716. void *, void *),
  717. void * check_param)
  718. {
  719. struct attestation_request req;
  720. struct attestation att;
  721. int bytes, ret;
  722. for (bytes = 0, ret = 0 ; bytes < sizeof(req) ; bytes += ret) {
  723. ret = _DkStreamRead(stream, 0, sizeof(req) - bytes,
  724. ((void *) &req) + bytes, NULL, 0);
  725. if (ret < 0) {
  726. SGX_DBG(DBG_S, "Attestation Respond: DkStreamRead failed: %d\n", ret);
  727. goto out;
  728. }
  729. }
  730. SGX_DBG(DBG_S, "Received attestation request ... (mrenclave = %s)\n",
  731. hex2str(req.mrenclave));
  732. ret = sgx_get_report(&req.mrenclave, &req.attributes, data, &att.report);
  733. if (ret < 0) {
  734. SGX_DBG(DBG_S, "Attestation Respond: sgx_get_report failed: %d\n", ret);
  735. goto out;
  736. }
  737. memcpy(att.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
  738. memcpy(&att.attributes, &pal_sec.enclave_attributes,
  739. sizeof(sgx_arch_attributes_t));
  740. SGX_DBG(DBG_S, "Sending attestation ... (mrenclave = %s)\n",
  741. hex2str(att.mrenclave));
  742. for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
  743. ret = _DkStreamWrite(stream, 0, sizeof(att) - bytes,
  744. ((void *) &att) + bytes, NULL, 0);
  745. if (ret < 0) {
  746. SGX_DBG(DBG_S, "Attestation Respond: DkStreamWrite failed: %d\n", ret);
  747. goto out;
  748. }
  749. }
  750. for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
  751. ret = _DkStreamRead(stream, 0, sizeof(att) - bytes,
  752. ((void *) &att) + bytes, NULL, 0);
  753. if (ret < 0) {
  754. SGX_DBG(DBG_S, "Attestation Respond: DkStreamRead failed: %d\n", ret);
  755. goto out;
  756. }
  757. }
  758. SGX_DBG(DBG_S, "Received attestation (mrenclave = %s)\n",
  759. hex2str(att.mrenclave));
  760. ret = sgx_verify_report(&att.report);
  761. if (ret < 0) {
  762. SGX_DBG(DBG_S, "Attestation Respond: sgx_verify_report failed: %d\n", ret);
  763. goto out;
  764. }
  765. if (ret == 1) {
  766. SGX_DBG(DBG_S, "Remote attestation not signed by SGX!\n");
  767. goto out;
  768. }
  769. ret = check_mrenclave(&att.report.mrenclave, &att.report.report_data,
  770. check_param);
  771. if (ret < 0) {
  772. SGX_DBG(DBG_S, "Attestation Request: check_mrenclave failed: %d\n", ret);
  773. goto out;
  774. }
  775. if (ret == 1) {
  776. SGX_DBG(DBG_S, "Not an allowed enclave (mrenclave = %s)\n",
  777. hex2str(att.mrenclave));
  778. ret = -PAL_ERROR_DENIED;
  779. goto out;
  780. }
  781. SGX_DBG(DBG_S, "Remote attestation succeeded!\n");
  782. return 0;
  783. out:
  784. DkStreamDelete(stream, 0);
  785. return ret;
  786. }