Provide process function for key transport message

This commit is contained in:
Andreas Straub 2015-07-31 23:28:09 +02:00
parent 909f761ca1
commit 6059b96456
4 changed files with 84 additions and 19 deletions

View file

@ -150,8 +150,13 @@ public class AxolotlService {
@Override @Override
public void put(AxolotlAddress address, XmppAxolotlSession value) { public void put(AxolotlAddress address, XmppAxolotlSession value) {
super.put(address, value); super.put(address, value);
value.setNotFresh();
xmppConnectionService.syncRosterToDisk(account); xmppConnectionService.syncRosterToDisk(account);
} }
public void put(XmppAxolotlSession session) {
this.put(session.getRemoteAddress(), session);
}
} }
private static enum FetchStatus { private static enum FetchStatus {
@ -641,24 +646,32 @@ public class AxolotlService {
return axolotlMessage; return axolotlMessage;
} }
public XmppAxolotlMessage.XmppAxolotlPlaintextMessage processReceiving(XmppAxolotlMessage message) { private XmppAxolotlSession recreateUncachedSession(AxolotlAddress address) {
XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = null; IdentityKey identityKey = axolotlStore.loadSession(address).getSessionState().getRemoteIdentityKey();
return (identityKey != null)
? new XmppAxolotlSession(account, axolotlStore, address,
identityKey.getFingerprint().replaceAll("\\s", ""))
: null;
}
private XmppAxolotlSession getReceivingSession(XmppAxolotlMessage message) {
AxolotlAddress senderAddress = new AxolotlAddress(message.getFrom().toString(), AxolotlAddress senderAddress = new AxolotlAddress(message.getFrom().toString(),
message.getSenderDeviceId()); message.getSenderDeviceId());
boolean newSession = false;
XmppAxolotlSession session = sessions.get(senderAddress); XmppAxolotlSession session = sessions.get(senderAddress);
if (session == null) { if (session == null) {
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Account: " + account.getJid() + " No axolotl session found while parsing received message " + message); Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Account: " + account.getJid() + " No axolotl session found while parsing received message " + message);
IdentityKey identityKey = axolotlStore.loadSession(senderAddress).getSessionState().getRemoteIdentityKey(); session = recreateUncachedSession(senderAddress);
if (identityKey != null) { if (session == null) {
session = new XmppAxolotlSession(account, axolotlStore, senderAddress, identityKey.getFingerprint().replaceAll("\\s", ""));
} else {
session = new XmppAxolotlSession(account, axolotlStore, senderAddress); session = new XmppAxolotlSession(account, axolotlStore, senderAddress);
} }
newSession = true; }
return session;
} }
public XmppAxolotlMessage.XmppAxolotlPlaintextMessage processReceivingPayloadMessage(XmppAxolotlMessage message) {
XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = null;
XmppAxolotlSession session = getReceivingSession(message);
try { try {
plaintextMessage = message.decrypt(session, getOwnDeviceId()); plaintextMessage = message.decrypt(session, getOwnDeviceId());
Integer preKeyId = session.getPreKeyId(); Integer preKeyId = session.getPreKeyId();
@ -670,10 +683,23 @@ public class AxolotlService {
Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to decrypt message: " + e.getMessage()); Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to decrypt message: " + e.getMessage());
} }
if (newSession && plaintextMessage != null) { if (session.isFresh() && plaintextMessage != null) {
sessions.put(senderAddress, session); sessions.put(session);
} }
return plaintextMessage; return plaintextMessage;
} }
public XmppAxolotlMessage.XmppAxolotlKeyTransportMessage processReceivingKeyTransportMessage(XmppAxolotlMessage message) {
XmppAxolotlMessage.XmppAxolotlKeyTransportMessage keyTransportMessage = null;
XmppAxolotlSession session = getReceivingSession(message);
keyTransportMessage = message.getParameters(session, getOwnDeviceId());
if (session.isFresh() && keyTransportMessage != null) {
sessions.put(session);
}
return keyTransportMessage;
}
} }

View file

@ -64,6 +64,30 @@ public class XmppAxolotlMessage {
} }
} }
public static class XmppAxolotlKeyTransportMessage {
private final String fingerprint;
private final byte[] key;
private final byte[] iv;
public XmppAxolotlKeyTransportMessage(String fingerprint, byte[] key, byte[] iv) {
this.fingerprint = fingerprint;
this.key = key;
this.iv = iv;
}
public String getFingerprint() {
return fingerprint;
}
public byte[] getKey() {
return key;
}
public byte[] getIv() {
return iv;
}
}
private XmppAxolotlMessage(final Element axolotlMessage, final Jid from) throws IllegalArgumentException { private XmppAxolotlMessage(final Element axolotlMessage, final Jid from) throws IllegalArgumentException {
this.from = from; this.from = from;
Element header = axolotlMessage.findChild(HEADER); Element header = axolotlMessage.findChild(HEADER);
@ -188,11 +212,18 @@ public class XmppAxolotlMessage {
return encryptionElement; return encryptionElement;
} }
public byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId) { private byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId) {
byte[] encryptedKey = keys.get(sourceDeviceId); byte[] encryptedKey = keys.get(sourceDeviceId);
return (encryptedKey != null) ? session.processReceiving(encryptedKey) : null; return (encryptedKey != null) ? session.processReceiving(encryptedKey) : null;
} }
public XmppAxolotlKeyTransportMessage getParameters(XmppAxolotlSession session, Integer sourceDeviceId) {
byte[] key = unpackKey(session, sourceDeviceId);
return (key != null)
? new XmppAxolotlKeyTransportMessage(session.getFingerprint(), key, getIV())
: null;
}
public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException { public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException {
XmppAxolotlPlaintextMessage plaintextMessage = null; XmppAxolotlPlaintextMessage plaintextMessage = null;
byte[] key = unpackKey(session, sourceDeviceId); byte[] key = unpackKey(session, sourceDeviceId);

View file

@ -23,16 +23,12 @@ import eu.siacs.conversations.entities.Account;
public class XmppAxolotlSession { public class XmppAxolotlSession {
private final SessionCipher cipher; private final SessionCipher cipher;
private Integer preKeyId = null;
private final SQLiteAxolotlStore sqLiteAxolotlStore; private final SQLiteAxolotlStore sqLiteAxolotlStore;
public AxolotlAddress getRemoteAddress() {
return remoteAddress;
}
private final AxolotlAddress remoteAddress; private final AxolotlAddress remoteAddress;
private final Account account; private final Account account;
private String fingerprint = null; private String fingerprint = null;
private Integer preKeyId = null;
private boolean fresh = true;
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress, String fingerprint) { public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress, String fingerprint) {
this(account, store, remoteAddress); this(account, store, remoteAddress);
@ -59,6 +55,18 @@ public class XmppAxolotlSession {
return fingerprint; return fingerprint;
} }
public AxolotlAddress getRemoteAddress() {
return remoteAddress;
}
public boolean isFresh() {
return fresh;
}
public void setNotFresh() {
this.fresh = false;
}
protected void setTrust(SQLiteAxolotlStore.Trust trust) { protected void setTrust(SQLiteAxolotlStore.Trust trust) {
sqLiteAxolotlStore.setFingerprintTrust(fingerprint, trust); sqLiteAxolotlStore.setFingerprintTrust(fingerprint, trust);
} }

View file

@ -100,7 +100,7 @@ public class MessageParser extends AbstractParser implements
Message finishedMessage = null; Message finishedMessage = null;
AxolotlService service = conversation.getAccount().getAxolotlService(); AxolotlService service = conversation.getAccount().getAxolotlService();
XmppAxolotlMessage xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlMessage, from.toBareJid()); XmppAxolotlMessage xmppAxolotlMessage = XmppAxolotlMessage.fromElement(axolotlMessage, from.toBareJid());
XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = service.processReceiving(xmppAxolotlMessage); XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintextMessage = service.processReceivingPayloadMessage(xmppAxolotlMessage);
if(plaintextMessage != null) { if(plaintextMessage != null) {
finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status); finishedMessage = new Message(conversation, plaintextMessage.getPlaintext(), Message.ENCRYPTION_AXOLOTL, status);
finishedMessage.setAxolotlFingerprint(plaintextMessage.getFingerprint()); finishedMessage.setAxolotlFingerprint(plaintextMessage.getFingerprint());