serverMain.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  1. #include <atomic>
  2. #include <chrono>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <cstring>
  6. #include <cstdlib>
  7. #include <vector>
  8. #include <string>
  9. #include "networkServer.hpp"
  10. using namespace std;
  11. atomic<size_t> epochNum(0);
  12. // Initialize the classes we use
  13. void initialize_prsona_classes()
  14. {
  15. Scalar::init();
  16. PrsonaBase::init();
  17. PrsonaBase::set_client_malicious();
  18. }
  19. PrsonaServer *create_server_from_bgn_file(
  20. size_t numServers,
  21. struct synchronization_tool *sync,
  22. const char *filename)
  23. {
  24. unique_lock<mutex> lck(sync->mtx);
  25. ifstream bgnFile(filename);
  26. BGN privateKey;
  27. bgnFile >> privateKey;
  28. return new PrsonaServer(numServers, privateKey);
  29. }
  30. Twistpoint update_generator_from_gen_file(
  31. Proof& pi,
  32. struct synchronization_tool *sync,
  33. const char *filename)
  34. {
  35. unique_lock<mutex> lck(sync->mtx);
  36. ifstream genFile(filename);
  37. Twistpoint retval;
  38. genFile >> pi;
  39. genFile >> retval;
  40. return retval;
  41. }
  42. Twistpoint update_data_from_epoch_gen_file(
  43. vector<Proof>& pi,
  44. struct synchronization_tool *sync,
  45. const char *filename)
  46. {
  47. unique_lock<mutex> lck(sync->mtx);
  48. ifstream epochFile(filename);
  49. Twistpoint retval;
  50. BinarySizeT sizeOfVector;
  51. pi.clear();
  52. epochFile >> sizeOfVector;
  53. for (size_t i = 0; i < sizeOfVector.val(); i++)
  54. {
  55. Proof currProof;
  56. epochFile >> currProof;
  57. pi.push_back(currProof);
  58. }
  59. epochFile >> retval;
  60. return retval;
  61. }
  62. static int epoch_websocket_data_handler(
  63. struct mg_connection *conn,
  64. int bits,
  65. char *data,
  66. size_t data_len,
  67. void *user_data)
  68. {
  69. if ((bits & 0xf) == MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE || (bits & 0xf) == MG_WEBSOCKET_OPCODE_DATACOMPLETE)
  70. return false;
  71. if ((bits & 0xf) == MG_WEBSOCKET_OPCODE_DATACOMPLETE)
  72. {
  73. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  74. unique_lock<mutex> lck(sync->mtx);
  75. sync->val++;
  76. return false;
  77. }
  78. if ((bits & 0xf) != MG_WEBSOCKET_OPCODE_BINARY && (bits & 0xf) != MG_WEBSOCKET_OPCODE_CONTINUATION)
  79. {
  80. std::cerr << "Unknown opcode: failing." << std::endl;
  81. return false;
  82. }
  83. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  84. char *filename = (char *) mg_get_user_connection_data(conn);
  85. unique_lock<mutex> lck(sync->mtx);
  86. FILE *currFile = fopen(filename, "ab");
  87. fwrite(data, sizeof(char), data_len, currFile);
  88. fclose(currFile);
  89. return true;
  90. }
  91. static void epoch_websocket_close_handler(
  92. const struct mg_connection *conn,
  93. void *user_data)
  94. {
  95. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  96. unique_lock<mutex> lck(sync->mtx);
  97. sync->val2 = 0;
  98. sync->cv.notify_all();
  99. }
  100. Twistpoint get_generator(
  101. default_random_engine& rng,
  102. vector<Proof>& pi,
  103. PrsonaServer *prsonaServer,
  104. const vector<string>& serverIPs,
  105. const vector<int>& serverPorts,
  106. const string& selfIP,
  107. int selfPort,
  108. bool fresh)
  109. {
  110. Twistpoint retval = PrsonaServer::EL_GAMAL_GENERATOR;
  111. pi.clear();
  112. if (fresh)
  113. retval = prsonaServer->add_curr_seed_to_generator(pi, retval);
  114. else
  115. retval = prsonaServer->add_rand_seed_to_generator(pi, retval);
  116. const char* which = (fresh ? GET_FRESH_GEN_URI : GET_BLIND_GEN_URI);
  117. for (size_t i = 0; i < serverIPs.size(); i++)
  118. {
  119. if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
  120. continue;
  121. struct synchronization_tool generatorSync;
  122. char *genFilename;
  123. bool flag = false;
  124. while (!flag)
  125. {
  126. struct mg_connection *conn =
  127. mg_connect_websocket_client(
  128. serverIPs[i].c_str(),
  129. serverPorts[i],
  130. USE_SSL,
  131. NULL,
  132. 0,
  133. which,
  134. "null",
  135. file_websocket_data_handler,
  136. file_websocket_close_handler,
  137. &generatorSync);
  138. if (!conn)
  139. {
  140. cerr << "Couldn't get server " << i << "'s update on generator" << endl;
  141. continue;
  142. }
  143. stringstream buffer;
  144. string data;
  145. buffer << retval;
  146. data = buffer.str();
  147. mg_websocket_client_write(
  148. conn,
  149. MG_WEBSOCKET_OPCODE_BINARY,
  150. data.c_str(),
  151. data.length());
  152. unique_lock<mutex> lck(generatorSync.mtx);
  153. genFilename = set_temp_filename(rng, conn);
  154. generatorSync.val = 0;
  155. mg_websocket_client_write(
  156. conn,
  157. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  158. "",
  159. 0);
  160. while (!generatorSync.val)
  161. generatorSync.cv.wait(lck);
  162. mg_close_connection(conn);
  163. flag = true;
  164. }
  165. Proof currProof;
  166. retval = update_generator_from_gen_file(currProof, &generatorSync, genFilename);
  167. pi.push_back(currProof);
  168. remove(genFilename);
  169. delete [] genFilename;
  170. }
  171. return retval;
  172. }
  173. void handout_generator(
  174. const vector<Proof>& pi,
  175. const Twistpoint& generator,
  176. PrsonaServer *prsonaServer,
  177. const vector<string>& serverIPs,
  178. const vector<int>& serverPorts,
  179. const string& selfIP,
  180. int selfPort,
  181. bool fresh)
  182. {
  183. if (fresh)
  184. prsonaServer->initialize_fresh_generator(pi, generator);
  185. else
  186. prsonaServer->set_EG_blind_generator(pi, generator);
  187. stringstream buffer;
  188. string data;
  189. const char* which = (fresh ? GIVE_FRESH_GEN_URI : GIVE_BLIND_GEN_URI);
  190. BinarySizeT sizeOfVector(pi.size());
  191. buffer << sizeOfVector;
  192. for (size_t i = 0; i < sizeOfVector.val(); i++)
  193. buffer << pi[i];
  194. buffer << generator;
  195. data = buffer.str();
  196. for (size_t i = 0; i < serverIPs.size(); i++)
  197. {
  198. if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
  199. continue;
  200. bool flag = false;
  201. while (!flag)
  202. {
  203. struct mg_connection *conn =
  204. mg_connect_websocket_client(
  205. serverIPs[i].c_str(),
  206. serverPorts[i],
  207. USE_SSL,
  208. NULL,
  209. 0,
  210. which,
  211. "null",
  212. empty_websocket_data_handler,
  213. empty_websocket_close_handler,
  214. NULL);
  215. if (!conn)
  216. {
  217. cerr << "Couldn't give " << (fresh ? "fresh" : "blind") << " generator to server " << i << endl;
  218. continue;
  219. }
  220. mg_websocket_client_write(
  221. conn,
  222. MG_WEBSOCKET_OPCODE_BINARY,
  223. data.c_str(),
  224. data.length());
  225. mg_websocket_client_write(
  226. conn,
  227. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  228. "",
  229. 0);
  230. mg_close_connection(conn);
  231. flag = true;
  232. }
  233. }
  234. }
  235. Twistpoint initiate_epoch_updates(
  236. default_random_engine& rng,
  237. const string& recipient,
  238. int recipientPort,
  239. const string& data,
  240. vector<vector<Proof>>& generatorProofHolder,
  241. bool isBreakdown)
  242. {
  243. Twistpoint retval;
  244. struct synchronization_tool epochSync;
  245. char * epochFilename;
  246. const char* which = (isBreakdown ? EPOCH_BREAK_DOWN_URI : EPOCH_BUILD_UP_URI);
  247. bool flag = false;
  248. while (!flag)
  249. {
  250. struct mg_connection *conn =
  251. mg_connect_websocket_client(
  252. recipient.c_str(),
  253. recipientPort,
  254. USE_SSL,
  255. NULL,
  256. 0,
  257. which,
  258. "null",
  259. epoch_websocket_data_handler,
  260. epoch_websocket_close_handler,
  261. &epochSync);
  262. if (!conn)
  263. {
  264. std::cerr << "Trouble initiating epoch update with server at " << recipient << std::endl;
  265. continue;
  266. }
  267. unique_lock<mutex> lck(epochSync.mtx);
  268. epochFilename = set_temp_filename(rng, conn);
  269. epochSync.val = 0;
  270. epochSync.val2 = 1;
  271. mg_websocket_client_write(
  272. conn,
  273. MG_WEBSOCKET_OPCODE_BINARY,
  274. data.c_str(),
  275. data.length());
  276. mg_websocket_client_write(
  277. conn,
  278. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  279. "",
  280. 0);
  281. while (epochSync.val2)
  282. epochSync.cv.wait(lck);
  283. if (!epochSync.val)
  284. flag = true;
  285. mg_close_connection(conn);
  286. }
  287. if (isBreakdown)
  288. return retval;
  289. vector<Proof> generatorProof;
  290. generatorProofHolder.clear();
  291. retval = update_data_from_epoch_gen_file(generatorProof, &epochSync, epochFilename);
  292. generatorProofHolder.push_back(generatorProof);
  293. remove(epochFilename);
  294. delete [] epochFilename;
  295. return retval;
  296. }
  297. vector<Proof> epoch_build_up(
  298. PrsonaServer *prsonaServer,
  299. default_random_engine& rng,
  300. const vector<string>& serverIPs,
  301. const vector<int>& serverPorts,
  302. const string& selfIP,
  303. int selfPort,
  304. Twistpoint& nextGenerator)
  305. {
  306. std::vector<std::vector<std::vector<Proof>>> pi;
  307. std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
  308. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
  309. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
  310. std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
  311. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
  312. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
  313. std::vector<std::vector<Proof>> generatorProofHolder(1);
  314. for (size_t i = 0; i < serverIPs.size(); i++)
  315. {
  316. if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
  317. {
  318. pi.clear();
  319. permutationCommits.clear();
  320. freshPseudonymCommits.clear();
  321. freshPseudonymSeedCommits.clear();
  322. serverTallyCommits.clear();
  323. partwayVoteMatrixCommits.clear();
  324. finalVoteMatrixCommits.clear();
  325. pi.push_back(generatorProofHolder);
  326. prsonaServer->build_up_midway_pseudonyms(
  327. pi,
  328. permutationCommits,
  329. freshPseudonymCommits,
  330. freshPseudonymSeedCommits,
  331. serverTallyCommits,
  332. partwayVoteMatrixCommits,
  333. finalVoteMatrixCommits,
  334. nextGenerator);
  335. vector<vector<Twistpoint>> currUserTallyMaskCommits;
  336. vector<vector<Twistpoint>> currUserTallyMessageCommits;
  337. vector<vector<Twistpoint>> currUserTallySeedCommits;
  338. string data = make_epoch_update_string(
  339. pi[1],
  340. permutationCommits[0],
  341. freshPseudonymCommits[0],
  342. freshPseudonymSeedCommits[0],
  343. serverTallyCommits[0],
  344. partwayVoteMatrixCommits[0],
  345. finalVoteMatrixCommits[0],
  346. currUserTallyMaskCommits,
  347. currUserTallyMessageCommits,
  348. currUserTallySeedCommits,
  349. nextGenerator,
  350. false);
  351. struct synchronization_tool epochSync;
  352. vector<struct mg_connection *> conns;
  353. unique_lock<mutex> lck(epochSync.mtx);
  354. epochSync.val = 1;
  355. for (size_t j = 0; j < serverIPs.size(); j++)
  356. {
  357. if (i == j)
  358. continue;
  359. struct mg_connection *currConn =
  360. distribute_epoch_updates(
  361. serverIPs[j],
  362. serverPorts[j],
  363. data,
  364. &epochSync);
  365. conns.push_back(currConn);
  366. }
  367. while (epochSync.val < serverIPs.size())
  368. epochSync.cv.wait(lck);
  369. for (size_t j = 0; j < conns.size(); j++)
  370. mg_close_connection(conns[j]);
  371. generatorProofHolder = pi[0];
  372. }
  373. else
  374. {
  375. string data = make_epoch_initiator_string(
  376. generatorProofHolder[0],
  377. nextGenerator);
  378. nextGenerator = initiate_epoch_updates(
  379. rng,
  380. serverIPs[i],
  381. serverPorts[i],
  382. data,
  383. generatorProofHolder,
  384. false);
  385. }
  386. }
  387. return generatorProofHolder[0];
  388. }
  389. void epoch_break_down(
  390. PrsonaServer *prsonaServer,
  391. default_random_engine& rng,
  392. const vector<string>& serverIPs,
  393. const vector<int>& serverPorts,
  394. const string& selfIP,
  395. int selfPort,
  396. const vector<Proof>& generatorProof,
  397. const Twistpoint& nextGenerator)
  398. {
  399. std::vector<std::vector<std::vector<Proof>>> pi;
  400. std::vector<std::vector<std::vector<Twistpoint>>> permutationCommits;
  401. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymCommits;
  402. std::vector<std::vector<std::vector<Twistpoint>>> freshPseudonymSeedCommits;
  403. std::vector<std::vector<std::vector<CurveBipoint>>> serverTallyCommits;
  404. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> partwayVoteMatrixCommits;
  405. std::vector<std::vector<std::vector<std::vector<TwistBipoint>>>> finalVoteMatrixCommits;
  406. std::vector<std::vector<std::vector<Twistpoint>>> userTallyMaskCommits;
  407. std::vector<std::vector<std::vector<Twistpoint>>> userTallyMessageCommits;
  408. std::vector<std::vector<std::vector<Twistpoint>>> userTallySeedCommits;
  409. for (size_t i = 0; i < serverIPs.size(); i++)
  410. {
  411. pi.clear();
  412. permutationCommits.clear();
  413. freshPseudonymCommits.clear();
  414. freshPseudonymSeedCommits.clear();
  415. serverTallyCommits.clear();
  416. partwayVoteMatrixCommits.clear();
  417. finalVoteMatrixCommits.clear();
  418. userTallyMaskCommits.clear();
  419. userTallyMessageCommits.clear();
  420. userTallySeedCommits.clear();
  421. if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
  422. {
  423. prsonaServer->break_down_midway_pseudonyms(
  424. generatorProof,
  425. pi,
  426. permutationCommits,
  427. freshPseudonymCommits,
  428. freshPseudonymSeedCommits,
  429. serverTallyCommits,
  430. partwayVoteMatrixCommits,
  431. finalVoteMatrixCommits,
  432. userTallyMaskCommits,
  433. userTallyMessageCommits,
  434. userTallySeedCommits,
  435. nextGenerator);
  436. string data = make_epoch_update_string(
  437. pi[0],
  438. permutationCommits[0],
  439. freshPseudonymCommits[0],
  440. freshPseudonymSeedCommits[0],
  441. serverTallyCommits[0],
  442. partwayVoteMatrixCommits[0],
  443. finalVoteMatrixCommits[0],
  444. userTallyMaskCommits[0],
  445. userTallyMessageCommits[0],
  446. userTallySeedCommits[0],
  447. nextGenerator,
  448. true);
  449. struct synchronization_tool epochSync;
  450. vector<struct mg_connection *> conns;
  451. epochSync.val = 1;
  452. for (size_t j = 0; j < serverIPs.size(); j++)
  453. {
  454. if (i == j)
  455. continue;
  456. struct mg_connection *currConn =
  457. distribute_epoch_updates(
  458. serverIPs[j],
  459. serverPorts[j],
  460. data,
  461. &epochSync);
  462. conns.push_back(currConn);
  463. }
  464. unique_lock<mutex> lck(epochSync.mtx);
  465. while (epochSync.val < serverIPs.size())
  466. epochSync.cv.wait(lck);
  467. for (size_t j = 0; j < conns.size(); j++)
  468. mg_close_connection(conns[j]);
  469. }
  470. else
  471. {
  472. vector<vector<Proof>> unused;
  473. string data = make_epoch_initiator_string(
  474. generatorProof,
  475. nextGenerator);
  476. initiate_epoch_updates(
  477. rng,
  478. serverIPs[i],
  479. serverPorts[i],
  480. data,
  481. unused,
  482. true);
  483. }
  484. }
  485. }
  486. void tally_scores(
  487. PrsonaServer *prsonaServer,
  488. const vector<string>& serverIPs,
  489. const vector<int>& serverPorts,
  490. const string& selfIP,
  491. int selfPort,
  492. const Twistpoint& nextGenerator,
  493. std::vector<EGCiphertext>& userTallyScores,
  494. std::vector<CurveBipoint>& serverTallyScores)
  495. {
  496. struct synchronization_tool tallySync;
  497. vector<struct mg_connection *> conns;
  498. unique_lock<mutex> lck(tallySync.mtx);
  499. tallySync.val = 1;
  500. for (size_t i = 0; i < serverIPs.size(); i++)
  501. {
  502. if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
  503. continue;
  504. struct mg_connection *currConn = NULL;
  505. while (!currConn)
  506. {
  507. currConn = mg_connect_websocket_client(
  508. serverIPs[i].c_str(),
  509. serverPorts[i],
  510. USE_SSL,
  511. NULL,
  512. 0,
  513. GET_DECRYPTION_URI,
  514. "null",
  515. synchro_websocket_data_handler,
  516. synchro_websocket_close_handler,
  517. &tallySync);
  518. if (!currConn)
  519. cerr << "Trouble getting partial decryption from server at " << serverIPs[i] << ":" << serverPorts[i] << endl;
  520. }
  521. mg_websocket_client_write(
  522. currConn,
  523. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  524. "",
  525. 0);
  526. conns.push_back(currConn);
  527. }
  528. while (tallySync.val < serverIPs.size())
  529. tallySync.cv.wait(lck);
  530. for (size_t i = 0; i < conns.size(); i++)
  531. mg_close_connection(conns[i]);
  532. std::vector<EGCiphertext> retval;
  533. std::vector<Twistpoint> currentPseudonyms = prsonaServer->get_current_pseudonyms();
  534. std::vector<Scalar> decryptedTalliedScores = prsonaServer->tally_scores();
  535. mpz_class maxScorePossibleThisRound =
  536. prsonaServer->get_max_possible_score().toInt() *
  537. PrsonaBase::get_max_allowed_vote();
  538. mpz_class topOfScoreRange =
  539. decryptedTalliedScores.size() * PrsonaBase::get_max_allowed_vote();
  540. userTallyScores.clear();
  541. serverTallyScores.clear();
  542. for (size_t i = 0; i < decryptedTalliedScores.size(); i++)
  543. {
  544. decryptedTalliedScores[i] =
  545. Scalar(
  546. (decryptedTalliedScores[i].toInt() * topOfScoreRange) /
  547. maxScorePossibleThisRound
  548. );
  549. EGCiphertext currCiphertext;
  550. userTallyScores.push_back(currCiphertext);
  551. CurveBipoint currServerScore;
  552. serverTallyScores.push_back(currServerScore);
  553. Scalar currMask;
  554. currMask.set_random();
  555. // Give the server the new weights,
  556. // to get passed around to the other servers
  557. prsonaServer->encrypt(
  558. serverTallyScores[i], decryptedTalliedScores[i]);
  559. userTallyScores[i].mask = currentPseudonyms[i] * currMask;
  560. userTallyScores[i].encryptedMessage =
  561. (nextGenerator * currMask) +
  562. (prsonaServer->get_blinding_generator() * decryptedTalliedScores[i]);
  563. }
  564. }
  565. void distribute_tallied_scores(
  566. PrsonaServer *prsonaServer,
  567. const vector<string>& serverIPs,
  568. const vector<int>& serverPorts,
  569. const string& selfIP,
  570. int selfPort,
  571. const Twistpoint& nextGenerator,
  572. const std::vector<EGCiphertext>& userTallyScores,
  573. const std::vector<CurveBipoint>& serverTallyScores)
  574. {
  575. stringstream buffer;
  576. string data;
  577. BinarySizeT sizeOfVector(userTallyScores.size());
  578. buffer << sizeOfVector;
  579. for (size_t i = 0; i < sizeOfVector.val(); i++)
  580. buffer << userTallyScores[i];
  581. for (size_t i = 0; i < sizeOfVector.val(); i++)
  582. buffer << serverTallyScores[i];
  583. data = buffer.str();
  584. struct synchronization_tool tallySync;
  585. vector<struct mg_connection *> conns;
  586. unique_lock<mutex> lck(tallySync.mtx);
  587. prsonaServer->receive_tallied_scores(userTallyScores, serverTallyScores);
  588. tallySync.val = 1;
  589. for (size_t i = 0; i < serverIPs.size(); i++)
  590. {
  591. if (serverIPs[i] == selfIP && serverPorts[i] == selfPort)
  592. continue;
  593. struct mg_connection *currConn = NULL;
  594. while (!currConn)
  595. {
  596. currConn = mg_connect_websocket_client(
  597. serverIPs[i].c_str(),
  598. serverPorts[i],
  599. USE_SSL,
  600. NULL,
  601. 0,
  602. GIVE_DECRYPTION_URI,
  603. "null",
  604. synchro_websocket_data_handler,
  605. synchro_websocket_close_handler,
  606. &tallySync);
  607. if (!currConn)
  608. cerr << "Trouble giving full re-encryption to server at " << serverIPs[i] << ":" << serverPorts[i] << endl;
  609. }
  610. mg_websocket_client_write(
  611. currConn,
  612. MG_WEBSOCKET_OPCODE_BINARY,
  613. data.c_str(),
  614. data.length());
  615. mg_websocket_client_write(
  616. currConn,
  617. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  618. "",
  619. 0);
  620. conns.push_back(currConn);
  621. }
  622. while (tallySync.val < serverIPs.size())
  623. tallySync.cv.wait(lck);
  624. for (size_t i = 0; i < conns.size(); i++)
  625. mg_close_connection(conns[i]);
  626. }
  627. void epoch(
  628. mutex *updateMtx,
  629. atomic<size_t> *epochNum,
  630. PrsonaServer *prsonaServer,
  631. default_random_engine& rng,
  632. const vector<string>& serverIPs,
  633. const vector<int>& serverPorts,
  634. const string& selfIP,
  635. int selfPort)
  636. {
  637. Twistpoint nextGenerator = PrsonaServer::EL_GAMAL_GENERATOR;
  638. struct synchronization_tool updateSync;
  639. unique_lock<mutex> lck(*updateMtx, defer_lock);
  640. obtain_update_locks(
  641. lck,
  642. serverIPs,
  643. serverPorts,
  644. selfIP,
  645. selfPort,
  646. &updateSync);
  647. vector<Proof> generatorProof =
  648. epoch_build_up(
  649. prsonaServer,
  650. rng,
  651. serverIPs,
  652. serverPorts,
  653. selfIP,
  654. selfPort,
  655. nextGenerator);
  656. std::vector<EGCiphertext> currentUserEncryptedTallies;
  657. std::vector<CurveBipoint> currentServerEncryptedTallies;
  658. tally_scores(
  659. prsonaServer,
  660. serverIPs,
  661. serverPorts,
  662. selfIP,
  663. selfPort,
  664. nextGenerator,
  665. currentUserEncryptedTallies,
  666. currentServerEncryptedTallies);
  667. distribute_tallied_scores(
  668. prsonaServer,
  669. serverIPs,
  670. serverPorts,
  671. selfIP,
  672. selfPort,
  673. nextGenerator,
  674. currentUserEncryptedTallies,
  675. currentServerEncryptedTallies);
  676. epoch_break_down(
  677. prsonaServer,
  678. rng,
  679. serverIPs,
  680. serverPorts,
  681. selfIP,
  682. selfPort,
  683. generatorProof,
  684. nextGenerator);
  685. epochNum->fetch_add(1);
  686. release_update_locks(
  687. lck,
  688. serverIPs,
  689. serverPorts,
  690. selfIP,
  691. selfPort,
  692. &updateSync);
  693. }
  694. class EpochReadyHandler : public CivetHandler
  695. {
  696. public:
  697. EpochReadyHandler(struct synchronization_tool *exitSync, struct synchronization_tool *readySync, mutex *updateMtx, size_t numServers)
  698. : exitSync(exitSync), readySync(readySync), updateMtx(updateMtx), numServers(numServers)
  699. { /* */ }
  700. bool handleGet(CivetServer *server, struct mg_connection *conn)
  701. {
  702. unique_lock<mutex> exitLock(exitSync->mtx, defer_lock);
  703. unique_lock<mutex> updateLock(*updateMtx, defer_lock);
  704. unique_lock<mutex> readyLock(readySync->mtx);
  705. if (readySync->val < numServers)
  706. {
  707. mg_printf(conn,
  708. "HTTP/1.1 503 Service Unavailable\r\nContent-Type: "
  709. "text/plain\r\nConnection: close\r\n\r\n");
  710. mg_printf(conn, "Server is waiting for other servers to begin.\n");
  711. }
  712. else if (!exitLock.try_lock())
  713. {
  714. mg_printf(conn,
  715. "HTTP/1.1 503 Service Unavailable\r\nContent-Type: "
  716. "text/plain\r\nConnection: close\r\n\r\n");
  717. mg_printf(conn, "Server is still in a previous epoch.\n");
  718. }
  719. else if (!updateLock.try_lock())
  720. {
  721. mg_printf(conn,
  722. "HTTP/1.1 503 Service Unavailable\r\nContent-Type: "
  723. "text/plain\r\nConnection: close\r\n\r\n");
  724. mg_printf(conn, "Server is handling other updates.\n");
  725. }
  726. else
  727. {
  728. mg_printf(conn,
  729. "HTTP/1.1 200 OK\r\nContent-Type: "
  730. "text/plain\r\nConnection: close\r\n\r\n");
  731. mg_printf(conn, "Server is ready for epoch.\n");
  732. }
  733. return true;
  734. }
  735. private:
  736. struct synchronization_tool *exitSync, *readySync;
  737. mutex *updateMtx;
  738. const size_t numServers;
  739. };
  740. class EpochNumHandler : public CivetHandler
  741. {
  742. public:
  743. EpochNumHandler(atomic<size_t> *epochNum)
  744. : epochNum(epochNum)
  745. { /* */ }
  746. bool handleGet(CivetServer *server, struct mg_connection *conn)
  747. {
  748. mg_printf(conn,
  749. "HTTP/1.1 200 OK\r\nContent-Type: "
  750. "text/plain\r\nConnection: close\r\n\r\n");
  751. mg_printf(conn, "Epoch num: %lu\n", epochNum->load());
  752. return true;
  753. }
  754. private:
  755. atomic<size_t> *epochNum;
  756. };
  757. class UpdateLockWebSocketHandler : public CivetWebSocketHandler
  758. {
  759. public:
  760. UpdateLockWebSocketHandler(mutex *updateMtx, unique_lock<mutex> **lockHolder, bool isLocking)
  761. : updateMtx(updateMtx), lockHolder(lockHolder), isLocking(isLocking)
  762. { /* */ }
  763. ~UpdateLockWebSocketHandler()
  764. { delete *lockHolder; }
  765. bool handleConnection(CivetServer *server, const struct mg_connection *conn)
  766. { return true; }
  767. void handleReadyState(CivetServer *server, struct mg_connection *conn)
  768. { /* */ }
  769. bool handleData(CivetServer *server, struct mg_connection *conn, int bits, char *data, size_t data_len)
  770. {
  771. switch (bits & 0xf)
  772. {
  773. case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
  774. if (isLocking)
  775. {
  776. unique_lock<mutex> *tempHolder = new unique_lock<mutex>(*updateMtx);
  777. // Once you get to this line, we now hold the lock,
  778. // and lockHolder is guaranteed to be NULL
  779. *lockHolder = tempHolder;
  780. // Respond to notify that the requesting process holds the lock
  781. mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  782. }
  783. else
  784. {
  785. // You must do things in this order so that *lockHolder will be
  786. // guaranteed to be NULL at the time the lock unlocks
  787. // (deletion of the lock object)
  788. unique_lock<mutex> *tempHolder = *lockHolder;
  789. *lockHolder = NULL;
  790. delete tempHolder;
  791. // Respond to notify that the requesting process has released the lock
  792. mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_DATACOMPLETE, "", 0);
  793. }
  794. break;
  795. case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
  796. break;
  797. default:
  798. cerr << "Unknown opcode: failing." << endl;
  799. break;
  800. }
  801. return false;
  802. }
  803. void handleClose(CivetServer *server, const struct mg_connection *conn)
  804. { /* */ }
  805. private:
  806. mutex *updateMtx;
  807. unique_lock<mutex> **lockHolder;
  808. const bool isLocking;
  809. };
  810. int main(int argc, char *argv[])
  811. {
  812. initialize_prsona_classes();
  813. #if USE_SSL
  814. mg_init_library(0);
  815. #else
  816. mg_init_library(MG_FEATURES_SSL);
  817. #endif
  818. string id = "";
  819. if (argc > 1)
  820. id = argv[1];
  821. string seedStr;
  822. if (id.empty())
  823. seedStr = "default-server";
  824. else
  825. {
  826. seedStr = id;
  827. seedStr += "-server";
  828. }
  829. vector<string> serverIPs;
  830. vector<int> serverPorts;
  831. string selfIP, selfPortStr, dealerIP;
  832. int selfPort = 0, dealerPort = 0;
  833. char buffer[46], *helper;
  834. ifstream serverConfig("cfg/serverIPs.cfg");
  835. while (!serverConfig.eof())
  836. {
  837. serverConfig.getline(buffer, 46);
  838. if (strlen(buffer) > 0)
  839. {
  840. helper = buffer;
  841. if (strchr(helper, ':'))
  842. {
  843. helper = strtok(helper, ":");
  844. serverIPs.push_back(string(helper));
  845. helper = strtok(NULL, ":");
  846. serverPorts.push_back(atoi(helper));
  847. }
  848. else
  849. {
  850. serverIPs.push_back(string(helper));
  851. serverPorts.push_back(atoi(PRSONA_PORT_STR));
  852. }
  853. }
  854. }
  855. string selfConfigFilename = "cfg/selfIP";
  856. if (!id.empty())
  857. {
  858. selfConfigFilename += "-";
  859. selfConfigFilename += id;
  860. }
  861. selfConfigFilename += ".cfg";
  862. ifstream selfConfig(selfConfigFilename);
  863. while (!selfConfig.eof())
  864. {
  865. selfConfig.getline(buffer, 46);
  866. if (strlen(buffer) > 0)
  867. {
  868. helper = buffer;
  869. if (strchr(helper, ':'))
  870. {
  871. helper = strtok(helper, ":");
  872. selfIP = helper;
  873. helper = strtok(NULL, ":");
  874. selfPortStr = helper;
  875. selfPort = atoi(helper);
  876. }
  877. else
  878. {
  879. selfIP = helper;
  880. selfPortStr = PRSONA_PORT_STR;
  881. selfPort = atoi(PRSONA_PORT_STR);
  882. }
  883. }
  884. }
  885. ifstream dealerConfig("cfg/dealerIP.cfg");
  886. while (!dealerConfig.eof())
  887. {
  888. dealerConfig.getline(buffer, 46);
  889. if (strlen(buffer) > 0)
  890. {
  891. helper = buffer;
  892. if (strchr(helper, ':'))
  893. {
  894. helper = strtok(helper, ":");
  895. dealerIP = helper;
  896. helper = strtok(NULL, ":");
  897. dealerPort = atoi(helper);
  898. }
  899. else
  900. {
  901. dealerIP = helper;
  902. dealerPort = atoi(PRSONA_PORT_STR);
  903. }
  904. }
  905. }
  906. // Defaults
  907. size_t numServers = serverIPs.size();
  908. bool bgnDealer = selfIP == dealerIP && selfPort == dealerPort;
  909. bool maliciousServers = true;
  910. const char *options[] = {"listening_ports", selfPortStr.c_str(), 0};
  911. if (argc > 2)
  912. {
  913. bool setting = argv[2][0] == 't' || argv[2][0] == 'T';
  914. maliciousServers = setting;
  915. }
  916. seed_seq seed(seedStr.begin(), seedStr.end());
  917. default_random_engine rng(seed);
  918. cout << "[" << seedStr << "] Establishing PRSONA server with the following parameters: " << endl;
  919. cout << "[" << seedStr << "] " << numServers << " PRSONA servers" << endl;
  920. cout << "[" << seedStr << "] This server " << (bgnDealer ? "IS" : "is NOT") << " the trusted BGN dealer" << endl;
  921. cout << "[" << seedStr << "] Servers are set to " << (maliciousServers ? "MALICIOUS" : "HBC") << " security" << endl;
  922. cout << "[" << seedStr << "] This server is at IP address: " << selfIP << ":" << selfPort << endl;
  923. cout << "[" << seedStr << "] The BGN dealer is at IP address: " << dealerIP << ":" << dealerPort << endl;
  924. cout << endl;
  925. // Set malicious flags where necessary
  926. if (maliciousServers)
  927. PrsonaBase::set_server_malicious();
  928. struct synchronization_tool exitSync, readySync;
  929. mutex updateMtx;
  930. unique_lock<mutex> *updateLockHolder;
  931. atomic<size_t> epochNum(0);
  932. cout << "[" << seedStr << "] Creating PrsonaServer entity." << endl;
  933. // Entities we operate with
  934. PrsonaServer *prsonaServer;
  935. if (bgnDealer)
  936. prsonaServer = new PrsonaServer(numServers);
  937. else
  938. {
  939. cout << "[" << seedStr << "] Retrieving BGN details." << endl;
  940. struct synchronization_tool bgnSync;
  941. char *bgnFilename;
  942. bool flag = false;
  943. while (!flag)
  944. {
  945. struct mg_connection *conn =
  946. mg_connect_websocket_client(
  947. dealerIP.c_str(),
  948. dealerPort,
  949. USE_SSL,
  950. NULL,
  951. 0,
  952. PRIVATE_BGN_URI,
  953. "null",
  954. file_websocket_data_handler,
  955. file_websocket_close_handler,
  956. &bgnSync);
  957. if (!conn)
  958. {
  959. cerr << "[" << seedStr << "] Couldn't obtain BGN details." << endl;
  960. continue;
  961. }
  962. unique_lock<mutex> lck(bgnSync.mtx);
  963. bgnFilename = set_temp_filename(rng, conn);
  964. bgnSync.val = 0;
  965. mg_websocket_client_write(
  966. conn,
  967. MG_WEBSOCKET_OPCODE_DATACOMPLETE,
  968. "",
  969. 0);
  970. while (!bgnSync.val)
  971. bgnSync.cv.wait(lck);
  972. mg_close_connection(conn);
  973. flag = true;
  974. }
  975. prsonaServer = create_server_from_bgn_file(numServers, &bgnSync, bgnFilename);
  976. remove(bgnFilename);
  977. delete [] bgnFilename;
  978. }
  979. CivetServer server(options);
  980. PrsonaServerWebSocketHandler wsHandler(prsonaServer, &rng, &updateMtx, &epochNum, serverIPs, serverPorts, selfIP, selfPort);
  981. server.addWebSocketHandler("/ws", wsHandler);
  982. if (bgnDealer)
  983. {
  984. cout << "[" << seedStr << "] Waiting for other servers to check in and retrieve BGN details." << endl;
  985. unique_lock<mutex> lck(readySync.mtx);
  986. RemoteControlHandler serverReadyHandler(&readySync, "ACK");
  987. server.addHandler(SERVER_READY_URI, serverReadyHandler);
  988. readySync.val++;
  989. while (readySync.val < numServers)
  990. readySync.cv.wait(lck);
  991. vector<Proof> pi;
  992. Twistpoint freshGenerator =
  993. get_generator(rng, pi, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, true);
  994. handout_generator(pi, freshGenerator, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, true);
  995. Twistpoint blindGenerator =
  996. get_generator(rng, pi, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, false);
  997. handout_generator(pi, blindGenerator, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, false);
  998. }
  999. else
  1000. {
  1001. cout << "[" << seedStr << "] Notifying BGN dealer that this server is ready." << endl;
  1002. stringstream sysString;
  1003. string data;
  1004. struct mg_connection *conn =
  1005. mg_connect_client(
  1006. dealerIP.c_str(),
  1007. dealerPort,
  1008. USE_SSL,
  1009. NULL,
  1010. 0);
  1011. sysString << "GET " << SERVER_READY_URI << " HTTP/1.1\r\n";
  1012. sysString << "Host: " << dealerIP << ":" << dealerPort << "\r\n\r\n";
  1013. data = sysString.str();
  1014. mg_write(conn, data.c_str(), data.length());
  1015. mg_close_connection(conn);
  1016. }
  1017. unique_lock<mutex> exitLock(exitSync.mtx);
  1018. exitSync.val = 0;
  1019. exitSync.val2 = 0;
  1020. RemoteControlHandler exitHandler(&exitSync, "Server coming down!");
  1021. server.addHandler(EXIT_URI, exitHandler);
  1022. UpdateLockWebSocketHandler lockHandler(&updateMtx, &updateLockHolder, true);
  1023. UpdateLockWebSocketHandler unlockHandler(&updateMtx, &updateLockHolder, false);
  1024. server.addWebSocketHandler(UPDATE_LOCK_URI, lockHandler);
  1025. server.addWebSocketHandler(UPDATE_UNLOCK_URI, unlockHandler);
  1026. cout << "[" << seedStr << "] Entering main ready loop." << endl;
  1027. if (bgnDealer)
  1028. {
  1029. AltRemoteControlHandler triggerEpochHandler(1, &exitSync, "Server will initiate epoch!");
  1030. server.addHandler(TRIGGER_EPOCH_URI, triggerEpochHandler);
  1031. EpochReadyHandler epochReadyHandler(&exitSync, &readySync, &updateMtx, numServers);
  1032. server.addHandler(EPOCH_READY_URI, epochReadyHandler);
  1033. EpochNumHandler epochNumHandler(&epochNum);
  1034. server.addHandler(WHICH_EPOCH_URI, epochNumHandler);
  1035. while (!exitSync.val)
  1036. {
  1037. while (!exitSync.val && !exitSync.val2)
  1038. exitSync.cv.wait(exitLock);
  1039. if (exitSync.val2)
  1040. {
  1041. size_t currEpoch = epochNum.load();
  1042. cout << "[" << seedStr << "] Executing epoch calculations (going from t = " << currEpoch << " to " << currEpoch + 1 << ")." << endl;
  1043. epoch(&updateMtx, &epochNum, prsonaServer, rng, serverIPs, serverPorts, selfIP, selfPort);
  1044. currEpoch = epochNum.load();
  1045. cout << "[" << seedStr << "] Epoch calculations complete (now in t = " << currEpoch << ")." << endl;
  1046. exitSync.val2 = 0;
  1047. }
  1048. }
  1049. }
  1050. else
  1051. {
  1052. while (!exitSync.val)
  1053. exitSync.cv.wait(exitLock);
  1054. }
  1055. cout << "[" << seedStr << "] Shutting down." << endl;
  1056. mg_exit_library();
  1057. delete prsonaServer;
  1058. return 0;
  1059. }