serverMain.cpp 37 KB

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