treat omemo keys >= 32 bytes as containing auth tag. add config flag to put auth tag in key
This commit is contained in:
parent
a1cb855739
commit
f0c3b31a42
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue