serverMain.cpp 30 KB

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