aboutsummaryrefslogtreecommitdiff
path: root/src/service/messenger/messenger_api_message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/messenger/messenger_api_message.c')
-rw-r--r--src/service/messenger/messenger_api_message.c1149
1 files changed, 1149 insertions, 0 deletions
diff --git a/src/service/messenger/messenger_api_message.c b/src/service/messenger/messenger_api_message.c
new file mode 100644
index 000000000..f77d171f6
--- /dev/null
+++ b/src/service/messenger/messenger_api_message.c
@@ -0,0 +1,1149 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 * @author Tobias Frisch
22 * @file src/messenger/messenger_api_message.c
23 * @brief messenger api: client and service implementation of GNUnet MESSENGER service
24 */
25
26#include "platform.h"
27#include "messenger_api_message.h"
28
29struct GNUNET_MESSENGER_MessageSignature
30{
31 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
32 struct GNUNET_HashCode hash;
33};
34
35struct GNUNET_MESSENGER_ShortMessage
36{
37 enum GNUNET_MESSENGER_MessageKind kind;
38 struct GNUNET_MESSENGER_MessageBody body;
39};
40
41struct GNUNET_MESSENGER_Message*
42create_message (enum GNUNET_MESSENGER_MessageKind kind)
43{
44 struct GNUNET_MESSENGER_Message *message = GNUNET_new (struct
45 GNUNET_MESSENGER_Message);
46
47 message->header.kind = kind;
48
49 switch (message->header.kind)
50 {
51 case GNUNET_MESSENGER_KIND_NAME:
52 message->body.name.name = NULL;
53 break;
54 case GNUNET_MESSENGER_KIND_TEXT:
55 message->body.text.text = NULL;
56 break;
57 case GNUNET_MESSENGER_KIND_FILE:
58 message->body.file.uri = NULL;
59 break;
60 case GNUNET_MESSENGER_KIND_PRIVATE:
61 message->body.privacy.length = 0;
62 message->body.privacy.data = NULL;
63 break;
64 default:
65 break;
66 }
67
68 return message;
69}
70
71
72struct GNUNET_MESSENGER_Message*
73copy_message (const struct GNUNET_MESSENGER_Message *message)
74{
75 GNUNET_assert (message);
76
77 struct GNUNET_MESSENGER_Message *copy = GNUNET_new (struct
78 GNUNET_MESSENGER_Message);
79
80 GNUNET_memcpy (copy, message, sizeof(struct GNUNET_MESSENGER_Message));
81
82 switch (message->header.kind)
83 {
84 case GNUNET_MESSENGER_KIND_NAME:
85 copy->body.name.name = GNUNET_strdup (message->body.name.name);
86 break;
87 case GNUNET_MESSENGER_KIND_TEXT:
88 copy->body.text.text = GNUNET_strdup (message->body.text.text);
89 break;
90 case GNUNET_MESSENGER_KIND_FILE:
91 copy->body.file.uri = GNUNET_strdup (message->body.file.uri);
92 break;
93 case GNUNET_MESSENGER_KIND_PRIVATE:
94 copy->body.privacy.data = copy->body.privacy.length ? GNUNET_malloc (
95 copy->body.privacy.length) : NULL;
96
97 if (copy->body.privacy.data)
98 {
99 GNUNET_memcpy (copy->body.privacy.data, message->body.privacy.data,
100 copy->body.privacy.length);
101 }
102
103 break;
104 default:
105 break;
106 }
107
108 return copy;
109}
110
111
112static void
113destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind,
114 struct GNUNET_MESSENGER_MessageBody *body)
115{
116 switch (kind)
117 {
118 case GNUNET_MESSENGER_KIND_NAME:
119 GNUNET_free (body->name.name);
120 break;
121 case GNUNET_MESSENGER_KIND_TEXT:
122 GNUNET_free (body->text.text);
123 break;
124 case GNUNET_MESSENGER_KIND_FILE:
125 GNUNET_free (body->file.uri);
126 break;
127 case GNUNET_MESSENGER_KIND_PRIVATE:
128 GNUNET_free (body->privacy.data);
129 break;
130 default:
131 break;
132 }
133}
134
135
136void
137cleanup_message (struct GNUNET_MESSENGER_Message *message)
138{
139 GNUNET_assert (message);
140
141 destroy_message_body (message->header.kind, &(message->body));
142}
143
144
145void
146destroy_message (struct GNUNET_MESSENGER_Message *message)
147{
148 GNUNET_assert (message);
149
150 destroy_message_body (message->header.kind, &(message->body));
151
152 GNUNET_free (message);
153}
154
155
156int
157is_message_session_bound (const struct GNUNET_MESSENGER_Message *message)
158{
159 GNUNET_assert (message);
160
161 if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) ||
162 (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) ||
163 (GNUNET_MESSENGER_KIND_NAME == message->header.kind) ||
164 (GNUNET_MESSENGER_KIND_KEY == message->header.kind) ||
165 (GNUNET_MESSENGER_KIND_ID == message->header.kind))
166 return GNUNET_YES;
167 else
168 return GNUNET_NO;
169}
170
171
172static void
173fold_short_message (const struct GNUNET_MESSENGER_Message *message,
174 struct GNUNET_MESSENGER_ShortMessage *shortened)
175{
176 shortened->kind = message->header.kind;
177
178 GNUNET_memcpy (&(shortened->body), &(message->body), sizeof(struct
179 GNUNET_MESSENGER_MessageBody));
180}
181
182
183static void
184unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened,
185 struct GNUNET_MESSENGER_Message *message)
186{
187 destroy_message_body (message->header.kind, &(message->body));
188
189 message->header.kind = shortened->kind;
190
191 GNUNET_memcpy (&(message->body), &(shortened->body), sizeof(struct
192 GNUNET_MESSENGER_MessageBody));
193}
194
195
196#define member_size(type, member) sizeof(((type*) NULL)->member)
197
198static uint16_t
199get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
200{
201 uint16_t length = 0;
202
203 switch (kind)
204 {
205 case GNUNET_MESSENGER_KIND_INFO:
206 length += member_size (struct GNUNET_MESSENGER_Message,
207 body.info.messenger_version);
208 break;
209 case GNUNET_MESSENGER_KIND_PEER:
210 length += member_size (struct GNUNET_MESSENGER_Message, body.peer.peer);
211 break;
212 case GNUNET_MESSENGER_KIND_ID:
213 length += member_size (struct GNUNET_MESSENGER_Message, body.id.id);
214 break;
215 case GNUNET_MESSENGER_KIND_MISS:
216 length += member_size (struct GNUNET_MESSENGER_Message, body.miss.peer);
217 break;
218 case GNUNET_MESSENGER_KIND_MERGE:
219 length += member_size (struct GNUNET_MESSENGER_Message,
220 body.merge.previous);
221 break;
222 case GNUNET_MESSENGER_KIND_REQUEST:
223 length += member_size (struct GNUNET_MESSENGER_Message, body.request.hash);
224 break;
225 case GNUNET_MESSENGER_KIND_INVITE:
226 length += member_size (struct GNUNET_MESSENGER_Message, body.invite.door);
227 length += member_size (struct GNUNET_MESSENGER_Message, body.invite.key);
228 break;
229 case GNUNET_MESSENGER_KIND_TEXT:
230 break;
231 case GNUNET_MESSENGER_KIND_FILE:
232 length += member_size (struct GNUNET_MESSENGER_Message, body.file.key);
233 length += member_size (struct GNUNET_MESSENGER_Message, body.file.hash);
234 length += member_size (struct GNUNET_MESSENGER_Message, body.file.name);
235 break;
236 case GNUNET_MESSENGER_KIND_PRIVATE:
237 length += member_size (struct GNUNET_MESSENGER_Message, body.privacy.key);
238 break;
239 case GNUNET_MESSENGER_KIND_DELETE:
240 length += member_size (struct GNUNET_MESSENGER_Message, body.deletion.hash);
241 length += member_size (struct GNUNET_MESSENGER_Message,
242 body.deletion.delay);
243 break;
244 default:
245 break;
246 }
247
248 return length;
249}
250
251
252typedef uint32_t kind_t;
253
254uint16_t
255get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind,
256 int include_header)
257{
258 uint16_t length = 0;
259
260 if (GNUNET_YES == include_header)
261 {
262 length += member_size (struct GNUNET_MESSENGER_Message, header.timestamp);
263 length += member_size (struct GNUNET_MESSENGER_Message, header.sender_id);
264 length += member_size (struct GNUNET_MESSENGER_Message, header.previous);
265 }
266
267 length += sizeof(kind_t);
268
269 return length + get_message_body_kind_size (kind);
270}
271
272
273static uint16_t
274get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind,
275 const struct GNUNET_MESSENGER_MessageBody *body)
276{
277 uint16_t length = 0;
278
279 switch (kind)
280 {
281 case GNUNET_MESSENGER_KIND_JOIN:
282 length += GNUNET_CRYPTO_public_key_get_length (&(body->join.key));
283 break;
284 case GNUNET_MESSENGER_KIND_NAME:
285 length += (body->name.name ? strlen (body->name.name) : 0);
286 break;
287 case GNUNET_MESSENGER_KIND_KEY:
288 length += GNUNET_CRYPTO_public_key_get_length (&(body->key.key));
289 break;
290 case GNUNET_MESSENGER_KIND_TEXT:
291 length += strlen (body->text.text);
292 break;
293 case GNUNET_MESSENGER_KIND_FILE:
294 length += strlen (body->file.uri);
295 break;
296 case GNUNET_MESSENGER_KIND_PRIVATE:
297 length += body->privacy.length;
298 break;
299 default:
300 break;
301 }
302
303 return length;
304}
305
306
307uint16_t
308get_message_size (const struct GNUNET_MESSENGER_Message *message,
309 int include_header)
310{
311 GNUNET_assert (message);
312
313 uint16_t length = 0;
314
315 if (GNUNET_YES == include_header)
316 length += GNUNET_CRYPTO_signature_get_length (
317 &(message->header.signature));
318
319 length += get_message_kind_size (message->header.kind, include_header);
320 length += get_message_body_size (message->header.kind, &(message->body));
321
322 return length;
323}
324
325
326static uint16_t
327get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message,
328 int include_body)
329{
330 const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t);
331
332 if (message)
333 return minimum_size + get_message_body_kind_size (message->kind)
334 + (include_body == GNUNET_YES? get_message_body_size (message->kind,
335 &(message->body))
336 : 0);
337 else
338 return minimum_size;
339}
340
341
342static uint16_t
343calc_usual_padding ()
344{
345 uint16_t padding = 0;
346 uint16_t kind_size;
347
348 for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++)
349 {
350 kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i,
351 GNUNET_YES);
352
353 if (kind_size > padding)
354 padding = kind_size;
355 }
356
357 return padding + GNUNET_MESSENGER_PADDING_MIN;
358}
359
360
361#define max(x, y) (x > y? x : y)
362
363static uint16_t
364calc_padded_length (uint16_t length)
365{
366 static uint16_t usual_padding = 0;
367
368 if (! usual_padding)
369 usual_padding = calc_usual_padding ();
370
371 const uint16_t padded_length = max (
372 length + GNUNET_MESSENGER_PADDING_MIN,
373 usual_padding
374 );
375
376 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
377 return GNUNET_MESSENGER_PADDING_LEVEL0;
378
379 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1)
380 return GNUNET_MESSENGER_PADDING_LEVEL1;
381
382 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2)
383 return GNUNET_MESSENGER_PADDING_LEVEL2;
384
385 return GNUNET_MESSENGER_MAX_MESSAGE_SIZE;
386
387}
388
389
390#define min(x, y) (x < y? x : y)
391
392#define encode_step_ext(dst, offset, src, size) do { \
393 GNUNET_memcpy (dst + offset, src, size); \
394 offset += size; \
395} while (0)
396
397#define encode_step(dst, offset, src) do { \
398 encode_step_ext (dst, offset, src, sizeof(*src)); \
399} while (0)
400
401#define encode_step_key(dst, offset, src, length) do { \
402 ssize_t result = GNUNET_CRYPTO_write_public_key_to_buffer ( \
403 src, dst + offset, length - offset \
404 ); \
405 if (result < 0) \
406 GNUNET_break (0); \
407 else \
408 offset += result; \
409} while (0)
410
411#define encode_step_signature(dst, offset, src, length) do { \
412 ssize_t result = GNUNET_CRYPTO_write_signature_to_buffer ( \
413 src, dst + offset, length - offset \
414 ); \
415 if (result < 0) \
416 GNUNET_break (0); \
417 else \
418 offset += result; \
419} while (0)
420
421static void
422encode_message_body (enum GNUNET_MESSENGER_MessageKind kind,
423 const struct GNUNET_MESSENGER_MessageBody *body,
424 uint16_t length,
425 char *buffer,
426 uint16_t offset)
427{
428 uint32_t version;
429 switch (kind)
430 {
431 case GNUNET_MESSENGER_KIND_INFO:
432 version = GNUNET_htobe32 (body->info.messenger_version);
433
434 encode_step (buffer, offset, &version);
435 break;
436 case GNUNET_MESSENGER_KIND_JOIN:
437 encode_step_key (buffer, offset, &(body->join.key), length);
438 break;
439 case GNUNET_MESSENGER_KIND_NAME:
440 if (body->name.name)
441 encode_step_ext (buffer, offset, body->name.name, min (length - offset,
442 strlen (
443 body->name.name)));
444 break;
445 case GNUNET_MESSENGER_KIND_KEY:
446 encode_step_key (buffer, offset, &(body->key.key), length);
447 break;
448 case GNUNET_MESSENGER_KIND_PEER:
449 encode_step (buffer, offset, &(body->peer.peer));
450 break;
451 case GNUNET_MESSENGER_KIND_ID:
452 encode_step (buffer, offset, &(body->id.id));
453 break;
454 case GNUNET_MESSENGER_KIND_MISS:
455 encode_step (buffer, offset, &(body->miss.peer));
456 break;
457 case GNUNET_MESSENGER_KIND_MERGE:
458 encode_step (buffer, offset, &(body->merge.previous));
459 break;
460 case GNUNET_MESSENGER_KIND_REQUEST:
461 encode_step (buffer, offset, &(body->request.hash));
462 break;
463 case GNUNET_MESSENGER_KIND_INVITE:
464 encode_step (buffer, offset, &(body->invite.door));
465 encode_step (buffer, offset, &(body->invite.key));
466 break;
467 case GNUNET_MESSENGER_KIND_TEXT:
468 encode_step_ext (buffer, offset, body->text.text, min (length - offset,
469 strlen (
470 body->text.text)));
471 break;
472 case GNUNET_MESSENGER_KIND_FILE:
473 encode_step (buffer, offset, &(body->file.key));
474 encode_step (buffer, offset, &(body->file.hash));
475 encode_step_ext (buffer, offset, body->file.name, sizeof(body->file.name));
476 encode_step_ext (buffer, offset, body->file.uri, min (length - offset,
477 strlen (
478 body->file.uri)));
479 break;
480 case GNUNET_MESSENGER_KIND_PRIVATE:
481 encode_step (buffer, offset, &(body->privacy.key));
482 encode_step_ext (buffer, offset, body->privacy.data, min (length - offset,
483 body->privacy.
484 length));
485 break;
486 case GNUNET_MESSENGER_KIND_DELETE:
487 encode_step (buffer, offset, &(body->deletion.hash));
488 encode_step (buffer, offset, &(body->deletion.delay));
489 break;
490 default:
491 break;
492 }
493
494 if (offset >= length)
495 return;
496
497 const uint16_t padding = length - offset;
498 const uint16_t used_padding = sizeof(padding) + sizeof(char);
499
500 GNUNET_assert (padding >= used_padding);
501
502 buffer[offset++] = '\0';
503
504 if (padding > used_padding)
505 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset,
506 padding - used_padding);
507
508 GNUNET_memcpy (buffer + length - sizeof(padding), &padding, sizeof(padding));
509}
510
511
512void
513encode_message (const struct GNUNET_MESSENGER_Message *message,
514 uint16_t length,
515 char *buffer,
516 int include_header)
517{
518 GNUNET_assert ((message) && (buffer));
519
520 uint16_t offset = 0;
521
522 if (GNUNET_YES == include_header)
523 encode_step_signature (buffer, offset, &(message->header.signature),
524 length);
525
526 const kind_t kind = GNUNET_htobe32 ((kind_t) message->header.kind);
527
528 if (GNUNET_YES == include_header)
529 {
530 encode_step (buffer, offset, &(message->header.timestamp));
531 encode_step (buffer, offset, &(message->header.sender_id));
532 encode_step (buffer, offset, &(message->header.previous));
533 }
534
535 encode_step (buffer, offset, &kind);
536
537 encode_message_body (message->header.kind, &(message->body), length, buffer,
538 offset);
539}
540
541
542static void
543encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message,
544 uint16_t length,
545 char *buffer)
546{
547 struct GNUNET_HashCode hash;
548 uint16_t offset = sizeof(hash);
549
550 const kind_t kind = GNUNET_htobe32 ((kind_t) message->kind);
551
552 encode_step (buffer, offset, &kind);
553
554 encode_message_body (message->kind, &(message->body), length, buffer, offset);
555
556 GNUNET_CRYPTO_hash (
557 buffer + sizeof(hash),
558 length - sizeof(hash),
559 &hash
560 );
561
562 GNUNET_memcpy (buffer, &hash, sizeof(hash));
563}
564
565
566#define decode_step_ext(src, offset, dst, size) do { \
567 GNUNET_memcpy (dst, src + offset, size); \
568 offset += size; \
569} while (0)
570
571#define decode_step(src, offset, dst) do { \
572 decode_step_ext (src, offset, dst, sizeof(*dst)); \
573} while (0)
574
575#define decode_step_malloc(src, offset, dst, size, zero) do { \
576 dst = GNUNET_malloc (size + zero); \
577 if (zero) dst[size] = 0; \
578 decode_step_ext (src, offset, dst, size); \
579} while (0)
580
581#define decode_step_key(src, offset, dst, length) do { \
582 enum GNUNET_GenericReturnValue result; \
583 size_t read; \
584 result = GNUNET_CRYPTO_read_public_key_from_buffer ( \
585 src + offset, length - offset, dst, &read \
586 ); \
587 if (GNUNET_SYSERR == result) \
588 GNUNET_break (0); \
589 else \
590 offset += read; \
591} while (0)
592
593static uint16_t
594decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind,
595 struct GNUNET_MESSENGER_MessageBody *body,
596 uint16_t length,
597 const char *buffer,
598 uint16_t offset)
599{
600 uint16_t padding = 0;
601
602 GNUNET_memcpy (&padding, buffer + length - sizeof(padding), sizeof(padding));
603
604 if (padding > length - offset)
605 padding = 0;
606
607 const uint16_t end_zero = length - padding;
608
609 if ((padding) && (buffer[end_zero] != '\0'))
610 padding = 0;
611
612 length -= padding;
613
614 uint32_t version;
615 switch (*kind)
616 {
617 case GNUNET_MESSENGER_KIND_INFO: {
618 decode_step (buffer, offset, &version);
619
620 body->info.messenger_version = GNUNET_be32toh (version);
621 break;
622 } case GNUNET_MESSENGER_KIND_JOIN: {
623 decode_step_key (buffer, offset, &(body->join.key), length);
624 break;
625 } case GNUNET_MESSENGER_KIND_NAME:
626 if (length - offset > 0)
627 decode_step_malloc (buffer, offset, body->name.name, length - offset, 1);
628 else
629 body->name.name = NULL;
630 break;
631 case GNUNET_MESSENGER_KIND_KEY:
632 decode_step_key (buffer, offset, &(body->key.key), length);
633 break;
634 case GNUNET_MESSENGER_KIND_PEER:
635 decode_step (buffer, offset, &(body->peer.peer));
636 break;
637 case GNUNET_MESSENGER_KIND_ID:
638 decode_step (buffer, offset, &(body->id.id));
639 break;
640 case GNUNET_MESSENGER_KIND_MISS:
641 decode_step (buffer, offset, &(body->miss.peer));
642 break;
643 case GNUNET_MESSENGER_KIND_MERGE:
644 decode_step (buffer, offset, &(body->merge.previous));
645 break;
646 case GNUNET_MESSENGER_KIND_REQUEST:
647 decode_step (buffer, offset, &(body->request.hash));
648 break;
649 case GNUNET_MESSENGER_KIND_INVITE:
650 decode_step (buffer, offset, &(body->invite.door));
651 decode_step (buffer, offset, &(body->invite.key));
652 break;
653 case GNUNET_MESSENGER_KIND_TEXT:
654 decode_step_malloc (buffer, offset, body->text.text, length - offset, 1);
655 break;
656 case GNUNET_MESSENGER_KIND_FILE:
657 decode_step (buffer, offset, &(body->file.key));
658 decode_step (buffer, offset, &(body->file.hash));
659 decode_step_ext (buffer, offset, body->file.name, sizeof(body->file.name));
660 decode_step_malloc (buffer, offset, body->file.uri, length - offset, 1);
661 break;
662 case GNUNET_MESSENGER_KIND_PRIVATE:
663 decode_step (buffer, offset, &(body->privacy.key));
664
665 body->privacy.length = (length - offset);
666 decode_step_malloc (buffer, offset, body->privacy.data, length - offset, 0);
667 break;
668 case GNUNET_MESSENGER_KIND_DELETE:
669 decode_step (buffer, offset, &(body->deletion.hash));
670 decode_step (buffer, offset, &(body->deletion.delay));
671 break;
672 default:
673 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
674 break;
675 }
676
677 return padding;
678}
679
680
681int
682decode_message (struct GNUNET_MESSENGER_Message *message,
683 uint16_t length,
684 const char *buffer,
685 int include_header,
686 uint16_t *padding)
687{
688 GNUNET_assert (
689 (message) &&
690 (buffer) &&
691 (length >= get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN,
692 include_header))
693 );
694
695 uint16_t offset = 0;
696
697 if (GNUNET_YES == include_header)
698 {
699 ssize_t result = GNUNET_CRYPTO_read_signature_from_buffer (
700 &(message->header.signature), buffer, length - offset
701 );
702
703 if (result < 0)
704 return GNUNET_NO;
705 else
706 offset += result;
707 }
708
709 const uint16_t count = length - offset;
710
711 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN,
712 include_header))
713 return GNUNET_NO;
714
715 kind_t kind;
716
717 if (GNUNET_YES == include_header)
718 {
719 decode_step (buffer, offset, &(message->header.timestamp));
720 decode_step (buffer, offset, &(message->header.sender_id));
721 decode_step (buffer, offset, &(message->header.previous));
722 }
723
724 decode_step (buffer, offset, &kind);
725
726 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh (
727 kind);
728
729 if (count < get_message_kind_size (message->header.kind, include_header))
730 return GNUNET_NO;
731
732 const uint16_t result = decode_message_body (&(message->header.kind),
733 &(message->body), length, buffer,
734 offset);
735
736 if (padding)
737 *padding = result;
738
739 return GNUNET_YES;
740}
741
742
743static int
744decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message,
745 uint16_t length,
746 const char *buffer)
747{
748 struct GNUNET_HashCode expected, hash;
749 uint16_t offset = sizeof(hash);
750
751 if (length < get_short_message_size (NULL, GNUNET_NO))
752 return GNUNET_NO;
753
754 GNUNET_memcpy (&hash, buffer, sizeof(hash));
755
756 GNUNET_CRYPTO_hash (
757 buffer + sizeof(hash),
758 length - sizeof(hash),
759 &expected
760 );
761
762 if (0 != GNUNET_CRYPTO_hash_cmp (&hash, &expected))
763 return GNUNET_NO;
764
765 kind_t kind;
766
767 decode_step (buffer, offset, &kind);
768
769 message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh (kind);
770
771 if (length < get_short_message_size (message, GNUNET_NO))
772 return GNUNET_NO;
773
774 decode_message_body (&(message->kind), &(message->body), length, buffer,
775 offset);
776
777 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
778 return GNUNET_NO;
779
780 return GNUNET_YES;
781}
782
783
784void
785hash_message (const struct GNUNET_MESSENGER_Message *message,
786 uint16_t length,
787 const char *buffer,
788 struct GNUNET_HashCode *hash)
789{
790 GNUNET_assert ((message) && (buffer) && (hash));
791
792 const ssize_t offset = GNUNET_CRYPTO_signature_get_length (
793 &(message->header.signature)
794 );
795
796 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
797}
798
799
800void
801sign_message (struct GNUNET_MESSENGER_Message *message,
802 uint16_t length,
803 char *buffer,
804 const struct GNUNET_HashCode *hash,
805 const struct GNUNET_CRYPTO_PrivateKey *key)
806{
807 GNUNET_assert ((message) && (buffer) && (hash) && (key));
808
809 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sign message by member: %s\n",
810 GNUNET_h2s (hash));
811
812 struct GNUNET_MESSENGER_MessageSignature signature;
813
814 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
815 signature.purpose.size = htonl (sizeof(signature));
816
817 GNUNET_memcpy (&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
818 GNUNET_CRYPTO_sign (key, &signature, &(message->header.signature));
819
820 message->header.signature.type = key->type;
821
822 uint16_t offset = 0;
823 encode_step_signature (buffer, offset, &(message->header.signature), length);
824}
825
826
827void
828sign_message_by_peer (struct GNUNET_MESSENGER_Message *message,
829 uint16_t length,
830 char *buffer,
831 const struct GNUNET_HashCode *hash,
832 const struct GNUNET_CONFIGURATION_Handle *cfg)
833{
834 GNUNET_assert ((message) && (buffer) && (hash) && (cfg));
835
836 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sign message by peer: %s\n",
837 GNUNET_h2s (hash));
838
839 struct GNUNET_MESSENGER_MessageSignature signature;
840
841 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
842 signature.purpose.size = htonl (sizeof(signature));
843
844 GNUNET_memcpy (&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
845 GNUNET_CRYPTO_sign_by_peer_identity (cfg, &signature.purpose,
846 &(message->header.signature.
847 eddsa_signature));
848
849 message->header.signature.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
850
851 uint16_t offset = 0;
852 encode_step_signature (buffer, offset, &(message->header.signature), length);
853}
854
855
856int
857verify_message (const struct GNUNET_MESSENGER_Message *message,
858 const struct GNUNET_HashCode *hash,
859 const struct GNUNET_CRYPTO_PublicKey *key)
860{
861 GNUNET_assert ((message) && (hash) && (key));
862
863 if (key->type != message->header.signature.type)
864 return GNUNET_SYSERR;
865
866 struct GNUNET_MESSENGER_MessageSignature signature;
867
868 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
869 signature.purpose.size = htonl (sizeof(signature));
870
871 GNUNET_memcpy (&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
872
873 return GNUNET_CRYPTO_signature_verify (
874 GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
875 &(message->header.signature), key);
876}
877
878
879int
880verify_message_by_peer (const struct GNUNET_MESSENGER_Message *message,
881 const struct GNUNET_HashCode *hash,
882 const struct GNUNET_PeerIdentity *identity)
883{
884 GNUNET_assert ((message) && (hash) && (identity));
885
886 if (ntohl (GNUNET_PUBLIC_KEY_TYPE_EDDSA) != message->header.signature.type)
887 return GNUNET_SYSERR;
888
889 struct GNUNET_MESSENGER_MessageSignature signature;
890
891 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
892 signature.purpose.size = htonl (sizeof(signature));
893
894 GNUNET_memcpy (&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
895
896 return GNUNET_CRYPTO_verify_peer_identity (
897 GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature.purpose,
898 &(message->header.signature.
899 eddsa_signature), identity);
900}
901
902
903int
904encrypt_message (struct GNUNET_MESSENGER_Message *message,
905 const struct GNUNET_CRYPTO_PublicKey *key)
906{
907 GNUNET_assert ((message) && (key));
908
909 if (GNUNET_YES == is_service_message (message))
910 return GNUNET_NO;
911
912 struct GNUNET_MESSENGER_ShortMessage shortened;
913
914 fold_short_message (message, &shortened);
915
916 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
917 const uint16_t padded_length = calc_padded_length (
918 length + GNUNET_CRYPTO_ENCRYPT_OVERHEAD_BYTES
919 );
920
921 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
922 message->body.privacy.data = GNUNET_malloc (padded_length);
923 message->body.privacy.length = padded_length;
924
925 const uint16_t encoded_length = (
926 padded_length - GNUNET_CRYPTO_ENCRYPT_OVERHEAD_BYTES
927 );
928
929 encode_short_message (&shortened, encoded_length, message->body.privacy.data);
930
931 if (GNUNET_OK != GNUNET_CRYPTO_encrypt (message->body.privacy.data,
932 encoded_length,
933 key,
934 message->body.privacy.data,
935 padded_length))
936 {
937 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
938
939 unfold_short_message (&shortened, message);
940 return GNUNET_NO;
941 }
942
943 destroy_message_body (shortened.kind, &(shortened.body));
944 return GNUNET_YES;
945}
946
947
948int
949decrypt_message (struct GNUNET_MESSENGER_Message *message,
950 const struct GNUNET_CRYPTO_PrivateKey *key)
951{
952 GNUNET_assert ((message) && (key));
953
954 const uint16_t padded_length = message->body.privacy.length;
955
956 if (padded_length < GNUNET_CRYPTO_ENCRYPT_OVERHEAD_BYTES)
957 {
958 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
959 "Message length too short to decrypt!\n");
960
961 return GNUNET_NO;
962 }
963
964 const uint16_t encoded_length = (
965 padded_length - GNUNET_CRYPTO_ENCRYPT_OVERHEAD_BYTES
966 );
967
968 if (GNUNET_OK != GNUNET_CRYPTO_decrypt (message->body.privacy.data,
969 padded_length,
970 key,
971 message->body.privacy.data,
972 encoded_length))
973 {
974 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
975
976 return GNUNET_NO;
977 }
978
979 struct GNUNET_MESSENGER_ShortMessage shortened;
980
981 if (GNUNET_YES != decode_short_message (&shortened,
982 encoded_length,
983 message->body.privacy.data))
984 {
985 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
986 "Decoding decrypted message failed!\n");
987
988 return GNUNET_NO;
989 }
990
991 unfold_short_message (&shortened, message);
992 return GNUNET_YES;
993}
994
995
996struct GNUNET_MQ_Envelope*
997pack_message (struct GNUNET_MESSENGER_Message *message,
998 struct GNUNET_HashCode *hash,
999 const GNUNET_MESSENGER_SignFunction sign,
1000 int mode,
1001 const void *cls)
1002{
1003 GNUNET_assert (message);
1004
1005 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1006 "Packing message kind=%u and sender: %s\n",
1007 message->header.kind, GNUNET_sh2s (&(message->header.sender_id)));
1008
1009 struct GNUNET_MessageHeader *header;
1010
1011 const uint16_t length = get_message_size (message, GNUNET_YES);
1012 const uint16_t padded_length = calc_padded_length (length);
1013
1014 struct GNUNET_MQ_Envelope *env;
1015 char *buffer;
1016
1017 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
1018 {
1019 env = GNUNET_MQ_msg_extra (header, padded_length,
1020 GNUNET_MESSAGE_TYPE_CADET_CLI);
1021
1022 buffer = (char*) &(header[1]);
1023 }
1024 else
1025 {
1026 env = NULL;
1027
1028 buffer = GNUNET_malloc (padded_length);
1029 }
1030
1031 encode_message (message, padded_length, buffer, GNUNET_YES);
1032
1033 if (hash)
1034 {
1035 hash_message (message, length, buffer, hash);
1036
1037 if (sign)
1038 sign (cls, message, length, buffer, hash);
1039 }
1040
1041 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
1042 GNUNET_free (buffer);
1043
1044 return env;
1045}
1046
1047
1048int
1049is_peer_message (const struct GNUNET_MESSENGER_Message *message)
1050{
1051 switch (message->header.kind)
1052 {
1053 case GNUNET_MESSENGER_KIND_INFO:
1054 case GNUNET_MESSENGER_KIND_PEER:
1055 case GNUNET_MESSENGER_KIND_MISS:
1056 case GNUNET_MESSENGER_KIND_MERGE:
1057 return GNUNET_YES;
1058 default:
1059 return GNUNET_NO;
1060 }
1061}
1062
1063
1064int
1065is_service_message (const struct GNUNET_MESSENGER_Message *message)
1066{
1067 if (GNUNET_YES == is_peer_message (message))
1068 return GNUNET_YES;
1069
1070 switch (message->header.kind)
1071 {
1072 case GNUNET_MESSENGER_KIND_INFO:
1073 return GNUNET_YES; // Reserved for connection handling only!
1074 case GNUNET_MESSENGER_KIND_JOIN:
1075 return GNUNET_YES; // Reserved for member handling only!
1076 case GNUNET_MESSENGER_KIND_LEAVE:
1077 return GNUNET_YES; // Reserved for member handling only!
1078 case GNUNET_MESSENGER_KIND_NAME:
1079 return GNUNET_YES; // Reserved for member name handling only!
1080 case GNUNET_MESSENGER_KIND_KEY:
1081 return GNUNET_YES; // Reserved for member key handling only!
1082 case GNUNET_MESSENGER_KIND_PEER:
1083 return GNUNET_YES; // Reserved for connection handling only!
1084 case GNUNET_MESSENGER_KIND_ID:
1085 return GNUNET_YES; // Reserved for member id handling only!
1086 case GNUNET_MESSENGER_KIND_MISS:
1087 return GNUNET_YES; // Reserved for connection handling only!
1088 case GNUNET_MESSENGER_KIND_MERGE:
1089 return GNUNET_YES; // Reserved for peers only!
1090 case GNUNET_MESSENGER_KIND_REQUEST:
1091 return GNUNET_YES; // Requests should not apply individually! (inefficieny)
1092 case GNUNET_MESSENGER_KIND_INVITE:
1093 return GNUNET_NO;
1094 case GNUNET_MESSENGER_KIND_TEXT:
1095 return GNUNET_NO;
1096 case GNUNET_MESSENGER_KIND_FILE:
1097 return GNUNET_NO;
1098 case GNUNET_MESSENGER_KIND_PRIVATE:
1099 return GNUNET_YES; // Prevent duplicate encryption breaking all access!
1100 case GNUNET_MESSENGER_KIND_DELETE:
1101 return GNUNET_YES; // Deletion should not apply individually! (inefficieny)
1102 default:
1103 return GNUNET_SYSERR;
1104 }
1105}
1106
1107
1108int
1109filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
1110{
1111 if (GNUNET_YES == is_peer_message (message))
1112 return GNUNET_SYSERR; // Requires signature of peer rather than ego!
1113
1114 switch (message->header.kind)
1115 {
1116 case GNUNET_MESSENGER_KIND_INFO:
1117 return GNUNET_SYSERR; // Reserved for connection handling only!
1118 case GNUNET_MESSENGER_KIND_JOIN:
1119 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
1120 case GNUNET_MESSENGER_KIND_LEAVE:
1121 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
1122 case GNUNET_MESSENGER_KIND_NAME:
1123 return GNUNET_YES;
1124 case GNUNET_MESSENGER_KIND_KEY:
1125 return GNUNET_NO; // Use #GNUNET_MESSENGER_set_key_by_ego(...) instead!
1126 case GNUNET_MESSENGER_KIND_PEER:
1127 return GNUNET_SYSERR; // Use #GNUNET_MESSENGER_open_room(...) instead!
1128 case GNUNET_MESSENGER_KIND_ID:
1129 return GNUNET_NO; // Reserved for member id handling only!
1130 case GNUNET_MESSENGER_KIND_MISS:
1131 return GNUNET_SYSERR; // Reserved for connection handling only!
1132 case GNUNET_MESSENGER_KIND_MERGE:
1133 return GNUNET_SYSERR; // Reserved for peers only!
1134 case GNUNET_MESSENGER_KIND_REQUEST:
1135 return GNUNET_YES;
1136 case GNUNET_MESSENGER_KIND_INVITE:
1137 return GNUNET_YES;
1138 case GNUNET_MESSENGER_KIND_TEXT:
1139 return GNUNET_YES;
1140 case GNUNET_MESSENGER_KIND_FILE:
1141 return GNUNET_YES;
1142 case GNUNET_MESSENGER_KIND_PRIVATE:
1143 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
1144 case GNUNET_MESSENGER_KIND_DELETE:
1145 return GNUNET_YES;
1146 default:
1147 return GNUNET_SYSERR;
1148 }
1149}