mirror of
https://github.com/profanity-im/profanity.git
synced 2024-12-04 14:46:46 -05:00
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.
This commit is contained in:
parent
249701fe7a
commit
23485eb4e7
@ -25,6 +25,8 @@
|
|||||||
static gboolean loaded;
|
static gboolean loaded;
|
||||||
|
|
||||||
static void omemo_generate_short_term_crypto_materials(ProfAccount *account);
|
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 lock(void *user_data);
|
||||||
static void unlock(void *user_data);
|
static void unlock(void *user_data);
|
||||||
static void omemo_log(int level, const char *message, size_t len, 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();
|
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)) {
|
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);
|
load_identity();
|
||||||
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);
|
omemo_generate_short_term_crypto_materials(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
omemo_ctx.sessions_keyfile = g_key_file_new();
|
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)) {
|
if (g_key_file_load_from_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
|
||||||
int i;
|
load_sessions();
|
||||||
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
|
void
|
||||||
omemo_generate_crypto_materials(ProfAccount *account)
|
omemo_generate_crypto_materials(ProfAccount *account)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
return;
|
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_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);
|
g_free(identity_key_private);
|
||||||
|
|
||||||
if (!g_key_file_save_to_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, &error)) {
|
omemo_identity_keyfile_save();
|
||||||
log_error("Error saving OMEMO identity to: %s, %s", omemo_ctx.identity_filename->str, error->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
omemo_generate_short_term_crypto_materials(account);
|
omemo_generate_short_term_crypto_materials(account);
|
||||||
}
|
}
|
||||||
@ -426,6 +381,22 @@ omemo_set_device_list(const char *const jid, GList * device_list)
|
|||||||
free(barejid);
|
free(barejid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 *
|
GKeyFile *
|
||||||
omemo_sessions_keyfile(void)
|
omemo_sessions_keyfile(void)
|
||||||
{
|
{
|
||||||
@ -802,3 +773,73 @@ free_omemo_key(omemo_key_t *key)
|
|||||||
free((void *)key->data);
|
free((void *)key->data);
|
||||||
free(key);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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_signed_prekey_signature(unsigned char **output, size_t *length);
|
||||||
void omemo_prekeys(GList **prekeys, GList **ids, GList **lengths);
|
void omemo_prekeys(GList **prekeys, GList **ids, GList **lengths);
|
||||||
void omemo_set_device_list(const char *const jid, GList * device_list);
|
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);
|
GKeyFile *omemo_sessions_keyfile(void);
|
||||||
void omemo_sessions_keyfile_save(void);
|
void omemo_sessions_keyfile_save(void);
|
||||||
char *omemo_fingerprint(const unsigned char *const identity_key_public, size_t len);
|
char *omemo_fingerprint(const unsigned char *const identity_key_public, size_t len);
|
||||||
|
@ -26,7 +26,7 @@ signed_pre_key_store_new(void)
|
|||||||
void
|
void
|
||||||
identity_key_store_new(identity_key_store_t *identity_key_store)
|
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->private = NULL;
|
||||||
identity_key_store->public = 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);
|
char *node = g_strdup_printf("%s:%d", address->name, address->device_id);
|
||||||
|
|
||||||
signal_buffer *buffer = signal_buffer_create(key_data, key_len);
|
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;
|
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);
|
char *node = g_strdup_printf("%s:%d", address->name, address->device_id);
|
||||||
|
|
||||||
signal_buffer *buffer = signal_buffer_create(key_data, key_len);
|
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
|
int
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define OMEMO_STORE_GROUP_IDENTITY "identity"
|
#define OMEMO_STORE_GROUP_IDENTITY "identity"
|
||||||
|
#define OMEMO_STORE_GROUP_TRUST "trust"
|
||||||
#define OMEMO_STORE_KEY_DEVICE_ID "device_id"
|
#define OMEMO_STORE_KEY_DEVICE_ID "device_id"
|
||||||
#define OMEMO_STORE_KEY_REGISTRATION_ID "registration_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_PUBLIC "identity_key_public"
|
||||||
@ -12,7 +13,7 @@ typedef struct {
|
|||||||
signal_buffer *public;
|
signal_buffer *public;
|
||||||
signal_buffer *private;
|
signal_buffer *private;
|
||||||
uint32_t registration_id;
|
uint32_t registration_id;
|
||||||
GHashTable * identity_key_store;
|
GHashTable *trusted;
|
||||||
} identity_key_store_t;
|
} identity_key_store_t;
|
||||||
|
|
||||||
GHashTable * session_store_new(void);
|
GHashTable * session_store_new(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user