diff options
Diffstat (limited to 'src/messenger/messenger_api_message.c')
-rw-r--r-- | src/messenger/messenger_api_message.c | 602 |
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 | |||
28 | struct GNUNET_MESSENGER_MessageSignature | ||
29 | { | ||
30 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
31 | struct GNUNET_HashCode hash; | ||
32 | }; | ||
33 | |||
34 | struct GNUNET_MESSENGER_ShortMessage | ||
35 | { | ||
36 | enum GNUNET_MESSENGER_MessageKind kind; | ||
37 | struct GNUNET_MESSENGER_MessageBody body; | ||
38 | }; | ||
39 | |||
40 | struct GNUNET_MESSENGER_Message* | ||
41 | create_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 | |||
69 | struct GNUNET_MESSENGER_Message* | ||
70 | copy_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 | |||
103 | static void | ||
104 | destroy_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 | |||
125 | void | ||
126 | destroy_message (struct GNUNET_MESSENGER_Message *message) | ||
127 | { | ||
128 | destroy_message_body (message->header.kind, &(message->body)); | ||
129 | |||
130 | GNUNET_free(message); | ||
131 | } | ||
132 | |||
133 | static void | ||
134 | fold_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 | |||
141 | static void | ||
142 | unfold_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 | |||
153 | static uint16_t | ||
154 | get_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 | |||
210 | uint16_t | ||
211 | get_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 | |||
224 | static uint16_t | ||
225 | get_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 | |||
250 | uint16_t | ||
251 | get_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 | |||
256 | static uint16_t | ||
257 | get_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 | |||
277 | static void | ||
278 | encode_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 | |||
336 | void | ||
337 | encode_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 | |||
350 | static void | ||
351 | encode_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 | |||
375 | static void | ||
376 | decode_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 | |||
439 | int | ||
440 | decode_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 | |||
461 | static int | ||
462 | decode_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 | |||
479 | void | ||
480 | hash_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 | |||
486 | void | ||
487 | sign_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 | |||
501 | int | ||
502 | verify_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 | |||
516 | int | ||
517 | encrypt_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 | |||
544 | int | ||
545 | decrypt_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 | |||
562 | struct GNUNET_MQ_Envelope* | ||
563 | pack_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 | } | ||