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.c1357
1 files changed, 0 insertions, 1357 deletions
diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c
deleted file mode 100644
index 471569cb3..000000000
--- a/src/identity/identity_api.c
+++ /dev/null
@@ -1,1357 +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
957static enum GNUNET_GenericReturnValue
958check_key_type (uint32_t type)
959{
960 switch (type)
961 {
962 case GNUNET_IDENTITY_TYPE_ECDSA:
963 case GNUNET_IDENTITY_TYPE_EDDSA:
964 return GNUNET_OK;
965 default:
966 return GNUNET_SYSERR;
967 }
968 return GNUNET_SYSERR;
969}
970
971
972static ssize_t
973private_key_get_length (const struct GNUNET_IDENTITY_PrivateKey *key)
974{
975 switch (ntohl (key->type))
976 {
977 case GNUNET_IDENTITY_TYPE_ECDSA:
978 return sizeof (key->type) + sizeof (key->ecdsa_key);
979 break;
980 case GNUNET_IDENTITY_TYPE_EDDSA:
981 return sizeof (key->type) + sizeof (key->eddsa_key);
982 break;
983 default:
984 GNUNET_break (0);
985 }
986 return -1;
987}
988
989
990ssize_t
991GNUNET_IDENTITY_key_get_length (const struct GNUNET_IDENTITY_PublicKey *key)
992{
993 switch (ntohl (key->type))
994 {
995 case GNUNET_IDENTITY_TYPE_ECDSA:
996 return sizeof (key->type) + sizeof (key->ecdsa_key);
997 case GNUNET_IDENTITY_TYPE_EDDSA:
998 return sizeof (key->type) + sizeof (key->eddsa_key);
999 default:
1000 GNUNET_break (0);
1001 }
1002 return -1;
1003}
1004
1005
1006ssize_t
1007GNUNET_IDENTITY_read_key_from_buffer (struct GNUNET_IDENTITY_PublicKey *key,
1008 const void *buffer,
1009 size_t len)
1010{
1011 if (len < sizeof (key->type))
1012 return -1;
1013 GNUNET_memcpy (&key->type,
1014 buffer,
1015 sizeof (key->type));
1016 ssize_t length = GNUNET_IDENTITY_key_get_length (key);
1017 if (len < length)
1018 return -1;
1019 if (length < 0)
1020 return -2;
1021 GNUNET_memcpy (&key->ecdsa_key,
1022 buffer + sizeof (key->type),
1023 length - sizeof (key->type));
1024 return length;
1025}
1026
1027
1028ssize_t
1029GNUNET_IDENTITY_write_key_to_buffer (const struct
1030 GNUNET_IDENTITY_PublicKey *key,
1031 void*buffer,
1032 size_t len)
1033{
1034 const ssize_t length = GNUNET_IDENTITY_key_get_length (key);
1035 if (len < length)
1036 return -1;
1037 if (length < 0)
1038 return -2;
1039 GNUNET_memcpy (buffer, &(key->type), sizeof (key->type));
1040 GNUNET_memcpy (buffer + sizeof (key->type), &(key->ecdsa_key), length
1041 - sizeof (key->type));
1042 return length;
1043}
1044
1045
1046ssize_t
1047GNUNET_IDENTITY_signature_get_length (const struct
1048 GNUNET_IDENTITY_Signature *sig)
1049{
1050 switch (ntohl (sig->type))
1051 {
1052 case GNUNET_IDENTITY_TYPE_ECDSA:
1053 return sizeof (sig->type) + sizeof (sig->ecdsa_signature);
1054 break;
1055 case GNUNET_IDENTITY_TYPE_EDDSA:
1056 return sizeof (sig->type) + sizeof (sig->eddsa_signature);
1057 break;
1058 default:
1059 GNUNET_break (0);
1060 }
1061 return -1;
1062}
1063
1064
1065ssize_t
1066GNUNET_IDENTITY_signature_get_raw_length_by_type (uint32_t type)
1067{
1068 switch (ntohl (type))
1069 {
1070 case GNUNET_IDENTITY_TYPE_ECDSA:
1071 return sizeof (struct GNUNET_CRYPTO_EcdsaSignature);
1072 break;
1073 case GNUNET_IDENTITY_TYPE_EDDSA:
1074 return sizeof (struct GNUNET_CRYPTO_EddsaSignature);
1075 break;
1076 default:
1077 GNUNET_break (0);
1078 }
1079 return -1;
1080}
1081
1082
1083
1084ssize_t
1085GNUNET_IDENTITY_read_signature_from_buffer (struct
1086 GNUNET_IDENTITY_Signature *sig,
1087 const void*buffer,
1088 size_t len)
1089{
1090 if (len < sizeof (sig->type))
1091 return -1;
1092 GNUNET_memcpy (&(sig->type), buffer, sizeof (sig->type));
1093 const ssize_t length = GNUNET_IDENTITY_signature_get_length (sig);
1094 if (len < length)
1095 return -1;
1096 if (length < 0)
1097 return -2;
1098 GNUNET_memcpy (&(sig->ecdsa_signature), buffer + sizeof (sig->type), length
1099 - sizeof (sig->type));
1100 return length;
1101}
1102
1103
1104ssize_t
1105GNUNET_IDENTITY_write_signature_to_buffer (const struct
1106 GNUNET_IDENTITY_Signature *sig,
1107 void*buffer,
1108 size_t len)
1109{
1110 const ssize_t length = GNUNET_IDENTITY_signature_get_length (sig);
1111 if (len < length)
1112 return -1;
1113 if (length < 0)
1114 return -2;
1115 GNUNET_memcpy (buffer, &(sig->type), sizeof (sig->type));
1116 GNUNET_memcpy (buffer + sizeof (sig->type), &(sig->ecdsa_signature), length
1117 - sizeof (sig->type));
1118 return length;
1119}
1120
1121enum GNUNET_GenericReturnValue
1122GNUNET_IDENTITY_sign_raw_ (const struct
1123 GNUNET_IDENTITY_PrivateKey *priv,
1124 const struct
1125 GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1126 unsigned char *sig)
1127{
1128 switch (ntohl (priv->type))
1129 {
1130 case GNUNET_IDENTITY_TYPE_ECDSA:
1131 return GNUNET_CRYPTO_ecdsa_sign_ (&(priv->ecdsa_key), purpose,
1132 (struct GNUNET_CRYPTO_EcdsaSignature*)sig);
1133 break;
1134 case GNUNET_IDENTITY_TYPE_EDDSA:
1135 return GNUNET_CRYPTO_eddsa_sign_ (&(priv->eddsa_key), purpose,
1136 (struct GNUNET_CRYPTO_EddsaSignature*)sig);
1137 break;
1138 default:
1139 GNUNET_break (0);
1140 }
1141
1142 return GNUNET_SYSERR;
1143}
1144
1145
1146
1147enum GNUNET_GenericReturnValue
1148GNUNET_IDENTITY_sign_ (const struct
1149 GNUNET_IDENTITY_PrivateKey *priv,
1150 const struct
1151 GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1152 struct GNUNET_IDENTITY_Signature *sig)
1153{
1154 sig->type = priv->type;
1155 switch (ntohl (priv->type))
1156 {
1157 case GNUNET_IDENTITY_TYPE_ECDSA:
1158 return GNUNET_CRYPTO_ecdsa_sign_ (&(priv->ecdsa_key), purpose,
1159 &(sig->ecdsa_signature));
1160 break;
1161 case GNUNET_IDENTITY_TYPE_EDDSA:
1162 return GNUNET_CRYPTO_eddsa_sign_ (&(priv->eddsa_key), purpose,
1163 &(sig->eddsa_signature));
1164 break;
1165 default:
1166 GNUNET_break (0);
1167 }
1168
1169 return GNUNET_SYSERR;
1170}
1171
1172
1173enum GNUNET_GenericReturnValue
1174GNUNET_IDENTITY_signature_verify_ (uint32_t purpose,
1175 const struct
1176 GNUNET_CRYPTO_EccSignaturePurpose *validate,
1177 const struct GNUNET_IDENTITY_Signature *sig,
1178 const struct GNUNET_IDENTITY_PublicKey *pub)
1179{
1180 /* check type matching of 'sig' and 'pub' */
1181 GNUNET_assert (ntohl (pub->type) == ntohl (sig->type));
1182 switch (ntohl (pub->type))
1183 {
1184 case GNUNET_IDENTITY_TYPE_ECDSA:
1185 return GNUNET_CRYPTO_ecdsa_verify_ (purpose, validate,
1186 &(sig->ecdsa_signature),
1187 &(pub->ecdsa_key));
1188 break;
1189 case GNUNET_IDENTITY_TYPE_EDDSA:
1190 return GNUNET_CRYPTO_eddsa_verify_ (purpose, validate,
1191 &(sig->eddsa_signature),
1192 &(pub->eddsa_key));
1193 break;
1194 default:
1195 GNUNET_break (0);
1196 }
1197
1198 return GNUNET_SYSERR;
1199}
1200
1201
1202enum GNUNET_GenericReturnValue
1203GNUNET_IDENTITY_signature_verify_raw_ (uint32_t purpose,
1204 const struct
1205 GNUNET_CRYPTO_EccSignaturePurpose *
1206 validate,
1207 const unsigned char *sig,
1208 const struct
1209 GNUNET_IDENTITY_PublicKey *pub)
1210{
1211 switch (ntohl (pub->type))
1212 {
1213 case GNUNET_IDENTITY_TYPE_ECDSA:
1214 return GNUNET_CRYPTO_ecdsa_verify_ (purpose, validate,
1215 (struct GNUNET_CRYPTO_EcdsaSignature*)sig,
1216 &(pub->ecdsa_key));
1217 break;
1218 case GNUNET_IDENTITY_TYPE_EDDSA:
1219 return GNUNET_CRYPTO_eddsa_verify_ (purpose, validate,
1220 (struct GNUNET_CRYPTO_EddsaSignature*)sig,
1221 &(pub->eddsa_key));
1222 break;
1223 default:
1224 GNUNET_break (0);
1225 }
1226
1227 return GNUNET_SYSERR;
1228}
1229
1230
1231
1232
1233ssize_t
1234GNUNET_IDENTITY_encrypt (const void *block,
1235 size_t size,
1236 const struct GNUNET_IDENTITY_PublicKey *pub,
1237 struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
1238 void *result)
1239{
1240 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
1241 GNUNET_CRYPTO_ecdhe_key_create (&pk);
1242 struct GNUNET_HashCode hash;
1243 switch (ntohl (pub->type))
1244 {
1245 case GNUNET_IDENTITY_TYPE_ECDSA:
1246 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_ecdsa (&pk, &(pub->ecdsa_key),
1247 &hash))
1248 return -1;
1249 break;
1250 case GNUNET_IDENTITY_TYPE_EDDSA:
1251 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_eddsa (&pk, &(pub->eddsa_key),
1252 &hash))
1253 return -1;
1254 break;
1255 default:
1256 return -1;
1257 }
1258 GNUNET_CRYPTO_ecdhe_key_get_public (&pk, ecc);
1259 GNUNET_CRYPTO_ecdhe_key_clear (&pk);
1260 struct GNUNET_CRYPTO_SymmetricSessionKey key;
1261 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1262 GNUNET_CRYPTO_hash_to_aes_key (&hash, &key, &iv);
1263 GNUNET_CRYPTO_zero_keys (&hash, sizeof(hash));
1264 const ssize_t encrypted = GNUNET_CRYPTO_symmetric_encrypt (block, size, &key,
1265 &iv, result);
1266 GNUNET_CRYPTO_zero_keys (&key, sizeof(key));
1267 GNUNET_CRYPTO_zero_keys (&iv, sizeof(iv));
1268 return encrypted;
1269}
1270
1271
1272ssize_t
1273GNUNET_IDENTITY_decrypt (const void *block,
1274 size_t size,
1275 const struct GNUNET_IDENTITY_PrivateKey *priv,
1276 const struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
1277 void *result)
1278{
1279 struct GNUNET_HashCode hash;
1280 switch (ntohl (priv->type))
1281 {
1282 case GNUNET_IDENTITY_TYPE_ECDSA:
1283 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_ecdh (&(priv->ecdsa_key), ecc,
1284 &hash))
1285 return -1;
1286 break;
1287 case GNUNET_IDENTITY_TYPE_EDDSA:
1288 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_ecdh (&(priv->eddsa_key), ecc,
1289 &hash))
1290 return -1;
1291 break;
1292 default:
1293 return -1;
1294 }
1295 struct GNUNET_CRYPTO_SymmetricSessionKey key;
1296 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1297 GNUNET_CRYPTO_hash_to_aes_key (&hash, &key, &iv);
1298 GNUNET_CRYPTO_zero_keys (&hash, sizeof(hash));
1299 const ssize_t decrypted = GNUNET_CRYPTO_symmetric_decrypt (block, size, &key,
1300 &iv, result);
1301 GNUNET_CRYPTO_zero_keys (&key, sizeof(key));
1302 GNUNET_CRYPTO_zero_keys (&iv, sizeof(iv));
1303 return decrypted;
1304}
1305
1306
1307char *
1308GNUNET_IDENTITY_public_key_to_string (const struct
1309 GNUNET_IDENTITY_PublicKey *key)
1310{
1311 size_t size = GNUNET_IDENTITY_key_get_length (key);
1312 return GNUNET_STRINGS_data_to_string_alloc (key,
1313 size);
1314}
1315
1316
1317char *
1318GNUNET_IDENTITY_private_key_to_string (const struct
1319 GNUNET_IDENTITY_PrivateKey *key)
1320{
1321 size_t size = private_key_get_length (key);
1322 return GNUNET_STRINGS_data_to_string_alloc (key,
1323 size);
1324}
1325
1326enum GNUNET_GenericReturnValue
1327GNUNET_IDENTITY_public_key_from_string (const char *str,
1328 struct GNUNET_IDENTITY_PublicKey *key)
1329{
1330 enum GNUNET_GenericReturnValue ret;
1331 ret = GNUNET_STRINGS_string_to_data (str,
1332 strlen (str),
1333 key,
1334 sizeof (*key));
1335 if (GNUNET_OK != ret)
1336 return GNUNET_SYSERR;
1337 return check_key_type (ntohl (key->type));
1338
1339}
1340
1341
1342enum GNUNET_GenericReturnValue
1343GNUNET_IDENTITY_private_key_from_string (const char *str,
1344 struct GNUNET_IDENTITY_PrivateKey *key)
1345{
1346 enum GNUNET_GenericReturnValue ret;
1347 ret = GNUNET_STRINGS_string_to_data (str,
1348 strlen (str),
1349 key,
1350 sizeof (*key));
1351 if (GNUNET_OK != ret)
1352 return GNUNET_SYSERR;
1353 return check_key_type (ntohl (key->type));
1354}
1355
1356
1357/* end of identity_api.c */