From e4bfda2f8a957f17c959269fa0beb606c7594da5 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Sun, 22 Mar 2026 17:14:24 +0100 Subject: [PATCH] fix: Incorrect omemo decryption error for Key Transport Messages Correctly handle OMEMO stanzas that contain a
but no . These "Key Transport Messages" (heartbeats) are used by some clients for session maintenance and establishing trust. Ref: a2726b6a7 made the element mandatory in the parser. Ref: 4d49c2b74 the bug became user-visible. Fixes: https://github.com/profanity-im/profanity/issues/2129 Signed-off-by: Michael Vetter --- src/omemo/omemo.c | 5 +++++ src/xmpp/message.c | 6 ++++++ src/xmpp/omemo.c | 28 ++++++++++++++-------------- src/xmpp/xmpp.h | 1 + 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 728fe5c1..9dac4d76 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -1145,6 +1145,11 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid, return NULL; } + if (payload == NULL) { + signal_buffer_free(plaintext_key); + return NULL; + } + size_t plaintext_len = payload_len; plaintext = malloc(plaintext_len + 1); res = aes128gcm_decrypt(plaintext, &plaintext_len, payload, payload_len, iv, diff --git a/src/xmpp/message.c b/src/xmpp/message.c index a154f7d3..09f90ba9 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -1102,6 +1102,8 @@ _handle_groupchat(xmpp_stanza_t* const stanza) case OMEMO_ERR_DECRYPT_FAILED: message->plain = g_strdup("OMEMO message received but decryption failed."); break; + case OMEMO_ERR_KEY_TRANSPORT: + break; default: message->plain = g_strdup("OMEMO message received but could not be decrypted."); break; @@ -1283,6 +1285,8 @@ _handle_muc_private_message(xmpp_stanza_t* const stanza) case OMEMO_ERR_DECRYPT_FAILED: message->plain = g_strdup("OMEMO message received but decryption failed."); break; + case OMEMO_ERR_KEY_TRANSPORT: + break; default: message->plain = g_strdup("OMEMO message received but could not be decrypted."); break; @@ -1471,6 +1475,8 @@ _handle_chat(xmpp_stanza_t* const stanza, gboolean is_mam, gboolean is_carbon, c case OMEMO_ERR_DECRYPT_FAILED: message->plain = g_strdup("OMEMO message received but decryption failed."); break; + case OMEMO_ERR_KEY_TRANSPORT: + break; default: message->plain = g_strdup("OMEMO message received but could not be decrypted."); break; diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index ca55d5f4..9238f493 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -333,6 +333,7 @@ omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted, omemo_erro unsigned char* payload_raw = NULL; char* iv_text = NULL; char* payload_text = NULL; + size_t payload_len = 0; *error = OMEMO_ERR_NONE; @@ -372,20 +373,15 @@ omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted, omemo_erro } xmpp_stanza_t* payload = xmpp_stanza_get_child_by_name(encrypted, "payload"); - if (!payload) { - *error = OMEMO_ERR_OTHER; - goto quit; - } - payload_text = xmpp_stanza_get_text(payload); - if (!payload_text) { - *error = OMEMO_ERR_OTHER; - goto quit; - } - size_t payload_len; - payload_raw = g_base64_decode(payload_text, &payload_len); - if (!payload_raw) { - *error = OMEMO_ERR_OTHER; - goto quit; + if (payload) { + payload_text = xmpp_stanza_get_text(payload); + if (payload_text) { + payload_raw = g_base64_decode(payload_text, &payload_len); + if (!payload_raw) { + *error = OMEMO_ERR_OTHER; + goto quit; + } + } } xmpp_stanza_t* key_stanza; @@ -425,6 +421,10 @@ omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted, omemo_erro keys, payload_raw, payload_len, g_strcmp0(type, STANZA_TYPE_GROUPCHAT) == 0, trusted, error); + if (plaintext == NULL && *error == OMEMO_ERR_NONE && payload == NULL) { + *error = OMEMO_ERR_KEY_TRANSPORT; + } + if (keys) { g_list_free_full(keys, (GDestroyNotify)omemo_key_free); } diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index c329d221..83d87fb6 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -132,6 +132,7 @@ typedef enum { OMEMO_ERR_DECRYPT_FAILED, OMEMO_ERR_INVALID_JID, OMEMO_ERR_MUC_SENDER_NOT_FOUND, + OMEMO_ERR_KEY_TRANSPORT, OMEMO_ERR_OTHER } omemo_error_t;