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