From ed79719bab45661a8e4c4e76a57a90b767e4c9be Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Mon, 5 Jan 2015 18:55:17 +0000
Subject: [PATCH] Unit tests for StreamEncrypterImpl.

---
 .../crypto/StreamEncrypterImplTest.java       | 240 +++++++++++++++++-
 .../crypto/TestAuthenticatedCipher.java       |  45 ++++
 2 files changed, 279 insertions(+), 6 deletions(-)
 create mode 100644 briar-tests/src/org/briarproject/crypto/TestAuthenticatedCipher.java

diff --git a/briar-tests/src/org/briarproject/crypto/StreamEncrypterImplTest.java b/briar-tests/src/org/briarproject/crypto/StreamEncrypterImplTest.java
index a4738b56dd..a874314165 100644
--- a/briar-tests/src/org/briarproject/crypto/StreamEncrypterImplTest.java
+++ b/briar-tests/src/org/briarproject/crypto/StreamEncrypterImplTest.java
@@ -1,27 +1,255 @@
 package org.briarproject.crypto;
 
+import static org.briarproject.api.transport.TransportConstants.HEADER_LENGTH;
+import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
+import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Random;
+
 import org.briarproject.BriarTestCase;
+import org.briarproject.api.crypto.AuthenticatedCipher;
+import org.briarproject.api.crypto.SecretKey;
 import org.junit.Test;
 
 public class StreamEncrypterImplTest extends BriarTestCase {
 
+	private final AuthenticatedCipher frameCipher;
+	private final SecretKey frameKey;
+	private final byte[] tag;
+
+	public StreamEncrypterImplTest() {
+		frameCipher = new TestAuthenticatedCipher();
+		frameKey = new SecretKey(new byte[32]);
+		tag = new byte[TAG_LENGTH];
+		new Random().nextBytes(tag);
+	}
+
+	@Test
+	public void testWriteUnpaddedNonFinalFrameWithTag() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, tag);
+		int payloadLength = 123;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+
+		s.writeFrame(payload, payloadLength, 0, false);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, false, payloadLength, 0);
+		byte[] expected = new byte[TAG_LENGTH + HEADER_LENGTH + payloadLength
+		                           + MAC_LENGTH];
+		System.arraycopy(tag, 0, expected, 0, TAG_LENGTH);
+		System.arraycopy(header, 0, expected, TAG_LENGTH, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, TAG_LENGTH + HEADER_LENGTH,
+				payloadLength);
+		assertArrayEquals(expected, out.toByteArray());
+	}
+
+	@Test
+	public void testWriteUnpaddedFinalFrameWithTag() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, tag);
+		int payloadLength = 123;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+
+		s.writeFrame(payload, payloadLength, 0, true);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, true, payloadLength, 0);
+		byte[] expected = new byte[TAG_LENGTH + HEADER_LENGTH + payloadLength
+		                           + MAC_LENGTH];
+		System.arraycopy(tag, 0, expected, 0, TAG_LENGTH);
+		System.arraycopy(header, 0, expected, TAG_LENGTH, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, TAG_LENGTH + HEADER_LENGTH,
+				payloadLength);
+		assertArrayEquals(expected, out.toByteArray());
+	}
+
+	@Test
+	public void testWriteUnpaddedNonFinalFrameWithoutTag() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, null);
+		int payloadLength = 123;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+
+		s.writeFrame(payload, payloadLength, 0, false);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, false, payloadLength, 0);
+		byte[] expected = new byte[HEADER_LENGTH + payloadLength + MAC_LENGTH];
+		System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
+		assertArrayEquals(expected, out.toByteArray());
+	}
+
 	@Test
-	public void testEncryptionWithoutTag() throws Exception {
-		// FIXME
+	public void testWriteUnpaddedFinalFrameWithoutTag() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, null);
+		int payloadLength = 123;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+
+		s.writeFrame(payload, payloadLength, 0, true);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, true, payloadLength, 0);
+		byte[] expected = new byte[HEADER_LENGTH + payloadLength + MAC_LENGTH];
+		System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
+		assertArrayEquals(expected, out.toByteArray());
 	}
 
 	@Test
-	public void testEncryptionWithTag() throws Exception {
-		// FIXME
+	public void testWritePaddedNonFinalFrameWithTag() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, tag);
+		int payloadLength = 123, paddingLength = 234;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+
+		s.writeFrame(payload, payloadLength, paddingLength, false);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, false, payloadLength, paddingLength);
+		byte[] expected = new byte[TAG_LENGTH + HEADER_LENGTH + payloadLength
+		                           + paddingLength + MAC_LENGTH];
+		System.arraycopy(tag, 0, expected, 0, TAG_LENGTH);
+		System.arraycopy(header, 0, expected, TAG_LENGTH, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, TAG_LENGTH + HEADER_LENGTH,
+				payloadLength);
+		assertArrayEquals(expected, out.toByteArray());
+	}
+
+	@Test
+	public void testWritePaddedFinalFrameWithTag() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, tag);
+		int payloadLength = 123, paddingLength = 234;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+
+		s.writeFrame(payload, payloadLength, paddingLength, true);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, true, payloadLength, paddingLength);
+		byte[] expected = new byte[TAG_LENGTH + HEADER_LENGTH + payloadLength
+		                           + paddingLength + MAC_LENGTH];
+		System.arraycopy(tag, 0, expected, 0, TAG_LENGTH);
+		System.arraycopy(header, 0, expected, TAG_LENGTH, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, TAG_LENGTH + HEADER_LENGTH,
+				payloadLength);
+		assertArrayEquals(expected, out.toByteArray());
+	}
+
+	@Test
+	public void testWritePaddedNonFinalFrameWithoutTag() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, null);
+		int payloadLength = 123, paddingLength = 234;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+
+		s.writeFrame(payload, payloadLength, paddingLength, false);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, false, payloadLength, paddingLength);
+		byte[] expected = new byte[HEADER_LENGTH + payloadLength
+		                           + paddingLength + MAC_LENGTH];
+		System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
+		assertArrayEquals(expected, out.toByteArray());
+	}
+
+	@Test
+	public void testWritePaddedFinalFrameWithoutTag() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, null);
+		int payloadLength = 123, paddingLength = 234;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+
+		s.writeFrame(payload, payloadLength, paddingLength, true);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, true, payloadLength, paddingLength);
+		byte[] expected = new byte[HEADER_LENGTH + payloadLength
+		                           + paddingLength + MAC_LENGTH];
+		System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
+		assertArrayEquals(expected, out.toByteArray());
+	}
+
+	@Test
+	public void testWriteTwoFrames() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, null);
+		int payloadLength = 123, paddingLength = 234;
+		byte[] payload = new byte[payloadLength];
+		new Random().nextBytes(payload);
+		int payloadLength1 = 345, paddingLength1 = 456;
+		byte[] payload1 = new byte[payloadLength1];
+		new Random().nextBytes(payload1);
+
+		s.writeFrame(payload, payloadLength, paddingLength, false);
+		s.writeFrame(payload1, payloadLength1, paddingLength1, true);
+
+		byte[] header = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header, false, payloadLength, paddingLength);
+		byte[] header1 = new byte[HEADER_LENGTH];
+		FrameEncoder.encodeHeader(header1, true, payloadLength1,
+				paddingLength1);
+		byte[] expected = new byte[HEADER_LENGTH + payloadLength
+		                           + paddingLength + MAC_LENGTH
+		                           + HEADER_LENGTH + payloadLength1
+		                           + paddingLength1 + MAC_LENGTH];
+		System.arraycopy(header, 0, expected, 0, HEADER_LENGTH);
+		System.arraycopy(payload, 0, expected, HEADER_LENGTH, payloadLength);
+		System.arraycopy(header1, 0, expected, HEADER_LENGTH + payloadLength
+				+ paddingLength + MAC_LENGTH, HEADER_LENGTH);
+		System.arraycopy(payload1, 0, expected, HEADER_LENGTH + payloadLength
+				+ paddingLength + MAC_LENGTH + HEADER_LENGTH, payloadLength1);
+		assertArrayEquals(expected, out.toByteArray());
 	}
 
 	@Test
 	public void testFlushWritesTagIfNotAlreadyWritten() throws Exception {
-		// FIXME
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, tag);
+		s.flush();
+		assertArrayEquals(tag, out.toByteArray());
 	}
 
 	@Test
 	public void testFlushDoesNotWriteTagIfAlreadyWritten() throws Exception {
-		// FIXME
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, tag);
+		s.flush();
+		s.flush();
+		assertArrayEquals(tag, out.toByteArray());
+	}
+
+	@Test
+	public void testFlushDoesNotWriteTagIfNull() throws Exception {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		StreamEncrypterImpl s = new StreamEncrypterImpl(out, frameCipher,
+				frameKey, null);
+		s.flush();
+		assertEquals(0, out.size());
 	}
 }
diff --git a/briar-tests/src/org/briarproject/crypto/TestAuthenticatedCipher.java b/briar-tests/src/org/briarproject/crypto/TestAuthenticatedCipher.java
new file mode 100644
index 0000000000..0271975bd4
--- /dev/null
+++ b/briar-tests/src/org/briarproject/crypto/TestAuthenticatedCipher.java
@@ -0,0 +1,45 @@
+package org.briarproject.crypto;
+
+import static org.briarproject.api.transport.TransportConstants.MAC_LENGTH;
+
+import java.security.GeneralSecurityException;
+
+import org.briarproject.api.crypto.AuthenticatedCipher;
+import org.briarproject.api.crypto.SecretKey;
+
+class TestAuthenticatedCipher implements AuthenticatedCipher {
+
+	private static final int BLOCK_BYTES = 16;
+
+	private boolean encrypt = false;
+
+	public void init(boolean encrypt, SecretKey key, byte[] iv, byte[] aad)
+			throws GeneralSecurityException {
+		this.encrypt = encrypt;
+	}
+
+	public int process(byte[] input, int inputOff, int len, byte[] output,
+			int outputOff) throws GeneralSecurityException {
+		if(encrypt) {
+			System.arraycopy(input, inputOff, output, outputOff, len);
+			for(int i = 0; i < MAC_LENGTH; i++)
+				output[outputOff + len + i] = 0;
+			return len + MAC_LENGTH;
+		} else {
+			for(int i = 0; i < MAC_LENGTH; i++)
+				if(input[inputOff + len - MAC_LENGTH + i] != 0)
+					throw new GeneralSecurityException();
+			System.arraycopy(input, inputOff, output, outputOff,
+					len - MAC_LENGTH);
+			return len - MAC_LENGTH;
+		}
+	}
+
+	public int getMacLength() {
+		return MAC_LENGTH;
+	}
+
+	public int getBlockSize() {
+		return BLOCK_BYTES;
+	}
+}
-- 
GitLab