From f0c3b31a42ac6269a0ca299f2fa470586f6120be Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 9 Jan 2017 21:47:07 +0100 Subject: [PATCH] treat omemo keys >= 32 bytes as containing auth tag. add config flag to put auth tag in key --- .../java/eu/siacs/conversations/Config.java | 1 + .../crypto/axolotl/AxolotlService.java | 47 ++++++++++--------- .../crypto/axolotl/XmppAxolotlMessage.java | 31 +++++++++++- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 91bc14318..1a992e483 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -83,6 +83,7 @@ public final class Config { public static final long OMEMO_AUTO_EXPIRY = 7 * MILLISECONDS_IN_DAY; public static final boolean REMOVE_BROKEN_DEVICES = false; public static final boolean OMEMO_PADDING = false; + public static boolean PUT_AUTH_TAG_INTO_KEY = false; public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 7f54ce2fe..65ac7b0a2 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -1007,14 +1007,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { } @Nullable - private XmppAxolotlMessage buildHeader(Conversation conversation) { - final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage( - account.getJid().toBareJid(), getOwnDeviceId()); - + private boolean buildHeader(XmppAxolotlMessage axolotlMessage, Conversation conversation) { Set remoteSessions = findSessionsForConversation(conversation); Collection ownSessions = findOwnSessions(); if (remoteSessions.isEmpty()) { - return null; + return false; } for (XmppAxolotlSession session : remoteSessions) { axolotlMessage.addDevice(session); @@ -1023,26 +1020,26 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { axolotlMessage.addDevice(session); } - return axolotlMessage; + return true; } @Nullable public XmppAxolotlMessage encrypt(Message message) { - XmppAxolotlMessage axolotlMessage = buildHeader(message.getConversation()); - - if (axolotlMessage != null) { - final String content; - if (message.hasFileOnRemoteHost()) { - content = message.getFileParams().url.toString(); - } else { - content = message.getBody(); - } - try { - axolotlMessage.encrypt(content); - } catch (CryptoFailedException e) { - Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage()); - return null; - } + final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().toBareJid(), getOwnDeviceId()); + final String content; + if (message.hasFileOnRemoteHost()) { + content = message.getFileParams().url.toString(); + } else { + content = message.getBody(); + } + try { + axolotlMessage.encrypt(content); + } catch (CryptoFailedException e) { + Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage()); + return null; + } + if (!buildHeader(axolotlMessage,message.getConversation())) { + return null; } return axolotlMessage; @@ -1069,8 +1066,12 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { executor.execute(new Runnable() { @Override public void run() { - XmppAxolotlMessage axolotlMessage = buildHeader(conversation); - onMessageCreatedCallback.run(axolotlMessage); + final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().toBareJid(), getOwnDeviceId()); + if (buildHeader(axolotlMessage,conversation)) { + onMessageCreatedCallback.run(axolotlMessage); + } else { + onMessageCreatedCallback.run(null); + } } }); } diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java index 2d6bba55e..1f5323702 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java @@ -3,7 +3,6 @@ package eu.siacs.conversations.crypto.axolotl; import android.util.Base64; import android.util.Log; -import org.whispersystems.libaxolotl.protocol.CiphertextMessage; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; @@ -24,6 +23,7 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import eu.siacs.conversations.Config; +import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xmpp.jid.Jid; @@ -42,6 +42,7 @@ public class XmppAxolotlMessage { private byte[] innerKey; private byte[] ciphertext = null; + private byte[] authtagPlusInnerKey = null; private byte[] iv = null; private final Map keys; private final Jid from; @@ -166,6 +167,14 @@ public class XmppAxolotlMessage { Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); this.ciphertext = cipher.doFinal(Config.OMEMO_PADDING ? getPaddedBytes(plaintext) : plaintext.getBytes()); + if (Config.PUT_AUTH_TAG_INTO_KEY && this.ciphertext != null) { + this.authtagPlusInnerKey = new byte[16+16]; + byte[] ciphertext = new byte[this.ciphertext.length - 16]; + System.arraycopy(this.ciphertext,0,ciphertext,0,ciphertext.length); + System.arraycopy(this.ciphertext,ciphertext.length,authtagPlusInnerKey,16,16); + System.arraycopy(this.innerKey,0,authtagPlusInnerKey,0,this.innerKey.length); + this.ciphertext = ciphertext; + } } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException | InvalidAlgorithmParameterException e) { @@ -202,7 +211,12 @@ public class XmppAxolotlMessage { } public void addDevice(XmppAxolotlSession session) { - XmppAxolotlSession.AxolotlKey key = session.processSending(innerKey); + XmppAxolotlSession.AxolotlKey key; + if (authtagPlusInnerKey != null) { + key = session.processSending(authtagPlusInnerKey); + } else { + key = session.processSending(innerKey); + } if (key != null) { keys.put(session.getRemoteAddress().getDeviceId(), key); } @@ -254,6 +268,19 @@ public class XmppAxolotlMessage { byte[] key = unpackKey(session, sourceDeviceId); if (key != null) { try { + + if (key.length >= 32) { + int authtaglength = key.length - 16; + Log.d(Config.LOGTAG,"found auth tag as part of omemo key"); + byte[] newCipherText = new byte[key.length - 16 + ciphertext.length]; + byte[] newKey = new byte[16]; + System.arraycopy(ciphertext, 0, newCipherText, 0, ciphertext.length); + System.arraycopy(key, 16, newCipherText, ciphertext.length, authtaglength); + System.arraycopy(key,0,newKey,0,newKey.length); + ciphertext = newCipherText; + key = newKey; + } + Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER); SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE); IvParameterSpec ivSpec = new IvParameterSpec(iv);