aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/messenger_api_message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/messenger_api_message.c')
-rw-r--r--src/messenger/messenger_api_message.c944
1 files changed, 0 insertions, 944 deletions
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
deleted file mode 100644
index 3814def70..000000000
--- a/src/messenger/messenger_api_message.c
+++ /dev/null
@@ -1,944 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 * @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 "messenger_api_message.h"
27
28struct GNUNET_MESSENGER_MessageSignature
29{
30 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
31 struct GNUNET_HashCode hash;
32};
33
34struct GNUNET_MESSENGER_ShortMessage
35{
36 enum GNUNET_MESSENGER_MessageKind kind;
37 struct GNUNET_MESSENGER_MessageBody body;
38};
39
40struct GNUNET_MESSENGER_Message*
41create_message (enum GNUNET_MESSENGER_MessageKind kind)
42{
43 struct GNUNET_MESSENGER_Message *message = GNUNET_new(struct GNUNET_MESSENGER_Message);
44
45 message->header.kind = kind;
46
47 switch (message->header.kind)
48 {
49 case GNUNET_MESSENGER_KIND_NAME:
50 message->body.name.name = NULL;
51 break;
52 case GNUNET_MESSENGER_KIND_TEXT:
53 message->body.text.text = NULL;
54 break;
55 case GNUNET_MESSENGER_KIND_FILE:
56 message->body.file.uri = NULL;
57 break;
58 case GNUNET_MESSENGER_KIND_PRIVATE:
59 message->body.privacy.length = 0;
60 message->body.privacy.data = NULL;
61 break;
62 default:
63 break;
64 }
65
66 return message;
67}
68
69struct GNUNET_MESSENGER_Message*
70copy_message (const struct GNUNET_MESSENGER_Message *message)
71{
72 GNUNET_assert(message);
73
74 struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message);
75
76 GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message));
77
78 switch (message->header.kind)
79 {
80 case GNUNET_MESSENGER_KIND_NAME:
81 copy->body.name.name = GNUNET_strdup(message->body.name.name);
82 break;
83 case GNUNET_MESSENGER_KIND_TEXT:
84 copy->body.text.text = GNUNET_strdup(message->body.text.text);
85 break;
86 case GNUNET_MESSENGER_KIND_FILE:
87 copy->body.file.uri = GNUNET_strdup(message->body.file.uri);
88 break;
89 case GNUNET_MESSENGER_KIND_PRIVATE:
90 copy->body.privacy.data = copy->body.privacy.length ? GNUNET_malloc(copy->body.privacy.length) : NULL;
91
92 if (copy->body.privacy.data)
93 {
94 GNUNET_memcpy(copy->body.privacy.data, message->body.privacy.data, copy->body.privacy.length);
95 }
96
97 break;
98 default:
99 break;
100 }
101
102 return copy;
103}
104
105static void
106destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind,
107 struct GNUNET_MESSENGER_MessageBody *body)
108{
109 switch (kind)
110 {
111 case GNUNET_MESSENGER_KIND_NAME:
112 GNUNET_free(body->name.name);
113 break;
114 case GNUNET_MESSENGER_KIND_TEXT:
115 GNUNET_free(body->text.text);
116 break;
117 case GNUNET_MESSENGER_KIND_FILE:
118 GNUNET_free(body->file.uri);
119 break;
120 case GNUNET_MESSENGER_KIND_PRIVATE:
121 GNUNET_free(body->privacy.data);
122 break;
123 default:
124 break;
125 }
126}
127
128void
129cleanup_message (struct GNUNET_MESSENGER_Message *message)
130{
131 GNUNET_assert(message);
132
133 destroy_message_body (message->header.kind, &(message->body));
134}
135
136void
137destroy_message (struct GNUNET_MESSENGER_Message *message)
138{
139 GNUNET_assert(message);
140
141 destroy_message_body (message->header.kind, &(message->body));
142
143 GNUNET_free(message);
144}
145
146int
147is_message_session_bound (const struct GNUNET_MESSENGER_Message *message)
148{
149 GNUNET_assert(message);
150
151 if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) ||
152 (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) ||
153 (GNUNET_MESSENGER_KIND_NAME == message->header.kind) ||
154 (GNUNET_MESSENGER_KIND_KEY == message->header.kind) ||
155 (GNUNET_MESSENGER_KIND_ID == message->header.kind))
156 return GNUNET_YES;
157 else
158 return GNUNET_NO;
159}
160
161static void
162fold_short_message (const struct GNUNET_MESSENGER_Message *message,
163 struct GNUNET_MESSENGER_ShortMessage *shortened)
164{
165 shortened->kind = message->header.kind;
166
167 GNUNET_memcpy(&(shortened->body), &(message->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
168}
169
170static void
171unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened,
172 struct GNUNET_MESSENGER_Message *message)
173{
174 destroy_message_body (message->header.kind, &(message->body));
175
176 message->header.kind = shortened->kind;
177
178 GNUNET_memcpy(&(message->body), &(shortened->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
179}
180
181#define member_size(type, member) sizeof(((type*) NULL)->member)
182
183static uint16_t
184get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
185{
186 uint16_t length = 0;
187
188 switch (kind)
189 {
190 case GNUNET_MESSENGER_KIND_INFO:
191 length += member_size(struct GNUNET_MESSENGER_Message, body.info.messenger_version);
192 break;
193 case GNUNET_MESSENGER_KIND_PEER:
194 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer);
195 break;
196 case GNUNET_MESSENGER_KIND_ID:
197 length += member_size(struct GNUNET_MESSENGER_Message, body.id.id);
198 break;
199 case GNUNET_MESSENGER_KIND_MISS:
200 length += member_size(struct GNUNET_MESSENGER_Message, body.miss.peer);
201 break;
202 case GNUNET_MESSENGER_KIND_MERGE:
203 length += member_size(struct GNUNET_MESSENGER_Message, body.merge.previous);
204 break;
205 case GNUNET_MESSENGER_KIND_REQUEST:
206 length += member_size(struct GNUNET_MESSENGER_Message, body.request.hash);
207 break;
208 case GNUNET_MESSENGER_KIND_INVITE:
209 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.door);
210 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.key);
211 break;
212 case GNUNET_MESSENGER_KIND_TEXT:
213 break;
214 case GNUNET_MESSENGER_KIND_FILE:
215 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key);
216 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash);
217 length += member_size(struct GNUNET_MESSENGER_Message, body.file.name);
218 break;
219 case GNUNET_MESSENGER_KIND_PRIVATE:
220 length += member_size(struct GNUNET_MESSENGER_Message, body.privacy.key);
221 break;
222 case GNUNET_MESSENGER_KIND_DELETE:
223 length += member_size(struct GNUNET_MESSENGER_Message, body.deletion.hash);
224 length += member_size(struct GNUNET_MESSENGER_Message, body.deletion.delay);
225 break;
226 default:
227 break;
228 }
229
230 return length;
231}
232
233typedef uint32_t kind_t;
234
235uint16_t
236get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind,
237 int include_header)
238{
239 uint16_t length = 0;
240
241 if (GNUNET_YES == include_header)
242 {
243 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
244 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
245 length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
246 }
247
248 length += sizeof(kind_t);
249
250 return length + get_message_body_kind_size (kind);
251}
252
253static uint16_t
254get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind,
255 const struct GNUNET_MESSENGER_MessageBody *body)
256{
257 uint16_t length = 0;
258
259 switch (kind)
260 {
261 case GNUNET_MESSENGER_KIND_INFO:
262 length += GNUNET_IDENTITY_key_get_length(&(body->info.host_key));
263 break;
264 case GNUNET_MESSENGER_KIND_JOIN:
265 length += GNUNET_IDENTITY_key_get_length(&(body->join.key));
266 break;
267 case GNUNET_MESSENGER_KIND_NAME:
268 length += (body->name.name ? strlen (body->name.name) : 0);
269 break;
270 case GNUNET_MESSENGER_KIND_KEY:
271 length += GNUNET_IDENTITY_key_get_length(&(body->key.key));
272 break;
273 case GNUNET_MESSENGER_KIND_TEXT:
274 length += strlen (body->text.text);
275 break;
276 case GNUNET_MESSENGER_KIND_FILE:
277 length += strlen (body->file.uri);
278 break;
279 case GNUNET_MESSENGER_KIND_PRIVATE:
280 length += body->privacy.length;
281 break;
282 default:
283 break;
284 }
285
286 return length;
287}
288
289uint16_t
290get_message_size (const struct GNUNET_MESSENGER_Message *message,
291 int include_header)
292{
293 GNUNET_assert(message);
294
295 uint16_t length = 0;
296
297 if (GNUNET_YES == include_header)
298 length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature));
299
300 length += get_message_kind_size (message->header.kind, include_header);
301 length += get_message_body_size (message->header.kind, &(message->body));
302
303 return length;
304}
305
306static uint16_t
307get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message,
308 int include_body)
309{
310 const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t);
311
312 if (message)
313 return minimum_size + get_message_body_kind_size (message->kind)
314 + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0);
315 else
316 return minimum_size;
317}
318
319static uint16_t
320calc_usual_padding ()
321{
322 uint16_t padding = 0;
323 uint16_t kind_size;
324
325 for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) {
326 kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i, GNUNET_YES);
327
328 if (kind_size > padding)
329 padding = kind_size;
330 }
331
332 return padding + GNUNET_MESSENGER_PADDING_MIN;
333}
334
335#define max(x, y) (x > y? x : y)
336
337static uint16_t
338calc_padded_length (uint16_t length)
339{
340 static uint16_t usual_padding = 0;
341
342 if (!usual_padding)
343 usual_padding = calc_usual_padding();
344
345 const uint16_t padded_length = max(
346 length + GNUNET_MESSENGER_PADDING_MIN,
347 usual_padding
348 );
349
350 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
351 return GNUNET_MESSENGER_PADDING_LEVEL0;
352
353 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1)
354 return GNUNET_MESSENGER_PADDING_LEVEL1;
355
356 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2)
357 return GNUNET_MESSENGER_PADDING_LEVEL2;
358
359 return GNUNET_MESSENGER_MAX_MESSAGE_SIZE;
360
361}
362
363#define min(x, y) (x < y? x : y)
364
365#define encode_step_ext(dst, offset, src, size) do { \
366 GNUNET_memcpy(dst + offset, src, size); \
367 offset += size; \
368} while (0)
369
370#define encode_step(dst, offset, src) do { \
371 encode_step_ext(dst, offset, src, sizeof(*src)); \
372} while (0)
373
374#define encode_step_key(dst, offset, src, length) do { \
375 ssize_t result = GNUNET_IDENTITY_write_key_to_buffer( \
376 src, dst + offset, length - offset \
377 ); \
378 if (result < 0) \
379 GNUNET_break (0); \
380 else \
381 offset += result; \
382} while (0)
383
384#define encode_step_signature(dst, offset, src, length) do { \
385 ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \
386 src, dst + offset, length - offset \
387 ); \
388 if (result < 0) \
389 GNUNET_break (0); \
390 else \
391 offset += result; \
392} while (0)
393
394static void
395encode_message_body (enum GNUNET_MESSENGER_MessageKind kind,
396 const struct GNUNET_MESSENGER_MessageBody *body,
397 uint16_t length,
398 char *buffer,
399 uint16_t offset)
400{
401 uint32_t version;
402 switch (kind)
403 {
404 case GNUNET_MESSENGER_KIND_INFO:
405 version = GNUNET_htobe32(body->info.messenger_version);
406
407 encode_step_key(buffer, offset, &(body->info.host_key), length);
408 encode_step(buffer, offset, &version);
409 break;
410 case GNUNET_MESSENGER_KIND_JOIN:
411 encode_step_key(buffer, offset, &(body->join.key), length);
412 break;
413 case GNUNET_MESSENGER_KIND_NAME:
414 if (body->name.name)
415 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
416 break;
417 case GNUNET_MESSENGER_KIND_KEY:
418 encode_step_key(buffer, offset, &(body->key.key), length);
419 break;
420 case GNUNET_MESSENGER_KIND_PEER:
421 encode_step(buffer, offset, &(body->peer.peer));
422 break;
423 case GNUNET_MESSENGER_KIND_ID:
424 encode_step(buffer, offset, &(body->id.id));
425 break;
426 case GNUNET_MESSENGER_KIND_MISS:
427 encode_step(buffer, offset, &(body->miss.peer));
428 break;
429 case GNUNET_MESSENGER_KIND_MERGE:
430 encode_step(buffer, offset, &(body->merge.previous));
431 break;
432 case GNUNET_MESSENGER_KIND_REQUEST:
433 encode_step(buffer, offset, &(body->request.hash));
434 break;
435 case GNUNET_MESSENGER_KIND_INVITE:
436 encode_step(buffer, offset, &(body->invite.door));
437 encode_step(buffer, offset, &(body->invite.key));
438 break;
439 case GNUNET_MESSENGER_KIND_TEXT:
440 encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text)));
441 break;
442 case GNUNET_MESSENGER_KIND_FILE:
443 encode_step(buffer, offset, &(body->file.key));
444 encode_step(buffer, offset, &(body->file.hash));
445 encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
446 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
447 break;
448 case GNUNET_MESSENGER_KIND_PRIVATE:
449 encode_step(buffer, offset, &(body->privacy.key));
450 encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, body->privacy.length));
451 break;
452 case GNUNET_MESSENGER_KIND_DELETE:
453 encode_step(buffer, offset, &(body->deletion.hash));
454 encode_step(buffer, offset, &(body->deletion.delay));
455 break;
456 default:
457 break;
458 }
459
460 if (offset >= length)
461 return;
462
463 const uint16_t padding = length - offset;
464 const uint16_t used_padding = sizeof(padding) + sizeof(char);
465
466 GNUNET_assert(padding >= used_padding);
467
468 buffer[offset++] = '\0';
469
470 if (padding > used_padding)
471 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding);
472
473 GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
474}
475
476void
477encode_message (const struct GNUNET_MESSENGER_Message *message,
478 uint16_t length,
479 char *buffer,
480 int include_header)
481{
482 GNUNET_assert((message) && (buffer));
483
484 uint16_t offset = 0;
485
486 if (GNUNET_YES == include_header)
487 encode_step_signature(buffer, offset, &(message->header.signature), length);
488
489 const kind_t kind = GNUNET_htobe32((kind_t) message->header.kind);
490
491 if (GNUNET_YES == include_header)
492 {
493 encode_step(buffer, offset, &(message->header.timestamp));
494 encode_step(buffer, offset, &(message->header.sender_id));
495 encode_step(buffer, offset, &(message->header.previous));
496 }
497
498 encode_step(buffer, offset, &kind);
499
500 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
501}
502
503static void
504encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message,
505 uint16_t length,
506 char *buffer)
507{
508 struct GNUNET_HashCode hash;
509 uint16_t offset = sizeof(hash);
510
511 const kind_t kind = GNUNET_htobe32((kind_t) message->kind);
512
513 encode_step(buffer, offset, &kind);
514
515 encode_message_body (message->kind, &(message->body), length, buffer, offset);
516
517 GNUNET_CRYPTO_hash(
518 buffer + sizeof(hash),
519 length - sizeof(hash),
520 &hash
521 );
522
523 GNUNET_memcpy(buffer, &hash, sizeof(hash));
524}
525
526#define decode_step_ext(src, offset, dst, size) do { \
527 GNUNET_memcpy(dst, src + offset, size); \
528 offset += size; \
529} while (0)
530
531#define decode_step(src, offset, dst) do { \
532 decode_step_ext(src, offset, dst, sizeof(*dst)); \
533} while (0)
534
535#define decode_step_malloc(src, offset, dst, size, zero) do { \
536 dst = GNUNET_malloc(size + zero); \
537 if (zero) dst[size] = 0; \
538 decode_step_ext(src, offset, dst, size); \
539} while (0)
540
541#define decode_step_key(src, offset, dst, length) do { \
542 ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \
543 dst, src + offset, length - offset \
544 ); \
545 if (result < 0) \
546 GNUNET_break(0); \
547 else \
548 offset += result; \
549} while (0)
550
551static uint16_t
552decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind,
553 struct GNUNET_MESSENGER_MessageBody *body,
554 uint16_t length,
555 const char *buffer,
556 uint16_t offset)
557{
558 uint16_t padding = 0;
559
560 GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
561
562 if (padding > length - offset)
563 padding = 0;
564
565 const uint16_t end_zero = length - padding;
566
567 if ((padding) && (buffer[end_zero] != '\0'))
568 padding = 0;
569
570 length -= padding;
571
572 uint32_t version;
573 switch (*kind)
574 {
575 case GNUNET_MESSENGER_KIND_INFO: {
576 decode_step_key(buffer, offset, &(body->info.host_key), length);
577 decode_step(buffer, offset, &version);
578
579 body->info.messenger_version = GNUNET_be32toh(version);
580 break;
581 } case GNUNET_MESSENGER_KIND_JOIN: {
582 decode_step_key(buffer, offset, &(body->join.key), length);
583 break;
584 } case GNUNET_MESSENGER_KIND_NAME:
585 if (length - offset > 0)
586 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
587 else
588 body->name.name = NULL;
589 break;
590 case GNUNET_MESSENGER_KIND_KEY:
591 decode_step_key(buffer, offset, &(body->key.key), length);
592 break;
593 case GNUNET_MESSENGER_KIND_PEER:
594 decode_step(buffer, offset, &(body->peer.peer));
595 break;
596 case GNUNET_MESSENGER_KIND_ID:
597 decode_step(buffer, offset, &(body->id.id));
598 break;
599 case GNUNET_MESSENGER_KIND_MISS:
600 decode_step(buffer, offset, &(body->miss.peer));
601 break;
602 case GNUNET_MESSENGER_KIND_MERGE:
603 decode_step(buffer, offset, &(body->merge.previous));
604 break;
605 case GNUNET_MESSENGER_KIND_REQUEST:
606 decode_step(buffer, offset, &(body->request.hash));
607 break;
608 case GNUNET_MESSENGER_KIND_INVITE:
609 decode_step(buffer, offset, &(body->invite.door));
610 decode_step(buffer, offset, &(body->invite.key));
611 break;
612 case GNUNET_MESSENGER_KIND_TEXT:
613 decode_step_malloc(buffer, offset, body->text.text, length - offset, 1);
614 break;
615 case GNUNET_MESSENGER_KIND_FILE:
616 decode_step(buffer, offset, &(body->file.key));
617 decode_step(buffer, offset, &(body->file.hash));
618 decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
619 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
620 break;
621 case GNUNET_MESSENGER_KIND_PRIVATE:
622 decode_step(buffer, offset, &(body->privacy.key));
623
624 body->privacy.length = (length - offset);
625 decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0);
626 break;
627 case GNUNET_MESSENGER_KIND_DELETE:
628 decode_step(buffer, offset, &(body->deletion.hash));
629 decode_step(buffer, offset, &(body->deletion.delay));
630 break;
631 default:
632 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
633 break;
634 }
635
636 return padding;
637}
638
639int
640decode_message (struct GNUNET_MESSENGER_Message *message,
641 uint16_t length,
642 const char *buffer,
643 int include_header,
644 uint16_t *padding)
645{
646 GNUNET_assert(
647 (message) &&
648 (buffer) &&
649 (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, include_header))
650 );
651
652 uint16_t offset = 0;
653
654 if (GNUNET_YES == include_header)
655 {
656 ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
657 &(message->header.signature), buffer, length - offset
658 );
659
660 if (result < 0)
661 return GNUNET_NO;
662 else
663 offset += result;
664 }
665
666 const uint16_t count = length - offset;
667
668 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, include_header))
669 return GNUNET_NO;
670
671 kind_t kind;
672
673 if (GNUNET_YES == include_header)
674 {
675 decode_step(buffer, offset, &(message->header.timestamp));
676 decode_step(buffer, offset, &(message->header.sender_id));
677 decode_step(buffer, offset, &(message->header.previous));
678 }
679
680 decode_step(buffer, offset, &kind);
681
682 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
683
684 if (count < get_message_kind_size (message->header.kind, include_header))
685 return GNUNET_NO;
686
687 const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
688
689 if (padding)
690 *padding = result;
691
692 return GNUNET_YES;
693}
694
695static int
696decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message,
697 uint16_t length,
698 const char *buffer)
699{
700 struct GNUNET_HashCode expected, hash;
701 uint16_t offset = sizeof(hash);
702
703 if (length < get_short_message_size (NULL, GNUNET_NO))
704 return GNUNET_NO;
705
706 GNUNET_memcpy(&hash, buffer, sizeof(hash));
707
708 GNUNET_CRYPTO_hash(
709 buffer + sizeof(hash),
710 length - sizeof(hash),
711 &expected
712 );
713
714 if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
715 return GNUNET_NO;
716
717 kind_t kind;
718
719 decode_step(buffer, offset, &kind);
720
721 message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
722
723 if (length < get_short_message_size (message, GNUNET_NO))
724 return GNUNET_NO;
725
726 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
727
728 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
729 return GNUNET_NO;
730
731 return GNUNET_YES;
732}
733
734void
735hash_message (const struct GNUNET_MESSENGER_Message *message,
736 uint16_t length,
737 const char *buffer,
738 struct GNUNET_HashCode *hash)
739{
740 GNUNET_assert((message) && (buffer) && (hash));
741
742 const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
743 &(message->header.signature)
744 );
745
746 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
747}
748
749void
750sign_message (struct GNUNET_MESSENGER_Message *message,
751 uint16_t length,
752 char *buffer,
753 const struct GNUNET_HashCode *hash,
754 const struct GNUNET_MESSENGER_Ego *ego)
755{
756 GNUNET_assert((message) && (buffer) && (hash) && (ego));
757
758 struct GNUNET_MESSENGER_MessageSignature signature;
759
760 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
761 signature.purpose.size = htonl (sizeof(signature));
762
763 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
764 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
765
766 uint16_t offset = 0;
767 encode_step_signature(buffer, offset, &(message->header.signature), length);
768}
769
770int
771verify_message (const struct GNUNET_MESSENGER_Message *message,
772 const struct GNUNET_HashCode *hash,
773 const struct GNUNET_IDENTITY_PublicKey *key)
774{
775 GNUNET_assert((message) && (hash) && (key));
776
777 if (ntohl (key->type) != ntohl (message->header.signature.type))
778 return GNUNET_SYSERR;
779
780 struct GNUNET_MESSENGER_MessageSignature signature;
781
782 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
783 signature.purpose.size = htonl (sizeof(signature));
784
785 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
786
787 return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
788 &(message->header.signature), key);
789}
790
791int
792encrypt_message (struct GNUNET_MESSENGER_Message *message,
793 const struct GNUNET_IDENTITY_PublicKey *key)
794{
795 GNUNET_assert((message) && (key));
796
797 struct GNUNET_MESSENGER_ShortMessage shortened;
798
799 fold_short_message (message, &shortened);
800
801 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
802 const uint16_t padded_length = calc_padded_length(length);
803
804 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
805 message->body.privacy.data = GNUNET_malloc(padded_length);
806 message->body.privacy.length = padded_length;
807
808 encode_short_message (&shortened, padded_length, message->body.privacy.data);
809
810 if (padded_length == GNUNET_IDENTITY_encrypt (message->body.privacy.data, padded_length, key,
811 &(message->body.privacy.key),
812 message->body.privacy.data))
813 {
814 destroy_message_body (shortened.kind, &(shortened.body));
815 return GNUNET_YES;
816 }
817 else
818 {
819 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
820
821 unfold_short_message (&shortened, message);
822 return GNUNET_NO;
823 }
824}
825
826int
827decrypt_message (struct GNUNET_MESSENGER_Message *message,
828 const struct GNUNET_IDENTITY_PrivateKey *key)
829{
830 GNUNET_assert((message) && (key));
831
832 if (message->body.privacy.length != GNUNET_IDENTITY_decrypt (message->body.privacy.data, message->body.privacy.length,
833 key, &(message->body.privacy.key),
834 message->body.privacy.data))
835 {
836 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
837
838 return GNUNET_NO;
839 }
840
841 struct GNUNET_MESSENGER_ShortMessage shortened;
842
843 if (GNUNET_YES != decode_short_message (&shortened, message->body.privacy.length, message->body.privacy.data))
844 {
845 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n");
846
847 return GNUNET_NO;
848 }
849
850 unfold_short_message (&shortened, message);
851
852 return GNUNET_YES;
853}
854
855struct GNUNET_MQ_Envelope*
856pack_message (struct GNUNET_MESSENGER_Message *message,
857 struct GNUNET_HashCode *hash,
858 const struct GNUNET_MESSENGER_Ego *ego,
859 int mode)
860{
861 GNUNET_assert(message);
862
863 if (ego)
864 message->header.signature.type = ego->priv.type;
865
866 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n",
867 message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
868
869 struct GNUNET_MessageHeader *header;
870
871 const uint16_t length = get_message_size (message, GNUNET_YES);
872 const uint16_t padded_length = calc_padded_length(length);
873
874 struct GNUNET_MQ_Envelope *env;
875 char *buffer;
876
877 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
878 {
879 env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI);
880
881 buffer = (char*) &(header[1]);
882 }
883 else
884 {
885 env = NULL;
886
887 buffer = GNUNET_malloc(padded_length);
888 }
889
890 encode_message (message, padded_length, buffer, GNUNET_YES);
891
892 if (hash)
893 {
894 hash_message (message, length, buffer, hash);
895
896 if (ego)
897 sign_message (message, length, buffer, hash, ego);
898 }
899
900 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
901 GNUNET_free(buffer);
902
903 return env;
904}
905
906int
907filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
908{
909 switch (message->header.kind)
910 {
911 case GNUNET_MESSENGER_KIND_INFO:
912 return GNUNET_SYSERR; // Reserved for connection handling only!
913 case GNUNET_MESSENGER_KIND_JOIN:
914 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
915 case GNUNET_MESSENGER_KIND_LEAVE:
916 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
917 case GNUNET_MESSENGER_KIND_NAME:
918 return GNUNET_YES;
919 case GNUNET_MESSENGER_KIND_KEY:
920 return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
921 case GNUNET_MESSENGER_KIND_PEER:
922 return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
923 case GNUNET_MESSENGER_KIND_ID:
924 return GNUNET_SYSERR; // Reserved for member id handling only!
925 case GNUNET_MESSENGER_KIND_MISS:
926 return GNUNET_SYSERR; // Reserved for connection handling only!
927 case GNUNET_MESSENGER_KIND_MERGE:
928 return GNUNET_YES;
929 case GNUNET_MESSENGER_KIND_REQUEST:
930 return GNUNET_YES;
931 case GNUNET_MESSENGER_KIND_INVITE:
932 return GNUNET_YES;
933 case GNUNET_MESSENGER_KIND_TEXT:
934 return GNUNET_YES;
935 case GNUNET_MESSENGER_KIND_FILE:
936 return GNUNET_YES;
937 case GNUNET_MESSENGER_KIND_PRIVATE:
938 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
939 case GNUNET_MESSENGER_KIND_DELETE:
940 return GNUNET_YES;
941 default:
942 return GNUNET_SYSERR;
943 }
944}