about summary refs log tree commit diff stats
path: root/src/omemo
diff options
context:
space:
mode:
authorPaul Fariello <paul@fariello.eu>2019-03-07 19:38:15 +0140
committerPaul Fariello <paul@fariello.eu>2019-04-10 17:12:31 +0200
commit23485eb4e7e2f31cb72ba03c3ec2110bafe25a36 (patch)
tree09335d95e73f71e89f31c9dcdd915acdf0b82499 /src/omemo
parent249701fe7a20247b85f4bad59158ba1215419cc3 (diff)
downloadprofani-tty-23485eb4e7e2f31cb72ba03c3ec2110bafe25a36.tar.gz
Don't trust unknown identity keys
Also add long terme storage of known identity keys.
If a key is stored it means it is trusted.
Diffstat (limited to 'src/omemo')
-rw-r--r--src/omemo/omemo.c141
-rw-r--r--src/omemo/omemo.h2
-rw-r--r--src/omemo/store.c14
-rw-r--r--src/omemo/store.h3
4 files changed, 105 insertions, 55 deletions
diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c
index b293022f..d649ff7e 100644
--- a/src/omemo/omemo.c
+++ b/src/omemo/omemo.c
@@ -25,6 +25,8 @@
 static gboolean loaded;
 
 static void omemo_generate_short_term_crypto_materials(ProfAccount *account);
+static void load_identity(void);
+static void load_sessions(void);
 static void lock(void *user_data);
 static void unlock(void *user_data);
 static void omemo_log(int level, const char *message, size_t len, void *user_data);
@@ -188,64 +190,19 @@ omemo_on_connect(ProfAccount *account)
 
     omemo_ctx.identity_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, NULL)) {
-        omemo_ctx.device_id = g_key_file_get_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_DEVICE_ID, NULL);
-        omemo_ctx.registration_id = g_key_file_get_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_REGISTRATION_ID, NULL);
-
-        char *identity_key_public_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PUBLIC, NULL);
-        size_t identity_key_public_len;
-        unsigned char *identity_key_public = g_base64_decode(identity_key_public_b64, &identity_key_public_len);
-        omemo_ctx.identity_key_store.public = signal_buffer_create(identity_key_public, identity_key_public_len);
-
-        char *identity_key_private_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PRIVATE, NULL);
-        size_t identity_key_private_len;
-        unsigned char *identity_key_private = g_base64_decode(identity_key_private_b64, &identity_key_private_len);
-        omemo_ctx.identity_key_store.private = signal_buffer_create(identity_key_private, identity_key_private_len);
-        signal_buffer_create(identity_key_private, identity_key_private_len);
-
-        ec_public_key *public_key;
-        curve_decode_point(&public_key, identity_key_public, identity_key_public_len, omemo_ctx.signal);
-        ec_private_key *private_key;
-        curve_decode_private_point(&private_key, identity_key_private, identity_key_private_len, omemo_ctx.signal);
-        ratchet_identity_key_pair_create(&omemo_ctx.identity_key_pair, public_key, private_key);
-
-        g_free(identity_key_public);
-        g_free(identity_key_private);
-
+        load_identity();
         omemo_generate_short_term_crypto_materials(account);
     }
 
     omemo_ctx.sessions_keyfile = g_key_file_new();
     if (g_key_file_load_from_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
-        int i;
-        char **groups = g_key_file_get_groups(omemo_ctx.sessions_keyfile, NULL);
-        for (i = 0; groups[i] != NULL; i++) {
-            int j;
-            GHashTable *device_store = NULL;
-
-            device_store = g_hash_table_lookup(omemo_ctx.session_store, groups[i]);
-            if (!device_store) {
-                device_store = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)signal_buffer_free);
-                g_hash_table_insert(omemo_ctx.session_store, groups[i], device_store);
-            }
-
-            char **keys = g_key_file_get_keys(omemo_ctx.sessions_keyfile, groups[i], NULL, NULL);
-            for (j = 0; keys[j] != NULL; j++) {
-                uint32_t id = strtoul(keys[j], NULL, 10);
-                char *record_b64 = g_key_file_get_string(omemo_ctx.sessions_keyfile, groups[i], keys[j], NULL);
-                size_t record_len;
-                unsigned char *record = g_base64_decode(record_b64, &record_len);
-                signal_buffer *buffer = signal_buffer_create(record, record_len);
-                g_hash_table_insert(device_store, GINT_TO_POINTER(id), buffer);
-            }
-        }
+        load_sessions();
     }
 }
 
 void
 omemo_generate_crypto_materials(ProfAccount *account)
 {
-    GError *error = NULL;
-
     if (loaded) {
         return;
     }
@@ -268,9 +225,7 @@ omemo_generate_crypto_materials(ProfAccount *account)
     g_key_file_set_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PRIVATE, identity_key_private);
     g_free(identity_key_private);
 
-    if (!g_key_file_save_to_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, &error)) {
-        log_error("Error saving OMEMO identity to: %s, %s", omemo_ctx.identity_filename->str, error->message);
-    }
+    omemo_identity_keyfile_save();
 
     omemo_generate_short_term_crypto_materials(account);
 }
@@ -427,6 +382,22 @@ omemo_set_device_list(const char *const jid, GList * device_list)
 }
 
 GKeyFile *
+omemo_identity_keyfile(void)
+{
+    return omemo_ctx.identity_keyfile;
+}
+
+void
+omemo_identity_keyfile_save(void)
+{
+    GError *error = NULL;
+
+    if (!g_key_file_save_to_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, &error)) {
+        log_error("Error saving OMEMO identity to: %s, %s", omemo_ctx.identity_filename->str, error->message);
+    }
+}
+
+GKeyFile *
 omemo_sessions_keyfile(void)
 {
     return omemo_ctx.sessions_keyfile;
@@ -802,3 +773,73 @@ free_omemo_key(omemo_key_t *key)
     free((void *)key->data);
     free(key);
 }
+
+static void
+load_identity(void)
+{
+    omemo_ctx.device_id = g_key_file_get_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_DEVICE_ID, NULL);
+    omemo_ctx.registration_id = g_key_file_get_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_REGISTRATION_ID, NULL);
+
+    char *identity_key_public_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PUBLIC, NULL);
+    size_t identity_key_public_len;
+    unsigned char *identity_key_public = g_base64_decode(identity_key_public_b64, &identity_key_public_len);
+    omemo_ctx.identity_key_store.public = signal_buffer_create(identity_key_public, identity_key_public_len);
+
+    char *identity_key_private_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PRIVATE, NULL);
+    size_t identity_key_private_len;
+    unsigned char *identity_key_private = g_base64_decode(identity_key_private_b64, &identity_key_private_len);
+    omemo_ctx.identity_key_store.private = signal_buffer_create(identity_key_private, identity_key_private_len);
+    signal_buffer_create(identity_key_private, identity_key_private_len);
+
+    ec_public_key *public_key;
+    curve_decode_point(&public_key, identity_key_public, identity_key_public_len, omemo_ctx.signal);
+    ec_private_key *private_key;
+    curve_decode_private_point(&private_key, identity_key_private, identity_key_private_len, omemo_ctx.signal);
+    ratchet_identity_key_pair_create(&omemo_ctx.identity_key_pair, public_key, private_key);
+
+    g_free(identity_key_public);
+    g_free(identity_key_private);
+
+    char **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);
+            signal_buffer *buffer = signal_buffer_create(key, key_len);
+            g_hash_table_insert(omemo_ctx.identity_key_store.trusted, keys[i], buffer);
+            free(key_b64);
+        }
+    }
+}
+
+static void
+load_sessions(void)
+{
+    int i;
+    char **groups = g_key_file_get_groups(omemo_ctx.sessions_keyfile, NULL);
+    if (groups) {
+        for (i = 0; groups[i] != NULL; i++) {
+            int j;
+            GHashTable *device_store = NULL;
+
+            device_store = g_hash_table_lookup(omemo_ctx.session_store, groups[i]);
+            if (!device_store) {
+                device_store = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)signal_buffer_free);
+                g_hash_table_insert(omemo_ctx.session_store, groups[i], device_store);
+            }
+
+            char **keys = g_key_file_get_keys(omemo_ctx.sessions_keyfile, groups[i], NULL, NULL);
+            for (j = 0; keys[j] != NULL; j++) {
+                uint32_t id = strtoul(keys[j], NULL, 10);
+                char *record_b64 = g_key_file_get_string(omemo_ctx.sessions_keyfile, groups[i], keys[j], NULL);
+                size_t record_len;
+                unsigned char *record = g_base64_decode(record_b64, &record_len);
+                signal_buffer *buffer = signal_buffer_create(record, record_len);
+                g_hash_table_insert(device_store, GINT_TO_POINTER(id), buffer);
+                free(record_b64);
+            }
+        }
+    }
+}
diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h
index 88c6d27c..72d3d3aa 100644
--- a/src/omemo/omemo.h
+++ b/src/omemo/omemo.h
@@ -26,6 +26,8 @@ void omemo_signed_prekey(unsigned char **output, size_t *length);
 void omemo_signed_prekey_signature(unsigned char **output, size_t *length);
 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_sessions_keyfile(void);
 void omemo_sessions_keyfile_save(void);
 char *omemo_fingerprint(const unsigned char *const identity_key_public, size_t len);
diff --git a/src/omemo/store.c b/src/omemo/store.c
index eee58e19..621c902c 100644
--- a/src/omemo/store.c
+++ b/src/omemo/store.c
@@ -26,7 +26,7 @@ signed_pre_key_store_new(void)
 void
 identity_key_store_new(identity_key_store_t *identity_key_store)
 {
-    identity_key_store->identity_key_store = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)signal_buffer_free);
+    identity_key_store->trusted = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)signal_buffer_free);
     identity_key_store->private = NULL;
     identity_key_store->public = NULL;
 }
@@ -279,7 +279,13 @@ save_identity(const signal_protocol_address *address, uint8_t *key_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->identity_key_store, node, buffer);
+    g_hash_table_insert(identity_key_store->trusted, strdup(node), buffer);
+
+    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);
+
+    omemo_identity_keyfile_save();
+    free(node);
 
     return SG_SUCCESS;
 }
@@ -292,9 +298,9 @@ is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data,
     char *node = g_strdup_printf("%s:%d", address->name, address->device_id);
 
     signal_buffer *buffer = signal_buffer_create(key_data, key_len);
-    signal_buffer *original = g_hash_table_lookup(identity_key_store->identity_key_store, node);
+    signal_buffer *original = g_hash_table_lookup(identity_key_store->trusted, node);
 
-    return original == NULL || signal_buffer_compare(buffer, original) == 0;
+    return original != NULL && signal_buffer_compare(buffer, original) == 0;
 }
 
 int
diff --git a/src/omemo/store.h b/src/omemo/store.h
index 986b7c42..03800f84 100644
--- a/src/omemo/store.h
+++ b/src/omemo/store.h
@@ -3,6 +3,7 @@
 #include "config.h"
 
 #define OMEMO_STORE_GROUP_IDENTITY "identity"
+#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"
@@ -12,7 +13,7 @@ typedef struct {
    signal_buffer *public;
    signal_buffer *private;
    uint32_t registration_id;
-   GHashTable * identity_key_store;
+   GHashTable *trusted;
 } identity_key_store_t;
 
 GHashTable * session_store_new(void);