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