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