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.c602
1 files changed, 602 insertions, 0 deletions
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
new file mode 100644
index 000000000..fdab60eef
--- /dev/null
+++ b/src/messenger/messenger_api_message.c
@@ -0,0 +1,602 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 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 struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message);
73
74 GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message));
75
76 switch (message->header.kind)
77 {
78 case GNUNET_MESSENGER_KIND_NAME:
79 copy->body.name.name = GNUNET_strdup(message->body.name.name);
80 break;
81 case GNUNET_MESSENGER_KIND_TEXT:
82 copy->body.text.text = GNUNET_strdup(message->body.text.text);
83 break;
84 case GNUNET_MESSENGER_KIND_FILE:
85 copy->body.file.uri = GNUNET_strdup(message->body.file.uri);
86 break;
87 case GNUNET_MESSENGER_KIND_PRIVATE:
88 copy->body.private.data = copy->body.private.length ? GNUNET_malloc(copy->body.private.length) : NULL;
89
90 if (copy->body.private.data)
91 {
92 GNUNET_memcpy(copy->body.private.data, message->body.private.data, copy->body.private.length);
93 }
94
95 break;
96 default:
97 break;
98 }
99
100 return copy;
101}
102
103static void
104destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind, struct GNUNET_MESSENGER_MessageBody *body)
105{
106 switch (kind)
107 {
108 case GNUNET_MESSENGER_KIND_NAME:
109 GNUNET_free(body->name.name);
110 break;
111 case GNUNET_MESSENGER_KIND_TEXT:
112 GNUNET_free(body->text.text);
113 break;
114 case GNUNET_MESSENGER_KIND_FILE:
115 GNUNET_free(body->file.uri);
116 break;
117 case GNUNET_MESSENGER_KIND_PRIVATE:
118 GNUNET_free(body->private.data);
119 break;
120 default:
121 break;
122 }
123}
124
125void
126destroy_message (struct GNUNET_MESSENGER_Message *message)
127{
128 destroy_message_body (message->header.kind, &(message->body));
129
130 GNUNET_free(message);
131}
132
133static void
134fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened)
135{
136 shortened->kind = message->header.kind;
137
138 GNUNET_memcpy(&(shortened->body), &(message->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
139}
140
141static void
142unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened, struct GNUNET_MESSENGER_Message *message)
143{
144 destroy_message_body (message->header.kind, &(message->body));
145
146 message->header.kind = shortened->kind;
147
148 GNUNET_memcpy(&(message->body), &(shortened->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
149}
150
151#define member_size(type, member) sizeof(((type*) NULL)->member)
152
153static uint16_t
154get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
155{
156 uint16_t length = 0;
157
158 switch (kind)
159 {
160 case GNUNET_MESSENGER_KIND_INFO:
161 length += member_size(struct GNUNET_MESSENGER_Message, body.info.host_key);
162 length += member_size(struct GNUNET_MESSENGER_Message, body.info.unique_id);
163 break;
164 case GNUNET_MESSENGER_KIND_JOIN:
165 length += member_size(struct GNUNET_MESSENGER_Message, body.join.key);
166 break;
167 case GNUNET_MESSENGER_KIND_LEAVE:
168 break;
169 case GNUNET_MESSENGER_KIND_NAME:
170 break;
171 case GNUNET_MESSENGER_KIND_KEY:
172 length += member_size(struct GNUNET_MESSENGER_Message, body.key.key);
173 break;
174 case GNUNET_MESSENGER_KIND_PEER:
175 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer);
176 break;
177 case GNUNET_MESSENGER_KIND_ID:
178 length += member_size(struct GNUNET_MESSENGER_Message, body.id.id);
179 break;
180 case GNUNET_MESSENGER_KIND_MISS:
181 length += member_size(struct GNUNET_MESSENGER_Message, body.miss.peer);
182 break;
183 case GNUNET_MESSENGER_KIND_MERGE:
184 length += member_size(struct GNUNET_MESSENGER_Message, body.merge.previous);
185 break;
186 case GNUNET_MESSENGER_KIND_REQUEST:
187 length += member_size(struct GNUNET_MESSENGER_Message, body.request.hash);
188 break;
189 case GNUNET_MESSENGER_KIND_INVITE:
190 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.door);
191 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.key);
192 break;
193 case GNUNET_MESSENGER_KIND_TEXT:
194 break;
195 case GNUNET_MESSENGER_KIND_FILE:
196 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key);
197 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash);
198 length += NAME_MAX;
199 break;
200 case GNUNET_MESSENGER_KIND_PRIVATE:
201 length += member_size(struct GNUNET_MESSENGER_Message, body.private.key);
202 break;
203 default:
204 break;
205 }
206
207 return length;
208}
209
210uint16_t
211get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
212{
213 uint16_t length = 0;
214
215 length += member_size(struct GNUNET_MESSENGER_Message, header.signature);
216 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
217 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
218 length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
219 length += member_size(struct GNUNET_MESSENGER_Message, header.kind);
220
221 return length + get_message_body_kind_size (kind);
222}
223
224static uint16_t
225get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body)
226{
227 uint16_t length = 0;
228
229 switch (kind)
230 {
231 case GNUNET_MESSENGER_KIND_NAME:
232 length += (body->name.name? strlen (body->name.name) : 0);
233 break;
234 case GNUNET_MESSENGER_KIND_TEXT:
235 length += strlen (body->text.text);
236 break;
237 case GNUNET_MESSENGER_KIND_FILE:
238 length += strlen (body->file.uri);
239 break;
240 case GNUNET_MESSENGER_KIND_PRIVATE:
241 length += body->private.length;
242 break;
243 default:
244 break;
245 }
246
247 return length;
248}
249
250uint16_t
251get_message_size (const struct GNUNET_MESSENGER_Message *message)
252{
253 return get_message_kind_size (message->header.kind) + get_message_body_size (message->header.kind, &(message->body));
254}
255
256static uint16_t
257get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message)
258{
259 if (message)
260 return sizeof(message->kind) + get_message_body_kind_size (message->kind)
261 + get_message_body_size (message->kind, &(message->body));
262 else
263 return sizeof(message->kind);
264}
265
266#define min(x, y) (x < y? x : y)
267
268#define encode_step_ext(dst, offset, src, size) do { \
269 GNUNET_memcpy(dst + offset, src, size); \
270 offset += size; \
271} while (0)
272
273#define encode_step(dst, offset, src) do { \
274 encode_step_ext(dst, offset, src, sizeof(*src)); \
275} while(0)
276
277static void
278encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body,
279 uint16_t length, char *buffer, uint16_t offset)
280{
281 switch (kind)
282 {
283 case GNUNET_MESSENGER_KIND_INFO:
284 encode_step(buffer, offset, &(body->info.host_key));
285 encode_step(buffer, offset, &(body->info.unique_id));
286 break;
287 case GNUNET_MESSENGER_KIND_JOIN:
288 encode_step(buffer, offset, &(body->join.key));
289 break;
290 case GNUNET_MESSENGER_KIND_LEAVE:
291 break;
292 case GNUNET_MESSENGER_KIND_NAME:
293 if (body->name.name)
294 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
295 break;
296 case GNUNET_MESSENGER_KIND_KEY:
297 encode_step(buffer, offset, &(body->key.key));
298 break;
299 case GNUNET_MESSENGER_KIND_PEER:
300 encode_step(buffer, offset, &(body->peer.peer));
301 break;
302 case GNUNET_MESSENGER_KIND_ID:
303 encode_step(buffer, offset, &(body->id.id));
304 break;
305 case GNUNET_MESSENGER_KIND_MISS:
306 encode_step(buffer, offset, &(body->miss.peer));
307 break;
308 case GNUNET_MESSENGER_KIND_MERGE:
309 encode_step(buffer, offset, &(body->merge.previous));
310 break;
311 case GNUNET_MESSENGER_KIND_REQUEST:
312 encode_step(buffer, offset, &(body->request.hash));
313 break;
314 case GNUNET_MESSENGER_KIND_INVITE:
315 encode_step(buffer, offset, &(body->invite.door));
316 encode_step(buffer, offset, &(body->invite.key));
317 break;
318 case GNUNET_MESSENGER_KIND_TEXT:
319 encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text)));
320 break;
321 case GNUNET_MESSENGER_KIND_FILE:
322 encode_step(buffer, offset, &(body->file.key));
323 encode_step(buffer, offset, &(body->file.hash));
324 encode_step_ext(buffer, offset, body->file.name, NAME_MAX);
325 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
326 break;
327 case GNUNET_MESSENGER_KIND_PRIVATE:
328 encode_step(buffer, offset, &(body->private.key));
329 encode_step_ext(buffer, offset, body->private.data, min(length - offset, body->private.length));
330 break;
331 default:
332 break;
333 }
334}
335
336void
337encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer)
338{
339 uint16_t offset = 0;
340
341 encode_step(buffer, offset, &(message->header.signature));
342 encode_step(buffer, offset, &(message->header.timestamp));
343 encode_step(buffer, offset, &(message->header.sender_id));
344 encode_step(buffer, offset, &(message->header.previous));
345 encode_step(buffer, offset, &(message->header.kind));
346
347 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
348}
349
350static void
351encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer)
352{
353 uint16_t offset = 0;
354
355 encode_step(buffer, offset, &(message->kind));
356
357 encode_message_body (message->kind, &(message->body), length, buffer, offset);
358}
359
360#define decode_step_ext(src, offset, dst, size) do { \
361 GNUNET_memcpy(dst, src + offset, size); \
362 offset += size; \
363} while (0)
364
365#define decode_step(src, offset, dst) do { \
366 decode_step_ext(src, offset, dst, sizeof(*dst)); \
367} while (0)
368
369#define decode_step_malloc(src, offset, dst, size, zero) do { \
370 dst = GNUNET_malloc(size + zero); \
371 if (zero) dst[size] = 0; \
372 decode_step_ext(src, offset, dst, size); \
373} while (0)
374
375static void
376decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body,
377 uint16_t length, const char *buffer, uint16_t offset)
378{
379 switch (*kind)
380 {
381 case GNUNET_MESSENGER_KIND_INFO:
382 decode_step(buffer, offset, &(body->info.host_key));
383 decode_step(buffer, offset, &(body->info.unique_id));
384 break;
385 case GNUNET_MESSENGER_KIND_JOIN:
386 decode_step(buffer, offset, &(body->join.key));
387 break;
388 case GNUNET_MESSENGER_KIND_LEAVE:
389 break;
390 case GNUNET_MESSENGER_KIND_NAME:
391 if (length - offset > 0)
392 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
393 else
394 body->name.name = NULL;
395 break;
396 case GNUNET_MESSENGER_KIND_KEY:
397 decode_step(buffer, offset, &(body->key.key));
398 break;
399 case GNUNET_MESSENGER_KIND_PEER:
400 decode_step(buffer, offset, &(body->peer.peer));
401 break;
402 case GNUNET_MESSENGER_KIND_ID:
403 decode_step(buffer, offset, &(body->id.id));
404 break;
405 case GNUNET_MESSENGER_KIND_MISS:
406 decode_step(buffer, offset, &(body->miss.peer));
407 break;
408 case GNUNET_MESSENGER_KIND_MERGE:
409 decode_step(buffer, offset, &(body->merge.previous));
410 break;
411 case GNUNET_MESSENGER_KIND_REQUEST:
412 decode_step(buffer, offset, &(body->request.hash));
413 break;
414 case GNUNET_MESSENGER_KIND_INVITE:
415 decode_step(buffer, offset, &(body->invite.door));
416 decode_step(buffer, offset, &(body->invite.key));
417 break;
418 case GNUNET_MESSENGER_KIND_TEXT:
419 decode_step_malloc(buffer, offset, body->text.text, length - offset, 1);
420 break;
421 case GNUNET_MESSENGER_KIND_FILE:
422 decode_step(buffer, offset, &(body->file.key));
423 decode_step(buffer, offset, &(body->file.hash));
424 decode_step_ext(buffer, offset, body->file.name, NAME_MAX);
425 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
426 break;
427 case GNUNET_MESSENGER_KIND_PRIVATE:
428 decode_step(buffer, offset, &(body->private.key));
429
430 body->private.length = (length - offset);
431 decode_step_malloc(buffer, offset, body->private.data, length - offset, 0);
432 break;
433 default:
434 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
435 break;
436 }
437}
438
439int
440decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer)
441{
442 uint16_t offset = 0;
443
444 if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN))
445 return GNUNET_NO;
446
447 decode_step(buffer, offset, &(message->header.signature));
448 decode_step(buffer, offset, &(message->header.timestamp));
449 decode_step(buffer, offset, &(message->header.sender_id));
450 decode_step(buffer, offset, &(message->header.previous));
451 decode_step(buffer, offset, &(message->header.kind));
452
453 if (length < get_message_kind_size (message->header.kind))
454 return GNUNET_NO;
455
456 decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
457
458 return GNUNET_YES;
459}
460
461static int
462decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer)
463{
464 uint16_t offset = 0;
465
466 if (length < get_short_message_size (NULL))
467 return GNUNET_NO;
468
469 decode_step(buffer, offset, &(message->kind));
470
471 if (length < get_short_message_size (message))
472 return GNUNET_NO;
473
474 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
475
476 return GNUNET_YES;
477}
478
479void
480hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash)
481{
482 GNUNET_CRYPTO_hash (buffer + sizeof(struct GNUNET_CRYPTO_EcdsaSignature),
483 length - sizeof(struct GNUNET_CRYPTO_EcdsaSignature), hash);
484}
485
486void
487sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
488 const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego)
489{
490 struct GNUNET_MESSENGER_MessageSignature signature;
491
492 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
493 signature.purpose.size = htonl (sizeof(signature));
494
495 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
496
497 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
498 GNUNET_memcpy(buffer, &(message->header.signature), sizeof(struct GNUNET_CRYPTO_EcdsaSignature));
499}
500
501int
502verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
503 const struct GNUNET_IDENTITY_PublicKey *key)
504{
505 struct GNUNET_MESSENGER_MessageSignature signature;
506
507 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
508 signature.purpose.size = htonl (sizeof(signature));
509
510 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
511
512 return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
513 &(message->header.signature), key);
514}
515
516int
517encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key)
518{
519 struct GNUNET_MESSENGER_ShortMessage shortened;
520
521 fold_short_message (message, &shortened);
522
523 const uint16_t length = get_short_message_size (&shortened);
524
525 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
526 message->body.private.data = GNUNET_malloc(length);
527
528 encode_short_message (&shortened, length, message->body.private.data);
529
530 if (GNUNET_IDENTITY_encrypt (message->body.private.data, length, key, &(message->body.private.key),
531 message->body.private.data)
532 == length)
533 {
534 destroy_message_body (shortened.kind, &(shortened.body));
535 return GNUNET_YES;
536 }
537 else
538 {
539 unfold_short_message (&shortened, message);
540 return GNUNET_NO;
541 }
542}
543
544int
545decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key)
546{
547 if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data,
548 message->body.private.length, key,
549 &(message->body.private.key),
550 message->body.private.data))
551 return GNUNET_NO;
552
553 struct GNUNET_MESSENGER_ShortMessage shortened;
554
555 if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data))
556 return GNUNET_NO;
557
558 unfold_short_message (&shortened, message);
559 return GNUNET_YES;
560}
561
562struct GNUNET_MQ_Envelope*
563pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
564 const struct GNUNET_MESSENGER_Ego *ego, int mode)
565{
566 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message: %u\n", message->header.kind);
567
568 struct GNUNET_MessageHeader *header;
569
570 uint16_t length = get_message_size (message);
571
572 struct GNUNET_MQ_Envelope *env;
573 char *buffer;
574
575 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
576 {
577 env = GNUNET_MQ_msg_extra(header, length, GNUNET_MESSAGE_TYPE_CADET_CLI);
578
579 buffer = (char*) &(header[1]);
580 }
581 else
582 {
583 env = NULL;
584
585 buffer = GNUNET_malloc(length);
586 }
587
588 encode_message (message, length, buffer);
589
590 if (hash)
591 {
592 hash_message (length, buffer, hash);
593
594 if (ego)
595 sign_message (message, length, buffer, hash, ego);
596 }
597
598 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
599 GNUNET_free(buffer);
600
601 return env;
602}