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.c932
1 files changed, 0 insertions, 932 deletions
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
deleted file mode 100644
index 496c98dbf..000000000
--- a/src/messenger/messenger_api_message.c
+++ /dev/null
@@ -1,932 +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 default:
223 break;
224 }
225
226 return length;
227}
228
229typedef uint32_t kind_t;
230
231uint16_t
232get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind,
233 int include_header)
234{
235 uint16_t length = 0;
236
237 if (GNUNET_YES == include_header)
238 {
239 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
240 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
241 length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
242 }
243
244 length += sizeof(kind_t);
245
246 return length + get_message_body_kind_size (kind);
247}
248
249static uint16_t
250get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind,
251 const struct GNUNET_MESSENGER_MessageBody *body)
252{
253 uint16_t length = 0;
254
255 switch (kind)
256 {
257 case GNUNET_MESSENGER_KIND_INFO:
258 length += GNUNET_IDENTITY_key_get_length(&(body->info.host_key));
259 break;
260 case GNUNET_MESSENGER_KIND_JOIN:
261 length += GNUNET_IDENTITY_key_get_length(&(body->join.key));
262 break;
263 case GNUNET_MESSENGER_KIND_NAME:
264 length += (body->name.name ? strlen (body->name.name) : 0);
265 break;
266 case GNUNET_MESSENGER_KIND_KEY:
267 length += GNUNET_IDENTITY_key_get_length(&(body->key.key));
268 break;
269 case GNUNET_MESSENGER_KIND_TEXT:
270 length += strlen (body->text.text);
271 break;
272 case GNUNET_MESSENGER_KIND_FILE:
273 length += strlen (body->file.uri);
274 break;
275 case GNUNET_MESSENGER_KIND_PRIVATE:
276 length += body->privacy.length;
277 break;
278 default:
279 break;
280 }
281
282 return length;
283}
284
285uint16_t
286get_message_size (const struct GNUNET_MESSENGER_Message *message,
287 int include_header)
288{
289 GNUNET_assert(message);
290
291 uint16_t length = 0;
292
293 if (GNUNET_YES == include_header)
294 length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature));
295
296 length += get_message_kind_size (message->header.kind, include_header);
297 length += get_message_body_size (message->header.kind, &(message->body));
298
299 return length;
300}
301
302static uint16_t
303get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message,
304 int include_body)
305{
306 const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t);
307
308 if (message)
309 return minimum_size + get_message_body_kind_size (message->kind)
310 + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0);
311 else
312 return minimum_size;
313}
314
315static uint16_t
316calc_usual_padding ()
317{
318 uint16_t padding = 0;
319 uint16_t kind_size;
320
321 for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) {
322 kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i, GNUNET_YES);
323
324 if (kind_size > padding)
325 padding = kind_size;
326 }
327
328 return padding + GNUNET_MESSENGER_PADDING_MIN;
329}
330
331#define max(x, y) (x > y? x : y)
332
333static uint16_t
334calc_padded_length (uint16_t length)
335{
336 static uint16_t usual_padding = 0;
337
338 if (!usual_padding)
339 usual_padding = calc_usual_padding();
340
341 const uint16_t padded_length = max(
342 length + GNUNET_MESSENGER_PADDING_MIN,
343 usual_padding
344 );
345
346 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
347 return GNUNET_MESSENGER_PADDING_LEVEL0;
348
349 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1)
350 return GNUNET_MESSENGER_PADDING_LEVEL1;
351
352 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2)
353 return GNUNET_MESSENGER_PADDING_LEVEL2;
354
355 return GNUNET_MESSENGER_MAX_MESSAGE_SIZE;
356
357}
358
359#define min(x, y) (x < y? x : y)
360
361#define encode_step_ext(dst, offset, src, size) do { \
362 GNUNET_memcpy(dst + offset, src, size); \
363 offset += size; \
364} while (0)
365
366#define encode_step(dst, offset, src) do { \
367 encode_step_ext(dst, offset, src, sizeof(*src)); \
368} while (0)
369
370#define encode_step_key(dst, offset, src, length) do { \
371 ssize_t result = GNUNET_IDENTITY_write_key_to_buffer( \
372 src, dst + offset, length - offset \
373 ); \
374 if (result < 0) \
375 GNUNET_break (0); \
376 else \
377 offset += result; \
378} while (0)
379
380#define encode_step_signature(dst, offset, src, length) do { \
381 ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \
382 src, dst + offset, length - offset \
383 ); \
384 if (result < 0) \
385 GNUNET_break (0); \
386 else \
387 offset += result; \
388} while (0)
389
390static void
391encode_message_body (enum GNUNET_MESSENGER_MessageKind kind,
392 const struct GNUNET_MESSENGER_MessageBody *body,
393 uint16_t length,
394 char *buffer,
395 uint16_t offset)
396{
397 uint32_t version;
398 switch (kind)
399 {
400 case GNUNET_MESSENGER_KIND_INFO:
401 version = GNUNET_htobe32(body->info.messenger_version);
402
403 encode_step_key(buffer, offset, &(body->info.host_key), length);
404 encode_step(buffer, offset, &version);
405 break;
406 case GNUNET_MESSENGER_KIND_JOIN:
407 encode_step_key(buffer, offset, &(body->join.key), length);
408 break;
409 case GNUNET_MESSENGER_KIND_NAME:
410 if (body->name.name)
411 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
412 break;
413 case GNUNET_MESSENGER_KIND_KEY:
414 encode_step_key(buffer, offset, &(body->key.key), length);
415 break;
416 case GNUNET_MESSENGER_KIND_PEER:
417 encode_step(buffer, offset, &(body->peer.peer));
418 break;
419 case GNUNET_MESSENGER_KIND_ID:
420 encode_step(buffer, offset, &(body->id.id));
421 break;
422 case GNUNET_MESSENGER_KIND_MISS:
423 encode_step(buffer, offset, &(body->miss.peer));
424 break;
425 case GNUNET_MESSENGER_KIND_MERGE:
426 encode_step(buffer, offset, &(body->merge.previous));
427 break;
428 case GNUNET_MESSENGER_KIND_REQUEST:
429 encode_step(buffer, offset, &(body->request.hash));
430 break;
431 case GNUNET_MESSENGER_KIND_INVITE:
432 encode_step(buffer, offset, &(body->invite.door));
433 encode_step(buffer, offset, &(body->invite.key));
434 break;
435 case GNUNET_MESSENGER_KIND_TEXT:
436 encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text)));
437 break;
438 case GNUNET_MESSENGER_KIND_FILE:
439 encode_step(buffer, offset, &(body->file.key));
440 encode_step(buffer, offset, &(body->file.hash));
441 encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
442 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
443 break;
444 case GNUNET_MESSENGER_KIND_PRIVATE:
445 encode_step(buffer, offset, &(body->privacy.key));
446 encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, body->privacy.length));
447 break;
448 default:
449 break;
450 }
451
452 if (offset >= length)
453 return;
454
455 const uint16_t padding = length - offset;
456 const uint16_t used_padding = sizeof(padding) + sizeof(char);
457
458 GNUNET_assert(padding >= used_padding);
459
460 buffer[offset++] = '\0';
461
462 if (padding > used_padding)
463 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding);
464
465 GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
466}
467
468void
469encode_message (const struct GNUNET_MESSENGER_Message *message,
470 uint16_t length,
471 char *buffer,
472 int include_header)
473{
474 GNUNET_assert((message) && (buffer));
475
476 uint16_t offset = 0;
477
478 if (GNUNET_YES == include_header)
479 encode_step_signature(buffer, offset, &(message->header.signature), length);
480
481 const kind_t kind = GNUNET_htobe32((kind_t) message->header.kind);
482
483 if (GNUNET_YES == include_header)
484 {
485 encode_step(buffer, offset, &(message->header.timestamp));
486 encode_step(buffer, offset, &(message->header.sender_id));
487 encode_step(buffer, offset, &(message->header.previous));
488 }
489
490 encode_step(buffer, offset, &kind);
491
492 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
493}
494
495static void
496encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message,
497 uint16_t length,
498 char *buffer)
499{
500 struct GNUNET_HashCode hash;
501 uint16_t offset = sizeof(hash);
502
503 const kind_t kind = GNUNET_htobe32((kind_t) message->kind);
504
505 encode_step(buffer, offset, &kind);
506
507 encode_message_body (message->kind, &(message->body), length, buffer, offset);
508
509 GNUNET_CRYPTO_hash(
510 buffer + sizeof(hash),
511 length - sizeof(hash),
512 &hash
513 );
514
515 GNUNET_memcpy(buffer, &hash, sizeof(hash));
516}
517
518#define decode_step_ext(src, offset, dst, size) do { \
519 GNUNET_memcpy(dst, src + offset, size); \
520 offset += size; \
521} while (0)
522
523#define decode_step(src, offset, dst) do { \
524 decode_step_ext(src, offset, dst, sizeof(*dst)); \
525} while (0)
526
527#define decode_step_malloc(src, offset, dst, size, zero) do { \
528 dst = GNUNET_malloc(size + zero); \
529 if (zero) dst[size] = 0; \
530 decode_step_ext(src, offset, dst, size); \
531} while (0)
532
533#define decode_step_key(src, offset, dst, length) do { \
534 ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \
535 dst, src + offset, length - offset \
536 ); \
537 if (result < 0) \
538 GNUNET_break(0); \
539 else \
540 offset += result; \
541} while (0)
542
543static uint16_t
544decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind,
545 struct GNUNET_MESSENGER_MessageBody *body,
546 uint16_t length,
547 const char *buffer,
548 uint16_t offset)
549{
550 uint16_t padding = 0;
551
552 GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
553
554 if (padding > length - offset)
555 padding = 0;
556
557 const uint16_t end_zero = length - padding;
558
559 if ((padding) && (buffer[end_zero] != '\0'))
560 padding = 0;
561
562 length -= padding;
563
564 uint32_t version;
565 switch (*kind)
566 {
567 case GNUNET_MESSENGER_KIND_INFO: {
568 decode_step_key(buffer, offset, &(body->info.host_key), length);
569 decode_step(buffer, offset, &version);
570
571 body->info.messenger_version = GNUNET_be32toh(version);
572 break;
573 } case GNUNET_MESSENGER_KIND_JOIN: {
574 decode_step_key(buffer, offset, &(body->join.key), length);
575 break;
576 } case GNUNET_MESSENGER_KIND_NAME:
577 if (length - offset > 0)
578 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
579 else
580 body->name.name = NULL;
581 break;
582 case GNUNET_MESSENGER_KIND_KEY:
583 decode_step_key(buffer, offset, &(body->key.key), length);
584 break;
585 case GNUNET_MESSENGER_KIND_PEER:
586 decode_step(buffer, offset, &(body->peer.peer));
587 break;
588 case GNUNET_MESSENGER_KIND_ID:
589 decode_step(buffer, offset, &(body->id.id));
590 break;
591 case GNUNET_MESSENGER_KIND_MISS:
592 decode_step(buffer, offset, &(body->miss.peer));
593 break;
594 case GNUNET_MESSENGER_KIND_MERGE:
595 decode_step(buffer, offset, &(body->merge.previous));
596 break;
597 case GNUNET_MESSENGER_KIND_REQUEST:
598 decode_step(buffer, offset, &(body->request.hash));
599 break;
600 case GNUNET_MESSENGER_KIND_INVITE:
601 decode_step(buffer, offset, &(body->invite.door));
602 decode_step(buffer, offset, &(body->invite.key));
603 break;
604 case GNUNET_MESSENGER_KIND_TEXT:
605 decode_step_malloc(buffer, offset, body->text.text, length - offset, 1);
606 break;
607 case GNUNET_MESSENGER_KIND_FILE:
608 decode_step(buffer, offset, &(body->file.key));
609 decode_step(buffer, offset, &(body->file.hash));
610 decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
611 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
612 break;
613 case GNUNET_MESSENGER_KIND_PRIVATE:
614 decode_step(buffer, offset, &(body->privacy.key));
615
616 body->privacy.length = (length - offset);
617 decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0);
618 break;
619 default:
620 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
621 break;
622 }
623
624 return padding;
625}
626
627int
628decode_message (struct GNUNET_MESSENGER_Message *message,
629 uint16_t length,
630 const char *buffer,
631 int include_header,
632 uint16_t *padding)
633{
634 GNUNET_assert(
635 (message) &&
636 (buffer) &&
637 (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, include_header))
638 );
639
640 uint16_t offset = 0;
641
642 if (GNUNET_YES == include_header)
643 {
644 ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
645 &(message->header.signature), buffer, length - offset
646 );
647
648 if (result < 0)
649 return GNUNET_NO;
650 else
651 offset += result;
652 }
653
654 const uint16_t count = length - offset;
655
656 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, include_header))
657 return GNUNET_NO;
658
659 kind_t kind;
660
661 if (GNUNET_YES == include_header)
662 {
663 decode_step(buffer, offset, &(message->header.timestamp));
664 decode_step(buffer, offset, &(message->header.sender_id));
665 decode_step(buffer, offset, &(message->header.previous));
666 }
667
668 decode_step(buffer, offset, &kind);
669
670 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
671
672 if (count < get_message_kind_size (message->header.kind, include_header))
673 return GNUNET_NO;
674
675 const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
676
677 if (padding)
678 *padding = result;
679
680 return GNUNET_YES;
681}
682
683static int
684decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message,
685 uint16_t length,
686 const char *buffer)
687{
688 struct GNUNET_HashCode expected, hash;
689 uint16_t offset = sizeof(hash);
690
691 if (length < get_short_message_size (NULL, GNUNET_NO))
692 return GNUNET_NO;
693
694 GNUNET_memcpy(&hash, buffer, sizeof(hash));
695
696 GNUNET_CRYPTO_hash(
697 buffer + sizeof(hash),
698 length - sizeof(hash),
699 &expected
700 );
701
702 if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
703 return GNUNET_NO;
704
705 kind_t kind;
706
707 decode_step(buffer, offset, &kind);
708
709 message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
710
711 if (length < get_short_message_size (message, GNUNET_NO))
712 return GNUNET_NO;
713
714 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
715
716 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
717 return GNUNET_NO;
718
719 return GNUNET_YES;
720}
721
722void
723hash_message (const struct GNUNET_MESSENGER_Message *message,
724 uint16_t length,
725 const char *buffer,
726 struct GNUNET_HashCode *hash)
727{
728 GNUNET_assert((message) && (buffer) && (hash));
729
730 const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
731 &(message->header.signature)
732 );
733
734 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
735}
736
737void
738sign_message (struct GNUNET_MESSENGER_Message *message,
739 uint16_t length,
740 char *buffer,
741 const struct GNUNET_HashCode *hash,
742 const struct GNUNET_MESSENGER_Ego *ego)
743{
744 GNUNET_assert((message) && (buffer) && (hash) && (ego));
745
746 struct GNUNET_MESSENGER_MessageSignature signature;
747
748 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
749 signature.purpose.size = htonl (sizeof(signature));
750
751 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
752 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
753
754 uint16_t offset = 0;
755 encode_step_signature(buffer, offset, &(message->header.signature), length);
756}
757
758int
759verify_message (const struct GNUNET_MESSENGER_Message *message,
760 const struct GNUNET_HashCode *hash,
761 const struct GNUNET_IDENTITY_PublicKey *key)
762{
763 GNUNET_assert((message) && (hash) && (key));
764
765 if (ntohl (key->type) != ntohl (message->header.signature.type))
766 return GNUNET_SYSERR;
767
768 struct GNUNET_MESSENGER_MessageSignature signature;
769
770 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
771 signature.purpose.size = htonl (sizeof(signature));
772
773 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
774
775 return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
776 &(message->header.signature), key);
777}
778
779int
780encrypt_message (struct GNUNET_MESSENGER_Message *message,
781 const struct GNUNET_IDENTITY_PublicKey *key)
782{
783 GNUNET_assert((message) && (key));
784
785 struct GNUNET_MESSENGER_ShortMessage shortened;
786
787 fold_short_message (message, &shortened);
788
789 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
790 const uint16_t padded_length = calc_padded_length(length);
791
792 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
793 message->body.privacy.data = GNUNET_malloc(padded_length);
794 message->body.privacy.length = padded_length;
795
796 encode_short_message (&shortened, padded_length, message->body.privacy.data);
797
798 if (padded_length == GNUNET_IDENTITY_encrypt (message->body.privacy.data, padded_length, key,
799 &(message->body.privacy.key),
800 message->body.privacy.data))
801 {
802 destroy_message_body (shortened.kind, &(shortened.body));
803 return GNUNET_YES;
804 }
805 else
806 {
807 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
808
809 unfold_short_message (&shortened, message);
810 return GNUNET_NO;
811 }
812}
813
814int
815decrypt_message (struct GNUNET_MESSENGER_Message *message,
816 const struct GNUNET_IDENTITY_PrivateKey *key)
817{
818 GNUNET_assert((message) && (key));
819
820 if (message->body.privacy.length != GNUNET_IDENTITY_decrypt (message->body.privacy.data, message->body.privacy.length,
821 key, &(message->body.privacy.key),
822 message->body.privacy.data))
823 {
824 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
825
826 return GNUNET_NO;
827 }
828
829 struct GNUNET_MESSENGER_ShortMessage shortened;
830
831 if (GNUNET_YES != decode_short_message (&shortened, message->body.privacy.length, message->body.privacy.data))
832 {
833 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n");
834
835 return GNUNET_NO;
836 }
837
838 unfold_short_message (&shortened, message);
839
840 return GNUNET_YES;
841}
842
843struct GNUNET_MQ_Envelope*
844pack_message (struct GNUNET_MESSENGER_Message *message,
845 struct GNUNET_HashCode *hash,
846 const struct GNUNET_MESSENGER_Ego *ego,
847 int mode)
848{
849 GNUNET_assert(message);
850
851 if (ego)
852 message->header.signature.type = ego->priv.type;
853
854 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n",
855 message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
856
857 struct GNUNET_MessageHeader *header;
858
859 const uint16_t length = get_message_size (message, GNUNET_YES);
860 const uint16_t padded_length = calc_padded_length(length);
861
862 struct GNUNET_MQ_Envelope *env;
863 char *buffer;
864
865 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
866 {
867 env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI);
868
869 buffer = (char*) &(header[1]);
870 }
871 else
872 {
873 env = NULL;
874
875 buffer = GNUNET_malloc(padded_length);
876 }
877
878 encode_message (message, padded_length, buffer, GNUNET_YES);
879
880 if (hash)
881 {
882 hash_message (message, length, buffer, hash);
883
884 if (ego)
885 sign_message (message, length, buffer, hash, ego);
886 }
887
888 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
889 GNUNET_free(buffer);
890
891 return env;
892}
893
894int
895filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
896{
897 switch (message->header.kind)
898 {
899 case GNUNET_MESSENGER_KIND_INFO:
900 return GNUNET_SYSERR; // Reserved for connection handling only!
901 case GNUNET_MESSENGER_KIND_JOIN:
902 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
903 case GNUNET_MESSENGER_KIND_LEAVE:
904 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
905 case GNUNET_MESSENGER_KIND_NAME:
906 return GNUNET_YES;
907 case GNUNET_MESSENGER_KIND_KEY:
908 return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
909 case GNUNET_MESSENGER_KIND_PEER:
910 return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
911 case GNUNET_MESSENGER_KIND_ID:
912 return GNUNET_SYSERR; // Reserved for member id handling only!
913 case GNUNET_MESSENGER_KIND_MISS:
914 return GNUNET_SYSERR; // Reserved for connection handling only!
915 case GNUNET_MESSENGER_KIND_MERGE:
916 return GNUNET_YES;
917 case GNUNET_MESSENGER_KIND_REQUEST:
918 return GNUNET_YES;
919 case GNUNET_MESSENGER_KIND_INVITE:
920 return GNUNET_YES;
921 case GNUNET_MESSENGER_KIND_TEXT:
922 return GNUNET_YES;
923 case GNUNET_MESSENGER_KIND_FILE:
924 return GNUNET_YES;
925 case GNUNET_MESSENGER_KIND_PRIVATE:
926 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
927 case GNUNET_MESSENGER_KIND_DELETE:
928 return GNUNET_YES;
929 default:
930 return GNUNET_SYSERR;
931 }
932}