diff --git a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java index f587991f2de10328fe4c8e110ae6e8e4b7d2fdd9..95c0524571cbda43d2851afd543037db2fc1cf42 100644 --- a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java @@ -44,18 +44,18 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory { // Create the decrypter Cipher tagCipher = crypto.getTagCipher(); Cipher segCipher = crypto.getSegmentCipher(); - IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in, + IncomingEncryptionLayer encryption = new IncomingEncryptionLayerImpl(in, tagCipher, segCipher, tagKey, segKey, false, bufferedTag); // No error correction - IncomingErrorCorrectionLayer correcter = - new NullIncomingErrorCorrectionLayer(decrypter); + IncomingErrorCorrectionLayer correction = + new NullIncomingErrorCorrectionLayer(encryption); // Create the authenticator Mac mac = crypto.getMac(); - IncomingAuthenticationLayer authenticator = - new IncomingAuthenticationLayerImpl(correcter, mac, macKey); + IncomingAuthenticationLayer authentication = + new IncomingAuthenticationLayerImpl(correction, mac, macKey); // No reordering or retransmission IncomingReliabilityLayer reliability = - new NullIncomingReliabilityLayer(authenticator); + new NullIncomingReliabilityLayer(authentication); // Create the reader - don't tolerate errors return new ConnectionReaderImpl(reliability, false); } @@ -80,19 +80,19 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory { // Create the decrypter Cipher tagCipher = crypto.getTagCipher(); Cipher segCipher = crypto.getSegmentCipher(); - IncomingEncryptionLayer decrypter = + IncomingEncryptionLayer encryption = new IncomingSegmentedEncryptionLayer(in, tagCipher, segCipher, tagKey, segKey, false, bufferedSegment); // No error correction - IncomingErrorCorrectionLayer correcter = - new NullIncomingErrorCorrectionLayer(decrypter); + IncomingErrorCorrectionLayer correction = + new NullIncomingErrorCorrectionLayer(encryption); // Create the authenticator Mac mac = crypto.getMac(); - IncomingAuthenticationLayer authenticator = - new IncomingAuthenticationLayerImpl(correcter, mac, macKey); + IncomingAuthenticationLayer authentication = + new IncomingAuthenticationLayerImpl(correction, mac, macKey); // No reordering or retransmission IncomingReliabilityLayer reliability = - new NullIncomingReliabilityLayer(authenticator); + new NullIncomingReliabilityLayer(authentication); // Create the reader - don't tolerate errors return new ConnectionReaderImpl(reliability, false); } diff --git a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java index 067e041952fb14b7b18ae3b5a1877e5b7da5c54d..6382955245b48b4ed6b24c7cf61107e46c57dec8 100644 --- a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java @@ -33,14 +33,20 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory { // Create the encrypter Cipher tagCipher = crypto.getTagCipher(); Cipher segCipher = crypto.getSegmentCipher(); - OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out, - capacity, tagCipher, segCipher, tagKey, segKey, false); + OutgoingEncryptionLayer encryption = new OutgoingEncryptionLayerImpl( + out, capacity, tagCipher, segCipher, tagKey, segKey, false); // No error correction - OutgoingErrorCorrectionLayer correcter = - new NullOutgoingErrorCorrectionLayer(encrypter); - // Create the writer + OutgoingErrorCorrectionLayer correction = + new NullOutgoingErrorCorrectionLayer(encryption); + // Authentication Mac mac = crypto.getMac(); - return new ConnectionWriterImpl(correcter, mac, macKey); + OutgoingAuthenticationLayer authentication = + new OutgoingAuthenticationLayerImpl(correction, mac, macKey); + // No retransmission + OutgoingReliabilityLayer reliability = + new NullOutgoingReliabilityLayer(authentication); + // Create the writer + return new ConnectionWriterImpl(reliability); } public ConnectionWriter createConnectionWriter(SegmentSink out, @@ -53,14 +59,20 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory { // Create the encrypter Cipher tagCipher = crypto.getTagCipher(); Cipher segCipher = crypto.getSegmentCipher(); - OutgoingEncryptionLayer encrypter = + OutgoingEncryptionLayer encryption = new OutgoingSegmentedEncryptionLayer(out, capacity, tagCipher, segCipher, tagKey, segKey, false); // No error correction - OutgoingErrorCorrectionLayer correcter = - new NullOutgoingErrorCorrectionLayer(encrypter); - // Create the writer + OutgoingErrorCorrectionLayer correction = + new NullOutgoingErrorCorrectionLayer(encryption); + // Authentication Mac mac = crypto.getMac(); - return new ConnectionWriterImpl(correcter, mac, macKey); + OutgoingAuthenticationLayer authentication = + new OutgoingAuthenticationLayerImpl(correction, mac, macKey); + // No retransmission + OutgoingReliabilityLayer reliability = + new NullOutgoingReliabilityLayer(authentication); + // Create the writer + return new ConnectionWriterImpl(reliability); } } diff --git a/components/net/sf/briar/transport/ConnectionWriterImpl.java b/components/net/sf/briar/transport/ConnectionWriterImpl.java index 9a7ad2efca1ddd919ac03bc28424d1b5c1ab185c..d1fcbd7a0d74a3fdd6843c1421837ab03a276dfb 100644 --- a/components/net/sf/briar/transport/ConnectionWriterImpl.java +++ b/components/net/sf/briar/transport/ConnectionWriterImpl.java @@ -7,12 +7,7 @@ import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import java.io.IOException; import java.io.OutputStream; -import java.security.InvalidKeyException; -import javax.crypto.Mac; -import javax.crypto.ShortBufferException; - -import net.sf.briar.api.crypto.ErasableKey; import net.sf.briar.api.transport.ConnectionWriter; /** @@ -23,26 +18,14 @@ import net.sf.briar.api.transport.ConnectionWriter; */ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter { - private final OutgoingErrorCorrectionLayer out; - private final Mac mac; + private final OutgoingReliabilityLayer out; private final Frame frame; private int offset = FRAME_HEADER_LENGTH; private long frameNumber = 0L; - ConnectionWriterImpl(OutgoingErrorCorrectionLayer out, Mac mac, - ErasableKey macKey) { + ConnectionWriterImpl(OutgoingReliabilityLayer out) { this.out = out; - this.mac = mac; - // Initialise the MAC - try { - mac.init(macKey); - } catch(InvalidKeyException badKey) { - throw new IllegalArgumentException(badKey); - } - macKey.erase(); - if(mac.getMacLength() != MAC_LENGTH) - throw new IllegalArgumentException(); frame = new Frame(); } @@ -96,16 +79,9 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter { private void writeFrame() throws IOException { if(frameNumber > MAX_32_BIT_UNSIGNED) throw new IllegalStateException(); - byte[] buf = frame.getBuffer(); - int payloadLength = offset - FRAME_HEADER_LENGTH; - assert payloadLength > 0; - HeaderEncoder.encodeHeader(buf, frameNumber, payloadLength, 0); - mac.update(buf, 0, offset); - try { - mac.doFinal(buf, offset); - } catch(ShortBufferException badMac) { - throw new RuntimeException(badMac); - } + int payload = offset - FRAME_HEADER_LENGTH; + assert payload > 0; + HeaderEncoder.encodeHeader(frame.getBuffer(), frameNumber, payload, 0); frame.setLength(offset + MAC_LENGTH); out.writeFrame(frame); offset = FRAME_HEADER_LENGTH; diff --git a/components/net/sf/briar/transport/NullOutgoingReliabilityLayer.java b/components/net/sf/briar/transport/NullOutgoingReliabilityLayer.java new file mode 100644 index 0000000000000000000000000000000000000000..a00a2e9c4e0c1bd14ef356dee2a3ce41673440a5 --- /dev/null +++ b/components/net/sf/briar/transport/NullOutgoingReliabilityLayer.java @@ -0,0 +1,24 @@ +package net.sf.briar.transport; + +import java.io.IOException; + +class NullOutgoingReliabilityLayer implements OutgoingReliabilityLayer { + + private final OutgoingAuthenticationLayer out; + + NullOutgoingReliabilityLayer(OutgoingAuthenticationLayer out) { + this.out = out; + } + + public void writeFrame(Frame f) throws IOException { + out.writeFrame(f); + } + + public void flush() throws IOException { + out.flush(); + } + + public long getRemainingCapacity() { + return out.getRemainingCapacity(); + } +} diff --git a/components/net/sf/briar/transport/OutgoingAuthenticationLayer.java b/components/net/sf/briar/transport/OutgoingAuthenticationLayer.java new file mode 100644 index 0000000000000000000000000000000000000000..e1b9b72b6d7ed61857b0c80cfe1714c2fdb6c0d1 --- /dev/null +++ b/components/net/sf/briar/transport/OutgoingAuthenticationLayer.java @@ -0,0 +1,15 @@ +package net.sf.briar.transport; + +import java.io.IOException; + +interface OutgoingAuthenticationLayer { + + /** Writes the given frame. */ + void writeFrame(Frame f) throws IOException; + + /** Flushes the stack. */ + void flush() throws IOException; + + /** Returns the maximum number of bytes that can be written. */ + long getRemainingCapacity(); +} diff --git a/components/net/sf/briar/transport/OutgoingAuthenticationLayerImpl.java b/components/net/sf/briar/transport/OutgoingAuthenticationLayerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..c8cee560b454b3e083cfd4e933061c15de204bfa --- /dev/null +++ b/components/net/sf/briar/transport/OutgoingAuthenticationLayerImpl.java @@ -0,0 +1,52 @@ +package net.sf.briar.transport; + +import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; + +import java.io.IOException; +import java.security.InvalidKeyException; + +import javax.crypto.Mac; +import javax.crypto.ShortBufferException; + +import net.sf.briar.api.crypto.ErasableKey; + +class OutgoingAuthenticationLayerImpl implements OutgoingAuthenticationLayer { + + private final OutgoingErrorCorrectionLayer out; + private final Mac mac; + + OutgoingAuthenticationLayerImpl(OutgoingErrorCorrectionLayer out, Mac mac, + ErasableKey macKey) { + this.out = out; + this.mac = mac; + // Initialise the MAC + try { + mac.init(macKey); + } catch(InvalidKeyException badKey) { + throw new IllegalArgumentException(badKey); + } + macKey.erase(); + if(mac.getMacLength() != MAC_LENGTH) + throw new IllegalArgumentException(); + } + + public void writeFrame(Frame f) throws IOException { + byte[] buf = f.getBuffer(); + int length = f.getLength() - MAC_LENGTH; + mac.update(buf, 0, length); + try { + mac.doFinal(buf, length); + } catch(ShortBufferException badMac) { + throw new RuntimeException(badMac); + } + out.writeFrame(f); + } + + public void flush() throws IOException { + out.flush(); + } + + public long getRemainingCapacity() { + return out.getRemainingCapacity(); + } +} diff --git a/components/net/sf/briar/transport/OutgoingReliabilityLayer.java b/components/net/sf/briar/transport/OutgoingReliabilityLayer.java new file mode 100644 index 0000000000000000000000000000000000000000..49aacb499a883964f7d52a3b5057035fe89cd79f --- /dev/null +++ b/components/net/sf/briar/transport/OutgoingReliabilityLayer.java @@ -0,0 +1,15 @@ +package net.sf.briar.transport; + +import java.io.IOException; + +interface OutgoingReliabilityLayer { + + /** Writes the given frame. */ + void writeFrame(Frame f) throws IOException; + + /** Flushes the stack. */ + void flush() throws IOException; + + /** Returns the maximum number of bytes that can be written. */ + long getRemainingCapacity(); +} diff --git a/test/net/sf/briar/transport/ConnectionReaderImplTest.java b/test/net/sf/briar/transport/ConnectionReaderImplTest.java index d03330fa914593f8e1f49d9651f5f1faf7df3cfe..feaddea5ce670569c7afed45d770f8f404dcf1c0 100644 --- a/test/net/sf/briar/transport/ConnectionReaderImplTest.java +++ b/test/net/sf/briar/transport/ConnectionReaderImplTest.java @@ -217,13 +217,14 @@ public class ConnectionReaderImplTest extends TransportTest { } private ConnectionReader createConnectionReader(InputStream in) { - IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in); - IncomingErrorCorrectionLayer correcter = - new NullIncomingErrorCorrectionLayer(decrypter); - IncomingAuthenticationLayer authenticator = - new IncomingAuthenticationLayerImpl(correcter, mac, macKey); + IncomingEncryptionLayer encryption = + new NullIncomingEncryptionLayer(in); + IncomingErrorCorrectionLayer correction = + new NullIncomingErrorCorrectionLayer(encryption); + IncomingAuthenticationLayer authentication = + new IncomingAuthenticationLayerImpl(correction, mac, macKey); IncomingReliabilityLayer reliability = - new NullIncomingReliabilityLayer(authenticator); + new NullIncomingReliabilityLayer(authentication); return new ConnectionReaderImpl(reliability, false); } } diff --git a/test/net/sf/briar/transport/ConnectionWriterImplTest.java b/test/net/sf/briar/transport/ConnectionWriterImplTest.java index 4259d717b5c524045e7517784f32b0e31c98ab65..225062ba19a9e5aa83b1859daf1ff3d55687aae1 100644 --- a/test/net/sf/briar/transport/ConnectionWriterImplTest.java +++ b/test/net/sf/briar/transport/ConnectionWriterImplTest.java @@ -12,6 +12,7 @@ import net.sf.briar.api.transport.ConnectionWriter; import org.junit.Test; +// FIXME: This test covers too many classes public class ConnectionWriterImplTest extends TransportTest { public ConnectionWriterImplTest() throws Exception { @@ -21,11 +22,7 @@ public class ConnectionWriterImplTest extends TransportTest { @Test public void testFlushWithoutWriteProducesNothing() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutgoingEncryptionLayer encrypter = - new NullOutgoingEncryptionLayer(out); - OutgoingErrorCorrectionLayer correcter = - new NullOutgoingErrorCorrectionLayer(encrypter); - ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey); + ConnectionWriter w = createConnectionWriter(out); w.getOutputStream().flush(); w.getOutputStream().flush(); w.getOutputStream().flush(); @@ -44,11 +41,7 @@ public class ConnectionWriterImplTest extends TransportTest { mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength); // Check that the ConnectionWriter gets the same results ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutgoingEncryptionLayer encrypter = - new NullOutgoingEncryptionLayer(out); - OutgoingErrorCorrectionLayer correcter = - new NullOutgoingErrorCorrectionLayer(encrypter); - ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey); + ConnectionWriter w = createConnectionWriter(out); w.getOutputStream().write(0); w.getOutputStream().flush(); assertArrayEquals(frame, out.toByteArray()); @@ -57,11 +50,7 @@ public class ConnectionWriterImplTest extends TransportTest { @Test public void testWriteByteToMaxLengthWritesFrame() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutgoingEncryptionLayer encrypter = - new NullOutgoingEncryptionLayer(out); - OutgoingErrorCorrectionLayer correcter = - new NullOutgoingErrorCorrectionLayer(encrypter); - ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey); + ConnectionWriter w = createConnectionWriter(out); OutputStream out1 = w.getOutputStream(); // The first maxPayloadLength - 1 bytes should be buffered for(int i = 0; i < MAX_PAYLOAD_LENGTH - 1; i++) out1.write(0); @@ -74,11 +63,7 @@ public class ConnectionWriterImplTest extends TransportTest { @Test public void testWriteArrayToMaxLengthWritesFrame() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutgoingEncryptionLayer encrypter = - new NullOutgoingEncryptionLayer(out); - OutgoingErrorCorrectionLayer correcter = - new NullOutgoingErrorCorrectionLayer(encrypter); - ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey); + ConnectionWriter w = createConnectionWriter(out); OutputStream out1 = w.getOutputStream(); // The first maxPayloadLength - 1 bytes should be buffered out1.write(new byte[MAX_PAYLOAD_LENGTH - 1]); @@ -112,11 +97,7 @@ public class ConnectionWriterImplTest extends TransportTest { byte[] expected = out.toByteArray(); // Check that the ConnectionWriter gets the same results out.reset(); - OutgoingEncryptionLayer encrypter = - new NullOutgoingEncryptionLayer(out); - OutgoingErrorCorrectionLayer correcter = - new NullOutgoingErrorCorrectionLayer(encrypter); - ConnectionWriter w = new ConnectionWriterImpl(correcter, mac, macKey); + ConnectionWriter w = createConnectionWriter(out); w.getOutputStream().write(new byte[123]); w.getOutputStream().flush(); w.getOutputStream().write(new byte[1234]); @@ -124,4 +105,16 @@ public class ConnectionWriterImplTest extends TransportTest { byte[] actual = out.toByteArray(); assertArrayEquals(expected, actual); } + + private ConnectionWriter createConnectionWriter(OutputStream out) { + OutgoingEncryptionLayer encryption = + new NullOutgoingEncryptionLayer(out); + OutgoingErrorCorrectionLayer correction = + new NullOutgoingErrorCorrectionLayer(encryption); + OutgoingAuthenticationLayer authentication = + new OutgoingAuthenticationLayerImpl(correction, mac, macKey); + OutgoingReliabilityLayer reliability = + new NullOutgoingReliabilityLayer(authentication); + return new ConnectionWriterImpl(reliability); + } } diff --git a/test/net/sf/briar/transport/FrameReadWriteTest.java b/test/net/sf/briar/transport/FrameReadWriteTest.java index ef0403f3a0658a74c5031ab1277d3a3f1aa41cfd..5ca19087826e3778623d9121ee9096b789350435 100644 --- a/test/net/sf/briar/transport/FrameReadWriteTest.java +++ b/test/net/sf/briar/transport/FrameReadWriteTest.java @@ -74,13 +74,16 @@ public class FrameReadWriteTest extends BriarTestCase { ErasableKey macCopy = macKey.copy(); // Write the frames ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out, - Long.MAX_VALUE, tagCipher, segCipher, tagCopy, segCopy, + OutgoingEncryptionLayer encryptionOut = new OutgoingEncryptionLayerImpl( + out, Long.MAX_VALUE, tagCipher, segCipher, tagCopy, segCopy, false); - OutgoingErrorCorrectionLayer correcter = - new NullOutgoingErrorCorrectionLayer(encrypter); - ConnectionWriter writer = new ConnectionWriterImpl(correcter, mac, - macCopy); + OutgoingErrorCorrectionLayer correctionOut = + new NullOutgoingErrorCorrectionLayer(encryptionOut); + OutgoingAuthenticationLayer authenticationOut = + new OutgoingAuthenticationLayerImpl(correctionOut, mac, macCopy); + OutgoingReliabilityLayer reliabilityOut = + new NullOutgoingReliabilityLayer(authenticationOut); + ConnectionWriter writer = new ConnectionWriterImpl(reliabilityOut); OutputStream out1 = writer.getOutputStream(); out1.write(frame); out1.flush(); @@ -93,15 +96,16 @@ public class FrameReadWriteTest extends BriarTestCase { assertArrayEquals(tag, recoveredTag); assertEquals(0L, TagEncoder.decodeTag(tag, tagCipher, tagKey)); // Read the frames back - IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in, - tagCipher, segCipher, tagKey, segKey, false, recoveredTag); - IncomingErrorCorrectionLayer correcter1 = - new NullIncomingErrorCorrectionLayer(decrypter); - IncomingAuthenticationLayer authenticator = - new IncomingAuthenticationLayerImpl(correcter1, mac, macKey); - IncomingReliabilityLayer reliability = - new NullIncomingReliabilityLayer(authenticator); - ConnectionReader reader = new ConnectionReaderImpl(reliability, false); + IncomingEncryptionLayer encryptionIn = new IncomingEncryptionLayerImpl( + in, tagCipher, segCipher, tagKey, segKey, false, recoveredTag); + IncomingErrorCorrectionLayer correctionIn = + new NullIncomingErrorCorrectionLayer(encryptionIn); + IncomingAuthenticationLayer authenticationIn = + new IncomingAuthenticationLayerImpl(correctionIn, mac, macKey); + IncomingReliabilityLayer reliabilityIn = + new NullIncomingReliabilityLayer(authenticationIn); + ConnectionReader reader = new ConnectionReaderImpl(reliabilityIn, + false); InputStream in1 = reader.getInputStream(); byte[] recovered = new byte[frame.length]; int offset = 0;