App.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /*
  2. * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <assert.h>
  34. # include <unistd.h>
  35. # include <pwd.h>
  36. # define MAX_PATH FILENAME_MAX
  37. #include "sgx_urts.h"
  38. #include "App.h"
  39. #include "Enclave_u.h"
  40. #include "Seal_u.h"
  41. #define SEAL_FILENAME "Seal.signed.so"
  42. #define SEALED_KEY_FILE_NAME "sealed_key.bin"
  43. #define TOKEN_FILENAME "enclave.token"
  44. /* Global EID shared by multiple threads */
  45. sgx_enclave_id_t global_eid = 0;
  46. typedef struct _sgx_errlist_t {
  47. sgx_status_t err;
  48. const char *msg;
  49. const char *sug; /* Suggestion */
  50. } sgx_errlist_t;
  51. /* Error code returned by sgx_create_enclave */
  52. static sgx_errlist_t sgx_errlist[] = {
  53. {
  54. SGX_ERROR_UNEXPECTED,
  55. "Unexpected error occurred.",
  56. NULL
  57. },
  58. {
  59. SGX_ERROR_INVALID_PARAMETER,
  60. "Invalid parameter.",
  61. NULL
  62. },
  63. {
  64. SGX_ERROR_OUT_OF_MEMORY,
  65. "Out of memory.",
  66. NULL
  67. },
  68. {
  69. SGX_ERROR_ENCLAVE_LOST,
  70. "Power transition occurred.",
  71. "Please refer to the sample \"PowerTransition\" for details."
  72. },
  73. {
  74. SGX_ERROR_INVALID_ENCLAVE,
  75. "Invalid enclave image.",
  76. NULL
  77. },
  78. {
  79. SGX_ERROR_INVALID_ENCLAVE_ID,
  80. "Invalid enclave identification.",
  81. NULL
  82. },
  83. {
  84. SGX_ERROR_INVALID_SIGNATURE,
  85. "Invalid enclave signature.",
  86. NULL
  87. },
  88. {
  89. SGX_ERROR_OUT_OF_EPC,
  90. "Out of EPC memory.",
  91. NULL
  92. },
  93. {
  94. SGX_ERROR_NO_DEVICE,
  95. "Invalid Intel(R) SGX device.",
  96. "Please make sure Intel(R) SGX module is enabled in the BIOS, and install Intel(R) SGX driver afterwards."
  97. },
  98. {
  99. SGX_ERROR_MEMORY_MAP_CONFLICT,
  100. "Memory map conflicted.",
  101. NULL
  102. },
  103. {
  104. SGX_ERROR_INVALID_METADATA,
  105. "Invalid enclave metadata.",
  106. NULL
  107. },
  108. {
  109. SGX_ERROR_DEVICE_BUSY,
  110. "Intel(R) SGX device was busy.",
  111. NULL
  112. },
  113. {
  114. SGX_ERROR_INVALID_VERSION,
  115. "Enclave version was invalid.",
  116. NULL
  117. },
  118. {
  119. SGX_ERROR_INVALID_ATTRIBUTE,
  120. "Enclave was not authorized.",
  121. NULL
  122. },
  123. {
  124. SGX_ERROR_ENCLAVE_FILE_ACCESS,
  125. "Can't open enclave file.",
  126. NULL
  127. },
  128. {
  129. SGX_ERROR_PCL_ENCRYPTED,
  130. "sgx_create_enclave can't open encrypted enclave.",
  131. NULL
  132. },
  133. {
  134. SGX_ERROR_PCL_NOT_ENCRYPTED,
  135. "sgx_create_encrypted_enclave can't open not-encrypted enclave.",
  136. NULL
  137. },
  138. {
  139. SGX_ERROR_PCL_MAC_MISMATCH,
  140. "PCL detected invalid section in encrypted enclave.",
  141. NULL
  142. },
  143. {
  144. SGX_ERROR_PCL_SHA_MISMATCH,
  145. "PCL sealed key SHA mismatch.",
  146. NULL
  147. },
  148. {
  149. SGX_ERROR_PCL_GUID_MISMATCH,
  150. "PCL sealed key GUID mismatch.",
  151. NULL
  152. },
  153. };
  154. /* Check error conditions for loading enclave */
  155. void print_error_message(sgx_status_t ret)
  156. {
  157. size_t idx = 0;
  158. size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0];
  159. for (idx = 0; idx < ttl; idx++) {
  160. if(ret == sgx_errlist[idx].err) {
  161. if(NULL != sgx_errlist[idx].sug)
  162. printf("Info: %s\n", sgx_errlist[idx].sug);
  163. printf("Error: %s\n", sgx_errlist[idx].msg);
  164. break;
  165. }
  166. }
  167. if (idx == ttl)
  168. printf("Error: Unexpected error occurred.\n");
  169. }
  170. /* Initialize the enclave:
  171. * Step 1: try to retrieve the launch token saved by last transaction
  172. * Step 2: call sgx_create_enclave to initialize an enclave instance
  173. * Step 3: save the launch token if it is updated
  174. */
  175. sgx_status_t initialize_enclave ( const char *file_name, sgx_enclave_id_t* eid )
  176. {
  177. char token_path[MAX_PATH] = {'\0'};
  178. sgx_launch_token_t token = {0};
  179. sgx_status_t ret = SGX_ERROR_UNEXPECTED;
  180. int updated = 0;
  181. size_t read_num = 0;
  182. /* Step 1: try to retrieve the launch token saved by last transaction
  183. * if there is no token, then create a new one.
  184. */
  185. /* try to get the token saved in $HOME */
  186. const char *home_dir = getpwuid(getuid())->pw_dir;
  187. if (home_dir != NULL &&
  188. (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
  189. /* compose the token path */
  190. strncpy(token_path, home_dir, strlen(home_dir));
  191. strncat(token_path, "/", strlen("/"));
  192. strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1);
  193. } else {
  194. /* if token path is too long or $HOME is NULL */
  195. strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME));
  196. }
  197. FILE *fp = fopen(token_path, "rb");
  198. if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) {
  199. printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path);
  200. }
  201. if (fp != NULL) {
  202. /* read the token from saved file */
  203. read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp);
  204. if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) {
  205. /* if token is invalid, clear the buffer */
  206. memset(&token, 0x0, sizeof(sgx_launch_token_t));
  207. printf("Warning: Invalid launch token read from \"%s\".\n", token_path);
  208. }
  209. }
  210. /* Step 2: call sgx_create_enclave to initialize an enclave instance */
  211. /* Debug Support: set 2nd parameter to 1 */
  212. #ifdef SGX_USE_PCL
  213. bool open_seal_enclave = true;
  214. uint8_t* sealed_blob = NULL;
  215. FILE *fsealp = fopen(SEALED_KEY_FILE_NAME, "rb");
  216. size_t sealed_blob_size = 0;
  217. if(NULL != fsealp)
  218. {
  219. // Read file size:
  220. fseek(fsealp, 0L, SEEK_END);
  221. sealed_blob_size = ftell(fsealp);
  222. fseek(fsealp, 0L, SEEK_SET);
  223. // Read file into buffer:
  224. sealed_blob = new uint8_t[sealed_blob_size];
  225. read_num = fread(sealed_blob, 1, sealed_blob_size, fsealp);
  226. if ( read_num != sealed_blob_size )
  227. {
  228. printf ( "Warning: Failed to read sealed blob.\n" );
  229. }
  230. else
  231. {
  232. open_seal_enclave = false;
  233. }
  234. fclose(fsealp);
  235. }
  236. if (true == open_seal_enclave)
  237. {
  238. printf ("Open Seal Enclave: %s\n", SEAL_FILENAME );
  239. sgx_enclave_id_t seal_eid = 0;
  240. ret = sgx_create_enclave(
  241. SEAL_FILENAME,
  242. SGX_DEBUG_FLAG,
  243. &token,
  244. &updated,
  245. &seal_eid,
  246. NULL);
  247. if (SGX_SUCCESS != ret)
  248. {
  249. print_error_message(ret);
  250. if(NULL != fp)
  251. {
  252. fclose(fp);
  253. }
  254. return ret;
  255. }
  256. ret = ecall_get_sealed_blob_size(seal_eid, &sealed_blob_size);
  257. if (ret != SGX_SUCCESS || UINT32_MAX == sealed_blob_size)
  258. {
  259. printf("ecall_get_sealed_blob_size: ret = %d, sealed_blob_size = %ld\n", ret, sealed_blob_size);
  260. sgx_destroy_enclave(seal_eid);
  261. return ret;
  262. }
  263. //printf("ecall_get_sealed_blob_size: ret = %d, sealed_blob_size = %ld\n", ret, sealed_blob_size);
  264. sealed_blob = new uint8_t[sealed_blob_size];
  265. sgx_status_t gret = SGX_ERROR_UNEXPECTED;
  266. ret = ecall_generate_sealed_blob(seal_eid, &gret, sealed_blob, sealed_blob_size);
  267. if ((SGX_SUCCESS != ret) || (SGX_SUCCESS != gret))
  268. {
  269. printf("ecall_generate_sealed_blob: ret = %d, gret = 0x%x\n", ret, gret);
  270. sgx_destroy_enclave(seal_eid);
  271. delete sealed_blob;
  272. return ret;
  273. }
  274. sgx_destroy_enclave(seal_eid);
  275. fsealp = fopen(SEALED_KEY_FILE_NAME, "wb");
  276. if(NULL != fsealp)
  277. {
  278. fwrite(sealed_blob, 1, sealed_blob_size, fsealp);
  279. fclose(fsealp);
  280. }
  281. }
  282. // Load the PCL protected Enclave:
  283. ret = sgx_create_encrypted_enclave(file_name, SGX_DEBUG_FLAG, &token, &updated, eid, NULL, sealed_blob);
  284. delete sealed_blob;
  285. #else // SGX_USE_PCL
  286. ret = sgx_create_enclave(file_name, SGX_DEBUG_FLAG, &token, &updated, eid, NULL);
  287. #endif // SGX_USE_PCL
  288. if (ret != SGX_SUCCESS) {
  289. print_error_message(ret);
  290. if (fp != NULL) fclose(fp);
  291. return ret;
  292. }
  293. /* Step 3: save the launch token if it is updated */
  294. if (updated == FALSE || fp == NULL) {
  295. /* if the token is not updated, or file handler is invalid, do not perform saving */
  296. if (fp != NULL) fclose(fp);
  297. return SGX_SUCCESS;
  298. }
  299. /* reopen the file with write capablity */
  300. fp = freopen(token_path, "wb", fp);
  301. if (fp == NULL) return SGX_SUCCESS;
  302. size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp);
  303. if (write_num != sizeof(sgx_launch_token_t))
  304. printf("Warning: Failed to save launch token to \"%s\".\n", token_path);
  305. fclose(fp);
  306. return SGX_SUCCESS;
  307. }
  308. /* OCall functions */
  309. void ocall_print_string(const char *str)
  310. {
  311. /* Proxy/Bridge will check the length and null-terminate
  312. * the input string to prevent buffer overflow.
  313. */
  314. printf("%s", str);
  315. }
  316. /* Application entry */
  317. int SGX_CDECL main(int argc, char *argv[])
  318. {
  319. (void)(argc);
  320. (void)(argv);
  321. /* Initialize the enclave */
  322. if ( initialize_enclave ( ENCLAVE_FILENAME, &global_eid ) < 0 ){
  323. return -1;
  324. }
  325. /* Utilize edger8r attributes */
  326. edger8r_array_attributes();
  327. edger8r_pointer_attributes();
  328. edger8r_type_attributes();
  329. edger8r_function_attributes();
  330. /* Utilize trusted libraries */
  331. ecall_libc_functions();
  332. ecall_libcxx_functions();
  333. ecall_thread_functions();
  334. /* Destroy the enclave */
  335. sgx_destroy_enclave(global_eid);
  336. printf("Info: SampleEnclave successfully returned.\n");
  337. return 0;
  338. }