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