App.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. // App.cpp : Define the entry point for the console application.
  32. //
  33. #include <string.h>
  34. #include <assert.h>
  35. #include <fstream>
  36. #include <thread>
  37. #include <iostream>
  38. #include "Enclave_u.h"
  39. #include "sgx_urts.h"
  40. #include "sgx_tseal.h"
  41. #include "rwlock.h"
  42. #include "ErrorSupport.h"
  43. #define ENCLAVE_NAME "libenclave.signed.so"
  44. #define TOKEN_NAME "Enclave.token"
  45. #define THREAD_NUM 3
  46. // Global data
  47. sgx_enclave_id_t global_eid = 0;
  48. sgx_launch_token_t token = {0};
  49. rwlock_t lock_eid;
  50. struct sealed_buf_t sealed_buf;
  51. using namespace std;
  52. // Ocall function
  53. void print(const char *str)
  54. {
  55. cout<<str;
  56. }
  57. // load_and_initialize_enclave():
  58. // To load and initialize the enclave
  59. sgx_status_t load_and_initialize_enclave(sgx_enclave_id_t *eid, struct sealed_buf_t *sealed_buf)
  60. {
  61. sgx_status_t ret = SGX_SUCCESS;
  62. int retval = 0;
  63. int updated = 0;
  64. for( ; ; )
  65. {
  66. // Step 1: check whether the loading and initialization operations are caused by power transition.
  67. // If the loading and initialization operations are caused by power transition, we need to call sgx_destory_enclave() first.
  68. if(*eid != 0)
  69. {
  70. sgx_destroy_enclave(*eid);
  71. }
  72. // Step 2: load the enclave
  73. // Debug: set the 2nd parameter to 1 which indicates the enclave are launched in debug mode
  74. ret = sgx_create_enclave(ENCLAVE_NAME, SGX_DEBUG_FLAG, &token, &updated, eid, NULL);
  75. if(ret != SGX_SUCCESS)
  76. return ret;
  77. // Save the launch token if updated
  78. if(updated == 1)
  79. {
  80. ofstream ofs(TOKEN_NAME, std::ios::binary|std::ios::out);
  81. if(!ofs.good())
  82. {
  83. cout<< "Warning: Failed to save the launch token to \"" <<TOKEN_NAME <<"\""<<endl;
  84. }
  85. else
  86. ofs << token;
  87. }
  88. // Step 3: enter the enclave to initialize the enclave
  89. // If power transition occurs when the process is inside the enclave, SGX_ERROR_ENCLAVE_LOST will be returned after the system resumes.
  90. // Then we can load and intialize the enclave again or just return this error code and exit to handle the power transition.
  91. // In this sample, we choose to load and intialize the enclave again.
  92. ret = initialize_enclave(*eid, &retval, sealed_buf);
  93. if(ret == SGX_ERROR_ENCLAVE_LOST)
  94. {
  95. cout<<"Power transition occured in initialize_enclave()" <<endl;
  96. continue; // Try to load and initialize the enclave again
  97. }
  98. else
  99. {
  100. // No power transilation occurs.
  101. // If the initialization operation returns failure, change the return value.
  102. if(ret == SGX_SUCCESS && retval != 0)
  103. {
  104. ret = SGX_ERROR_UNEXPECTED;
  105. sgx_destroy_enclave(*eid);
  106. }
  107. break;
  108. }
  109. }
  110. return ret;
  111. }
  112. bool increase_and_seal_data_in_enclave()
  113. {
  114. size_t thread_id = std::hash<std::thread::id>()(std::this_thread::get_id());
  115. sgx_status_t ret = SGX_SUCCESS;
  116. int retval = 0;
  117. sgx_enclave_id_t current_eid = 0;
  118. // Enter the enclave to increase and seal the secret data for 100 times.
  119. for(unsigned int i = 0; i< 50000; i++)
  120. {
  121. for( ; ; )
  122. {
  123. // If power transition occurs, all the data inside the enclave will be lost when the system resumes.
  124. // Therefore, if there are some secret data which need to be backed up for recover,
  125. // users can choose to seal the secret data inside the enclave and back up the sealed data.
  126. // Enter the enclave to increase the secret data and back up the sealed data
  127. rdlock(&lock_eid);
  128. current_eid = global_eid;
  129. rdunlock(&lock_eid);
  130. ret = increase_and_seal_data(current_eid, &retval, thread_id, &sealed_buf);
  131. if(ret == SGX_ERROR_ENCLAVE_LOST)
  132. {
  133. // SGX_ERROR_ENCLAVE_LOST indicates the power transition occurs before the system resumes.
  134. // Lock here is to make sure there is only one thread to load and initialize the enclave at the same time
  135. wtlock(&lock_eid);
  136. // The loading and initialization operations happen in current thread only if there is no other thread reloads and initializes the enclave before
  137. if(current_eid == global_eid)
  138. {
  139. cout <<"power transition occured in increase_and_seal_data()." << endl;
  140. // Use the backup sealed data to reload and initialize the enclave.
  141. if((ret = load_and_initialize_enclave(&current_eid, &sealed_buf)) != SGX_SUCCESS)
  142. {
  143. ret_error_support(ret);
  144. wtunlock(&lock_eid);
  145. return false;
  146. }
  147. else
  148. {
  149. // Update the global_eid after initializing the enclave successfully
  150. global_eid = current_eid;
  151. }
  152. }
  153. else
  154. {
  155. // The enclave has been reloaded by another thread.
  156. // Update the current EID and do increase_and_seal_data() again.
  157. current_eid = global_eid;
  158. }
  159. wtunlock(&lock_eid);
  160. }
  161. else
  162. {
  163. // No power transition occurs
  164. break;
  165. }
  166. }
  167. if(ret != SGX_SUCCESS)
  168. {
  169. ret_error_support(ret);
  170. return false;
  171. }
  172. else if(retval != 0)
  173. {
  174. return false;
  175. }
  176. }
  177. return true;
  178. }
  179. void thread_func()
  180. {
  181. if(increase_and_seal_data_in_enclave() != true)
  182. {
  183. abort();
  184. }
  185. }
  186. bool set_global_data()
  187. {
  188. // Initialize the read/write lock.
  189. init_rwlock(&lock_eid);
  190. // Get the saved launch token.
  191. // If error occures, zero the token.
  192. ifstream ifs(TOKEN_NAME, std::ios::binary | std::ios::in);
  193. if(!ifs.good())
  194. {
  195. memset(token, 0, sizeof(sgx_launch_token_t));
  196. }
  197. else
  198. {
  199. ifs.read(reinterpret_cast<char *>(&token), sizeof(sgx_launch_token_t));
  200. if(ifs.fail())
  201. {
  202. memset(&token, 0, sizeof(sgx_launch_token_t));
  203. }
  204. }
  205. // Allocate memory to save the sealed data.
  206. uint32_t sealed_len = sizeof(sgx_sealed_data_t) + sizeof(uint32_t);
  207. for(int i = 0; i < BUF_NUM; i++)
  208. {
  209. sealed_buf.sealed_buf_ptr[i] = (uint8_t *)malloc(sealed_len);
  210. if(sealed_buf.sealed_buf_ptr[i] == NULL)
  211. {
  212. cout << "Out of memory" << endl;
  213. return false;
  214. }
  215. memset(sealed_buf.sealed_buf_ptr[i], 0, sealed_len);
  216. }
  217. sealed_buf.index = 0; // index indicates which buffer contains current sealed data and which contains the backup sealed data
  218. return true;
  219. }
  220. void release_source()
  221. {
  222. for(int i = 0; i < BUF_NUM; i++)
  223. {
  224. if(sealed_buf.sealed_buf_ptr[i] != NULL)
  225. {
  226. free(sealed_buf.sealed_buf_ptr[i]);
  227. sealed_buf.sealed_buf_ptr[i] = NULL;
  228. }
  229. }
  230. fini_rwlock(&lock_eid);
  231. return;
  232. }
  233. int main(int argc, char* argv[])
  234. {
  235. (void)argc, (void)argv;
  236. // Initialize the global data
  237. if(!set_global_data())
  238. {
  239. release_source();
  240. cout << "Enter a character before exit ..." << endl;
  241. getchar();
  242. return -1;
  243. }
  244. // Load and initialize the signed enclave
  245. // sealed_buf == NULL indicates it is the first time to initialize the enclave.
  246. sgx_status_t ret = load_and_initialize_enclave(&global_eid , NULL);
  247. if(ret != SGX_SUCCESS)
  248. {
  249. ret_error_support(ret);
  250. release_source();
  251. cout << "Enter a character before exit ..." << endl;
  252. getchar();
  253. return -1;
  254. }
  255. cout << "****************************************************************" << endl;
  256. cout << "Demonstrating Power transition needs your cooperation." << endl
  257. << "Please take the following actions:" << endl
  258. << " 1. Enter a character;" << endl
  259. << " 2. Manually put the OS into a sleep or hibernate state;" << endl
  260. << " 3. Resume the OS from that state;" << endl
  261. << "Then you will see the application continues." << endl;
  262. cout << "****************************************************************" << endl;
  263. cout << "Now enter a character ...";
  264. getchar();
  265. // Create multiple threads to calculate the sum
  266. thread trd[THREAD_NUM];
  267. for (int i = 0; i< THREAD_NUM; i++)
  268. {
  269. trd[i] = thread(thread_func);
  270. }
  271. for (int i = 0; i < THREAD_NUM; i++)
  272. {
  273. trd[i].join();
  274. }
  275. // Release resources
  276. release_source();
  277. // Destroy the enclave
  278. sgx_destroy_enclave(global_eid);
  279. cout << "Enter a character before exit ..." << endl;
  280. getchar();
  281. return 0;
  282. }