aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/eu/siacs/conversations/crypto/axolotl
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/eu/siacs/conversations/crypto/axolotl')
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java13
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java5
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java10
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java15
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java52
5 files changed, 55 insertions, 40 deletions
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 65ac7b0a..6bde0fe7 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
@@ -439,8 +439,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
mXmppConnectionService.sendIqPacket(account, publish, null);
}
- public void purgeKey(final String fingerprint) {
- axolotlStore.setFingerprintStatus(fingerprint.replaceAll("\\s", ""), FingerprintStatus.createCompromised());
+ public void distrustFingerprint(final String fingerprint) {
+ final String fp = fingerprint.replaceAll("\\s", "");
+ final FingerprintStatus fingerprintStatus = axolotlStore.getFingerprintStatus(fp);
+ axolotlStore.setFingerprintStatus(fp,fingerprintStatus.toUntrusted());
}
public void publishOwnDeviceIdIfNeeded() {
@@ -1120,7 +1122,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
session.resetPreKeyId();
}
} catch (CryptoFailedException e) {
- Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to decrypt message: " + e.getMessage());
+ Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to decrypt message from "+message.getFrom()+": " + e.getMessage());
}
if (session.isFresh() && plaintextMessage != null) {
@@ -1134,7 +1136,12 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
XmppAxolotlMessage.XmppAxolotlKeyTransportMessage keyTransportMessage;
XmppAxolotlSession session = getReceivingSession(message);
+ try {
keyTransportMessage = message.getParameters(session, getOwnDeviceId());
+ } catch (CryptoFailedException e) {
+ Log.d(Config.LOGTAG,"could not decrypt keyTransport message "+e.getMessage());
+ keyTransportMessage = null;
+ }
if (session.isFresh() && keyTransportMessage != null) {
putFreshSession(session);
diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java
index 5796ef30..e549598c 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java
@@ -1,6 +1,11 @@
package eu.siacs.conversations.crypto.axolotl;
public class CryptoFailedException extends Exception {
+
+ public CryptoFailedException(String msg) {
+ super(msg);
+ }
+
public CryptoFailedException(Exception e){
super(e);
}
diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java
index 31b2264b..56f4a5d2 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java
@@ -126,17 +126,17 @@ public class FingerprintStatus implements Comparable<FingerprintStatus> {
return trust;
}
- public static FingerprintStatus createCompromised() {
+ public FingerprintStatus toVerified() {
FingerprintStatus status = new FingerprintStatus();
- status.active = false;
- status.trust = Trust.COMPROMISED;
+ status.active = active;
+ status.trust = Trust.VERIFIED;
return status;
}
- public FingerprintStatus toVerified() {
+ public FingerprintStatus toUntrusted() {
FingerprintStatus status = new FingerprintStatus();
status.active = active;
- status.trust = Trust.VERIFIED;
+ status.trust = Trust.UNTRUSTED;
return status;
}
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 1f532370..cac298e0 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
@@ -23,7 +23,6 @@ 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;
@@ -251,16 +250,16 @@ public class XmppAxolotlMessage {
return encryptionElement;
}
- private byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId) {
+ private byte[] unpackKey(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException {
XmppAxolotlSession.AxolotlKey encryptedKey = keys.get(sourceDeviceId);
- return (encryptedKey != null) ? session.processReceiving(encryptedKey) : null;
+ if (encryptedKey == null) {
+ throw new CryptoFailedException("Message was not encrypted for this device");
+ }
+ return session.processReceiving(encryptedKey);
}
- public XmppAxolotlKeyTransportMessage getParameters(XmppAxolotlSession session, Integer sourceDeviceId) {
- byte[] key = unpackKey(session, sourceDeviceId);
- return (key != null)
- ? new XmppAxolotlKeyTransportMessage(session.getFingerprint(), key, getIV())
- : null;
+ public XmppAxolotlKeyTransportMessage getParameters(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException {
+ return new XmppAxolotlKeyTransportMessage(session.getFingerprint(), unpackKey(session, sourceDeviceId), getIV());
}
public XmppAxolotlPlaintextMessage decrypt(XmppAxolotlSession session, Integer sourceDeviceId) throws CryptoFailedException {
diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java
index 773b6857..359cb7fd 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java
@@ -4,6 +4,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
+import org.bouncycastle.math.ec.PreCompInfo;
import org.whispersystems.libaxolotl.AxolotlAddress;
import org.whispersystems.libaxolotl.DuplicateMessageException;
import org.whispersystems.libaxolotl.IdentityKey;
@@ -18,9 +19,11 @@ import org.whispersystems.libaxolotl.UntrustedIdentityException;
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
import org.whispersystems.libaxolotl.protocol.WhisperMessage;
+import org.whispersystems.libaxolotl.util.guava.Optional;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.utils.CryptoHelper;
public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
private final SessionCipher cipher;
@@ -82,42 +85,43 @@ public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
}
@Nullable
- public byte[] processReceiving(AxolotlKey encryptedKey) {
- byte[] plaintext = null;
+ public byte[] processReceiving(AxolotlKey encryptedKey) throws CryptoFailedException {
+ byte[] plaintext;
FingerprintStatus status = getTrust();
if (!status.isCompromised()) {
try {
+ CiphertextMessage ciphertextMessage;
try {
- PreKeyWhisperMessage message = new PreKeyWhisperMessage(encryptedKey.key);
- if (!message.getPreKeyId().isPresent()) {
- Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage did not contain a PreKeyId");
- return null;
+ ciphertextMessage = new PreKeyWhisperMessage(encryptedKey.key);
+ Optional<Integer> optionalPreKeyId = ((PreKeyWhisperMessage) ciphertextMessage).getPreKeyId();
+ IdentityKey identityKey = ((PreKeyWhisperMessage) ciphertextMessage).getIdentityKey();
+ if (!optionalPreKeyId.isPresent()) {
+ throw new CryptoFailedException("PreKeyWhisperMessage did not contain a PreKeyId");
+ }
+ preKeyId = optionalPreKeyId.get();
+ if (this.identityKey != null && !this.identityKey.equals(identityKey)) {
+ throw new CryptoFailedException("Received PreKeyWhisperMessage but preexisting identity key changed.");
+ }
+ this.identityKey = identityKey;
+ } catch (InvalidVersionException | InvalidMessageException e) {
+ ciphertextMessage = new WhisperMessage(encryptedKey.key);
}
- Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
- IdentityKey msgIdentityKey = message.getIdentityKey();
- if (this.identityKey != null && !this.identityKey.equals(msgIdentityKey)) {
- Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Had session with fingerprint " + this.getFingerprint() + ", received message with fingerprint " + msgIdentityKey.getFingerprint());
+ if (ciphertextMessage instanceof PreKeyWhisperMessage) {
+ plaintext = cipher.decrypt((PreKeyWhisperMessage) ciphertextMessage);
} else {
- this.identityKey = msgIdentityKey;
- plaintext = cipher.decrypt(message);
- preKeyId = message.getPreKeyId().get();
+ plaintext = cipher.decrypt((WhisperMessage) ciphertextMessage);
}
- } catch (InvalidMessageException | InvalidVersionException e) {
- Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "WhisperMessage received");
- WhisperMessage message = new WhisperMessage(encryptedKey.key);
- plaintext = cipher.decrypt(message);
- } catch (InvalidKeyException | InvalidKeyIdException | UntrustedIdentityException e) {
- Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
+ } catch (InvalidKeyException | LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException | InvalidKeyIdException | UntrustedIdentityException e) {
+ if (!(e instanceof DuplicateMessageException)) {
+ e.printStackTrace();
}
- } catch (LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException e) {
- Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Error decrypting axolotl header, " + e.getClass().getName() + ": " + e.getMessage());
+ throw new CryptoFailedException("Error decrypting WhisperMessage " + e.getClass().getSimpleName() + ": " + e.getMessage());
}
-
- if (plaintext != null) {
if (!status.isActive()) {
setTrust(status.toActive());
}
- }
+ } else {
+ throw new CryptoFailedException("not encrypting omemo message from fingerprint "+getFingerprint()+" because it was marked as compromised");
}
return plaintext;
}