enclave_framework.c 28 KB

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