gnunet-service-scalarproduct.c 86 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2013, 2014 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file scalarproduct/gnunet-service-scalarproduct.c
  19. * @brief scalarproduct service implementation
  20. * @author Christian M. Fuchs
  21. * @author Christian Grothoff
  22. */
  23. #include "platform.h"
  24. #include <limits.h>
  25. #include <gcrypt.h>
  26. #include "gnunet_util_lib.h"
  27. #include "gnunet_core_service.h"
  28. #include "gnunet_cadet_service.h"
  29. #include "gnunet_applications.h"
  30. #include "gnunet_protocols.h"
  31. #include "gnunet_scalarproduct_service.h"
  32. #include "gnunet_set_service.h"
  33. #include "scalarproduct.h"
  34. #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct", __VA_ARGS__)
  35. /**
  36. * Maximum count of elements we can put into a multipart message
  37. */
  38. #define MULTIPART_ELEMENT_CAPACITY ((GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct MultipartMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
  39. GNUNET_NETWORK_STRUCT_BEGIN
  40. /**
  41. * Message type passed from requesting service Alice to responding
  42. * service Bob to initiate a request and make Bob participate in our
  43. * protocol
  44. */
  45. struct ServiceRequestMessage
  46. {
  47. /**
  48. * Type is #GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION
  49. */
  50. struct GNUNET_MessageHeader header;
  51. /**
  52. * For alignment. Always zero.
  53. */
  54. uint32_t reserved;
  55. /**
  56. * The transaction/session key used to identify a session
  57. */
  58. struct GNUNET_HashCode session_id;
  59. /**
  60. * Alice's public key
  61. */
  62. struct GNUNET_CRYPTO_PaillierPublicKey public_key;
  63. };
  64. /**
  65. * Vector of Pallier-encrypted values sent by Alice to Bob
  66. * (after set intersection).
  67. */
  68. struct AliceCryptodataMessage
  69. {
  70. /**
  71. * Type is #GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA
  72. */
  73. struct GNUNET_MessageHeader header;
  74. /**
  75. * How many elements we appended to this message? In NBO.
  76. */
  77. uint32_t contained_element_count GNUNET_PACKED;
  78. /**
  79. * struct GNUNET_CRYPTO_PaillierCiphertext[contained_element_count]
  80. */
  81. };
  82. /**
  83. * Multipart Message type passed between to supply additional elements
  84. * for the peer.
  85. */
  86. struct MultipartMessage
  87. {
  88. /**
  89. * GNUNET message header
  90. */
  91. struct GNUNET_MessageHeader header;
  92. /**
  93. * How many elements we supply within this message? In NBO.
  94. */
  95. uint32_t contained_element_count GNUNET_PACKED;
  96. /**
  97. * struct GNUNET_CRYPTO_PaillierCiphertext[multipart_element_count]
  98. */
  99. };
  100. /**
  101. * Message type passed from responding service Bob to responding service Alice
  102. * to complete a request and allow Alice to compute the result.
  103. */
  104. struct ServiceResponseMessage
  105. {
  106. /**
  107. * GNUNET message header
  108. */
  109. struct GNUNET_MessageHeader header;
  110. /**
  111. * How many elements the session input had (in NBO).
  112. */
  113. uint32_t total_element_count GNUNET_PACKED;
  114. /**
  115. * How many elements were included after the mask was applied
  116. * including all multipart msgs (in NBO).
  117. */
  118. uint32_t used_element_count GNUNET_PACKED;
  119. /**
  120. * How many elements this individual message delivers (in NBO).
  121. */
  122. uint32_t contained_element_count GNUNET_PACKED;
  123. /**
  124. * The transaction/session key used to identify a session.
  125. * FIXME: needed? CADET should already identify sessions!
  126. */
  127. struct GNUNET_HashCode key;
  128. /**
  129. * followed by s | s' | k[i][perm]
  130. */
  131. };
  132. GNUNET_NETWORK_STRUCT_END
  133. /**
  134. * Role a peer in a session can assume.
  135. */
  136. enum PeerRole
  137. {
  138. /**
  139. * Alice is the peer that learns the result of the scalar product
  140. * calculation.
  141. */
  142. ALICE,
  143. /**
  144. * Bob merely provides his vector to compute the scalar product, but
  145. * does not learn anything about Alice's vector (except which elements
  146. * Alice's vector may contain, as the compute an intersection).
  147. */
  148. BOB
  149. };
  150. /**
  151. * DLL for sorting elements.
  152. */
  153. struct SortedValue
  154. {
  155. /**
  156. * Sorted Values are kept in a DLL
  157. */
  158. struct SortedValue *next;
  159. /**
  160. * Sorted Values are kept in a DLL
  161. */
  162. struct SortedValue *prev;
  163. /**
  164. * The element's id+integer-value
  165. */
  166. struct GNUNET_SCALARPRODUCT_Element *elem;
  167. /**
  168. * The element's value converted to MPI
  169. */
  170. gcry_mpi_t val;
  171. };
  172. /**
  173. * A scalarproduct session which tracks:
  174. *
  175. * a request form the client to our final response.
  176. * or
  177. * a request from a service to us (service).
  178. */
  179. struct ServiceSession
  180. {
  181. /**
  182. * Session information is kept in a DLL
  183. */
  184. struct ServiceSession *next;
  185. /**
  186. * Session information is kept in a DLL
  187. */
  188. struct ServiceSession *prev;
  189. /**
  190. * (hopefully) unique transaction ID
  191. */
  192. struct GNUNET_HashCode session_id;
  193. /**
  194. * Alice or Bob's peerID
  195. */
  196. struct GNUNET_PeerIdentity peer;
  197. /**
  198. * The client this request is related to.
  199. */
  200. struct GNUNET_SERVER_Client *client;
  201. /**
  202. * The message to send
  203. */
  204. struct GNUNET_MessageHeader *msg;
  205. /**
  206. * all non-0-value'd elements transmitted to us
  207. */
  208. struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
  209. /**
  210. * Set of elements for which will conduction an intersection.
  211. * the resulting elements are then used for computing the scalar product.
  212. */
  213. struct GNUNET_SET_Handle *intersection_set;
  214. /**
  215. * Set of elements for which will conduction an intersection.
  216. * the resulting elements are then used for computing the scalar product.
  217. */
  218. struct GNUNET_SET_OperationHandle *intersection_op;
  219. /**
  220. * Handle to Alice's Intersection operation listening for Bob
  221. */
  222. struct GNUNET_SET_ListenHandle *intersection_listen;
  223. /**
  224. * DLL for sorting elements after intersection
  225. */
  226. struct SortedValue *a_head;
  227. /**
  228. * a(Alice)
  229. */
  230. struct SortedValue *a_tail;
  231. /**
  232. * a(Alice)
  233. */
  234. gcry_mpi_t *sorted_elements;
  235. /**
  236. * E(ai)(Bob) after applying the mask
  237. */
  238. struct GNUNET_CRYPTO_PaillierCiphertext *e_a;
  239. /**
  240. * Bob's permutation p of R
  241. */
  242. struct GNUNET_CRYPTO_PaillierCiphertext *r;
  243. /**
  244. * Bob's permutation q of R
  245. */
  246. struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
  247. /**
  248. * Bob's "s"
  249. */
  250. struct GNUNET_CRYPTO_PaillierCiphertext s;
  251. /**
  252. * Bob's "s'"
  253. */
  254. struct GNUNET_CRYPTO_PaillierCiphertext s_prime;
  255. /**
  256. * Bob's matching response session from the client
  257. */
  258. struct ServiceSession *response;
  259. /**
  260. * My transmit handle for the current message to a Alice/Bob
  261. */
  262. struct GNUNET_CADET_TransmitHandle *service_transmit_handle;
  263. /**
  264. * My transmit handle for the current message to the client
  265. */
  266. struct GNUNET_SERVER_TransmitHandle *client_transmit_handle;
  267. /**
  268. * channel-handle associated with our cadet handle
  269. */
  270. struct GNUNET_CADET_Channel *channel;
  271. /**
  272. * Public key of the remote service, only used by Bob
  273. */
  274. struct GNUNET_CRYPTO_PaillierPublicKey remote_pubkey;
  275. /**
  276. * Handle to a task that sends a msg to the our client
  277. */
  278. GNUNET_SCHEDULER_TaskIdentifier client_notification_task;
  279. /**
  280. * The computed scalar
  281. */
  282. gcry_mpi_t product;
  283. /**
  284. * how many elements we were supplied with from the client
  285. */
  286. uint32_t total;
  287. /**
  288. * how many elements actually are used for the scalar product.
  289. * Size of the arrays in @e r and @e r_prime.
  290. */
  291. uint32_t used_element_count;
  292. /**
  293. * already transferred elements (sent/received) for multipart messages, less or equal than @e used_element_count for
  294. */
  295. uint32_t transferred_element_count;
  296. /**
  297. * Is this session active (#GNUNET_YES), Concluded (#GNUNET_NO), or had an error (#GNUNET_SYSERR)
  298. */
  299. int32_t active;
  300. /**
  301. * the role this peer has
  302. */
  303. enum PeerRole role;
  304. };
  305. /**
  306. * GNUnet configuration handle
  307. */
  308. static const struct GNUNET_CONFIGURATION_Handle * cfg;
  309. /**
  310. * Handle to the core service (NULL until we've connected to it).
  311. */
  312. static struct GNUNET_CADET_Handle *my_cadet;
  313. /**
  314. * The identity of this host.
  315. */
  316. static struct GNUNET_PeerIdentity me;
  317. /**
  318. * Service's own public key
  319. */
  320. static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey;
  321. /**
  322. * Service's own private key
  323. */
  324. static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey;
  325. /**
  326. * Service's offset for values that could possibly be negative but are plaintext for encryption.
  327. */
  328. static gcry_mpi_t my_offset;
  329. /**
  330. * Head of our double linked list for client-requests sent to us.
  331. * for all of these elements we calculate a scalar product with a remote peer
  332. * split between service->service and client->service for simplicity
  333. */
  334. static struct ServiceSession *from_client_head;
  335. /**
  336. * Tail of our double linked list for client-requests sent to us.
  337. * for all of these elements we calculate a scalar product with a remote peer
  338. * split between service->service and client->service for simplicity
  339. */
  340. static struct ServiceSession *from_client_tail;
  341. /**
  342. * Head of our double linked list for service-requests sent to us.
  343. * for all of these elements we help the requesting service in calculating a scalar product
  344. * split between service->service and client->service for simplicity
  345. */
  346. static struct ServiceSession *from_service_head;
  347. /**
  348. * Tail of our double linked list for service-requests sent to us.
  349. * for all of these elements we help the requesting service in calculating a scalar product
  350. * split between service->service and client->service for simplicity
  351. */
  352. static struct ServiceSession *from_service_tail;
  353. /**
  354. * Certain events (callbacks for server & cadet operations) must not be queued after shutdown.
  355. */
  356. static int do_shutdown;
  357. /**
  358. * Send a multi part chunk of a service request from alice to bob.
  359. * This element only contains a part of the elements-vector (session->a[]),
  360. * mask and public key set have to be contained within the first message
  361. *
  362. * This allows a ~32kbit key length while using 32000 elements or 62000 elements per request.
  363. *
  364. * @param cls the associated service session
  365. */
  366. static void
  367. prepare_alices_cyrptodata_message_multipart (void *cls);
  368. /**
  369. * Send a multi part chunk of a service response from Bob to Alice.
  370. * This element only contains the two permutations of R, R'.
  371. *
  372. * @param cls the associated service session
  373. */
  374. static void
  375. prepare_bobs_cryptodata_message_multipart (void *cls);
  376. /**
  377. * Computes the square sum over a vector of a given length.
  378. *
  379. * @param vector the vector to encrypt
  380. * @param length the length of the vector
  381. * @return an MPI value containing the calculated sum, never NULL
  382. */
  383. static gcry_mpi_t
  384. compute_square_sum (gcry_mpi_t *vector,
  385. uint32_t length)
  386. {
  387. gcry_mpi_t elem;
  388. gcry_mpi_t sum;
  389. uint32_t i;
  390. GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
  391. GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
  392. for (i = 0; i < length; i++)
  393. {
  394. gcry_mpi_mul (elem, vector[i], vector[i]);
  395. gcry_mpi_add (sum, sum, elem);
  396. }
  397. gcry_mpi_release (elem);
  398. return sum;
  399. }
  400. /**
  401. * Safely frees ALL memory areas referenced by a session.
  402. *
  403. * @param session - the session to free elements from
  404. */
  405. static void
  406. free_session_variables (struct ServiceSession *s)
  407. {
  408. struct SortedValue *e;
  409. while (NULL != (e = s->a_head))
  410. {
  411. GNUNET_free (e->elem);
  412. gcry_mpi_release (e->val);
  413. GNUNET_CONTAINER_DLL_remove (s->a_head,
  414. s->a_tail,
  415. e);
  416. GNUNET_free (e);
  417. }
  418. if (NULL != s->intersected_elements)
  419. {
  420. GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
  421. /* elements are freed independently in above loop over a_head */
  422. s->intersected_elements = NULL;
  423. }
  424. if (NULL != s->intersection_listen)
  425. {
  426. GNUNET_SET_listen_cancel (s->intersection_listen);
  427. s->intersection_listen = NULL;
  428. }
  429. if (NULL != s->intersection_op)
  430. {
  431. GNUNET_SET_operation_cancel (s->intersection_op);
  432. s->intersection_op = NULL;
  433. }
  434. if (NULL != s->intersection_set)
  435. {
  436. GNUNET_SET_destroy (s->intersection_set);
  437. s->intersection_set = NULL;
  438. }
  439. if (NULL != s->e_a)
  440. {
  441. GNUNET_free (s->e_a);
  442. s->e_a = NULL;
  443. }
  444. if (NULL != s->sorted_elements)
  445. {
  446. GNUNET_free (s->sorted_elements);
  447. s->sorted_elements = NULL;
  448. }
  449. if (NULL != s->msg)
  450. {
  451. GNUNET_free (s->msg);
  452. s->msg = NULL;
  453. }
  454. if (NULL != s->r)
  455. {
  456. GNUNET_free (s->r);
  457. s->r = NULL;
  458. }
  459. if (NULL != s->r_prime)
  460. {
  461. GNUNET_free (s->r_prime);
  462. s->r_prime = NULL;
  463. }
  464. if (NULL != s->product)
  465. {
  466. gcry_mpi_release (s->product);
  467. s->product = NULL;
  468. }
  469. }
  470. /**
  471. * Primitive callback for copying over a message, as they usually are
  472. * too complex to be handled in the callback itself. Clears a
  473. * session-callback, if a session was handed over and the transmit
  474. * handle was stored.
  475. *
  476. * @param cls the session containing the message object
  477. * @param size the size of the @a buf we got
  478. * @param buf the buffer to copy the message to
  479. * @return 0 if we couldn't copy, else the size copied over
  480. */
  481. static size_t
  482. cb_transfer_message (void *cls,
  483. size_t size,
  484. void *buf)
  485. {
  486. struct ServiceSession *s = cls;
  487. uint16_t type;
  488. s->client_transmit_handle = NULL;
  489. GNUNET_assert (buf);
  490. if (ntohs (s->msg->size) > size)
  491. {
  492. GNUNET_break (0);
  493. return 0;
  494. }
  495. size = ntohs (s->msg->size);
  496. type = ntohs (s->msg->type);
  497. memcpy (buf,
  498. s->msg,
  499. size);
  500. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  501. "Sending a message of type %u.\n",
  502. (unsigned int) type);
  503. GNUNET_free (s->msg);
  504. s->msg = NULL;
  505. switch (type)
  506. {
  507. case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT:
  508. free_session_variables (s);
  509. // FIXME: that does not fully clean up 's'
  510. break;
  511. case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION:
  512. break;
  513. case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA:
  514. case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART:
  515. if (s->used_element_count != s->transferred_element_count)
  516. prepare_alices_cyrptodata_message_multipart (s);
  517. else
  518. s->channel = NULL;
  519. break;
  520. case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA:
  521. case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART:
  522. if (s->used_element_count != s->transferred_element_count)
  523. prepare_bobs_cryptodata_message_multipart (s);
  524. else
  525. s->channel = NULL;
  526. break;
  527. default:
  528. GNUNET_assert (0);
  529. }
  530. return size;
  531. }
  532. /**
  533. * Finds a not terminated client/service session in the
  534. * given DLL based on session key, element count and state.
  535. *
  536. * FIXME: Use hashmap based on key instead of linear search.
  537. *
  538. * @param tail - the tail of the DLL
  539. * @param key - the key we want to search for
  540. * @param peerid - a pointer to the peer ID of the associated peer, NULL to ignore
  541. * @return a pointer to a matching session, or NULL
  542. */
  543. static struct ServiceSession *
  544. find_matching_session (struct ServiceSession *tail,
  545. const struct GNUNET_HashCode *key,
  546. const struct GNUNET_PeerIdentity *peerid)
  547. {
  548. struct ServiceSession * s;
  549. for (s = tail; NULL != s; s = s->prev)
  550. {
  551. // if the key matches, and the element_count is same
  552. if (0 == memcmp (&s->session_id, key, sizeof (struct GNUNET_HashCode)))
  553. {
  554. // if peerid is NULL OR same as the peer Id in the queued request
  555. if ((NULL == peerid)
  556. || (0 == memcmp (&s->peer, peerid, sizeof (struct GNUNET_PeerIdentity))))
  557. // matches and is not an already terminated session
  558. return s;
  559. }
  560. }
  561. return NULL;
  562. }
  563. /**
  564. * A client disconnected.
  565. *
  566. * Remove the associated session(s), release data structures
  567. * and cancel pending outgoing transmissions to the client.
  568. * if the session has not yet completed, we also cancel Alice's request to Bob.
  569. *
  570. * @param cls closure, NULL
  571. * @param client identification of the client
  572. */
  573. static void
  574. cb_client_disconnect (void *cls,
  575. struct GNUNET_SERVER_Client *client)
  576. {
  577. struct ServiceSession *s;
  578. if (NULL == client)
  579. return;
  580. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  581. "Client %p disconnected from us.\n",
  582. client);
  583. s = GNUNET_SERVER_client_get_user_context (client,
  584. struct ServiceSession);
  585. if (NULL == s)
  586. return;
  587. GNUNET_CONTAINER_DLL_remove (from_client_head,
  588. from_client_tail,
  589. s);
  590. if (NULL != s->service_transmit_handle)
  591. {
  592. GNUNET_CADET_notify_transmit_ready_cancel (s->service_transmit_handle);
  593. s->service_transmit_handle = NULL;
  594. }
  595. if (NULL != s->channel)
  596. {
  597. GNUNET_CADET_channel_destroy (s->channel);
  598. s->channel = NULL;
  599. }
  600. if (GNUNET_SCHEDULER_NO_TASK != s->client_notification_task)
  601. {
  602. GNUNET_SCHEDULER_cancel (s->client_notification_task);
  603. s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
  604. }
  605. if (NULL != s->client_transmit_handle)
  606. {
  607. GNUNET_SERVER_notify_transmit_ready_cancel (s->client_transmit_handle);
  608. s->client_transmit_handle = NULL;
  609. }
  610. free_session_variables (s);
  611. GNUNET_free (s);
  612. }
  613. /**
  614. * Notify the client that the session has succeeded or failed completely.
  615. * This message gets sent to
  616. * - Alice's client if Bob disconnected or to
  617. * - Bob's client if the operation completed or Alice disconnected
  618. *
  619. * @param cls the associated client session
  620. * @param tc the task context handed to us by the scheduler, unused
  621. */
  622. static void
  623. prepare_client_end_notification (void *cls,
  624. const struct GNUNET_SCHEDULER_TaskContext *tc)
  625. {
  626. struct ServiceSession *session = cls;
  627. struct ClientResponseMessage *msg;
  628. session->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
  629. msg = GNUNET_new (struct ClientResponseMessage);
  630. msg->header.size = htons (sizeof (struct ClientResponseMessage));
  631. msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
  632. // signal error if not signalized, positive result-range field but zero length.
  633. msg->product_length = htonl (0);
  634. msg->status = htonl (session->active);
  635. session->msg = &msg->header;
  636. //transmit this message to our client
  637. session->client_transmit_handle
  638. = GNUNET_SERVER_notify_transmit_ready (session->client,
  639. sizeof (struct ClientResponseMessage),
  640. GNUNET_TIME_UNIT_FOREVER_REL,
  641. &cb_transfer_message,
  642. session);
  643. // if we could not even queue our request, something is wrong
  644. if (NULL == session->client_transmit_handle)
  645. {
  646. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  647. _("Could not send message to client (%p)!\n"),
  648. session->client);
  649. GNUNET_SERVER_client_disconnect (session->client);
  650. free_session_variables (session);
  651. GNUNET_CONTAINER_DLL_remove (from_client_head,
  652. from_client_tail,
  653. session);
  654. GNUNET_free (session);
  655. return;
  656. }
  657. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  658. _("Sending session-end notification to client (%p) for session %s\n"),
  659. session->client,
  660. GNUNET_h2s (&session->session_id));
  661. }
  662. /**
  663. * Executed by Alice, fills in a service-request message and sends it
  664. * to the given peer.
  665. *
  666. * @param cls the session associated with this request
  667. */
  668. static void
  669. prepare_alices_cyrptodata_message (void *cls)
  670. {
  671. struct ServiceSession *session = cls;
  672. struct AliceCryptodataMessage * msg;
  673. struct GNUNET_CRYPTO_PaillierCiphertext * payload;
  674. unsigned int i;
  675. uint32_t msg_length;
  676. gcry_mpi_t a;
  677. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  678. "Successfully created new channel to peer (%s)!\n",
  679. GNUNET_i2s (&session->peer));
  680. msg_length = sizeof (struct AliceCryptodataMessage)
  681. + session->used_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  682. if (GNUNET_SERVER_MAX_MESSAGE_SIZE > msg_length)
  683. {
  684. session->transferred_element_count = session->used_element_count;
  685. }
  686. else
  687. {
  688. //create a multipart msg, first we calculate a new msg size for the head msg
  689. session->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct AliceCryptodataMessage))
  690. / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  691. msg_length = sizeof (struct AliceCryptodataMessage)
  692. + session->transferred_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  693. }
  694. msg = GNUNET_malloc (msg_length);
  695. msg->header.size = htons (msg_length);
  696. msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA);
  697. msg->contained_element_count = htonl (session->transferred_element_count);
  698. // fill in the payload
  699. payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
  700. // now copy over the sorted element vector
  701. a = gcry_mpi_new (0);
  702. for (i = 0; i < session->transferred_element_count; i++)
  703. {
  704. gcry_mpi_add (a, session->sorted_elements[i], my_offset);
  705. GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[i]);
  706. }
  707. gcry_mpi_release (a);
  708. session->msg = (struct GNUNET_MessageHeader *) msg;
  709. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  710. "Transmitting service request.\n");
  711. //transmit via cadet messaging
  712. session->service_transmit_handle
  713. = GNUNET_CADET_notify_transmit_ready (session->channel,
  714. GNUNET_YES,
  715. GNUNET_TIME_UNIT_FOREVER_REL,
  716. msg_length,
  717. &cb_transfer_message,
  718. session);
  719. if (NULL == session->service_transmit_handle)
  720. {
  721. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  722. _("Could not send message to channel!\n"));
  723. GNUNET_free (msg);
  724. session->msg = NULL;
  725. session->active = GNUNET_SYSERR;
  726. session->client_notification_task
  727. = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  728. session);
  729. return;
  730. }
  731. }
  732. /**
  733. * Send a multipart chunk of a service response from bob to alice.
  734. * This element only contains the two permutations of R, R'.
  735. *
  736. * @param cls the associated service session
  737. */
  738. static void
  739. prepare_bobs_cryptodata_message_multipart (void *cls)
  740. {
  741. struct ServiceSession *session = cls;
  742. struct GNUNET_CRYPTO_PaillierCiphertext * payload;
  743. struct MultipartMessage * msg;
  744. unsigned int i;
  745. unsigned int j;
  746. uint32_t msg_length;
  747. uint32_t todo_count;
  748. msg_length = sizeof (struct MultipartMessage);
  749. todo_count = session->used_element_count - session->transferred_element_count;
  750. if (todo_count > MULTIPART_ELEMENT_CAPACITY / 2)
  751. // send the currently possible maximum chunk, we always transfer both permutations
  752. todo_count = MULTIPART_ELEMENT_CAPACITY / 2;
  753. msg_length += todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2;
  754. msg = GNUNET_malloc (msg_length);
  755. msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART);
  756. msg->header.size = htons (msg_length);
  757. msg->contained_element_count = htonl (todo_count);
  758. payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
  759. for (i = session->transferred_element_count, j = 0; i < session->transferred_element_count + todo_count; i++)
  760. {
  761. //r[i][p] and r[i][q]
  762. memcpy (&payload[j++],
  763. &session->r[i],
  764. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  765. memcpy (&payload[j++],
  766. &session->r_prime[i],
  767. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  768. }
  769. session->transferred_element_count += todo_count;
  770. session->msg = (struct GNUNET_MessageHeader *) msg;
  771. session->service_transmit_handle
  772. = GNUNET_CADET_notify_transmit_ready (session->channel,
  773. GNUNET_YES,
  774. GNUNET_TIME_UNIT_FOREVER_REL,
  775. msg_length,
  776. &cb_transfer_message,
  777. session);
  778. if (NULL == session->service_transmit_handle)
  779. {
  780. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  781. _("Could not send service-response message via CADET!)\n"));
  782. GNUNET_free (msg);
  783. session->msg = NULL;
  784. GNUNET_CADET_channel_destroy (session->channel);
  785. session->response->active = GNUNET_SYSERR;
  786. GNUNET_CONTAINER_DLL_remove (from_service_head,
  787. from_service_tail,
  788. session);
  789. session->response->client_notification_task
  790. = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  791. session->response);
  792. free_session_variables (session);
  793. GNUNET_free (session);
  794. return;
  795. }
  796. if (session->transferred_element_count == session->used_element_count)
  797. {
  798. // final part
  799. session->active = GNUNET_NO;
  800. GNUNET_free (session->r_prime);
  801. GNUNET_free (session->r);
  802. session->r_prime = NULL;
  803. session->r = NULL;
  804. }
  805. }
  806. /**
  807. * Bob executes:
  808. * generates the response message to be sent to alice after computing
  809. * the values (1), (2), S and S'
  810. * (1)[]: $E_A(a_{pi(i)}) times E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$
  811. * (2)[]: $E_A(a_{pi'(i)}) times E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
  812. * S: $S := E_A(sum (r_i + b_i)^2)$
  813. * S': $S' := E_A(sum r_i^2)$
  814. *
  815. * @param session the associated requesting session with alice
  816. */
  817. static void
  818. prepare_bobs_cryptodata_message (void *cls,
  819. const struct GNUNET_SCHEDULER_TaskContext *tc)
  820. {
  821. struct ServiceSession * s = cls;
  822. struct ServiceResponseMessage *msg;
  823. uint32_t msg_length = 0;
  824. struct GNUNET_CRYPTO_PaillierCiphertext *payload;
  825. unsigned int i;
  826. msg_length = sizeof (struct ServiceResponseMessage)
  827. + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); // s, stick
  828. if (GNUNET_SERVER_MAX_MESSAGE_SIZE >
  829. msg_length + 2 * s->used_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
  830. { //r, r'
  831. msg_length += 2 * s->used_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  832. s->transferred_element_count = s->used_element_count;
  833. }
  834. else
  835. s->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - msg_length) /
  836. (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2);
  837. msg = GNUNET_malloc (msg_length);
  838. msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA);
  839. msg->header.size = htons (msg_length);
  840. msg->total_element_count = htonl (s->total);
  841. msg->used_element_count = htonl (s->used_element_count);
  842. msg->contained_element_count = htonl (s->transferred_element_count);
  843. msg->key = s->session_id;
  844. payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
  845. memcpy (&payload[0],
  846. &s->s,
  847. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  848. memcpy (&payload[1],
  849. &s->s_prime,
  850. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  851. payload = &payload[2];
  852. // convert k[][]
  853. for (i = 0; i < s->transferred_element_count; i++)
  854. {
  855. //k[i][p] and k[i][q]
  856. memcpy (&payload[i * 2],
  857. &s->r[i],
  858. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  859. memcpy (&payload[i * 2 + 1],
  860. &s->r_prime[i],
  861. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  862. }
  863. s->msg = (struct GNUNET_MessageHeader *) msg;
  864. s->service_transmit_handle
  865. = GNUNET_CADET_notify_transmit_ready (s->channel,
  866. GNUNET_YES,
  867. GNUNET_TIME_UNIT_FOREVER_REL,
  868. msg_length,
  869. &cb_transfer_message,
  870. s);
  871. if (NULL == s->service_transmit_handle)
  872. {
  873. //disconnect our client
  874. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  875. _("Could not send service-response message via cadet!)\n"));
  876. GNUNET_free (msg);
  877. s->msg = NULL;
  878. GNUNET_CONTAINER_DLL_remove (from_service_head,
  879. from_service_tail,
  880. s);
  881. GNUNET_CADET_channel_destroy(s->channel);
  882. s->response->active = GNUNET_SYSERR;
  883. s->response->client_notification_task =
  884. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  885. s->response);
  886. free_session_variables (s);
  887. GNUNET_free(s);
  888. return;
  889. }
  890. if (s->transferred_element_count != s->used_element_count)
  891. {
  892. // multipart
  893. }
  894. else
  895. {
  896. //singlepart
  897. s->active = GNUNET_NO;
  898. GNUNET_free (s->r);
  899. s->r = NULL;
  900. GNUNET_free (s->r_prime);
  901. s->r_prime = NULL;
  902. }
  903. }
  904. /**
  905. * executed by bob:
  906. * compute the values
  907. * (1)[]: $E_A(a_{pi(i)}) otimes E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$
  908. * (2)[]: $E_A(a_{pi'(i)}) otimes E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
  909. * S: $S := E_A(sum (r_i + b_i)^2)$
  910. * S': $S' := E_A(sum r_i^2)$
  911. *
  912. * @param request the requesting session + bob's requesting peer
  913. */
  914. static void
  915. compute_service_response (struct ServiceSession *session)
  916. {
  917. int i;
  918. unsigned int *p;
  919. unsigned int *q;
  920. uint32_t count;
  921. gcry_mpi_t *rand;
  922. gcry_mpi_t tmp;
  923. gcry_mpi_t *b;
  924. struct GNUNET_CRYPTO_PaillierCiphertext *a;
  925. struct GNUNET_CRYPTO_PaillierCiphertext *r;
  926. struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
  927. count = session->used_element_count;
  928. a = session->e_a;
  929. b = session->sorted_elements;
  930. q = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
  931. count);
  932. p = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
  933. count);
  934. rand = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
  935. for (i = 0; i < count; i++)
  936. GNUNET_assert (NULL != (rand[i] = gcry_mpi_new (0)));
  937. r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
  938. r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
  939. for (i = 0; i < count; i++)
  940. {
  941. int32_t svalue;
  942. svalue = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
  943. UINT32_MAX);
  944. // long to gcry_mpi_t
  945. if (svalue < 0)
  946. gcry_mpi_sub_ui (rand[i],
  947. rand[i],
  948. - svalue);
  949. else
  950. rand[i] = gcry_mpi_set_ui (rand[i], svalue);
  951. }
  952. tmp = gcry_mpi_new (0);
  953. // encrypt the element
  954. // for the sake of readability I decided to have dedicated permutation
  955. // vectors, which get rid of all the lookups in p/q.
  956. // however, ap/aq are not absolutely necessary but are just abstraction
  957. // Calculate Kp = E(S + a_pi) (+) E(S - r_pi - b_pi)
  958. for (i = 0; i < count; i++)
  959. {
  960. // E(S - r_pi - b_pi)
  961. gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
  962. gcry_mpi_sub (tmp, tmp, b[p[i]]);
  963. GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
  964. tmp,
  965. 2,
  966. &r[i]);
  967. // E(S - r_pi - b_pi) * E(S + a_pi) == E(2*S + a - r - b)
  968. GNUNET_CRYPTO_paillier_hom_add (&session->remote_pubkey,
  969. &r[i],
  970. &a[p[i]],
  971. &r[i]);
  972. }
  973. // Calculate Kq = E(S + a_qi) (+) E(S - r_qi)
  974. for (i = 0; i < count; i++)
  975. {
  976. // E(S - r_qi)
  977. gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
  978. GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
  979. tmp,
  980. 2,
  981. &r_prime[i]));
  982. // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
  983. GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (&session->remote_pubkey,
  984. &r_prime[i],
  985. &a[q[i]],
  986. &r_prime[i]));
  987. }
  988. // Calculate S' = E(SUM( r_i^2 ))
  989. tmp = compute_square_sum (rand, count);
  990. GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
  991. tmp,
  992. 1,
  993. &session->s_prime);
  994. // Calculate S = E(SUM( (r_i + b_i)^2 ))
  995. for (i = 0; i < count; i++)
  996. gcry_mpi_add (rand[i], rand[i], b[i]);
  997. tmp = compute_square_sum (rand, count);
  998. GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
  999. tmp,
  1000. 1,
  1001. &session->s);
  1002. session->r = r;
  1003. session->r_prime = r_prime;
  1004. // release rand, b and a
  1005. for (i = 0; i < count; i++)
  1006. {
  1007. gcry_mpi_release (rand[i]);
  1008. gcry_mpi_release (b[i]);
  1009. }
  1010. gcry_mpi_release (tmp);
  1011. GNUNET_free (session->e_a);
  1012. session->e_a = NULL;
  1013. GNUNET_free (p);
  1014. GNUNET_free (q);
  1015. GNUNET_free (b);
  1016. GNUNET_free (rand);
  1017. // copy the r[], r_prime[], S and Stick into a new message, prepare_service_response frees these
  1018. GNUNET_SCHEDULER_add_now (&prepare_bobs_cryptodata_message,
  1019. session);
  1020. }
  1021. /**
  1022. * Iterator over all hash map entries in session->intersected_elements.
  1023. *
  1024. * @param cls closure
  1025. * @param key current key code
  1026. * @param value value in the hash map
  1027. * @return #GNUNET_YES if we should continue to
  1028. * iterate,
  1029. * #GNUNET_NO if not.
  1030. */
  1031. static int
  1032. cb_insert_element_sorted (void *cls,
  1033. const struct GNUNET_HashCode *key,
  1034. void *value)
  1035. {
  1036. struct ServiceSession * s = cls;
  1037. struct SortedValue * e = GNUNET_new (struct SortedValue);
  1038. struct SortedValue * o = s->a_head;
  1039. int64_t val;
  1040. e->elem = value;
  1041. e->val = gcry_mpi_new (0);
  1042. val = (int64_t) GNUNET_ntohll (e->elem->value);
  1043. if (0 > val)
  1044. gcry_mpi_sub_ui (e->val, e->val, -val);
  1045. else
  1046. gcry_mpi_add_ui (e->val, e->val, val);
  1047. // insert as first element with the lowest key
  1048. if (NULL == s->a_head
  1049. || (0 <= GNUNET_CRYPTO_hash_cmp (&s->a_head->elem->key,
  1050. &e->elem->key)))
  1051. {
  1052. GNUNET_CONTAINER_DLL_insert (s->a_head,
  1053. s->a_tail,
  1054. e);
  1055. return GNUNET_YES;
  1056. }
  1057. else if (0 > GNUNET_CRYPTO_hash_cmp (&s->a_tail->elem->key,
  1058. &e->elem->key))
  1059. {
  1060. // insert as last element with the highest key
  1061. GNUNET_CONTAINER_DLL_insert_tail (s->a_head,
  1062. s->a_tail,
  1063. e);
  1064. return GNUNET_YES;
  1065. }
  1066. // insert before the first higher/equal element
  1067. do
  1068. {
  1069. if (0 <= GNUNET_CRYPTO_hash_cmp (&o->elem->key,
  1070. &e->elem->key))
  1071. {
  1072. GNUNET_CONTAINER_DLL_insert_before (s->a_head,
  1073. s->a_tail,
  1074. o,
  1075. e);
  1076. return GNUNET_YES;
  1077. }
  1078. o = o->next;
  1079. }
  1080. while (NULL != o);
  1081. // broken DLL
  1082. GNUNET_assert (0);
  1083. }
  1084. /**
  1085. * Callback for set operation results. Called for each element
  1086. * in the result set.
  1087. *
  1088. * @param cls closure
  1089. * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
  1090. * @param status see `enum GNUNET_SET_Status`
  1091. */
  1092. static void
  1093. cb_intersection_element_removed (void *cls,
  1094. const struct GNUNET_SET_Element *element,
  1095. enum GNUNET_SET_Status status)
  1096. {
  1097. struct ServiceSession * s = cls;
  1098. struct GNUNET_SCALARPRODUCT_Element * se;
  1099. int i;
  1100. switch (status)
  1101. {
  1102. case GNUNET_SET_STATUS_OK:
  1103. //this element has been removed from the set
  1104. se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
  1105. element->data);
  1106. GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
  1107. element->data,
  1108. se);
  1109. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1110. "%s: removed element with key %s value %d\n",
  1111. s->role == ALICE ? "ALICE" : "BOB",
  1112. GNUNET_h2s(&se->key),
  1113. se->value);
  1114. return;
  1115. case GNUNET_SET_STATUS_DONE:
  1116. s->intersection_op = NULL;
  1117. s->intersection_set = NULL;
  1118. s->used_element_count
  1119. = GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
  1120. &cb_insert_element_sorted,
  1121. s);
  1122. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1123. "%s: Finished intersection, %d items remain\n",
  1124. s->role == ALICE ? "ALICE" : "BOB",
  1125. s->used_element_count);
  1126. if (2 > s->used_element_count)
  1127. {
  1128. // failed! do not leak information about our single remaining element!
  1129. // continue after the loop
  1130. break;
  1131. }
  1132. s->sorted_elements = GNUNET_malloc (s->used_element_count * sizeof (gcry_mpi_t));
  1133. for (i = 0; NULL != s->a_head; i++)
  1134. {
  1135. struct SortedValue* a = s->a_head;
  1136. GNUNET_assert (i < s->used_element_count);
  1137. s->sorted_elements[i] = a->val;
  1138. GNUNET_CONTAINER_DLL_remove (s->a_head, s->a_tail, a);
  1139. GNUNET_free (a->elem);
  1140. }
  1141. GNUNET_assert (i == s->used_element_count);
  1142. if (ALICE == s->role) {
  1143. prepare_alices_cyrptodata_message (s);
  1144. return;
  1145. }
  1146. else if (s->used_element_count == s->transferred_element_count)
  1147. {
  1148. compute_service_response (s);
  1149. return;
  1150. }
  1151. break;
  1152. default:
  1153. LOG (GNUNET_ERROR_TYPE_DEBUG, "%s: OOOPS %d", s->role == ALICE ? "ALICE" : "BOB", status);
  1154. if (NULL != s->intersection_listen)
  1155. {
  1156. GNUNET_SET_listen_cancel (s->intersection_listen);
  1157. s->intersection_listen = NULL;
  1158. }
  1159. // the op failed and has already been invalidated by the set service
  1160. break;
  1161. }
  1162. s->intersection_op = NULL;
  1163. s->intersection_set = NULL;
  1164. //failed if we go here
  1165. GNUNET_break_op (0);
  1166. // and notify our client-session that we could not complete the session
  1167. if (ALICE == s->role) {
  1168. s->active = GNUNET_SYSERR;
  1169. s->client_notification_task =
  1170. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1171. s);
  1172. }
  1173. else
  1174. {
  1175. GNUNET_CONTAINER_DLL_remove (from_service_head,
  1176. from_service_tail,
  1177. s);
  1178. free_session_variables (s);
  1179. s->response->active = GNUNET_SYSERR;
  1180. s->response->client_notification_task =
  1181. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1182. s->response);
  1183. GNUNET_free(s);
  1184. }
  1185. }
  1186. /**
  1187. * Called when another peer wants to do a set operation with the
  1188. * local peer. If a listen error occurs, the @a request is NULL.
  1189. *
  1190. * @param cls closure
  1191. * @param other_peer the other peer
  1192. * @param context_msg message with application specific information from
  1193. * the other peer
  1194. * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
  1195. * to accept it, otherwise the request will be refused
  1196. * Note that we can't just return value from the listen callback,
  1197. * as it is also necessary to specify the set we want to do the
  1198. * operation with, whith sometimes can be derived from the context
  1199. * message. It's necessary to specify the timeout.
  1200. */
  1201. static void
  1202. cb_intersection_request_alice (void *cls,
  1203. const struct GNUNET_PeerIdentity *other_peer,
  1204. const struct GNUNET_MessageHeader *context_msg,
  1205. struct GNUNET_SET_Request *request)
  1206. {
  1207. struct ServiceSession * s = cls;
  1208. s->intersection_op = GNUNET_SET_accept (request,
  1209. GNUNET_SET_RESULT_REMOVED,
  1210. cb_intersection_element_removed,
  1211. s);
  1212. if (NULL == s->intersection_op)
  1213. {
  1214. s->active = GNUNET_SYSERR;
  1215. s->client_notification_task =
  1216. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1217. s);
  1218. return;
  1219. }
  1220. if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set))
  1221. {
  1222. s->active = GNUNET_SYSERR;
  1223. s->client_notification_task =
  1224. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1225. s);
  1226. return;
  1227. }
  1228. s->intersection_set = NULL;
  1229. s->intersection_listen = NULL;
  1230. }
  1231. /**
  1232. * prepare the response we will send to alice or bobs' clients.
  1233. * in Bobs case the product will be NULL.
  1234. *
  1235. * @param cls the session associated with our client.
  1236. * @param tc the task context handed to us by the scheduler, unused
  1237. */
  1238. static void
  1239. prepare_client_response (void *cls,
  1240. const struct GNUNET_SCHEDULER_TaskContext *tc)
  1241. {
  1242. struct ServiceSession * s = cls;
  1243. struct ClientResponseMessage *msg;
  1244. unsigned char * product_exported = NULL;
  1245. size_t product_length = 0;
  1246. uint32_t msg_length = 0;
  1247. int8_t range = -1;
  1248. gcry_error_t rc;
  1249. int sign;
  1250. s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
  1251. if (s->product)
  1252. {
  1253. gcry_mpi_t value = gcry_mpi_new (0);
  1254. sign = gcry_mpi_cmp_ui (s->product, 0);
  1255. // libgcrypt can not handle a print of a negative number
  1256. // if (a->sign) return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
  1257. if (0 > sign)
  1258. {
  1259. gcry_mpi_sub (value, value, s->product);
  1260. }
  1261. else if (0 < sign)
  1262. {
  1263. range = 1;
  1264. gcry_mpi_add (value, value, s->product);
  1265. }
  1266. else
  1267. range = 0;
  1268. gcry_mpi_release (s->product);
  1269. s->product = NULL;
  1270. // get representation as string
  1271. if (range
  1272. && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
  1273. &product_exported,
  1274. &product_length,
  1275. value))))
  1276. {
  1277. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
  1278. "gcry_mpi_scan",
  1279. rc);
  1280. product_length = 0;
  1281. range = -1; // signal error with product-length = 0 and range = -1
  1282. }
  1283. gcry_mpi_release (value);
  1284. }
  1285. msg_length = sizeof (struct ClientResponseMessage) + product_length;
  1286. msg = GNUNET_malloc (msg_length);
  1287. if (NULL != product_exported)
  1288. {
  1289. memcpy (&msg[1],
  1290. product_exported,
  1291. product_length);
  1292. GNUNET_free (product_exported);
  1293. }
  1294. msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
  1295. msg->header.size = htons (msg_length);
  1296. msg->range = range;
  1297. msg->product_length = htonl (product_length);
  1298. s->msg = (struct GNUNET_MessageHeader *) msg;
  1299. s->client_transmit_handle =
  1300. GNUNET_SERVER_notify_transmit_ready (s->client,
  1301. msg_length,
  1302. GNUNET_TIME_UNIT_FOREVER_REL,
  1303. &cb_transfer_message,
  1304. s);
  1305. GNUNET_break (NULL != s->client_transmit_handle);
  1306. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1307. "Sent result to client (%p), this session (%s) has ended!\n",
  1308. s->client,
  1309. GNUNET_h2s (&s->session_id));
  1310. }
  1311. /**
  1312. * Executed by Alice, fills in a service-request message and sends it to the given peer
  1313. *
  1314. * @param session the session associated with this request
  1315. */
  1316. static void
  1317. prepare_alices_computation_request (struct ServiceSession * s)
  1318. {
  1319. struct ServiceRequestMessage * msg;
  1320. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1321. _("Successfully created new channel to peer (%s)!\n"),
  1322. GNUNET_i2s (&s->peer));
  1323. msg = GNUNET_new (struct ServiceRequestMessage);
  1324. msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION);
  1325. memcpy (&msg->session_id, &s->session_id, sizeof (struct GNUNET_HashCode));
  1326. msg->header.size = htons (sizeof (struct ServiceRequestMessage));
  1327. s->msg = (struct GNUNET_MessageHeader *) msg;
  1328. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1329. _("Transmitting service request.\n"));
  1330. //transmit via cadet messaging
  1331. s->service_transmit_handle
  1332. = GNUNET_CADET_notify_transmit_ready (s->channel, GNUNET_YES,
  1333. GNUNET_TIME_UNIT_FOREVER_REL,
  1334. sizeof (struct ServiceRequestMessage),
  1335. &cb_transfer_message,
  1336. s);
  1337. if (! s->service_transmit_handle)
  1338. {
  1339. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1340. _("Could not send message to channel!\n"));
  1341. GNUNET_free (msg);
  1342. s->msg = NULL;
  1343. s->active = GNUNET_SYSERR;
  1344. s->client_notification_task =
  1345. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1346. s);
  1347. return;
  1348. }
  1349. }
  1350. /**
  1351. * Send a multi part chunk of a service request from alice to bob.
  1352. * This element only contains a part of the elements-vector (session->a[]),
  1353. * mask and public key set have to be contained within the first message
  1354. *
  1355. * This allows a ~32kbit key length while using 32000 elements or 62000 elements per request.
  1356. *
  1357. * @param cls the associated service session
  1358. */
  1359. static void
  1360. prepare_alices_cyrptodata_message_multipart (void *cls)
  1361. {
  1362. struct ServiceSession * s = cls;
  1363. struct MultipartMessage * msg;
  1364. struct GNUNET_CRYPTO_PaillierCiphertext * payload;
  1365. unsigned int i;
  1366. uint32_t msg_length;
  1367. uint32_t todo_count;
  1368. gcry_mpi_t a;
  1369. msg_length = sizeof (struct MultipartMessage);
  1370. todo_count = s->used_element_count - s->transferred_element_count;
  1371. if (todo_count > MULTIPART_ELEMENT_CAPACITY)
  1372. // send the currently possible maximum chunk
  1373. todo_count = MULTIPART_ELEMENT_CAPACITY;
  1374. msg_length += todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  1375. msg = GNUNET_malloc (msg_length);
  1376. msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART);
  1377. msg->header.size = htons (msg_length);
  1378. msg->contained_element_count = htonl (todo_count);
  1379. payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
  1380. // now copy over the sorted element vector
  1381. a = gcry_mpi_new (0);
  1382. for (i = s->transferred_element_count; i < todo_count; i++)
  1383. {
  1384. gcry_mpi_add (a, s->sorted_elements[i], my_offset);
  1385. GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[i - s->transferred_element_count]);
  1386. }
  1387. gcry_mpi_release (a);
  1388. s->transferred_element_count += todo_count;
  1389. s->msg = (struct GNUNET_MessageHeader *) msg;
  1390. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1391. "Transmitting service request.\n");
  1392. //transmit via cadet messaging
  1393. s->service_transmit_handle
  1394. = GNUNET_CADET_notify_transmit_ready (s->channel,
  1395. GNUNET_YES,
  1396. GNUNET_TIME_UNIT_FOREVER_REL,
  1397. msg_length,
  1398. &cb_transfer_message,
  1399. s);
  1400. if (!s->service_transmit_handle)
  1401. {
  1402. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1403. _("Could not send service-request multipart message to channel!\n"));
  1404. GNUNET_free (msg);
  1405. s->msg = NULL;
  1406. s->active = GNUNET_SYSERR;
  1407. s->client_notification_task
  1408. = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1409. s);
  1410. return;
  1411. }
  1412. }
  1413. /**
  1414. * Our client has finished sending us its multipart message.
  1415. *
  1416. * @param session the service session context
  1417. */
  1418. static void
  1419. client_request_complete_bob (struct ServiceSession * client_session)
  1420. {
  1421. struct ServiceSession * s;
  1422. //check if service queue contains a matching request
  1423. s = find_matching_session (from_service_tail,
  1424. &client_session->session_id,
  1425. NULL);
  1426. if (NULL != s)
  1427. {
  1428. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1429. "Got client-responder-session with key %s and a matching service-request-session set, processing.\n",
  1430. GNUNET_h2s (&client_session->session_id));
  1431. s->response = client_session;
  1432. s->intersected_elements = client_session->intersected_elements;
  1433. client_session->intersected_elements = NULL;
  1434. s->intersection_set = client_session->intersection_set;
  1435. client_session->intersection_set = NULL;
  1436. s->intersection_op = GNUNET_SET_prepare (&s->peer,
  1437. &s->session_id,
  1438. NULL,
  1439. GNUNET_SET_RESULT_REMOVED,
  1440. cb_intersection_element_removed,
  1441. s);
  1442. GNUNET_SET_commit (s->intersection_op, s->intersection_set);
  1443. }
  1444. else
  1445. {
  1446. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1447. "Got client-responder-session with key %s but NO matching service-request-session set, queuing element for later use.\n",
  1448. GNUNET_h2s (&client_session->session_id));
  1449. // no matching session exists yet, store the response
  1450. // for later processing by handle_service_request()
  1451. }
  1452. }
  1453. /**
  1454. * Our client has finished sending us its multipart message.
  1455. *
  1456. * @param session the service session context
  1457. */
  1458. static void
  1459. client_request_complete_alice (struct ServiceSession * s)
  1460. {
  1461. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1462. _ ("Creating new channel for session with key %s.\n"),
  1463. GNUNET_h2s (&s->session_id));
  1464. s->channel = GNUNET_CADET_channel_create (my_cadet, s,
  1465. &s->peer,
  1466. GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
  1467. GNUNET_CADET_OPTION_RELIABLE);
  1468. if (NULL == s->channel)
  1469. {
  1470. s->active = GNUNET_SYSERR;
  1471. s->client_notification_task =
  1472. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1473. s);
  1474. return;
  1475. }
  1476. s->intersection_listen = GNUNET_SET_listen (cfg,
  1477. GNUNET_SET_OPERATION_INTERSECTION,
  1478. &s->session_id,
  1479. cb_intersection_request_alice,
  1480. s);
  1481. if (NULL == s->intersection_listen)
  1482. {
  1483. s->active = GNUNET_SYSERR;
  1484. s->client_notification_task =
  1485. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1486. s);
  1487. return;
  1488. }
  1489. prepare_alices_computation_request (s);
  1490. }
  1491. static void
  1492. handle_client_message_multipart (void *cls,
  1493. struct GNUNET_SERVER_Client *client,
  1494. const struct GNUNET_MessageHeader *message)
  1495. {
  1496. const struct ComputationMultipartMessage * msg;
  1497. struct ServiceSession *s;
  1498. uint32_t contained_count;
  1499. struct GNUNET_SCALARPRODUCT_Element *elements;
  1500. uint32_t i;
  1501. msg = (const struct ComputationMultipartMessage *) message;
  1502. // only one concurrent session per client connection allowed, simplifies logics a lot...
  1503. s = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession);
  1504. if (NULL == s)
  1505. {
  1506. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  1507. return;
  1508. }
  1509. contained_count = ntohl (msg->element_count_contained);
  1510. //sanity check: is the message as long as the message_count fields suggests?
  1511. if ( (ntohs (msg->header.size) != (sizeof (struct ComputationMultipartMessage) + contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ||
  1512. (0 == contained_count) ||
  1513. (s->total < s->transferred_element_count + contained_count))
  1514. {
  1515. GNUNET_break_op (0);
  1516. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  1517. return;
  1518. }
  1519. s->transferred_element_count += contained_count;
  1520. elements = (struct GNUNET_SCALARPRODUCT_Element *) & msg[1];
  1521. for (i = 0; i < contained_count; i++)
  1522. {
  1523. struct GNUNET_SET_Element set_elem;
  1524. struct GNUNET_SCALARPRODUCT_Element * elem;
  1525. if (0 == GNUNET_ntohll (elements[i].value))
  1526. continue;
  1527. elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
  1528. memcpy (elem, &elements[i], sizeof (struct GNUNET_SCALARPRODUCT_Element));
  1529. if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
  1530. &elem->key,
  1531. elem,
  1532. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
  1533. {
  1534. GNUNET_free (elem);
  1535. continue;
  1536. }
  1537. set_elem.data = &elem->key;
  1538. set_elem.size = sizeof (elem->key);
  1539. set_elem.element_type = 0; /* do we REALLY need this? */
  1540. GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
  1541. s->used_element_count++;
  1542. }
  1543. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  1544. if (s->total != s->transferred_element_count)
  1545. // multipart msg
  1546. return;
  1547. if (ALICE == s->role)
  1548. client_request_complete_alice (s);
  1549. else
  1550. client_request_complete_bob (s);
  1551. }
  1552. /**
  1553. * Handler for a client request message.
  1554. * Can either be type A or B
  1555. * A: request-initiation to compute a scalar product with a peer
  1556. * B: response role, keep the values + session and wait for a matching session or process a waiting request
  1557. *
  1558. * @param cls closure
  1559. * @param client identification of the client
  1560. * @param message the actual message
  1561. */
  1562. static void
  1563. handle_client_message (void *cls,
  1564. struct GNUNET_SERVER_Client *client,
  1565. const struct GNUNET_MessageHeader *message)
  1566. {
  1567. const struct ComputationMessage * msg = (const struct ComputationMessage *) message;
  1568. struct ServiceSession * s;
  1569. uint32_t contained_count;
  1570. uint32_t total_count;
  1571. uint32_t msg_type;
  1572. struct GNUNET_SCALARPRODUCT_Element * elements;
  1573. uint32_t i;
  1574. // only one concurrent session per client connection allowed, simplifies logics a lot...
  1575. s = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession);
  1576. if (NULL != s)
  1577. {
  1578. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  1579. return;
  1580. }
  1581. msg_type = ntohs (msg->header.type);
  1582. total_count = ntohl (msg->element_count_total);
  1583. contained_count = ntohl (msg->element_count_contained);
  1584. if ((GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type)
  1585. && (!memcmp (&msg->peer, &me, sizeof (struct GNUNET_PeerIdentity))))
  1586. {
  1587. //session with ourself makes no sense!
  1588. GNUNET_break_op (0);
  1589. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  1590. return;
  1591. }
  1592. //sanity check: is the message as long as the message_count fields suggests?
  1593. if ((ntohs (msg->header.size) !=
  1594. (sizeof (struct ComputationMessage) + contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element)))
  1595. || (0 == total_count))
  1596. {
  1597. GNUNET_break_op (0);
  1598. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  1599. return;
  1600. }
  1601. // do we have a duplicate session here already?
  1602. if (NULL != find_matching_session (from_client_tail,
  1603. &msg->session_key,
  1604. NULL))
  1605. {
  1606. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1607. _ ("Duplicate session information received, can not create new session with key `%s'\n"),
  1608. GNUNET_h2s (&msg->session_key));
  1609. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  1610. return;
  1611. }
  1612. s = GNUNET_new (struct ServiceSession);
  1613. s->active = GNUNET_YES;
  1614. s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
  1615. s->client = client;
  1616. s->total = total_count;
  1617. s->transferred_element_count = contained_count;
  1618. // get our transaction key
  1619. memcpy (&s->session_id, &msg->session_key, sizeof (struct GNUNET_HashCode));
  1620. elements = (struct GNUNET_SCALARPRODUCT_Element *) & msg[1];
  1621. s->intersected_elements = GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_NO);
  1622. s->intersection_set = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION);
  1623. for (i = 0; i < contained_count; i++)
  1624. {
  1625. struct GNUNET_SET_Element set_elem;
  1626. struct GNUNET_SCALARPRODUCT_Element * elem;
  1627. if (0 == GNUNET_ntohll (elements[i].value))
  1628. continue;
  1629. elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
  1630. memcpy (elem, &elements[i], sizeof (struct GNUNET_SCALARPRODUCT_Element));
  1631. if (GNUNET_SYSERR ==
  1632. GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
  1633. &elem->key,
  1634. elem,
  1635. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
  1636. {
  1637. GNUNET_free (elem);
  1638. continue;
  1639. }
  1640. set_elem.data = &elem->key;
  1641. set_elem.size = sizeof (elem->key);
  1642. set_elem.element_type = 0;
  1643. GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
  1644. s->used_element_count++;
  1645. }
  1646. if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type)
  1647. {
  1648. s->role = ALICE;
  1649. memcpy (&s->peer,
  1650. &msg->peer,
  1651. sizeof (struct GNUNET_PeerIdentity));
  1652. }
  1653. else
  1654. {
  1655. s->role = BOB;
  1656. }
  1657. GNUNET_CONTAINER_DLL_insert (from_client_head,
  1658. from_client_tail,
  1659. s);
  1660. GNUNET_SERVER_client_set_user_context (client, s);
  1661. GNUNET_SERVER_receive_done (client, GNUNET_YES);
  1662. if (s->total != s->transferred_element_count)
  1663. // multipart msg
  1664. return;
  1665. if (ALICE == s->role)
  1666. client_request_complete_alice (s);
  1667. else
  1668. client_request_complete_bob (s);
  1669. }
  1670. /**
  1671. * Function called for inbound channels.
  1672. *
  1673. * @param cls closure
  1674. * @param channel new handle to the channel
  1675. * @param initiator peer that started the channel
  1676. * @param port unused
  1677. * @param options unused
  1678. * @return session associated with the channel
  1679. */
  1680. static void *
  1681. cb_channel_incoming (void *cls,
  1682. struct GNUNET_CADET_Channel *channel,
  1683. const struct GNUNET_PeerIdentity *initiator,
  1684. uint32_t port,
  1685. enum GNUNET_CADET_ChannelOption options)
  1686. {
  1687. struct ServiceSession *s;
  1688. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1689. _ ("New incoming channel from peer %s.\n"),
  1690. GNUNET_i2s (initiator));
  1691. s = GNUNET_new (struct ServiceSession);
  1692. s->peer = *initiator;
  1693. s->channel = channel;
  1694. s->role = BOB;
  1695. s->active = GNUNET_YES;
  1696. return s;
  1697. }
  1698. /**
  1699. * Function called whenever a channel is destroyed. Should clean up
  1700. * any associated state.
  1701. *
  1702. * It must NOT call #GNUNET_CADET_channel_destroy() on the channel.
  1703. *
  1704. * @param cls closure (set from #GNUNET_CADET_connect())
  1705. * @param channel connection to the other end (henceforth invalid)
  1706. * @param channel_ctx place where local state associated
  1707. * with the channel is stored
  1708. */
  1709. static void
  1710. cb_channel_destruction (void *cls,
  1711. const struct GNUNET_CADET_Channel *channel,
  1712. void *channel_ctx)
  1713. {
  1714. struct ServiceSession * s = channel_ctx;
  1715. struct ServiceSession * client_session;
  1716. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1717. "Peer disconnected, terminating session %s with peer (%s)\n",
  1718. GNUNET_h2s (&s->session_id),
  1719. GNUNET_i2s (&s->peer));
  1720. // as we have only one peer connected in each session, just remove the session
  1721. s->channel = NULL;
  1722. if ( (ALICE == s->role) &&
  1723. (GNUNET_YES == s->active) &&
  1724. (! do_shutdown) )
  1725. {
  1726. // if this happened before we received the answer, we must terminate the session
  1727. s->role = GNUNET_SYSERR;
  1728. s->client_notification_task =
  1729. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1730. s);
  1731. }
  1732. else if ((BOB == s->role) && (GNUNET_SYSERR != s->active))
  1733. {
  1734. if ( (s == from_service_head) ||
  1735. ( (NULL != from_service_head) &&
  1736. ( (NULL != s->next) ||
  1737. (NULL != s->a_tail)) ) )
  1738. GNUNET_CONTAINER_DLL_remove (from_service_head,
  1739. from_service_tail,
  1740. s);
  1741. // there is a client waiting for this service session, terminate it, too!
  1742. // i assume the tupel of key and element count is unique. if it was not the rest of the code would not work either.
  1743. client_session = s->response;
  1744. if ( (NULL != s->response ) &&
  1745. (GNUNET_NO == s->active) &&
  1746. (GNUNET_YES == client_session->active) )
  1747. client_session->active = GNUNET_NO;
  1748. free_session_variables (s);
  1749. // the client has to check if it was waiting for a result
  1750. // or if it was a responder, no point in adding more statefulness
  1751. if ((NULL != s->response ) && (! do_shutdown))
  1752. {
  1753. client_session->client_notification_task
  1754. = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1755. client_session);
  1756. }
  1757. GNUNET_free (s);
  1758. }
  1759. }
  1760. /**
  1761. * Compute our scalar product, done by Alice
  1762. *
  1763. * @param session - the session associated with this computation
  1764. * @return product as MPI, never NULL
  1765. */
  1766. static gcry_mpi_t
  1767. compute_scalar_product (struct ServiceSession *session)
  1768. {
  1769. uint32_t count;
  1770. gcry_mpi_t t;
  1771. gcry_mpi_t u;
  1772. gcry_mpi_t u_prime;
  1773. gcry_mpi_t p;
  1774. gcry_mpi_t p_prime;
  1775. gcry_mpi_t tmp;
  1776. gcry_mpi_t r[session->used_element_count];
  1777. gcry_mpi_t r_prime[session->used_element_count];
  1778. gcry_mpi_t s;
  1779. gcry_mpi_t s_prime;
  1780. unsigned int i;
  1781. count = session->used_element_count;
  1782. // due to the introduced static offset S, we now also have to remove this
  1783. // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
  1784. // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
  1785. for (i = 0; i < count; i++)
  1786. {
  1787. r[i] = gcry_mpi_new (0);
  1788. GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
  1789. &my_pubkey,
  1790. &session->r[i],
  1791. r[i]);
  1792. gcry_mpi_sub (r[i], r[i], my_offset);
  1793. gcry_mpi_sub (r[i], r[i], my_offset);
  1794. r_prime[i] = gcry_mpi_new (0);
  1795. GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
  1796. &my_pubkey,
  1797. &session->r_prime[i],
  1798. r_prime[i]);
  1799. gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
  1800. gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
  1801. }
  1802. // calculate t = sum(ai)
  1803. t = compute_square_sum (session->sorted_elements, count);
  1804. // calculate U
  1805. u = gcry_mpi_new (0);
  1806. tmp = compute_square_sum (r, count);
  1807. gcry_mpi_sub (u, u, tmp);
  1808. gcry_mpi_release (tmp);
  1809. //calculate U'
  1810. u_prime = gcry_mpi_new (0);
  1811. tmp = compute_square_sum (r_prime, count);
  1812. gcry_mpi_sub (u_prime, u_prime, tmp);
  1813. GNUNET_assert (p = gcry_mpi_new (0));
  1814. GNUNET_assert (p_prime = gcry_mpi_new (0));
  1815. GNUNET_assert (s = gcry_mpi_new (0));
  1816. GNUNET_assert (s_prime = gcry_mpi_new (0));
  1817. // compute P
  1818. GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
  1819. &my_pubkey,
  1820. &session->s,
  1821. s);
  1822. GNUNET_CRYPTO_paillier_decrypt (&my_privkey,
  1823. &my_pubkey,
  1824. &session->s_prime,
  1825. s_prime);
  1826. // compute P
  1827. gcry_mpi_add (p, s, t);
  1828. gcry_mpi_add (p, p, u);
  1829. // compute P'
  1830. gcry_mpi_add (p_prime, s_prime, t);
  1831. gcry_mpi_add (p_prime, p_prime, u_prime);
  1832. gcry_mpi_release (t);
  1833. gcry_mpi_release (u);
  1834. gcry_mpi_release (u_prime);
  1835. gcry_mpi_release (s);
  1836. gcry_mpi_release (s_prime);
  1837. // compute product
  1838. gcry_mpi_sub (p, p, p_prime);
  1839. gcry_mpi_release (p_prime);
  1840. tmp = gcry_mpi_set_ui (tmp, 2);
  1841. gcry_mpi_div (p, NULL, p, tmp, 0);
  1842. gcry_mpi_release (tmp);
  1843. for (i = 0; i < count; i++)
  1844. {
  1845. gcry_mpi_release (session->sorted_elements[i]);
  1846. gcry_mpi_release (r[i]);
  1847. gcry_mpi_release (r_prime[i]);
  1848. }
  1849. GNUNET_free (session->a_head);
  1850. session->a_head = NULL;
  1851. GNUNET_free (session->r);
  1852. session->r = NULL;
  1853. GNUNET_free (session->r_prime);
  1854. session->r_prime = NULL;
  1855. return p;
  1856. }
  1857. /**
  1858. * Handle a multipart-chunk of a request from another service to calculate a scalarproduct with us.
  1859. *
  1860. * @param cls closure (set from #GNUNET_CADET_connect)
  1861. * @param channel connection to the other end
  1862. * @param channel_ctx place to store local state associated with the @a channel
  1863. * @param message the actual message
  1864. * @return #GNUNET_OK to keep the connection open,
  1865. * #GNUNET_SYSERR to close it (signal serious error)
  1866. */
  1867. static int
  1868. handle_alices_cyrptodata_message_multipart (void *cls,
  1869. struct GNUNET_CADET_Channel *channel,
  1870. void **channel_ctx,
  1871. const struct GNUNET_MessageHeader *message)
  1872. {
  1873. struct ServiceSession * s;
  1874. const struct MultipartMessage * msg = (const struct MultipartMessage *) message;
  1875. struct GNUNET_CRYPTO_PaillierCiphertext *payload;
  1876. uint32_t contained_elements;
  1877. uint32_t msg_length;
  1878. // are we in the correct state?
  1879. s = (struct ServiceSession *) * channel_ctx;
  1880. //we are not bob
  1881. if ((NULL == s->e_a) || //or we did not expect this message yet
  1882. (s->used_element_count == s->transferred_element_count))
  1883. { //we are not expecting multipart messages
  1884. goto except;
  1885. }
  1886. // shorter than minimum?
  1887. if (ntohs (msg->header.size) <= sizeof (struct MultipartMessage))
  1888. {
  1889. goto except;
  1890. }
  1891. contained_elements = ntohl (msg->contained_element_count);
  1892. msg_length = sizeof (struct MultipartMessage)
  1893. +contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  1894. //sanity check
  1895. if ((ntohs (msg->header.size) != msg_length)
  1896. || (s->used_element_count < contained_elements + s->transferred_element_count)
  1897. || (0 == contained_elements))
  1898. {
  1899. goto except;
  1900. }
  1901. payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
  1902. // Convert each vector element to MPI_value
  1903. memcpy (&s->e_a[s->transferred_element_count], payload,
  1904. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * contained_elements);
  1905. s->transferred_element_count += contained_elements;
  1906. if (contained_elements == s->used_element_count)
  1907. {
  1908. // single part finished
  1909. if (NULL == s->intersection_op)
  1910. // intersection has already finished, so we can proceed
  1911. compute_service_response (s);
  1912. }
  1913. return GNUNET_OK;
  1914. except:
  1915. s->channel = NULL;
  1916. // and notify our client-session that we could not complete the session
  1917. free_session_variables (s);
  1918. if (NULL != s->client)
  1919. {
  1920. //Alice
  1921. s->active = GNUNET_SYSERR;
  1922. s->client_notification_task =
  1923. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1924. s);
  1925. }
  1926. else
  1927. {
  1928. //Bob
  1929. if (NULL != s->response){
  1930. s->response->active = GNUNET_SYSERR;
  1931. s->response->client_notification_task =
  1932. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  1933. s->response);
  1934. }
  1935. if ( (s == from_service_head) ||
  1936. ( (NULL != from_service_head) &&
  1937. ( (NULL != s->next) ||
  1938. (NULL != s->a_tail)) ) )
  1939. GNUNET_CONTAINER_DLL_remove (from_service_head,
  1940. from_service_tail,
  1941. s);
  1942. GNUNET_free (s);
  1943. }
  1944. return GNUNET_SYSERR;
  1945. }
  1946. /**
  1947. * Handle a request from another service to calculate a scalarproduct with us.
  1948. *
  1949. * @param cls closure (set from #GNUNET_CADET_connect)
  1950. * @param channel connection to the other end
  1951. * @param channel_ctx place to store local state associated with the channel
  1952. * @param message the actual message
  1953. * @return #GNUNET_OK to keep the connection open,
  1954. * #GNUNET_SYSERR to close it (signal serious error)
  1955. */
  1956. static int
  1957. handle_alices_cyrptodata_message (void *cls,
  1958. struct GNUNET_CADET_Channel *channel,
  1959. void **channel_ctx,
  1960. const struct GNUNET_MessageHeader *message)
  1961. {
  1962. struct ServiceSession * s;
  1963. const struct AliceCryptodataMessage *msg;
  1964. struct GNUNET_CRYPTO_PaillierCiphertext *payload;
  1965. uint32_t contained_elements = 0;
  1966. uint32_t msg_length;
  1967. s = (struct ServiceSession *) * channel_ctx;
  1968. //we are not bob
  1969. if ((BOB != s->role)
  1970. //we are expecting multipart messages instead
  1971. || (NULL != s->e_a)
  1972. //or we did not expect this message yet
  1973. || //intersection OP has not yet finished
  1974. !((NULL != s->intersection_op)
  1975. //intersection OP done
  1976. || (s->response->sorted_elements)
  1977. ))
  1978. {
  1979. goto invalid_msg;
  1980. }
  1981. if (ntohs (message->size) < sizeof (struct AliceCryptodataMessage))
  1982. {
  1983. GNUNET_break_op (0);
  1984. goto invalid_msg;
  1985. }
  1986. msg = (const struct AliceCryptodataMessage *) message;
  1987. contained_elements = ntohl (msg->contained_element_count);
  1988. msg_length = sizeof (struct AliceCryptodataMessage)
  1989. +contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  1990. //sanity check: is the message as long as the message_count fields suggests?
  1991. if ((ntohs (msg->header.size) != msg_length) ||
  1992. (s->used_element_count < s->transferred_element_count + contained_elements) ||
  1993. (0 == contained_elements))
  1994. {
  1995. goto invalid_msg;
  1996. }
  1997. s->transferred_element_count = contained_elements;
  1998. payload = (struct GNUNET_CRYPTO_PaillierCiphertext*) &msg[1];
  1999. s->e_a = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
  2000. memcpy (&s->e_a[0],
  2001. payload,
  2002. contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  2003. if (contained_elements == s->used_element_count)
  2004. {
  2005. // single part finished
  2006. if (NULL == s->intersection_op)
  2007. // intersection has already finished, so we can proceed
  2008. compute_service_response (s);
  2009. }
  2010. return GNUNET_OK;
  2011. invalid_msg:
  2012. GNUNET_break_op (0);
  2013. s->channel = NULL;
  2014. // and notify our client-session that we could not complete the session
  2015. free_session_variables (s);
  2016. if (NULL != s->client)
  2017. {
  2018. //Alice
  2019. s->active = GNUNET_SYSERR;
  2020. s->client_notification_task =
  2021. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  2022. s);
  2023. }
  2024. else
  2025. {
  2026. //Bob
  2027. if (NULL != s->response)
  2028. {
  2029. s->response->active = GNUNET_SYSERR;
  2030. s->response->client_notification_task =
  2031. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  2032. s->response);
  2033. }
  2034. if ( (s == from_service_head) ||
  2035. ( (NULL != from_service_head) &&
  2036. ( (NULL != s->next) ||
  2037. (NULL != s->a_tail)) ) )
  2038. GNUNET_CONTAINER_DLL_remove (from_service_head,
  2039. from_service_tail,
  2040. s);
  2041. GNUNET_free(s);
  2042. }
  2043. return GNUNET_SYSERR;
  2044. }
  2045. /**
  2046. * Handle a request from another service to calculate a scalarproduct with us.
  2047. *
  2048. * @param cls closure (set from #GNUNET_CADET_connect)
  2049. * @param channel connection to the other end
  2050. * @param channel_ctx place to store local state associated with the channel
  2051. * @param message the actual message
  2052. * @return #GNUNET_OK to keep the connection open,
  2053. * #GNUNET_SYSERR to close it (signal serious error)
  2054. */
  2055. static int
  2056. handle_alices_computation_request (void *cls,
  2057. struct GNUNET_CADET_Channel *channel,
  2058. void **channel_ctx,
  2059. const struct GNUNET_MessageHeader *message)
  2060. {
  2061. struct ServiceSession * s;
  2062. struct ServiceSession * client_session;
  2063. const struct ServiceRequestMessage *msg;
  2064. msg = (const struct ServiceRequestMessage *) message;
  2065. s = (struct ServiceSession *) * channel_ctx;
  2066. if ((BOB != s->role) || (0 != s->total))
  2067. {
  2068. // must be a fresh session
  2069. goto invalid_msg;
  2070. }
  2071. // Check if message was sent by me, which would be bad!
  2072. if (0 != memcmp (&s->peer,
  2073. &me,
  2074. sizeof (struct GNUNET_PeerIdentity)))
  2075. {
  2076. GNUNET_free (s);
  2077. GNUNET_break (0);
  2078. return GNUNET_SYSERR;
  2079. }
  2080. if (find_matching_session (from_service_tail,
  2081. &msg->session_id,
  2082. NULL))
  2083. {
  2084. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2085. _("Got message with duplicate session key (`%s'), ignoring service request.\n"),
  2086. (const char *) &(msg->session_id));
  2087. GNUNET_free (s);
  2088. return GNUNET_SYSERR;
  2089. }
  2090. s->channel = channel;
  2091. s->session_id = msg->session_id;
  2092. s->remote_pubkey = msg->public_key;
  2093. //check if service queue contains a matching request
  2094. client_session = find_matching_session (from_client_tail,
  2095. &s->session_id,
  2096. NULL);
  2097. GNUNET_CONTAINER_DLL_insert (from_service_head,
  2098. from_service_tail,
  2099. s);
  2100. if ( (NULL != client_session) &&
  2101. (client_session->transferred_element_count == client_session->total) )
  2102. {
  2103. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2104. "Got session with key %s and a matching element set, processing.\n",
  2105. GNUNET_h2s (&s->session_id));
  2106. s->response = client_session;
  2107. s->intersected_elements = client_session->intersected_elements;
  2108. client_session->intersected_elements = NULL;
  2109. s->intersection_set = client_session->intersection_set;
  2110. client_session->intersection_set = NULL;
  2111. s->intersection_op
  2112. = GNUNET_SET_prepare (&s->peer,
  2113. &s->session_id,
  2114. NULL,
  2115. GNUNET_SET_RESULT_REMOVED,
  2116. &cb_intersection_element_removed,
  2117. s);
  2118. GNUNET_SET_commit (s->intersection_op,
  2119. s->intersection_set);
  2120. }
  2121. else
  2122. {
  2123. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2124. "Got session with key %s without a matching element set, queueing.\n",
  2125. GNUNET_h2s (&s->session_id));
  2126. }
  2127. return GNUNET_OK;
  2128. invalid_msg:
  2129. GNUNET_break_op (0);
  2130. s->channel = NULL;
  2131. // and notify our client-session that we could not complete the session
  2132. free_session_variables (s);
  2133. if (NULL != s->client)
  2134. {
  2135. //Alice
  2136. s->active = GNUNET_SYSERR;
  2137. s->client_notification_task =
  2138. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  2139. s);
  2140. }
  2141. else
  2142. {
  2143. //Bob
  2144. if (NULL != s->response) {
  2145. s->response->active = GNUNET_SYSERR;
  2146. s->response->client_notification_task =
  2147. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  2148. s->response);
  2149. }
  2150. if ( (s == from_service_head) ||
  2151. ( (NULL != from_service_head) &&
  2152. ( (NULL != s->next) ||
  2153. (NULL != s->a_tail)) ) )
  2154. GNUNET_CONTAINER_DLL_remove (from_service_head,
  2155. from_service_tail,
  2156. s);
  2157. GNUNET_free(s);
  2158. }
  2159. return GNUNET_SYSERR;
  2160. }
  2161. /**
  2162. * Handle a multipart chunk of a response we got from another service we wanted to calculate a scalarproduct with.
  2163. *
  2164. * @param cls closure (set from #GNUNET_CADET_connect)
  2165. * @param channel connection to the other end
  2166. * @param channel_ctx place to store local state associated with the @a channel
  2167. * @param message the actual message
  2168. * @return #GNUNET_OK to keep the connection open,
  2169. * #GNUNET_SYSERR to close it (signal serious error)
  2170. */
  2171. static int
  2172. handle_bobs_cryptodata_multipart (void *cls,
  2173. struct GNUNET_CADET_Channel *channel,
  2174. void **channel_ctx,
  2175. const struct GNUNET_MessageHeader *message)
  2176. {
  2177. struct ServiceSession * s;
  2178. const struct MultipartMessage *msg;
  2179. struct GNUNET_CRYPTO_PaillierCiphertext * payload;
  2180. size_t i;
  2181. uint32_t contained = 0;
  2182. size_t msg_size;
  2183. size_t required_size;
  2184. GNUNET_assert (NULL != message);
  2185. // are we in the correct state?
  2186. s = (struct ServiceSession *) * channel_ctx;
  2187. if ((ALICE != s->role) || (NULL == s->sorted_elements))
  2188. {
  2189. goto invalid_msg;
  2190. }
  2191. msg_size = ntohs (message->size);
  2192. if (sizeof (struct MultipartMessage) > msg_size)
  2193. {
  2194. GNUNET_break_op (0);
  2195. goto invalid_msg;
  2196. }
  2197. msg = (const struct MultipartMessage *) message;
  2198. contained = ntohl (msg->contained_element_count);
  2199. required_size = sizeof (struct MultipartMessage)
  2200. + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  2201. //sanity check: is the message as long as the message_count fields suggests?
  2202. if ( (required_size != msg_size) ||
  2203. (s->used_element_count < s->transferred_element_count + contained) )
  2204. {
  2205. goto invalid_msg;
  2206. }
  2207. payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
  2208. // Convert each k[][perm] to its MPI_value
  2209. for (i = 0; i < contained; i++)
  2210. {
  2211. memcpy (&s->r[s->transferred_element_count + i],
  2212. &payload[2 * i],
  2213. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  2214. memcpy (&s->r_prime[s->transferred_element_count + i],
  2215. &payload[2 * i],
  2216. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  2217. }
  2218. s->transferred_element_count += contained;
  2219. if (s->transferred_element_count != s->used_element_count)
  2220. return GNUNET_OK;
  2221. s->product = compute_scalar_product (s); //never NULL
  2222. invalid_msg:
  2223. GNUNET_break_op (NULL != s->product);
  2224. s->channel = NULL;
  2225. // send message with product to client
  2226. if (NULL != s->client)
  2227. {
  2228. //Alice
  2229. if (NULL != s->product)
  2230. s->active = GNUNET_NO;
  2231. else
  2232. s->active = GNUNET_SYSERR;
  2233. s->client_notification_task =
  2234. GNUNET_SCHEDULER_add_now (&prepare_client_response,
  2235. s);
  2236. }
  2237. else
  2238. {
  2239. //Bob
  2240. if (NULL != s->response){
  2241. s->response->active = GNUNET_SYSERR;
  2242. s->response->client_notification_task =
  2243. GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  2244. s->response);
  2245. }
  2246. if ( (s == from_service_head) ||
  2247. ( (NULL != from_service_head) &&
  2248. ( (NULL != s->next) ||
  2249. (NULL != s->a_tail)) ) )
  2250. GNUNET_CONTAINER_DLL_remove (from_service_head,
  2251. from_service_tail,
  2252. s);
  2253. free_session_variables (s);
  2254. GNUNET_free(s);
  2255. }
  2256. // the channel has done its job, terminate our connection and the channel
  2257. // the peer will be notified that the channel was destroyed via channel_destruction_handler
  2258. // just close the connection, as recommended by Christian
  2259. return GNUNET_SYSERR;
  2260. }
  2261. /**
  2262. * Handle a response we got from another service we wanted to calculate a scalarproduct with.
  2263. *
  2264. * @param cls closure (set from #GNUNET_CADET_connect)
  2265. * @param channel connection to the other end
  2266. * @param channel_ctx place to store local state associated with the channel
  2267. * @param message the actual message
  2268. * @return #GNUNET_OK to keep the connection open,
  2269. * #GNUNET_SYSERR to close it (we are done)
  2270. */
  2271. static int
  2272. handle_bobs_cryptodata_message (void *cls,
  2273. struct GNUNET_CADET_Channel *channel,
  2274. void **channel_ctx,
  2275. const struct GNUNET_MessageHeader *message)
  2276. {
  2277. struct ServiceSession *s;
  2278. const struct ServiceResponseMessage *msg;
  2279. struct GNUNET_CRYPTO_PaillierCiphertext * payload;
  2280. size_t i;
  2281. uint32_t contained = 0;
  2282. size_t msg_size;
  2283. size_t required_size;
  2284. GNUNET_assert (NULL != message);
  2285. s = (struct ServiceSession *) * channel_ctx;
  2286. // are we in the correct state?
  2287. if (NULL == s->sorted_elements
  2288. || NULL != s->msg
  2289. || s->used_element_count != s->transferred_element_count)
  2290. {
  2291. goto invalid_msg;
  2292. }
  2293. //we need at least a full message without elements attached
  2294. msg_size = ntohs (message->size);
  2295. if (sizeof (struct ServiceResponseMessage) > msg_size)
  2296. {
  2297. GNUNET_break_op (0);
  2298. goto invalid_msg;
  2299. }
  2300. msg = (const struct ServiceResponseMessage *) message;
  2301. contained = ntohl (msg->contained_element_count);
  2302. required_size = sizeof (struct ServiceResponseMessage)
  2303. + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)
  2304. + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
  2305. //sanity check: is the message as long as the message_count fields suggests?
  2306. if ((msg_size != required_size) || (s->used_element_count < contained))
  2307. {
  2308. goto invalid_msg;
  2309. }
  2310. s->transferred_element_count = contained;
  2311. //convert s
  2312. payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
  2313. memcpy (&s->s,
  2314. &payload[0],
  2315. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  2316. memcpy (&s->s_prime,
  2317. &payload[1],
  2318. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  2319. s->r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
  2320. s->r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
  2321. payload = &payload[2];
  2322. // Convert each k[][perm] to its MPI_value
  2323. for (i = 0; i < contained; i++)
  2324. {
  2325. memcpy (&s->r[i],
  2326. &payload[2 * i],
  2327. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  2328. memcpy (&s->r_prime[i],
  2329. &payload[2 * i + 1],
  2330. sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
  2331. }
  2332. if (s->transferred_element_count != s->used_element_count)
  2333. return GNUNET_OK; //wait for the other multipart chunks
  2334. s->product = compute_scalar_product (s); //never NULL
  2335. invalid_msg:
  2336. GNUNET_break_op (NULL != s->product);
  2337. s->channel = NULL;
  2338. // send message with product to client
  2339. if (NULL != s->client)
  2340. {
  2341. //Alice
  2342. s->client_notification_task =
  2343. GNUNET_SCHEDULER_add_now (&prepare_client_response,
  2344. s);
  2345. }
  2346. else
  2347. {
  2348. //Bob
  2349. if (NULL != s->response)
  2350. {
  2351. s->response->active = GNUNET_SYSERR;
  2352. s->response->client_notification_task
  2353. = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
  2354. s->response);
  2355. }
  2356. if ( (s == from_service_head) ||
  2357. ( (NULL != from_service_head) &&
  2358. ( (NULL != s->next) ||
  2359. (NULL != s->a_tail)) ) )
  2360. GNUNET_CONTAINER_DLL_remove (from_service_head,
  2361. from_service_tail,
  2362. s);
  2363. free_session_variables (s);
  2364. GNUNET_free(s);
  2365. }
  2366. // the channel has done its job, terminate our connection and the channel
  2367. // the peer will be notified that the channel was destroyed via channel_destruction_handler
  2368. // just close the connection, as recommended by Christian
  2369. return GNUNET_SYSERR;
  2370. }
  2371. /**
  2372. * Task run during shutdown.
  2373. *
  2374. * @param cls unused
  2375. * @param tc unused
  2376. */
  2377. static void
  2378. shutdown_task (void *cls,
  2379. const struct GNUNET_SCHEDULER_TaskContext *tc)
  2380. {
  2381. struct ServiceSession * s;
  2382. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2383. "Shutting down, initiating cleanup.\n");
  2384. do_shutdown = GNUNET_YES;
  2385. // terminate all owned open channels.
  2386. // FIXME: this should be unnecessary, as we should
  2387. // get client disconnect events that create the same effect.
  2388. for (s = from_client_head; NULL != s; s = s->next)
  2389. {
  2390. if ((GNUNET_NO != s->active) && (NULL != s->channel))
  2391. {
  2392. GNUNET_CADET_channel_destroy (s->channel);
  2393. s->channel = NULL;
  2394. }
  2395. if (GNUNET_SCHEDULER_NO_TASK != s->client_notification_task)
  2396. {
  2397. GNUNET_SCHEDULER_cancel (s->client_notification_task);
  2398. s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
  2399. }
  2400. if (NULL != s->client)
  2401. {
  2402. GNUNET_SERVER_client_disconnect (s->client);
  2403. s->client = NULL;
  2404. }
  2405. }
  2406. for (s = from_service_head; NULL != s; s = s->next)
  2407. if (NULL != s->channel)
  2408. {
  2409. GNUNET_CADET_channel_destroy (s->channel);
  2410. s->channel = NULL;
  2411. }
  2412. if (my_cadet)
  2413. {
  2414. GNUNET_CADET_disconnect (my_cadet);
  2415. my_cadet = NULL;
  2416. }
  2417. }
  2418. /**
  2419. * Initialization of the program and message handlers
  2420. *
  2421. * @param cls closure
  2422. * @param server the initialized server
  2423. * @param c configuration to use
  2424. */
  2425. static void
  2426. run (void *cls,
  2427. struct GNUNET_SERVER_Handle *server,
  2428. const struct GNUNET_CONFIGURATION_Handle *c)
  2429. {
  2430. static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
  2431. { &handle_client_message, NULL,
  2432. GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE,
  2433. 0},
  2434. { &handle_client_message, NULL,
  2435. GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB,
  2436. 0},
  2437. { &handle_client_message_multipart, NULL,
  2438. GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART,
  2439. 0},
  2440. { NULL, NULL, 0, 0}
  2441. };
  2442. static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
  2443. { &handle_alices_computation_request,
  2444. GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION,
  2445. sizeof (struct ServiceRequestMessage) },
  2446. { &handle_alices_cyrptodata_message,
  2447. GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA,
  2448. 0},
  2449. { &handle_alices_cyrptodata_message_multipart,
  2450. GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART,
  2451. 0},
  2452. { &handle_bobs_cryptodata_message,
  2453. GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA,
  2454. 0},
  2455. { &handle_bobs_cryptodata_multipart,
  2456. GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART,
  2457. 0},
  2458. { NULL, 0, 0}
  2459. };
  2460. static const uint32_t ports[] = {
  2461. GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
  2462. 0
  2463. };
  2464. cfg = c;
  2465. //generate private/public key set
  2466. GNUNET_CRYPTO_paillier_create (&my_pubkey,
  2467. &my_privkey);
  2468. // offset has to be sufficiently small to allow computation of:
  2469. // m1+m2 mod n == (S + a) + (S + b) mod n,
  2470. // if we have more complex operations, this factor needs to be lowered
  2471. my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
  2472. gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
  2473. // register server callbacks and disconnect handler
  2474. GNUNET_SERVER_add_handlers (server, server_handlers);
  2475. GNUNET_SERVER_disconnect_notify (server,
  2476. &cb_client_disconnect,
  2477. NULL);
  2478. GNUNET_break (GNUNET_OK ==
  2479. GNUNET_CRYPTO_get_peer_identity (cfg,
  2480. &me));
  2481. my_cadet = GNUNET_CADET_connect (cfg, NULL,
  2482. &cb_channel_incoming,
  2483. &cb_channel_destruction,
  2484. cadet_handlers,
  2485. ports);
  2486. if (!my_cadet)
  2487. {
  2488. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2489. _("Connect to CADET failed\n"));
  2490. GNUNET_SCHEDULER_shutdown ();
  2491. return;
  2492. }
  2493. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  2494. "Connection to CADET initialized\n");
  2495. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
  2496. &shutdown_task,
  2497. NULL);
  2498. }
  2499. /**
  2500. * The main function for the scalarproduct service.
  2501. *
  2502. * @param argc number of arguments from the command line
  2503. * @param argv command line arguments
  2504. * @return 0 ok, 1 on error
  2505. */
  2506. int
  2507. main (int argc, char *const *argv)
  2508. {
  2509. return (GNUNET_OK ==
  2510. GNUNET_SERVICE_run (argc, argv,
  2511. "scalarproduct",
  2512. GNUNET_SERVICE_OPTION_NONE,
  2513. &run, NULL)) ? 0 : 1;
  2514. }
  2515. /* end of gnunet-service-scalarproduct.c */