storage.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. #include "utils.hpp"
  2. #include "config.hpp"
  3. #include "ORExpand.hpp"
  4. #include "sort.hpp"
  5. #include "storage.hpp"
  6. #include "client.hpp"
  7. #define PROFILE_STORAGE
  8. static std::vector<StgClient> clients;
  9. static uint8_t *epoch_tokens;
  10. static uint8_t *epoch_mailboxes;
  11. static struct {
  12. uint32_t max_users;
  13. uint32_t my_storage_node_id;
  14. // A local storage buffer, used when we need to do non-in-place
  15. // sorts of the messages that have arrived
  16. MsgBuffer stg_buf;
  17. // The destination vector for ORExpand
  18. std::vector<uint32_t> dest;
  19. } storage_state;
  20. static bool storage_generateClientKeys(uint32_t num_clients,
  21. uint32_t my_stg_no) {
  22. clients.resize(num_clients);
  23. for(uint32_t i =0; i < num_clients; i++) {
  24. uint32_t mid = storage_state.my_storage_node_id + i;
  25. clients[i].my_id = mid;
  26. clients[i].token_friends.resize(g_teems_config.m_token_out);
  27. // Initialize this client's token channel friends as themself
  28. for(int j = 0; j < g_teems_config.m_token_out; j++) {
  29. (clients[i].token_friends)[j] = mid;
  30. }
  31. }
  32. uint32_t num_stg_nodes = g_teems_config.num_storage_nodes;
  33. uint32_t c_simid = my_stg_no;
  34. for (uint32_t i=0; i<num_clients; i++) {
  35. const sgx_aes_gcm_128bit_key_t *pESK = &(g_teems_config.ESK);
  36. unsigned char zeroes[SGX_AESGCM_KEY_SIZE];
  37. unsigned char iv[SGX_AESGCM_IV_SIZE];
  38. sgx_aes_gcm_128bit_tag_t tag;
  39. memset(zeroes, 0, SGX_AESGCM_KEY_SIZE);
  40. memset(iv, 0, SGX_AESGCM_IV_SIZE);
  41. memcpy(iv, (uint8_t*) (&c_simid), sizeof(c_simid));
  42. memcpy(iv + sizeof(c_simid), "STG", sizeof("STG"));
  43. sgx_status_t ret = SGX_SUCCESS;
  44. ret = sgx_rijndael128GCM_encrypt(pESK, zeroes, SGX_AESGCM_KEY_SIZE,
  45. (uint8_t*) (clients[i].key), iv, SGX_AESGCM_IV_SIZE,
  46. NULL, 0, &tag);
  47. if(ret!=SGX_SUCCESS) {
  48. printf("stg_generateClientKeys FAIL\n");
  49. return false;
  50. }
  51. /*
  52. if(c_simid % 10 == 0) {
  53. printf("Storage: c_simid = %d, Key:", c_simid);
  54. for (int k = 0; k<SGX_AESGCM_KEY_SIZE; k++) {
  55. printf("%x", (clients[i].key)[k]);
  56. }
  57. printf("\n");
  58. }
  59. */
  60. c_simid+=num_stg_nodes;
  61. }
  62. return true;
  63. }
  64. struct UserRange {
  65. uint32_t start, num;
  66. bool ret;
  67. };
  68. static void* generate_all_tokens_launch(void *voidargs)
  69. {
  70. UserRange *args = (UserRange *)voidargs;
  71. uint32_t pt_tokens_size = (g_teems_config.m_token_out * SGX_CMAC_MAC_SIZE);
  72. uint32_t enc_tokens_size = pt_tokens_size +
  73. SGX_AESGCM_IV_SIZE + SGX_AESGCM_MAC_SIZE;
  74. unsigned char token_body[pt_tokens_size];
  75. uint32_t user_start = args->start;
  76. uint32_t user_end = args->start + args->num;
  77. const sgx_aes_gcm_128bit_key_t *pTSK = &(g_teems_config.TSK);
  78. for(uint32_t lcid=user_start; lcid < user_end; lcid++) {
  79. unsigned char *tkn_iv_ptr = epoch_tokens + enc_tokens_size * lcid;
  80. unsigned char *tkn_ptr = tkn_iv_ptr + SGX_AESGCM_IV_SIZE;
  81. unsigned char *tkn_tag = tkn_ptr + pt_tokens_size;
  82. // We construct the plaintext [S|R|Epoch] underlying the token in
  83. // the correct location for this client in the epoch_tokens buffer
  84. // The tokens ( i.e., CMAC over S|R|Epoch) is stored in token_body
  85. // Then encrypt token_body with the client's storage key and overwrite
  86. // the correct location in epoch_tokens
  87. memset(token_body, 0, pt_tokens_size);
  88. memset(tkn_iv_ptr, 0, SGX_AESGCM_IV_SIZE);
  89. // IV = epoch_no, for encrypting the token bundle
  90. // epoch_no used is for the next epoch
  91. unsigned long epoch_val = storage_epoch + 1;
  92. memcpy(tkn_iv_ptr, &epoch_val, sizeof(epoch_val));
  93. sgx_status_t ret = SGX_SUCCESS;
  94. unsigned char *ptr = tkn_ptr;
  95. unsigned char *tkn_body_ptr = token_body;
  96. for(int i = 0; i<g_teems_config.m_token_out; i++)
  97. {
  98. memcpy(ptr, (&(clients[lcid].my_id)), sizeof(clientid_t));
  99. memcpy(ptr + sizeof(clientid_t),
  100. (&(clients[lcid].token_friends[i])), sizeof(clientid_t));
  101. memcpy(ptr + 2 * sizeof(clientid_t),
  102. &epoch_val, sizeof(epoch_val));
  103. ret = sgx_rijndael128_cmac_msg(pTSK, ptr, pt_tokens_size,
  104. (sgx_cmac_128bit_tag_t*) tkn_body_ptr);
  105. if(ret!=SGX_SUCCESS) {
  106. printf("generate_tokens: Creating token FAIL\n");
  107. args->ret = false;
  108. return NULL;
  109. }
  110. ptr+=SGX_CMAC_MAC_SIZE;
  111. tkn_body_ptr+=SGX_CMAC_MAC_SIZE;
  112. }
  113. /*
  114. if(lcid == 0) {
  115. printf("Checking generated token_body:");
  116. for(uint32_t i = 0; i < pt_tokens_size; i++) {
  117. printf("%x", token_body[i]);
  118. }
  119. printf("\n");
  120. }
  121. */
  122. unsigned char *cl_iv = clients[lcid].iv;
  123. ret = (sgx_rijndael128GCM_encrypt(&(clients[lcid].key),
  124. token_body, pt_tokens_size,
  125. (uint8_t*) tkn_ptr, cl_iv, SGX_AESGCM_IV_SIZE, NULL, 0,
  126. (sgx_aes_gcm_128bit_tag_t*) tkn_tag));
  127. if(ret!=SGX_SUCCESS) {
  128. printf("generate_tokens: Encrypting token FAIL\n");
  129. args->ret = false;
  130. return NULL;
  131. }
  132. memcpy(tkn_iv_ptr, cl_iv, SGX_AESGCM_IV_SIZE);
  133. // Update IV
  134. uint64_t *iv_ctr = (uint64_t*) cl_iv;
  135. (*iv_ctr)+=1;
  136. /*
  137. if(lcid == 0) {
  138. printf("Encrypted client token bundle:");
  139. for(uint32_t i = 0; i < enc_tokens_size; i++) {
  140. printf("%x", tkn_iv_ptr[i]);
  141. }
  142. printf("\n");
  143. }
  144. */
  145. }
  146. args->ret = true;
  147. return NULL;
  148. }
  149. static bool launch_all_users(void *(*launch)(void *)) {
  150. threadid_t nthreads = g_teems_config.nthreads;
  151. // Special-case nthread=1 for efficiency
  152. if (nthreads <= 1) {
  153. UserRange args = { 0, storage_state.max_users, false };
  154. return launch(&args);
  155. }
  156. UserRange args[nthreads];
  157. uint32_t inc = storage_state.max_users / nthreads;
  158. uint32_t extra = storage_state.max_users % nthreads;
  159. uint32_t last = 0;
  160. for (threadid_t i=0; i<nthreads; ++i) {
  161. uint32_t num = inc + (i < extra);
  162. args[i] = { last, num, false };
  163. last += num;
  164. }
  165. // Launch all but the first section into other threads
  166. for (threadid_t i=1; i<nthreads; ++i) {
  167. threadpool_dispatch(g_thread_id+i, launch, args+i);
  168. }
  169. // Do the first section ourselves
  170. launch(args);
  171. // Join the threads
  172. for (threadid_t i=1; i<nthreads; ++i) {
  173. threadpool_join(g_thread_id+i, NULL);
  174. }
  175. bool ret = true;
  176. for (threadid_t i=0; i<nthreads; ++i) {
  177. ret &= args[i].ret;
  178. }
  179. return ret;
  180. }
  181. bool generate_all_tokens() {
  182. return launch_all_users(generate_all_tokens_launch);
  183. }
  184. // Obliviously sanitize the given message by setting everything to 0
  185. // except the sender and receiver id, which are set to 0xffffffff,
  186. // if it is a padding message (the low DEST_UID_BITS of the receiver id
  187. // are all 1). The function is oblivious as to whether the message is a
  188. // padding message. msg_size must be a multiple of 16.
  189. // sender_id_offset should be set to 4 for token-channel routing, or 8
  190. // for ID-channel routing.
  191. static inline void padding_sanitize_msg(unsigned char *msg,
  192. size_t msg_size, size_t sender_id_offset)
  193. {
  194. static const uint32_t uid_mask = (1<<DEST_UID_BITS)-1;
  195. // The first 4 bytes of the message are the receiver id
  196. uint32_t receiver_id = *(uint32_t*)msg;
  197. // The message is padding if receiver_id & uid_mask == uid_mask, or
  198. // equivalently, (~receiver_id) & uid_mask == 0.
  199. // So !((~receiver_id) & uid_mask) is 1 if this is a padding
  200. // message, and 0 if not. Then (!((~receiver_id) & uid_mask))-1 is
  201. // 0 if this is a padding message, and -1 (0xffffffffffffffff) if
  202. // not. ANDing this mask with the body will do what we want: keep
  203. // it unchanged if this is not padding, and set it to 0 if it is
  204. // padding
  205. uint64_t content_mask = (!((~receiver_id) & uid_mask))-1;
  206. // Mask the first 16 bytes, which includes the 8 or 12 byte header
  207. // (depending on token or ID-channel routing). The first 4
  208. // bytes are the destination id; set those to 0xffffffff if this is
  209. // a padding message. Set the rest of the first 16 bytes to 0 if
  210. // this is a padding message (all obliviously).
  211. *(uint32_t*)(msg) |= uint32_t(~content_mask);
  212. *(uint32_t*)(msg+4) &= uint32_t(content_mask);
  213. *(uint64_t*)(msg+8) &= content_mask;
  214. // Set the sender id to 0xffffffff if this is a padding message
  215. *(uint32_t*)(msg+sender_id_offset) |= uint32_t(~content_mask);
  216. // Set the rest of the message to 0 if this is a padding message
  217. unsigned char *msgend = msg + msg_size;
  218. for (msg = msg+16; msg<msgend; msg += 16) {
  219. *(uint64_t*)(msg) &= content_mask;
  220. *(uint64_t*)(msg+8) &= content_mask;
  221. }
  222. }
  223. /* processMsgs
  224. - Take all the messages in storage_state.stg_buf
  225. - Encrypt them all with their corresponding client key and IV and store into
  226. epoch_mailboxes
  227. */
  228. static void *processMsgs_launch(void *voidargs) {
  229. UserRange *args = (UserRange *)voidargs;
  230. uint32_t user_start = args->start;
  231. uint32_t user_end = args->start + args->num;
  232. uint32_t msg_size = g_teems_config.msg_size;
  233. uint32_t mailbox_size;
  234. size_t sender_id_offset;
  235. if (g_teems_config.token_channel) {
  236. mailbox_size = g_teems_config.m_token_in * msg_size;
  237. sender_id_offset = 4;
  238. } else {
  239. mailbox_size = g_teems_config.m_id_in * msg_size;
  240. sender_id_offset = 8;
  241. }
  242. uint32_t enc_mailbox_size = mailbox_size + SGX_AESGCM_IV_SIZE +
  243. SGX_AESGCM_MAC_SIZE;
  244. unsigned char *epoch_buf_ptr = epoch_mailboxes +
  245. enc_mailbox_size * user_start;
  246. unsigned char *stg_buf_ptr = storage_state.stg_buf.buf +
  247. mailbox_size * user_start;
  248. sgx_status_t ret = SGX_SUCCESS;
  249. unsigned char *epoch_buf_ct_ptr = epoch_buf_ptr + SGX_AESGCM_IV_SIZE;
  250. unsigned char *epoch_buf_tag_ptr = epoch_buf_ct_ptr + mailbox_size;
  251. for(uint32_t lcid = user_start; lcid < user_end; lcid++) {
  252. memcpy(epoch_buf_ptr, clients[lcid].iv, SGX_AESGCM_IV_SIZE);
  253. unsigned char *stg_buf_end = stg_buf_ptr + mailbox_size;
  254. for (unsigned char *msg = stg_buf_ptr; msg < stg_buf_end;
  255. msg += msg_size) {
  256. padding_sanitize_msg(msg, msg_size, sender_id_offset);
  257. }
  258. ret = sgx_rijndael128GCM_encrypt(&(clients[lcid].key), stg_buf_ptr,
  259. mailbox_size, (uint8_t*) epoch_buf_ct_ptr, epoch_buf_ptr,
  260. SGX_AESGCM_IV_SIZE, NULL, 0,
  261. (sgx_aes_gcm_128bit_tag_t*) epoch_buf_tag_ptr);
  262. if(ret!=SGX_SUCCESS) {
  263. printf("processMsgs: Encrypting msgs FAIL\n");
  264. args->ret = false;
  265. return NULL;
  266. }
  267. // Update IV
  268. uint64_t *iv_ctr = (uint64_t*) clients[lcid].iv;
  269. (*iv_ctr)+=1;
  270. /*
  271. if(lcid==0) {
  272. printf("\n\nMessage for lcid 0, S, R = %d, %d\n\n\n",
  273. *((uint32_t*) stg_buf_ptr),
  274. *((uint32_t*) (stg_buf_ptr + 4)));
  275. }
  276. */
  277. stg_buf_ptr+=mailbox_size;
  278. epoch_buf_ptr+=enc_mailbox_size;
  279. epoch_buf_ct_ptr+=enc_mailbox_size;
  280. epoch_buf_tag_ptr+=enc_mailbox_size;
  281. }
  282. args->ret = true;
  283. return NULL;
  284. }
  285. bool processMsgs() {
  286. return launch_all_users(processMsgs_launch);
  287. }
  288. // route_init will call this function; no one else should call it
  289. // explicitly. The parameter is the number of messages that can fit in
  290. // the storage-side MsgBuffer. Returns true on success, false on
  291. // failure.
  292. bool storage_init(uint32_t max_users, uint32_t msg_buf_size)
  293. {
  294. storage_state.max_users = max_users;
  295. storage_state.stg_buf.alloc(msg_buf_size);
  296. storage_state.dest.resize(msg_buf_size);
  297. uint32_t my_storage_node_id = 0;
  298. uint32_t my_stg_pos = 0;
  299. for (nodenum_t i=0; i<g_teems_config.num_nodes; ++i) {
  300. if (g_teems_config.roles[i] & ROLE_STORAGE) {
  301. if (i == g_teems_config.my_node_num) {
  302. storage_state.my_storage_node_id =
  303. my_storage_node_id << DEST_UID_BITS;
  304. my_stg_pos = my_storage_node_id;
  305. } else {
  306. ++my_storage_node_id;
  307. }
  308. }
  309. }
  310. storage_generateClientKeys(max_users, my_stg_pos);
  311. return true;
  312. }
  313. void storage_close() {
  314. }
  315. // Handle the messages received by a storage node. Pass a _locked_
  316. // MsgBuffer. This function will itself reset and unlock it when it's
  317. // done with it.
  318. void storage_received(MsgBuffer &storage_buf)
  319. {
  320. uint16_t msg_size = g_teems_config.msg_size;
  321. nodenum_t my_node_num = g_teems_config.my_node_num;
  322. const uint8_t *msgs = storage_buf.buf;
  323. uint32_t num_msgs = storage_buf.inserted;
  324. uint32_t real = 0, padding = 0;
  325. uint32_t uid_mask = (1 << DEST_UID_BITS) - 1;
  326. uint32_t nid_mask = ~uid_mask;
  327. #ifdef PROFILE_STORAGE
  328. unsigned long start_received =
  329. printf_with_rtclock("begin storage_received (%u)\n",
  330. storage_buf.inserted);
  331. #endif
  332. // It's OK to test for errors in a way that's non-oblivous if
  333. // there's an error (but it should be oblivious if there are no
  334. // errors)
  335. for (uint32_t i=0; i<num_msgs; ++i) {
  336. uint32_t uid = *(const uint32_t*)(storage_buf.buf+(i*msg_size));
  337. bool ok = ((((uid & nid_mask) == storage_state.my_storage_node_id)
  338. & ((uid & uid_mask) < storage_state.max_users))
  339. | ((uid & uid_mask) == uid_mask));
  340. if (!ok) {
  341. printf("Received bad uid: %08x\n", uid);
  342. assert(ok);
  343. }
  344. }
  345. // Testing: report how many real and dummy messages arrived
  346. printf("Storage server received %u messages:\n", num_msgs);
  347. for (uint32_t i=0; i<num_msgs; ++i) {
  348. uint32_t dest_addr = *(const uint32_t*)msgs;
  349. nodenum_t dest_node =
  350. g_teems_config.storage_map[dest_addr >> DEST_UID_BITS];
  351. if (dest_node != my_node_num) {
  352. char hexbuf[2*msg_size + 1];
  353. for (uint32_t j=0;j<msg_size;++j) {
  354. snprintf(hexbuf+2*j, 3, "%02x", msgs[j]);
  355. }
  356. printf("Misrouted message: %s\n", hexbuf);
  357. } else if ((dest_addr & uid_mask) == uid_mask) {
  358. ++padding;
  359. } else {
  360. ++real;
  361. }
  362. msgs += msg_size;
  363. }
  364. printf("%u real, %u padding\n", real, padding);
  365. /*
  366. for (uint32_t i=0;i<num_msgs; ++i) {
  367. printf("%3d: %08x %08x\n", i,
  368. *(uint32_t*)(storage_buf.buf+(i*msg_size)),
  369. *(uint32_t*)(storage_buf.buf+(i*msg_size+4)));
  370. }
  371. */
  372. // Sort the received messages by userid into the
  373. // storage_state.stg_buf MsgBuffer.
  374. #ifdef PROFILE_STORAGE
  375. unsigned long start_sort =
  376. printf_with_rtclock("begin oblivious sort (%u)\n",
  377. storage_buf.inserted);
  378. #endif
  379. sort_mtobliv<UidKey>(g_teems_config.nthreads, storage_buf.buf,
  380. msg_size, storage_buf.inserted, storage_buf.bufsize,
  381. storage_state.stg_buf.buf);
  382. #ifdef PROFILE_STORAGE
  383. printf_with_rtclock_diff(start_sort, "end oblivious sort (%u)\n",
  384. storage_buf.inserted);
  385. #endif
  386. /*
  387. for (uint32_t i=0;i<num_msgs; ++i) {
  388. printf("%3d: %08x %08x\n", i,
  389. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size)),
  390. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size+4)));
  391. }
  392. */
  393. #ifdef PROFILE_STORAGE
  394. unsigned long start_dest =
  395. printf_with_rtclock("begin setting dests (%u)\n",
  396. storage_state.stg_buf.bufsize);
  397. #endif
  398. // Obliviously set the dest array
  399. uint32_t *dests = storage_state.dest.data();
  400. uint32_t stg_size = storage_state.stg_buf.bufsize;
  401. uint8_t *buf = storage_state.stg_buf.buf;
  402. uint32_t m_in = g_teems_config.token_channel ?
  403. g_teems_config.m_token_in : g_teems_config.m_id_in;
  404. uint32_t uid = *(uint32_t*)(buf);
  405. uid &= uid_mask;
  406. // num_msgs is not a private value
  407. if (num_msgs > 0) {
  408. dests[0] = oselect_uint32_t(uid * m_in, 0xffffffff,
  409. uid == uid_mask);
  410. }
  411. uint32_t prev_uid = uid;
  412. for (uint32_t i=1; i<num_msgs; ++i) {
  413. uid = *(uint32_t*)(buf + i*msg_size);
  414. uid &= uid_mask;
  415. uint32_t next = oselect_uint32_t(uid * m_in, dests[i-1]+1,
  416. uid == prev_uid);
  417. dests[i] = oselect_uint32_t(next, 0xffffffff, uid == uid_mask);
  418. prev_uid = uid;
  419. }
  420. for (uint32_t i=num_msgs; i<stg_size; ++i) {
  421. dests[i] = 0xffffffff;
  422. *(uint32_t*)(buf + i*msg_size) = 0xffffffff;
  423. }
  424. #ifdef PROFILE_STORAGE
  425. printf_with_rtclock_diff(start_dest, "end setting dests (%u)\n", stg_size);
  426. #endif
  427. /*
  428. for (uint32_t i=0;i<stg_size; ++i) {
  429. printf("%3d: %08x %08x %08x %08x %u\n", i,
  430. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size)),
  431. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size+4)),
  432. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size+8)),
  433. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size+12)),
  434. dests[i]);
  435. }
  436. */
  437. #ifdef PROFILE_STORAGE
  438. unsigned long start_expand =
  439. printf_with_rtclock("begin ORExpand (%u)\n", stg_size);
  440. #endif
  441. ORExpand_parallel<OSWAP_16X>(storage_state.stg_buf.buf, dests,
  442. msg_size, stg_size, g_teems_config.nthreads);
  443. #ifdef PROFILE_STORAGE
  444. printf_with_rtclock_diff(start_expand, "end ORExpand (%u)\n", stg_size);
  445. #endif
  446. /*
  447. for (uint32_t i=0;i<stg_size; ++i) {
  448. printf("%3d: %08x %08x %08x %08x %u\n", i,
  449. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size)),
  450. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size+4)),
  451. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size+8)),
  452. *(uint32_t*)(storage_state.stg_buf.buf+(i*msg_size+12)),
  453. dests[i]);
  454. }
  455. */
  456. // You can do more processing after these lines, as long as they
  457. // don't touch storage_buf. They _can_ touch the backing buffer
  458. // storage_state.stg_buf.
  459. storage_buf.reset();
  460. pthread_mutex_unlock(&storage_buf.mutex);
  461. if (g_teems_config.token_channel) {
  462. generate_all_tokens();
  463. }
  464. processMsgs();
  465. storage_epoch++;
  466. storage_state.stg_buf.reset();
  467. #ifdef PROFILE_STORAGE
  468. printf_with_rtclock_diff(start_received,
  469. "end storage_received (%u)\n", storage_buf.inserted);
  470. #endif
  471. }
  472. bool ecall_storage_authenticate(clientid_t cid, unsigned char *auth_message)
  473. {
  474. bool ret = false;
  475. uint32_t lcid = cid / g_teems_config.num_storage_nodes;
  476. const sgx_aes_gcm_128bit_key_t *ckey = &(clients[lcid].key);
  477. ret = authenticateClient(auth_message, ckey);
  478. if(!ret) {
  479. printf("Storage authentication FAIL\n");
  480. }
  481. return ret;
  482. }
  483. void ecall_supply_storage_buffers(unsigned char *mailboxes,
  484. uint32_t mailboxes_size, unsigned char *tokens, uint32_t tokens_size)
  485. {
  486. epoch_mailboxes = mailboxes;
  487. epoch_tokens = tokens;
  488. }