diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxId.java b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxId.java index 06719fb80..a4ca809f2 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxId.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxId.java @@ -2,6 +2,7 @@ package org.briarproject.bramble.api.mailbox; import com.fasterxml.jackson.annotation.JsonValue; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.UniqueId; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -32,7 +33,7 @@ public abstract class MailboxId extends UniqueId { } try { return fromHexString(token); - } catch (IllegalArgumentException e) { + } catch (FormatException e) { throw new InvalidMailboxIdException(); } } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java index 9b6b1220c..e98d2b648 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.util; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.io.UnsupportedEncodingException; @@ -95,10 +96,10 @@ public class StringUtils { /** * Converts the given hex string to a byte array. */ - public static byte[] fromHexString(String hex) { + public static byte[] fromHexString(String hex) throws FormatException { int len = hex.length(); if (len % 2 != 0) - throw new IllegalArgumentException("Not a hex string"); + throw new FormatException(); byte[] bytes = new byte[len / 2]; for (int i = 0, j = 0; i < len; i += 2, j++) { int high = hexDigitToInt(hex.charAt(i)); @@ -108,11 +109,11 @@ public class StringUtils { return bytes; } - private static int hexDigitToInt(char c) { + private static int hexDigitToInt(char c) throws FormatException { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return c - 'A' + 10; if (c >= 'a' && c <= 'f') return c - 'a' + 10; - throw new IllegalArgumentException("Not a hex digit: " + c); + throw new FormatException(); } public static String trim(String s) { @@ -130,13 +131,13 @@ public class StringUtils { return MAC.matcher(mac).matches(); } - public static byte[] macToBytes(String mac) { - if (!MAC.matcher(mac).matches()) throw new IllegalArgumentException(); + public static byte[] macToBytes(String mac) throws FormatException { + if (!MAC.matcher(mac).matches()) throw new FormatException(); return fromHexString(mac.replaceAll(":", "")); } - public static String macToString(byte[] mac) { - if (mac.length != 6) throw new IllegalArgumentException(); + public static String macToString(byte[] mac) throws FormatException { + if (mac.length != 6) throw new FormatException(); StringBuilder s = new StringBuilder(); for (byte b : mac) { if (s.length() > 0) s.append(':'); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java index 4636dfad3..3410c394f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.account; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.DecryptionException; @@ -209,7 +210,13 @@ class AccountManagerImpl implements AccountManager { LOG.warning("Failed to load encrypted database key"); throw new DecryptionException(INVALID_CIPHERTEXT); } - byte[] ciphertext = fromHexString(hex); + byte[] ciphertext; + try { + ciphertext = fromHexString(hex); + } catch (FormatException e) { + LOG.warning("Encrypted database key has invalid format"); + throw new DecryptionException(INVALID_CIPHERTEXT); + } KeyStrengthener keyStrengthener = databaseConfig.getKeyStrengthener(); byte[] plaintext = crypto.decryptWithPassword(ciphertext, password, keyStrengthener); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java index 1af124561..5d41a0bb6 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java @@ -427,7 +427,13 @@ abstract class AbstractBluetoothPlugin implements BluetoothPlugin, BdfList descriptor = new BdfList(); descriptor.add(TRANSPORT_ID_BLUETOOTH); String address = getBluetoothAddress(); - if (address != null) descriptor.add(macToBytes(address)); + if (address != null) { + try { + descriptor.add(macToBytes(address)); + } catch (FormatException e) { + throw new RuntimeException(); + } + } return new BluetoothKeyAgreementListener(descriptor, ss); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java index f0860e0ad..6330a50cf 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java @@ -285,7 +285,7 @@ class LanTcpPlugin extends TcpPlugin { if (ip.length == 16) addrs.add(InetAddress.getByAddress(ip)); } return addrs; - } catch (IllegalArgumentException | UnknownHostException e) { + } catch (FormatException | UnknownHostException e) { return emptyList(); } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/connection/ConnectionRegistryImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/connection/ConnectionRegistryImplTest.java index c8b6de86d..f7fc016f5 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/connection/ConnectionRegistryImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/connection/ConnectionRegistryImplTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.connection; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.connection.ConnectionRegistry; import org.briarproject.bramble.api.connection.InterruptibleConnection; import org.briarproject.bramble.api.contact.ContactId; @@ -57,6 +58,10 @@ public class ConnectionRegistryImplTest extends BrambleMockTestCase { private final Priority high = new Priority(fromHexString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")); + public ConnectionRegistryImplTest() throws FormatException { + // required for throws declaration + } + @Test public void testRegisterMultipleConnections() { context.checking(new Expectations() {{ diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/Blake2bDigestTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/Blake2bDigestTest.java index 29b5d8b65..4980bb5eb 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/Blake2bDigestTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/Blake2bDigestTest.java @@ -1,6 +1,7 @@ package org.briarproject.bramble.crypto; import org.bouncycastle.crypto.digests.Blake2bDigest; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.util.StringUtils; import org.junit.Test; @@ -47,7 +48,7 @@ public class Blake2bDigestTest extends BrambleTestCase { }; @Test - public void testDigestWithKeyedTestVectors() { + public void testDigestWithKeyedTestVectors() throws FormatException { for (String[] keyedTestVector : KEYED_TEST_VECTORS) { byte[] input = StringUtils.fromHexString(keyedTestVector[0]); byte[] key = StringUtils.fromHexString(keyedTestVector[1]); @@ -63,7 +64,8 @@ public class Blake2bDigestTest extends BrambleTestCase { } @Test - public void testDigestWithKeyedTestVectorsAndRandomUpdate() { + public void testDigestWithKeyedTestVectorsAndRandomUpdate() + throws FormatException { Random random = new Random(); for (int i = 0; i < 100; i++) { for (String[] keyedTestVector : KEYED_TEST_VECTORS) { @@ -138,7 +140,7 @@ public class Blake2bDigestTest extends BrambleTestCase { } @Test - public void runSelfTest() { + public void runSelfTest() throws FormatException { Blake2bDigest testDigest = new Blake2bDigest(256); byte[] md = new byte[64]; diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java index aab957a8a..5612663ae 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyAgreementTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.crypto; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.crypto.AgreementPublicKey; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyPair; @@ -83,7 +84,7 @@ public class KeyAgreementTest extends BrambleTestCase { } @Test - public void testRfc7748TestVector() { + public void testRfc7748TestVector() throws FormatException { byte[] aPriv = parsePrivateKey(ALICE_PRIVATE); byte[] aPub = fromHexString(ALICE_PUBLIC); byte[] bPriv = parsePrivateKey(BOB_PRIVATE); @@ -97,7 +98,8 @@ public class KeyAgreementTest extends BrambleTestCase { } @Test - public void testDerivesSameSharedSecretFromEquivalentPublicKey() { + public void testDerivesSameSharedSecretFromEquivalentPublicKey() + throws FormatException { byte[] aPub = fromHexString(ALICE_PUBLIC); byte[] bPriv = parsePrivateKey(BOB_PRIVATE); byte[] sharedSecret = fromHexString(SHARED_SECRET); @@ -168,7 +170,7 @@ public class KeyAgreementTest extends BrambleTestCase { return crypto.deriveSharedSecret(label, publicKey, keyPair, inputs); } - private byte[] parsePrivateKey(String hex) { + private byte[] parsePrivateKey(String hex) throws FormatException { // Private keys need to be clamped because curve25519-java does the // clamping at key generation time, not multiplication time return AgreementKeyParser.clamp(fromHexString(hex)); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java index 9ddcc9487..a7d21dea8 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/XSalsa20Poly1305AuthenticatedCipherTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.crypto; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.util.StringUtils; @@ -15,11 +16,11 @@ public class XSalsa20Poly1305AuthenticatedCipherTest extends BrambleTestCase { // Test vectors from the NaCl paper // http://cr.yp.to/highspeed/naclcrypto-20090310.pdf - private static final byte[] TEST_KEY = StringUtils.fromHexString( + private final byte[] TEST_KEY = StringUtils.fromHexString( "1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389"); - private static final byte[] TEST_IV = StringUtils.fromHexString( + private final byte[] TEST_IV = StringUtils.fromHexString( "69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37"); - private static final byte[] TEST_PLAINTEXT = StringUtils.fromHexString( + private final byte[] TEST_PLAINTEXT = StringUtils.fromHexString( "be075fc53c81f2d5cf141316" + "ebeb0c7b5228c52a4c62cbd4" + "4b66849b64244ffce5ecbaaf" + @@ -31,7 +32,7 @@ public class XSalsa20Poly1305AuthenticatedCipherTest extends BrambleTestCase { "048977eb48f59ffd4924ca1c" + "60902e52f0a089bc76897040" + "e082f937763848645e0705"); - private static final byte[] TEST_CIPHERTEXT = StringUtils.fromHexString( + private final byte[] TEST_CIPHERTEXT = StringUtils.fromHexString( "f3ffc7703f9400e52a7dfb4b" + "3d3305d98e993b9f48681273" + "c29650ba32fc76ce48332ea7" + @@ -46,6 +47,10 @@ public class XSalsa20Poly1305AuthenticatedCipherTest extends BrambleTestCase { "a43d14a6599b1f654cb45a74" + "e355a5"); + public XSalsa20Poly1305AuthenticatedCipherTest() throws FormatException { + // required for throws declaration + } + @Test public void testEncrypt() throws Exception { SecretKey k = new SecretKey(TEST_KEY); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java index 6f1ce7049..f59584b57 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java @@ -618,11 +618,12 @@ public class BdfReaderImplTest extends BrambleTestCase { r.readDictionary(); } - private void setContents(String hex) { + private void setContents(String hex) throws FormatException { setContents(hex, DEFAULT_MAX_BUFFER_SIZE); } - private void setContents(String hex, int maxBufferSize) { + private void setContents(String hex, int maxBufferSize) + throws FormatException { ByteArrayInputStream in = new ByteArrayInputStream(fromHexString(hex)); r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, maxBufferSize); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/util/ByteUtilsTest.java b/bramble-core/src/test/java/org/briarproject/bramble/util/ByteUtilsTest.java index eef6c0b68..e02ab898f 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/util/ByteUtilsTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/util/ByteUtilsTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.util; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.test.BrambleTestCase; import org.junit.Test; @@ -11,7 +12,7 @@ import static org.junit.Assert.fail; public class ByteUtilsTest extends BrambleTestCase { @Test - public void testReadUint16() { + public void testReadUint16() throws FormatException { byte[] b = StringUtils.fromHexString("00000000"); assertEquals(0, ByteUtils.readUint16(b, 1)); b = StringUtils.fromHexString("00000100"); @@ -33,7 +34,7 @@ public class ByteUtilsTest extends BrambleTestCase { } @Test - public void testReadUint32() { + public void testReadUint32() throws FormatException { byte[] b = StringUtils.fromHexString("000000000000"); assertEquals(0, ByteUtils.readUint32(b, 1)); b = StringUtils.fromHexString("000000000100"); @@ -55,7 +56,7 @@ public class ByteUtilsTest extends BrambleTestCase { } @Test - public void testReadUint64() { + public void testReadUint64() throws FormatException { byte[] b = StringUtils.fromHexString("00000000000000000000"); assertEquals(0L, ByteUtils.readUint64(b, 1)); b = StringUtils.fromHexString("00000000000000000100"); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/util/StringUtilsTest.java b/bramble-core/src/test/java/org/briarproject/bramble/util/StringUtilsTest.java index f7042027d..593640824 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/util/StringUtilsTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/util/StringUtilsTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.util; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.test.BrambleTestCase; import org.junit.Test; @@ -24,18 +25,19 @@ public class StringUtilsTest extends BrambleTestCase { assertEquals("", StringUtils.toHexString(new byte[0])); } - @Test(expected = IllegalArgumentException.class) - public void testFromHexStringRejectsInvalidLength() { + @Test(expected = FormatException.class) + public void testFromHexStringRejectsInvalidLength() throws FormatException { StringUtils.fromHexString("12345"); } - @Test(expected = IllegalArgumentException.class) - public void testFromHexStringRejectsInvalidCharacter() { + @Test(expected = FormatException.class) + public void testFromHexStringRejectsInvalidCharacter() + throws FormatException { StringUtils.fromHexString("ABCDEFGH"); } @Test - public void testFromHexStringUppercase() { + public void testFromHexStringUppercase() throws FormatException { String s = "000102037F800A0B0C0D0EFF"; byte[] expected = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x7F, (byte) 0x80, @@ -45,7 +47,7 @@ public class StringUtilsTest extends BrambleTestCase { } @Test - public void testFromHexStringLowercase() { + public void testFromHexStringLowercase() throws FormatException { String s = "000102037f800a0b0c0d0eff"; byte[] expected = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x7F, (byte) 0x80, @@ -55,7 +57,7 @@ public class StringUtilsTest extends BrambleTestCase { } @Test - public void testFromHexStringEmptyInput() { + public void testFromHexStringEmptyInput() throws FormatException { assertArrayEquals(new byte[0], StringUtils.fromHexString("")); } @@ -174,52 +176,52 @@ public class StringUtilsTest extends BrambleTestCase { assertEquals("", StringUtils.truncateUtf8("", 123)); } - @Test(expected = IllegalArgumentException.class) - public void testMacToBytesRejectsShortMac() { + @Test(expected = FormatException.class) + public void testMacToBytesRejectsShortMac() throws FormatException { StringUtils.macToBytes("00:00:00:00:00"); } - @Test(expected = IllegalArgumentException.class) - public void testMacToBytesRejectsLongMac() { + @Test(expected = FormatException.class) + public void testMacToBytesRejectsLongMac() throws FormatException { StringUtils.macToBytes("00:00:00:00:00:00:00"); } - @Test(expected = IllegalArgumentException.class) - public void testMacToBytesRejectsInvalidCharacter() { + @Test(expected = FormatException.class) + public void testMacToBytesRejectsInvalidCharacter() throws FormatException { StringUtils.macToBytes("00:00:00:00:00:0g"); } - @Test(expected = IllegalArgumentException.class) - public void testMacToBytesRejectsInvalidFormat() { + @Test(expected = FormatException.class) + public void testMacToBytesRejectsInvalidFormat() throws FormatException { StringUtils.macToBytes("0:000:00:00:00:00"); } @Test - public void testMacToBytesUpperCase() { + public void testMacToBytesUpperCase() throws FormatException { byte[] expected = new byte[] {0x0A, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F}; String mac = "0A:1B:2C:3D:4E:5F"; assertArrayEquals(expected, StringUtils.macToBytes(mac)); } @Test - public void testMacToBytesLowerCase() { + public void testMacToBytesLowerCase() throws FormatException { byte[] expected = new byte[] {0x0A, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F}; String mac = "0a:1b:2c:3d:4e:5f"; assertArrayEquals(expected, StringUtils.macToBytes(mac)); } - @Test(expected = IllegalArgumentException.class) - public void testMacToStringRejectsShortMac() { + @Test(expected = FormatException.class) + public void testMacToStringRejectsShortMac() throws FormatException { StringUtils.macToString(new byte[5]); } - @Test(expected = IllegalArgumentException.class) - public void testMacToStringRejectsLongMac() { + @Test(expected = FormatException.class) + public void testMacToStringRejectsLongMac() throws FormatException { StringUtils.macToString(new byte[7]); } @Test - public void testMacToString() { + public void testMacToString() throws FormatException { byte[] mac = new byte[] {0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f}; String expected = "0A:1B:2C:3D:4E:5F"; assertEquals(expected, StringUtils.macToString(mac)); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index 55ebd6234..7fedfe6d1 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -8,6 +8,7 @@ import android.os.StrictMode; import com.vanniktech.emoji.RecentEmoji; import org.briarproject.bramble.api.FeatureFlags; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyStrengthener; import org.briarproject.bramble.api.crypto.PublicKey; @@ -242,7 +243,7 @@ public class AppModule { try { return crypto.getMessageKeyParser().parsePublicKey( StringUtils.fromHexString(DEV_PUBLIC_KEY_HEX)); - } catch (GeneralSecurityException e) { + } catch (GeneralSecurityException | FormatException e) { throw new RuntimeException(e); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java index 80a912178..1695970ab 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java @@ -22,6 +22,7 @@ import android.widget.Toast; import com.google.android.material.snackbar.Snackbar; import org.briarproject.bramble.api.FeatureFlags; +import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.connection.ConnectionRegistry; import org.briarproject.bramble.api.contact.ContactId; @@ -519,8 +520,12 @@ public class ConversationActivity extends BriarActivity Selection selection = tracker.getSelection(); List messages = new ArrayList<>(selection.size()); for (String str : selection) { - MessageId id = new MessageId(fromHexString(str)); - messages.add(id); + try { + MessageId id = new MessageId(fromHexString(str)); + messages.add(id); + } catch (FormatException e) { + LOG.warning("Invalid message id"); + } } return messages; }