about summary refs log tree commit diff stats
path: root/src/omemo
diff options
context:
space:
mode:
Diffstat (limited to 'src/omemo')
-rw-r--r--src/omemo/omemo.c91
-rw-r--r--src/omemo/omemo.h2
-rw-r--r--src/omemo/store.c25
-rw-r--r--src/omemo/store.h1
4 files changed, 90 insertions, 29 deletions
diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c
index a20dc109..377a2637 100644
--- a/src/omemo/omemo.c
+++ b/src/omemo/omemo.c
@@ -30,6 +30,7 @@ static gboolean loaded;
 static void _generate_pre_keys(int count);
 static void _generate_signed_pre_key(void);
 static void _load_identity(void);
+static void _load_trust(void);
 static void _load_sessions(void);
 static void _lock(void *user_data);
 static void _unlock(void *user_data);
@@ -61,6 +62,8 @@ struct omemo_context_t {
     GHashTable *device_ids;
     GString *identity_filename;
     GKeyFile *identity_keyfile;
+    GString *trust_filename;
+    GKeyFile *trust_keyfile;
     GString *sessions_filename;
     GKeyFile *sessions_keyfile;
     GHashTable *known_devices;
@@ -187,6 +190,8 @@ omemo_on_connect(ProfAccount *account)
 
     omemo_ctx.identity_filename = g_string_new(basedir->str);
     g_string_append(omemo_ctx.identity_filename, "identity.txt");
+    omemo_ctx.trust_filename = g_string_new(basedir->str);
+    g_string_append(omemo_ctx.trust_filename, "trust.txt");
     omemo_ctx.sessions_filename = g_string_new(basedir->str);
     g_string_append(omemo_ctx.sessions_filename, "sessions.txt");
 
@@ -207,6 +212,7 @@ omemo_on_connect(ProfAccount *account)
     omemo_devicelist_subscribe();
 
     omemo_ctx.identity_keyfile = g_key_file_new();
+    omemo_ctx.trust_keyfile = g_key_file_new();
     omemo_ctx.sessions_keyfile = g_key_file_new();
 
     if (g_key_file_load_from_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
@@ -217,12 +223,18 @@ omemo_on_connect(ProfAccount *account)
     }
 
     error = NULL;
+    if (g_key_file_load_from_file(omemo_ctx.trust_keyfile, omemo_ctx.trust_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
+        _load_trust();
+    } else if (error->code != G_FILE_ERROR_NOENT) {
+        log_warning("OMEMO: error loading trust from: %s, %s", omemo_ctx.sessions_filename->str, error->message);
+    }
+
+    error = NULL;
     if (g_key_file_load_from_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
         _load_sessions();
     } else if (error->code != G_FILE_ERROR_NOENT) {
         log_warning("OMEMO: error loading sessions from: %s, %s", omemo_ctx.sessions_filename->str, error->message);
     }
-
 }
 
 void
@@ -243,6 +255,8 @@ omemo_on_disconnect(void)
 
     g_string_free(omemo_ctx.identity_filename, TRUE);
     g_key_file_free(omemo_ctx.identity_keyfile);
+    g_string_free(omemo_ctx.trust_filename, TRUE);
+    g_key_file_free(omemo_ctx.trust_keyfile);
     g_string_free(omemo_ctx.sessions_filename, TRUE);
     g_key_file_free(omemo_ctx.sessions_keyfile);
 }
@@ -473,6 +487,22 @@ omemo_identity_keyfile_save(void)
 }
 
 GKeyFile *
+omemo_trust_keyfile(void)
+{
+    return omemo_ctx.trust_keyfile;
+}
+
+void
+omemo_trust_keyfile_save(void)
+{
+    GError *error = NULL;
+
+    if (!g_key_file_save_to_file(omemo_ctx.trust_keyfile, omemo_ctx.trust_filename->str, &error)) {
+        log_error("OMEMO: error saving trust to: %s, %s", omemo_ctx.trust_filename->str, error->message);
+    }
+}
+
+GKeyFile *
 omemo_sessions_keyfile(void)
 {
     return omemo_ctx.sessions_keyfile;
@@ -1039,14 +1069,19 @@ omemo_untrust(const char *const jid, const char *const fingerprint_formatted)
     GHashTableIter iter;
     gpointer key, value;
 
-    g_hash_table_iter_init(&iter, omemo_ctx.identity_key_store.trusted);
+    GHashTable *trusted = g_hash_table_lookup(omemo_ctx.identity_key_store.trusted, jid);
+    if (!trusted) {
+        return;
+    }
+
+    g_hash_table_iter_init(&iter, trusted);
     while (g_hash_table_iter_next(&iter, &key, &value)) {
         signal_buffer *buffer = value;
         unsigned char *original = signal_buffer_data(buffer);
         /* Skip DJB_TYPE byte */
         original++;
         if ((signal_buffer_len(buffer) - 1) == len && memcmp(original, fingerprint, len) == 0) {
-            g_hash_table_remove(omemo_ctx.identity_key_store.trusted, key);
+            g_hash_table_remove(trusted, key);
         }
     }
     free(fingerprint);
@@ -1214,28 +1249,44 @@ _load_identity(void)
         _generate_signed_pre_key();
     }
 
-    /* Trusted keys */
-    keys = g_key_file_get_keys(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_TRUST, NULL, NULL);
-    if (keys) {
-        int i;
-        for (i = 0; keys[i] != NULL; i++) {
-            char *key_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_TRUST, keys[i], NULL);
-            size_t key_len;
-            unsigned char *key = g_base64_decode(key_b64, &key_len);
-            g_free(key_b64);
-            signal_buffer *buffer = signal_buffer_create(key, key_len);
-            g_free(key);
-            g_hash_table_insert(omemo_ctx.identity_key_store.trusted, strdup(keys[i]), buffer);
-        }
-    }
-    g_strfreev(keys);
-
     loaded = TRUE;
 
     omemo_identity_keyfile_save();
 }
 
 static void
+_load_trust(void)
+{
+    char **keys = NULL;
+    char **groups = g_key_file_get_groups(omemo_ctx.trust_keyfile, NULL);
+    if (groups) {
+        int i;
+        for (i = 0; groups[i] != NULL; i++) {
+
+            keys = g_key_file_get_keys(omemo_ctx.trust_keyfile, groups[i], NULL, NULL);
+            int j;
+            for (j = 0; keys[j] != NULL; j++) {
+                char *key_b64 = g_key_file_get_string(omemo_ctx.trust_keyfile, groups[i], keys[j], NULL);
+                size_t key_len;
+                unsigned char *key = g_base64_decode(key_b64, &key_len);
+                g_free(key_b64);
+                signal_buffer *buffer = signal_buffer_create(key, key_len);
+                g_free(key);
+                uint32_t device_id = strtoul(keys[j], NULL, 10);
+                GHashTable *trusted = g_hash_table_lookup(omemo_ctx.identity_key_store.trusted, groups[i]);
+                if (!trusted) {
+                    trusted = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)signal_buffer_free);
+                    g_hash_table_insert(omemo_ctx.identity_key_store.trusted, strdup(groups[i]), trusted);
+                }
+                g_hash_table_insert(trusted, GINT_TO_POINTER(device_id), buffer);
+            }
+            g_strfreev(keys);
+        }
+        g_strfreev(groups);
+    }
+}
+
+static void
 _load_sessions(void)
 {
     int i;
@@ -1264,7 +1315,7 @@ _load_sessions(void)
             }
             g_strfreev(keys);
         }
-        free(groups);
+        g_strfreev(groups);
     }
 }
 
diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h
index 72e27429..e9186dfa 100644
--- a/src/omemo/omemo.h
+++ b/src/omemo/omemo.h
@@ -31,6 +31,8 @@ void omemo_prekeys(GList **prekeys, GList **ids, GList **lengths);
 void omemo_set_device_list(const char *const jid, GList * device_list);
 GKeyFile *omemo_identity_keyfile(void);
 void omemo_identity_keyfile_save(void);
+GKeyFile *omemo_trust_keyfile(void);
+void omemo_trust_keyfile_save(void);
 GKeyFile *omemo_sessions_keyfile(void);
 void omemo_sessions_keyfile_save(void);
 char *omemo_format_fingerprint(const char *const fingerprint);
diff --git a/src/omemo/store.c b/src/omemo/store.c
index 3520db6d..e380e12b 100644
--- a/src/omemo/store.c
+++ b/src/omemo/store.c
@@ -317,18 +317,24 @@ save_identity(const signal_protocol_address *address, uint8_t *key_data,
     size_t key_len, void *user_data)
 {
     identity_key_store_t *identity_key_store = (identity_key_store_t *)user_data;
-    char *node = g_strdup_printf("%s:%d", address->name, address->device_id);
 
     signal_buffer *buffer = signal_buffer_create(key_data, key_len);
-    g_hash_table_insert(identity_key_store->trusted, strdup(node), buffer);
+
+    GHashTable *trusted = g_hash_table_lookup(identity_key_store->trusted, strdup(address->name));
+    if (!trusted) {
+        trusted = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)signal_buffer_free);
+        g_hash_table_insert(identity_key_store->trusted, strdup(address->name), trusted);
+    }
+    g_hash_table_insert(trusted, GINT_TO_POINTER(address->device_id), buffer);
 
     /* Long term storage */
     char *key_b64 = g_base64_encode(key_data, key_len);
-    g_key_file_set_string(omemo_identity_keyfile(), OMEMO_STORE_GROUP_TRUST, node, key_b64);
+    char *device_id = g_strdup_printf("%d", address->device_id);
+    g_key_file_set_string(omemo_trust_keyfile(), address->name, strdup(device_id), key_b64);
+    g_free(device_id);
     g_free(key_b64);
 
-    omemo_identity_keyfile_save();
-    g_free(node);
+    omemo_trust_keyfile_save();
 
     return SG_SUCCESS;
 }
@@ -339,11 +345,14 @@ is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data,
 {
     int ret;
     identity_key_store_t *identity_key_store = (identity_key_store_t *)user_data;
-    char *node = g_strdup_printf("%s:%d", address->name, address->device_id);
+
+    GHashTable *trusted = g_hash_table_lookup(identity_key_store->trusted, address->name);
+    if (!trusted) {
+        return 0;
+    }
 
     signal_buffer *buffer = signal_buffer_create(key_data, key_len);
-    signal_buffer *original = g_hash_table_lookup(identity_key_store->trusted, node);
-    g_free(node);
+    signal_buffer *original = g_hash_table_lookup(trusted, GINT_TO_POINTER(address->device_id));
 
     ret = original != NULL && signal_buffer_compare(buffer, original) == 0;
 
diff --git a/src/omemo/store.h b/src/omemo/store.h
index 598f1bfa..d4096c90 100644
--- a/src/omemo/store.h
+++ b/src/omemo/store.h
@@ -5,7 +5,6 @@
 #define OMEMO_STORE_GROUP_IDENTITY "identity"
 #define OMEMO_STORE_GROUP_PREKEYS "prekeys"
 #define OMEMO_STORE_GROUP_SIGNED_PREKEYS "signed_prekeys"
-#define OMEMO_STORE_GROUP_TRUST "trust"
 #define OMEMO_STORE_KEY_DEVICE_ID "device_id"
 #define OMEMO_STORE_KEY_REGISTRATION_ID "registration_id"
 #define OMEMO_STORE_KEY_IDENTITY_KEY_PUBLIC "identity_key_public"