aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java84
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java7
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java3
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java3
-rw-r--r--src/main/java/eu/siacs/conversations/ui/XmppActivity.java37
5 files changed, 96 insertions, 38 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 1fe455ff..6e28f111 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
@@ -100,7 +100,8 @@ public class AxolotlService {
public enum Trust {
UNDECIDED, // 0
TRUSTED,
- UNTRUSTED;
+ UNTRUSTED,
+ COMPROMISED;
public String toString() {
switch(this){
@@ -514,41 +515,64 @@ public class AxolotlService {
return fingerprint;
}
+ private SQLiteAxolotlStore.Trust getTrust() {
+ return sqLiteAxolotlStore.getFingerprintTrust(fingerprint);
+ }
+
+ @Nullable
public byte[] processReceiving(XmppAxolotlMessage.XmppAxolotlMessageHeader incomingHeader) {
byte[] plaintext = null;
- try {
- try {
- PreKeyWhisperMessage message = new PreKeyWhisperMessage(incomingHeader.getContents());
- Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
- String fingerprint = message.getIdentityKey().getFingerprint().replaceAll("\\s", "");
- if (this.fingerprint != null && !this.fingerprint.equals(fingerprint)) {
- Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Had session with fingerprint "+ this.fingerprint+", received message with fingerprint "+fingerprint);
- } else {
- this.fingerprint = fingerprint;
- plaintext = cipher.decrypt(message);
- if (message.getPreKeyId().isPresent()) {
- preKeyId = message.getPreKeyId().get();
+ switch (getTrust()) {
+ case UNDECIDED:
+ case TRUSTED:
+ try {
+ try {
+ PreKeyWhisperMessage message = new PreKeyWhisperMessage(incomingHeader.getContents());
+ Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"PreKeyWhisperMessage received, new session ID:" + message.getSignedPreKeyId() + "/" + message.getPreKeyId());
+ String fingerprint = message.getIdentityKey().getFingerprint().replaceAll("\\s", "");
+ if (this.fingerprint != null && !this.fingerprint.equals(fingerprint)) {
+ Log.e(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Had session with fingerprint "+ this.fingerprint+", received message with fingerprint "+fingerprint);
+ } else {
+ this.fingerprint = fingerprint;
+ plaintext = cipher.decrypt(message);
+ if (message.getPreKeyId().isPresent()) {
+ preKeyId = message.getPreKeyId().get();
+ }
+ }
+ } catch (InvalidMessageException | InvalidVersionException e) {
+ Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"WhisperMessage received");
+ WhisperMessage message = new WhisperMessage(incomingHeader.getContents());
+ 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 (LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException e) {
+ Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Error decrypting axolotl header, "+e.getClass().getName()+": " + e.getMessage());
}
- } catch (InvalidMessageException | InvalidVersionException e) {
- Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account)+"WhisperMessage received");
- WhisperMessage message = new WhisperMessage(incomingHeader.getContents());
- 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 (LegacyMessageException | InvalidMessageException | DuplicateMessageException | NoSessionException e) {
- Log.w(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Error decrypting axolotl header, "+e.getClass().getName()+": " + e.getMessage());
+
+ break;
+
+ case COMPROMISED:
+ case UNTRUSTED:
+ default:
+ // ignore
+ break;
}
return plaintext;
}
- public XmppAxolotlMessage.XmppAxolotlMessageHeader processSending(byte[] outgoingMessage) {
- CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage);
- XmppAxolotlMessage.XmppAxolotlMessageHeader header =
- new XmppAxolotlMessage.XmppAxolotlMessageHeader(remoteAddress.getDeviceId(),
- ciphertextMessage.serialize());
- return header;
+ @Nullable
+ public XmppAxolotlMessage.XmppAxolotlMessageHeader processSending(@NonNull byte[] outgoingMessage) {
+ SQLiteAxolotlStore.Trust trust = getTrust();
+ if (trust == SQLiteAxolotlStore.Trust.TRUSTED) {
+ CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage);
+ XmppAxolotlMessage.XmppAxolotlMessageHeader header =
+ new XmppAxolotlMessage.XmppAxolotlMessageHeader(remoteAddress.getDeviceId(),
+ ciphertextMessage.serialize());
+ return header;
+ } else {
+ return null;
+ }
}
}
@@ -742,6 +766,10 @@ public class AxolotlService {
});
}
+ public void purgeKey(IdentityKey identityKey) {
+ axolotlStore.setFingerprintTrust(identityKey.getFingerprint().replaceAll("\\s",""), SQLiteAxolotlStore.Trust.COMPROMISED);
+ }
+
public void publishOwnDeviceIdIfNeeded() {
IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveDeviceIds(account.getJid().toBareJid());
mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
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 1378c94a..ec068ec7 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
@@ -1,5 +1,6 @@
package eu.siacs.conversations.crypto.axolotl;
+import android.support.annotation.Nullable;
import android.util.Base64;
import java.security.InvalidAlgorithmParameterException;
@@ -145,8 +146,10 @@ public class XmppAxolotlMessage {
return headers;
}
- public void addHeader(XmppAxolotlMessageHeader header) {
- headers.add(header);
+ public void addHeader(@Nullable XmppAxolotlMessageHeader header) {
+ if (header != null) {
+ headers.add(header);
+ }
}
public byte[] getInnerKey(){
diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
index cc2ef27c..16e16cff 100644
--- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java
@@ -384,8 +384,7 @@ public class ContactDetailsActivity extends XmppActivity implements OnAccountUpd
}
for(final IdentityKey identityKey : xmppConnectionService.databaseBackend.loadIdentityKeys(
contact.getAccount(), contact.getJid().toBareJid().toString())) {
- hasKeys = true;
- addFingerprintRow(keys, contact.getAccount(), identityKey);
+ hasKeys |= addFingerprintRow(keys, contact.getAccount(), identityKey);
}
if (contact.getPgpKeyId() != 0) {
hasKeys = true;
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index e7b51329..c9e70082 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -566,8 +566,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
if(ownKey.equals(identityKey)) {
continue;
}
- hasKeys = true;
- addFingerprintRow(keys, mAccount, identityKey);
+ hasKeys |= addFingerprintRow(keys, mAccount, identityKey);
}
if (hasKeys) {
keysCard.setVisibility(View.VISIBLE);
diff --git a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
index 69357224..19783627 100644
--- a/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/XmppActivity.java
@@ -601,11 +601,11 @@ public abstract class XmppActivity extends Activity {
builder.create().show();
}
- protected void addFingerprintRow(LinearLayout keys, final Account account, IdentityKey identityKey) {
+ protected boolean addFingerprintRow(LinearLayout keys, final Account account, IdentityKey identityKey) {
final String fingerprint = identityKey.getFingerprint().replaceAll("\\s", "");
final AxolotlService.SQLiteAxolotlStore.Trust trust = account.getAxolotlService()
.getFingerprintTrust(fingerprint);
- addFingerprintRowWithListeners(keys, account, identityKey, trust, true,
+ return addFingerprintRowWithListeners(keys, account, identityKey, trust, true,
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -633,13 +633,16 @@ public abstract class XmppActivity extends Activity {
);
}
- protected void addFingerprintRowWithListeners(LinearLayout keys, final Account account,
- IdentityKey identityKey,
+ protected boolean addFingerprintRowWithListeners(LinearLayout keys, final Account account,
+ final IdentityKey identityKey,
AxolotlService.SQLiteAxolotlStore.Trust trust,
boolean showTag,
CompoundButton.OnCheckedChangeListener
onCheckedChangeListener,
View.OnClickListener onClickListener) {
+ if (trust == AxolotlService.SQLiteAxolotlStore.Trust.COMPROMISED) {
+ return false;
+ }
View view = getLayoutInflater().inflate(R.layout.contact_key, keys, false);
TextView key = (TextView) view.findViewById(R.id.key);
TextView keyType = (TextView) view.findViewById(R.id.key_type);
@@ -647,6 +650,13 @@ public abstract class XmppActivity extends Activity {
trustToggle.setVisibility(View.VISIBLE);
trustToggle.setOnCheckedChangeListener(onCheckedChangeListener);
trustToggle.setOnClickListener(onClickListener);
+ view.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ showPurgeKeyDialog(account, identityKey);
+ return true;
+ }
+ });
switch (trust) {
case UNTRUSTED:
@@ -668,7 +678,26 @@ public abstract class XmppActivity extends Activity {
key.setText(CryptoHelper.prettifyFingerprint(identityKey.getFingerprint()));
keys.addView(view);
+ return true;
+ }
+ public void showPurgeKeyDialog(final Account account, final IdentityKey identityKey) {
+ Builder builder = new Builder(this);
+ builder.setTitle(getString(R.string.purge_key));
+ builder.setIconAttribute(android.R.attr.alertDialogIcon);
+ builder.setMessage(getString(R.string.purge_key_desc_part1)
+ + "\n\n" + CryptoHelper.prettifyFingerprint(identityKey.getFingerprint())
+ + "\n\n" + getString(R.string.purge_key_desc_part2));
+ builder.setNegativeButton(getString(R.string.cancel), null);
+ builder.setPositiveButton(getString(R.string.accept),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ account.getAxolotlService().purgeKey(identityKey);
+ refreshUi();
+ }
+ });
+ builder.create().show();
}
public void selectPresence(final Conversation conversation,