Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

Please unblock package gajim-omemo

There was a recent change in the OMEMO encryption protocol
(#859894), that makes it necessary to change this plugin.
Otherwise users could not communicate securely with users of
e.g. the latest version of Conversations. Therefore the first
patch, using only code from newer upstream versions.

Three more patches are added, again using only code from newer
upstream versions, to fix another incompatibility with the
standard, another security relevant bug (icon displays secure
connection, when in fact it is not), and finally a possible
crash.

Note, that there is also a new package 1.2.0-1 with all upstream
fixes and without any Debian patches, in experimental.

diff -Nru gajim-omemo-1.0.0/debian/changelog gajim-omemo-1.0.0/debian/changelog
--- gajim-omemo-1.0.0/debian/changelog  2016-12-07 23:33:40.000000000 +0100
+++ gajim-omemo-1.0.0/debian/changelog  2017-04-09 01:09:34.000000000 +0200
@@ -1,3 +1,12 @@
+gajim-omemo (1.0.0-2) unstable; urgency=medium
+
+  * Add patch for XEP-0384 compliance. (Closes: #859894)
+  * Add patch for XEP-0380 compliance (correct EME element)
+  * Add patch to hide lock icon, when OMEMO encryption is disabled
+  * Add patch to not handle "normal" messages, prevents crash
+
+ -- W. Martin Borgert <deba...@debian.org>  Sat, 08 Apr 2017 23:09:34 +0000
+
 gajim-omemo (1.0.0-1) unstable; urgency=medium
 
   * New upstream version
diff -Nru gajim-omemo-1.0.0/debian/patches/do_not_handle_type_normal_messages 
gajim-omemo-1.0.0/debian/patches/do_not_handle_type_normal_messages
--- gajim-omemo-1.0.0/debian/patches/do_not_handle_type_normal_messages 
1970-01-01 01:00:00.000000000 +0100
+++ gajim-omemo-1.0.0/debian/patches/do_not_handle_type_normal_messages 
2017-04-09 01:09:34.000000000 +0200
@@ -0,0 +1,20 @@
+Description: do not handle "normal" messages (unencrypted)
+Author: Philipp Hörist (upstream code), W. Martin Borgert (Debian patch)
+Origin: upstream
+Bug: https://dev.gajim.org/gajim/gajim-plugins/issues/182
+Applied-Upstream: 59baed68
+Last-Update: 2017-04-09
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/omemoplugin.py
++++ b/omemoplugin.py
+@@ -617,6 +617,9 @@
+             -------
+             Return if encryption is not activated
+         """
++        if event.type_ == 'normal':
++            return False
++
+         account = event.account
+         if account in self.disabled_accounts:
+             return
diff -Nru 
gajim-omemo-1.0.0/debian/patches/hide_lock_icon_when_omemo_gets_disabled 
gajim-omemo-1.0.0/debian/patches/hide_lock_icon_when_omemo_gets_disabled
--- gajim-omemo-1.0.0/debian/patches/hide_lock_icon_when_omemo_gets_disabled    
1970-01-01 01:00:00.000000000 +0100
+++ gajim-omemo-1.0.0/debian/patches/hide_lock_icon_when_omemo_gets_disabled    
2017-04-09 01:09:34.000000000 +0200
@@ -0,0 +1,19 @@
+Description: Hide lock icon when omemo gets disabled
+Author: Philipp Hörist (upstream code), W. Martin Borgert (Debian patch)
+Origin: upstream
+Bug: https://dev.gajim.org/gajim/gajim-plugins/issues/161
+Applied-Upstream: 5d0858e4
+Last-Update: 2017-04-09
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/ui.py
++++ b/ui.py
+@@ -322,6 +322,8 @@
+ 
+     def removeUi(self):
+         self.actions_hbox.remove(self.omemobutton)
++        self.chat_control._show_lock_image(False, 'OMEMO', False, True,
++                                           False)
+         self.chat_control.prepare_context_menu = \
+             self.chat_control.omemo_orig_prepare_context_menu
+         self.chat_control.send_message = self.chat_control.orig_send_message
diff -Nru gajim-omemo-1.0.0/debian/patches/series 
gajim-omemo-1.0.0/debian/patches/series
--- gajim-omemo-1.0.0/debian/patches/series     1970-01-01 01:00:00.000000000 
+0100
+++ gajim-omemo-1.0.0/debian/patches/series     2017-04-09 01:09:34.000000000 
+0200
@@ -0,0 +1,4 @@
+do_not_handle_type_normal_messages
+hide_lock_icon_when_omemo_gets_disabled
+xep-0380-compliance
+xep-0384-compliance
diff -Nru gajim-omemo-1.0.0/debian/patches/xep-0380-compliance 
gajim-omemo-1.0.0/debian/patches/xep-0380-compliance
--- gajim-omemo-1.0.0/debian/patches/xep-0380-compliance        1970-01-01 
01:00:00.000000000 +0100
+++ gajim-omemo-1.0.0/debian/patches/xep-0380-compliance        2017-04-09 
01:09:34.000000000 +0200
@@ -0,0 +1,43 @@
+Description: make the OMEMO plugin compliant with XEP-0380, use correct EME tag
+Author: Philipp Hörist (upstream code), W. Martin Borgert (Debian patch)
+Origin: upstream
+Applied-Upstream: 1f78bf71
+Last-Update: 2017-04-09
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/omemoplugin.py
++++ b/omemoplugin.py
+@@ -577,11 +577,11 @@
+             event.msg_iq.delChild('body')
+             event.msg_iq.addChild(node=encrypted_node)
+ 
+-            # XEP-xxxx: Explicit Message Encryption
+-            if not event.msg_iq.getTag('encrypted', attrs={'xmlns': NS_EME}):
+-                eme_node = Node('encrypted', attrs={'xmlns': NS_EME,
+-                                                    'name': 'OMEMO',
+-                                                    'namespace': NS_OMEMO})
++            # XEP-0380: Explicit Message Encryption
++            if not event.msg_iq.getTag('encryption', attrs={'xmlns': NS_EME}):
++                eme_node = Node('encryption', attrs={'xmlns': NS_EME,
++                                                     'name': 'OMEMO',
++                                                     'namespace': NS_OMEMO})
+                 event.msg_iq.addChild(node=eme_node)
+ 
+             # Add Message for devices that dont support OMEMO
+@@ -687,11 +687,11 @@
+ 
+             event.msg_iq.addChild(node=encrypted_node)
+ 
+-            # XEP-xxxx: Explicit Message Encryption
+-            if not event.msg_iq.getTag('encrypted', attrs={'xmlns': NS_EME}):
+-                eme_node = Node('encrypted', attrs={'xmlns': NS_EME,
+-                                                    'name': 'OMEMO',
+-                                                    'namespace': NS_OMEMO})
++            # XEP-0380: Explicit Message Encryption
++            if not event.msg_iq.getTag('encryption', attrs={'xmlns': NS_EME}):
++                eme_node = Node('encryption', attrs={'xmlns': NS_EME,
++                                                     'name': 'OMEMO',
++                                                     'namespace': NS_OMEMO})
+                 event.msg_iq.addChild(node=eme_node)
+ 
+             # Store Hint for MAM
diff -Nru gajim-omemo-1.0.0/debian/patches/xep-0384-compliance 
gajim-omemo-1.0.0/debian/patches/xep-0384-compliance
--- gajim-omemo-1.0.0/debian/patches/xep-0384-compliance        1970-01-01 
01:00:00.000000000 +0100
+++ gajim-omemo-1.0.0/debian/patches/xep-0384-compliance        2017-04-09 
01:09:34.000000000 +0200
@@ -0,0 +1,170 @@
+Description: make the OMEMO plugin compliant with XEP-0384
+Author: Philipp Hörist (upstream code), W. Martin Borgert (Debian patch)
+Origin: upstream
+Bug-Debian: #859894
+Applied-Upstream: 1b8c8a5a, 22271eb1, 81caa982
+Last-Update: 2017-04-09
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/omemo/aes_gcm_fallback.py
++++ b/omemo/aes_gcm_fallback.py
+@@ -140,13 +140,18 @@
+ 
+ def aes_encrypt(key, nonce, plaintext):
+     """ Use AES128 GCM with the given key and iv to encrypt the payload. """
+-    c, t = gcm_encrypt(key, nonce, plaintext, '')
+-    result = c + t
+-    return result
++    return gcm_encrypt(key, nonce, plaintext, '')
+ 
+-
+-def aes_decrypt(key, nonce, payload):
++def aes_decrypt(_key, nonce, payload):
+     """ Use AES128 GCM with the given key and iv to decrypt the payload. """
+-    ciphertext = payload[:-16]
+-    mac = payload[-16:]
++    if len(_key) >= 32:
++        # XEP-0384
++        ciphertext = payload
++        key = _key[:16]
++        mac = _key[16:]
++    else:
++        # Legacy
++        ciphertext = payload[:-16]
++        key = _key
++        mac = payload[-16:]
+     return gcm_decrypt(key, nonce, ciphertext, '', mac)
+--- a/omemo/aes_gcm_native.py
++++ b/omemo/aes_gcm_native.py
+@@ -33,10 +33,18 @@
+     from cryptography.hazmat.backends import default_backend
+ 
+ 
+-def aes_decrypt(key, iv, payload):
++def aes_decrypt(_key, iv, payload):
+     """ Use AES128 GCM with the given key and iv to decrypt the payload. """
+-    data = payload[:-16]
+-    tag = payload[-16:]
++    if len(_key) >= 32:
++        # XEP-0384
++        data = payload
++        key = _key[:16]
++        tag = _key[16:]
++    else:
++        # Legacy
++        data = payload[:-16]
++        key = _key
++        tag = payload[-16:]
+     if os.name == 'nt':
+         _backend = backend
+     else:
+@@ -58,4 +66,4 @@
+         algorithms.AES(key),
+         GCM(iv),
+         backend=_backend).encryptor()
+-    return encryptor.update(plaintext) + encryptor.finalize() + encryptor.tag
++    return encryptor.update(plaintext) + encryptor.finalize(), encryptor.tag
+--- a/omemo/state.py
++++ b/omemo/state.py
+@@ -226,12 +226,18 @@
+             log.error('No known devices')
+             return
+ 
++        payload, tag = encrypt(key, iv, plaintext)
++
++        key += tag
++
+         # Encrypt the message key with for each of receivers devices
+         for device in devices_list:
+             try:
+                 if self.isTrusted(jid, device) == TRUSTED:
+                     cipher = self.get_session_cipher(jid, device)
+-                    encrypted_keys[device] = cipher.encrypt(key).serialize()
++                    cipher_key = cipher.encrypt(key)
++                    prekey = isinstance(cipher_key, PreKeyWhisperMessage)
++                    encrypted_keys[device] = (cipher_key.serialize(), prekey)
+                 else:
+                     log.debug('Skipped Device because Trust is: ' +
+                               str(self.isTrusted(jid, device)))
+@@ -248,15 +254,15 @@
+             try:
+                 if self.isTrusted(from_jid, device) == TRUSTED:
+                     cipher = self.get_session_cipher(from_jid, device)
+-                    encrypted_keys[device] = cipher.encrypt(key).serialize()
++                    cipher_key = cipher.encrypt(key)
++                    prekey = isinstance(cipher_key, PreKeyWhisperMessage)
++                    encrypted_keys[device] = (cipher_key.serialize(), prekey)
+                 else:
+                     log.debug('Skipped own Device because Trust is: ' +
+                               str(self.isTrusted(from_jid, device)))
+             except:
+                 log.warning('Failed to find key for device ' + str(device))
+ 
+-        payload = encrypt(key, iv, plaintext)
+-
+         result = {'sid': self.own_device_id,
+                   'keys': encrypted_keys,
+                   'jid': jid,
+@@ -279,6 +285,10 @@
+             log.error('No known devices')
+             return
+ 
++        payload, tag = encrypt(key, iv, plaintext)
++
++        key += tag
++
+         for tup in devices_list:
+             self.get_session_cipher(tup[0], tup[1])
+ 
+@@ -292,8 +302,9 @@
+             for rid, cipher in self.session_ciphers[jid_to].items():
+                 try:
+                     if self.isTrusted(jid_to, rid) == TRUSTED:
+-                        encrypted_keys[rid] = cipher.encrypt(key). \
+-                            serialize()
++                        cipher_key = cipher.encrypt(key)
++                        prekey = isinstance(cipher_key, PreKeyWhisperMessage)
++                        encrypted_keys[rid] = (cipher_key.serialize(), prekey)
+                     else:
+                         log.debug('Skipped Device because Trust is: ' +
+                                   str(self.isTrusted(jid_to, rid)))
+@@ -313,7 +324,9 @@
+             try:
+                 cipher = self.get_session_cipher(from_jid, dev)
+                 if self.isTrusted(from_jid, dev) == TRUSTED:
+-                    encrypted_keys[dev] = cipher.encrypt(key).serialize()
++                    cipher_key = cipher.encrypt(key)
++                    prekey = isinstance(cipher_key, PreKeyWhisperMessage)
++                    encrypted_keys[dev] = (cipher_key.serialize(), prekey)
+                 else:
+                     log.debug('Skipped own Device because Trust is: ' +
+                               str(self.isTrusted(from_jid, dev)))
+@@ -321,8 +334,6 @@
+                 log.exception('ERROR:')
+                 log.warning('Failed to find key for device ' + str(dev))
+ 
+-        payload = encrypt(key, iv, plaintext)
+-
+         result = {'sid': self.own_device_id,
+                   'keys': encrypted_keys,
+                   'jid': jid,
+--- a/xmpp.py
++++ b/xmpp.py
+@@ -79,9 +79,14 @@
+         # , contact_jid, key, iv, payload, dev_id, my_dev_id):
+         Node.__init__(self, 'encrypted', attrs={'xmlns': NS_OMEMO})
+         header = Node('header', attrs={'sid': msg_dict['sid']})
+-        for rid, key in msg_dict['keys'].items():
+-            header.addChild('key', attrs={'rid': rid}).addData(b64encode(key))
+-
++        for rid, (key, prekey) in msg_dict['keys'].items():
++            if prekey:
++                child = header.addChild('key',
++                                        attrs={'prekey': 'true', 'rid': rid})
++            else:
++                child = header.addChild('key',
++                                        attrs={'rid': rid})
++            child.addData(b64encode(key))
+         header.addChild('iv').addData(b64encode(msg_dict['iv']))
+         self.addChild(node=header)
+         self.addChild('payload').addData(b64encode(msg_dict['payload']))

unblock gajim-omemo/1.0.0-2

Reply via email to