From 510f99c7dadca0910b48c84c6f1c9f61ccec85a6 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Mon, 27 Mar 2017 16:26:49 +0100
Subject: [PATCH] Validate arguments to StreamEncrypter#writeFrame().

---
 .../bramble/crypto/StreamEncrypterImpl.java   |  2 +
 .../crypto/StreamEncrypterImplTest.java       | 56 +++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterImpl.java
index cb708eb4cf..59afd8531f 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/StreamEncrypterImpl.java
@@ -62,6 +62,8 @@ class StreamEncrypterImpl implements StreamEncrypter {
 	@Override
 	public void writeFrame(byte[] payload, int payloadLength,
 			int paddingLength, boolean finalFrame) throws IOException {
+		if (payloadLength < 0 || paddingLength < 0)
+			throw new IllegalArgumentException();
 		if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH)
 			throw new IllegalArgumentException();
 		// Don't allow the frame counter to wrap
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/StreamEncrypterImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/StreamEncrypterImplTest.java
index 8ed35336d4..c13749f684 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/StreamEncrypterImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/StreamEncrypterImplTest.java
@@ -9,9 +9,13 @@ import java.io.ByteArrayOutputStream;
 
 import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
 import static org.briarproject.bramble.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_FRAME_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
 import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_IV_LENGTH;
+import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_LENGTH;
 import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
 
 public class StreamEncrypterImplTest extends BrambleTestCase {
 
@@ -30,6 +34,58 @@ public class StreamEncrypterImplTest extends BrambleTestCase {
 		payload = TestUtils.getRandomBytes(payloadLength);
 	}
 
+	@Test(expected = IllegalArgumentException.class)
+	public void testRejectsNegativePayloadLength() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
+				streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
+
+		s.writeFrame(payload, -1, 0, false);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testRejectsNegativePaddingLength() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
+				streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
+
+		s.writeFrame(payload, 0, -1, false);
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testRejectsMaxPayloadPlusPadding() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
+				streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
+
+		byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH + 1];
+		s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH, 1, false);
+	}
+
+	@Test
+	public void testAcceptsMaxPayloadIncludingPadding() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
+				streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
+
+		byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH];
+		s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH - 1, 1, false);
+		assertEquals(TAG_LENGTH + STREAM_HEADER_LENGTH + MAX_FRAME_LENGTH,
+				out.size());
+	}
+
+	@Test
+	public void testAcceptsMaxPayloadWithoutPadding() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, cipher,
+				streamNumber, tag, streamHeaderIv, streamHeaderKey, frameKey);
+
+		byte[] bigPayload = new byte[MAX_PAYLOAD_LENGTH];
+		s.writeFrame(bigPayload, MAX_PAYLOAD_LENGTH, 0, false);
+		assertEquals(TAG_LENGTH + STREAM_HEADER_LENGTH + MAX_FRAME_LENGTH,
+				out.size());
+	}
+
 	@Test
 	public void testWriteUnpaddedNonFinalFrameWithTag() throws Exception {
 		ByteArrayOutputStream out = new ByteArrayOutputStream();
-- 
GitLab