enclave_framework.c 29 KB

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