identity_api.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2013, 2016 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your 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. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file identity/identity_api.c
  18. * @brief api to interact with the identity service
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_constants.h"
  24. #include "gnunet_protocols.h"
  25. #include "gnunet_identity_service.h"
  26. #include "identity.h"
  27. #define LOG(kind, ...) GNUNET_log_from (kind, "identity-api", __VA_ARGS__)
  28. /**
  29. * Handle for an operation with the identity service.
  30. */
  31. struct GNUNET_IDENTITY_Operation
  32. {
  33. /**
  34. * Main identity handle.
  35. */
  36. struct GNUNET_IDENTITY_Handle *h;
  37. /**
  38. * We keep operations in a DLL.
  39. */
  40. struct GNUNET_IDENTITY_Operation *next;
  41. /**
  42. * We keep operations in a DLL.
  43. */
  44. struct GNUNET_IDENTITY_Operation *prev;
  45. /**
  46. * Message to send to the identity service.
  47. * Allocated at the end of this struct.
  48. */
  49. const struct GNUNET_MessageHeader *msg;
  50. /**
  51. * Continuation to invoke with the result of the transmission; @e cb
  52. * and @e create_cont will be NULL in this case.
  53. */
  54. GNUNET_IDENTITY_Continuation cont;
  55. /**
  56. * Continuation to invoke with the result of the transmission; @e cb
  57. * and @a cb will be NULL in this case.
  58. */
  59. GNUNET_IDENTITY_CreateContinuation create_cont;
  60. /**
  61. * Private key to return to @e create_cont, or NULL.
  62. */
  63. struct GNUNET_IDENTITY_PrivateKey pk;
  64. /**
  65. * Continuation to invoke with the result of the transmission for
  66. * 'get' operations (@e cont and @a create_cont will be NULL in this case).
  67. */
  68. GNUNET_IDENTITY_Callback cb;
  69. /**
  70. * Closure for @e cont or @e cb.
  71. */
  72. void *cls;
  73. };
  74. /**
  75. * Handle for the service.
  76. */
  77. struct GNUNET_IDENTITY_Handle
  78. {
  79. /**
  80. * Configuration to use.
  81. */
  82. const struct GNUNET_CONFIGURATION_Handle *cfg;
  83. /**
  84. * Connection to service.
  85. */
  86. struct GNUNET_MQ_Handle *mq;
  87. /**
  88. * Hash map from the hash of the private key to the
  89. * respective `GNUNET_IDENTITY_Ego` handle.
  90. */
  91. struct GNUNET_CONTAINER_MultiHashMap *egos;
  92. /**
  93. * Function to call when we receive updates.
  94. */
  95. GNUNET_IDENTITY_Callback cb;
  96. /**
  97. * Closure for @e cb.
  98. */
  99. void *cb_cls;
  100. /**
  101. * Head of active operations.
  102. */
  103. struct GNUNET_IDENTITY_Operation *op_head;
  104. /**
  105. * Tail of active operations.
  106. */
  107. struct GNUNET_IDENTITY_Operation *op_tail;
  108. /**
  109. * Task doing exponential back-off trying to reconnect.
  110. */
  111. struct GNUNET_SCHEDULER_Task *reconnect_task;
  112. /**
  113. * Time for next connect retry.
  114. */
  115. struct GNUNET_TIME_Relative reconnect_delay;
  116. /**
  117. * Are we polling for incoming messages right now?
  118. */
  119. int in_receive;
  120. };
  121. /**
  122. * Obtain the ego representing 'anonymous' users.
  123. *
  124. * @return handle for the anonymous user, MUST NOT be freed
  125. */
  126. struct GNUNET_IDENTITY_Ego *
  127. GNUNET_IDENTITY_ego_get_anonymous ()
  128. {
  129. static struct GNUNET_IDENTITY_Ego anon;
  130. static int setup;
  131. if (setup)
  132. return &anon;
  133. anon.pk.type = htonl (GNUNET_IDENTITY_TYPE_ECDSA);
  134. anon.pub.type = htonl (GNUNET_IDENTITY_TYPE_ECDSA);
  135. anon.pk.ecdsa_key = *GNUNET_CRYPTO_ecdsa_key_get_anonymous ();
  136. GNUNET_CRYPTO_hash (&anon.pk,
  137. sizeof(anon.pk),
  138. &anon.id);
  139. setup = 1;
  140. return &anon;
  141. }
  142. enum GNUNET_GenericReturnValue
  143. GNUNET_IDENTITY_key_get_public (const struct
  144. GNUNET_IDENTITY_PrivateKey *privkey,
  145. struct GNUNET_IDENTITY_PublicKey *key)
  146. {
  147. key->type = privkey->type;
  148. switch (ntohl (privkey->type))
  149. {
  150. case GNUNET_IDENTITY_TYPE_ECDSA:
  151. GNUNET_CRYPTO_ecdsa_key_get_public (&privkey->ecdsa_key,
  152. &key->ecdsa_key);
  153. break;
  154. case GNUNET_IDENTITY_TYPE_EDDSA:
  155. GNUNET_CRYPTO_eddsa_key_get_public (&privkey->eddsa_key,
  156. &key->eddsa_key);
  157. break;
  158. default:
  159. GNUNET_break (0);
  160. return GNUNET_SYSERR;
  161. }
  162. return GNUNET_OK;
  163. }
  164. static int
  165. private_key_create (enum GNUNET_IDENTITY_KeyType ktype,
  166. struct GNUNET_IDENTITY_PrivateKey *key)
  167. {
  168. key->type = htonl (ktype);
  169. switch (ktype)
  170. {
  171. case GNUNET_IDENTITY_TYPE_ECDSA:
  172. GNUNET_CRYPTO_ecdsa_key_create (&key->ecdsa_key);
  173. break;
  174. case GNUNET_IDENTITY_TYPE_EDDSA:
  175. GNUNET_CRYPTO_eddsa_key_create (&key->eddsa_key);
  176. break;
  177. default:
  178. GNUNET_break (0);
  179. return GNUNET_SYSERR;
  180. }
  181. return GNUNET_OK;
  182. }
  183. /**
  184. * Try again to connect to the identity service.
  185. *
  186. * @param cls handle to the identity service.
  187. */
  188. static void
  189. reconnect (void *cls);
  190. /**
  191. * Free ego from hash map.
  192. *
  193. * @param cls identity service handle
  194. * @param key unused
  195. * @param value ego to free
  196. * @return #GNUNET_OK (continue to iterate)
  197. */
  198. static int
  199. free_ego (void *cls,
  200. const struct GNUNET_HashCode *key,
  201. void *value)
  202. {
  203. struct GNUNET_IDENTITY_Handle *h = cls;
  204. struct GNUNET_IDENTITY_Ego *ego = value;
  205. if (NULL != h->cb)
  206. h->cb (h->cb_cls, ego,
  207. &ego->ctx,
  208. NULL);
  209. GNUNET_free (ego->name);
  210. GNUNET_assert (GNUNET_YES ==
  211. GNUNET_CONTAINER_multihashmap_remove (h->egos,
  212. key,
  213. value));
  214. GNUNET_free (ego);
  215. return GNUNET_OK;
  216. }
  217. /**
  218. * Reschedule a connect attempt to the service.
  219. *
  220. * @param h transport service to reconnect
  221. */
  222. static void
  223. reschedule_connect (struct GNUNET_IDENTITY_Handle *h)
  224. {
  225. struct GNUNET_IDENTITY_Operation *op;
  226. GNUNET_assert (NULL == h->reconnect_task);
  227. if (NULL != h->mq)
  228. {
  229. GNUNET_MQ_destroy (h->mq);
  230. h->mq = NULL;
  231. }
  232. while (NULL != (op = h->op_head))
  233. {
  234. GNUNET_CONTAINER_DLL_remove (h->op_head,
  235. h->op_tail,
  236. op);
  237. if (NULL != op->cont)
  238. op->cont (op->cls,
  239. "Error in communication with the identity service");
  240. else if (NULL != op->cb)
  241. op->cb (op->cls, NULL, NULL, NULL);
  242. else if (NULL != op->create_cont)
  243. op->create_cont (op->cls,
  244. NULL,
  245. "Failed to communicate with the identity service");
  246. GNUNET_free (op);
  247. }
  248. GNUNET_CONTAINER_multihashmap_iterate (h->egos,
  249. &free_ego,
  250. h);
  251. LOG (GNUNET_ERROR_TYPE_DEBUG,
  252. "Scheduling task to reconnect to identity service in %s.\n",
  253. GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay,
  254. GNUNET_YES));
  255. h->reconnect_task =
  256. GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
  257. &reconnect,
  258. h);
  259. h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
  260. }
  261. /**
  262. * Generic error handler, called with the appropriate error code and
  263. * the same closure specified at the creation of the message queue.
  264. * Not every message queue implementation supports an error handler.
  265. *
  266. * @param cls closure with the `struct GNUNET_IDENTITY_Handle *`
  267. * @param error error code
  268. */
  269. static void
  270. mq_error_handler (void *cls,
  271. enum GNUNET_MQ_Error error)
  272. {
  273. struct GNUNET_IDENTITY_Handle *h = cls;
  274. reschedule_connect (h);
  275. }
  276. /**
  277. * We received a result code from the service. Check the message
  278. * is well-formed.
  279. *
  280. * @param cls closure
  281. * @param rcm result message received
  282. * @return #GNUNET_OK if the message is well-formed
  283. */
  284. static int
  285. check_identity_result_code (void *cls,
  286. const struct ResultCodeMessage *rcm)
  287. {
  288. if (sizeof(*rcm) != htons (rcm->header.size))
  289. GNUNET_MQ_check_zero_termination (rcm);
  290. return GNUNET_OK;
  291. }
  292. /**
  293. * We received a result code from the service.
  294. *
  295. * @param cls closure
  296. * @param rcm result message received
  297. */
  298. static void
  299. handle_identity_result_code (void *cls,
  300. const struct ResultCodeMessage *rcm)
  301. {
  302. struct GNUNET_IDENTITY_Handle *h = cls;
  303. struct GNUNET_IDENTITY_Operation *op;
  304. uint16_t size = ntohs (rcm->header.size) - sizeof(*rcm);
  305. const char *str = (0 == size) ? NULL : (const char *) &rcm[1];
  306. op = h->op_head;
  307. if (NULL == op)
  308. {
  309. GNUNET_break (0);
  310. reschedule_connect (h);
  311. return;
  312. }
  313. GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
  314. if (NULL != op->cont)
  315. op->cont (op->cls, str);
  316. else if (NULL != op->cb)
  317. op->cb (op->cls, NULL, NULL, NULL);
  318. else if (NULL != op->create_cont)
  319. op->create_cont (op->cls, (NULL == str) ? &op->pk : NULL, str);
  320. GNUNET_free (op);
  321. }
  322. /**
  323. * Check validity of identity update message.
  324. *
  325. * @param cls closure
  326. * @param um message received
  327. * @return #GNUNET_OK if the message is well-formed
  328. */
  329. static int
  330. check_identity_update (void *cls,
  331. const struct UpdateMessage *um)
  332. {
  333. uint16_t size = ntohs (um->header.size);
  334. uint16_t name_len = ntohs (um->name_len);
  335. const char *str = (const char *) &um[1];
  336. if ((size != name_len + sizeof(struct UpdateMessage)) ||
  337. ((0 != name_len) && ('\0' != str[name_len - 1])))
  338. {
  339. GNUNET_break (0);
  340. return GNUNET_SYSERR;
  341. }
  342. return GNUNET_OK;
  343. }
  344. /**
  345. * Handle identity update message.
  346. *
  347. * @param cls closure
  348. * @param um message received
  349. */
  350. static void
  351. handle_identity_update (void *cls,
  352. const struct UpdateMessage *um)
  353. {
  354. struct GNUNET_IDENTITY_Handle *h = cls;
  355. uint16_t name_len = ntohs (um->name_len);
  356. const char *str = (0 == name_len) ? NULL : (const char *) &um[1];
  357. struct GNUNET_HashCode id;
  358. struct GNUNET_IDENTITY_Ego *ego;
  359. if (GNUNET_YES == ntohs (um->end_of_list))
  360. {
  361. /* end of initial list of data */
  362. if (NULL != h->cb)
  363. h->cb (h->cb_cls, NULL, NULL, NULL);
  364. return;
  365. }
  366. GNUNET_CRYPTO_hash (&um->private_key,
  367. sizeof (um->private_key),
  368. &id);
  369. ego = GNUNET_CONTAINER_multihashmap_get (h->egos,
  370. &id);
  371. if (NULL == ego)
  372. {
  373. /* ego was created */
  374. if (NULL == str)
  375. {
  376. /* deletion of unknown ego? not allowed */
  377. GNUNET_break (0);
  378. reschedule_connect (h);
  379. return;
  380. }
  381. ego = GNUNET_new (struct GNUNET_IDENTITY_Ego);
  382. ego->pub_initialized = GNUNET_NO;
  383. ego->pk = um->private_key;
  384. ego->name = GNUNET_strdup (str);
  385. ego->id = id;
  386. GNUNET_assert (GNUNET_YES ==
  387. GNUNET_CONTAINER_multihashmap_put (
  388. h->egos,
  389. &ego->id,
  390. ego,
  391. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
  392. }
  393. if (NULL == str)
  394. {
  395. /* ego was deleted */
  396. GNUNET_assert (GNUNET_YES ==
  397. GNUNET_CONTAINER_multihashmap_remove (h->egos,
  398. &ego->id,
  399. ego));
  400. }
  401. else
  402. {
  403. /* ego changed name */
  404. GNUNET_free (ego->name);
  405. ego->name = GNUNET_strdup (str);
  406. }
  407. /* inform application about change */
  408. if (NULL != h->cb)
  409. h->cb (h->cb_cls,
  410. ego,
  411. &ego->ctx,
  412. str);
  413. /* complete deletion */
  414. if (NULL == str)
  415. {
  416. GNUNET_free (ego->name);
  417. GNUNET_free (ego);
  418. }
  419. }
  420. /**
  421. * Function called when we receive a set default message from the
  422. * service.
  423. *
  424. * @param cls closure
  425. * @param sdm message received
  426. * @return #GNUNET_OK if the message is well-formed
  427. */
  428. static int
  429. check_identity_set_default (void *cls,
  430. const struct SetDefaultMessage *sdm)
  431. {
  432. uint16_t size = ntohs (sdm->header.size) - sizeof(*sdm);
  433. uint16_t name_len = ntohs (sdm->name_len);
  434. const char *str = (const char *) &sdm[1];
  435. if ((size != name_len) || ((0 != name_len) && ('\0' != str[name_len - 1])))
  436. {
  437. GNUNET_break (0);
  438. return GNUNET_SYSERR;
  439. }
  440. GNUNET_break (0 == ntohs (sdm->reserved));
  441. return GNUNET_OK;
  442. }
  443. /**
  444. * Type of a function to call when we receive a message
  445. * from the service.
  446. *
  447. * @param cls closure
  448. * @param sdm message received
  449. */
  450. static void
  451. handle_identity_set_default (void *cls,
  452. const struct SetDefaultMessage *sdm)
  453. {
  454. struct GNUNET_IDENTITY_Handle *h = cls;
  455. struct GNUNET_IDENTITY_Operation *op;
  456. struct GNUNET_HashCode id;
  457. struct GNUNET_IDENTITY_Ego *ego;
  458. GNUNET_CRYPTO_hash (&sdm->private_key,
  459. sizeof(sdm->private_key),
  460. &id);
  461. ego = GNUNET_CONTAINER_multihashmap_get (h->egos,
  462. &id);
  463. if (NULL == ego)
  464. {
  465. GNUNET_break (0);
  466. reschedule_connect (h);
  467. return;
  468. }
  469. op = h->op_head;
  470. if (NULL == op)
  471. {
  472. GNUNET_break (0);
  473. reschedule_connect (h);
  474. return;
  475. }
  476. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  477. "Received SET_DEFAULT message from identity service\n");
  478. GNUNET_CONTAINER_DLL_remove (h->op_head,
  479. h->op_tail,
  480. op);
  481. if (NULL != op->cb)
  482. op->cb (op->cls,
  483. ego,
  484. &ego->ctx,
  485. ego->name);
  486. GNUNET_free (op);
  487. }
  488. /**
  489. * Try again to connect to the identity service.
  490. *
  491. * @param cls handle to the identity service.
  492. */
  493. static void
  494. reconnect (void *cls)
  495. {
  496. struct GNUNET_IDENTITY_Handle *h = cls;
  497. struct GNUNET_MQ_MessageHandler handlers[] = {
  498. GNUNET_MQ_hd_var_size (identity_result_code,
  499. GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE,
  500. struct ResultCodeMessage,
  501. h),
  502. GNUNET_MQ_hd_var_size (identity_update,
  503. GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE,
  504. struct UpdateMessage,
  505. h),
  506. GNUNET_MQ_hd_var_size (identity_set_default,
  507. GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT,
  508. struct SetDefaultMessage,
  509. h),
  510. GNUNET_MQ_handler_end ()
  511. };
  512. struct GNUNET_MQ_Envelope *env;
  513. struct GNUNET_MessageHeader *msg;
  514. h->reconnect_task = NULL;
  515. LOG (GNUNET_ERROR_TYPE_DEBUG,
  516. "Connecting to identity service.\n");
  517. GNUNET_assert (NULL == h->mq);
  518. h->mq = GNUNET_CLIENT_connect (h->cfg,
  519. "identity",
  520. handlers,
  521. &mq_error_handler,
  522. h);
  523. if (NULL == h->mq)
  524. return;
  525. if (NULL != h->cb)
  526. {
  527. env = GNUNET_MQ_msg (msg,
  528. GNUNET_MESSAGE_TYPE_IDENTITY_START);
  529. GNUNET_MQ_send (h->mq,
  530. env);
  531. }
  532. }
  533. /**
  534. * Connect to the identity service.
  535. *
  536. * @param cfg the configuration to use
  537. * @param cb function to call on all identity events, can be NULL
  538. * @param cb_cls closure for @a cb
  539. * @return handle to use
  540. */
  541. struct GNUNET_IDENTITY_Handle *
  542. GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
  543. GNUNET_IDENTITY_Callback cb,
  544. void *cb_cls)
  545. {
  546. struct GNUNET_IDENTITY_Handle *h;
  547. h = GNUNET_new (struct GNUNET_IDENTITY_Handle);
  548. h->cfg = cfg;
  549. h->cb = cb;
  550. h->cb_cls = cb_cls;
  551. h->egos = GNUNET_CONTAINER_multihashmap_create (16,
  552. GNUNET_YES);
  553. reconnect (h);
  554. if (NULL == h->mq)
  555. {
  556. GNUNET_free (h);
  557. return NULL;
  558. }
  559. return h;
  560. }
  561. /**
  562. * Obtain the ECC key associated with a ego.
  563. *
  564. * @param ego the ego
  565. * @return associated ECC key, valid as long as the ego is valid
  566. */
  567. const struct GNUNET_IDENTITY_PrivateKey *
  568. GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego)
  569. {
  570. return &ego->pk;
  571. }
  572. /**
  573. * Get the identifier (public key) of an ego.
  574. *
  575. * @param ego identity handle with the private key
  576. * @param pk set to ego's public key
  577. */
  578. void
  579. GNUNET_IDENTITY_ego_get_public_key (struct GNUNET_IDENTITY_Ego *ego,
  580. struct GNUNET_IDENTITY_PublicKey *pk)
  581. {
  582. if (GNUNET_NO == ego->pub_initialized)
  583. {
  584. GNUNET_IDENTITY_key_get_public (&ego->pk, &ego->pub);
  585. ego->pub_initialized = GNUNET_YES;
  586. }
  587. *pk = ego->pub;
  588. }
  589. /**
  590. * Obtain the identity that is currently preferred/default
  591. * for a service.
  592. *
  593. * @param h identity service to query
  594. * @param service_name for which service is an identity wanted
  595. * @param cb function to call with the result (will only be called once)
  596. * @param cb_cls closure for @a cb
  597. * @return handle to abort the operation
  598. */
  599. struct GNUNET_IDENTITY_Operation *
  600. GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *h,
  601. const char *service_name,
  602. GNUNET_IDENTITY_Callback cb,
  603. void *cb_cls)
  604. {
  605. struct GNUNET_IDENTITY_Operation *op;
  606. struct GNUNET_MQ_Envelope *env;
  607. struct GetDefaultMessage *gdm;
  608. size_t slen;
  609. if (NULL == h->mq)
  610. return NULL;
  611. GNUNET_assert (NULL != h->cb);
  612. slen = strlen (service_name) + 1;
  613. if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct GetDefaultMessage))
  614. {
  615. GNUNET_break (0);
  616. return NULL;
  617. }
  618. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  619. op->h = h;
  620. op->cb = cb;
  621. op->cls = cb_cls;
  622. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  623. env =
  624. GNUNET_MQ_msg_extra (gdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT);
  625. gdm->name_len = htons (slen);
  626. gdm->reserved = htons (0);
  627. GNUNET_memcpy (&gdm[1], service_name, slen);
  628. GNUNET_MQ_send (h->mq, env);
  629. return op;
  630. }
  631. /**
  632. * Set the preferred/default identity for a service.
  633. *
  634. * @param h identity service to inform
  635. * @param service_name for which service is an identity set
  636. * @param ego new default identity to be set for this service
  637. * @param cont function to call once the operation finished
  638. * @param cont_cls closure for @a cont
  639. * @return handle to abort the operation
  640. */
  641. struct GNUNET_IDENTITY_Operation *
  642. GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *h,
  643. const char *service_name,
  644. struct GNUNET_IDENTITY_Ego *ego,
  645. GNUNET_IDENTITY_Continuation cont,
  646. void *cont_cls)
  647. {
  648. struct GNUNET_IDENTITY_Operation *op;
  649. struct GNUNET_MQ_Envelope *env;
  650. struct SetDefaultMessage *sdm;
  651. size_t slen;
  652. if (NULL == h->mq)
  653. return NULL;
  654. GNUNET_assert (NULL != h->cb);
  655. slen = strlen (service_name) + 1;
  656. if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct SetDefaultMessage))
  657. {
  658. GNUNET_break (0);
  659. return NULL;
  660. }
  661. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  662. op->h = h;
  663. op->cont = cont;
  664. op->cls = cont_cls;
  665. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  666. env =
  667. GNUNET_MQ_msg_extra (sdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT);
  668. sdm->name_len = htons (slen);
  669. sdm->reserved = htons (0);
  670. sdm->private_key = ego->pk;
  671. GNUNET_memcpy (&sdm[1], service_name, slen);
  672. GNUNET_MQ_send (h->mq, env);
  673. return op;
  674. }
  675. struct GNUNET_IDENTITY_Operation *
  676. GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *h,
  677. const char *name,
  678. const struct GNUNET_IDENTITY_PrivateKey *privkey,
  679. enum GNUNET_IDENTITY_KeyType ktype,
  680. GNUNET_IDENTITY_CreateContinuation cont,
  681. void *cont_cls)
  682. {
  683. struct GNUNET_IDENTITY_Operation *op;
  684. struct GNUNET_MQ_Envelope *env;
  685. struct CreateRequestMessage *crm;
  686. size_t slen;
  687. if (NULL == h->mq)
  688. return NULL;
  689. slen = strlen (name) + 1;
  690. if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct CreateRequestMessage))
  691. {
  692. GNUNET_break (0);
  693. return NULL;
  694. }
  695. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  696. op->h = h;
  697. op->create_cont = cont;
  698. op->cls = cont_cls;
  699. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  700. env = GNUNET_MQ_msg_extra (crm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_CREATE);
  701. crm->name_len = htons (slen);
  702. crm->reserved = htons (0);
  703. if (NULL == privkey)
  704. {
  705. GNUNET_assert (GNUNET_OK ==
  706. private_key_create (ktype, &crm->private_key));
  707. }
  708. else
  709. crm->private_key = *privkey;
  710. op->pk = crm->private_key;
  711. GNUNET_memcpy (&crm[1], name, slen);
  712. GNUNET_MQ_send (h->mq, env);
  713. return op;
  714. }
  715. /**
  716. * Renames an existing identity.
  717. *
  718. * @param h identity service to use
  719. * @param old_name old name
  720. * @param new_name desired new name
  721. * @param cb function to call with the result (will only be called once)
  722. * @param cb_cls closure for @a cb
  723. * @return handle to abort the operation
  724. */
  725. struct GNUNET_IDENTITY_Operation *
  726. GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *h,
  727. const char *old_name,
  728. const char *new_name,
  729. GNUNET_IDENTITY_Continuation cb,
  730. void *cb_cls)
  731. {
  732. struct GNUNET_IDENTITY_Operation *op;
  733. struct GNUNET_MQ_Envelope *env;
  734. struct RenameMessage *grm;
  735. size_t slen_old;
  736. size_t slen_new;
  737. char *dst;
  738. if (NULL == h->mq)
  739. return NULL;
  740. slen_old = strlen (old_name) + 1;
  741. slen_new = strlen (new_name) + 1;
  742. if ((slen_old >= GNUNET_MAX_MESSAGE_SIZE) ||
  743. (slen_new >= GNUNET_MAX_MESSAGE_SIZE) ||
  744. (slen_old + slen_new >=
  745. GNUNET_MAX_MESSAGE_SIZE - sizeof(struct RenameMessage)))
  746. {
  747. GNUNET_break (0);
  748. return NULL;
  749. }
  750. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  751. op->h = h;
  752. op->cont = cb;
  753. op->cls = cb_cls;
  754. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  755. env = GNUNET_MQ_msg_extra (grm,
  756. slen_old + slen_new,
  757. GNUNET_MESSAGE_TYPE_IDENTITY_RENAME);
  758. grm->old_name_len = htons (slen_old);
  759. grm->new_name_len = htons (slen_new);
  760. dst = (char *) &grm[1];
  761. GNUNET_memcpy (dst, old_name, slen_old);
  762. GNUNET_memcpy (&dst[slen_old], new_name, slen_new);
  763. GNUNET_MQ_send (h->mq, env);
  764. return op;
  765. }
  766. /**
  767. * Delete an existing identity.
  768. *
  769. * @param h identity service to use
  770. * @param name name of the identity to delete
  771. * @param cb function to call with the result (will only be called once)
  772. * @param cb_cls closure for @a cb
  773. * @return handle to abort the operation
  774. */
  775. struct GNUNET_IDENTITY_Operation *
  776. GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *h,
  777. const char *name,
  778. GNUNET_IDENTITY_Continuation cb,
  779. void *cb_cls)
  780. {
  781. struct GNUNET_IDENTITY_Operation *op;
  782. struct GNUNET_MQ_Envelope *env;
  783. struct DeleteMessage *gdm;
  784. size_t slen;
  785. if (NULL == h->mq)
  786. return NULL;
  787. slen = strlen (name) + 1;
  788. if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct DeleteMessage))
  789. {
  790. GNUNET_break (0);
  791. return NULL;
  792. }
  793. op = GNUNET_new (struct GNUNET_IDENTITY_Operation);
  794. op->h = h;
  795. op->cont = cb;
  796. op->cls = cb_cls;
  797. GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
  798. env = GNUNET_MQ_msg_extra (gdm, slen, GNUNET_MESSAGE_TYPE_IDENTITY_DELETE);
  799. gdm->name_len = htons (slen);
  800. gdm->reserved = htons (0);
  801. GNUNET_memcpy (&gdm[1], name, slen);
  802. GNUNET_MQ_send (h->mq, env);
  803. return op;
  804. }
  805. /**
  806. * Cancel an identity operation. Note that the operation MAY still
  807. * be executed; this merely cancels the continuation; if the request
  808. * was already transmitted, the service may still choose to complete
  809. * the operation.
  810. *
  811. * @param op operation to cancel
  812. */
  813. void
  814. GNUNET_IDENTITY_cancel (struct GNUNET_IDENTITY_Operation *op)
  815. {
  816. op->cont = NULL;
  817. op->cb = NULL;
  818. op->create_cont = NULL;
  819. memset (&op->pk,
  820. 0,
  821. sizeof (op->pk));
  822. }
  823. /**
  824. * Disconnect from identity service
  825. *
  826. * @param h handle to destroy
  827. */
  828. void
  829. GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h)
  830. {
  831. struct GNUNET_IDENTITY_Operation *op;
  832. GNUNET_assert (NULL != h);
  833. if (h->reconnect_task != NULL)
  834. {
  835. GNUNET_SCHEDULER_cancel (h->reconnect_task);
  836. h->reconnect_task = NULL;
  837. }
  838. if (NULL != h->egos)
  839. {
  840. GNUNET_CONTAINER_multihashmap_iterate (h->egos,
  841. &free_ego,
  842. h);
  843. GNUNET_CONTAINER_multihashmap_destroy (h->egos);
  844. h->egos = NULL;
  845. }
  846. while (NULL != (op = h->op_head))
  847. {
  848. GNUNET_break (NULL == op->cont);
  849. GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
  850. memset (&op->pk,
  851. 0,
  852. sizeof (op->pk));
  853. GNUNET_free (op);
  854. }
  855. if (NULL != h->mq)
  856. {
  857. GNUNET_MQ_destroy (h->mq);
  858. h->mq = NULL;
  859. }
  860. GNUNET_free (h);
  861. }
  862. ssize_t
  863. private_key_get_length (const struct GNUNET_IDENTITY_PrivateKey *key)
  864. {
  865. switch (ntohl (key->type))
  866. {
  867. case GNUNET_IDENTITY_TYPE_ECDSA:
  868. return sizeof (key->type) + sizeof (key->ecdsa_key);
  869. break;
  870. case GNUNET_IDENTITY_TYPE_EDDSA:
  871. return sizeof (key->type) + sizeof (key->eddsa_key);
  872. break;
  873. default:
  874. GNUNET_break (0);
  875. }
  876. return -1;
  877. }
  878. ssize_t
  879. GNUNET_IDENTITY_key_get_length (const struct GNUNET_IDENTITY_PublicKey *key)
  880. {
  881. switch (ntohl (key->type))
  882. {
  883. case GNUNET_IDENTITY_TYPE_ECDSA:
  884. return sizeof (key->type) + sizeof (key->ecdsa_key);
  885. break;
  886. case GNUNET_IDENTITY_TYPE_EDDSA:
  887. return sizeof (key->type) + sizeof (key->eddsa_key);
  888. break;
  889. default:
  890. GNUNET_break (0);
  891. }
  892. return -1;
  893. }
  894. ssize_t
  895. GNUNET_IDENTITY_read_key_from_buffer (struct GNUNET_IDENTITY_PublicKey *key,
  896. const void*buffer,
  897. size_t len)
  898. {
  899. if (len < sizeof (key->type))
  900. return -1;
  901. GNUNET_memcpy (&(key->type), buffer, sizeof (key->type));
  902. const ssize_t length = GNUNET_IDENTITY_key_get_length (key);
  903. if (len < length)
  904. return -1;
  905. if (length < 0)
  906. return -2;
  907. GNUNET_memcpy (&(key->ecdsa_key), buffer + sizeof (key->type), length
  908. - sizeof (key->type));
  909. return length;
  910. }
  911. ssize_t
  912. GNUNET_IDENTITY_write_key_to_buffer (const struct
  913. GNUNET_IDENTITY_PublicKey *key,
  914. void*buffer,
  915. size_t len)
  916. {
  917. const ssize_t length = GNUNET_IDENTITY_key_get_length (key);
  918. if (len < length)
  919. return -1;
  920. if (length < 0)
  921. return -2;
  922. GNUNET_memcpy (buffer, key, length);
  923. return length;
  924. }
  925. ssize_t
  926. GNUNET_IDENTITY_signature_get_length (const struct
  927. GNUNET_IDENTITY_Signature *sig)
  928. {
  929. switch (ntohl (sig->type))
  930. {
  931. case GNUNET_IDENTITY_TYPE_ECDSA:
  932. return sizeof (sig->type) + sizeof (sig->ecdsa_signature);
  933. break;
  934. case GNUNET_IDENTITY_TYPE_EDDSA:
  935. return sizeof (sig->type) + sizeof (sig->eddsa_signature);
  936. break;
  937. default:
  938. GNUNET_break (0);
  939. }
  940. return -1;
  941. }
  942. ssize_t
  943. GNUNET_IDENTITY_read_signature_from_buffer (struct
  944. GNUNET_IDENTITY_Signature *sig,
  945. const void*buffer,
  946. size_t len)
  947. {
  948. if (len < sizeof (sig->type))
  949. return -1;
  950. GNUNET_memcpy (&(sig->type), buffer, sizeof (sig->type));
  951. const ssize_t length = GNUNET_IDENTITY_signature_get_length (sig);
  952. if (len < length)
  953. return -1;
  954. if (length < 0)
  955. return -2;
  956. GNUNET_memcpy (&(sig->ecdsa_signature), buffer + sizeof (sig->type), length
  957. - sizeof (sig->type));
  958. return length;
  959. }
  960. ssize_t
  961. GNUNET_IDENTITY_write_signature_to_buffer (const struct
  962. GNUNET_IDENTITY_Signature *sig,
  963. void*buffer,
  964. size_t len)
  965. {
  966. const ssize_t length = GNUNET_IDENTITY_signature_get_length (sig);
  967. if (len < length)
  968. return -1;
  969. if (length < 0)
  970. return -2;
  971. GNUNET_memcpy (buffer, &(sig->type), sizeof (sig->type));
  972. GNUNET_memcpy (buffer + sizeof (sig->type), &(sig->ecdsa_signature), length
  973. - sizeof (sig->type));
  974. return length;
  975. }
  976. int
  977. GNUNET_IDENTITY_sign_ (const struct
  978. GNUNET_IDENTITY_PrivateKey *priv,
  979. const struct
  980. GNUNET_CRYPTO_EccSignaturePurpose *purpose,
  981. struct GNUNET_IDENTITY_Signature *sig)
  982. {
  983. sig->type = priv->type;
  984. switch (ntohl (priv->type))
  985. {
  986. case GNUNET_IDENTITY_TYPE_ECDSA:
  987. return GNUNET_CRYPTO_ecdsa_sign_ (&(priv->ecdsa_key), purpose,
  988. &(sig->ecdsa_signature));
  989. break;
  990. case GNUNET_IDENTITY_TYPE_EDDSA:
  991. return GNUNET_CRYPTO_eddsa_sign_ (&(priv->eddsa_key), purpose,
  992. &(sig->eddsa_signature));
  993. break;
  994. default:
  995. GNUNET_break (0);
  996. }
  997. return GNUNET_SYSERR;
  998. }
  999. int
  1000. GNUNET_IDENTITY_signature_verify_ (uint32_t purpose,
  1001. const struct
  1002. GNUNET_CRYPTO_EccSignaturePurpose *validate,
  1003. const struct GNUNET_IDENTITY_Signature *sig,
  1004. const struct GNUNET_IDENTITY_PublicKey *pub)
  1005. {
  1006. /* check type matching of 'sig' and 'pub' */
  1007. GNUNET_assert (ntohl (pub->type) == ntohl (sig->type));
  1008. switch (ntohl (pub->type))
  1009. {
  1010. case GNUNET_IDENTITY_TYPE_ECDSA:
  1011. return GNUNET_CRYPTO_ecdsa_verify_ (purpose, validate,
  1012. &(sig->ecdsa_signature),
  1013. &(pub->ecdsa_key));
  1014. break;
  1015. case GNUNET_IDENTITY_TYPE_EDDSA:
  1016. return GNUNET_CRYPTO_eddsa_verify_ (purpose, validate,
  1017. &(sig->eddsa_signature),
  1018. &(pub->eddsa_key));
  1019. break;
  1020. default:
  1021. GNUNET_break (0);
  1022. }
  1023. return GNUNET_SYSERR;
  1024. }
  1025. ssize_t
  1026. GNUNET_IDENTITY_encrypt (const void *block,
  1027. size_t size,
  1028. const struct GNUNET_IDENTITY_PublicKey *pub,
  1029. struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
  1030. void *result)
  1031. {
  1032. struct GNUNET_CRYPTO_EcdhePrivateKey pk;
  1033. GNUNET_CRYPTO_ecdhe_key_create (&pk);
  1034. struct GNUNET_HashCode hash;
  1035. switch (ntohl (pub->type))
  1036. {
  1037. case GNUNET_IDENTITY_TYPE_ECDSA:
  1038. if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_ecdsa (&pk, &(pub->ecdsa_key),
  1039. &hash))
  1040. return -1;
  1041. break;
  1042. case GNUNET_IDENTITY_TYPE_EDDSA:
  1043. if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_eddsa (&pk, &(pub->eddsa_key),
  1044. &hash))
  1045. return -1;
  1046. break;
  1047. default:
  1048. return -1;
  1049. }
  1050. GNUNET_CRYPTO_ecdhe_key_get_public (&pk, ecc);
  1051. GNUNET_CRYPTO_ecdhe_key_clear (&pk);
  1052. struct GNUNET_CRYPTO_SymmetricSessionKey key;
  1053. struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
  1054. GNUNET_CRYPTO_hash_to_aes_key (&hash, &key, &iv);
  1055. GNUNET_CRYPTO_zero_keys (&hash, sizeof(hash));
  1056. const ssize_t encrypted = GNUNET_CRYPTO_symmetric_encrypt (block, size, &key,
  1057. &iv, result);
  1058. GNUNET_CRYPTO_zero_keys (&key, sizeof(key));
  1059. GNUNET_CRYPTO_zero_keys (&iv, sizeof(iv));
  1060. return encrypted;
  1061. }
  1062. ssize_t
  1063. GNUNET_IDENTITY_decrypt (const void *block,
  1064. size_t size,
  1065. const struct GNUNET_IDENTITY_PrivateKey *priv,
  1066. const struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
  1067. void *result)
  1068. {
  1069. struct GNUNET_HashCode hash;
  1070. switch (ntohl (priv->type))
  1071. {
  1072. case GNUNET_IDENTITY_TYPE_ECDSA:
  1073. if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_ecdh (&(priv->ecdsa_key), ecc,
  1074. &hash))
  1075. return -1;
  1076. break;
  1077. case GNUNET_IDENTITY_TYPE_EDDSA:
  1078. if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_ecdh (&(priv->eddsa_key), ecc,
  1079. &hash))
  1080. return -1;
  1081. break;
  1082. default:
  1083. return -1;
  1084. }
  1085. struct GNUNET_CRYPTO_SymmetricSessionKey key;
  1086. struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
  1087. GNUNET_CRYPTO_hash_to_aes_key (&hash, &key, &iv);
  1088. GNUNET_CRYPTO_zero_keys (&hash, sizeof(hash));
  1089. const ssize_t decrypted = GNUNET_CRYPTO_symmetric_decrypt (block, size, &key,
  1090. &iv, result);
  1091. GNUNET_CRYPTO_zero_keys (&key, sizeof(key));
  1092. GNUNET_CRYPTO_zero_keys (&iv, sizeof(iv));
  1093. return decrypted;
  1094. }
  1095. char *
  1096. GNUNET_IDENTITY_public_key_to_string (const struct
  1097. GNUNET_IDENTITY_PublicKey *key)
  1098. {
  1099. size_t size = GNUNET_IDENTITY_key_get_length (key);
  1100. return GNUNET_STRINGS_data_to_string_alloc (key,
  1101. size);
  1102. }
  1103. char *
  1104. GNUNET_IDENTITY_private_key_to_string (const struct
  1105. GNUNET_IDENTITY_PrivateKey *key)
  1106. {
  1107. size_t size = private_key_get_length (key);
  1108. return GNUNET_STRINGS_data_to_string_alloc (key,
  1109. size);
  1110. }
  1111. enum GNUNET_GenericReturnValue
  1112. GNUNET_IDENTITY_public_key_from_string (const char *str,
  1113. struct GNUNET_IDENTITY_PublicKey *key)
  1114. {
  1115. enum GNUNET_GenericReturnValue ret;
  1116. enum GNUNET_IDENTITY_KeyType ktype;
  1117. ret = GNUNET_STRINGS_string_to_data (str,
  1118. strlen (str),
  1119. key,
  1120. sizeof (*key));
  1121. if (GNUNET_OK != ret)
  1122. return GNUNET_SYSERR;
  1123. ktype = ntohl (key->type);
  1124. return (GNUNET_IDENTITY_TYPE_ECDSA == ktype) ? GNUNET_OK : GNUNET_SYSERR; // FIXME other keys, cleaner way?
  1125. }
  1126. enum GNUNET_GenericReturnValue
  1127. GNUNET_IDENTITY_private_key_from_string (const char *str,
  1128. struct GNUNET_IDENTITY_PrivateKey *key)
  1129. {
  1130. enum GNUNET_GenericReturnValue ret;
  1131. enum GNUNET_IDENTITY_KeyType ktype;
  1132. ret = GNUNET_STRINGS_string_to_data (str,
  1133. strlen (str),
  1134. key,
  1135. sizeof (*key));
  1136. if (GNUNET_OK != ret)
  1137. return GNUNET_SYSERR;
  1138. ktype = ntohl (key->type);
  1139. return (GNUNET_IDENTITY_TYPE_ECDSA == ktype) ? GNUNET_OK : GNUNET_SYSERR; // FIXME other keys, cleaner way?
  1140. }
  1141. /* end of identity_api.c */