From bf8b89c568cbc6e2bc2c7dfe058b13a6ec33215a Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Wed, 6 Mar 2019 17:10:28 +0100 Subject: [PATCH] Randomly choose a prekey on session build --- src/omemo/omemo.c | 34 ++++++++++++++++++++++++++-------- src/omemo/omemo.h | 3 ++- src/xmpp/omemo.c | 41 ++++++++++++++++++++++------------------- 3 files changed, 50 insertions(+), 28 deletions(-) diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 98448a73..b7c31cd6 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -30,6 +30,7 @@ static void unlock(void *user_data); static void omemo_log(int level, const char *message, size_t len, void *user_data); static gboolean handle_own_device_list(const char *const jid, GList *device_list); static gboolean handle_device_list_start_session(const char *const jid, GList *device_list); +static void free_omemo_key(omemo_key_t *key); typedef gboolean (*OmemoDeviceListHandler)(const char *const jid, GList *device_list); @@ -396,11 +397,10 @@ omemo_set_device_list(const char *const jid, GList * device_list) void omemo_start_device_session(const char *const jid, uint32_t device_id, - uint32_t prekey_id, const unsigned char *const prekey_raw, size_t prekey_len, - uint32_t signed_prekey_id, const unsigned char *const signed_prekey_raw, - size_t signed_prekey_len, const unsigned char *const signature, - size_t signature_len, const unsigned char *const identity_key_raw, - size_t identity_key_len) + GList *prekeys, uint32_t signed_prekey_id, + const unsigned char *const signed_prekey_raw, size_t signed_prekey_len, + 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; @@ -414,15 +414,22 @@ omemo_start_device_session(const char *const jid, uint32_t device_id, session_builder *builder; session_builder_create(&builder, omemo_ctx.store, address, omemo_ctx.signal); - ec_public_key *prekey; - curve_decode_point(&prekey, prekey_raw, prekey_len, 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, signed_prekey_id, signed_prekey, signature, signature_len, identity_key); + 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 @@ -662,3 +669,14 @@ handle_device_list_start_session(const char *const jid, GList *device_list) return FALSE; } + +static void +free_omemo_key(omemo_key_t *key) +{ + if (key == NULL) { + return; + } + + free((void *)key->data); + free(key); +} diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h index f07d42bc..84f21e64 100644 --- a/src/omemo/omemo.h +++ b/src/omemo/omemo.h @@ -13,6 +13,7 @@ typedef struct omemo_key { size_t length; gboolean prekey; uint32_t device_id; + uint32_t id; } omemo_key_t; void omemo_init(void); @@ -27,7 +28,7 @@ void omemo_prekeys(GList **prekeys, GList **ids, GList **lengths); void omemo_set_device_list(const char *const jid, GList * device_list); void omemo_start_session(const char *const barejid); -void omemo_start_device_session(const char *const jid, uint32_t device_id, uint32_t prekey_id, const unsigned char *const prekey, size_t prekey_len, 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); +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); gboolean omemo_loaded(void); gboolean omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt); diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index 25057d55..f68f7d6e 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -129,22 +129,26 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *cons return 1; } - /* Should be random */ - xmpp_stanza_t *prekey = xmpp_stanza_get_children(prekeys); - if (!prekey) { - return 1; + GList *prekeys_list = NULL; + xmpp_stanza_t *prekey; + for (prekey = xmpp_stanza_get_children(prekeys); prekey != NULL; prekey = xmpp_stanza_get_next(prekey)) { + omemo_key_t *key = malloc(sizeof(omemo_key_t)); + + const char *prekey_id_text = xmpp_stanza_get_attribute(prekey, "preKeyId"); + if (!prekey_id_text) { + return 1; + } + key->id = strtoul(prekey_id_text, NULL, 10); + xmpp_stanza_t *prekey_text = xmpp_stanza_get_children(prekey); + if (!prekey_text) { + return 1; + } + key->data = g_base64_decode(xmpp_stanza_get_text(prekey_text), &key->length); + key->prekey = TRUE; + key->device_id = device_id; + + prekeys_list = g_list_append(prekeys_list, key); } - const char *prekey_id_text = xmpp_stanza_get_attribute(prekey, "preKeyId"); - if (!prekey_id_text) { - return 1; - } - uint32_t prekey_id = strtoul(prekey_id_text, NULL, 10); - xmpp_stanza_t *prekey_text = xmpp_stanza_get_children(prekey); - if (!prekey_text) { - return 1; - } - size_t prekey_len; - unsigned char *prekey_raw = g_base64_decode(xmpp_stanza_get_text(prekey_text), &prekey_len); xmpp_stanza_t *signed_prekey = xmpp_stanza_get_child_by_name(bundle, "signedPreKeyPublic"); if (!signed_prekey) { @@ -184,10 +188,9 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *cons size_t identity_key_len; unsigned char *identity_key_raw = g_base64_decode(xmpp_stanza_get_text(identity_key_text), &identity_key_len); - omemo_start_device_session(from, device_id, prekey_id, prekey_raw, - prekey_len, signed_prekey_id, signed_prekey_raw, signed_prekey_len, - signed_prekey_signature_raw, signed_prekey_signature_len, - identity_key_raw, identity_key_len); + omemo_start_device_session(from, device_id, prekeys_list, signed_prekey_id, + signed_prekey_raw, signed_prekey_len, signed_prekey_signature_raw, + signed_prekey_signature_len, identity_key_raw, identity_key_len); return 1; }