about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorPaul Fariello <paul@fariello.eu>2019-03-06 17:10:28 +0100
committerPaul Fariello <paul@fariello.eu>2019-04-10 16:31:45 +0200
commitbf8b89c568cbc6e2bc2c7dfe058b13a6ec33215a (patch)
treee29b3b1a7950b1646767a065499548cfaece4fb7
parentba0fa6e5360ce9350df469724d912be5644ac62b (diff)
downloadprofani-tty-bf8b89c568cbc6e2bc2c7dfe058b13a6ec33215a.tar.gz
Randomly choose a prekey on session build
-rw-r--r--src/omemo/omemo.c34
-rw-r--r--src/omemo/omemo.h3
-rw-r--r--src/xmpp/omemo.c41
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;
-    }
-    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;
+    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);
     }
-    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;
 }