1 /*
2 * omemo.c
3 * vim: expandtab:ts=4:sts=4:sw=4
4 *
5 * Copyright (C) 2019 Paul Fariello <paul@fariello.eu>
6 * Copyright (C) 2019 - 2021 Michael Vetter <jubalh@iodoru.org>
7 *
8 * This file is part of Profanity.
9 *
10 * Profanity is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Profanity is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Profanity. If not, see <https://www.gnu.org/licenses/>.
22 *
23 * In addition, as a special exception, the copyright holders give permission to
24 * link the code of portions of this program with the OpenSSL library under
25 * certain conditions as described in each individual source file, and
26 * distribute linked combinations including the two.
27 *
28 * You must obey the GNU General Public License in all respects for all of the
29 * code used other than OpenSSL. If you modify file(s) with this exception, you
30 * may extend this exception to your version of the file(s), but you are not
31 * obligated to do so. If you do not wish to do so, delete this exception
32 * statement from your version. If you delete this exception statement from all
33 * source files in the program, then also delete it here.
34 *
35 */
36 #include "config.h"
37
38 #include <sys/time.h>
39 #include <sys/stat.h>
40
41 #include <assert.h>
42 #include <errno.h>
43 #include <glib.h>
44 #include <pthread.h>
45 #include <signal/key_helper.h>
46 #include <signal/protocol.h>
47 #include <signal/signal_protocol.h>
48 #include <signal/session_builder.h>
49 #include <signal/session_cipher.h>
50
51 #include "config/account.h"
52 #include "config/files.h"
53 #include "config/preferences.h"
54 #include "log.h"
55 #include "omemo/crypto.h"
56 #include "omemo/omemo.h"
57 #include "omemo/store.h"
58 #include "ui/ui.h"
59 #include "ui/window_list.h"
60 #include "xmpp/connection.h"
61 #include "xmpp/muc.h"
62 #include "xmpp/omemo.h"
63 #include "xmpp/roster_list.h"
64 #include "xmpp/xmpp.h"
65
66 #define AESGCM_URL_NONCE_LEN (2 * OMEMO_AESGCM_NONCE_LENGTH)
67 #define AESGCM_URL_KEY_LEN (2 * OMEMO_AESGCM_KEY_LENGTH)
68
69 static gboolean loaded;
70
71 static void _generate_pre_keys(int count);
72 static void _generate_signed_pre_key(void);
73 static gboolean _load_identity(void);
74 static void _load_trust(void);
75 static void _load_sessions(void);
76 static void _load_known_devices(void);
77 static void _lock(void* user_data);
78 static void _unlock(void* user_data);
79 static void _omemo_log(int level, const char* message, size_t len, void* user_data);
80 static gboolean _handle_own_device_list(const char* const jid, GList* device_list);
81 static gboolean _handle_device_list_start_session(const char* const jid, GList* device_list);
82 static char* _omemo_fingerprint(ec_public_key* identity, gboolean formatted);
83 static unsigned char* _omemo_fingerprint_decode(const char* const fingerprint, size_t* len);
84 static char* _omemo_unformat_fingerprint(const char* const fingerprint_formatted);
85 static void _cache_device_identity(const char* const jid, uint32_t device_id, ec_public_key* identity);
86 static void _g_hash_table_free(GHashTable* hash_table);
87
88 typedef gboolean (*OmemoDeviceListHandler)(const char* const jid, GList* device_list);
89
90 struct omemo_context_t
91 {
92 pthread_mutexattr_t attr;
93 pthread_mutex_t lock;
94 signal_context* signal;
95 uint32_t device_id;
96 GHashTable* device_list;
97 GHashTable* device_list_handler;
98 ratchet_identity_key_pair* identity_key_pair;
99 uint32_t registration_id;
100 uint32_t signed_pre_key_id;
101 signal_protocol_store_context* store;
102 GHashTable* session_store;
103 GHashTable* pre_key_store;
104 GHashTable* signed_pre_key_store;
105 identity_key_store_t identity_key_store;
106 GString* identity_filename;
107 GKeyFile* identity_keyfile;
108 GString* trust_filename;
109 GKeyFile* trust_keyfile;
110 GString* sessions_filename;
111 GKeyFile* sessions_keyfile;
112 GHashTable* known_devices;
113 GString* known_devices_filename;
114 GKeyFile* known_devices_keyfile;
115 GHashTable* fingerprint_ac;
116 };
117
118 static omemo_context omemo_ctx;
119
120 void
omemo_init(void)121 omemo_init(void)
122 {
123 log_info("[OMEMO] initialising");
124 if (omemo_crypto_init() != 0) {
125 cons_show("Error initializing OMEMO crypto: gcry_check_version() failed");
126 }
127
128 pthread_mutexattr_init(&omemo_ctx.attr);
129 pthread_mutexattr_settype(&omemo_ctx.attr, PTHREAD_MUTEX_RECURSIVE);
130 pthread_mutex_init(&omemo_ctx.lock, &omemo_ctx.attr);
131
132 omemo_ctx.fingerprint_ac = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)autocomplete_free);
133 }
134
135 void
omemo_close(void)136 omemo_close(void)
137 {
138 if (omemo_ctx.fingerprint_ac) {
139 g_hash_table_destroy(omemo_ctx.fingerprint_ac);
140 omemo_ctx.fingerprint_ac = NULL;
141 }
142 }
143
144 void
omemo_on_connect(ProfAccount * account)145 omemo_on_connect(ProfAccount* account)
146 {
147 GError* error = NULL;
148
149 if (signal_context_create(&omemo_ctx.signal, &omemo_ctx) != 0) {
150 cons_show("Error initializing OMEMO context");
151 return;
152 }
153
154 if (signal_context_set_log_function(omemo_ctx.signal, _omemo_log) != 0) {
155 cons_show("Error initializing OMEMO log");
156 }
157
158 signal_crypto_provider crypto_provider = {
159 .random_func = omemo_random_func,
160 .hmac_sha256_init_func = omemo_hmac_sha256_init_func,
161 .hmac_sha256_update_func = omemo_hmac_sha256_update_func,
162 .hmac_sha256_final_func = omemo_hmac_sha256_final_func,
163 .hmac_sha256_cleanup_func = omemo_hmac_sha256_cleanup_func,
164 .sha512_digest_init_func = omemo_sha512_digest_init_func,
165 .sha512_digest_update_func = omemo_sha512_digest_update_func,
166 .sha512_digest_final_func = omemo_sha512_digest_final_func,
167 .sha512_digest_cleanup_func = omemo_sha512_digest_cleanup_func,
168 .encrypt_func = omemo_encrypt_func,
169 .decrypt_func = omemo_decrypt_func,
170 .user_data = NULL
171 };
172
173 if (signal_context_set_crypto_provider(omemo_ctx.signal, &crypto_provider) != 0) {
174 cons_show("Error initializing OMEMO crypto: unable to set crypto provider");
175 return;
176 }
177
178 signal_context_set_locking_functions(omemo_ctx.signal, _lock, _unlock);
179
180 signal_protocol_store_context_create(&omemo_ctx.store, omemo_ctx.signal);
181
182 omemo_ctx.session_store = session_store_new();
183 signal_protocol_session_store session_store = {
184 .load_session_func = load_session,
185 .get_sub_device_sessions_func = get_sub_device_sessions,
186 .store_session_func = store_session,
187 .contains_session_func = contains_session,
188 .delete_session_func = delete_session,
189 .delete_all_sessions_func = delete_all_sessions,
190 .destroy_func = NULL,
191 .user_data = omemo_ctx.session_store
192 };
193 signal_protocol_store_context_set_session_store(omemo_ctx.store, &session_store);
194
195 omemo_ctx.pre_key_store = pre_key_store_new();
196 signal_protocol_pre_key_store pre_key_store = {
197 .load_pre_key = load_pre_key,
198 .store_pre_key = store_pre_key,
199 .contains_pre_key = contains_pre_key,
200 .remove_pre_key = remove_pre_key,
201 .destroy_func = NULL,
202 .user_data = omemo_ctx.pre_key_store
203 };
204 signal_protocol_store_context_set_pre_key_store(omemo_ctx.store, &pre_key_store);
205
206 omemo_ctx.signed_pre_key_store = signed_pre_key_store_new();
207 signal_protocol_signed_pre_key_store signed_pre_key_store = {
208 .load_signed_pre_key = load_signed_pre_key,
209 .store_signed_pre_key = store_signed_pre_key,
210 .contains_signed_pre_key = contains_signed_pre_key,
211 .remove_signed_pre_key = remove_signed_pre_key,
212 .destroy_func = NULL,
213 .user_data = omemo_ctx.signed_pre_key_store
214 };
215 signal_protocol_store_context_set_signed_pre_key_store(omemo_ctx.store, &signed_pre_key_store);
216
217 identity_key_store_new(&omemo_ctx.identity_key_store);
218 signal_protocol_identity_key_store identity_key_store = {
219 .get_identity_key_pair = get_identity_key_pair,
220 .get_local_registration_id = get_local_registration_id,
221 .save_identity = save_identity,
222 .is_trusted_identity = is_trusted_identity,
223 .destroy_func = NULL,
224 .user_data = &omemo_ctx.identity_key_store
225 };
226 signal_protocol_store_context_set_identity_key_store(omemo_ctx.store, &identity_key_store);
227
228 loaded = FALSE;
229 omemo_ctx.device_list = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)g_list_free);
230 omemo_ctx.device_list_handler = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
231 omemo_ctx.known_devices = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_g_hash_table_free);
232
233 gchar* omemo_dir = files_get_account_data_path(DIR_OMEMO, account->jid);
234
235 omemo_ctx.identity_filename = g_string_new(omemo_dir);
236 g_string_append(omemo_ctx.identity_filename, "/identity.txt");
237 omemo_ctx.trust_filename = g_string_new(omemo_dir);
238 g_string_append(omemo_ctx.trust_filename, "/trust.txt");
239 omemo_ctx.sessions_filename = g_string_new(omemo_dir);
240 g_string_append(omemo_ctx.sessions_filename, "/sessions.txt");
241 omemo_ctx.known_devices_filename = g_string_new(omemo_dir);
242 g_string_append(omemo_ctx.known_devices_filename, "/known_devices.txt");
243
244 errno = 0;
245 int res = g_mkdir_with_parents(omemo_dir, S_IRWXU);
246 if (res == -1) {
247 const char* errmsg = strerror(errno);
248 if (errmsg) {
249 log_error("[OMEMO] error creating directory: %s, %s", omemo_dir, errmsg);
250 } else {
251 log_error("[OMEMO] creating directory: %s", omemo_dir);
252 }
253 }
254
255 g_free(omemo_dir);
256
257 omemo_devicelist_subscribe();
258
259 omemo_ctx.identity_keyfile = g_key_file_new();
260 omemo_ctx.trust_keyfile = g_key_file_new();
261 omemo_ctx.sessions_keyfile = g_key_file_new();
262 omemo_ctx.known_devices_keyfile = g_key_file_new();
263
264 if (g_key_file_load_from_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
265 if (!_load_identity()) {
266 return;
267 }
268 } else if (error->code != G_FILE_ERROR_NOENT) {
269 log_warning("[OMEMO] error loading identity from: %s, %s", omemo_ctx.identity_filename->str, error->message);
270 g_error_free(error);
271 return;
272 }
273
274 error = NULL;
275 if (g_key_file_load_from_file(omemo_ctx.trust_keyfile, omemo_ctx.trust_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
276 _load_trust();
277 } else if (error->code != G_FILE_ERROR_NOENT) {
278 log_warning("[OMEMO] error loading trust from: %s, %s", omemo_ctx.trust_filename->str, error->message);
279 g_error_free(error);
280 } else {
281 log_warning("[OMEMO] no such file: %s", omemo_ctx.trust_filename->str);
282 g_error_free(error);
283 }
284
285 error = NULL;
286 if (g_key_file_load_from_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
287 _load_sessions();
288 } else if (error->code != G_FILE_ERROR_NOENT) {
289 log_warning("[OMEMO] error loading sessions from: %s, %s", omemo_ctx.sessions_filename->str, error->message);
290 g_error_free(error);
291 } else {
292 log_warning("[OMEMO] no such file: %s", omemo_ctx.trust_filename->str);
293 g_error_free(error);
294 }
295
296 error = NULL;
297 if (g_key_file_load_from_file(omemo_ctx.known_devices_keyfile, omemo_ctx.known_devices_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
298 _load_known_devices();
299 } else if (error->code != G_FILE_ERROR_NOENT) {
300 log_warning("[OMEMO] error loading known devices from: %s, %s", omemo_ctx.known_devices_filename->str, error->message);
301 g_error_free(error);
302 } else {
303 log_warning("[OMEMO] no such file: %s", omemo_ctx.trust_filename->str);
304 g_error_free(error);
305 }
306 }
307
308 void
omemo_on_disconnect(void)309 omemo_on_disconnect(void)
310 {
311 if (!loaded) {
312 return;
313 }
314
315 _g_hash_table_free(omemo_ctx.signed_pre_key_store);
316 _g_hash_table_free(omemo_ctx.pre_key_store);
317 _g_hash_table_free(omemo_ctx.device_list_handler);
318
319 g_string_free(omemo_ctx.identity_filename, TRUE);
320 g_key_file_free(omemo_ctx.identity_keyfile);
321 g_string_free(omemo_ctx.trust_filename, TRUE);
322 g_key_file_free(omemo_ctx.trust_keyfile);
323 g_string_free(omemo_ctx.sessions_filename, TRUE);
324 g_key_file_free(omemo_ctx.sessions_keyfile);
325 _g_hash_table_free(omemo_ctx.session_store);
326 g_string_free(omemo_ctx.known_devices_filename, TRUE);
327 g_key_file_free(omemo_ctx.known_devices_keyfile);
328 }
329
330 void
omemo_generate_crypto_materials(ProfAccount * account)331 omemo_generate_crypto_materials(ProfAccount* account)
332 {
333 if (loaded) {
334 return;
335 }
336
337 log_info("Generate long term OMEMO cryptography materials");
338
339 /* Device ID */
340 gcry_randomize(&omemo_ctx.device_id, 4, GCRY_VERY_STRONG_RANDOM);
341 omemo_ctx.device_id &= 0x7fffffff;
342 g_key_file_set_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_DEVICE_ID, omemo_ctx.device_id);
343 log_info("[OMEMO] device id: %d", omemo_ctx.device_id);
344
345 /* Identity key */
346 signal_protocol_key_helper_generate_identity_key_pair(&omemo_ctx.identity_key_pair, omemo_ctx.signal);
347
348 ec_public_key_serialize(&omemo_ctx.identity_key_store.public, ratchet_identity_key_pair_get_public(omemo_ctx.identity_key_pair));
349 char* identity_key_public = g_base64_encode(signal_buffer_data(omemo_ctx.identity_key_store.public), signal_buffer_len(omemo_ctx.identity_key_store.public));
350 g_key_file_set_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PUBLIC, identity_key_public);
351 g_free(identity_key_public);
352
353 ec_private_key_serialize(&omemo_ctx.identity_key_store.private, ratchet_identity_key_pair_get_private(omemo_ctx.identity_key_pair));
354 char* identity_key_private = g_base64_encode(signal_buffer_data(omemo_ctx.identity_key_store.private), signal_buffer_len(omemo_ctx.identity_key_store.private));
355 g_key_file_set_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PRIVATE, identity_key_private);
356 g_free(identity_key_private);
357
358 /* Registration ID */
359 signal_protocol_key_helper_generate_registration_id(&omemo_ctx.registration_id, 0, omemo_ctx.signal);
360 g_key_file_set_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_REGISTRATION_ID, omemo_ctx.registration_id);
361
362 /* Pre keys */
363 _generate_pre_keys(100);
364
365 /* Signed pre key */
366 _generate_signed_pre_key();
367
368 omemo_identity_keyfile_save();
369
370 loaded = TRUE;
371
372 omemo_publish_crypto_materials();
373 omemo_start_sessions();
374 }
375
376 void
omemo_publish_crypto_materials(void)377 omemo_publish_crypto_materials(void)
378 {
379 log_debug("[OMEMO] publish crypto materials");
380
381 if (loaded != TRUE) {
382 cons_show("OMEMO: cannot publish crypto materials before they are generated");
383 log_error("[OMEMO] cannot publish crypto materials before they are generated");
384 return;
385 }
386
387 char* barejid = connection_get_barejid();
388
389 /* Ensure we get our current device list, and it gets updated with our
390 * device_id */
391 g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), _handle_own_device_list);
392 omemo_devicelist_request(barejid);
393
394 omemo_bundle_publish(true);
395
396 free(barejid);
397 }
398
399 void
omemo_start_sessions(void)400 omemo_start_sessions(void)
401 {
402 GSList* contacts = roster_get_contacts(ROSTER_ORD_NAME);
403 if (contacts) {
404 GSList* curr;
405 for (curr = contacts; curr != NULL; curr = g_slist_next(curr)) {
406 PContact contact = curr->data;
407 const char* jid = p_contact_barejid(contact);
408 omemo_start_session(jid);
409 }
410 g_slist_free(contacts);
411 }
412 }
413
414 void
omemo_start_session(const char * const barejid)415 omemo_start_session(const char* const barejid)
416 {
417 if (omemo_loaded()) {
418 log_debug("[OMEMO] start session with %s", barejid);
419 GList* device_list = g_hash_table_lookup(omemo_ctx.device_list, barejid);
420 if (!device_list) {
421 log_debug("[OMEMO] missing device list for %s", barejid);
422 // Own devices are handled by _handle_own_device_list
423 // We won't add _handle_device_list_start_session for ourself
424 char* mybarejid = connection_get_barejid();
425 if( g_strcmp0(mybarejid, barejid ) != 0 ) {
426 g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), _handle_device_list_start_session);
427 }
428 free(mybarejid);
429 omemo_devicelist_request(barejid);
430 return;
431 }
432
433 GList* device_id;
434 for (device_id = device_list; device_id != NULL; device_id = device_id->next) {
435 omemo_bundle_request(barejid, GPOINTER_TO_INT(device_id->data), omemo_start_device_session_handle_bundle, free, strdup(barejid));
436 }
437 }
438 }
439
440 void
omemo_start_muc_sessions(const char * const roomjid)441 omemo_start_muc_sessions(const char* const roomjid)
442 {
443 GList* members = muc_members(roomjid);
444 GList* iter;
445 for (iter = members; iter != NULL; iter = iter->next) {
446 Jid* jid = jid_create(iter->data);
447 omemo_start_session(jid->barejid);
448 jid_destroy(jid);
449 }
450 g_list_free(members);
451 }
452
453 gboolean
omemo_loaded(void)454 omemo_loaded(void)
455 {
456 return loaded;
457 }
458
459 uint32_t
omemo_device_id(void)460 omemo_device_id(void)
461 {
462 return omemo_ctx.device_id;
463 }
464
465 void
omemo_identity_key(unsigned char ** output,size_t * length)466 omemo_identity_key(unsigned char** output, size_t* length)
467 {
468 signal_buffer* buffer = NULL;
469 ec_public_key_serialize(&buffer, ratchet_identity_key_pair_get_public(omemo_ctx.identity_key_pair));
470 *length = signal_buffer_len(buffer);
471 *output = malloc(*length);
472 memcpy(*output, signal_buffer_data(buffer), *length);
473 signal_buffer_free(buffer);
474 }
475
476 void
omemo_signed_prekey(unsigned char ** output,size_t * length)477 omemo_signed_prekey(unsigned char** output, size_t* length)
478 {
479 session_signed_pre_key* signed_pre_key;
480 signal_buffer* buffer = NULL;
481
482 if (signal_protocol_signed_pre_key_load_key(omemo_ctx.store, &signed_pre_key, omemo_ctx.signed_pre_key_id) != SG_SUCCESS) {
483 *output = NULL;
484 *length = 0;
485 return;
486 }
487
488 ec_public_key_serialize(&buffer, ec_key_pair_get_public(session_signed_pre_key_get_key_pair(signed_pre_key)));
489 SIGNAL_UNREF(signed_pre_key);
490 *length = signal_buffer_len(buffer);
491 *output = malloc(*length);
492 memcpy(*output, signal_buffer_data(buffer), *length);
493 signal_buffer_free(buffer);
494 }
495
496 void
omemo_signed_prekey_signature(unsigned char ** output,size_t * length)497 omemo_signed_prekey_signature(unsigned char** output, size_t* length)
498 {
499 session_signed_pre_key* signed_pre_key;
500
501 if (signal_protocol_signed_pre_key_load_key(omemo_ctx.store, &signed_pre_key, omemo_ctx.signed_pre_key_id) != SG_SUCCESS) {
502 *output = NULL;
503 *length = 0;
504 return;
505 }
506
507 *length = session_signed_pre_key_get_signature_len(signed_pre_key);
508 *output = malloc(*length);
509 memcpy(*output, session_signed_pre_key_get_signature(signed_pre_key), *length);
510 SIGNAL_UNREF(signed_pre_key);
511 }
512
513 void
omemo_prekeys(GList ** prekeys,GList ** ids,GList ** lengths)514 omemo_prekeys(GList** prekeys, GList** ids, GList** lengths)
515 {
516 GHashTableIter iter;
517 gpointer id;
518
519 g_hash_table_iter_init(&iter, omemo_ctx.pre_key_store);
520 while (g_hash_table_iter_next(&iter, &id, NULL)) {
521 session_pre_key* pre_key;
522 int ret;
523 ret = signal_protocol_pre_key_load_key(omemo_ctx.store, &pre_key, GPOINTER_TO_INT(id));
524 if (ret != SG_SUCCESS) {
525 continue;
526 }
527
528 signal_buffer* public_key;
529 ec_public_key_serialize(&public_key, ec_key_pair_get_public(session_pre_key_get_key_pair(pre_key)));
530 SIGNAL_UNREF(pre_key);
531 size_t length = signal_buffer_len(public_key);
532 unsigned char* prekey_value = malloc(length);
533 memcpy(prekey_value, signal_buffer_data(public_key), length);
534 signal_buffer_free(public_key);
535
536 *prekeys = g_list_append(*prekeys, prekey_value);
537 *ids = g_list_append(*ids, GINT_TO_POINTER(id));
538 *lengths = g_list_append(*lengths, GINT_TO_POINTER(length));
539 }
540 }
541
542 void
omemo_set_device_list(const char * const from,GList * device_list)543 omemo_set_device_list(const char* const from, GList* device_list)
544 {
545 log_debug("[OMEMO] Setting device list for %s", from);
546 Jid* jid;
547 if (from) {
548 jid = jid_create(from);
549 } else {
550 jid = jid_create(connection_get_fulljid());
551 }
552
553 g_hash_table_insert(omemo_ctx.device_list, strdup(jid->barejid), device_list);
554
555 OmemoDeviceListHandler handler = g_hash_table_lookup(omemo_ctx.device_list_handler, jid->barejid);
556 if (handler) {
557 gboolean keep = handler(jid->barejid, device_list);
558 if (!keep) {
559 g_hash_table_remove(omemo_ctx.device_list_handler, jid->barejid);
560 }
561 } else {
562 log_debug("[OMEMO] No Device List Handler for %s", from);
563 }
564
565 // OMEMO trustmode ToFu
566 if (g_strcmp0(prefs_get_string(PREF_OMEMO_TRUST_MODE), "firstusage") == 0) {
567 log_debug("[OMEMO] Checking firstusage state for %s", jid->barejid);
568 GHashTable* trusted = g_hash_table_lookup(omemo_ctx.identity_key_store.trusted, jid->barejid);
569 if (trusted) {
570 if (g_hash_table_size(trusted) > 0) {
571 log_debug("[OMEMO] Found trusted device for %s - skip firstusage", jid->barejid);
572 return;
573 }
574 } else {
575 if (device_list) {
576 cons_show("OMEMO: No trusted devices found for %s", jid->barejid);
577 GList* device_id;
578 for (device_id = device_list; device_id != NULL; device_id = device_id->next) {
579 GHashTable* known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid->barejid);
580 if (known_identities) {
581 GList* fp = NULL;
582 for (fp = g_hash_table_get_keys(known_identities); fp != NULL; fp = fp->next) {
583 if (device_id->data == g_hash_table_lookup(known_identities, fp->data)) {
584 cons_show("OMEMO: Adding firstusage trust for %s device %d - Fingerprint %s", jid->barejid, device_id->data, omemo_format_fingerprint(fp->data));
585 omemo_trust(jid->barejid, omemo_format_fingerprint(fp->data));
586 }
587 }
588 }
589 }
590 }
591 }
592 }
593 jid_destroy(jid);
594 }
595
596 GKeyFile*
omemo_identity_keyfile(void)597 omemo_identity_keyfile(void)
598 {
599 return omemo_ctx.identity_keyfile;
600 }
601
602 void
omemo_identity_keyfile_save(void)603 omemo_identity_keyfile_save(void)
604 {
605 GError* error = NULL;
606
607 if (!g_key_file_save_to_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, &error)) {
608 log_error("[OMEMO] error saving identity to: %s, %s", omemo_ctx.identity_filename->str, error->message);
609 }
610 }
611
612 GKeyFile*
omemo_trust_keyfile(void)613 omemo_trust_keyfile(void)
614 {
615 return omemo_ctx.trust_keyfile;
616 }
617
618 void
omemo_trust_keyfile_save(void)619 omemo_trust_keyfile_save(void)
620 {
621 GError* error = NULL;
622
623 if (!g_key_file_save_to_file(omemo_ctx.trust_keyfile, omemo_ctx.trust_filename->str, &error)) {
624 log_error("[OMEMO] error saving trust to: %s, %s", omemo_ctx.trust_filename->str, error->message);
625 }
626 }
627
628 GKeyFile*
omemo_sessions_keyfile(void)629 omemo_sessions_keyfile(void)
630 {
631 return omemo_ctx.sessions_keyfile;
632 }
633
634 void
omemo_sessions_keyfile_save(void)635 omemo_sessions_keyfile_save(void)
636 {
637 GError* error = NULL;
638
639 if (!g_key_file_save_to_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, &error)) {
640 log_error("[OMEMO] error saving sessions to: %s, %s", omemo_ctx.sessions_filename->str, error->message);
641 }
642 }
643
644 void
omemo_known_devices_keyfile_save(void)645 omemo_known_devices_keyfile_save(void)
646 {
647 GError* error = NULL;
648
649 if (!g_key_file_save_to_file(omemo_ctx.known_devices_keyfile, omemo_ctx.known_devices_filename->str, &error)) {
650 log_error("[OMEMO] error saving known devices to: %s, %s", omemo_ctx.known_devices_filename->str, error->message);
651 }
652 }
653
654 void
omemo_start_device_session(const char * const jid,uint32_t device_id,GList * prekeys,uint32_t signed_prekey_id,const unsigned char * const signed_prekey_raw,size_t signed_prekey_len,const unsigned char * const signature,size_t signature_len,const unsigned char * const identity_key_raw,size_t identity_key_len)655 omemo_start_device_session(const char* const jid, uint32_t device_id,
656 GList* prekeys, uint32_t signed_prekey_id,
657 const unsigned char* const signed_prekey_raw, size_t signed_prekey_len,
658 const unsigned char* const signature, size_t signature_len,
659 const unsigned char* const identity_key_raw, size_t identity_key_len)
660 {
661 log_debug("[OMEMO] Starting device session for %s with device %d", jid, device_id);
662 signal_protocol_address address = {
663 .name = jid,
664 .name_len = strlen(jid),
665 .device_id = device_id,
666 };
667
668 ec_public_key* identity_key;
669 curve_decode_point(&identity_key, identity_key_raw, identity_key_len, omemo_ctx.signal);
670 _cache_device_identity(jid, device_id, identity_key);
671
672 gboolean trusted = is_trusted_identity(&address, (uint8_t*)identity_key_raw, identity_key_len, &omemo_ctx.identity_key_store);
673 log_debug("[OMEMO] Trust %s (%d): %d", jid, device_id, trusted);
674
675 if ((g_strcmp0(prefs_get_string(PREF_OMEMO_TRUST_MODE), "blind") == 0) && !trusted) {
676 char* fp = _omemo_fingerprint(identity_key, TRUE);
677 cons_show("Blind trust for %s device %d (%s)", jid, device_id, fp);
678 omemo_trust(jid, fp);
679 free(fp);
680 trusted = TRUE;
681 }
682
683 if (!trusted) {
684 log_debug("[OMEMO] We don't trust device %d for %s\n", device_id,jid);
685 goto out;
686 }
687
688 if (!contains_session(&address, omemo_ctx.session_store)) {
689 log_debug("[OMEMO] There is no Session for %s ( %d) ,... building session.", address.name, address.device_id );
690 int res;
691 session_pre_key_bundle* bundle;
692 signal_protocol_address* address;
693
694 address = malloc(sizeof(signal_protocol_address));
695 address->name = strdup(jid);
696 address->name_len = strlen(jid);
697 address->device_id = device_id;
698
699 session_builder* builder;
700 res = session_builder_create(&builder, omemo_ctx.store, address, omemo_ctx.signal);
701 if (res != 0) {
702 log_error("[OMEMO] cannot create session builder for %s device %d", jid, device_id);
703 goto out;
704 }
705
706 int prekey_index;
707 gcry_randomize(&prekey_index, sizeof(int), GCRY_STRONG_RANDOM);
708 prekey_index %= g_list_length(prekeys);
709 omemo_key_t* prekey = g_list_nth_data(prekeys, prekey_index);
710
711 ec_public_key* prekey_public;
712 curve_decode_point(&prekey_public, prekey->data, prekey->length, omemo_ctx.signal);
713 ec_public_key* signed_prekey;
714 curve_decode_point(&signed_prekey, signed_prekey_raw, signed_prekey_len, omemo_ctx.signal);
715
716 res = session_pre_key_bundle_create(&bundle, 0, device_id, prekey->id, prekey_public, signed_prekey_id, signed_prekey, signature, signature_len, identity_key);
717 if (res != 0) {
718 log_error("[OMEMO] cannot create pre key bundle for %s device %d", jid, device_id);
719 goto out;
720 }
721
722 res = session_builder_process_pre_key_bundle(builder, bundle);
723 if (res != 0) {
724 log_error("[OMEMO] cannot process pre key bundle for %s device %d", jid, device_id);
725 goto out;
726 }
727
728 log_debug("[OMEMO] create session with %s device %d", jid, device_id);
729 } else {
730 log_debug("[OMEMO] session with %s device %d exists", jid, device_id);
731 }
732
733 out:
734 SIGNAL_UNREF(identity_key);
735 }
736
737 char*
omemo_on_message_send(ProfWin * win,const char * const message,gboolean request_receipt,gboolean muc,const char * const replace_id)738 omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_receipt, gboolean muc, const char* const replace_id)
739 {
740 char* id = NULL;
741 int res;
742 Jid* jid = jid_create(connection_get_fulljid());
743 GList* keys = NULL;
744
745 unsigned char* key;
746 unsigned char* iv;
747 unsigned char* ciphertext;
748 unsigned char* tag;
749 unsigned char* key_tag;
750 size_t ciphertext_len, tag_len;
751
752 ciphertext_len = strlen(message);
753 ciphertext = malloc(ciphertext_len);
754 tag_len = AES128_GCM_TAG_LENGTH;
755 tag = gcry_malloc_secure(tag_len);
756 key_tag = gcry_malloc_secure(AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH);
757
758 key = gcry_random_bytes_secure(AES128_GCM_KEY_LENGTH, GCRY_VERY_STRONG_RANDOM);
759 iv = gcry_random_bytes_secure(AES128_GCM_IV_LENGTH, GCRY_VERY_STRONG_RANDOM);
760
761 res = aes128gcm_encrypt(ciphertext, &ciphertext_len, tag, &tag_len, (const unsigned char* const)message, strlen(message), iv, key);
762 if (res != 0) {
763 log_error("[OMEMO][SEND] cannot encrypt message");
764 goto out;
765 }
766
767 memcpy(key_tag, key, AES128_GCM_KEY_LENGTH);
768 memcpy(key_tag + AES128_GCM_KEY_LENGTH, tag, AES128_GCM_TAG_LENGTH);
769
770 // List of barejids of the recipients of this message
771 GList* recipients = NULL;
772 if (muc) {
773 ProfMucWin* mucwin = (ProfMucWin*)win;
774 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
775 GList* members = muc_members(mucwin->roomjid);
776 GList* iter;
777 for (iter = members; iter != NULL; iter = iter->next) {
778 Jid* jid = jid_create(iter->data);
779 recipients = g_list_append(recipients, strdup(jid->barejid));
780 jid_destroy(jid);
781 }
782 g_list_free(members);
783 } else {
784 ProfChatWin* chatwin = (ProfChatWin*)win;
785 assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
786 recipients = g_list_append(recipients, strdup(chatwin->barejid));
787 }
788
789 GList* device_ids_iter;
790
791 omemo_ctx.identity_key_store.recv = false;
792
793 // Encrypt keys for the recipients
794 GList* recipients_iter;
795 for (recipients_iter = recipients; recipients_iter != NULL; recipients_iter = recipients_iter->next) {
796 GList* recipient_device_id = NULL;
797 recipient_device_id = g_hash_table_lookup(omemo_ctx.device_list, recipients_iter->data);
798 if (!recipient_device_id) {
799 log_warning("[OMEMO][SEND] cannot find device ids for %s", recipients_iter->data);
800 win_println(win, THEME_ERROR, "!", "Can't find a OMEMO device id for %s.\n", recipients_iter->data);
801 continue;
802 }
803
804 for (device_ids_iter = recipient_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
805 int res;
806 ciphertext_message* ciphertext;
807 session_cipher* cipher;
808 signal_protocol_address address = {
809 .name = recipients_iter->data,
810 .name_len = strlen(recipients_iter->data),
811 .device_id = GPOINTER_TO_INT(device_ids_iter->data)
812 };
813
814 // Don't encrypt for this device (according to
815 // <https://xmpp.org/extensions/xep-0384.html#encrypt>).
816 // Yourself as recipients in case of MUC
817 char* mybarejid = connection_get_barejid();
818 if ( !g_strcmp0(mybarejid, recipients_iter->data) ) {
819 if (GPOINTER_TO_INT(device_ids_iter->data) == omemo_ctx.device_id) {
820 free(mybarejid);
821 log_debug("[OMEMO][SEND] Skipping %d (my device) ", GPOINTER_TO_INT(device_ids_iter->data));
822 continue;
823 }
824 }
825 free(mybarejid);
826
827 log_debug("[OMEMO][SEND] recipients with device id %d for %s", GPOINTER_TO_INT(device_ids_iter->data), recipients_iter->data);
828 res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal);
829 if (res != SG_SUCCESS ) {
830 log_error("[OMEMO][SEND] cannot create cipher for %s device id %d - code: %d", address.name, address.device_id, res);
831 continue;
832 }
833
834 res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext);
835 session_cipher_free(cipher);
836 if (res != SG_SUCCESS ) {
837 log_info("[OMEMO][SEND] cannot encrypt key for %s device id %d - code: %d", address.name, address.device_id,res);
838 continue;
839 }
840 signal_buffer* buffer = ciphertext_message_get_serialized(ciphertext);
841 omemo_key_t* key = malloc(sizeof(omemo_key_t));
842 key->length = signal_buffer_len(buffer);
843 key->data = malloc(key->length);
844 memcpy(key->data, signal_buffer_data(buffer), key->length);
845 key->device_id = GPOINTER_TO_INT(device_ids_iter->data);
846 key->prekey = ciphertext_message_get_type(ciphertext) == CIPHERTEXT_PREKEY_TYPE;
847 keys = g_list_append(keys, key);
848 SIGNAL_UNREF(ciphertext);
849 }
850 }
851
852 g_list_free_full(recipients, free);
853
854 // Don't send the message if no key could be encrypted.
855 // (Since none of the recipients would be able to read the message.)
856 if (keys == NULL) {
857 win_println(win, THEME_ERROR, "!", "This message cannot be decrypted for any recipient.\n"
858 "You should trust your recipients' device fingerprint(s) using \"/omemo fingerprint trust FINGERPRINT\".\n"
859 "It could also be that the key bundle of the recipient(s) have not been received. "
860 "In this case, you could try \"omemo end\", \"omemo start\", and send the message again.");
861 goto out;
862 }
863
864 // Encrypt keys for the sender
865 if (!muc) {
866 GList* sender_device_id = g_hash_table_lookup(omemo_ctx.device_list, jid->barejid);
867
868 for (device_ids_iter = sender_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
869 int res;
870 ciphertext_message* ciphertext;
871 session_cipher* cipher;
872 signal_protocol_address address = {
873 .name = jid->barejid,
874 .name_len = strlen(jid->barejid),
875 .device_id = GPOINTER_TO_INT(device_ids_iter->data)
876 };
877 log_debug("[OMEMO][SEND][Sender] Sending to device %d for %s ", address.device_id, address.name);
878 // Don't encrypt for this device (according to
879 // <https://xmpp.org/extensions/xep-0384.html#encrypt>).
880 if (address.device_id == omemo_ctx.device_id) {
881 continue;
882 }
883
884 res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal);
885 if (res != 0) {
886 log_info("[OMEMO][SEND][Sender] cannot create cipher for %s device id %d", address.name, address.device_id);
887 continue;
888 }
889
890 res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext);
891 session_cipher_free(cipher);
892 if (res != 0) {
893 log_info("[OMEMO][SEND][Sender] cannot encrypt key for %s device id %d", address.name, address.device_id);
894 continue;
895 }
896 signal_buffer* buffer = ciphertext_message_get_serialized(ciphertext);
897 omemo_key_t* key = malloc(sizeof(omemo_key_t));
898 key->length = signal_buffer_len(buffer);
899 key->data = malloc(key->length);
900 memcpy(key->data, signal_buffer_data(buffer), key->length);
901 key->device_id = GPOINTER_TO_INT(device_ids_iter->data);
902 key->prekey = ciphertext_message_get_type(ciphertext) == CIPHERTEXT_PREKEY_TYPE;
903 keys = g_list_append(keys, key);
904 SIGNAL_UNREF(ciphertext);
905 }
906 }
907
908 // Send the message
909 if (muc) {
910 ProfMucWin* mucwin = (ProfMucWin*)win;
911 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
912 id = message_send_chat_omemo(mucwin->roomjid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, TRUE, replace_id);
913 } else {
914 ProfChatWin* chatwin = (ProfChatWin*)win;
915 assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
916 id = message_send_chat_omemo(chatwin->barejid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, FALSE, replace_id);
917 }
918
919 out:
920 jid_destroy(jid);
921 g_list_free_full(keys, (GDestroyNotify)omemo_key_free);
922 free(ciphertext);
923 gcry_free(key);
924 gcry_free(iv);
925 gcry_free(tag);
926 gcry_free(key_tag);
927
928 return id;
929 }
930
931 char*
omemo_on_message_recv(const char * const from_jid,uint32_t sid,const unsigned char * const iv,size_t iv_len,GList * keys,const unsigned char * const payload,size_t payload_len,gboolean muc,gboolean * trusted)932 omemo_on_message_recv(const char* const from_jid, uint32_t sid,
933 const unsigned char* const iv, size_t iv_len, GList* keys,
934 const unsigned char* const payload, size_t payload_len, gboolean muc, gboolean* trusted)
935 {
936 unsigned char* plaintext = NULL;
937 Jid* sender = NULL;
938 Jid* from = jid_create(from_jid);
939 if (!from) {
940 log_error("[OMEMO][RECV] Invalid jid %s", from_jid);
941 goto out;
942 }
943
944 int res;
945 GList* key_iter;
946 omemo_key_t* key = NULL;
947 for (key_iter = keys; key_iter != NULL; key_iter = key_iter->next) {
948 if (((omemo_key_t*)key_iter->data)->device_id == omemo_ctx.device_id) {
949 key = key_iter->data;
950 break;
951 }
952 }
953
954 if (!key) {
955 log_warning("[OMEMO][RECV] received a message with no corresponding key");
956 goto out;
957 }
958
959 if (muc) {
960 GList* roster = muc_roster(from->barejid);
961 GList* iter;
962 for (iter = roster; iter != NULL; iter = iter->next) {
963 Occupant* occupant = (Occupant*)iter->data;
964 if (g_strcmp0(occupant->nick, from->resourcepart) == 0) {
965 sender = jid_create(occupant->jid);
966 break;
967 }
968 }
969 g_list_free(roster);
970 if (!sender) {
971 log_warning("[OMEMO][RECV] cannot find MUC message sender fulljid");
972 goto out;
973 }
974 } else {
975 sender = jid_create(from->barejid);
976 }
977
978 session_cipher* cipher;
979 signal_buffer* plaintext_key;
980 signal_protocol_address address = {
981 .name = sender->barejid,
982 .name_len = strlen(sender->barejid),
983 .device_id = sid
984 };
985
986 res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal);
987 if (res != 0) {
988 log_error("[OMEMO][RECV] cannot create session cipher");
989 goto out;
990 }
991
992 if (key->prekey) {
993 log_debug("[OMEMO][RECV] decrypting message with prekey");
994 pre_key_signal_message* message;
995 ec_public_key* their_identity_key;
996 signal_buffer* identity_buffer = NULL;
997
998 omemo_ctx.identity_key_store.recv = true;
999
1000 pre_key_signal_message_deserialize(&message, key->data, key->length, omemo_ctx.signal);
1001 their_identity_key = pre_key_signal_message_get_identity_key(message);
1002
1003 res = session_cipher_decrypt_pre_key_signal_message(cipher, message, NULL, &plaintext_key);
1004
1005 omemo_ctx.identity_key_store.recv = false;
1006
1007 /* Perform a real check of the identity */
1008 ec_public_key_serialize(&identity_buffer, their_identity_key);
1009 *trusted = is_trusted_identity(&address, signal_buffer_data(identity_buffer),
1010 signal_buffer_len(identity_buffer), &omemo_ctx.identity_key_store);
1011
1012 /* Replace used pre_key in bundle */
1013 uint32_t pre_key_id = pre_key_signal_message_get_pre_key_id(message);
1014 ec_key_pair* ec_pair;
1015 session_pre_key* new_pre_key;
1016 curve_generate_key_pair(omemo_ctx.signal, &ec_pair);
1017 session_pre_key_create(&new_pre_key, pre_key_id, ec_pair);
1018 signal_protocol_pre_key_store_key(omemo_ctx.store, new_pre_key);
1019 SIGNAL_UNREF(new_pre_key);
1020 SIGNAL_UNREF(message);
1021 SIGNAL_UNREF(ec_pair);
1022 omemo_bundle_publish(true);
1023
1024 if (res == 0) {
1025 /* Start a new session */
1026 log_debug("[OMEMO][RECV] Res is 0 => omemo_bundle_request");
1027 omemo_bundle_request(sender->barejid, sid, omemo_start_device_session_handle_bundle, free, strdup(sender->barejid));
1028 }
1029 } else {
1030 log_debug("[OMEMO][RECV] decrypting message with existing session");
1031 signal_message* message = NULL;
1032
1033 res = signal_message_deserialize(&message, key->data, key->length, omemo_ctx.signal);
1034
1035 if (res < 0) {
1036 log_error("[OMEMO][RECV] cannot deserialize message");
1037 } else {
1038 res = session_cipher_decrypt_signal_message(cipher, message, NULL, &plaintext_key);
1039 *trusted = true;
1040 SIGNAL_UNREF(message);
1041 }
1042 }
1043
1044 session_cipher_free(cipher);
1045 if (res != 0) {
1046 log_error("[OMEMO][RECV] cannot decrypt message key");
1047 goto out;
1048 }
1049
1050 if (signal_buffer_len(plaintext_key) != AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH) {
1051 log_error("[OMEMO][RECV] invalid key length");
1052 signal_buffer_free(plaintext_key);
1053 goto out;
1054 }
1055
1056 size_t plaintext_len = payload_len;
1057 plaintext = malloc(plaintext_len + 1);
1058 res = aes128gcm_decrypt(plaintext, &plaintext_len, payload, payload_len, iv,
1059 iv_len, signal_buffer_data(plaintext_key),
1060 signal_buffer_data(plaintext_key) + AES128_GCM_KEY_LENGTH);
1061 signal_buffer_free(plaintext_key);
1062 if (res != 0) {
1063 log_error("[OMEMO][RECV] cannot decrypt message: %s", gcry_strerror(res));
1064 free(plaintext);
1065 plaintext = NULL;
1066 goto out;
1067 }
1068
1069 plaintext[plaintext_len] = '\0';
1070
1071 out:
1072 jid_destroy(from);
1073 jid_destroy(sender);
1074 return (char*)plaintext;
1075 }
1076
1077 char*
omemo_format_fingerprint(const char * const fingerprint)1078 omemo_format_fingerprint(const char* const fingerprint)
1079 {
1080 char* output = malloc(strlen(fingerprint) + strlen(fingerprint) / 8);
1081
1082 int i, j;
1083 for (i = 0, j = 0; i < strlen(fingerprint); i++) {
1084 if (i > 0 && i % 8 == 0) {
1085 output[j++] = '-';
1086 }
1087 output[j++] = fingerprint[i];
1088 }
1089
1090 output[j] = '\0';
1091
1092 return output;
1093 }
1094
1095 static char*
_omemo_unformat_fingerprint(const char * const fingerprint_formatted)1096 _omemo_unformat_fingerprint(const char* const fingerprint_formatted)
1097 {
1098 /* Unformat fingerprint */
1099 char* fingerprint = malloc(strlen(fingerprint_formatted));
1100 int i;
1101 int j;
1102 for (i = 0, j = 0; fingerprint_formatted[i] != '\0'; i++) {
1103 if (!g_ascii_isxdigit(fingerprint_formatted[i])) {
1104 continue;
1105 }
1106 fingerprint[j++] = fingerprint_formatted[i];
1107 }
1108
1109 fingerprint[j] = '\0';
1110
1111 return fingerprint;
1112 }
1113
1114 char*
omemo_own_fingerprint(gboolean formatted)1115 omemo_own_fingerprint(gboolean formatted)
1116 {
1117 ec_public_key* identity = ratchet_identity_key_pair_get_public(omemo_ctx.identity_key_pair);
1118 return _omemo_fingerprint(identity, formatted);
1119 }
1120
1121 GList*
omemo_known_device_identities(const char * const jid)1122 omemo_known_device_identities(const char* const jid)
1123 {
1124 GHashTable* known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid);
1125 if (!known_identities) {
1126 return NULL;
1127 }
1128
1129 return g_hash_table_get_keys(known_identities);
1130 }
1131
1132 gboolean
omemo_is_trusted_identity(const char * const jid,const char * const fingerprint)1133 omemo_is_trusted_identity(const char* const jid, const char* const fingerprint)
1134 {
1135 GHashTable* known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid);
1136 if (!known_identities) {
1137 return FALSE;
1138 }
1139
1140 void* device_id = g_hash_table_lookup(known_identities, fingerprint);
1141 if (!device_id) {
1142 return FALSE;
1143 }
1144
1145 signal_protocol_address address = {
1146 .name = jid,
1147 .name_len = strlen(jid),
1148 .device_id = GPOINTER_TO_INT(device_id),
1149 };
1150
1151 size_t fingerprint_len;
1152 unsigned char* fingerprint_raw = _omemo_fingerprint_decode(fingerprint, &fingerprint_len);
1153 unsigned char djb_type[] = { '\x05' };
1154 signal_buffer* buffer = signal_buffer_create(djb_type, 1);
1155 buffer = signal_buffer_append(buffer, fingerprint_raw, fingerprint_len);
1156
1157 gboolean trusted = is_trusted_identity(&address, signal_buffer_data(buffer), signal_buffer_len(buffer), &omemo_ctx.identity_key_store);
1158 log_debug("[OMEMO] Device trusted %s (%d): %d", jid, GPOINTER_TO_INT(device_id), trusted);
1159
1160 free(fingerprint_raw);
1161 signal_buffer_free(buffer);
1162
1163 return trusted;
1164 }
1165
1166 static char*
_omemo_fingerprint(ec_public_key * identity,gboolean formatted)1167 _omemo_fingerprint(ec_public_key* identity, gboolean formatted)
1168 {
1169 int i;
1170 signal_buffer* identity_public_key;
1171
1172 ec_public_key_serialize(&identity_public_key, identity);
1173 size_t identity_public_key_len = signal_buffer_len(identity_public_key);
1174 unsigned char* identity_public_key_data = signal_buffer_data(identity_public_key);
1175
1176 /* Skip first byte corresponding to signal DJB_TYPE */
1177 identity_public_key_len--;
1178 identity_public_key_data = &identity_public_key_data[1];
1179
1180 char* fingerprint = malloc(identity_public_key_len * 2 + 1);
1181
1182 for (i = 0; i < identity_public_key_len; i++) {
1183 fingerprint[i * 2] = (identity_public_key_data[i] & 0xf0) >> 4;
1184 fingerprint[i * 2] += '0';
1185 if (fingerprint[i * 2] > '9') {
1186 fingerprint[i * 2] += 0x27;
1187 }
1188
1189 fingerprint[(i * 2) + 1] = identity_public_key_data[i] & 0x0f;
1190 fingerprint[(i * 2) + 1] += '0';
1191 if (fingerprint[(i * 2) + 1] > '9') {
1192 fingerprint[(i * 2) + 1] += 0x27;
1193 }
1194 }
1195
1196 fingerprint[i * 2] = '\0';
1197 signal_buffer_free(identity_public_key);
1198
1199 if (!formatted) {
1200 return fingerprint;
1201 } else {
1202 char* formatted_fingerprint = omemo_format_fingerprint(fingerprint);
1203 free(fingerprint);
1204 return formatted_fingerprint;
1205 }
1206 }
1207
1208 static unsigned char*
_omemo_fingerprint_decode(const char * const fingerprint,size_t * len)1209 _omemo_fingerprint_decode(const char* const fingerprint, size_t* len)
1210 {
1211 unsigned char* output = malloc(strlen(fingerprint) / 2 + 1);
1212
1213 int i;
1214 int j;
1215 for (i = 0, j = 0; i < strlen(fingerprint);) {
1216 if (!g_ascii_isxdigit(fingerprint[i])) {
1217 i++;
1218 continue;
1219 }
1220
1221 output[j] = g_ascii_xdigit_value(fingerprint[i++]) << 4;
1222 output[j] |= g_ascii_xdigit_value(fingerprint[i++]);
1223 j++;
1224 }
1225
1226 *len = j;
1227
1228 return output;
1229 }
1230
1231 void
omemo_trust(const char * const jid,const char * const fingerprint_formatted)1232 omemo_trust(const char* const jid, const char* const fingerprint_formatted)
1233 {
1234 size_t len;
1235
1236 GHashTable* known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid);
1237 if (!known_identities) {
1238 log_warning("[OMEMO] cannot trust unknown device: %s", fingerprint_formatted);
1239 cons_show("Cannot trust unknown device: %s", fingerprint_formatted);
1240 return;
1241 }
1242
1243 char* fingerprint = _omemo_unformat_fingerprint(fingerprint_formatted);
1244
1245 uint32_t device_id = GPOINTER_TO_INT(g_hash_table_lookup(known_identities, fingerprint));
1246 free(fingerprint);
1247
1248 if (!device_id) {
1249 log_warning("[OMEMO] cannot trust unknown device: %s", fingerprint_formatted);
1250 cons_show("Cannot trust unknown device: %s", fingerprint_formatted);
1251 return;
1252 }
1253
1254 /* TODO should not hardcode DJB_TYPE here
1255 * should instead store identity key in known_identities along with
1256 * device_id */
1257 signal_protocol_address address = {
1258 .name = jid,
1259 .name_len = strlen(jid),
1260 .device_id = device_id,
1261 };
1262
1263 unsigned char* fingerprint_raw = _omemo_fingerprint_decode(fingerprint_formatted, &len);
1264 unsigned char djb_type[] = { '\x05' };
1265 signal_buffer* buffer = signal_buffer_create(djb_type, 1);
1266 buffer = signal_buffer_append(buffer, fingerprint_raw, len);
1267 save_identity(&address, signal_buffer_data(buffer), signal_buffer_len(buffer), &omemo_ctx.identity_key_store);
1268 free(fingerprint_raw);
1269 signal_buffer_free(buffer);
1270
1271 omemo_bundle_request(jid, device_id, omemo_start_device_session_handle_bundle, free, strdup(jid));
1272 }
1273
1274 void
omemo_untrust(const char * const jid,const char * const fingerprint_formatted)1275 omemo_untrust(const char* const jid, const char* const fingerprint_formatted)
1276 {
1277 size_t len;
1278 unsigned char* identity = _omemo_fingerprint_decode(fingerprint_formatted, &len);
1279
1280 GHashTableIter iter;
1281 gpointer key, value;
1282
1283 GHashTable* trusted = g_hash_table_lookup(omemo_ctx.identity_key_store.trusted, jid);
1284 if (!trusted) {
1285 free(identity);
1286 return;
1287 }
1288
1289 g_hash_table_iter_init(&iter, trusted);
1290 while (g_hash_table_iter_next(&iter, &key, &value)) {
1291 signal_buffer* buffer = value;
1292 unsigned char* original = signal_buffer_data(buffer);
1293 /* Skip DJB_TYPE byte */
1294 original++;
1295 if ((signal_buffer_len(buffer) - 1) == len && memcmp(original, identity, len) == 0) {
1296 g_hash_table_remove(trusted, key);
1297 }
1298 }
1299 free(identity);
1300
1301 char* fingerprint = _omemo_unformat_fingerprint(fingerprint_formatted);
1302
1303 /* Remove existing session */
1304 GHashTable* known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid);
1305 if (!known_identities) {
1306 log_error("[OMEMO] cannot find known device while untrusting a fingerprint");
1307 goto out;
1308 }
1309
1310 uint32_t device_id = GPOINTER_TO_INT(g_hash_table_lookup(known_identities, fingerprint));
1311 if (!device_id) {
1312 log_error("[OMEMO] cannot find device id while untrusting a fingerprint");
1313 goto out;
1314 }
1315 signal_protocol_address address = {
1316 .name = jid,
1317 .name_len = strlen(jid),
1318 .device_id = device_id
1319 };
1320
1321 delete_session(&address, omemo_ctx.session_store);
1322
1323 /* Remove from keyfile */
1324 char* device_id_str = g_strdup_printf("%d", device_id);
1325 g_key_file_remove_key(omemo_ctx.trust_keyfile, jid, device_id_str, NULL);
1326 g_free(device_id_str);
1327 omemo_trust_keyfile_save();
1328
1329 out:
1330 free(fingerprint);
1331 }
1332
1333 static void
_lock(void * user_data)1334 _lock(void* user_data)
1335 {
1336 omemo_context* ctx = (omemo_context*)user_data;
1337 pthread_mutex_lock(&ctx->lock);
1338 }
1339
1340 static void
_unlock(void * user_data)1341 _unlock(void* user_data)
1342 {
1343 omemo_context* ctx = (omemo_context*)user_data;
1344 pthread_mutex_unlock(&ctx->lock);
1345 }
1346
1347 static void
_omemo_log(int level,const char * message,size_t len,void * user_data)1348 _omemo_log(int level, const char* message, size_t len, void* user_data)
1349 {
1350 switch (level) {
1351 case SG_LOG_ERROR:
1352 log_error("[OMEMO][SIGNAL] %s", message);
1353 break;
1354 case SG_LOG_WARNING:
1355 log_warning("[OMEMO][SIGNAL] %s", message);
1356 break;
1357 case SG_LOG_NOTICE:
1358 case SG_LOG_INFO:
1359 log_debug("[OMEMO][SIGNAL] %s", message);
1360 break;
1361 case SG_LOG_DEBUG:
1362 log_debug("[OMEMO][SIGNAL] %s", message);
1363 break;
1364 }
1365 }
1366
1367 static gboolean
_handle_own_device_list(const char * const jid,GList * device_list)1368 _handle_own_device_list(const char* const jid, GList* device_list)
1369 {
1370 // We didn't find the own device id -> publish
1371 if (!g_list_find(device_list, GINT_TO_POINTER(omemo_ctx.device_id))) {
1372 cons_show("Could not find own OMEMO device ID. Going to publish own device ID: %d", GINT_TO_POINTER(omemo_ctx.device_id));
1373 log_debug("[OMEMO] No device ID for our device. Publishing device list");
1374 device_list = g_list_copy(device_list);
1375 device_list = g_list_append(device_list, GINT_TO_POINTER(omemo_ctx.device_id));
1376 g_hash_table_insert(omemo_ctx.device_list, strdup(jid), device_list);
1377 omemo_devicelist_publish(device_list);
1378 }
1379
1380 log_debug("[OMEMO] Request OMEMO Bundles for our devices");
1381 GList* device_id;
1382 for (device_id = device_list; device_id != NULL; device_id = device_id->next) {
1383 omemo_bundle_request(jid, GPOINTER_TO_INT(device_id->data), omemo_start_device_session_handle_bundle, free, strdup(jid));
1384 }
1385
1386 return TRUE;
1387 }
1388
1389 static gboolean
_handle_device_list_start_session(const char * const jid,GList * device_list)1390 _handle_device_list_start_session(const char* const jid, GList* device_list)
1391 {
1392 log_debug("[OMEMO] Start session for %s - device_list", jid);
1393 omemo_start_session(jid);
1394
1395 return FALSE;
1396 }
1397
1398 void
omemo_key_free(omemo_key_t * key)1399 omemo_key_free(omemo_key_t* key)
1400 {
1401 if (key == NULL) {
1402 return;
1403 }
1404
1405 free(key->data);
1406 free(key);
1407 }
1408
1409 char*
omemo_fingerprint_autocomplete(const char * const search_str,gboolean previous,void * context)1410 omemo_fingerprint_autocomplete(const char* const search_str, gboolean previous, void* context)
1411 {
1412 Autocomplete ac = g_hash_table_lookup(omemo_ctx.fingerprint_ac, context);
1413 if (ac != NULL) {
1414 return autocomplete_complete(ac, search_str, FALSE, previous);
1415 } else {
1416 return NULL;
1417 }
1418 }
1419
1420 void
omemo_fingerprint_autocomplete_reset(void)1421 omemo_fingerprint_autocomplete_reset(void)
1422 {
1423 gpointer value;
1424 GHashTableIter iter;
1425 g_hash_table_iter_init(&iter, omemo_ctx.fingerprint_ac);
1426
1427 while (g_hash_table_iter_next(&iter, NULL, &value)) {
1428 Autocomplete ac = value;
1429 autocomplete_reset(ac);
1430 }
1431 }
1432
1433 gboolean
omemo_automatic_start(const char * const recipient)1434 omemo_automatic_start(const char* const recipient)
1435 {
1436 gboolean result = FALSE;
1437 char* account_name = session_get_account_name();
1438 ProfAccount* account = accounts_get_account(account_name);
1439 prof_omemopolicy_t policy;
1440
1441 if (account->omemo_policy) {
1442 // check default account setting
1443 if (g_strcmp0(account->omemo_policy, "manual") == 0) {
1444 policy = PROF_OMEMOPOLICY_MANUAL;
1445 }
1446 if (g_strcmp0(account->omemo_policy, "opportunistic") == 0) {
1447 policy = PROF_OMEMOPOLICY_AUTOMATIC;
1448 }
1449 if (g_strcmp0(account->omemo_policy, "always") == 0) {
1450 policy = PROF_OMEMOPOLICY_ALWAYS;
1451 }
1452 } else {
1453 // check global setting
1454 char* pref_omemo_policy = prefs_get_string(PREF_OMEMO_POLICY);
1455
1456 // pref defaults to manual
1457 policy = PROF_OMEMOPOLICY_AUTOMATIC;
1458
1459 if (strcmp(pref_omemo_policy, "manual") == 0) {
1460 policy = PROF_OMEMOPOLICY_MANUAL;
1461 } else if (strcmp(pref_omemo_policy, "always") == 0) {
1462 policy = PROF_OMEMOPOLICY_ALWAYS;
1463 }
1464
1465 g_free(pref_omemo_policy);
1466 }
1467
1468 switch (policy) {
1469 case PROF_OMEMOPOLICY_MANUAL:
1470 result = FALSE;
1471 break;
1472 case PROF_OMEMOPOLICY_AUTOMATIC:
1473 if (g_list_find_custom(account->omemo_enabled, recipient, (GCompareFunc)g_strcmp0)) {
1474 result = TRUE;
1475 } else if (g_list_find_custom(account->omemo_disabled, recipient, (GCompareFunc)g_strcmp0)) {
1476 result = FALSE;
1477 } else {
1478 result = FALSE;
1479 }
1480 break;
1481 case PROF_OMEMOPOLICY_ALWAYS:
1482 if (g_list_find_custom(account->omemo_disabled, recipient, (GCompareFunc)g_strcmp0)) {
1483 result = FALSE;
1484 } else {
1485 result = TRUE;
1486 }
1487 break;
1488 }
1489
1490 account_free(account);
1491 return result;
1492 }
1493
1494 static gboolean
_load_identity(void)1495 _load_identity(void)
1496 {
1497 GError* error = NULL;
1498 log_info("[OMEMO] Loading OMEMO identity");
1499
1500 /* Device ID */
1501 error = NULL;
1502 omemo_ctx.device_id = g_key_file_get_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_DEVICE_ID, &error);
1503 if (error != NULL) {
1504 log_error("[OMEMO] cannot load device id: %s", error->message);
1505 return FALSE;
1506 }
1507 log_debug("[OMEMO] device id: %d", omemo_ctx.device_id);
1508
1509 /* Registration ID */
1510 error = NULL;
1511 omemo_ctx.registration_id = g_key_file_get_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_REGISTRATION_ID, &error);
1512 if (error != NULL) {
1513 log_error("[OMEMO] cannot load registration id: %s", error->message);
1514 return FALSE;
1515 }
1516
1517 /* Identity key */
1518 error = NULL;
1519 char* identity_key_public_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PUBLIC, &error);
1520 if (!identity_key_public_b64) {
1521 log_error("[OMEMO] cannot load identity public key: %s", error->message);
1522 return FALSE;
1523 }
1524
1525 size_t identity_key_public_len;
1526 unsigned char* identity_key_public = g_base64_decode(identity_key_public_b64, &identity_key_public_len);
1527 g_free(identity_key_public_b64);
1528 omemo_ctx.identity_key_store.public = signal_buffer_create(identity_key_public, identity_key_public_len);
1529
1530 error = NULL;
1531 char* identity_key_private_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PRIVATE, &error);
1532 if (!identity_key_private_b64) {
1533 log_error("[OMEMO] cannot load identity private key: %s", error->message);
1534 return FALSE;
1535 }
1536
1537 size_t identity_key_private_len;
1538 unsigned char* identity_key_private = g_base64_decode(identity_key_private_b64, &identity_key_private_len);
1539 g_free(identity_key_private_b64);
1540 omemo_ctx.identity_key_store.private = signal_buffer_create(identity_key_private, identity_key_private_len);
1541
1542 ec_public_key* public_key;
1543 curve_decode_point(&public_key, identity_key_public, identity_key_public_len, omemo_ctx.signal);
1544 ec_private_key* private_key;
1545 curve_decode_private_point(&private_key, identity_key_private, identity_key_private_len, omemo_ctx.signal);
1546 ratchet_identity_key_pair_create(&omemo_ctx.identity_key_pair, public_key, private_key);
1547
1548 g_free(identity_key_public);
1549 g_free(identity_key_private);
1550
1551 char** keys = NULL;
1552 int i;
1553 /* Pre keys */
1554 i = 0;
1555 keys = g_key_file_get_keys(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_PREKEYS, NULL, NULL);
1556 if (keys) {
1557 for (i = 0; keys[i] != NULL; i++) {
1558 char* pre_key_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_PREKEYS, keys[i], NULL);
1559 size_t pre_key_len;
1560 unsigned char* pre_key = g_base64_decode(pre_key_b64, &pre_key_len);
1561 g_free(pre_key_b64);
1562 signal_buffer* buffer = signal_buffer_create(pre_key, pre_key_len);
1563 g_free(pre_key);
1564 g_hash_table_insert(omemo_ctx.pre_key_store, GINT_TO_POINTER(strtoul(keys[i], NULL, 10)), buffer);
1565 }
1566
1567 g_strfreev(keys);
1568 }
1569
1570 /* Ensure we have at least 100 pre keys */
1571 if (i < 100) {
1572 _generate_pre_keys(100 - i);
1573 }
1574
1575 /* Signed pre keys */
1576 i = 0;
1577 keys = g_key_file_get_keys(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_SIGNED_PREKEYS, NULL, NULL);
1578 if (keys) {
1579 for (i = 0; keys[i] != NULL; i++) {
1580 char* signed_pre_key_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_SIGNED_PREKEYS, keys[i], NULL);
1581 size_t signed_pre_key_len;
1582 unsigned char* signed_pre_key = g_base64_decode(signed_pre_key_b64, &signed_pre_key_len);
1583 g_free(signed_pre_key_b64);
1584 signal_buffer* buffer = signal_buffer_create(signed_pre_key, signed_pre_key_len);
1585 g_free(signed_pre_key);
1586 g_hash_table_insert(omemo_ctx.signed_pre_key_store, GINT_TO_POINTER(strtoul(keys[i], NULL, 10)), buffer);
1587 omemo_ctx.signed_pre_key_id = strtoul(keys[i], NULL, 10);
1588 }
1589 g_strfreev(keys);
1590 }
1591
1592 if (i == 0) {
1593 _generate_signed_pre_key();
1594 }
1595
1596 loaded = TRUE;
1597
1598 omemo_identity_keyfile_save();
1599 omemo_start_sessions();
1600
1601 return TRUE;
1602 }
1603
1604 static void
_load_trust(void)1605 _load_trust(void)
1606 {
1607 char** keys = NULL;
1608 char** groups = g_key_file_get_groups(omemo_ctx.trust_keyfile, NULL);
1609 if (groups) {
1610 int i;
1611 for (i = 0; groups[i] != NULL; i++) {
1612 GHashTable* trusted;
1613
1614 trusted = g_hash_table_lookup(omemo_ctx.identity_key_store.trusted, groups[i]);
1615 if (!trusted) {
1616 trusted = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)signal_buffer_free);
1617 g_hash_table_insert(omemo_ctx.identity_key_store.trusted, strdup(groups[i]), trusted);
1618 }
1619
1620 keys = g_key_file_get_keys(omemo_ctx.trust_keyfile, groups[i], NULL, NULL);
1621 int j;
1622 for (j = 0; keys[j] != NULL; j++) {
1623 char* key_b64 = g_key_file_get_string(omemo_ctx.trust_keyfile, groups[i], keys[j], NULL);
1624 size_t key_len;
1625 unsigned char* key = g_base64_decode(key_b64, &key_len);
1626 g_free(key_b64);
1627 signal_buffer* buffer = signal_buffer_create(key, key_len);
1628 g_free(key);
1629 uint32_t device_id = strtoul(keys[j], NULL, 10);
1630 g_hash_table_insert(trusted, GINT_TO_POINTER(device_id), buffer);
1631 }
1632 g_strfreev(keys);
1633 }
1634 g_strfreev(groups);
1635 }
1636 }
1637
1638 static void
_load_sessions(void)1639 _load_sessions(void)
1640 {
1641 int i;
1642 char** groups = g_key_file_get_groups(omemo_ctx.sessions_keyfile, NULL);
1643 if (groups) {
1644 for (i = 0; groups[i] != NULL; i++) {
1645 int j;
1646 GHashTable* device_store = NULL;
1647
1648 device_store = g_hash_table_lookup(omemo_ctx.session_store, groups[i]);
1649 if (!device_store) {
1650 device_store = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)signal_buffer_free);
1651 g_hash_table_insert(omemo_ctx.session_store, strdup(groups[i]), device_store);
1652 }
1653
1654 char** keys = g_key_file_get_keys(omemo_ctx.sessions_keyfile, groups[i], NULL, NULL);
1655 for (j = 0; keys[j] != NULL; j++) {
1656 uint32_t id = strtoul(keys[j], NULL, 10);
1657 char* record_b64 = g_key_file_get_string(omemo_ctx.sessions_keyfile, groups[i], keys[j], NULL);
1658 size_t record_len;
1659 unsigned char* record = g_base64_decode(record_b64, &record_len);
1660 g_free(record_b64);
1661 signal_buffer* buffer = signal_buffer_create(record, record_len);
1662 g_free(record);
1663 g_hash_table_insert(device_store, GINT_TO_POINTER(id), buffer);
1664 }
1665 g_strfreev(keys);
1666 }
1667 g_strfreev(groups);
1668 }
1669 }
1670
1671 static void
_load_known_devices(void)1672 _load_known_devices(void)
1673 {
1674 int i;
1675 char** groups = g_key_file_get_groups(omemo_ctx.known_devices_keyfile, NULL);
1676 if (groups) {
1677 for (i = 0; groups[i] != NULL; i++) {
1678 int j;
1679 GHashTable* known_identities = NULL;
1680
1681 known_identities = g_hash_table_lookup(omemo_ctx.known_devices, groups[i]);
1682 if (!known_identities) {
1683 known_identities = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
1684 g_hash_table_insert(omemo_ctx.known_devices, strdup(groups[i]), known_identities);
1685 }
1686
1687 char** keys = g_key_file_get_keys(omemo_ctx.known_devices_keyfile, groups[i], NULL, NULL);
1688 for (j = 0; keys[j] != NULL; j++) {
1689 uint32_t device_id = strtoul(keys[j], NULL, 10);
1690 char* fingerprint = g_key_file_get_string(omemo_ctx.known_devices_keyfile, groups[i], keys[j], NULL);
1691 g_hash_table_insert(known_identities, strdup(fingerprint), GINT_TO_POINTER(device_id));
1692 g_free(fingerprint);
1693 }
1694 g_strfreev(keys);
1695 }
1696 g_strfreev(groups);
1697 }
1698 }
1699
1700 static void
_cache_device_identity(const char * const jid,uint32_t device_id,ec_public_key * identity)1701 _cache_device_identity(const char* const jid, uint32_t device_id, ec_public_key* identity)
1702 {
1703 GHashTable* known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid);
1704 if (!known_identities) {
1705 known_identities = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
1706 g_hash_table_insert(omemo_ctx.known_devices, strdup(jid), known_identities);
1707 }
1708
1709 char* fingerprint = _omemo_fingerprint(identity, FALSE);
1710 log_debug("[OMEMO] cache identity for %s:%d: %s", jid, device_id, fingerprint);
1711 g_hash_table_insert(known_identities, strdup(fingerprint), GINT_TO_POINTER(device_id));
1712
1713 char* device_id_str = g_strdup_printf("%d", device_id);
1714 g_key_file_set_string(omemo_ctx.known_devices_keyfile, jid, device_id_str, fingerprint);
1715 g_free(device_id_str);
1716 omemo_known_devices_keyfile_save();
1717
1718 Autocomplete ac = g_hash_table_lookup(omemo_ctx.fingerprint_ac, jid);
1719 if (ac == NULL) {
1720 ac = autocomplete_new();
1721 g_hash_table_insert(omemo_ctx.fingerprint_ac, strdup(jid), ac);
1722 }
1723
1724 char* formatted_fingerprint = omemo_format_fingerprint(fingerprint);
1725 autocomplete_add(ac, formatted_fingerprint);
1726 free(formatted_fingerprint);
1727 free(fingerprint);
1728 }
1729
1730 static void
_g_hash_table_free(GHashTable * hash_table)1731 _g_hash_table_free(GHashTable* hash_table)
1732 {
1733 g_hash_table_remove_all(hash_table);
1734 g_hash_table_unref(hash_table);
1735 }
1736
1737 static void
_generate_pre_keys(int count)1738 _generate_pre_keys(int count)
1739 {
1740 unsigned int start;
1741 gcry_randomize(&start, sizeof(unsigned int), GCRY_VERY_STRONG_RANDOM);
1742 signal_protocol_key_helper_pre_key_list_node* pre_keys_head;
1743 signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start, count, omemo_ctx.signal);
1744
1745 signal_protocol_key_helper_pre_key_list_node* p;
1746 for (p = pre_keys_head; p != NULL; p = signal_protocol_key_helper_key_list_next(p)) {
1747 session_pre_key* prekey = signal_protocol_key_helper_key_list_element(p);
1748 signal_protocol_pre_key_store_key(omemo_ctx.store, prekey);
1749 }
1750 signal_protocol_key_helper_key_list_free(pre_keys_head);
1751 }
1752
1753 static void
_generate_signed_pre_key(void)1754 _generate_signed_pre_key(void)
1755 {
1756 session_signed_pre_key* signed_pre_key;
1757 struct timeval tv;
1758 gettimeofday(&tv, NULL);
1759 unsigned long long timestamp = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
1760
1761 omemo_ctx.signed_pre_key_id = 1;
1762 signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, omemo_ctx.identity_key_pair, omemo_ctx.signed_pre_key_id, timestamp, omemo_ctx.signal);
1763 signal_protocol_signed_pre_key_store_key(omemo_ctx.store, signed_pre_key);
1764 SIGNAL_UNREF(signed_pre_key);
1765 }
1766
1767 void
omemo_free(void * a)1768 omemo_free(void* a)
1769 {
1770 gcry_free(a);
1771 }
1772
1773 char*
omemo_encrypt_file(FILE * in,FILE * out,off_t file_size,int * gcry_res)1774 omemo_encrypt_file(FILE* in, FILE* out, off_t file_size, int* gcry_res)
1775 {
1776 unsigned char* key = gcry_random_bytes_secure(
1777 OMEMO_AESGCM_KEY_LENGTH,
1778 GCRY_VERY_STRONG_RANDOM);
1779
1780 // Create nonce/IV with random bytes.
1781 unsigned char nonce[OMEMO_AESGCM_NONCE_LENGTH];
1782 gcry_create_nonce(nonce, OMEMO_AESGCM_NONCE_LENGTH);
1783
1784 char* fragment = aes256gcm_create_secure_fragment(key, nonce);
1785 *gcry_res = aes256gcm_crypt_file(in, out, file_size, key, nonce, true);
1786
1787 if (*gcry_res != GPG_ERR_NO_ERROR) {
1788 gcry_free(fragment);
1789 fragment = NULL;
1790 }
1791
1792 gcry_free(key);
1793
1794 return fragment;
1795 }
1796
1797 void
_bytes_from_hex(const char * hex,size_t hex_size,unsigned char * bytes,size_t bytes_size)1798 _bytes_from_hex(const char* hex, size_t hex_size,
1799 unsigned char* bytes, size_t bytes_size)
1800 {
1801 const unsigned char ht[] = {
1802 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567
1803 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?
1804 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG
1805 };
1806 const size_t ht_size = sizeof(ht);
1807
1808 unsigned char b0;
1809 unsigned char b1;
1810
1811 memset(bytes, 0, bytes_size);
1812
1813 for (int i = 0; (i < hex_size) && (i / 2 < bytes_size); i += 2) {
1814 b0 = ((unsigned char)hex[i + 0] & 0x1f) ^ 0x10;
1815 b1 = ((unsigned char)hex[i + 1] & 0x1f) ^ 0x10;
1816
1817 if (b0 <= ht_size && b1 <= ht_size) {
1818 bytes[i / 2] = (unsigned char)(ht[b0] << 4) | ht[b1];
1819 }
1820 }
1821 }
1822
1823 gcry_error_t
omemo_decrypt_file(FILE * in,FILE * out,off_t file_size,const char * fragment)1824 omemo_decrypt_file(FILE* in, FILE* out, off_t file_size, const char* fragment)
1825 {
1826 char nonce_hex[AESGCM_URL_NONCE_LEN];
1827 char key_hex[AESGCM_URL_KEY_LEN];
1828
1829 const int nonce_pos = 0;
1830 const int key_pos = AESGCM_URL_NONCE_LEN;
1831
1832 memcpy(nonce_hex, &(fragment[nonce_pos]), AESGCM_URL_NONCE_LEN);
1833 memcpy(key_hex, &(fragment[key_pos]), AESGCM_URL_KEY_LEN);
1834
1835 unsigned char nonce[OMEMO_AESGCM_NONCE_LENGTH];
1836 unsigned char* key = gcry_malloc_secure(OMEMO_AESGCM_KEY_LENGTH);
1837
1838 _bytes_from_hex(nonce_hex, AESGCM_URL_NONCE_LEN,
1839 nonce, OMEMO_AESGCM_NONCE_LENGTH);
1840 _bytes_from_hex(key_hex, AESGCM_URL_KEY_LEN,
1841 key, OMEMO_AESGCM_KEY_LENGTH);
1842
1843 gcry_error_t crypt_res;
1844 crypt_res = aes256gcm_crypt_file(in, out, file_size, key, nonce, false);
1845
1846 gcry_free(key);
1847
1848 return crypt_res;
1849 }
1850
1851 int
omemo_parse_aesgcm_url(const char * aesgcm_url,char ** https_url,char ** fragment)1852 omemo_parse_aesgcm_url(const char* aesgcm_url,
1853 char** https_url,
1854 char** fragment)
1855 {
1856 CURLUcode ret;
1857 CURLU* url = curl_url();
1858
1859 // Required to allow for the "aesgcm://" scheme that OMEMO Media Sharing
1860 // uses.
1861 unsigned int curl_flags = CURLU_NON_SUPPORT_SCHEME;
1862
1863 ret = curl_url_set(url, CURLUPART_URL, aesgcm_url, curl_flags);
1864 if (ret) {
1865 goto out;
1866 }
1867
1868 ret = curl_url_get(url, CURLUPART_FRAGMENT, fragment, curl_flags);
1869 if (ret) {
1870 goto out;
1871 }
1872
1873 if (strlen(*fragment) != AESGCM_URL_NONCE_LEN + AESGCM_URL_KEY_LEN) {
1874 ret = 1;
1875 goto out;
1876 }
1877
1878 // Clear fragment from HTTPS URL as it's not required for download.
1879 ret = curl_url_set(url, CURLUPART_FRAGMENT, NULL, curl_flags);
1880 if (ret) {
1881 goto out;
1882 }
1883
1884 ret = curl_url_set(url, CURLUPART_SCHEME, "https", curl_flags);
1885 if (ret) {
1886 goto out;
1887 }
1888
1889 ret = curl_url_get(url, CURLUPART_URL, https_url, curl_flags);
1890 if (ret) {
1891 goto out;
1892 }
1893
1894 out:
1895 curl_url_cleanup(url);
1896 return ret;
1897 }
1898