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.c871
1 files changed, 0 insertions, 871 deletions
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
deleted file mode 100644
index d65b80576..000000000
--- a/src/messenger/messenger_api_message.c
+++ /dev/null
@@ -1,871 +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.private.length = 0;
60 message->body.private.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.private.data = copy->body.private.length ? GNUNET_malloc(copy->body.private.length) : NULL;
91
92 if (copy->body.private.data)
93 {
94 GNUNET_memcpy(copy->body.private.data, message->body.private.data, copy->body.private.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->private.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.private.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->private.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 switch (kind)
377 {
378 case GNUNET_MESSENGER_KIND_INFO:
379 encode_step_key(buffer, offset, &(body->info.host_key), length);
380 encode_step(buffer, offset, &(body->info.messenger_version));
381 break;
382 case GNUNET_MESSENGER_KIND_JOIN:
383 encode_step_key(buffer, offset, &(body->join.key), length);
384 break;
385 case GNUNET_MESSENGER_KIND_NAME:
386 if (body->name.name)
387 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
388 break;
389 case GNUNET_MESSENGER_KIND_KEY:
390 encode_step_key(buffer, offset, &(body->key.key), length);
391 break;
392 case GNUNET_MESSENGER_KIND_PEER:
393 encode_step(buffer, offset, &(body->peer.peer));
394 break;
395 case GNUNET_MESSENGER_KIND_ID:
396 encode_step(buffer, offset, &(body->id.id));
397 break;
398 case GNUNET_MESSENGER_KIND_MISS:
399 encode_step(buffer, offset, &(body->miss.peer));
400 break;
401 case GNUNET_MESSENGER_KIND_MERGE:
402 encode_step(buffer, offset, &(body->merge.previous));
403 break;
404 case GNUNET_MESSENGER_KIND_REQUEST:
405 encode_step(buffer, offset, &(body->request.hash));
406 break;
407 case GNUNET_MESSENGER_KIND_INVITE:
408 encode_step(buffer, offset, &(body->invite.door));
409 encode_step(buffer, offset, &(body->invite.key));
410 break;
411 case GNUNET_MESSENGER_KIND_TEXT:
412 encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text)));
413 break;
414 case GNUNET_MESSENGER_KIND_FILE:
415 encode_step(buffer, offset, &(body->file.key));
416 encode_step(buffer, offset, &(body->file.hash));
417 encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
418 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
419 break;
420 case GNUNET_MESSENGER_KIND_PRIVATE:
421 encode_step(buffer, offset, &(body->private.key));
422 encode_step_ext(buffer, offset, body->private.data, min(length - offset, body->private.length));
423 break;
424 default:
425 break;
426 }
427
428 if (offset >= length)
429 return;
430
431 const uint16_t padding = length - offset;
432 const uint16_t used_padding = sizeof(padding) + sizeof(char);
433
434 GNUNET_assert(padding >= used_padding);
435
436 buffer[offset++] = '\0';
437
438 if (padding > used_padding)
439 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding);
440
441 GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
442}
443
444void
445encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
446 int include_signature)
447{
448 GNUNET_assert((message) && (buffer));
449
450 uint16_t offset = 0;
451
452 if (GNUNET_YES == include_signature)
453 encode_step_signature(buffer, offset, &(message->header.signature), length);
454
455 const kind_t kind = (kind_t) message->header.kind;
456
457 encode_step(buffer, offset, &(message->header.timestamp));
458 encode_step(buffer, offset, &(message->header.sender_id));
459 encode_step(buffer, offset, &(message->header.previous));
460 encode_step(buffer, offset, &kind);
461
462 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
463}
464
465static void
466encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer)
467{
468 struct GNUNET_HashCode hash;
469 uint16_t offset = sizeof(hash);
470
471 const kind_t kind = (kind_t) message->kind;
472
473 encode_step(buffer, offset, &kind);
474
475 encode_message_body (message->kind, &(message->body), length, buffer, offset);
476
477 GNUNET_CRYPTO_hash(
478 buffer + sizeof(hash),
479 length - sizeof(hash),
480 &hash
481 );
482
483 GNUNET_memcpy(buffer, &hash, sizeof(hash));
484}
485
486#define decode_step_ext(src, offset, dst, size) do { \
487 GNUNET_memcpy(dst, src + offset, size); \
488 offset += size; \
489} while (0)
490
491#define decode_step(src, offset, dst) do { \
492 decode_step_ext(src, offset, dst, sizeof(*dst)); \
493} while (0)
494
495#define decode_step_malloc(src, offset, dst, size, zero) do { \
496 dst = GNUNET_malloc(size + zero); \
497 if (zero) dst[size] = 0; \
498 decode_step_ext(src, offset, dst, size); \
499} while (0)
500
501#define decode_step_key(src, offset, dst, length) do { \
502 ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \
503 dst, src + offset, length - offset \
504 ); \
505 if (result < 0) \
506 GNUNET_break(0); \
507 else \
508 offset += result; \
509} while (0)
510
511static uint16_t
512decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body,
513 uint16_t length, const char *buffer, uint16_t offset)
514{
515 uint16_t padding = 0;
516
517 GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
518
519 if (padding > length - offset)
520 padding = 0;
521
522 const uint16_t end_zero = length - padding;
523
524 if ((padding) && (buffer[end_zero] != '\0'))
525 padding = 0;
526
527 length -= padding;
528
529 switch (*kind)
530 {
531 case GNUNET_MESSENGER_KIND_INFO: {
532 decode_step_key(buffer, offset, &(body->info.host_key), length);
533 decode_step(buffer, offset, &(body->info.messenger_version));
534 break;
535 } case GNUNET_MESSENGER_KIND_JOIN: {
536 decode_step_key(buffer, offset, &(body->join.key), length);
537 break;
538 } case GNUNET_MESSENGER_KIND_NAME:
539 if (length - offset > 0)
540 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
541 else
542 body->name.name = NULL;
543 break;
544 case GNUNET_MESSENGER_KIND_KEY:
545 decode_step_key(buffer, offset, &(body->key.key), length);
546 break;
547 case GNUNET_MESSENGER_KIND_PEER:
548 decode_step(buffer, offset, &(body->peer.peer));
549 break;
550 case GNUNET_MESSENGER_KIND_ID:
551 decode_step(buffer, offset, &(body->id.id));
552 break;
553 case GNUNET_MESSENGER_KIND_MISS:
554 decode_step(buffer, offset, &(body->miss.peer));
555 break;
556 case GNUNET_MESSENGER_KIND_MERGE:
557 decode_step(buffer, offset, &(body->merge.previous));
558 break;
559 case GNUNET_MESSENGER_KIND_REQUEST:
560 decode_step(buffer, offset, &(body->request.hash));
561 break;
562 case GNUNET_MESSENGER_KIND_INVITE:
563 decode_step(buffer, offset, &(body->invite.door));
564 decode_step(buffer, offset, &(body->invite.key));
565 break;
566 case GNUNET_MESSENGER_KIND_TEXT:
567 decode_step_malloc(buffer, offset, body->text.text, length - offset, 1);
568 break;
569 case GNUNET_MESSENGER_KIND_FILE:
570 decode_step(buffer, offset, &(body->file.key));
571 decode_step(buffer, offset, &(body->file.hash));
572 decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
573 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
574 break;
575 case GNUNET_MESSENGER_KIND_PRIVATE:
576 decode_step(buffer, offset, &(body->private.key));
577
578 body->private.length = (length - offset);
579 decode_step_malloc(buffer, offset, body->private.data, length - offset, 0);
580 break;
581 default:
582 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
583 break;
584 }
585
586 return padding;
587}
588
589int
590decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
591 int include_signature, uint16_t *padding)
592{
593 GNUNET_assert((message) && (buffer) && (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN)));
594
595 uint16_t offset = 0;
596
597 if (GNUNET_YES == include_signature)
598 {
599 ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
600 &(message->header.signature), buffer, length - offset
601 );
602
603 if (result < 0)
604 return GNUNET_NO;
605 else
606 offset += result;
607 }
608
609 const uint16_t count = length - offset;
610
611 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN))
612 return GNUNET_NO;
613
614 kind_t kind;
615
616 decode_step(buffer, offset, &(message->header.timestamp));
617 decode_step(buffer, offset, &(message->header.sender_id));
618 decode_step(buffer, offset, &(message->header.previous));
619 decode_step(buffer, offset, &kind);
620
621 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) kind;
622
623 if (count < get_message_kind_size (message->header.kind))
624 return GNUNET_NO;
625
626 const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
627
628 if (padding)
629 *padding = result;
630
631 return GNUNET_YES;
632}
633
634static int
635decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer)
636{
637 struct GNUNET_HashCode expected, hash;
638 uint16_t offset = sizeof(hash);
639
640 if (length < get_short_message_size (NULL, GNUNET_NO))
641 return GNUNET_NO;
642
643 GNUNET_memcpy(&hash, buffer, sizeof(hash));
644
645 GNUNET_CRYPTO_hash(
646 buffer + sizeof(hash),
647 length - sizeof(hash),
648 &expected
649 );
650
651 if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
652 return GNUNET_NO;
653
654 kind_t kind;
655
656 decode_step(buffer, offset, &kind);
657
658 message->kind = (enum GNUNET_MESSENGER_MessageKind) kind;
659
660 if (length < get_short_message_size (message, GNUNET_NO))
661 return GNUNET_NO;
662
663 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
664
665 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
666 return GNUNET_NO;
667
668 return GNUNET_YES;
669}
670
671void
672hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
673 struct GNUNET_HashCode *hash)
674{
675 GNUNET_assert((message) && (buffer) && (hash));
676
677 const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
678 &(message->header.signature)
679 );
680
681 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
682}
683
684void
685sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
686 const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego)
687{
688 GNUNET_assert((message) && (buffer) && (hash) && (ego));
689
690 struct GNUNET_MESSENGER_MessageSignature signature;
691
692 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
693 signature.purpose.size = htonl (sizeof(signature));
694
695 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
696 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
697
698 uint16_t offset = 0;
699 encode_step_signature(buffer, offset, &(message->header.signature), length);
700}
701
702int
703verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
704 const struct GNUNET_IDENTITY_PublicKey *key)
705{
706 GNUNET_assert((message) && (hash) && (key));
707
708 if (ntohl (key->type) != ntohl (message->header.signature.type))
709 return GNUNET_SYSERR;
710
711 struct GNUNET_MESSENGER_MessageSignature signature;
712
713 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
714 signature.purpose.size = htonl (sizeof(signature));
715
716 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
717
718 return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
719 &(message->header.signature), key);
720}
721
722int
723encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key)
724{
725 GNUNET_assert((message) && (key));
726
727 struct GNUNET_MESSENGER_ShortMessage shortened;
728
729 fold_short_message (message, &shortened);
730
731 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
732 const uint16_t padded_length = calc_padded_length(length);
733
734 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
735 message->body.private.data = GNUNET_malloc(padded_length);
736 message->body.private.length = padded_length;
737
738 encode_short_message (&shortened, padded_length, message->body.private.data);
739
740 if (padded_length == GNUNET_IDENTITY_encrypt (message->body.private.data, padded_length, key,
741 &(message->body.private.key),
742 message->body.private.data))
743 {
744 destroy_message_body (shortened.kind, &(shortened.body));
745 return GNUNET_YES;
746 }
747 else
748 {
749 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
750
751 unfold_short_message (&shortened, message);
752 return GNUNET_NO;
753 }
754}
755
756int
757decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key)
758{
759 GNUNET_assert((message) && (key));
760
761 if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data, message->body.private.length,
762 key, &(message->body.private.key),
763 message->body.private.data))
764 {
765 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
766
767 return GNUNET_NO;
768 }
769
770 struct GNUNET_MESSENGER_ShortMessage shortened;
771
772 if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data))
773 {
774 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n");
775
776 return GNUNET_NO;
777 }
778
779 unfold_short_message (&shortened, message);
780
781 return GNUNET_YES;
782}
783
784struct GNUNET_MQ_Envelope*
785pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
786 const struct GNUNET_MESSENGER_Ego *ego, int mode)
787{
788 GNUNET_assert(message);
789
790 if (ego)
791 message->header.signature.type = ego->priv.type;
792
793 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n",
794 message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
795
796 struct GNUNET_MessageHeader *header;
797
798 const uint16_t length = get_message_size (message, GNUNET_YES);
799 const uint16_t padded_length = calc_padded_length(length);
800
801 struct GNUNET_MQ_Envelope *env;
802 char *buffer;
803
804 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
805 {
806 env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI);
807
808 buffer = (char*) &(header[1]);
809 }
810 else
811 {
812 env = NULL;
813
814 buffer = GNUNET_malloc(padded_length);
815 }
816
817 encode_message (message, padded_length, buffer, GNUNET_YES);
818
819 if (hash)
820 {
821 hash_message (message, length, buffer, hash);
822
823 if (ego)
824 sign_message (message, length, buffer, hash, ego);
825 }
826
827 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
828 GNUNET_free(buffer);
829
830 return env;
831}
832
833int
834filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
835{
836 switch (message->header.kind)
837 {
838 case GNUNET_MESSENGER_KIND_INFO:
839 return GNUNET_SYSERR; // Reserved for connection handling only!
840 case GNUNET_MESSENGER_KIND_JOIN:
841 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
842 case GNUNET_MESSENGER_KIND_LEAVE:
843 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
844 case GNUNET_MESSENGER_KIND_NAME:
845 return GNUNET_YES;
846 case GNUNET_MESSENGER_KIND_KEY:
847 return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
848 case GNUNET_MESSENGER_KIND_PEER:
849 return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
850 case GNUNET_MESSENGER_KIND_ID:
851 return GNUNET_SYSERR; // Reserved for member id handling only!
852 case GNUNET_MESSENGER_KIND_MISS:
853 return GNUNET_SYSERR; // Reserved for connection handling only!
854 case GNUNET_MESSENGER_KIND_MERGE:
855 return GNUNET_YES;
856 case GNUNET_MESSENGER_KIND_REQUEST:
857 return GNUNET_YES;
858 case GNUNET_MESSENGER_KIND_INVITE:
859 return GNUNET_YES;
860 case GNUNET_MESSENGER_KIND_TEXT:
861 return GNUNET_YES;
862 case GNUNET_MESSENGER_KIND_FILE:
863 return GNUNET_YES;
864 case GNUNET_MESSENGER_KIND_PRIVATE:
865 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
866 case GNUNET_MESSENGER_KIND_DELETE:
867 return GNUNET_YES;
868 default:
869 return GNUNET_SYSERR;
870 }
871}