1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
package eu.siacs.conversations.crypto.axolotl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import org.whispersystems.libaxolotl.AxolotlAddress;
import org.whispersystems.libaxolotl.DuplicateMessageException;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.InvalidKeyIdException;
import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.libaxolotl.InvalidVersionException;
import org.whispersystems.libaxolotl.LegacyMessageException;
import org.whispersystems.libaxolotl.NoSessionException;
import org.whispersystems.libaxolotl.SessionCipher;
import org.whispersystems.libaxolotl.UntrustedIdentityException;
import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
import org.whispersystems.libaxolotl.protocol.WhisperMessage;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
public class XmppAxolotlSession {
private final SessionCipher cipher;
private Integer preKeyId = null;
private final SQLiteAxolotlStore sqLiteAxolotlStore;
public AxolotlAddress getRemoteAddress() {
return remoteAddress;
}
private final AxolotlAddress remoteAddress;
private final Account account;
private String fingerprint = null;
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress, String fingerprint) {
this(account, store, remoteAddress);
this.fingerprint = fingerprint;
}
public XmppAxolotlSession(Account account, SQLiteAxolotlStore store, AxolotlAddress remoteAddress) {
this.cipher = new SessionCipher(store, remoteAddress);
this.remoteAddress = remoteAddress;
this.sqLiteAxolotlStore = store;
this.account = account;
}
public Integer getPreKeyId() {
return preKeyId;
}
public void resetPreKeyId() {
preKeyId = null;
}
public String getFingerprint() {
return fingerprint;
}
protected void setTrust(SQLiteAxolotlStore.Trust trust) {
sqLiteAxolotlStore.setFingerprintTrust(fingerprint, trust);
}
protected SQLiteAxolotlStore.Trust getTrust() {
SQLiteAxolotlStore.Trust trust = sqLiteAxolotlStore.getFingerprintTrust(fingerprint);
return (trust == null) ? SQLiteAxolotlStore.Trust.UNDECIDED : trust;
}
@Nullable
public byte[] processReceiving(byte[] encryptedKey) {
byte[] plaintext = null;
SQLiteAxolotlStore.Trust trust = getTrust();
switch (trust) {
case INACTIVE:
case UNDECIDED:
case UNTRUSTED:
case TRUSTED:
try {
try {
PreKeyWhisperMessage message = new PreKeyWhisperMessage(encryptedKey);
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(encryptedKey);
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());
}
if (plaintext != null && trust == SQLiteAxolotlStore.Trust.INACTIVE) {
setTrust(SQLiteAxolotlStore.Trust.TRUSTED);
}
break;
case COMPROMISED:
default:
// ignore
break;
}
return plaintext;
}
@Nullable
public byte[] processSending(@NonNull byte[] outgoingMessage) {
SQLiteAxolotlStore.Trust trust = getTrust();
if (trust == SQLiteAxolotlStore.Trust.TRUSTED) {
CiphertextMessage ciphertextMessage = cipher.encrypt(outgoingMessage);
return ciphertextMessage.serialize();
} else {
return null;
}
}
}
|