enclave_framework.c 28 KB

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