treat omemo keys >= 32 bytes as containing auth tag. add config flag to put auth tag in key

This commit is contained in:
Daniel Gultsch 2017-01-09 21:47:07 +01:00
parent a1cb855739
commit f0c3b31a42
3 changed files with 54 additions and 25 deletions

View File

@ -83,6 +83,7 @@ public final class Config {
public static final long OMEMO_AUTO_EXPIRY = 7 * MILLISECONDS_IN_DAY; public static final long OMEMO_AUTO_EXPIRY = 7 * MILLISECONDS_IN_DAY;
public static final boolean REMOVE_BROKEN_DEVICES = false; public static final boolean REMOVE_BROKEN_DEVICES = false;
public static final boolean OMEMO_PADDING = 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 public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb

View File

@ -1007,14 +1007,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
} }
@Nullable @Nullable
private XmppAxolotlMessage buildHeader(Conversation conversation) { private boolean buildHeader(XmppAxolotlMessage axolotlMessage, Conversation conversation) {
final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(
account.getJid().toBareJid(), getOwnDeviceId());
Set<XmppAxolotlSession> remoteSessions = findSessionsForConversation(conversation); Set<XmppAxolotlSession> remoteSessions = findSessionsForConversation(conversation);
Collection<XmppAxolotlSession> ownSessions = findOwnSessions(); Collection<XmppAxolotlSession> ownSessions = findOwnSessions();
if (remoteSessions.isEmpty()) { if (remoteSessions.isEmpty()) {
return null; return false;
} }
for (XmppAxolotlSession session : remoteSessions) { for (XmppAxolotlSession session : remoteSessions) {
axolotlMessage.addDevice(session); axolotlMessage.addDevice(session);
@ -1023,26 +1020,26 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
axolotlMessage.addDevice(session); axolotlMessage.addDevice(session);
} }
return axolotlMessage; return true;
} }
@Nullable @Nullable
public XmppAxolotlMessage encrypt(Message message) { public XmppAxolotlMessage encrypt(Message message) {
XmppAxolotlMessage axolotlMessage = buildHeader(message.getConversation()); final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().toBareJid(), getOwnDeviceId());
final String content;
if (axolotlMessage != null) { if (message.hasFileOnRemoteHost()) {
final String content; content = message.getFileParams().url.toString();
if (message.hasFileOnRemoteHost()) { } else {
content = message.getFileParams().url.toString(); content = message.getBody();
} else { }
content = message.getBody(); try {
} axolotlMessage.encrypt(content);
try { } catch (CryptoFailedException e) {
axolotlMessage.encrypt(content); Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage());
} catch (CryptoFailedException e) { return null;
Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage()); }
return null; if (!buildHeader(axolotlMessage,message.getConversation())) {
} return null;
} }
return axolotlMessage; return axolotlMessage;
@ -1069,8 +1066,12 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
executor.execute(new Runnable() { executor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
XmppAxolotlMessage axolotlMessage = buildHeader(conversation); final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(account.getJid().toBareJid(), getOwnDeviceId());
onMessageCreatedCallback.run(axolotlMessage); if (buildHeader(axolotlMessage,conversation)) {
onMessageCreatedCallback.run(axolotlMessage);
} else {
onMessageCreatedCallback.run(null);
}
} }
}); });
} }

View File

@ -3,7 +3,6 @@ package eu.siacs.conversations.crypto.axolotl;
import android.util.Base64; import android.util.Base64;
import android.util.Log; import android.util.Log;
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
@ -24,6 +23,7 @@ import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.jid.Jid; import eu.siacs.conversations.xmpp.jid.Jid;
@ -42,6 +42,7 @@ public class XmppAxolotlMessage {
private byte[] innerKey; private byte[] innerKey;
private byte[] ciphertext = null; private byte[] ciphertext = null;
private byte[] authtagPlusInnerKey = null;
private byte[] iv = null; private byte[] iv = null;
private final Map<Integer, XmppAxolotlSession.AxolotlKey> keys; private final Map<Integer, XmppAxolotlSession.AxolotlKey> keys;
private final Jid from; private final Jid from;
@ -166,6 +167,14 @@ public class XmppAxolotlMessage {
Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER); Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
this.ciphertext = cipher.doFinal(Config.OMEMO_PADDING ? getPaddedBytes(plaintext) : plaintext.getBytes()); 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 } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| IllegalBlockSizeException | BadPaddingException | NoSuchProviderException | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException
| InvalidAlgorithmParameterException e) { | InvalidAlgorithmParameterException e) {
@ -202,7 +211,12 @@ public class XmppAxolotlMessage {
} }
public void addDevice(XmppAxolotlSession session) { 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) { if (key != null) {
keys.put(session.getRemoteAddress().getDeviceId(), key); keys.put(session.getRemoteAddress().getDeviceId(), key);
} }
@ -254,6 +268,19 @@ public class XmppAxolotlMessage {
byte[] key = unpackKey(session, sourceDeviceId); byte[] key = unpackKey(session, sourceDeviceId);
if (key != null) { if (key != null) {
try { 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); Cipher cipher = Cipher.getInstance(CIPHERMODE, PROVIDER);
SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE); SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE);
IvParameterSpec ivSpec = new IvParameterSpec(iv); IvParameterSpec ivSpec = new IvParameterSpec(iv);