aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Straub <andy@strb.org>2015-07-21 01:15:32 +0200
committerAndreas Straub <andy@strb.org>2015-07-21 01:17:14 +0200
commit122bc97ce24181ccd07cf9badf8d4c3b81d80c3f (patch)
treea68680556a66f89c4725a418012da5d0a7c8801a
parent971aa3a11e1077a38746cb45e7177851725be47e (diff)
Switch payload encryption to AES-GCM
This also ensures that the IV is generated with proper randomness.
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java28
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java7
-rw-r--r--src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java28
3 files changed, 46 insertions, 17 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 b0724593..fbea3b0f 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java
@@ -4,6 +4,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.whispersystems.libaxolotl.AxolotlAddress;
import org.whispersystems.libaxolotl.DuplicateMessageException;
import org.whispersystems.libaxolotl.IdentityKey;
@@ -30,6 +31,7 @@ import org.whispersystems.libaxolotl.state.SessionRecord;
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
import org.whispersystems.libaxolotl.util.KeyHelper;
+import java.security.Security;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -678,6 +680,9 @@ public class AxolotlService {
}
public AxolotlService(Account account, XmppConnectionService connectionService) {
+ if (Security.getProvider("BC") == null) {
+ Security.addProvider(new BouncyCastleProvider());
+ }
this.mXmppConnectionService = connectionService;
this.account = account;
this.axolotlStore = new SQLiteAxolotlStore(this.account, this.mXmppConnectionService);
@@ -1050,11 +1055,17 @@ public class AxolotlService {
final String content;
if (message.hasFileOnRemoteHost()) {
content = message.getFileParams().url.toString();
- } else {
- content = message.getBody();
- }
- final XmppAxolotlMessage axolotlMessage = new XmppAxolotlMessage(message.getContact().getJid().toBareJid(),
- getOwnDeviceId(), content);
+ } else {
+ content = message.getBody();
+ }
+ final XmppAxolotlMessage axolotlMessage;
+ try {
+ axolotlMessage = new XmppAxolotlMessage(message.getContact().getJid().toBareJid(),
+ getOwnDeviceId(), content);
+ } catch (CryptoFailedException e) {
+ Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to encrypt message: " + e.getMessage());
+ return null;
+ }
if(findSessionsforContact(message.getContact()).isEmpty()) {
return null;
@@ -1143,7 +1154,12 @@ public class AxolotlService {
byte[] payloadKey = session.processReceiving(header);
if (payloadKey != null) {
Log.d(Config.LOGTAG, AxolotlService.getLogprefix(account)+"Got payload key from axolotl header. Decrypting message...");
- plaintextMessage = message.decrypt(session, payloadKey, session.getFingerprint());
+ try{
+ plaintextMessage = message.decrypt(session, payloadKey, session.getFingerprint());
+ } catch (CryptoFailedException e) {
+ Log.w(Config.LOGTAG, getLogprefix(account) + "Failed to decrypt message: " + e.getMessage());
+ break;
+ }
}
Integer preKeyId = session.getPreKeyId();
if (preKeyId != null) {
diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java
new file mode 100644
index 00000000..5796ef30
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/CryptoFailedException.java
@@ -0,0 +1,7 @@
+package eu.siacs.conversations.crypto.axolotl;
+
+public class CryptoFailedException extends Exception {
+ public CryptoFailedException(Exception e){
+ super(e);
+ }
+}
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 ec068ec7..24afeaea 100644
--- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
+++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java
@@ -6,6 +6,8 @@ import android.util.Base64;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
import java.util.HashSet;
import java.util.Set;
@@ -107,26 +109,30 @@ public class XmppAxolotlMessage {
}
}
- public XmppAxolotlMessage(Jid from, int sourceDeviceId, String plaintext) {
+ public XmppAxolotlMessage(Jid from, int sourceDeviceId, String plaintext) throws CryptoFailedException{
this.from = from;
this.sourceDeviceId = sourceDeviceId;
this.headers = new HashSet<>();
this.encrypt(plaintext);
}
- private void encrypt(String plaintext) {
+ private void encrypt(String plaintext) throws CryptoFailedException {
try {
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128);
SecretKey secretKey = generator.generateKey();
- Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
- cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+ SecureRandom random = new SecureRandom();
+ this.iv = new byte[16];
+ random.nextBytes(iv);
+ IvParameterSpec ivSpec = new IvParameterSpec(iv);
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
this.innerKey = secretKey.getEncoded();
- this.iv = cipher.getIV();
this.ciphertext = cipher.doFinal(plaintext.getBytes());
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
- | IllegalBlockSizeException | BadPaddingException e) {
-
+ | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException
+ | InvalidAlgorithmParameterException e) {
+ throw new CryptoFailedException(e);
}
}
@@ -174,11 +180,11 @@ public class XmppAxolotlMessage {
}
- public XmppAxolotlPlaintextMessage decrypt(AxolotlService.XmppAxolotlSession session, byte[] key, String fingerprint) {
+ public XmppAxolotlPlaintextMessage decrypt(AxolotlService.XmppAxolotlSession session, byte[] key, String fingerprint) throws CryptoFailedException {
XmppAxolotlPlaintextMessage plaintextMessage = null;
try {
- Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
@@ -189,8 +195,8 @@ public class XmppAxolotlMessage {
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| InvalidAlgorithmParameterException | IllegalBlockSizeException
- | BadPaddingException e) {
- throw new AssertionError(e);
+ | BadPaddingException | NoSuchProviderException e) {
+ throw new CryptoFailedException(e);
}
return plaintextMessage;
}