Fix some issues and delete old code.

This commit is contained in:
Paul Schaub 2017-12-31 16:55:25 +01:00
parent 2db7717abc
commit 7bff6e7d99
10 changed files with 76 additions and 1389 deletions

View File

@ -25,7 +25,7 @@ import java.util.HashMap;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.omemo.util.EphemeralTrustCallback; import org.jivesoftware.smackx.omemo.util.EphemeralTrustCallback;
import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.roster.PresenceEventListener; import org.jivesoftware.smack.roster.PresenceEventListener;
import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.Roster;
@ -98,8 +98,8 @@ public class OmemoManagerSetupHelper {
public static void trustAllIdentities(OmemoManager alice, OmemoManager bob) public static void trustAllIdentities(OmemoManager alice, OmemoManager bob)
throws InterruptedException, SmackException.NotConnectedException, SmackException.NotLoggedInException, throws InterruptedException, SmackException.NotConnectedException, SmackException.NotLoggedInException,
SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException,
{ XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException {
Roster roster = Roster.getInstanceFor(alice.getConnection()); Roster roster = Roster.getInstanceFor(alice.getConnection());
if (alice.getOwnJid() != bob.getOwnJid() && if (alice.getOwnJid() != bob.getOwnJid() &&
@ -118,8 +118,8 @@ public class OmemoManagerSetupHelper {
public static void trustAllIdentitiesWithTests(OmemoManager alice, OmemoManager bob) public static void trustAllIdentitiesWithTests(OmemoManager alice, OmemoManager bob)
throws InterruptedException, SmackException.NotConnectedException, SmackException.NotLoggedInException, throws InterruptedException, SmackException.NotConnectedException, SmackException.NotLoggedInException,
SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException,
{ XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException {
alice.requestDeviceListUpdateFor(bob.getOwnJid()); alice.requestDeviceListUpdateFor(bob.getOwnJid());
HashMap<OmemoDevice, OmemoFingerprint> fps1 = alice.getActiveFingerprints(bob.getOwnJid()); HashMap<OmemoDevice, OmemoFingerprint> fps1 = alice.getActiveFingerprints(bob.getOwnJid());
@ -177,7 +177,10 @@ public class OmemoManagerSetupHelper {
} }
} }
public static void cleanUpPubSub(OmemoManager omemoManager) throws SmackException.NotLoggedInException { public static void cleanUpPubSub(OmemoManager omemoManager)
throws SmackException.NotLoggedInException, XMPPException.XMPPErrorException,
PubSubException.NotALeafNodeException
{
PubSubManager pm = PubSubManager.getInstance(omemoManager.getConnection(),omemoManager.getOwnJid()); PubSubManager pm = PubSubManager.getInstance(omemoManager.getConnection(),omemoManager.getOwnJid());
try { try {
omemoManager.requestDeviceListUpdateFor(omemoManager.getOwnJid()); omemoManager.requestDeviceListUpdateFor(omemoManager.getOwnJid());

View File

@ -68,7 +68,7 @@ public class SignalOmemoRatchet
SessionCipher> store) SessionCipher> store)
{ {
super(omemoManager, store); super(omemoManager, store);
this.storeConnector = new SignalOmemoStoreConnector(omemoManager, store); this.storeConnector = new SignalOmemoStoreConnector(omemoManager.getOwnDevice(), store);
} }
@Override @Override

View File

@ -111,17 +111,17 @@ public final class SignalOmemoService
} }
@Override @Override
protected void processBundle(OmemoManager.LoggedInOmemoManager managerGuard, protected void processBundle(OmemoDevice userDevice,
PreKeyBundle preKeyBundle, PreKeyBundle contactsBundle,
OmemoDevice device) OmemoDevice contactsDevice)
throws CorruptedOmemoKeyException throws CorruptedOmemoKeyException
{ {
SignalOmemoStoreConnector connector = new SignalOmemoStoreConnector(managerGuard.get(), getOmemoStoreBackend()); SignalOmemoStoreConnector connector = new SignalOmemoStoreConnector(userDevice, getOmemoStoreBackend());
SessionBuilder builder = new SessionBuilder(connector, connector, connector, connector, SessionBuilder builder = new SessionBuilder(connector, connector, connector, connector,
SignalOmemoStoreConnector.asAddress(device)); SignalOmemoStoreConnector.asAddress(contactsDevice));
try { try {
builder.process(preKeyBundle); builder.process(contactsBundle);
LOGGER.log(Level.FINE, "Session built with " + device); LOGGER.log(Level.FINE, "Session built with " + contactsDevice);
} catch (org.whispersystems.libsignal.InvalidKeyException e) { } catch (org.whispersystems.libsignal.InvalidKeyException e) {
throw new CorruptedOmemoKeyException(e.getMessage()); throw new CorruptedOmemoKeyException(e.getMessage());
} catch (UntrustedIdentityException e) { } catch (UntrustedIdentityException e) {

View File

@ -26,7 +26,6 @@ import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.jivesoftware.smackx.omemo.OmemoManager;
import org.jivesoftware.smackx.omemo.OmemoStore; import org.jivesoftware.smackx.omemo.OmemoStore;
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
import org.jivesoftware.smackx.omemo.internal.OmemoDevice; import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
@ -59,20 +58,20 @@ public class SignalOmemoStoreConnector
private static final Logger LOGGER = Logger.getLogger(SignalOmemoStoreConnector.class.getName()); private static final Logger LOGGER = Logger.getLogger(SignalOmemoStoreConnector.class.getName());
private final OmemoManager omemoManager;
private final OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, private final OmemoStore<IdentityKeyPair, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord,
SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher> SignalProtocolAddress, ECPublicKey, PreKeyBundle, SessionCipher>
omemoStore; omemoStore;
private final OmemoDevice userDevice;
public SignalOmemoStoreConnector(OmemoManager omemoManager, OmemoStore<IdentityKeyPair, public SignalOmemoStoreConnector(OmemoDevice userDevice, OmemoStore<IdentityKeyPair,
IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, SignalProtocolAddress, ECPublicKey, IdentityKey, PreKeyRecord, SignedPreKeyRecord, SessionRecord, SignalProtocolAddress, ECPublicKey,
PreKeyBundle, SessionCipher> store) { PreKeyBundle, SessionCipher> store) {
this.omemoManager = omemoManager; this.userDevice = userDevice;
this.omemoStore = store; this.omemoStore = store;
} }
OmemoDevice getOurDevice() { OmemoDevice getOurDevice() {
return omemoManager.getOwnDevice(); return userDevice;
} }
@Override @Override

View File

@ -538,8 +538,8 @@ public final class OmemoManager extends Manager {
public OmemoFingerprint getFingerprint(OmemoDevice device) public OmemoFingerprint getFingerprint(OmemoDevice device)
throws CannotEstablishOmemoSessionException, SmackException.NotLoggedInException, throws CannotEstablishOmemoSessionException, SmackException.NotLoggedInException,
CorruptedOmemoKeyException CorruptedOmemoKeyException, SmackException.NotConnectedException, InterruptedException,
{ SmackException.NoResponseException {
synchronized (LOCK) { synchronized (LOCK) {
if (getOwnJid() == null) { if (getOwnJid() == null) {
throw new SmackException.NotLoggedInException(); throw new SmackException.NotLoggedInException();
@ -554,13 +554,22 @@ public final class OmemoManager extends Manager {
} }
/** /**
* Return all fingerprints of active devices of a contact. * Return all OmemoFingerprints of active devices of a contact.
* TODO: Make more fail-safe
* @param contact contact * @param contact contact
* @return HashMap of deviceIds and corresponding fingerprints. * @return Map of all active devices of the contact and their fingerprints.
*
* @throws SmackException.NotLoggedInException
* @throws CorruptedOmemoKeyException
* @throws CannotEstablishOmemoSessionException
* @throws SmackException.NotConnectedException
* @throws InterruptedException
* @throws SmackException.NoResponseException
*/ */
public HashMap<OmemoDevice, OmemoFingerprint> getActiveFingerprints(BareJid contact) public HashMap<OmemoDevice, OmemoFingerprint> getActiveFingerprints(BareJid contact)
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, throws SmackException.NotLoggedInException, CorruptedOmemoKeyException,
CannotEstablishOmemoSessionException CannotEstablishOmemoSessionException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException
{ {
synchronized (LOCK) { synchronized (LOCK) {
if (getOwnJid() == null) { if (getOwnJid() == null) {

View File

@ -42,6 +42,9 @@ import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement; import org.jivesoftware.smackx.omemo.element.OmemoBundleElement;
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement; import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement;
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement_VAxolotl; import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement_VAxolotl;
@ -317,7 +320,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
throw new AssertionError("Gullible Trust Callback reported undecided or untrusted device, " + throw new AssertionError("Gullible Trust Callback reported undecided or untrusted device, " +
"even though it MUST NOT do that."); "even though it MUST NOT do that.");
} catch (NoIdentityKeyException e) { } catch (NoIdentityKeyException e) {
throw new AssertionError("We MUST have an identityKey for " + contactsDevice + " since we built a session.", e); throw new AssertionError("We MUST have an identityKey for " + contactsDevice + " since we built a session." + e);
} }
return builder.finish(); return builder.finish();
@ -390,7 +393,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
skippedRecipients.put(contactsDevice, e); skippedRecipients.put(contactsDevice, e);
} }
catch (UndecidedOmemoIdentityException e) { catch (UndecidedOmemoIdentityException e) {
throw new AssertionError("At this point, devices cannot be undecided.", e); throw new AssertionError("At this point, devices cannot be undecided. " + e);
} }
catch (UntrustedOmemoIdentityException e) { catch (UntrustedOmemoIdentityException e) {
LOGGER.log(Level.WARNING, "Device " + contactsDevice + " is untrusted. Message is not encrypted for it."); LOGGER.log(Level.WARNING, "Device " + contactsDevice + " is untrusted. Message is not encrypted for it.");
@ -641,7 +644,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws CorruptedOmemoKeyException if our IdentityKeyPair is corrupted. * @throws CorruptedOmemoKeyException if our IdentityKeyPair is corrupted.
*/ */
private void buildFreshSessionWithDevice(XMPPConnection connection, OmemoDevice userDevice, OmemoDevice contactsDevice) void buildFreshSessionWithDevice(XMPPConnection connection, OmemoDevice userDevice, OmemoDevice contactsDevice)
throws CannotEstablishOmemoSessionException, SmackException.NotConnectedException, InterruptedException, throws CannotEstablishOmemoSessionException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, CorruptedOmemoKeyException { SmackException.NoResponseException, CorruptedOmemoKeyException {
@ -664,7 +667,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
T_Bundle randomPreKeyBundle = new ArrayList<>(bundlesList.values()).get(randomIndex); T_Bundle randomPreKeyBundle = new ArrayList<>(bundlesList.values()).get(randomIndex);
// build the session // build the session
processBundle(connection, userDevice, randomPreKeyBundle, contactsDevice); processBundle(userDevice, randomPreKeyBundle, contactsDevice);
} }
/** /**
@ -813,21 +816,19 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @param contactsDevice OmemoDevice of the contact. * @param contactsDevice OmemoDevice of the contact.
* @return true if userDevice has session with contactsDevice. * @return true if userDevice has session with contactsDevice.
*/ */
private boolean hasSession(OmemoDevice userDevice, OmemoDevice contactsDevice) { boolean hasSession(OmemoDevice userDevice, OmemoDevice contactsDevice) {
return getOmemoStoreBackend().loadRawSession(userDevice, contactsDevice) != null; return getOmemoStoreBackend().loadRawSession(userDevice, contactsDevice) != null;
} }
/** /**
* Process a received bundle. Typically that includes saving keys and building a session. * Process a received bundle. Typically that includes saving keys and building a session.
* *
* @param connection authenticated XMPP connection
* @param userDevice our OmemoDevice * @param userDevice our OmemoDevice
* @param contactsBundle bundle of the contact * @param contactsBundle bundle of the contact
* @param contactsDevice OmemoDevice of the contact * @param contactsDevice OmemoDevice of the contact
* @throws CorruptedOmemoKeyException * @throws CorruptedOmemoKeyException
*/ */
protected abstract void processBundle(XMPPConnection connection, protected abstract void processBundle(OmemoDevice userDevice,
OmemoDevice userDevice,
T_Bundle contactsBundle, T_Bundle contactsBundle,
OmemoDevice contactsDevice) OmemoDevice contactsDevice)
throws CorruptedOmemoKeyException; throws CorruptedOmemoKeyException;
@ -974,4 +975,13 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
} }
}; };
@Override
public void onOmemoCarbonCopyReceived(CarbonExtension.Direction direction, Message carbonCopy, Message wrappingMessage, OmemoManager.LoggedInOmemoManager omemoManager) {
// TODO: implement
}
@Override
public void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager omemoManager) {
// TODO: Implement
}
} }

View File

@ -26,6 +26,7 @@ import java.util.TreeMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smackx.omemo.element.OmemoBundleElement_VAxolotl; import org.jivesoftware.smackx.omemo.element.OmemoBundleElement_VAxolotl;
import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement; import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement;
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException; import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
@ -559,22 +560,33 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
/** /**
* Return the fingerprint of the given devices announced identityKey. * Return the fingerprint of the given devices announced identityKey.
* If we have no local copy of the identityKey of the contact, build a fresh session in order to get the key.
* *
* @param managerGuard omemoManager of our device. * @param managerGuard authenticated OmemoManager
* @param contactsDevice device * @param contactsDevice OmemoDevice we want to get the fingerprint from
* @throws CannotEstablishOmemoSessionException if we cannot establish a session * @return fingerprint
* @return fingerprint of the identityKey *
* @throws CannotEstablishOmemoSessionException If we have no local copy of the identityKey of the contact
* and are unable to build a fresh session
* @throws CorruptedOmemoKeyException If the identityKey we have of the contact is corrupted
* @throws SmackException.NotConnectedException
* @throws InterruptedException
* @throws SmackException.NoResponseException
*/ */
public OmemoFingerprint getFingerprintAndMaybeBuildSession(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contactsDevice) public OmemoFingerprint getFingerprintAndMaybeBuildSession(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contactsDevice)
throws CannotEstablishOmemoSessionException, CorruptedOmemoKeyException throws CannotEstablishOmemoSessionException, CorruptedOmemoKeyException,
{ SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
OmemoManager omemoManager = managerGuard.get(); OmemoManager omemoManager = managerGuard.get();
// Load identityKey
T_IdKey identityKey = loadOmemoIdentityKey(omemoManager.getOwnDevice(), contactsDevice); T_IdKey identityKey = loadOmemoIdentityKey(omemoManager.getOwnDevice(), contactsDevice);
if (identityKey == null) { if (identityKey == null) {
// Key cannot be loaded. Maybe it doesn't exist. Fetch a bundle to get it... // Key cannot be loaded. Maybe it doesn't exist. Fetch a bundle to get it...
OmemoService.getInstance().buildSessionWithDevice(managerGuard, contactsDevice, true); OmemoService.getInstance().buildFreshSessionWithDevice(omemoManager.getConnection(),
omemoManager.getOwnDevice(), contactsDevice);
} }
// Load identityKey again
identityKey = loadOmemoIdentityKey(omemoManager.getOwnDevice(), contactsDevice); identityKey = loadOmemoIdentityKey(omemoManager.getOwnDevice(), contactsDevice);
if (identityKey == null) { if (identityKey == null) {
return null; return null;

View File

@ -238,6 +238,7 @@ public class OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
case trusted: case trusted:
CiphertextTuple encryptedKey = ratchet.doubleRatchetEncrypt(contactsDevice, messageKey); CiphertextTuple encryptedKey = ratchet.doubleRatchetEncrypt(contactsDevice, messageKey);
keys.add(new OmemoKeyElement(encryptedKey.getCiphertext(), contactsDevice.getDeviceId(), encryptedKey.isPreKeyMessage())); keys.add(new OmemoKeyElement(encryptedKey.getCiphertext(), contactsDevice.getDeviceId(), encryptedKey.isPreKeyMessage()));
break;
case untrusted: case untrusted:
throw new UntrustedOmemoIdentityException(contactsDevice, fingerprint); throw new UntrustedOmemoIdentityException(contactsDevice, fingerprint);

View File

@ -18,6 +18,8 @@ package org.jivesoftware.smackx.omemo;
import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue; import static junit.framework.TestCase.assertTrue;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYLENGTH;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYTYPE;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@ -25,20 +27,14 @@ import static org.junit.Assert.assertNotNull;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Security; import java.security.Security;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.omemo.element.OmemoElement; import org.jivesoftware.smackx.omemo.element.OmemoElement;
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException; import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
import org.jivesoftware.smackx.omemo.internal.CipherAndAuthTag; import org.jivesoftware.smackx.omemo.internal.CipherAndAuthTag;
import org.jivesoftware.smackx.omemo.internal.CiphertextTuple; import org.jivesoftware.smackx.omemo.internal.CiphertextTuple;
import org.jivesoftware.smackx.omemo.internal.ClearTextMessage;
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
import org.jivesoftware.smackx.omemo.internal.OmemoMessageInformation;
import org.jivesoftware.smackx.omemo.util.OmemoMessageBuilder; import org.jivesoftware.smackx.omemo.util.OmemoMessageBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test; import org.junit.Test;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.impl.JidCreate;
/** /**
* Test the identityKeyWrapper. * Test the identityKeyWrapper.
@ -58,30 +54,10 @@ public class WrapperObjectsTest {
assertEquals(OmemoElement.TYPE_OMEMO_MESSAGE, c2.getMessageType()); assertEquals(OmemoElement.TYPE_OMEMO_MESSAGE, c2.getMessageType());
} }
@Test
public void clearTextMessageTest() throws Exception {
BareJid senderJid = JidCreate.bareFrom("bob@server.tld");
OmemoDevice sender = new OmemoDevice(senderJid, 1234);
OmemoMessageInformation information = new OmemoMessageInformation(null, sender, OmemoMessageInformation.CARBON.NONE);
assertTrue("OmemoInformation must state that the message is an OMEMO message.",
information.isOmemoMessage());
assertEquals(OmemoMessageInformation.CARBON.NONE, information.getCarbon());
assertEquals(sender, information.getSenderDevice());
String body = "Decrypted Body";
Message message = new Message(senderJid, body);
ClearTextMessage c = new ClearTextMessage(body, message, information);
assertEquals(message, c.getOriginalMessage());
assertEquals(information, c.getMessageInformation());
assertEquals(body, c.getBody());
}
@Test @Test
public void cipherAndAuthTagTest() throws NoSuchAlgorithmException, CryptoFailedException { public void cipherAndAuthTagTest() throws NoSuchAlgorithmException, CryptoFailedException {
Security.addProvider(new BouncyCastleProvider()); Security.addProvider(new BouncyCastleProvider());
byte[] key = OmemoMessageBuilder.generateKey(); byte[] key = OmemoMessageBuilder.generateKey(KEYTYPE, KEYLENGTH);
byte[] iv = OmemoMessageBuilder.generateIv(); byte[] iv = OmemoMessageBuilder.generateIv();
byte[] authTag = OmemoMessageBuilder.generateIv(); byte[] authTag = OmemoMessageBuilder.generateIv();