diff options
author | Paul Fariello <paul@fariello.eu> | 2019-03-07 08:00:29 +0140 |
---|---|---|
committer | Paul Fariello <paul@fariello.eu> | 2019-04-10 16:31:45 +0200 |
commit | 55407ee15f0ebdf93c076ae5ea28ec865497b121 (patch) | |
tree | 01057228ff99f86bbca8c7c929f88b273acc3554 /src/omemo | |
parent | 5eb66aea267c53c63af6dd76fe2555f113051fcd (diff) | |
download | profani-tty-55407ee15f0ebdf93c076ae5ea28ec865497b121.tar.gz |
Add OMEMO session long term storage
Diffstat (limited to 'src/omemo')
-rw-r--r-- | src/omemo/omemo.c | 115 | ||||
-rw-r--r-- | src/omemo/omemo.h | 2 | ||||
-rw-r--r-- | src/omemo/store.c | 8 |
3 files changed, 95 insertions, 30 deletions
diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 169623f4..3a771b6b 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -52,6 +52,8 @@ struct omemo_context_t { GHashTable *device_ids; GString *identity_filename; GKeyFile *identity_keyfile; + GString *sessions_filename; + GKeyFile *sessions_keyfile; }; static omemo_context omemo_ctx; @@ -169,15 +171,18 @@ 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.sessions_filename = g_string_new(basedir->str); + g_string_append(omemo_ctx.sessions_filename, "sessions.txt"); + errno = 0; int res = g_mkdir_with_parents(basedir->str, S_IRWXU); if (res == -1) { char *errmsg = strerror(errno); if (errmsg) { - log_error("Error creating directory: %s, %s", omemo_ctx.identity_filename->str, errmsg); + log_error("Error creating directory: %s, %s", basedir->str, errmsg); } else { - log_error("Error creating directory: %s", omemo_ctx.identity_filename->str); + log_error("Error creating directory: %s", basedir->str); } } @@ -208,6 +213,32 @@ omemo_on_connect(ProfAccount *account) 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); + } + } + } } void @@ -395,6 +426,22 @@ omemo_set_device_list(const char *const jid, GList * device_list) free(barejid); } +GKeyFile * +omemo_sessions_keyfile(void) +{ + return omemo_ctx.sessions_keyfile; +} + +void +omemo_sessions_keyfile_save(void) +{ + GError *error = NULL; + + if (!g_key_file_save_to_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, &error)) { + log_error("Error saving OMEMO sessions to: %s, %s", omemo_ctx.sessions_filename->str, error->message); + } +} + void omemo_start_device_session(const char *const jid, uint32_t device_id, GList *prekeys, uint32_t signed_prekey_id, @@ -402,34 +449,42 @@ omemo_start_device_session(const char *const jid, uint32_t device_id, const unsigned char *const signature, size_t signature_len, const unsigned char *const identity_key_raw, size_t identity_key_len) { - log_info("Start OMEMO session with %s device %d", jid, device_id); - session_pre_key_bundle *bundle; - signal_protocol_address *address; - - address = malloc(sizeof(signal_protocol_address)); - address->name = strdup(jid); - address->name_len = strlen(jid); - address->device_id = device_id; - - session_builder *builder; - session_builder_create(&builder, omemo_ctx.store, address, omemo_ctx.signal); - - int prekey_index; - gcry_randomize(&prekey_index, sizeof(int), GCRY_STRONG_RANDOM); - prekey_index %= g_list_length(prekeys); - omemo_key_t *prekey = g_list_nth_data(prekeys, prekey_index); - - ec_public_key *prekey_public; - curve_decode_point(&prekey_public, prekey->data, prekey->length, omemo_ctx.signal); - ec_public_key *signed_prekey; - curve_decode_point(&signed_prekey, signed_prekey_raw, signed_prekey_len, omemo_ctx.signal); - ec_public_key *identity_key; - curve_decode_point(&identity_key, identity_key_raw, identity_key_len, omemo_ctx.signal); - - session_pre_key_bundle_create(&bundle, 0, device_id, prekey->id, prekey_public, signed_prekey_id, signed_prekey, signature, signature_len, identity_key); - session_builder_process_pre_key_bundle(builder, bundle); - - g_list_free_full(prekeys, (GDestroyNotify)free_omemo_key); + signal_protocol_address address = { + .name = strdup(jid), + .name_len = strlen(jid), + .device_id = device_id, + }; + + if (!contains_session(&address, omemo_ctx.session_store)) { + log_info("Create OMEMO session with %s device %d", jid, device_id); + session_pre_key_bundle *bundle; + signal_protocol_address *address; + + address = malloc(sizeof(signal_protocol_address)); + address->name = strdup(jid); + address->name_len = strlen(jid); + address->device_id = device_id; + + session_builder *builder; + session_builder_create(&builder, omemo_ctx.store, address, omemo_ctx.signal); + + int prekey_index; + gcry_randomize(&prekey_index, sizeof(int), GCRY_STRONG_RANDOM); + prekey_index %= g_list_length(prekeys); + omemo_key_t *prekey = g_list_nth_data(prekeys, prekey_index); + + ec_public_key *prekey_public; + curve_decode_point(&prekey_public, prekey->data, prekey->length, omemo_ctx.signal); + ec_public_key *signed_prekey; + curve_decode_point(&signed_prekey, signed_prekey_raw, signed_prekey_len, omemo_ctx.signal); + ec_public_key *identity_key; + curve_decode_point(&identity_key, identity_key_raw, identity_key_len, omemo_ctx.signal); + + session_pre_key_bundle_create(&bundle, 0, device_id, prekey->id, prekey_public, signed_prekey_id, signed_prekey, signature, signature_len, identity_key); + session_builder_process_pre_key_bundle(builder, bundle); + + g_list_free_full(prekeys, (GDestroyNotify)free_omemo_key); + } } gboolean diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h index 84f21e64..ef43617d 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_sessions_keyfile(void); +void omemo_sessions_keyfile_save(void); void omemo_start_session(const char *const barejid); 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, size_t signed_prekey_len, const unsigned char *const signature, size_t signature_len, const unsigned char *const identity_key, size_t identity_key_len); diff --git a/src/omemo/store.c b/src/omemo/store.c index 9fec33e5..93289b90 100644 --- a/src/omemo/store.c +++ b/src/omemo/store.c @@ -1,6 +1,7 @@ #include <glib.h> #include <signal/signal_protocol.h> +#include "omemo/omemo.h" #include "omemo/store.h" GHashTable * @@ -90,6 +91,13 @@ store_session(const signal_protocol_address *address, uint8_t *record, signal_buffer *buffer = signal_buffer_create(record, record_len); g_hash_table_insert(device_store, GINT_TO_POINTER(address->device_id), buffer); + + + char *record_b64 = g_base64_encode(record, record_len); + g_key_file_set_string(omemo_sessions_keyfile(), address->name, g_strdup_printf("%d", address->device_id), record_b64); + + omemo_sessions_keyfile_save(); + return SG_SUCCESS; } |