mirror of
https://github.com/profanity-im/profanity.git
synced 2024-11-03 19:37:16 -05:00
Add OMEMO identity materials long term storage
This commit is contained in:
parent
810ea32223
commit
421d1b1560
@ -50,6 +50,7 @@
|
||||
#define DIR_CHATLOGS "chatlogs"
|
||||
#define DIR_OTR "otr"
|
||||
#define DIR_PGP "pgp"
|
||||
#define DIR_OMEMO "omemo"
|
||||
#define DIR_PLUGINS "plugins"
|
||||
|
||||
void files_create_directories(void);
|
||||
|
@ -59,6 +59,10 @@
|
||||
#include "pgp/gpg.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OMEMO
|
||||
#include "omemo/omemo.h"
|
||||
#endif
|
||||
|
||||
#include "ui/ui.h"
|
||||
|
||||
void
|
||||
@ -76,6 +80,10 @@ sv_ev_login_account_success(char *account_name, gboolean secured)
|
||||
p_gpg_on_connect(account->jid);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OMEMO
|
||||
omemo_on_connect(account);
|
||||
#endif
|
||||
|
||||
ui_handle_login_account_success(account, secured);
|
||||
|
||||
// attempt to rejoin rooms with passwords
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <pthread.h>
|
||||
#include <signal/key_helper.h>
|
||||
@ -18,9 +20,11 @@
|
||||
#include "xmpp/xmpp.h"
|
||||
#include "xmpp/connection.h"
|
||||
#include "xmpp/omemo.h"
|
||||
#include "config/files.h"
|
||||
|
||||
static gboolean loaded;
|
||||
|
||||
static void omemo_generate_short_term_crypto_materials(ProfAccount *account);
|
||||
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);
|
||||
@ -41,6 +45,8 @@ struct omemo_context_t {
|
||||
GHashTable *signed_pre_key_store;
|
||||
identity_key_store_t identity_key_store;
|
||||
GHashTable *device_ids;
|
||||
GString *identity_filename;
|
||||
GKeyFile *identity_keyfile;
|
||||
};
|
||||
|
||||
static omemo_context omemo_ctx;
|
||||
@ -142,15 +148,98 @@ omemo_init(void)
|
||||
}
|
||||
|
||||
void
|
||||
omemo_generate_crypto_materials(ProfAccount *account)
|
||||
omemo_on_connect(ProfAccount *account)
|
||||
{
|
||||
xmpp_ctx_t * const ctx = connection_get_ctx();
|
||||
char *barejid = xmpp_jid_bare(ctx, session_get_account_name());
|
||||
char *omemodir = files_get_data_path(DIR_OMEMO);
|
||||
GString *basedir = g_string_new(omemodir);
|
||||
free(omemodir);
|
||||
gchar *account_dir = str_replace(barejid, "@", "_at_");
|
||||
g_string_append(basedir, "/");
|
||||
g_string_append(basedir, account_dir);
|
||||
g_string_append(basedir, "/");
|
||||
free(account_dir);
|
||||
|
||||
omemo_ctx.identity_filename = g_string_new(basedir->str);
|
||||
g_string_append(omemo_ctx.identity_filename, "identity.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);
|
||||
} else {
|
||||
log_error("Error creating directory: %s", omemo_ctx.identity_filename->str);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
omemo_generate_short_term_crypto_materials(account);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
omemo_generate_crypto_materials(ProfAccount *account)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
omemo_ctx.device_id = randombytes_uniform(0x80000000);
|
||||
|
||||
signal_protocol_key_helper_generate_identity_key_pair(&omemo_ctx.identity_key_pair, omemo_ctx.signal);
|
||||
signal_protocol_key_helper_generate_registration_id(&omemo_ctx.registration_id, 0, omemo_ctx.signal);
|
||||
|
||||
ec_public_key_serialize(&omemo_ctx.identity_key_store.public, ratchet_identity_key_pair_get_public(omemo_ctx.identity_key_pair));
|
||||
ec_private_key_serialize(&omemo_ctx.identity_key_store.private, ratchet_identity_key_pair_get_private(omemo_ctx.identity_key_pair));
|
||||
|
||||
g_key_file_set_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_DEVICE_ID, omemo_ctx.device_id);
|
||||
g_key_file_set_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_REGISTRATION_ID, omemo_ctx.registration_id);
|
||||
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));
|
||||
g_key_file_set_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PUBLIC, identity_key_public);
|
||||
g_free(identity_key_public);
|
||||
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));
|
||||
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_generate_short_term_crypto_materials(account);
|
||||
}
|
||||
|
||||
static void
|
||||
omemo_generate_short_term_crypto_materials(ProfAccount *account)
|
||||
{
|
||||
signal_protocol_key_helper_generate_pre_keys(&omemo_ctx.pre_keys_head, randombytes_random(), 100, omemo_ctx.signal);
|
||||
|
||||
struct timeval tv;
|
||||
@ -158,14 +247,14 @@ omemo_generate_crypto_materials(ProfAccount *account)
|
||||
unsigned long long timestamp = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
|
||||
signal_protocol_key_helper_generate_signed_pre_key(&omemo_ctx.signed_pre_key, omemo_ctx.identity_key_pair, 5, timestamp, omemo_ctx.signal);
|
||||
|
||||
ec_public_key_serialize(&omemo_ctx.identity_key_store.public, ratchet_identity_key_pair_get_public(omemo_ctx.identity_key_pair));
|
||||
ec_private_key_serialize(&omemo_ctx.identity_key_store.private, ratchet_identity_key_pair_get_private(omemo_ctx.identity_key_pair));
|
||||
|
||||
loaded = TRUE;
|
||||
|
||||
/* Ensure we get our current device list, and it gets updated with our
|
||||
* device_id */
|
||||
xmpp_ctx_t * const ctx = connection_get_ctx();
|
||||
char *barejid = xmpp_jid_bare(ctx, session_get_account_name());
|
||||
omemo_devicelist_request(barejid);
|
||||
|
||||
omemo_bundle_publish();
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ typedef struct omemo_key {
|
||||
} omemo_key_t;
|
||||
|
||||
void omemo_init(void);
|
||||
void omemo_on_connect(ProfAccount *account);
|
||||
void omemo_generate_crypto_materials(ProfAccount *account);
|
||||
|
||||
uint32_t omemo_device_id(void);
|
||||
|
@ -1,5 +1,11 @@
|
||||
#include <signal/signal_protocol.h>
|
||||
|
||||
#define OMEMO_STORE_GROUP_IDENTITY "identity"
|
||||
#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"
|
||||
#define OMEMO_STORE_KEY_IDENTITY_KEY_PRIVATE "identity_key_private"
|
||||
|
||||
typedef struct {
|
||||
signal_buffer *public;
|
||||
signal_buffer *private;
|
||||
|
Loading…
Reference in New Issue
Block a user