From 5fcc135f810862f6a4717d11718095686990255e Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Tue, 30 Sep 2014 11:58:56 -0700 Subject: [PATCH] Make sure senderkeys encrypt is correctly initialized. --- .../test/groups/GroupCipherTest.java | 18 ++++++++-- .../libaxolotl/NoSessionException.java | 4 +++ .../libaxolotl/groups/GroupCipher.java | 34 ++++++++++--------- .../groups/state/SenderKeyRecord.java | 9 +++-- .../groups/state/SenderKeyState.java | 2 -- .../groups/state/SenderKeyStore.java | 2 -- 6 files changed, 43 insertions(+), 26 deletions(-) diff --git a/libaxolotl/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java b/libaxolotl/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java index 8a1017c56d..6d93e92123 100644 --- a/libaxolotl/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java +++ b/libaxolotl/src/androidTest/java/org/whispersystems/test/groups/GroupCipherTest.java @@ -6,6 +6,7 @@ import android.util.Log; import org.whispersystems.libaxolotl.DuplicateMessageException; import org.whispersystems.libaxolotl.InvalidMessageException; import org.whispersystems.libaxolotl.LegacyMessageException; +import org.whispersystems.libaxolotl.NoSessionException; import org.whispersystems.libaxolotl.ecc.ECKeyPair; import org.whispersystems.libaxolotl.groups.GroupCipher; import org.whispersystems.libaxolotl.groups.GroupSessionBuilder; @@ -21,7 +22,7 @@ import java.util.List; public class GroupCipherTest extends AndroidTestCase { public void testBasicEncryptDecrypt() - throws LegacyMessageException, DuplicateMessageException, InvalidMessageException + throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException { InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore(); InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore(); @@ -49,7 +50,7 @@ public class GroupCipherTest extends AndroidTestCase { } public void testBasicRatchet() - throws LegacyMessageException, DuplicateMessageException, InvalidMessageException + throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException { InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore(); InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore(); @@ -92,7 +93,7 @@ public class GroupCipherTest extends AndroidTestCase { } public void testOutOfOrder() - throws LegacyMessageException, DuplicateMessageException, InvalidMessageException + throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException { InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore(); InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore(); @@ -129,6 +130,17 @@ public class GroupCipherTest extends AndroidTestCase { } } + public void testEncryptNoSession() { + InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore(); + GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, "groupWithBobInIt"); + try { + aliceGroupCipher.encrypt("up the punks".getBytes()); + throw new AssertionError("Should have failed!"); + } catch (NoSessionException nse) { + // good + } + } + private int randomInt() { try { return SecureRandom.getInstance("SHA1PRNG").nextInt(Integer.MAX_VALUE); diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java index 246c5b025f..162035542c 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/NoSessionException.java @@ -4,4 +4,8 @@ public class NoSessionException extends Exception { public NoSessionException(String s) { super(s); } + + public NoSessionException(Exception nested) { + super(nested); + } } diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java index 9ef14c385e..43dac752e4 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/GroupCipher.java @@ -1,18 +1,16 @@ package org.whispersystems.libaxolotl.groups; -import android.util.Log; - import org.whispersystems.libaxolotl.DuplicateMessageException; import org.whispersystems.libaxolotl.InvalidKeyIdException; import org.whispersystems.libaxolotl.InvalidMessageException; import org.whispersystems.libaxolotl.LegacyMessageException; +import org.whispersystems.libaxolotl.NoSessionException; import org.whispersystems.libaxolotl.groups.ratchet.SenderChainKey; import org.whispersystems.libaxolotl.groups.ratchet.SenderMessageKey; import org.whispersystems.libaxolotl.groups.state.SenderKeyRecord; import org.whispersystems.libaxolotl.groups.state.SenderKeyState; -import org.whispersystems.libaxolotl.protocol.SenderKeyMessage; import org.whispersystems.libaxolotl.groups.state.SenderKeyStore; - +import org.whispersystems.libaxolotl.protocol.SenderKeyMessage; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; @@ -36,23 +34,27 @@ public class GroupCipher { this.senderKeyId = senderKeyId; } - public byte[] encrypt(byte[] paddedPlaintext) { + public byte[] encrypt(byte[] paddedPlaintext) throws NoSessionException { synchronized (LOCK) { - SenderKeyRecord record = senderKeyStore.loadSenderKey(senderKeyId); - SenderKeyState senderKeyState = record.getSenderKeyState(); - SenderMessageKey senderKey = senderKeyState.getSenderChainKey().getSenderMessageKey(); - byte[] ciphertext = getCipherText(senderKey.getIv(), senderKey.getCipherKey(), paddedPlaintext); + try { + SenderKeyRecord record = senderKeyStore.loadSenderKey(senderKeyId); + SenderKeyState senderKeyState = record.getSenderKeyState(); + SenderMessageKey senderKey = senderKeyState.getSenderChainKey().getSenderMessageKey(); + byte[] ciphertext = getCipherText(senderKey.getIv(), senderKey.getCipherKey(), paddedPlaintext); - SenderKeyMessage senderKeyMessage = new SenderKeyMessage(senderKeyState.getKeyId(), - senderKey.getIteration(), - ciphertext, - senderKeyState.getSigningKeyPrivate()); + SenderKeyMessage senderKeyMessage = new SenderKeyMessage(senderKeyState.getKeyId(), + senderKey.getIteration(), + ciphertext, + senderKeyState.getSigningKeyPrivate()); - senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext()); + senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext()); - senderKeyStore.storeSenderKey(senderKeyId, record); + senderKeyStore.storeSenderKey(senderKeyId, record); - return senderKeyMessage.serialize(); + return senderKeyMessage.serialize(); + } catch (InvalidKeyIdException e) { + throw new NoSessionException(e); + } } } diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java index aaeac08cae..bb1ba952ab 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyRecord.java @@ -3,7 +3,6 @@ package org.whispersystems.libaxolotl.groups.state; import org.whispersystems.libaxolotl.InvalidKeyIdException; import org.whispersystems.libaxolotl.ecc.ECKeyPair; import org.whispersystems.libaxolotl.ecc.ECPublicKey; -import org.whispersystems.libaxolotl.groups.state.SenderKeyState; import org.whispersystems.libaxolotl.state.StorageProtos; import java.io.IOException; @@ -26,8 +25,12 @@ public class SenderKeyRecord { } } - public SenderKeyState getSenderKeyState() { - return senderKeyStates.get(0); + public SenderKeyState getSenderKeyState() throws InvalidKeyIdException { + if (!senderKeyStates.isEmpty()) { + return senderKeyStates.get(0); + } else { + throw new InvalidKeyIdException("No key state in record!"); + } } public SenderKeyState getSenderKeyState(int keyId) throws InvalidKeyIdException { diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java index 5ec02a82bb..80498ce0bf 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyState.java @@ -1,7 +1,5 @@ package org.whispersystems.libaxolotl.groups.state; -import android.util.Log; - import com.google.protobuf.ByteString; import org.whispersystems.libaxolotl.InvalidKeyException; diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java index c41d1ec611..da01b1f3d0 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/groups/state/SenderKeyStore.java @@ -1,7 +1,5 @@ package org.whispersystems.libaxolotl.groups.state; -import org.whispersystems.libaxolotl.groups.state.SenderKeyRecord; - public interface SenderKeyStore { public void storeSenderKey(String senderKeyId, SenderKeyRecord record); public SenderKeyRecord loadSenderKey(String senderKeyId);