diff --git a/api/net/sf/briar/api/crypto/CryptoComponent.java b/api/net/sf/briar/api/crypto/CryptoComponent.java index 8b1944fa4b5d6845edd7ecf16c6153c1366f2e29..6801a40ed71e75d2a4c98bf856bd0f23305b58d2 100644 --- a/api/net/sf/briar/api/crypto/CryptoComponent.java +++ b/api/net/sf/briar/api/crypto/CryptoComponent.java @@ -9,10 +9,10 @@ import javax.crypto.Mac; public interface CryptoComponent { - ErasableKey deriveSegmentKey(byte[] secret, boolean initiator); - ErasableKey deriveTagKey(byte[] secret, boolean initiator); + ErasableKey deriveFrameKey(byte[] secret, boolean initiator); + ErasableKey deriveMacKey(byte[] secret, boolean initiator); byte[] deriveNextSecret(byte[] secret, int index, long connection); @@ -27,11 +27,11 @@ public interface CryptoComponent { SecureRandom getSecureRandom(); - Cipher getSegmentCipher(); + Cipher getTagCipher(); + + Cipher getFrameCipher(); Signature getSignature(); - Cipher getTagCipher(); - Mac getMac(); } diff --git a/api/net/sf/briar/api/plugins/SegmentSink.java b/api/net/sf/briar/api/plugins/SegmentSink.java deleted file mode 100644 index 83eaa2f6ae62eca33535d184112ccbb8d6cdb8b5..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/SegmentSink.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.sf.briar.api.plugins; - -import java.io.IOException; - -import net.sf.briar.api.transport.Segment; - -public interface SegmentSink { - - /** Writes the given segment. */ - void writeSegment(Segment s) throws IOException; - - /** - * Returns the maximum length in bytes of the segments this sink accepts. - */ - int getMaxSegmentLength(); -} diff --git a/api/net/sf/briar/api/plugins/SegmentSource.java b/api/net/sf/briar/api/plugins/SegmentSource.java deleted file mode 100644 index 135d03f548a624962ff5ea3c2d674e4d4868d95a..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/SegmentSource.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.sf.briar.api.plugins; - -import java.io.IOException; - -import net.sf.briar.api.transport.Segment; - -public interface SegmentSource { - - /** - * Attempts to read a segment into the given buffer and returns true if a - * segment was read, or false if no more segments can be read. - */ - boolean readSegment(Segment s) throws IOException; - - /** - * Returns the maximum length in bytes of the segments this source returns. - */ - int getMaxSegmentLength(); -} diff --git a/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPlugin.java b/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPlugin.java deleted file mode 100644 index 1dd7bf0d8a9f2079b302d440c45c9eb26c1774bd..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPlugin.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.sf.briar.api.plugins.duplex; - -import net.sf.briar.api.ContactId; -import net.sf.briar.api.plugins.Plugin; - -/** - * An interface for transport plugins that support duplex segmented - * communication. - */ -public interface DuplexSegmentedPlugin extends Plugin { - - /** - * Attempts to create and return a connection to the given contact using - * the current transport and configuration properties. Returns null if a - * connection could not be created. - */ - DuplexSegmentedTransportConnection createConnection(ContactId c); - - /** - * Starts the invitation process from the inviter's side. Returns null if - * no connection can be established within the given timeout. - */ - DuplexSegmentedTransportConnection sendInvitation(int code, long timeout); - - /** - * Starts the invitation process from the invitee's side. Returns null if - * no connection can be established within the given timeout. - */ - DuplexSegmentedTransportConnection acceptInvitation(int code, long timeout); -} diff --git a/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPluginCallback.java b/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPluginCallback.java deleted file mode 100644 index 9fcbb1c56b70d93478c859ff177f05766cd52f55..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPluginCallback.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.sf.briar.api.plugins.duplex; - -import net.sf.briar.api.ContactId; -import net.sf.briar.api.plugins.PluginCallback; - -/** - * An interface for handling connections created by a duplex segmented - * transport plugin. - */ -public interface DuplexSegmentedPluginCallback extends PluginCallback { - - void incomingConnectionCreated(DuplexSegmentedTransportConnection d); - - void outgoingConnectionCreated(ContactId c, - DuplexSegmentedTransportConnection d); - -} diff --git a/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPluginFactory.java b/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPluginFactory.java deleted file mode 100644 index d32e372fafdb46b119710ecadea9150d5e6dbe63..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedPluginFactory.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.sf.briar.api.plugins.duplex; - -import java.util.concurrent.Executor; - -public interface DuplexSegmentedPluginFactory { - - DuplexSegmentedPlugin createPlugin(Executor pluginExecutor, - DuplexSegmentedPluginCallback callback); - -} diff --git a/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedTransportConnection.java b/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedTransportConnection.java deleted file mode 100644 index c9b16844edc621f914643b04c9fde63a8472f078..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/duplex/DuplexSegmentedTransportConnection.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.sf.briar.api.plugins.duplex; - -import net.sf.briar.api.plugins.SegmentSink; -import net.sf.briar.api.plugins.SegmentSource; - -/** - * An interface for reading and writing data over a duplex segmented transport. - * The connection is not responsible for encrypting/decrypting or authenticating - * the data. - */ -public interface DuplexSegmentedTransportConnection extends SegmentSource, -SegmentSink { - - /** Returns the maximum length of a segment in bytes. */ - int getMaximumSegmentLength(); - - /** - * Returns true if the output stream should be flushed after each packet. - */ - boolean shouldFlush(); - - /** - * Closes the connection and disposes of any associated resources. The - * first argument indicates whether the connection is being closed because - * of an exception and the second argument indicates whether the connection - * was recognised, which may affect how resources are disposed of. - */ - void dispose(boolean exception, boolean recognised); -} diff --git a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPlugin.java b/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPlugin.java deleted file mode 100644 index 54deb5de058217e199bab33347818cf93acda46d..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPlugin.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.sf.briar.api.plugins.simplex; - -import net.sf.briar.api.ContactId; -import net.sf.briar.api.plugins.Plugin; - -/** - * An interface for transport plugins that support simplex segmented - * communication. - */ -public interface SimplexSegmentedPlugin extends Plugin { - - /** - * Attempts to create and return a reader for the given contact using the - * current transport and configuration properties. Returns null if a reader - * could not be created. - */ - SimplexSegmentedTransportReader createReader(ContactId c); - - /** - * Attempts to create and return a writer for the given contact using the - * current transport and configuration properties. Returns null if a writer - * could not be created. - */ - SimplexSegmentedTransportWriter createWriter(ContactId c); - - /** - * Starts the invitation process from the inviter's side. Returns null if - * no connection can be established within the given timeout. - */ - SimplexSegmentedTransportWriter sendInvitation(int code, long timeout); - - /** - * Starts the invitation process from the invitee's side. Returns null if - * no connection can be established within the given timeout. - */ - SimplexSegmentedTransportReader acceptInvitation(int code, long timeout); - - /** - * Continues the invitation process from the invitee's side. Returns null - * if no connection can be established within the given timeout. - */ - SimplexSegmentedTransportWriter sendInvitationResponse(int code, - long timeout); - - /** - * Continues the invitation process from the inviter's side. Returns null - * if no connection can be established within the given timeout. - */ - SimplexSegmentedTransportReader acceptInvitationResponse(int code, - long timeout); -} diff --git a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPluginCallback.java b/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPluginCallback.java deleted file mode 100644 index 654b89907bb6c1d29d214990c62fb1e8b2d0be20..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPluginCallback.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.sf.briar.api.plugins.simplex; - -import net.sf.briar.api.ContactId; -import net.sf.briar.api.plugins.PluginCallback; - -/** - * An interface for handling readers and writers created by a simplex - * segmented transport plugin. - */ -public interface SimplexSegmentedPluginCallback extends PluginCallback { - - void readerCreated(SimplexSegmentedTransportReader r); - - void writerCreated(ContactId c, SimplexSegmentedTransportWriter w); - -} diff --git a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPluginFactory.java b/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPluginFactory.java deleted file mode 100644 index 1657c5f280bce1f7ba2f2ddafbded7b8288069e7..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedPluginFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.sf.briar.api.plugins.simplex; - -import java.util.concurrent.Executor; - -public interface SimplexSegmentedPluginFactory { - - SimplexSegmentedPlugin createPlugin(Executor pluginExecutor, - SimplexSegmentedPluginCallback callback); -} diff --git a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedTransportReader.java b/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedTransportReader.java deleted file mode 100644 index c34946d5cf14a8a512f70d44973c671e2100745b..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedTransportReader.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.sf.briar.api.plugins.simplex; - -import net.sf.briar.api.plugins.SegmentSource; - -/** - * An interface for reading data from a simplex segmented transport. The reader - * is not responsible for decrypting or authenticating the data before - * returning it. - */ -public interface SimplexSegmentedTransportReader extends SegmentSource { - - /** - * Closes the reader and disposes of any associated resources. The first - * argument indicates whether the reader is being closed because of an - * exception and the second argument indicates whether the connection was - * recognised, which may affect how resources are disposed of. - */ - void dispose(boolean exception, boolean recognised); -} diff --git a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedTransportWriter.java b/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedTransportWriter.java deleted file mode 100644 index 364faf6ab34708a0713a27f4fef8cdfccd8de41d..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/plugins/simplex/SimplexSegmentedTransportWriter.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.sf.briar.api.plugins.simplex; - -import net.sf.briar.api.plugins.SegmentSink; - -/** - * An interface for writing data to a simplex segmented transport. The writer is - * not responsible for authenticating or encrypting the data before writing it. - */ -public interface SimplexSegmentedTransportWriter extends SegmentSink { - - /** Returns the capacity of the transport in bytes. */ - long getCapacity(); - - /** Returns the maximum length of a segment in bytes. */ - int getMaximumSegmentLength(); - - /** - * Returns true if the output stream should be flushed after each packet. - */ - boolean shouldFlush(); - - /** - * Closes the writer and disposes of any associated resources. The - * argument indicates whether the writer is being closed because of an - * exception, which may affect how resources are disposed of. - */ - void dispose(boolean exception); -} diff --git a/api/net/sf/briar/api/protocol/duplex/DuplexConnectionFactory.java b/api/net/sf/briar/api/protocol/duplex/DuplexConnectionFactory.java index 94b22389bc3e29bb916bd9f48fd1759e528baf97..0d8e1dce2d5ef2f7371a863e7bba2f7a07cf3b38 100644 --- a/api/net/sf/briar/api/protocol/duplex/DuplexConnectionFactory.java +++ b/api/net/sf/briar/api/protocol/duplex/DuplexConnectionFactory.java @@ -9,7 +9,7 @@ import net.sf.briar.api.transport.ConnectionContext; public interface DuplexConnectionFactory { void createIncomingConnection(ConnectionContext ctx, TransportId t, - DuplexTransportConnection d, byte[] tag); + DuplexTransportConnection d); void createOutgoingConnection(ContactId c, TransportId t, TransportIndex i, DuplexTransportConnection d); diff --git a/api/net/sf/briar/api/protocol/simplex/SimplexConnectionFactory.java b/api/net/sf/briar/api/protocol/simplex/SimplexConnectionFactory.java index 7c18457c0b1a0f10c32b4f4336b101292c5cc29b..63c33a290b7bbb6560a08266155a3313732350a8 100644 --- a/api/net/sf/briar/api/protocol/simplex/SimplexConnectionFactory.java +++ b/api/net/sf/briar/api/protocol/simplex/SimplexConnectionFactory.java @@ -10,7 +10,7 @@ import net.sf.briar.api.transport.ConnectionContext; public interface SimplexConnectionFactory { void createIncomingConnection(ConnectionContext ctx, TransportId t, - SimplexTransportReader r, byte[] tag); + SimplexTransportReader r); void createOutgoingConnection(ContactId c, TransportId t, TransportIndex i, SimplexTransportWriter w); diff --git a/api/net/sf/briar/api/transport/ConnectionReaderFactory.java b/api/net/sf/briar/api/transport/ConnectionReaderFactory.java index 4620c5296e0981099f687b6ae9a846ae995ed9ad..c688ca9852b5be11c35830c60195e7473b98af1a 100644 --- a/api/net/sf/briar/api/transport/ConnectionReaderFactory.java +++ b/api/net/sf/briar/api/transport/ConnectionReaderFactory.java @@ -2,35 +2,12 @@ package net.sf.briar.api.transport; import java.io.InputStream; -import net.sf.briar.api.plugins.SegmentSource; - public interface ConnectionReaderFactory { /** - * Creates a connection reader for a simplex connection or the initiator's - * side of a duplex connection. The secret is erased before this method - * returns. + * Creates a connection reader for a simplex connection or one side of a + * duplex connection. The secret is erased before this method returns. */ ConnectionReader createConnectionReader(InputStream in, byte[] secret, - byte[] bufferedTag); - - /** - * Creates a connection reader for a simplex connection or the initiator's - * side of a duplex connection. The secret is erased before this method - * returns. - */ - ConnectionReader createConnectionReader(SegmentSource in, byte[] secret, - Segment bufferedSegment); - - /** - * Creates a connection reader for the responder's side of a duplex - * connection. The secret is erased before this method returns. - */ - ConnectionReader createConnectionReader(InputStream in, byte[] secret); - - /** - * Creates a connection reader for the responder's side of a duplex - * connection. The secret is erased before this method returns. - */ - ConnectionReader createConnectionReader(SegmentSource in, byte[] secret); + boolean initiator); } diff --git a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java index be3d55747f93e0a754f686ab8872101956e6eaff..b5996f3f5f9a6d9e799349537579410a3b5488f3 100644 --- a/api/net/sf/briar/api/transport/ConnectionWriterFactory.java +++ b/api/net/sf/briar/api/transport/ConnectionWriterFactory.java @@ -2,8 +2,6 @@ package net.sf.briar.api.transport; import java.io.OutputStream; -import net.sf.briar.api.plugins.SegmentSink; - public interface ConnectionWriterFactory { /** @@ -12,11 +10,4 @@ public interface ConnectionWriterFactory { */ ConnectionWriter createConnectionWriter(OutputStream out, long capacity, byte[] secret, boolean initiator); - - /** - * Creates a connection writer for a simplex connection or one side of a - * duplex connection. The secret is erased before this method returns. - */ - ConnectionWriter createConnectionWriter(SegmentSink out, long capacity, - byte[] secret, boolean initiator); } diff --git a/api/net/sf/briar/api/transport/Segment.java b/api/net/sf/briar/api/transport/Segment.java deleted file mode 100644 index da91745fa4140d803c2372774a9a835360edd503..0000000000000000000000000000000000000000 --- a/api/net/sf/briar/api/transport/Segment.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.sf.briar.api.transport; - -public interface Segment { - - byte[] getBuffer(); - - int getLength(); - - long getSegmentNumber(); - - void setLength(int length); - - void setSegmentNumber(long segmentNumber); -} diff --git a/api/net/sf/briar/api/transport/TransportConstants.java b/api/net/sf/briar/api/transport/TransportConstants.java index 0e73fb1fddd349602ba08dbc58ba998c89f36848..e0ee78b2d56eeeb487b7cd769c4c7cd16c1438b0 100644 --- a/api/net/sf/briar/api/transport/TransportConstants.java +++ b/api/net/sf/briar/api/transport/TransportConstants.java @@ -2,21 +2,15 @@ package net.sf.briar.api.transport; public interface TransportConstants { - /** The maximum length of a segment in bytes, including the tag. */ - static final int MAX_SEGMENT_LENGTH = 65536; // 2^16, 64 KiB - - /** The length of the segment tag in bytes. */ + /** The length of the connection tag in bytes. */ static final int TAG_LENGTH = 16; /** The maximum length of a frame in bytes, including the header and MAC. */ - static final int MAX_FRAME_LENGTH = MAX_SEGMENT_LENGTH - TAG_LENGTH; + static final int MAX_FRAME_LENGTH = 65536; // 2^16, 64 KiB /** The length of the frame header in bytes. */ static final int FRAME_HEADER_LENGTH = 8; - /** The length of the ack header in bytes. */ - static final int ACK_HEADER_LENGTH = 5; - /** The length of the MAC in bytes. */ static final int MAC_LENGTH = 32; @@ -29,7 +23,4 @@ public interface TransportConstants { /** The size of the connection reordering window. */ static final int CONNECTION_WINDOW_SIZE = 32; - - /** The size of the frame reordering window. */ - static final int FRAME_WINDOW_SIZE = 32; } diff --git a/components/net/sf/briar/crypto/CryptoComponentImpl.java b/components/net/sf/briar/crypto/CryptoComponentImpl.java index f8f046b1d1fc997c5636e2f0c630ac0c2b9f10e5..d60c53b1b63d05d04997a969235a3e923a4ca656 100644 --- a/components/net/sf/briar/crypto/CryptoComponentImpl.java +++ b/components/net/sf/briar/crypto/CryptoComponentImpl.java @@ -33,12 +33,12 @@ class CryptoComponentImpl implements CryptoComponent { private static final String DIGEST_ALGO = "SHA-256"; private static final String SIGNATURE_ALGO = "ECDSA"; private static final String TAG_CIPHER_ALGO = "AES/ECB/NoPadding"; - private static final String SEGMENT_CIPHER_ALGO = "AES/CTR/NoPadding"; + private static final String FRAME_CIPHER_ALGO = "AES/CTR/NoPadding"; private static final String MAC_ALGO = "HMacSHA256"; // Labels for key derivation, null-terminated private static final byte[] TAG = { 'T', 'A', 'G', 0 }; - private static final byte[] SEGMENT = { 'S', 'E', 'G', 0 }; + private static final byte[] FRAME = { 'F', 'R', 'A', 'M', 'E', 0 }; private static final byte[] MAC = { 'M', 'A', 'C', 0 }; private static final byte[] NEXT = { 'N', 'E', 'X', 'T', 0 }; // Context strings for key derivation @@ -71,9 +71,9 @@ class CryptoComponentImpl implements CryptoComponent { else return deriveKey(secret, TAG, RESPONDER); } - public ErasableKey deriveSegmentKey(byte[] secret, boolean initiator) { - if(initiator) return deriveKey(secret, SEGMENT, INITIATOR); - else return deriveKey(secret, SEGMENT, RESPONDER); + public ErasableKey deriveFrameKey(byte[] secret, boolean initiator) { + if(initiator) return deriveKey(secret, FRAME, INITIATOR); + else return deriveKey(secret, FRAME, RESPONDER); } public ErasableKey deriveMacKey(byte[] secret, boolean initiator) { @@ -168,9 +168,9 @@ class CryptoComponentImpl implements CryptoComponent { } } - public Cipher getSegmentCipher() { + public Cipher getFrameCipher() { try { - return Cipher.getInstance(SEGMENT_CIPHER_ALGO, PROVIDER); + return Cipher.getInstance(FRAME_CIPHER_ALGO, PROVIDER); } catch(GeneralSecurityException e) { throw new RuntimeException(e); } diff --git a/components/net/sf/briar/protocol/duplex/StreamConnectionFactoryImpl.java b/components/net/sf/briar/protocol/duplex/DuplexConnectionFactoryImpl.java similarity index 93% rename from components/net/sf/briar/protocol/duplex/StreamConnectionFactoryImpl.java rename to components/net/sf/briar/protocol/duplex/DuplexConnectionFactoryImpl.java index 3a2953abbf5fcbd15e1887dbc4a018b0b88b3539..ed4f08f1fb52b2f332f5e5c8852c0a8e105a48bb 100644 --- a/components/net/sf/briar/protocol/duplex/StreamConnectionFactoryImpl.java +++ b/components/net/sf/briar/protocol/duplex/DuplexConnectionFactoryImpl.java @@ -19,7 +19,7 @@ import net.sf.briar.api.transport.ConnectionWriterFactory; import com.google.inject.Inject; -class StreamConnectionFactoryImpl implements DuplexConnectionFactory { +class DuplexConnectionFactoryImpl implements DuplexConnectionFactory { private final Executor dbExecutor, verificationExecutor; private final DatabaseComponent db; @@ -30,7 +30,7 @@ class StreamConnectionFactoryImpl implements DuplexConnectionFactory { private final ProtocolWriterFactory protoWriterFactory; @Inject - StreamConnectionFactoryImpl(@DatabaseExecutor Executor dbExecutor, + DuplexConnectionFactoryImpl(@DatabaseExecutor Executor dbExecutor, @VerificationExecutor Executor verificationExecutor, DatabaseComponent db, ConnectionRegistry connRegistry, ConnectionReaderFactory connReaderFactory, @@ -48,11 +48,11 @@ class StreamConnectionFactoryImpl implements DuplexConnectionFactory { } public void createIncomingConnection(ConnectionContext ctx, TransportId t, - DuplexTransportConnection d, byte[] tag) { + DuplexTransportConnection d) { final DuplexConnection conn = new IncomingDuplexConnection(dbExecutor, verificationExecutor, db, connRegistry, connReaderFactory, connWriterFactory, protoReaderFactory, protoWriterFactory, - ctx, t, d, tag); + ctx, t, d); Runnable write = new Runnable() { public void run() { conn.write(); diff --git a/components/net/sf/briar/protocol/duplex/DuplexProtocolModule.java b/components/net/sf/briar/protocol/duplex/DuplexProtocolModule.java index e04df3b249e029a0018e6e7022e268b52f290402..1ba18df14b28537b1e2282678a9a816640831917 100644 --- a/components/net/sf/briar/protocol/duplex/DuplexProtocolModule.java +++ b/components/net/sf/briar/protocol/duplex/DuplexProtocolModule.java @@ -10,6 +10,6 @@ public class DuplexProtocolModule extends AbstractModule { @Override protected void configure() { bind(DuplexConnectionFactory.class).to( - StreamConnectionFactoryImpl.class).in(Singleton.class); + DuplexConnectionFactoryImpl.class).in(Singleton.class); } } diff --git a/components/net/sf/briar/protocol/duplex/IncomingDuplexConnection.java b/components/net/sf/briar/protocol/duplex/IncomingDuplexConnection.java index 898cefd8aa08d67abb6ad46bb8b07eaec9ec81fa..3a888eaa7fa5f487830fe53111119449762c921a 100644 --- a/components/net/sf/briar/protocol/duplex/IncomingDuplexConnection.java +++ b/components/net/sf/briar/protocol/duplex/IncomingDuplexConnection.java @@ -20,7 +20,6 @@ import net.sf.briar.api.transport.ConnectionWriterFactory; class IncomingDuplexConnection extends DuplexConnection { private final ConnectionContext ctx; - private final byte[] tag; IncomingDuplexConnection(@DatabaseExecutor Executor dbExecutor, @VerificationExecutor Executor verificationExecutor, @@ -30,18 +29,17 @@ class IncomingDuplexConnection extends DuplexConnection { ProtocolReaderFactory protoReaderFactory, ProtocolWriterFactory protoWriterFactory, ConnectionContext ctx, TransportId transportId, - DuplexTransportConnection transport, byte[] tag) { + DuplexTransportConnection transport) { super(dbExecutor, verificationExecutor, db, connRegistry, connReaderFactory, connWriterFactory, protoReaderFactory, protoWriterFactory, ctx.getContactId(), transportId, transport); this.ctx = ctx; - this.tag = tag; } @Override protected ConnectionReader createConnectionReader() throws IOException { return connReaderFactory.createConnectionReader( - transport.getInputStream(), ctx.getSecret(), tag); + transport.getInputStream(), ctx.getSecret(), true); } @Override diff --git a/components/net/sf/briar/protocol/duplex/OutgoingDuplexConnection.java b/components/net/sf/briar/protocol/duplex/OutgoingDuplexConnection.java index ffc60361d98f1ea24f192d1147ff7632c8d9d105..b784b8115eda9f7c67273e5dd6f6ad51cd2d7c4c 100644 --- a/components/net/sf/briar/protocol/duplex/OutgoingDuplexConnection.java +++ b/components/net/sf/briar/protocol/duplex/OutgoingDuplexConnection.java @@ -49,7 +49,7 @@ class OutgoingDuplexConnection extends DuplexConnection { ctx = db.getConnectionContext(contactId, transportIndex); } return connReaderFactory.createConnectionReader( - transport.getInputStream(), ctx.getSecret()); + transport.getInputStream(), ctx.getSecret(), false); } @Override diff --git a/components/net/sf/briar/protocol/simplex/IncomingSimplexConnection.java b/components/net/sf/briar/protocol/simplex/IncomingSimplexConnection.java index 224071e59a35b350c6d80c2b15620b125d3ceecc..f05e8c5ec78836c426b79f367349721fb8ef43ef 100644 --- a/components/net/sf/briar/protocol/simplex/IncomingSimplexConnection.java +++ b/components/net/sf/briar/protocol/simplex/IncomingSimplexConnection.java @@ -40,7 +40,6 @@ class IncomingSimplexConnection { private final ConnectionContext ctx; private final TransportId transportId; private final SimplexTransportReader transport; - private final byte[] tag; private final ContactId contactId; IncomingSimplexConnection(@DatabaseExecutor Executor dbExecutor, @@ -48,8 +47,7 @@ class IncomingSimplexConnection { DatabaseComponent db, ConnectionRegistry connRegistry, ConnectionReaderFactory connFactory, ProtocolReaderFactory protoFactory, ConnectionContext ctx, - TransportId transportId, SimplexTransportReader transport, - byte[] tag) { + TransportId transportId, SimplexTransportReader transport) { this.dbExecutor = dbExecutor; this.verificationExecutor = verificationExecutor; this.db = db; @@ -59,7 +57,6 @@ class IncomingSimplexConnection { this.ctx = ctx; this.transportId = transportId; this.transport = transport; - this.tag = tag; contactId = ctx.getContactId(); } @@ -67,7 +64,7 @@ class IncomingSimplexConnection { connRegistry.registerConnection(contactId, transportId); try { ConnectionReader conn = connFactory.createConnectionReader( - transport.getInputStream(), ctx.getSecret(), tag); + transport.getInputStream(), ctx.getSecret(), true); InputStream in = conn.getInputStream(); ProtocolReader reader = protoFactory.createProtocolReader(in); // Read packets until EOF diff --git a/components/net/sf/briar/protocol/simplex/SimplexConnectionFactoryImpl.java b/components/net/sf/briar/protocol/simplex/SimplexConnectionFactoryImpl.java index 6dfa5892f0ca10aa0a0efc925fb7204497b44b2c..1c08ffe8942e1658f31c7f47065e90b4418fc7a7 100644 --- a/components/net/sf/briar/protocol/simplex/SimplexConnectionFactoryImpl.java +++ b/components/net/sf/briar/protocol/simplex/SimplexConnectionFactoryImpl.java @@ -49,10 +49,10 @@ class SimplexConnectionFactoryImpl implements SimplexConnectionFactory { } public void createIncomingConnection(ConnectionContext ctx, TransportId t, - SimplexTransportReader r, byte[] tag) { + SimplexTransportReader r) { final IncomingSimplexConnection conn = new IncomingSimplexConnection( dbExecutor, verificationExecutor, db, connRegistry, - connReaderFactory, protoReaderFactory, ctx, t, r, tag); + connReaderFactory, protoReaderFactory, ctx, t, r); Runnable read = new Runnable() { public void run() { conn.read(); diff --git a/components/net/sf/briar/transport/ConnectionDispatcherImpl.java b/components/net/sf/briar/transport/ConnectionDispatcherImpl.java index 42c3b6cba3dd4c768a6a5c6d9d690134367c3006..4adbba871fad240f83426b1623a317a21f69d5f1 100644 --- a/components/net/sf/briar/transport/ConnectionDispatcherImpl.java +++ b/components/net/sf/briar/transport/ConnectionDispatcherImpl.java @@ -93,7 +93,7 @@ class ConnectionDispatcherImpl implements ConnectionDispatcher { tag); if(ctx == null) transport.dispose(false, false); else batchConnFactory.createIncomingConnection(ctx, transportId, - transport, tag); + transport); } catch(DbException e) { if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString()); transport.dispose(true, false); @@ -122,7 +122,7 @@ class ConnectionDispatcherImpl implements ConnectionDispatcher { tag); if(ctx == null) transport.dispose(false, false); else streamConnFactory.createIncomingConnection(ctx, - transportId, transport, tag); + transportId, transport); } catch(DbException e) { if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString()); transport.dispose(true, false); diff --git a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java index 70b8982021d340df8042f211b2975ee401f4fff1..8163e047ffa6b31e371ba30ab63e7a6bb2d2e14a 100644 --- a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java @@ -7,10 +7,8 @@ import javax.crypto.Mac; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.plugins.SegmentSource; import net.sf.briar.api.transport.ConnectionReader; import net.sf.briar.api.transport.ConnectionReaderFactory; -import net.sf.briar.api.transport.Segment; import net.sf.briar.util.ByteUtils; import com.google.inject.Inject; @@ -25,76 +23,22 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory { } public ConnectionReader createConnectionReader(InputStream in, - byte[] secret, byte[] bufferedTag) { - return createConnectionReader(in, secret, bufferedTag, true); - } - - public ConnectionReader createConnectionReader(InputStream in, - byte[] secret) { - return createConnectionReader(in, secret, null, false); - } - - private ConnectionReader createConnectionReader(InputStream in, - byte[] secret, byte[] bufferedTag, boolean initiator) { - // Derive the keys and erase the secret - ErasableKey tagKey = crypto.deriveTagKey(secret, initiator); - ErasableKey segKey = crypto.deriveSegmentKey(secret, initiator); - ErasableKey macKey = crypto.deriveMacKey(secret, initiator); - ByteUtils.erase(secret); - // Create the decrypter - Cipher tagCipher = crypto.getTagCipher(); - Cipher segCipher = crypto.getSegmentCipher(); - IncomingEncryptionLayer encryption = new IncomingEncryptionLayerImpl(in, - tagCipher, segCipher, tagKey, segKey, false, false, - bufferedTag); - // No error correction - IncomingErrorCorrectionLayer correction = - new NullIncomingErrorCorrectionLayer(encryption); - // Create the authenticator - Mac mac = crypto.getMac(); - IncomingAuthenticationLayer authentication = - new IncomingAuthenticationLayerImpl(correction, mac, macKey, false); - // No reordering or retransmission - IncomingReliabilityLayer reliability = - new NullIncomingReliabilityLayer(authentication); - // Create the reader - don't tolerate errors - return new ConnectionReaderImpl(reliability, false, false); - } - - public ConnectionReader createConnectionReader(SegmentSource in, - byte[] secret, Segment bufferedSegment) { - return createConnectionReader(in, secret, bufferedSegment, true); - } - - public ConnectionReader createConnectionReader(SegmentSource in, - byte[] secret) { - return createConnectionReader(in, secret, null, false); - } - - private ConnectionReader createConnectionReader(SegmentSource in, - byte[] secret, Segment bufferedSegment, boolean initiator) { + byte[] secret, boolean initiator) { // Derive the keys and erase the secret ErasableKey tagKey = crypto.deriveTagKey(secret, initiator); - ErasableKey segKey = crypto.deriveSegmentKey(secret, initiator); + ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator); ErasableKey macKey = crypto.deriveMacKey(secret, initiator); ByteUtils.erase(secret); - // Create the decrypter + // Encryption Cipher tagCipher = crypto.getTagCipher(); - Cipher segCipher = crypto.getSegmentCipher(); - IncomingEncryptionLayer encryption = - new SegmentedIncomingEncryptionLayer(in, tagCipher, segCipher, - tagKey, segKey, false, false, bufferedSegment); - // No error correction - IncomingErrorCorrectionLayer correction = - new NullIncomingErrorCorrectionLayer(encryption); - // Create the authenticator + Cipher frameCipher = crypto.getFrameCipher(); + FrameReader encryption = new IncomingEncryptionLayerImpl(in, tagCipher, + frameCipher, tagKey, frameKey, !initiator); + // Authentication Mac mac = crypto.getMac(); - IncomingAuthenticationLayer authentication = - new IncomingAuthenticationLayerImpl(correction, mac, macKey, false); - // No reordering or retransmission - IncomingReliabilityLayer reliability = - new NullIncomingReliabilityLayer(authentication); - // Create the reader - don't tolerate errors - return new ConnectionReaderImpl(reliability, false, false); + FrameReader authentication = new IncomingAuthenticationLayerImpl( + encryption, mac, macKey); + // Create the reader + return new ConnectionReaderImpl(authentication); } } diff --git a/components/net/sf/briar/transport/ConnectionReaderImpl.java b/components/net/sf/briar/transport/ConnectionReaderImpl.java index 484a0736e84f8236b8b739e5411b797e2977e481..ad539dc63b94d9a0b41f1d61e26e2fd886b3f070 100644 --- a/components/net/sf/briar/transport/ConnectionReaderImpl.java +++ b/components/net/sf/briar/transport/ConnectionReaderImpl.java @@ -1,30 +1,23 @@ package net.sf.briar.transport; -import static net.sf.briar.api.transport.TransportConstants.ACK_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; import java.io.IOException; import java.io.InputStream; -import net.sf.briar.api.FormatException; import net.sf.briar.api.transport.ConnectionReader; class ConnectionReaderImpl extends InputStream implements ConnectionReader { - private final IncomingReliabilityLayer in; - private final boolean tolerateErrors; - private final int headerLength; + private final FrameReader in; + private final Frame frame; - private Frame frame; private int offset = 0, length = 0; - ConnectionReaderImpl(IncomingReliabilityLayer in, boolean tolerateErrors, - boolean ackHeader) { + ConnectionReaderImpl(FrameReader in) { this.in = in; - this.tolerateErrors = tolerateErrors; - if(ackHeader) headerLength = FRAME_HEADER_LENGTH + ACK_HEADER_LENGTH; - else headerLength = FRAME_HEADER_LENGTH; - frame = new Frame(in.getMaxFrameLength()); + frame = new Frame(); + offset = FRAME_HEADER_LENGTH; } public InputStream getInputStream() { @@ -60,19 +53,14 @@ class ConnectionReaderImpl extends InputStream implements ConnectionReader { private boolean readFrame() throws IOException { assert length == 0; while(true) { - try { - frame = in.readFrame(frame); - if(frame == null) { - length = -1; - return false; - } - offset = headerLength; - length = HeaderEncoder.getPayloadLength(frame.getBuffer()); - return true; - } catch(InvalidDataException e) { - if(tolerateErrors) continue; - throw new FormatException(); + frame.reset(); + if(!in.readFrame(frame)) { + length = -1; + return false; } + offset = FRAME_HEADER_LENGTH; + length = HeaderEncoder.getPayloadLength(frame.getBuffer()); + return true; } } } diff --git a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java index 68cfe03cd6ad7b998a0a999c884dd95d35f0c243..5babc2278cd3c3f1d33e9fe9e53b2b4cb97f504c 100644 --- a/components/net/sf/briar/transport/ConnectionRecogniserImpl.java +++ b/components/net/sf/briar/transport/ConnectionRecogniserImpl.java @@ -103,7 +103,7 @@ DatabaseListener { private Bytes calculateTag(Context ctx, byte[] secret) { ErasableKey tagKey = crypto.deriveTagKey(secret, true); byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); + TagEncoder.encodeTag(tag, tagCipher, tagKey); tagKey.erase(); return new Bytes(tag); } diff --git a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java index 843150e8b6c4dcb21c1df30bb3dc445249881743..cffa5521861e6455282129057a26ac5688ec5671 100644 --- a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java @@ -7,7 +7,6 @@ import javax.crypto.Mac; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.plugins.SegmentSink; import net.sf.briar.api.transport.ConnectionWriter; import net.sf.briar.api.transport.ConnectionWriterFactory; import net.sf.briar.util.ByteUtils; @@ -27,52 +26,19 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory { long capacity, byte[] secret, boolean initiator) { // Derive the keys and erase the secret ErasableKey tagKey = crypto.deriveTagKey(secret, initiator); - ErasableKey segKey = crypto.deriveSegmentKey(secret, initiator); + ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator); ErasableKey macKey = crypto.deriveMacKey(secret, initiator); ByteUtils.erase(secret); - // Create the encrypter + // Encryption Cipher tagCipher = crypto.getTagCipher(); - Cipher segCipher = crypto.getSegmentCipher(); - OutgoingEncryptionLayer encryption = new OutgoingEncryptionLayerImpl( - out, capacity, tagCipher, segCipher, tagKey, segKey, false); - // No error correction - OutgoingErrorCorrectionLayer correction = - new NullOutgoingErrorCorrectionLayer(encryption); + Cipher frameCipher = crypto.getFrameCipher(); + FrameWriter encryption = new OutgoingEncryptionLayerImpl( + out, capacity, tagCipher, frameCipher, tagKey, frameKey); // Authentication Mac mac = crypto.getMac(); - OutgoingAuthenticationLayer authentication = - new OutgoingAuthenticationLayerImpl(correction, mac, macKey); - // No retransmission - OutgoingReliabilityLayer reliability = - new NullOutgoingReliabilityLayer(authentication); + FrameWriter authentication = + new OutgoingAuthenticationLayerImpl(encryption, mac, macKey); // Create the writer - return new ConnectionWriterImpl(reliability, false); - } - - public ConnectionWriter createConnectionWriter(SegmentSink out, - long capacity, byte[] secret, boolean initiator) { - // Derive the keys and erase the secret - ErasableKey tagKey = crypto.deriveTagKey(secret, initiator); - ErasableKey segKey = crypto.deriveSegmentKey(secret, initiator); - ErasableKey macKey = crypto.deriveMacKey(secret, initiator); - ByteUtils.erase(secret); - // Create the encrypter - Cipher tagCipher = crypto.getTagCipher(); - Cipher segCipher = crypto.getSegmentCipher(); - OutgoingEncryptionLayer encryption = - new SegmentedOutgoingEncryptionLayer(out, capacity, tagCipher, - segCipher, tagKey, segKey, false, false); - // No error correction - OutgoingErrorCorrectionLayer correction = - new NullOutgoingErrorCorrectionLayer(encryption); - // Authentication - Mac mac = crypto.getMac(); - OutgoingAuthenticationLayer authentication = - new OutgoingAuthenticationLayerImpl(correction, mac, macKey); - // No retransmission - OutgoingReliabilityLayer reliability = - new NullOutgoingReliabilityLayer(authentication); - // Create the writer - return new ConnectionWriterImpl(reliability, false); + return new ConnectionWriterImpl(authentication); } } diff --git a/components/net/sf/briar/transport/ConnectionWriterImpl.java b/components/net/sf/briar/transport/ConnectionWriterImpl.java index f5947152657e3a8c5d7381a67e095d65a8cddf15..bc95444f19bfd06e3a8067ef7a1cffac95ebbf82 100644 --- a/components/net/sf/briar/transport/ConnectionWriterImpl.java +++ b/components/net/sf/briar/transport/ConnectionWriterImpl.java @@ -1,8 +1,8 @@ package net.sf.briar.transport; -import static net.sf.briar.api.transport.TransportConstants.ACK_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; +import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import java.io.IOException; @@ -18,20 +18,16 @@ import net.sf.briar.api.transport.ConnectionWriter; */ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter { - private final OutgoingReliabilityLayer out; - private final int headerLength, maxFrameLength; + private final FrameWriter out; private final Frame frame; private int offset; private long frameNumber; - ConnectionWriterImpl(OutgoingReliabilityLayer out, boolean ackHeader) { + ConnectionWriterImpl(FrameWriter out) { this.out = out; - if(ackHeader) headerLength = FRAME_HEADER_LENGTH + ACK_HEADER_LENGTH; - else headerLength = FRAME_HEADER_LENGTH; - maxFrameLength = out.getMaxFrameLength(); - frame = new Frame(maxFrameLength); - offset = headerLength; + frame = new Frame(); + offset = FRAME_HEADER_LENGTH; frameNumber = 0L; } @@ -42,23 +38,23 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter { public long getRemainingCapacity() { long capacity = out.getRemainingCapacity(); // If there's any data buffered, subtract it and its overhead - if(offset > headerLength) capacity -= offset + MAC_LENGTH; + if(offset > FRAME_HEADER_LENGTH) capacity -= offset + MAC_LENGTH; // Subtract the overhead from the remaining capacity - long frames = (long) Math.ceil((double) capacity / maxFrameLength); - int overheadPerFrame = headerLength + MAC_LENGTH; + long frames = (long) Math.ceil((double) capacity / MAX_FRAME_LENGTH); + int overheadPerFrame = FRAME_HEADER_LENGTH + MAC_LENGTH; return Math.max(0L, capacity - frames * overheadPerFrame); } @Override public void flush() throws IOException { - if(offset > headerLength) writeFrame(); + if(offset > FRAME_HEADER_LENGTH) writeFrame(); out.flush(); } @Override public void write(int b) throws IOException { frame.getBuffer()[offset++] = (byte) b; - if(offset + MAC_LENGTH == maxFrameLength) writeFrame(); + if(offset + MAC_LENGTH == MAX_FRAME_LENGTH) writeFrame(); } @Override @@ -69,14 +65,14 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter { @Override public void write(byte[] b, int off, int len) throws IOException { byte[] buf = frame.getBuffer(); - int available = maxFrameLength - offset - MAC_LENGTH; + int available = MAX_FRAME_LENGTH - offset - MAC_LENGTH; while(available <= len) { System.arraycopy(b, off, buf, offset, available); offset += available; writeFrame(); off += available; len -= available; - available = maxFrameLength - offset - MAC_LENGTH; + available = MAX_FRAME_LENGTH - offset - MAC_LENGTH; } System.arraycopy(b, off, buf, offset, len); offset += len; @@ -84,12 +80,13 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter { private void writeFrame() throws IOException { if(frameNumber > MAX_32_BIT_UNSIGNED) throw new IllegalStateException(); - int payload = offset - headerLength; + 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 = headerLength; + frame.reset(); + offset = FRAME_HEADER_LENGTH; frameNumber++; } } diff --git a/components/net/sf/briar/transport/ErasureDecoder.java b/components/net/sf/briar/transport/ErasureDecoder.java deleted file mode 100644 index 679c26ab20f19ffa35a17bafdd510488c8485b11..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/ErasureDecoder.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.sf.briar.transport; - -import net.sf.briar.api.FormatException; -import net.sf.briar.api.transport.Segment; - -interface ErasureDecoder { - - /** - * Decodes the given set of segments into the given frame, or returns false - * if the segments cannot be decoded. The segment set may contain nulls. - */ - public boolean decodeFrame(Frame f, Segment[] set) throws FormatException; -} diff --git a/components/net/sf/briar/transport/ErasureEncoder.java b/components/net/sf/briar/transport/ErasureEncoder.java deleted file mode 100644 index b09fd687cb79916f803bd47be4357d6444866025..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/ErasureEncoder.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.sf.briar.transport; - -import net.sf.briar.api.transport.Segment; - -interface ErasureEncoder { - - /** Encodes the given frame as a set of segments. */ - Segment[] encodeFrame(Frame f); -} diff --git a/components/net/sf/briar/transport/Frame.java b/components/net/sf/briar/transport/Frame.java index 3b1910e19dfa2394d8b50b154a523f314b1fc49d..93ef395c36e7ce6151bb76c2e8f229e51f9d9ff7 100644 --- a/components/net/sf/briar/transport/Frame.java +++ b/components/net/sf/briar/transport/Frame.java @@ -3,7 +3,6 @@ package net.sf.briar.transport; import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; class Frame { @@ -12,25 +11,13 @@ class Frame { private int length = -1; Frame() { - this(MAX_FRAME_LENGTH); - } - - Frame(int length) { - if(length < FRAME_HEADER_LENGTH + MAC_LENGTH) - throw new IllegalArgumentException(); - if(length > MAX_SEGMENT_LENGTH) throw new IllegalArgumentException(); - buf = new byte[length]; + buf = new byte[MAX_FRAME_LENGTH]; } public byte[] getBuffer() { return buf; } - public long getFrameNumber() { - if(length == -1) throw new IllegalStateException(); - return HeaderEncoder.getFrameNumber(buf); - } - public int getLength() { if(length == -1) throw new IllegalStateException(); return length; @@ -41,4 +28,8 @@ class Frame { throw new IllegalArgumentException(); this.length = length; } + + public void reset() { + length = -1; + } } diff --git a/components/net/sf/briar/transport/FrameReader.java b/components/net/sf/briar/transport/FrameReader.java new file mode 100644 index 0000000000000000000000000000000000000000..ad4a8b625180c9e0c8ef0d7e1301f2d5e694eab5 --- /dev/null +++ b/components/net/sf/briar/transport/FrameReader.java @@ -0,0 +1,12 @@ +package net.sf.briar.transport; + +import java.io.IOException; + +interface FrameReader { + + /** + * Reads a frame into the given buffer. Returns false if no more frames can + * be read from the connection. + */ + boolean readFrame(Frame f) throws IOException; +} diff --git a/components/net/sf/briar/transport/FrameWindow.java b/components/net/sf/briar/transport/FrameWindow.java deleted file mode 100644 index 85e162b1f1cc90c909dfe91ead44e7b933606953..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/FrameWindow.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.sf.briar.transport; - -interface FrameWindow { - - /** Returns true if the given number is too high to fit in the window. */ - boolean isTooHigh(long frameNumber); - - /** Returns true if the given number is in the window. */ - boolean contains(long frameNumber); - - /** - * Removes the given number from the window and advances the window. - * Returns false if the given number is not in the window. - */ - boolean remove(long frameNumber); -} diff --git a/components/net/sf/briar/transport/FrameWindowImpl.java b/components/net/sf/briar/transport/FrameWindowImpl.java deleted file mode 100644 index c3ff67a75a789c42d15fa8528f0f682d7c391c5a..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/FrameWindowImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.FRAME_WINDOW_SIZE; -import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; - -import java.util.Collection; -import java.util.HashSet; - -/** A frame window that allows a limited amount of reordering. */ -class FrameWindowImpl implements FrameWindow { - - private final Collection<Long> window; - - private long base; - - FrameWindowImpl() { - window = new HashSet<Long>(); - fill(0, FRAME_WINDOW_SIZE); - base = 0; - } - - public boolean isTooHigh(long frameNumber) { - if(frameNumber < 0 || frameNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - return frameNumber >= base + FRAME_WINDOW_SIZE; - } - - public boolean contains(long frameNumber) { - if(frameNumber < 0 || frameNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - return window.contains(frameNumber); - } - - public boolean remove(long frameNumber) { - if(frameNumber < 0 || frameNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - if(!window.remove(frameNumber)) return false; - if(frameNumber == base) { - // Find the new base - if(window.isEmpty()) { - base += FRAME_WINDOW_SIZE; - fill(base, base + FRAME_WINDOW_SIZE); - } else { - for(long l = base; l < base + FRAME_WINDOW_SIZE; l++) { - if(window.contains(l)) { - fill(base + FRAME_WINDOW_SIZE, l + FRAME_WINDOW_SIZE); - base = l; - break; - } - } - } - } - return true; - } - - private void fill(long from, long to) { - for(long l = from; l < to; l++) { - if(l <= MAX_32_BIT_UNSIGNED) window.add(l); - else return; - } - } -} diff --git a/components/net/sf/briar/transport/OutgoingReliabilityLayer.java b/components/net/sf/briar/transport/FrameWriter.java similarity index 67% rename from components/net/sf/briar/transport/OutgoingReliabilityLayer.java rename to components/net/sf/briar/transport/FrameWriter.java index ef6797d9a893fdfb6576bc53491130928593eb4f..d8f24517f431a5be34456cae2d39381dcf9e1100 100644 --- a/components/net/sf/briar/transport/OutgoingReliabilityLayer.java +++ b/components/net/sf/briar/transport/FrameWriter.java @@ -2,7 +2,7 @@ package net.sf.briar.transport; import java.io.IOException; -interface OutgoingReliabilityLayer { +interface FrameWriter { /** Writes the given frame. */ void writeFrame(Frame f) throws IOException; @@ -12,7 +12,4 @@ interface OutgoingReliabilityLayer { /** Returns the maximum number of bytes that can be written. */ long getRemainingCapacity(); - - /** Returns the maximum length in bytes of the frames this layer accepts. */ - int getMaxFrameLength(); } diff --git a/components/net/sf/briar/transport/IncomingAuthenticationLayer.java b/components/net/sf/briar/transport/IncomingAuthenticationLayer.java deleted file mode 100644 index 33a6f20aa3e9590bc47c6390cb6d202aed00683b..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/IncomingAuthenticationLayer.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -interface IncomingAuthenticationLayer { - - /** - * Reads a frame into the given buffer. The frame number must be contained - * in the given window. Returns false if no more frames can be read from - * the connection. - * @throws IOException if an unrecoverable error occurs and the connection - * must be closed. - * @throws InvalidDataException if a recoverable error occurs. The caller - * may choose whether to retry the read or close the connection. - */ - boolean readFrame(Frame f, FrameWindow window) throws IOException, - InvalidDataException; - - /** Returns the maximum length in bytes of the frames this layer returns. */ - int getMaxFrameLength(); -} diff --git a/components/net/sf/briar/transport/IncomingAuthenticationLayerImpl.java b/components/net/sf/briar/transport/IncomingAuthenticationLayerImpl.java index 9e4ed9b8919ee228c27fb01af07baf118ba1cbec..81cacbae19a5d29811c0979b6a695e69910ec1cf 100644 --- a/components/net/sf/briar/transport/IncomingAuthenticationLayerImpl.java +++ b/components/net/sf/briar/transport/IncomingAuthenticationLayerImpl.java @@ -1,24 +1,24 @@ package net.sf.briar.transport; -import static net.sf.briar.api.transport.TransportConstants.ACK_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; +import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; import java.io.IOException; import java.security.InvalidKeyException; import javax.crypto.Mac; +import net.sf.briar.api.FormatException; import net.sf.briar.api.crypto.ErasableKey; -class IncomingAuthenticationLayerImpl implements IncomingAuthenticationLayer { +class IncomingAuthenticationLayerImpl implements FrameReader { - private final IncomingErrorCorrectionLayer in; + private final FrameReader in; private final Mac mac; - private final int headerLength, maxFrameLength; - IncomingAuthenticationLayerImpl(IncomingErrorCorrectionLayer in, Mac mac, - ErasableKey macKey, boolean ackHeader) { + IncomingAuthenticationLayerImpl(FrameReader in, Mac mac, + ErasableKey macKey) { this.in = in; this.mac = mac; try { @@ -29,43 +29,34 @@ class IncomingAuthenticationLayerImpl implements IncomingAuthenticationLayer { macKey.erase(); if(mac.getMacLength() != MAC_LENGTH) throw new IllegalArgumentException(); - if(ackHeader) headerLength = FRAME_HEADER_LENGTH + ACK_HEADER_LENGTH; - else headerLength = FRAME_HEADER_LENGTH; - maxFrameLength = in.getMaxFrameLength(); } - public boolean readFrame(Frame f, FrameWindow window) throws IOException, - InvalidDataException { + public boolean readFrame(Frame f) throws IOException { // Read a frame - if(!in.readFrame(f, window)) return false; + if(!in.readFrame(f)) return false; // Check that the length is legal int length = f.getLength(); - if(length < headerLength + MAC_LENGTH) - throw new InvalidDataException(); - if(length > maxFrameLength) throw new InvalidDataException(); + if(length < FRAME_HEADER_LENGTH + MAC_LENGTH) + throw new FormatException(); + if(length > MAX_FRAME_LENGTH) throw new FormatException(); // Check that the payload and padding lengths are correct byte[] buf = f.getBuffer(); int payload = HeaderEncoder.getPayloadLength(buf); int padding = HeaderEncoder.getPaddingLength(buf); - if(length != headerLength + payload + padding + MAC_LENGTH) - throw new InvalidDataException(); + if(length != FRAME_HEADER_LENGTH + payload + padding + MAC_LENGTH) + throw new FormatException(); // Check that the padding is all zeroes - int paddingStart = headerLength + payload; + int paddingStart = FRAME_HEADER_LENGTH + payload; for(int i = paddingStart; i < paddingStart + padding; i++) { - if(buf[i] != 0) throw new InvalidDataException(); + if(buf[i] != 0) throw new FormatException(); } // Verify the MAC - int macStart = headerLength + payload + padding; + int macStart = FRAME_HEADER_LENGTH + payload + padding; mac.update(buf, 0, macStart); byte[] expectedMac = mac.doFinal(); for(int i = 0; i < expectedMac.length; i++) { - if(expectedMac[i] != buf[macStart + i]) - throw new InvalidDataException(); + if(expectedMac[i] != buf[macStart + i]) throw new FormatException(); } return true; } - - public int getMaxFrameLength() { - return maxFrameLength; - } } diff --git a/components/net/sf/briar/transport/IncomingEncryptionLayer.java b/components/net/sf/briar/transport/IncomingEncryptionLayer.java deleted file mode 100644 index 08e903a28b6ed1810eb952c8041f80e1fe5c1f85..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/IncomingEncryptionLayer.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -import net.sf.briar.api.transport.Segment; - -interface IncomingEncryptionLayer { - - /** - * Reads a segment, excluding its tag, into the given buffer. Returns false - * if no more segments can be read from the connection. - * @throws IOException if an unrecoverable error occurs and the connection - * must be closed. - * @throws InvalidDataException if a recoverable error occurs. The caller - * may choose whether to retry the read or close the connection. - */ - boolean readSegment(Segment s) throws IOException, InvalidDataException; - - /** - * Returns the maximum length in bytes of the segments this layer returns. - */ - int getMaxSegmentLength(); -} diff --git a/components/net/sf/briar/transport/IncomingEncryptionLayerImpl.java b/components/net/sf/briar/transport/IncomingEncryptionLayerImpl.java index 80e5c66beaa9f218f352d1a3853f8cd362993a8a..ef8e1f61e0956ffa9b871c92e9966ab15bfb1e0d 100644 --- a/components/net/sf/briar/transport/IncomingEncryptionLayerImpl.java +++ b/components/net/sf/briar/transport/IncomingEncryptionLayerImpl.java @@ -1,10 +1,8 @@ package net.sf.briar.transport; -import static net.sf.briar.api.transport.TransportConstants.ACK_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import java.io.EOFException; @@ -17,86 +15,70 @@ import javax.crypto.spec.IvParameterSpec; import net.sf.briar.api.FormatException; import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.transport.Segment; -class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer { +class IncomingEncryptionLayerImpl implements FrameReader { private final InputStream in; - private final Cipher tagCipher, segCipher; - private final ErasableKey tagKey, segKey; - private final boolean tagEverySegment; - private final int headerLength, blockSize; + private final Cipher tagCipher, frameCipher; + private final ErasableKey tagKey, frameKey; + private final int blockSize; private final byte[] iv, ciphertext; - private byte[] bufferedTag; - private boolean firstSegment = true; - private long segmentNumber = 0L; + private boolean readTag; + private long frameNumber; IncomingEncryptionLayerImpl(InputStream in, Cipher tagCipher, - Cipher segCipher, ErasableKey tagKey, ErasableKey segKey, - boolean tagEverySegment, boolean ackHeader, byte[] bufferedTag) { + Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey, + boolean readTag) { this.in = in; this.tagCipher = tagCipher; - this.segCipher = segCipher; + this.frameCipher = frameCipher; this.tagKey = tagKey; - this.segKey = segKey; - this.tagEverySegment = tagEverySegment; - this.bufferedTag = bufferedTag; - if(ackHeader) headerLength = FRAME_HEADER_LENGTH + ACK_HEADER_LENGTH; - else headerLength = FRAME_HEADER_LENGTH; - blockSize = segCipher.getBlockSize(); + this.frameKey = frameKey; + this.readTag = readTag; + blockSize = frameCipher.getBlockSize(); if(blockSize < FRAME_HEADER_LENGTH) throw new IllegalArgumentException(); iv = IvEncoder.encodeIv(0L, blockSize); - ciphertext = new byte[MAX_SEGMENT_LENGTH]; + ciphertext = new byte[MAX_FRAME_LENGTH]; + frameNumber = 0L; } - public boolean readSegment(Segment s) throws IOException { - boolean expectTag = tagEverySegment || firstSegment; - firstSegment = false; + public boolean readFrame(Frame f) throws IOException { try { - if(expectTag) { - // Read the tag if we don't have one buffered - if(bufferedTag == null) { - int offset = 0; - while(offset < TAG_LENGTH) { - int read = in.read(ciphertext, offset, - TAG_LENGTH - offset); - if(read == -1) { - if(offset == 0) return false; - throw new EOFException(); - } - offset += read; + // Read the tag if it hasn't already been read + if(readTag) { + int offset = 0; + while(offset < TAG_LENGTH) { + int read = in.read(ciphertext, offset, + TAG_LENGTH - offset); + if(read == -1) { + if(offset == 0) return false; + throw new EOFException(); } - long seg = TagEncoder.decodeTag(ciphertext, tagCipher, - tagKey); - if(seg == -1) throw new FormatException(); - segmentNumber = seg; - } else { - long seg = TagEncoder.decodeTag(bufferedTag, tagCipher, - tagKey); - bufferedTag = null; - if(seg == -1) throw new FormatException(); - segmentNumber = seg; + offset += read; } + if(!TagEncoder.decodeTag(ciphertext, tagCipher, tagKey)) + throw new FormatException(); } // Read the first block of the frame int offset = 0; while(offset < blockSize) { int read = in.read(ciphertext, offset, blockSize - offset); if(read == -1) { - if(offset == 0 && !expectTag) return false; + if(offset == 0 && !readTag) return false; throw new EOFException(); } offset += read; } + readTag = false; // Decrypt the first block of the frame - byte[] plaintext = s.getBuffer(); + byte[] plaintext = f.getBuffer(); try { - IvEncoder.updateIv(iv, segmentNumber); + IvEncoder.updateIv(iv, frameNumber); IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.DECRYPT_MODE, segKey, ivSpec); - int decrypted = segCipher.update(ciphertext, 0, blockSize, + frameCipher.init(Cipher.DECRYPT_MODE, frameKey, ivSpec); + int decrypted = frameCipher.update(ciphertext, 0, blockSize, plaintext); if(decrypted != blockSize) throw new RuntimeException(); } catch(GeneralSecurityException badCipher) { @@ -105,7 +87,7 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer { // Parse the frame header int payload = HeaderEncoder.getPayloadLength(plaintext); int padding = HeaderEncoder.getPaddingLength(plaintext); - int length = headerLength + payload + padding + MAC_LENGTH; + int length = FRAME_HEADER_LENGTH + payload + padding + MAC_LENGTH; if(length > MAX_FRAME_LENGTH) throw new FormatException(); // Read the remainder of the frame while(offset < length) { @@ -115,24 +97,20 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer { } // Decrypt the remainder of the frame try { - int decrypted = segCipher.doFinal(ciphertext, blockSize, + int decrypted = frameCipher.doFinal(ciphertext, blockSize, length - blockSize, plaintext, blockSize); if(decrypted != length - blockSize) throw new RuntimeException(); } catch(GeneralSecurityException badCipher) { throw new RuntimeException(badCipher); } - s.setLength(length); - s.setSegmentNumber(segmentNumber++); + f.setLength(length); + frameNumber++; return true; } catch(IOException e) { - segKey.erase(); + frameKey.erase(); tagKey.erase(); throw e; } } - - public int getMaxSegmentLength() { - return MAX_SEGMENT_LENGTH - TAG_LENGTH; - } } \ No newline at end of file diff --git a/components/net/sf/briar/transport/IncomingErrorCorrectionLayer.java b/components/net/sf/briar/transport/IncomingErrorCorrectionLayer.java deleted file mode 100644 index f909dcd606b0a46957643456e4da05a52e39138e..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/IncomingErrorCorrectionLayer.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -interface IncomingErrorCorrectionLayer { - - /** - * Reads a frame into the given buffer. The frame number must be contained - * in the given window. Returns false if no more frames can be read from - * the connection. - * @throws IOException if an unrecoverable error occurs and the connection - * must be closed. - * @throws InvalidDataException if a recoverable error occurs. The caller - * may choose whether to retry the read or close the connection. - */ - boolean readFrame(Frame f, FrameWindow window) throws IOException, - InvalidDataException; - - /** Returns the maximum length in bytes of the frames this layer returns. */ - int getMaxFrameLength(); -} diff --git a/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java b/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java deleted file mode 100644 index ff1d2f89524966fdff4012288997b372b992a454..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java +++ /dev/null @@ -1,101 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -import net.sf.briar.api.FormatException; -import net.sf.briar.api.transport.Segment; - -class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer { - - private final IncomingEncryptionLayer in; - private final ErasureDecoder decoder; - private final int n, k, maxSegmentLength, maxFrameLength; - private final Map<Long, Integer> discardCounts; - private final Map<Long, Segment[]> segmentSets; - private final ArrayList<Segment> freeSegments; - - IncomingErrorCorrectionLayerImpl(IncomingEncryptionLayer in, - ErasureDecoder decoder, int n, int k) { - this.in = in; - this.decoder = decoder; - this.n = n; - this.k = k; - maxSegmentLength = in.getMaxSegmentLength(); - maxFrameLength = Math.min(MAX_FRAME_LENGTH, maxSegmentLength * k); - discardCounts = new HashMap<Long, Integer>(); - segmentSets = new HashMap<Long, Segment[]>(); - freeSegments = new ArrayList<Segment>(); - } - - public boolean readFrame(Frame f, FrameWindow window) throws IOException, - InvalidDataException { - // Free any segment sets that have been removed from the window - Iterator<Entry<Long, Segment[]>> it = segmentSets.entrySet().iterator(); - while(it.hasNext()) { - Entry<Long, Segment[]> e = it.next(); - if(!window.contains(e.getKey())) { - it.remove(); - for(Segment s : e.getValue()) if(s != null) freeSegments.add(s); - } - } - // Free any discard counts that are no longer too high for the window - Iterator<Long> it1 = discardCounts.keySet().iterator(); - while(it1.hasNext()) if(!window.isTooHigh(it1.next())) it1.remove(); - // Grab a free segment, or allocate one if necessary - Segment s; - int free = freeSegments.size(); - if(free == 0) s = new SegmentImpl(maxSegmentLength); - else s = freeSegments.remove(free - 1); - // Read segments until a frame can be decoded - while(true) { - // Read segments until a segment in the window is returned - long frameNumber; - while(true) { - if(!in.readSegment(s)) { - freeSegments.add(s); - return false; - } - frameNumber = s.getSegmentNumber() / n; - if(window.contains(frameNumber)) break; - if(window.isTooHigh(frameNumber)) countDiscard(frameNumber); - } - // Add the segment to its set, creating a set if necessary - Segment[] set = segmentSets.get(frameNumber); - if(set == null) { - set = new Segment[n]; - segmentSets.put(frameNumber, set); - } - set[(int) (frameNumber % n)] = s; - // Try to decode the frame - if(decoder.decodeFrame(f, set)) return true; - } - } - - public int getMaxFrameLength() { - return maxFrameLength; - } - - private void countDiscard(long frameNumber) throws FormatException { - Integer count = discardCounts.get(frameNumber); - if(count == null) discardCounts.put(frameNumber, 1); - else if(count == n - k) throw new FormatException(); - else discardCounts.put(frameNumber, count + 1); - } - - // Only for testing - Map<Long, Segment[]> getSegmentSets() { - return segmentSets; - } - - // Only for testing - Map<Long, Integer> getDiscardCounts() { - return discardCounts; - } -} diff --git a/components/net/sf/briar/transport/IncomingReliabilityLayer.java b/components/net/sf/briar/transport/IncomingReliabilityLayer.java deleted file mode 100644 index 01525c0e4bed2714e727769d8513860fb36dc382..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/IncomingReliabilityLayer.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -interface IncomingReliabilityLayer { - - /** - * Reads and returns a frame, possibly using the given buffer. Returns null - * if no more frames can be read from the connection. - * @throws IOException if an unrecoverable error occurs and the connection - * must be closed. - * @throws InvalidDataException if a recoverable error occurs. The caller - * may choose whether to retry the read or close the connection. - */ - Frame readFrame(Frame f) throws IOException, InvalidDataException; - - /** Returns the maximum length in bytes of the frames this layer returns. */ - int getMaxFrameLength(); -} diff --git a/components/net/sf/briar/transport/IncomingReliabilityLayerImpl.java b/components/net/sf/briar/transport/IncomingReliabilityLayerImpl.java deleted file mode 100644 index 5ed04342e19e9b27d3918cfc79c2da76cdcce1a9..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/IncomingReliabilityLayerImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.SortedMap; -import java.util.TreeMap; - -/** A reliability layer that reorders out-of-order frames. */ -class IncomingReliabilityLayerImpl implements IncomingReliabilityLayer { - - private final IncomingAuthenticationLayer in; - private final int maxFrameLength; - private final FrameWindow window; - private final SortedMap<Long, Frame> frames; - private final ArrayList<Frame> freeFrames; - - private long nextFrameNumber = 0L; - - IncomingReliabilityLayerImpl(IncomingAuthenticationLayer in) { - this.in = in; - maxFrameLength = in.getMaxFrameLength(); - window = new FrameWindowImpl(); - frames = new TreeMap<Long, Frame>(); - freeFrames = new ArrayList<Frame>(); - } - - public Frame readFrame(Frame f) throws IOException, - InvalidDataException { - freeFrames.add(f); - // Read frames until there's an in-order frame to return - while(frames.isEmpty() || frames.firstKey() > nextFrameNumber) { - // Grab a free frame, or allocate one if necessary - int free = freeFrames.size(); - if(free == 0) f = new Frame(maxFrameLength); - else f = freeFrames.remove(free - 1); - // Read a frame - if(!in.readFrame(f, window)) return null; - // If the frame is in order, return it - long frameNumber = f.getFrameNumber(); - if(frameNumber == nextFrameNumber) { - if(!window.remove(nextFrameNumber)) - throw new IllegalStateException(); - nextFrameNumber++; - return f; - } - // Insert the frame into the map - frames.put(frameNumber, f); - } - if(!window.remove(nextFrameNumber)) throw new IllegalStateException(); - nextFrameNumber++; - return frames.remove(frames.firstKey()); - } - - public int getMaxFrameLength() { - return maxFrameLength; - } - - // Only for testing - public int getFreeFramesCount() { - return freeFrames.size(); - } -} diff --git a/components/net/sf/briar/transport/InvalidDataException.java b/components/net/sf/briar/transport/InvalidDataException.java deleted file mode 100644 index 34580d4340feeb2239993105f8c02e8b859b02a2..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/InvalidDataException.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.sf.briar.transport; - -/** An exception that indicates a recoverable formatting error. */ -class InvalidDataException extends Exception { - - private static final long serialVersionUID = 4455775710413826953L; -} diff --git a/components/net/sf/briar/transport/NullFrameWindow.java b/components/net/sf/briar/transport/NullFrameWindow.java deleted file mode 100644 index 9f5fb19f7145b800fb871b31b5460472fd5c8621..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/NullFrameWindow.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; - -/** A frame window that does not allow any reordering. */ -class NullFrameWindow implements FrameWindow { - - private long base = 0L; - - public boolean isTooHigh(long frameNumber) { - if(frameNumber < 0 || frameNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - return frameNumber != base; - } - - public boolean contains(long frameNumber) { - if(frameNumber < 0 || frameNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - return frameNumber == base; - } - - public boolean remove(long frameNumber) { - if(frameNumber < 0 || frameNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - if(frameNumber != base) return false; - base++; - return true; - } -} diff --git a/components/net/sf/briar/transport/NullIncomingErrorCorrectionLayer.java b/components/net/sf/briar/transport/NullIncomingErrorCorrectionLayer.java deleted file mode 100644 index 1e5077d3c139d7377bd93ec8e7d620b699064f0d..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/NullIncomingErrorCorrectionLayer.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -import net.sf.briar.api.transport.Segment; - -class NullIncomingErrorCorrectionLayer implements IncomingErrorCorrectionLayer { - - private final IncomingEncryptionLayer in; - private final int maxFrameLength; - private final Segment segment; - - NullIncomingErrorCorrectionLayer(IncomingEncryptionLayer in) { - this.in = in; - maxFrameLength = in.getMaxSegmentLength(); - segment = new SegmentImpl(maxFrameLength); - } - - public boolean readFrame(Frame f, FrameWindow window) throws IOException, - InvalidDataException { - while(true) { - if(!in.readSegment(segment)) return false; - byte[] buf = segment.getBuffer(); - long frameNumber = HeaderEncoder.getFrameNumber(buf); - if(window.contains(frameNumber)) break; - } - int length = segment.getLength(); - // FIXME: Unnecessary copy - System.arraycopy(segment.getBuffer(), 0, f.getBuffer(), 0, length); - f.setLength(length); - return true; - } - - public int getMaxFrameLength() { - return maxFrameLength; - } -} diff --git a/components/net/sf/briar/transport/NullIncomingReliabilityLayer.java b/components/net/sf/briar/transport/NullIncomingReliabilityLayer.java deleted file mode 100644 index 194df4f4bf1517fb41870ab0afde64cde7a25450..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/NullIncomingReliabilityLayer.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -class NullIncomingReliabilityLayer implements IncomingReliabilityLayer { - - private final IncomingAuthenticationLayer in; - private final int maxFrameLength; - private final FrameWindow window; - - NullIncomingReliabilityLayer(IncomingAuthenticationLayer in) { - this.in = in; - maxFrameLength = in.getMaxFrameLength(); - window = new NullFrameWindow(); - } - - public Frame readFrame(Frame f) throws IOException, InvalidDataException { - if(!in.readFrame(f, window)) return null; - if(!window.remove(f.getFrameNumber())) - throw new IllegalStateException(); - return f; - } - - public int getMaxFrameLength() { - return maxFrameLength; - } -} diff --git a/components/net/sf/briar/transport/NullOutgoingErrorCorrectionLayer.java b/components/net/sf/briar/transport/NullOutgoingErrorCorrectionLayer.java deleted file mode 100644 index 6847697f9a59e0231dbd495a0652b8ed335d57d3..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/NullOutgoingErrorCorrectionLayer.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; - -import java.io.IOException; - -import net.sf.briar.api.transport.Segment; - -class NullOutgoingErrorCorrectionLayer implements OutgoingErrorCorrectionLayer { - - private final OutgoingEncryptionLayer out; - private final int maxSegmentLength; - private final Segment segment; - - private long segmentNumber = 0L; - - public NullOutgoingErrorCorrectionLayer(OutgoingEncryptionLayer out) { - this.out = out; - maxSegmentLength = out.getMaxSegmentLength(); - segment = new SegmentImpl(maxSegmentLength); - } - - public void writeFrame(Frame f) throws IOException { - if(segmentNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalStateException(); - int length = f.getLength(); - // FIXME: Unnecessary copy - System.arraycopy(f.getBuffer(), 0, segment.getBuffer(), 0, length); - segment.setLength(length); - segment.setSegmentNumber(segmentNumber++); - out.writeSegment(segment); - } - - public void flush() throws IOException { - out.flush(); - } - - public long getRemainingCapacity() { - return out.getRemainingCapacity(); - } - - public int getMaxFrameLength() { - return maxSegmentLength; - } -} diff --git a/components/net/sf/briar/transport/NullOutgoingReliabilityLayer.java b/components/net/sf/briar/transport/NullOutgoingReliabilityLayer.java deleted file mode 100644 index 650f245e54c0e9b84ae8119d62ce8329138a598d..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/NullOutgoingReliabilityLayer.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -class NullOutgoingReliabilityLayer implements OutgoingReliabilityLayer { - - private final OutgoingAuthenticationLayer out; - private final int maxFrameLength; - - NullOutgoingReliabilityLayer(OutgoingAuthenticationLayer out) { - this.out = out; - maxFrameLength = out.getMaxFrameLength(); - } - - public void writeFrame(Frame f) throws IOException { - out.writeFrame(f); - } - - public void flush() throws IOException { - out.flush(); - } - - public long getRemainingCapacity() { - return out.getRemainingCapacity(); - } - - public int getMaxFrameLength() { - return maxFrameLength; - } -} diff --git a/components/net/sf/briar/transport/OutgoingAuthenticationLayer.java b/components/net/sf/briar/transport/OutgoingAuthenticationLayer.java deleted file mode 100644 index 21e41a9243aed1bbc5cd58444c61b2d634d83664..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/OutgoingAuthenticationLayer.java +++ /dev/null @@ -1,18 +0,0 @@ -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(); - - /** Returns the maximum length in bytes of the frames this layer accepts. */ - int getMaxFrameLength(); -} diff --git a/components/net/sf/briar/transport/OutgoingAuthenticationLayerImpl.java b/components/net/sf/briar/transport/OutgoingAuthenticationLayerImpl.java index 535ec4834a2a0af64d12da6616527b657f8d5ea7..2e3798dc36b54560f73872578b9eef8852e07536 100644 --- a/components/net/sf/briar/transport/OutgoingAuthenticationLayerImpl.java +++ b/components/net/sf/briar/transport/OutgoingAuthenticationLayerImpl.java @@ -10,13 +10,12 @@ import javax.crypto.ShortBufferException; import net.sf.briar.api.crypto.ErasableKey; -class OutgoingAuthenticationLayerImpl implements OutgoingAuthenticationLayer { +class OutgoingAuthenticationLayerImpl implements FrameWriter { - private final OutgoingErrorCorrectionLayer out; + private final FrameWriter out; private final Mac mac; - private final int maxFrameLength; - OutgoingAuthenticationLayerImpl(OutgoingErrorCorrectionLayer out, Mac mac, + OutgoingAuthenticationLayerImpl(FrameWriter out, Mac mac, ErasableKey macKey) { this.out = out; this.mac = mac; @@ -28,7 +27,6 @@ class OutgoingAuthenticationLayerImpl implements OutgoingAuthenticationLayer { macKey.erase(); if(mac.getMacLength() != MAC_LENGTH) throw new IllegalArgumentException(); - maxFrameLength = out.getMaxFrameLength(); } public void writeFrame(Frame f) throws IOException { @@ -50,8 +48,4 @@ class OutgoingAuthenticationLayerImpl implements OutgoingAuthenticationLayer { public long getRemainingCapacity() { return out.getRemainingCapacity(); } - - public int getMaxFrameLength() { - return maxFrameLength; - } } diff --git a/components/net/sf/briar/transport/OutgoingEncryptionLayer.java b/components/net/sf/briar/transport/OutgoingEncryptionLayer.java deleted file mode 100644 index e0e4b44023ae29e67cc6d3776dcb6a2397f0a5e6..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/OutgoingEncryptionLayer.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -import net.sf.briar.api.transport.Segment; - -interface OutgoingEncryptionLayer { - - /** Writes the given segment. */ - void writeSegment(Segment s) throws IOException; - - /** Flushes the stack. */ - void flush() throws IOException; - - /** Returns the maximum number of bytes that can be written. */ - long getRemainingCapacity(); - - /** - * Returns the maximum length in bytes of the segments this layer accepts. - */ - int getMaxSegmentLength(); -} diff --git a/components/net/sf/briar/transport/OutgoingEncryptionLayerImpl.java b/components/net/sf/briar/transport/OutgoingEncryptionLayerImpl.java index 6e9696b2060aef6f545b2bee480e61a29a9eef4f..f79b6831d6c4f9642287f2c803973e2212a4eb98 100644 --- a/components/net/sf/briar/transport/OutgoingEncryptionLayerImpl.java +++ b/components/net/sf/briar/transport/OutgoingEncryptionLayerImpl.java @@ -1,6 +1,6 @@ package net.sf.briar.transport; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; +import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import java.io.IOException; @@ -11,46 +11,43 @@ import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.transport.Segment; -class OutgoingEncryptionLayerImpl implements OutgoingEncryptionLayer { +class OutgoingEncryptionLayerImpl implements FrameWriter { private final OutputStream out; - private final Cipher tagCipher, segCipher; - private final ErasableKey tagKey, segKey; - private final boolean tagEverySegment; + private final Cipher tagCipher, frameCipher; + private final ErasableKey tagKey, frameKey; private final byte[] iv, ciphertext; - private long capacity; + private long capacity, frameNumber; OutgoingEncryptionLayerImpl(OutputStream out, long capacity, - Cipher tagCipher, Cipher segCipher, ErasableKey tagKey, - ErasableKey segKey, boolean tagEverySegment) { + Cipher tagCipher, Cipher frameCipher, ErasableKey tagKey, + ErasableKey frameKey) { this.out = out; this.capacity = capacity; this.tagCipher = tagCipher; - this.segCipher = segCipher; + this.frameCipher = frameCipher; this.tagKey = tagKey; - this.segKey = segKey; - this.tagEverySegment = tagEverySegment; - iv = IvEncoder.encodeIv(0L, segCipher.getBlockSize()); - ciphertext = new byte[MAX_SEGMENT_LENGTH]; + this.frameKey = frameKey; + iv = IvEncoder.encodeIv(0L, frameCipher.getBlockSize()); + ciphertext = new byte[TAG_LENGTH + MAX_FRAME_LENGTH]; + frameNumber = 0L; } - public void writeSegment(Segment s) throws IOException { - byte[] plaintext = s.getBuffer(); - int length = s.getLength(); - long segmentNumber = s.getSegmentNumber(); + public void writeFrame(Frame f) throws IOException { + byte[] plaintext = f.getBuffer(); + int length = f.getLength(); int offset = 0; - if(tagEverySegment || segmentNumber == 0) { - TagEncoder.encodeTag(ciphertext, segmentNumber, tagCipher, tagKey); + if(frameNumber == 0) { + TagEncoder.encodeTag(ciphertext, tagCipher, tagKey); offset = TAG_LENGTH; } - IvEncoder.updateIv(iv, segmentNumber); + IvEncoder.updateIv(iv, frameNumber); IvParameterSpec ivSpec = new IvParameterSpec(iv); try { - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - int encrypted = segCipher.doFinal(plaintext, 0, length, + frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec); + int encrypted = frameCipher.doFinal(plaintext, 0, length, ciphertext, offset); if(encrypted != length) throw new RuntimeException(); } catch(GeneralSecurityException badCipher) { @@ -59,11 +56,12 @@ class OutgoingEncryptionLayerImpl implements OutgoingEncryptionLayer { try { out.write(ciphertext, 0, offset + length); } catch(IOException e) { - segKey.erase(); + frameKey.erase(); tagKey.erase(); throw e; } capacity -= offset + length; + frameNumber++; } public void flush() throws IOException { @@ -73,8 +71,4 @@ class OutgoingEncryptionLayerImpl implements OutgoingEncryptionLayer { public long getRemainingCapacity() { return capacity; } - - public int getMaxSegmentLength() { - return MAX_SEGMENT_LENGTH - TAG_LENGTH; - } } \ No newline at end of file diff --git a/components/net/sf/briar/transport/OutgoingErrorCorrectionLayer.java b/components/net/sf/briar/transport/OutgoingErrorCorrectionLayer.java deleted file mode 100644 index 9dfd9eac37647014bb66dc871a41eedd18f5dffb..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/OutgoingErrorCorrectionLayer.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; - -interface OutgoingErrorCorrectionLayer { - - /** 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(); - - /** Returns the maximum length in bytes of the frames this layer accepts. */ - int getMaxFrameLength(); -} diff --git a/components/net/sf/briar/transport/OutgoingErrorCorrectionLayerImpl.java b/components/net/sf/briar/transport/OutgoingErrorCorrectionLayerImpl.java deleted file mode 100644 index e7662d002e123b8b9cecefacdf5c43e754f12c11..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/OutgoingErrorCorrectionLayerImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; - -import java.io.IOException; - -import net.sf.briar.api.transport.Segment; - -class OutgoingErrorCorrectionLayerImpl implements OutgoingErrorCorrectionLayer { - - private final OutgoingEncryptionLayer out; - private final ErasureEncoder encoder; - private final int n, maxFrameLength; - - OutgoingErrorCorrectionLayerImpl(OutgoingEncryptionLayer out, - ErasureEncoder encoder, int n, int k) { - this.out = out; - this.encoder = encoder; - this.n = n; - maxFrameLength = Math.min(MAX_FRAME_LENGTH, - out.getMaxSegmentLength() * k); - } - - public void writeFrame(Frame f) throws IOException { - for(Segment s : encoder.encodeFrame(f)) out.writeSegment(s); - } - - public void flush() throws IOException { - out.flush(); - } - - public long getRemainingCapacity() { - return out.getRemainingCapacity() / n; - } - - public int getMaxFrameLength() { - return maxFrameLength; - } -} diff --git a/components/net/sf/briar/transport/SegmentImpl.java b/components/net/sf/briar/transport/SegmentImpl.java deleted file mode 100644 index a62c41e8343bdd170c8d690f9d92a7c950e5e344..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/SegmentImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; -import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; -import net.sf.briar.api.transport.Segment; - -class SegmentImpl implements Segment { - - private final byte[] buf; - - private int length = -1; - private long segmentNumber = -1; - - SegmentImpl() { - this(MAX_SEGMENT_LENGTH); - } - - SegmentImpl(int length) { - if(length < FRAME_HEADER_LENGTH + MAC_LENGTH) - throw new IllegalArgumentException(); - if(length > MAX_SEGMENT_LENGTH) throw new IllegalArgumentException(); - buf = new byte[length]; - } - - public byte[] getBuffer() { - return buf; - } - - public int getLength() { - if(length == -1) throw new IllegalStateException(); - return length; - } - - public long getSegmentNumber() { - if(segmentNumber == -1) throw new IllegalStateException(); - return segmentNumber; - } - - public void setLength(int length) { - if(length < FRAME_HEADER_LENGTH + MAC_LENGTH || length > buf.length) - throw new IllegalArgumentException(); - this.length = length; - } - - public void setSegmentNumber(long segmentNumber) { - if(segmentNumber < 0 || segmentNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - this.segmentNumber = segmentNumber; - } -} diff --git a/components/net/sf/briar/transport/SegmentedIncomingEncryptionLayer.java b/components/net/sf/briar/transport/SegmentedIncomingEncryptionLayer.java deleted file mode 100644 index 0316dd4832c6ca50f5a6c975fb9fe474c2647b2c..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/SegmentedIncomingEncryptionLayer.java +++ /dev/null @@ -1,109 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.ACK_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; - -import java.io.IOException; -import java.security.GeneralSecurityException; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; - -import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.plugins.SegmentSource; -import net.sf.briar.api.transport.Segment; - -class SegmentedIncomingEncryptionLayer implements IncomingEncryptionLayer { - - private final SegmentSource in; - private final Cipher tagCipher, segCipher; - private final ErasableKey tagKey, segKey; - private final boolean tagEverySegment; - private final int blockSize, headerLength, maxSegmentLength; - private final Segment segment; - private final byte[] iv; - - private Segment bufferedSegment; - private boolean firstSegment = true; - private long segmentNumber = 0L; - - SegmentedIncomingEncryptionLayer(SegmentSource in, Cipher tagCipher, - Cipher segCipher, ErasableKey tagKey, ErasableKey segKey, - boolean tagEverySegment, boolean ackHeader, - Segment bufferedSegment) { - this.in = in; - this.tagCipher = tagCipher; - this.segCipher = segCipher; - this.tagKey = tagKey; - this.segKey = segKey; - this.tagEverySegment = tagEverySegment; - this.bufferedSegment = bufferedSegment; - blockSize = segCipher.getBlockSize(); - if(blockSize < FRAME_HEADER_LENGTH) - throw new IllegalArgumentException(); - if(ackHeader) headerLength = FRAME_HEADER_LENGTH + ACK_HEADER_LENGTH; - else headerLength = FRAME_HEADER_LENGTH; - int length = in.getMaxSegmentLength(); - if(length < TAG_LENGTH + headerLength + 1 + MAC_LENGTH) - throw new IllegalArgumentException(); - if(length > MAX_SEGMENT_LENGTH) throw new IllegalArgumentException(); - maxSegmentLength = length - TAG_LENGTH; - segment = new SegmentImpl(length); - iv = IvEncoder.encodeIv(0L, blockSize); - } - - public boolean readSegment(Segment s) throws IOException, - InvalidDataException { - boolean expectTag = tagEverySegment || firstSegment; - firstSegment = false; - try { - // Read the segment, unless we have one buffered - Segment segment; - if(bufferedSegment == null) { - segment = this.segment; - if(!in.readSegment(segment)) return false; - } else { - segment = bufferedSegment; - bufferedSegment = null; - } - int offset = expectTag ? TAG_LENGTH : 0; - int length = segment.getLength(); - if(length < offset + headerLength + MAC_LENGTH) - throw new InvalidDataException(); - if(length > offset + maxSegmentLength) - throw new InvalidDataException(); - byte[] ciphertext = segment.getBuffer(); - // If a tag is expected then decrypt and validate it - if(expectTag) { - long seg = TagEncoder.decodeTag(ciphertext, tagCipher, tagKey); - if(seg == -1) throw new InvalidDataException(); - segmentNumber = seg; - } - // Decrypt the segment - try { - IvEncoder.updateIv(iv, segmentNumber); - IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.DECRYPT_MODE, segKey, ivSpec); - int decrypted = segCipher.doFinal(ciphertext, offset, - length - offset, s.getBuffer()); - if(decrypted != length - offset) throw new RuntimeException(); - } catch(GeneralSecurityException badCipher) { - throw new RuntimeException(badCipher); - } - s.setLength(length - offset); - s.setSegmentNumber(segmentNumber++); - return true; - } catch(IOException e) { - segKey.erase(); - tagKey.erase(); - throw e; - } - } - - public int getMaxSegmentLength() { - return maxSegmentLength; - } -} diff --git a/components/net/sf/briar/transport/SegmentedOutgoingEncryptionLayer.java b/components/net/sf/briar/transport/SegmentedOutgoingEncryptionLayer.java deleted file mode 100644 index 8eb1c0a683ee9259d75db6f827c7ecff26b8a704..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/SegmentedOutgoingEncryptionLayer.java +++ /dev/null @@ -1,91 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.ACK_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; - -import java.io.IOException; -import java.security.GeneralSecurityException; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; - -import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.plugins.SegmentSink; -import net.sf.briar.api.transport.Segment; - -class SegmentedOutgoingEncryptionLayer implements OutgoingEncryptionLayer { - - private final SegmentSink out; - private final Cipher tagCipher, segCipher; - private final ErasableKey tagKey, segKey; - private final boolean tagEverySegment; - private final int headerLength, maxSegmentLength; - private final Segment segment; - private final byte[] iv; - - private long capacity; - - SegmentedOutgoingEncryptionLayer(SegmentSink out, long capacity, - Cipher tagCipher, Cipher segCipher, ErasableKey tagKey, - ErasableKey segKey, boolean tagEverySegment, boolean ackHeader) { - this.out = out; - this.capacity = capacity; - this.tagCipher = tagCipher; - this.segCipher = segCipher; - this.tagKey = tagKey; - this.segKey = segKey; - this.tagEverySegment = tagEverySegment; - if(ackHeader) headerLength = FRAME_HEADER_LENGTH + ACK_HEADER_LENGTH; - else headerLength = FRAME_HEADER_LENGTH; - int length = out.getMaxSegmentLength(); - if(length < TAG_LENGTH + headerLength + 1 + MAC_LENGTH) - throw new IllegalArgumentException(); - if(length > MAX_SEGMENT_LENGTH) throw new IllegalArgumentException(); - maxSegmentLength = length - MAC_LENGTH; - segment = new SegmentImpl(length); - iv = IvEncoder.encodeIv(0L, segCipher.getBlockSize()); - } - - public void writeSegment(Segment s) throws IOException { - byte[] plaintext = s.getBuffer(), ciphertext = segment.getBuffer(); - int length = s.getLength(); - long segmentNumber = s.getSegmentNumber(); - int offset = 0; - if(tagEverySegment || segmentNumber == 0) { - TagEncoder.encodeTag(ciphertext, segmentNumber, tagCipher, tagKey); - offset = TAG_LENGTH; - } - IvEncoder.updateIv(iv, segmentNumber); - IvParameterSpec ivSpec = new IvParameterSpec(iv); - try { - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - int encrypted = segCipher.doFinal(plaintext, 0, length, - ciphertext, offset); - if(encrypted != length) throw new RuntimeException(); - } catch(GeneralSecurityException badCipher) { - throw new RuntimeException(badCipher); - } - segment.setLength(offset + length); - try { - out.writeSegment(segment); - } catch(IOException e) { - segKey.erase(); - tagKey.erase(); - throw e; - } - capacity -= offset + length; - } - - public void flush() throws IOException {} - - public long getRemainingCapacity() { - return capacity; - } - - public int getMaxSegmentLength() { - return maxSegmentLength; - } -} \ No newline at end of file diff --git a/components/net/sf/briar/transport/TagEncoder.java b/components/net/sf/briar/transport/TagEncoder.java index e7a223f2a3cee537515e093c8e7dc5400b56d9f7..dca0c60debee9c91edb0fdfa4ce0c5d3a2d1e988 100644 --- a/components/net/sf/briar/transport/TagEncoder.java +++ b/components/net/sf/briar/transport/TagEncoder.java @@ -1,26 +1,19 @@ package net.sf.briar.transport; import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; -import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import java.security.GeneralSecurityException; import javax.crypto.Cipher; import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.util.ByteUtils; class TagEncoder { - static void encodeTag(byte[] tag, long segmentNumber, Cipher tagCipher, - ErasableKey tagKey) { + static void encodeTag(byte[] tag, Cipher tagCipher, ErasableKey tagKey) { if(tag.length < TAG_LENGTH) throw new IllegalArgumentException(); - if(segmentNumber < 0 || segmentNumber > MAX_32_BIT_UNSIGNED) - throw new IllegalArgumentException(); - // Clear the tag + // Blank plaintext for(int i = 0; i < TAG_LENGTH; i++) tag[i] = 0; - // Encode the segment number as a uint32 at the end of the tag - ByteUtils.writeUint32(segmentNumber, tag, TAG_LENGTH - 4); try { tagCipher.init(Cipher.ENCRYPT_MODE, tagKey); int encrypted = tagCipher.doFinal(tag, 0, TAG_LENGTH, tag); @@ -31,18 +24,18 @@ class TagEncoder { } } - static long decodeTag(byte[] tag, Cipher tagCipher, ErasableKey tagKey) { + static boolean decodeTag(byte[] tag, Cipher tagCipher, ErasableKey tagKey) { if(tag.length < TAG_LENGTH) throw new IllegalArgumentException(); try { tagCipher.init(Cipher.DECRYPT_MODE, tagKey); byte[] plaintext = tagCipher.doFinal(tag, 0, TAG_LENGTH); if(plaintext.length != TAG_LENGTH) throw new IllegalArgumentException(); - // All but the last four bytes of the plaintext should be blank - for(int i = 0; i < TAG_LENGTH - 4; i++) { - if(plaintext[i] != 0) return -1; + //The plaintext should be blank + for(int i = 0; i < TAG_LENGTH; i++) { + if(plaintext[i] != 0) return false; } - return ByteUtils.readUint32(plaintext, TAG_LENGTH - 4); + return true; } catch(GeneralSecurityException e) { // Unsuitable cipher or key throw new IllegalArgumentException(e); diff --git a/components/net/sf/briar/transport/XorErasureDecoder.java b/components/net/sf/briar/transport/XorErasureDecoder.java deleted file mode 100644 index 4ae174bb8a3cda8c934716db6fcf246250577f92..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/XorErasureDecoder.java +++ /dev/null @@ -1,75 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.ACK_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; -import net.sf.briar.api.FormatException; -import net.sf.briar.api.transport.Segment; - -/** An erasure decoder that uses k data segments and one parity segment. */ -class XorErasureDecoder implements ErasureDecoder { - - private final int n, headerLength; - - XorErasureDecoder(int n, boolean ackHeader) { - this.n = n; - if(ackHeader) headerLength = FRAME_HEADER_LENGTH + ACK_HEADER_LENGTH; - else headerLength = FRAME_HEADER_LENGTH; - } - - public boolean decodeFrame(Frame f, Segment[] set) throws FormatException { - // We need at least n - 1 pieces - int pieces = 0; - for(int i = 0; i < n; i++) if(set[i] != null) pieces++; - if(pieces < n - 1) return false; - // All the pieces must have the same length - take the minimum - int length = MAX_FRAME_LENGTH; - for(int i = 0; i < n; i++) { - if(set[i] != null) { - int len = set[i].getLength(); - if(len < length) length = len; - } - } - if(length * (n - 1) > MAX_FRAME_LENGTH) throw new FormatException(); - // Decode the frame - byte[] dest = f.getBuffer(); - int offset = 0; - if(pieces == n || set[n - 1] == null) { - // We don't need no stinkin' parity segment - for(int i = 0; i < n - 1; i++) { - byte[] src = set[i].getBuffer(); - int copyLength = Math.min(length, dest.length - offset); - System.arraycopy(src, 0, dest, offset, copyLength); - offset += length; - } - } else { - // Reconstruct the missing segment - byte[] parity = new byte[length]; - int missingOffset = -1; - for(int i = 0; i < n - 1; i++) { - if(set[i] == null) { - missingOffset = offset; - } else { - byte[] src = set[i].getBuffer(); - for(int j = 0; j < length; j++) parity[j] ^= src[j]; - int copyLength = Math.min(length, dest.length - offset); - System.arraycopy(src, 0, dest, offset, copyLength); - } - offset += length; - } - byte[] src = set[n - 1].getBuffer(); - for(int i = 0; i < length; i++) parity[i] ^= src[i]; - assert missingOffset != -1; - int copyLength = Math.min(length, dest.length - missingOffset); - System.arraycopy(parity, 0, dest, missingOffset, copyLength); - } - // The frame length might not be an exact multiple of the segment length - int payload = HeaderEncoder.getPayloadLength(dest); - int padding = HeaderEncoder.getPaddingLength(dest); - int frameLength = headerLength + payload + padding + MAC_LENGTH; - if(frameLength > MAX_FRAME_LENGTH) throw new FormatException(); - f.setLength(frameLength); - return true; - } -} diff --git a/components/net/sf/briar/transport/XorErasureEncoder.java b/components/net/sf/briar/transport/XorErasureEncoder.java deleted file mode 100644 index 220f679e38b92968cb902a5a709944430a05402b..0000000000000000000000000000000000000000 --- a/components/net/sf/briar/transport/XorErasureEncoder.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.sf.briar.transport; - -import net.sf.briar.api.transport.Segment; - -/** An erasure encoder than uses k data segments and one parity segment. */ -class XorErasureEncoder implements ErasureEncoder { - - private final int n; - - XorErasureEncoder(int n) { - this.n = n; - } - - public Segment[] encodeFrame(Frame f) { - Segment[] set = new Segment[n]; - int length = (int) Math.ceil((float) f.getLength() / (n - 1)); - for(int i = 0; i < n; i++) { - set[i] = new SegmentImpl(length); - set[i].setLength(length); - } - byte[] src = f.getBuffer(), parity = set[n - 1].getBuffer(); - int offset = 0; - for(int i = 0; i < n - 1; i++) { - int copyLength = Math.min(length, src.length - offset); - System.arraycopy(src, offset, set[i].getBuffer(), 0, copyLength); - for(int j = 0; j < copyLength; j++) parity[j] ^= src[offset + j]; - offset += length; - } - return set; - } -} diff --git a/test/build.xml b/test/build.xml index 77541769ffe5425e41d192557f174ee53c8f9809..c28327848121a228f899cc8ce9d502f77410e3e6 100644 --- a/test/build.xml +++ b/test/build.xml @@ -56,16 +56,8 @@ <test name='net.sf.briar.transport.ConnectionWriterImplTest'/> <test name='net.sf.briar.transport.ConnectionWriterTest'/> <test name='net.sf.briar.transport.FrameReadWriteTest'/> - <test name='net.sf.briar.transport.FrameWindowImplTest'/> <test name='net.sf.briar.transport.IncomingEncryptionLayerImplTest'/> - <test name='net.sf.briar.transport.IncomingErrorCorrectionLayerImplTest'/> - <test name='net.sf.briar.transport.IncomingReliabilityLayerImplTest'/> <test name='net.sf.briar.transport.OutgoingEncryptionLayerImplTest'/> - <test name='net.sf.briar.transport.SegmentedIncomingEncryptionLayerTest'/> - <test name='net.sf.briar.transport.SegmentedOutgoingEncryptionLayerTest'/> - <test name='net.sf.briar.transport.XorErasureCodeTest'/> - <test name='net.sf.briar.transport.XorErasureDecoderTest'/> - <test name='net.sf.briar.transport.XorErasureEncoderTest'/> <test name='net.sf.briar.util.ByteUtilsTest'/> <test name='net.sf.briar.util.FileUtilsTest'/> <test name='net.sf.briar.util.StringUtilsTest'/> diff --git a/test/net/sf/briar/ProtocolIntegrationTest.java b/test/net/sf/briar/ProtocolIntegrationTest.java index db5f968cef7d1439b74b704942876f2dc069c6d2..1d313a3de50add697ec01b585d55af96f564cdac 100644 --- a/test/net/sf/briar/ProtocolIntegrationTest.java +++ b/test/net/sf/briar/ProtocolIntegrationTest.java @@ -189,7 +189,7 @@ public class ProtocolIntegrationTest extends BriarTestCase { byte[] tag = new byte[TAG_LENGTH]; assertEquals(TAG_LENGTH, in.read(tag, 0, TAG_LENGTH)); ConnectionReader conn = connectionReaderFactory.createConnectionReader( - in, secret.clone(), tag); + in, secret.clone(), true); InputStream in1 = conn.getInputStream(); ProtocolReader reader = protocolReaderFactory.createProtocolReader(in1); diff --git a/test/net/sf/briar/crypto/KeyDerivationTest.java b/test/net/sf/briar/crypto/KeyDerivationTest.java index 3823291e73070b5466a67eed5b011ae36d129e78..b777cd7921491bafd8a483db0a65d9b8bec5b803 100644 --- a/test/net/sf/briar/crypto/KeyDerivationTest.java +++ b/test/net/sf/briar/crypto/KeyDerivationTest.java @@ -27,8 +27,8 @@ public class KeyDerivationTest extends BriarTestCase { @Test public void testSixKeysAreDistinct() { List<ErasableKey> keys = new ArrayList<ErasableKey>(); - keys.add(crypto.deriveSegmentKey(secret, true)); - keys.add(crypto.deriveSegmentKey(secret, false)); + keys.add(crypto.deriveFrameKey(secret, true)); + keys.add(crypto.deriveFrameKey(secret, false)); keys.add(crypto.deriveTagKey(secret, true)); keys.add(crypto.deriveTagKey(secret, false)); keys.add(crypto.deriveMacKey(secret, true)); diff --git a/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java b/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java index 7c551d09b5b97cca8249239ed0b56c78189c34a4..59bc557661594046317524462ba06f8c46730ec1 100644 --- a/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java +++ b/test/net/sf/briar/protocol/simplex/SimplexConnectionReadWriteTest.java @@ -174,7 +174,7 @@ public class SimplexConnectionReadWriteTest extends BriarTestCase { IncomingSimplexConnection batchIn = new IncomingSimplexConnection( new ImmediateExecutor(), new ImmediateExecutor(), db, connRegistry, connFactory, protoFactory, ctx, transportId, - transport, tag); + transport); // No messages should have been added yet assertFalse(listener.messagesAdded); // Read whatever needs to be read diff --git a/test/net/sf/briar/transport/ConnectionReaderImplTest.java b/test/net/sf/briar/transport/ConnectionReaderImplTest.java index 152ae8b4071c1ad7a2a5dc67ca18670227f58c06..92d431cfa8548ca926fb4820db30ae089bea3ebf 100644 --- a/test/net/sf/briar/transport/ConnectionReaderImplTest.java +++ b/test/net/sf/briar/transport/ConnectionReaderImplTest.java @@ -15,7 +15,6 @@ import net.sf.briar.api.transport.ConnectionReader; import org.apache.commons.io.output.ByteArrayOutputStream; import org.junit.Test; -// FIXME: This test covers too many classes public class ConnectionReaderImplTest extends TransportTest { public ConnectionReaderImplTest() throws Exception { @@ -217,14 +216,9 @@ public class ConnectionReaderImplTest extends TransportTest { } private ConnectionReader createConnectionReader(InputStream in) { - IncomingEncryptionLayer encryption = - new NullIncomingEncryptionLayer(in); - IncomingErrorCorrectionLayer correction = - new NullIncomingErrorCorrectionLayer(encryption); - IncomingAuthenticationLayer authentication = - new IncomingAuthenticationLayerImpl(correction, mac, macKey, false); - IncomingReliabilityLayer reliability = - new NullIncomingReliabilityLayer(authentication); - return new ConnectionReaderImpl(reliability, false, false); + FrameReader encryption = new NullIncomingEncryptionLayer(in); + FrameReader authentication = new IncomingAuthenticationLayerImpl( + encryption, mac, macKey); + return new ConnectionReaderImpl(authentication); } } diff --git a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java index a18f12b5be892295cb88813d2867c5d69e589337..e4cd00d3cab2249b2ef3aec8c25e094c352969c6 100644 --- a/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java +++ b/test/net/sf/briar/transport/ConnectionRecogniserImplTest.java @@ -618,7 +618,7 @@ public class ConnectionRecogniserImplTest extends BriarTestCase { ErasableKey tagKey = crypto.deriveTagKey(secret, true); Cipher tagCipher = crypto.getTagCipher(); byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); + TagEncoder.encodeTag(tag, tagCipher, tagKey); return tag; } } diff --git a/test/net/sf/briar/transport/ConnectionWriterImplTest.java b/test/net/sf/briar/transport/ConnectionWriterImplTest.java index a5e0d5ac6e7fb55981b6c842e5e2e07615f8cb37..335b922204e6f3206b604cc962cd4eafdce66e35 100644 --- a/test/net/sf/briar/transport/ConnectionWriterImplTest.java +++ b/test/net/sf/briar/transport/ConnectionWriterImplTest.java @@ -12,7 +12,6 @@ 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 { @@ -107,14 +106,9 @@ public class ConnectionWriterImplTest extends TransportTest { } 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, false); + FrameWriter encryption = new NullOutgoingEncryptionLayer(out); + FrameWriter authentication = + new OutgoingAuthenticationLayerImpl(encryption, mac, macKey); + return new ConnectionWriterImpl(authentication); } } diff --git a/test/net/sf/briar/transport/FrameReadWriteTest.java b/test/net/sf/briar/transport/FrameReadWriteTest.java index 89f54dd26a0a7468036715eaa2547f7e0c6bf893..62e275873fd2c2ead287fa239ef712161dc72a1a 100644 --- a/test/net/sf/briar/transport/FrameReadWriteTest.java +++ b/test/net/sf/briar/transport/FrameReadWriteTest.java @@ -27,25 +27,25 @@ import com.google.inject.Injector; public class FrameReadWriteTest extends BriarTestCase { private final CryptoComponent crypto; - private final Cipher tagCipher, segCipher; + private final Cipher tagCipher, frameCipher; private final Mac mac; private final Random random; private final byte[] outSecret; - private final ErasableKey tagKey, segKey, macKey; + private final ErasableKey tagKey, frameKey, macKey; public FrameReadWriteTest() { super(); Injector i = Guice.createInjector(new CryptoModule()); crypto = i.getInstance(CryptoComponent.class); tagCipher = crypto.getTagCipher(); - segCipher = crypto.getSegmentCipher(); + frameCipher = crypto.getFrameCipher(); mac = crypto.getMac(); random = new Random(); // Since we're sending frames to ourselves, we only need outgoing keys outSecret = new byte[32]; random.nextBytes(outSecret); tagKey = crypto.deriveTagKey(outSecret, true); - segKey = crypto.deriveSegmentKey(outSecret, true); + frameKey = crypto.deriveFrameKey(outSecret, true); macKey = crypto.deriveMacKey(outSecret, true); } @@ -62,7 +62,7 @@ public class FrameReadWriteTest extends BriarTestCase { private void testWriteAndRead(boolean initiator) throws Exception { // Encode the tag byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); + TagEncoder.encodeTag(tag, tagCipher, tagKey); // Generate two random frames byte[] frame = new byte[12345]; random.nextBytes(frame); @@ -70,21 +70,15 @@ public class FrameReadWriteTest extends BriarTestCase { random.nextBytes(frame1); // Copy the keys - the copies will be erased ErasableKey tagCopy = tagKey.copy(); - ErasableKey segCopy = segKey.copy(); + ErasableKey frameCopy = frameKey.copy(); ErasableKey macCopy = macKey.copy(); // Write the frames ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutgoingEncryptionLayer encryptionOut = new OutgoingEncryptionLayerImpl( - out, Long.MAX_VALUE, tagCipher, segCipher, tagCopy, segCopy, - false); - OutgoingErrorCorrectionLayer correctionOut = - new NullOutgoingErrorCorrectionLayer(encryptionOut); - OutgoingAuthenticationLayer authenticationOut = - new OutgoingAuthenticationLayerImpl(correctionOut, mac, macCopy); - OutgoingReliabilityLayer reliabilityOut = - new NullOutgoingReliabilityLayer(authenticationOut); - ConnectionWriter writer = new ConnectionWriterImpl(reliabilityOut, - false); + FrameWriter encryptionOut = new OutgoingEncryptionLayerImpl(out, + Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy); + FrameWriter authenticationOut = new OutgoingAuthenticationLayerImpl( + encryptionOut, mac, macCopy); + ConnectionWriter writer = new ConnectionWriterImpl(authenticationOut); OutputStream out1 = writer.getOutputStream(); out1.write(frame); out1.flush(); @@ -95,20 +89,13 @@ public class FrameReadWriteTest extends BriarTestCase { byte[] recoveredTag = new byte[TAG_LENGTH]; assertEquals(TAG_LENGTH, in.read(recoveredTag)); assertArrayEquals(tag, recoveredTag); - assertEquals(0L, TagEncoder.decodeTag(tag, tagCipher, tagKey)); + assertTrue(TagEncoder.decodeTag(tag, tagCipher, tagKey)); // Read the frames back - IncomingEncryptionLayer encryptionIn = new IncomingEncryptionLayerImpl( - in, tagCipher, segCipher, tagKey, segKey, false, false, - recoveredTag); - IncomingErrorCorrectionLayer correctionIn = - new NullIncomingErrorCorrectionLayer(encryptionIn); - IncomingAuthenticationLayer authenticationIn = - new IncomingAuthenticationLayerImpl(correctionIn, mac, macKey, - false); - IncomingReliabilityLayer reliabilityIn = - new NullIncomingReliabilityLayer(authenticationIn); - ConnectionReader reader = new ConnectionReaderImpl(reliabilityIn, false, - false); + FrameReader encryptionIn = new IncomingEncryptionLayerImpl(in, + tagCipher, frameCipher, tagKey, frameKey, false); + FrameReader authenticationIn = new IncomingAuthenticationLayerImpl( + encryptionIn, mac, macKey); + ConnectionReader reader = new ConnectionReaderImpl(authenticationIn); InputStream in1 = reader.getInputStream(); byte[] recovered = new byte[frame.length]; int offset = 0; diff --git a/test/net/sf/briar/transport/FrameWindowImplTest.java b/test/net/sf/briar/transport/FrameWindowImplTest.java deleted file mode 100644 index fc8913befca114f27139d541c02111513e5a8eb5..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/FrameWindowImplTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.FRAME_WINDOW_SIZE; -import net.sf.briar.BriarTestCase; - -import org.junit.Test; - -public class FrameWindowImplTest extends BriarTestCase { - - @Test - public void testWindowSliding() { - FrameWindow w = new FrameWindowImpl(); - for(int i = 0; i < 100; i++) { - assertTrue(w.contains(i)); - assertTrue(w.remove(i)); - assertFalse(w.contains(i)); - } - for(int i = 100; i < 100 + FRAME_WINDOW_SIZE; i++) { - assertTrue(w.contains(i)); - assertFalse(w.isTooHigh(i)); - } - assertFalse(w.contains(100 + FRAME_WINDOW_SIZE)); - assertTrue(w.isTooHigh(100 + FRAME_WINDOW_SIZE)); - } - - @Test - public void testWindowJumping() { - FrameWindow w = new FrameWindowImpl(); - // Base of the window is 0 - for(int i = 0; i < FRAME_WINDOW_SIZE; i++) assertTrue(w.contains(i)); - assertFalse(w.contains(FRAME_WINDOW_SIZE)); - assertFalse(w.isTooHigh(FRAME_WINDOW_SIZE - 1)); - assertTrue(w.isTooHigh(FRAME_WINDOW_SIZE)); - // Remove all numbers except 0 and 5 - for(int i = 1; i < 5; i++) assertTrue(w.remove(i)); - for(int i = 6; i < FRAME_WINDOW_SIZE; i++) assertTrue(w.remove(i)); - // Base of the window should still be 0 - assertTrue(w.contains(0)); - for(int i = 1; i < 5; i++) assertFalse(w.contains(i)); - assertTrue(w.contains(5)); - for(int i = 6; i < FRAME_WINDOW_SIZE; i++) assertFalse(w.contains(i)); - assertFalse(w.contains(FRAME_WINDOW_SIZE)); - assertFalse(w.isTooHigh(FRAME_WINDOW_SIZE - 1)); - assertTrue(w.isTooHigh(FRAME_WINDOW_SIZE)); - // Remove 0 - assertTrue(w.remove(0)); - // Base of the window should now be 5 - for(int i = 0; i < 5; i++) assertFalse(w.contains(i)); - assertTrue(w.contains(5)); - for(int i = 6; i < FRAME_WINDOW_SIZE; i++) assertFalse(w.contains(i)); - for(int i = FRAME_WINDOW_SIZE; i < FRAME_WINDOW_SIZE + 5; i++) { - assertTrue(w.contains(i)); - } - assertFalse(w.contains(FRAME_WINDOW_SIZE + 5)); - assertFalse(w.isTooHigh(FRAME_WINDOW_SIZE + 4)); - assertTrue(w.isTooHigh(FRAME_WINDOW_SIZE + 5)); - // Remove all numbers except 5 - for(int i = FRAME_WINDOW_SIZE; i < FRAME_WINDOW_SIZE + 5; i++) { - assertTrue(w.remove(i)); - } - // Base of the window should still be 5 - assertTrue(w.contains(5)); - for(int i = 6; i < FRAME_WINDOW_SIZE + 5; i++) { - assertFalse(w.contains(i)); - } - assertFalse(w.contains(FRAME_WINDOW_SIZE + 5)); - assertFalse(w.isTooHigh(FRAME_WINDOW_SIZE + 4)); - assertTrue(w.isTooHigh(FRAME_WINDOW_SIZE + 5)); - // Remove 5 - assertTrue(w.remove(5)); - // Base of the window should now be FRAME_WINDOW_SIZE + 5 - for(int i = 0; i < FRAME_WINDOW_SIZE + 5; i++) { - assertFalse(w.contains(i)); - } - for(int i = FRAME_WINDOW_SIZE + 5; i < FRAME_WINDOW_SIZE * 2 + 5; i++) { - assertTrue(w.contains(i)); - } - assertFalse(w.contains(FRAME_WINDOW_SIZE * 2 + 5)); - assertFalse(w.isTooHigh(FRAME_WINDOW_SIZE * 2 + 4)); - assertTrue(w.isTooHigh(FRAME_WINDOW_SIZE * 2 + 5)); - } -} \ No newline at end of file diff --git a/test/net/sf/briar/transport/IncomingEncryptionLayerImplTest.java b/test/net/sf/briar/transport/IncomingEncryptionLayerImplTest.java index 0b34ece3bff1842e8229ce427568de023782d141..58c80823aba6b436d462d340697a56daa57d87d7 100644 --- a/test/net/sf/briar/transport/IncomingEncryptionLayerImplTest.java +++ b/test/net/sf/briar/transport/IncomingEncryptionLayerImplTest.java @@ -12,7 +12,6 @@ import javax.crypto.spec.IvParameterSpec; import net.sf.briar.BriarTestCase; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.transport.Segment; import net.sf.briar.crypto.CryptoModule; import org.apache.commons.io.output.ByteArrayOutputStream; @@ -23,112 +22,106 @@ import com.google.inject.Injector; public class IncomingEncryptionLayerImplTest extends BriarTestCase { - private final Cipher tagCipher, segCipher; - private final ErasableKey tagKey, segKey; + private final Cipher tagCipher, frameCipher; + private final ErasableKey tagKey, frameKey; public IncomingEncryptionLayerImplTest() { super(); Injector i = Guice.createInjector(new CryptoModule()); CryptoComponent crypto = i.getInstance(CryptoComponent.class); tagCipher = crypto.getTagCipher(); - segCipher = crypto.getSegmentCipher(); + frameCipher = crypto.getFrameCipher(); tagKey = crypto.generateTestKey(); - segKey = crypto.generateTestKey(); + frameKey = crypto.generateTestKey(); } @Test - public void testDecryptionWithFirstSegmentTagged() throws Exception { - // Calculate the tag for the first segment + public void testDecryptionWithTag() throws Exception { + // Calculate the tag byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); - // Calculate the ciphertext for the first segment + TagEncoder.encodeTag(tag, tagCipher, tagKey); + // Calculate the ciphertext for the first frame byte[] plaintext = new byte[FRAME_HEADER_LENGTH + 123 + MAC_LENGTH]; HeaderEncoder.encodeHeader(plaintext, 0L, 123, 0); - byte[] iv = IvEncoder.encodeIv(0L, segCipher.getBlockSize()); + byte[] iv = IvEncoder.encodeIv(0L, frameCipher.getBlockSize()); IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext = segCipher.doFinal(plaintext, 0, plaintext.length); - // Calculate the ciphertext for the second segment + frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec); + byte[] ciphertext = frameCipher.doFinal(plaintext, 0, plaintext.length); + // Calculate the ciphertext for the second frame byte[] plaintext1 = new byte[FRAME_HEADER_LENGTH + 1234 + MAC_LENGTH]; HeaderEncoder.encodeHeader(plaintext1, 1L, 1234, 0); IvEncoder.updateIv(iv, 1L); ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext1 = segCipher.doFinal(plaintext1, 0, + frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec); + byte[] ciphertext1 = frameCipher.doFinal(plaintext1, 0, plaintext1.length); - // Concatenate the ciphertexts, excluding the first tag + // Concatenate the ciphertexts, including the tag ByteArrayOutputStream out = new ByteArrayOutputStream(); + out.write(tag); out.write(ciphertext); out.write(ciphertext1); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); // Use the encryption layer to decrypt the ciphertext - IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in, - tagCipher, segCipher, tagKey, segKey, false, false, tag); - // First segment - Segment s = new SegmentImpl(); - assertTrue(decrypter.readSegment(s)); - assertEquals(plaintext.length, s.getLength()); - assertEquals(0L, s.getSegmentNumber()); - byte[] decrypted = s.getBuffer(); + FrameReader decrypter = new IncomingEncryptionLayerImpl(in, tagCipher, + frameCipher, tagKey, frameKey, true); + // First frame + Frame f = new Frame(); + assertTrue(decrypter.readFrame(f)); + assertEquals(plaintext.length, f.getLength()); + byte[] decrypted = f.getBuffer(); + assertEquals(0L, HeaderEncoder.getFrameNumber(decrypted)); for(int i = 0; i < plaintext.length; i++) { assertEquals(plaintext[i], decrypted[i]); } - // Second segment - assertTrue(decrypter.readSegment(s)); - assertEquals(plaintext1.length, s.getLength()); - assertEquals(1L, s.getSegmentNumber()); - decrypted = s.getBuffer(); + // Second frame + assertTrue(decrypter.readFrame(f)); + assertEquals(plaintext1.length, f.getLength()); + decrypted = f.getBuffer(); + assertEquals(1L, HeaderEncoder.getFrameNumber(decrypted)); for(int i = 0; i < plaintext1.length; i++) { assertEquals(plaintext1[i], decrypted[i]); } } @Test - public void testDecryptionWithEverySegmentTagged() throws Exception { - // Calculate the tag for the first segment - byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); - // Calculate the ciphertext for the first segment + public void testDecryptionWithoutTag() throws Exception { + // Calculate the ciphertext for the first frame byte[] plaintext = new byte[FRAME_HEADER_LENGTH + 123 + MAC_LENGTH]; HeaderEncoder.encodeHeader(plaintext, 0L, 123, 0); - byte[] iv = IvEncoder.encodeIv(0L, segCipher.getBlockSize()); + byte[] iv = IvEncoder.encodeIv(0L, frameCipher.getBlockSize()); IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext = segCipher.doFinal(plaintext, 0, plaintext.length); - // Calculate the tag for the second segment - byte[] tag1 = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag1, 1L, tagCipher, tagKey); - // Calculate the ciphertext for the second segment + frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec); + byte[] ciphertext = frameCipher.doFinal(plaintext, 0, plaintext.length); + // Calculate the ciphertext for the second frame byte[] plaintext1 = new byte[FRAME_HEADER_LENGTH + 1234 + MAC_LENGTH]; HeaderEncoder.encodeHeader(plaintext1, 1L, 1234, 0); IvEncoder.updateIv(iv, 1L); ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext1 = segCipher.doFinal(plaintext1, 0, + frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec); + byte[] ciphertext1 = frameCipher.doFinal(plaintext1, 0, plaintext1.length); - // Concatenate the ciphertexts, excluding the first tag + // Concatenate the ciphertexts, excluding the tag ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(ciphertext); - out.write(tag1); out.write(ciphertext1); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); // Use the encryption layer to decrypt the ciphertext - IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in, - tagCipher, segCipher, tagKey, segKey, true, false, tag); - // First segment - Segment s = new SegmentImpl(); - assertTrue(decrypter.readSegment(s)); - assertEquals(plaintext.length, s.getLength()); - assertEquals(0L, s.getSegmentNumber()); - byte[] decrypted = s.getBuffer(); + FrameReader decrypter = new IncomingEncryptionLayerImpl(in, tagCipher, + frameCipher, tagKey, frameKey, false); + // First frame + Frame f = new Frame(); + assertTrue(decrypter.readFrame(f)); + assertEquals(plaintext.length, f.getLength()); + byte[] decrypted = f.getBuffer(); + assertEquals(0L, HeaderEncoder.getFrameNumber(decrypted)); for(int i = 0; i < plaintext.length; i++) { assertEquals(plaintext[i], decrypted[i]); } - // Second segment - assertTrue(decrypter.readSegment(s)); - assertEquals(plaintext1.length, s.getLength()); - assertEquals(1L, s.getSegmentNumber()); - decrypted = s.getBuffer(); + // Second frame + assertTrue(decrypter.readFrame(f)); + assertEquals(plaintext1.length, f.getLength()); + assertEquals(1L, HeaderEncoder.getFrameNumber(decrypted)); + decrypted = f.getBuffer(); for(int i = 0; i < plaintext1.length; i++) { assertEquals(plaintext1[i], decrypted[i]); } diff --git a/test/net/sf/briar/transport/IncomingErrorCorrectionLayerImplTest.java b/test/net/sf/briar/transport/IncomingErrorCorrectionLayerImplTest.java deleted file mode 100644 index f6f507bb55aad999f154cbce0374c6142464a9a2..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/IncomingErrorCorrectionLayerImplTest.java +++ /dev/null @@ -1,168 +0,0 @@ -package net.sf.briar.transport; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.Map; - -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.FormatException; -import net.sf.briar.api.transport.Segment; - -import org.jmock.Expectations; -import org.jmock.Mockery; -import org.junit.Test; - -public class IncomingErrorCorrectionLayerImplTest extends BriarTestCase { - - @Test - public void testDiscardedSegmentsAreCounted() throws Exception { - LinkedList<Long> segmentNumbers = new LinkedList<Long>(); - segmentNumbers.add(123L); // 123 / 3 = frame number 41 - segmentNumbers.add(456L); // 456 / 3 = frame number 152 - segmentNumbers.add(0L); // 0 / 3 = frame number 0 - IncomingEncryptionLayer in = new TestIncomingEncryptionLayer( - segmentNumbers, 1234); - Mockery context = new Mockery(); - final ErasureDecoder decoder = context.mock(ErasureDecoder.class); - final FrameWindow window = context.mock(FrameWindow.class); - context.checking(new Expectations() {{ - // First segment - one(window).contains(41L); - will(returnValue(false)); - one(window).isTooHigh(41L); - will(returnValue(true)); - // Second segment - one(window).contains(152L); - will(returnValue(false)); - one(window).isTooHigh(152L); - will(returnValue(true)); - // Third segment - one(window).contains(0L); - will(returnValue(true)); - one(decoder).decodeFrame(with(any(Frame.class)), - with(any(Segment[].class))); - will(returnValue(false)); - }}); - - IncomingErrorCorrectionLayerImpl err = - new IncomingErrorCorrectionLayerImpl(in, decoder, 3, 2); - Frame f = new Frame(); - assertFalse(err.readFrame(f, window)); - Map<Long, Integer> discardCounts = err.getDiscardCounts(); - assertEquals(2, discardCounts.size()); - assertEquals(Integer.valueOf(1), discardCounts.get(41L)); - assertEquals(Integer.valueOf(1), discardCounts.get(152L)); - - context.assertIsSatisfied(); - } - - @Test - public void testTooManyDiscardedSegmentsCauseException() throws Exception { - LinkedList<Long> segmentNumbers = new LinkedList<Long>(); - segmentNumbers.add(123L); // 123 / 3 = frame number 41 - segmentNumbers.add(124L); // 124 / 3 = frame number 41 - IncomingEncryptionLayer in = new TestIncomingEncryptionLayer( - segmentNumbers, 1234); - Mockery context = new Mockery(); - final ErasureDecoder decoder = context.mock(ErasureDecoder.class); - final FrameWindow window = context.mock(FrameWindow.class); - context.checking(new Expectations() {{ - // First segment - one(window).contains(41L); - will(returnValue(false)); - one(window).isTooHigh(41L); - will(returnValue(true)); - // Second segment - one(window).contains(41L); - will(returnValue(false)); - one(window).isTooHigh(41L); - will(returnValue(true)); - }}); - IncomingErrorCorrectionLayerImpl err = - new IncomingErrorCorrectionLayerImpl(in, decoder, 3, 2); - Frame f = new Frame(); - try { - err.readFrame(f, window); - fail(); - } catch(FormatException expected) {} - - context.assertIsSatisfied(); - } - - @Test - public void testSetsAndDiscardedSegmentsAreFreed() throws Exception { - LinkedList<Long> segmentNumbers = new LinkedList<Long>(); - segmentNumbers.add(96L); // 96 / 3 = frame number 32 - segmentNumbers.add(0L); // 0 / 3 = frame number 0 - segmentNumbers.add(1L); // 1 / 3 = frame number 0 - IncomingEncryptionLayer in = new TestIncomingEncryptionLayer( - segmentNumbers, 1234); - Mockery context = new Mockery(); - final ErasureDecoder decoder = context.mock(ErasureDecoder.class); - final FrameWindow window = context.mock(FrameWindow.class); - context.checking(new Expectations() {{ - // First segment - one(window).contains(32L); - will(returnValue(false)); - one(window).isTooHigh(32L); - will(returnValue(true)); - // Second segment - one(window).contains(0L); - will(returnValue(true)); - one(decoder).decodeFrame(with(any(Frame.class)), - with(any(Segment[].class))); - will(returnValue(false)); - // Third segment - one(window).contains(0L); - will(returnValue(true)); - one(decoder).decodeFrame(with(any(Frame.class)), - with(any(Segment[].class))); - will(returnValue(true)); - // Second call, new window - one(window).contains(0L); - will(returnValue(false)); - one(window).isTooHigh(32L); - will(returnValue(false)); - }}); - IncomingErrorCorrectionLayerImpl err = - new IncomingErrorCorrectionLayerImpl(in, decoder, 3, 2); - Frame f = new Frame(); - // The first call discards one segment and decodes two - assertTrue(err.readFrame(f, window)); - // The second call reaches EOF - assertFalse(err.readFrame(f, window)); - // The segment set and discard count should have been freed - Map<Long, Segment[]> segmentSets = err.getSegmentSets(); - assertTrue(segmentSets.isEmpty()); - Map<Long, Integer> discardCounts = err.getDiscardCounts(); - assertTrue(discardCounts.isEmpty()); - - context.assertIsSatisfied(); - } - - private static class TestIncomingEncryptionLayer - implements IncomingEncryptionLayer { - - private final LinkedList<Long> segmentNumbers; - private final int length; - - private TestIncomingEncryptionLayer(LinkedList<Long> segmentNumbers, - int length) { - this.segmentNumbers = segmentNumbers; - this.length = length; - } - - public boolean readSegment(Segment s) throws IOException, - InvalidDataException { - Long segmentNumber = segmentNumbers.poll(); - if(segmentNumber == null) return false; - s.setSegmentNumber(segmentNumber); - s.setLength(length); - return true; - } - - public int getMaxSegmentLength() { - return length; - } - } -} diff --git a/test/net/sf/briar/transport/IncomingReliabilityLayerImplTest.java b/test/net/sf/briar/transport/IncomingReliabilityLayerImplTest.java deleted file mode 100644 index 23bba20b49cbe278bbd0ae45a0b17e5003707597..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/IncomingReliabilityLayerImplTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.FRAME_WINDOW_SIZE; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.transport.ConnectionReader; - -import org.junit.Test; - -public class IncomingReliabilityLayerImplTest extends BriarTestCase { - - @Test - public void testNoReordering() throws Exception { - List<Integer> frameNumbers = new ArrayList<Integer>(); - // Receive FRAME_WINDOW_SIZE * 2 frames in the correct order - for(int i = 0; i < FRAME_WINDOW_SIZE * 2; i++) frameNumbers.add(i); - IncomingAuthenticationLayer authentication = - new TestIncomingAuthenticationLayer(frameNumbers); - IncomingReliabilityLayerImpl reliability = - new IncomingReliabilityLayerImpl(authentication); - ConnectionReader reader = new ConnectionReaderImpl(reliability, false, - false); - InputStream in = reader.getInputStream(); - for(int i = 0; i < FRAME_WINDOW_SIZE * 2; i++) { - for(int j = 0; j < 100; j++) assertEquals(i, in.read()); - } - assertEquals(-1, in.read()); - // No free frames should be cached - assertEquals(0, reliability.getFreeFramesCount()); - } - - @Test - public void testReordering() throws Exception { - List<Integer> frameNumbers = new ArrayList<Integer>(); - // Receive the first FRAME_WINDOW_SIZE frames in a random order - for(int i = 0; i < FRAME_WINDOW_SIZE; i++) frameNumbers.add(i); - Collections.shuffle(frameNumbers); - // Receive the next FRAME_WINDOW_SIZE frames in the correct order - for(int i = FRAME_WINDOW_SIZE; i < FRAME_WINDOW_SIZE * 2; i++) { - frameNumbers.add(i); - } - // The reliability layer should reorder the frames - IncomingAuthenticationLayer authentication = - new TestIncomingAuthenticationLayer(frameNumbers); - IncomingReliabilityLayerImpl reliability = - new IncomingReliabilityLayerImpl(authentication); - ConnectionReader reader = new ConnectionReaderImpl(reliability, false, - false); - InputStream in = reader.getInputStream(); - for(int i = 0; i < FRAME_WINDOW_SIZE * 2; i++) { - for(int j = 0; j < 100; j++) assertEquals(i, in.read()); - } - assertEquals(-1, in.read()); - // Fewer than FRAME_WINDOW_SIZE free frames should be cached - assertTrue(reliability.getFreeFramesCount() < 32); - } - - private static class TestIncomingAuthenticationLayer - implements IncomingAuthenticationLayer { - - private final List<Integer> frameNumbers; - - private int index; - - private TestIncomingAuthenticationLayer(List<Integer> frameNumbers) { - this.frameNumbers = frameNumbers; - index = 0; - } - - public boolean readFrame(Frame f, FrameWindow window) { - if(index >= frameNumbers.size()) return false; - int frameNumber = frameNumbers.get(index); - assertTrue(window.contains(frameNumber)); - index++; - byte[] buf = f.getBuffer(); - HeaderEncoder.encodeHeader(buf, frameNumber, 100, 0); - for(int i = 0; i < 100; i++) { - buf[FRAME_HEADER_LENGTH + i] = (byte) frameNumber; - } - f.setLength(FRAME_HEADER_LENGTH + 100 + MAC_LENGTH); - return true; - } - - public int getMaxFrameLength() { - return FRAME_HEADER_LENGTH + 100 + MAC_LENGTH; - } - } -} diff --git a/test/net/sf/briar/transport/NullIncomingEncryptionLayer.java b/test/net/sf/briar/transport/NullIncomingEncryptionLayer.java index dd244eeaffc0a43b89cfdcac11d0ab8fa294b5e6..dcf0386702c2eced15b8afb961f28bc259890f9e 100644 --- a/test/net/sf/briar/transport/NullIncomingEncryptionLayer.java +++ b/test/net/sf/briar/transport/NullIncomingEncryptionLayer.java @@ -3,29 +3,24 @@ package net.sf.briar.transport; import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import net.sf.briar.api.FormatException; -import net.sf.briar.api.transport.Segment; /** An encryption layer that performs no encryption. */ -class NullIncomingEncryptionLayer implements IncomingEncryptionLayer { +class NullIncomingEncryptionLayer implements FrameReader { private final InputStream in; - private long segmentNumber = 0L; - NullIncomingEncryptionLayer(InputStream in) { this.in = in; } - public boolean readSegment(Segment s) throws IOException { - byte[] buf = s.getBuffer(); + public boolean readFrame(Frame f) throws IOException { + byte[] buf = f.getBuffer(); // Read the frame header int offset = 0, length = FRAME_HEADER_LENGTH; while(offset < length) { @@ -47,12 +42,7 @@ class NullIncomingEncryptionLayer implements IncomingEncryptionLayer { if(read == -1) throw new EOFException(); offset += read; } - s.setLength(length); - s.setSegmentNumber(segmentNumber++); + f.setLength(length); return true; } - - public int getMaxSegmentLength() { - return MAX_SEGMENT_LENGTH - TAG_LENGTH; - } } diff --git a/test/net/sf/briar/transport/NullOutgoingEncryptionLayer.java b/test/net/sf/briar/transport/NullOutgoingEncryptionLayer.java index 88921aff0321f7ca4ac996c0fc56972be0beb21e..598562877bcdf93c99c4dcc0df74805d663a0523 100644 --- a/test/net/sf/briar/transport/NullOutgoingEncryptionLayer.java +++ b/test/net/sf/briar/transport/NullOutgoingEncryptionLayer.java @@ -1,15 +1,10 @@ package net.sf.briar.transport; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; - import java.io.IOException; import java.io.OutputStream; -import net.sf.briar.api.transport.Segment; - /** An encryption layer that performs no encryption. */ -class NullOutgoingEncryptionLayer implements OutgoingEncryptionLayer { +class NullOutgoingEncryptionLayer implements FrameWriter { private final OutputStream out; @@ -25,9 +20,9 @@ class NullOutgoingEncryptionLayer implements OutgoingEncryptionLayer { this.capacity = capacity; } - public void writeSegment(Segment s) throws IOException { - out.write(s.getBuffer(), 0, s.getLength()); - capacity -= s.getLength(); + public void writeFrame(Frame f) throws IOException { + out.write(f.getBuffer(), 0, f.getLength()); + capacity -= f.getLength(); } public void flush() throws IOException { @@ -37,8 +32,4 @@ class NullOutgoingEncryptionLayer implements OutgoingEncryptionLayer { public long getRemainingCapacity() { return capacity; } - - public int getMaxSegmentLength() { - return MAX_SEGMENT_LENGTH - TAG_LENGTH; - } } diff --git a/test/net/sf/briar/transport/OutgoingEncryptionLayerImplTest.java b/test/net/sf/briar/transport/OutgoingEncryptionLayerImplTest.java index a535725385ddb5be3898503f3c1daf4f2c55986f..aca3f7192be20c26a4d5867e29542abaf7156abf 100644 --- a/test/net/sf/briar/transport/OutgoingEncryptionLayerImplTest.java +++ b/test/net/sf/briar/transport/OutgoingEncryptionLayerImplTest.java @@ -11,7 +11,6 @@ import javax.crypto.spec.IvParameterSpec; import net.sf.briar.BriarTestCase; import net.sf.briar.api.crypto.CryptoComponent; import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.transport.Segment; import net.sf.briar.crypto.CryptoModule; import org.junit.Test; @@ -23,36 +22,36 @@ public class OutgoingEncryptionLayerImplTest extends BriarTestCase { private static final int MAC_LENGTH = 32; - private final Cipher tagCipher, segCipher; - private final ErasableKey tagKey, segKey; + private final Cipher tagCipher, frameCipher; + private final ErasableKey tagKey, frameKey; public OutgoingEncryptionLayerImplTest() { super(); Injector i = Guice.createInjector(new CryptoModule()); CryptoComponent crypto = i.getInstance(CryptoComponent.class); tagCipher = crypto.getTagCipher(); - segCipher = crypto.getSegmentCipher(); + frameCipher = crypto.getFrameCipher(); tagKey = crypto.generateTestKey(); - segKey = crypto.generateTestKey(); + frameKey = crypto.generateTestKey(); } @Test - public void testEncryptionWithFirstSegmentTagged() throws Exception { + public void testEncryptionWithTag() throws Exception { // Calculate the expected tag byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); - // Calculate the expected ciphertext for the first segment - byte[] iv = new byte[segCipher.getBlockSize()]; + TagEncoder.encodeTag(tag, tagCipher, tagKey); + // Calculate the expected ciphertext for the first frame + byte[] iv = new byte[frameCipher.getBlockSize()]; byte[] plaintext = new byte[123 + MAC_LENGTH]; IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext = segCipher.doFinal(plaintext); - // Calculate the expected ciphertext for the second segment + frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec); + byte[] ciphertext = frameCipher.doFinal(plaintext); + // Calculate the expected ciphertext for the second frame byte[] plaintext1 = new byte[1234 + MAC_LENGTH]; IvEncoder.updateIv(iv, 1L); ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext1 = segCipher.doFinal(plaintext1); + frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec); + byte[] ciphertext1 = frameCipher.doFinal(plaintext1); // Concatenate the ciphertexts ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(tag); @@ -61,65 +60,15 @@ public class OutgoingEncryptionLayerImplTest extends BriarTestCase { byte[] expected = out.toByteArray(); // Use the encryption layer to encrypt the plaintext out.reset(); - OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out, - Long.MAX_VALUE, tagCipher, segCipher, tagKey, segKey, - false); - Segment s = new SegmentImpl(); - System.arraycopy(plaintext, 0, s.getBuffer(), 0, plaintext.length); - s.setLength(plaintext.length); - s.setSegmentNumber(0L); - encrypter.writeSegment(s); - System.arraycopy(plaintext1, 0, s.getBuffer(), 0, plaintext1.length); - s.setLength(plaintext1.length); - s.setSegmentNumber(1L); - encrypter.writeSegment(s); - byte[] actual = out.toByteArray(); - // Check that the actual ciphertext matches the expected ciphertext - assertArrayEquals(expected, actual); - assertEquals(Long.MAX_VALUE - actual.length, - encrypter.getRemainingCapacity()); - } - - @Test - public void testEncryptionWithEverySegmentTagged() throws Exception { - // Calculate the expected tag for the first segment - byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); - // Calculate the expected ciphertext for the first segment - byte[] iv = new byte[segCipher.getBlockSize()]; - byte[] plaintext = new byte[123 + MAC_LENGTH]; - IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext = segCipher.doFinal(plaintext); - // Calculate the expected tag for the second segment - byte[] tag1 = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag1, 1L, tagCipher, tagKey); - // Calculate the expected ciphertext for the second segment - byte[] plaintext1 = new byte[1234 + MAC_LENGTH]; - IvEncoder.updateIv(iv, 1L); - ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext1 = segCipher.doFinal(plaintext1); - // Concatenate the ciphertexts - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write(tag); - out.write(ciphertext); - out.write(tag1); - out.write(ciphertext1); - byte[] expected = out.toByteArray(); - // Use the encryption layer to encrypt the plaintext - out.reset(); - OutgoingEncryptionLayer encrypter = new OutgoingEncryptionLayerImpl(out, - Long.MAX_VALUE, tagCipher, segCipher, tagKey, segKey, true); - Segment s = new SegmentImpl(); - System.arraycopy(plaintext, 0, s.getBuffer(), 0, plaintext.length); - s.setLength(plaintext.length); - s.setSegmentNumber(0L); - encrypter.writeSegment(s); - System.arraycopy(plaintext1, 0, s.getBuffer(), 0, plaintext1.length); - s.setLength(plaintext1.length); - s.setSegmentNumber(1L); - encrypter.writeSegment(s); + FrameWriter encrypter = new OutgoingEncryptionLayerImpl(out, + Long.MAX_VALUE, tagCipher, frameCipher, tagKey, frameKey); + Frame f = new Frame(); + System.arraycopy(plaintext, 0, f.getBuffer(), 0, plaintext.length); + f.setLength(plaintext.length); + encrypter.writeFrame(f); + System.arraycopy(plaintext1, 0, f.getBuffer(), 0, plaintext1.length); + f.setLength(plaintext1.length); + encrypter.writeFrame(f); byte[] actual = out.toByteArray(); // Check that the actual ciphertext matches the expected ciphertext assertArrayEquals(expected, actual); diff --git a/test/net/sf/briar/transport/SegmentedIncomingEncryptionLayerTest.java b/test/net/sf/briar/transport/SegmentedIncomingEncryptionLayerTest.java deleted file mode 100644 index 2e8321d6e30f651dc704922bed25e33a5084ad89..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/SegmentedIncomingEncryptionLayerTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; - -import java.io.IOException; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; - -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.plugins.SegmentSource; -import net.sf.briar.api.transport.Segment; -import net.sf.briar.crypto.CryptoModule; - -import org.junit.Test; - -import com.google.inject.Guice; -import com.google.inject.Injector; - -public class SegmentedIncomingEncryptionLayerTest extends BriarTestCase { - - private final Cipher tagCipher, segCipher; - private final ErasableKey tagKey, segKey; - - public SegmentedIncomingEncryptionLayerTest() { - super(); - Injector i = Guice.createInjector(new CryptoModule()); - CryptoComponent crypto = i.getInstance(CryptoComponent.class); - tagCipher = crypto.getTagCipher(); - segCipher = crypto.getSegmentCipher(); - tagKey = crypto.generateTestKey(); - segKey = crypto.generateTestKey(); - } - - @Test - public void testDecryptionWithFirstSegmentTagged() throws Exception { - // Calculate the ciphertext for the first segment, including its tag - byte[] plaintext = new byte[FRAME_HEADER_LENGTH + 123 + MAC_LENGTH]; - HeaderEncoder.encodeHeader(plaintext, 0L, 123, 0); - byte[] ciphertext = new byte[TAG_LENGTH + plaintext.length]; - TagEncoder.encodeTag(ciphertext, 0L, tagCipher, tagKey); - byte[] iv = IvEncoder.encodeIv(0L, segCipher.getBlockSize()); - IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - segCipher.doFinal(plaintext, 0, plaintext.length, ciphertext, - TAG_LENGTH); - // Calculate the ciphertext for the second segment - byte[] plaintext1 = new byte[FRAME_HEADER_LENGTH + 1234 + MAC_LENGTH]; - HeaderEncoder.encodeHeader(plaintext1, 1L, 1234, 0); - IvEncoder.updateIv(iv, 1L); - ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext1 = segCipher.doFinal(plaintext1, 0, - plaintext1.length); - // Buffer the first segment and create a source for the second - Segment buffered = new SegmentImpl(); - System.arraycopy(ciphertext, 0, buffered.getBuffer(), 0, - ciphertext.length); - buffered.setLength(ciphertext.length); - SegmentSource in = new ByteArraySegmentSource(ciphertext1); - // Use the encryption layer to decrypt the ciphertext - IncomingEncryptionLayer decrypter = - new SegmentedIncomingEncryptionLayer(in, tagCipher, segCipher, - tagKey, segKey, false, false, buffered); - // First segment - Segment s = new SegmentImpl(); - assertTrue(decrypter.readSegment(s)); - assertEquals(plaintext.length, s.getLength()); - assertEquals(0L, s.getSegmentNumber()); - byte[] decrypted = s.getBuffer(); - for(int i = 0; i < plaintext.length; i++) { - assertEquals(plaintext[i], decrypted[i]); - } - // Second segment - assertTrue(decrypter.readSegment(s)); - assertEquals(plaintext1.length, s.getLength()); - assertEquals(1L, s.getSegmentNumber()); - decrypted = s.getBuffer(); - for(int i = 0; i < plaintext1.length; i++) { - assertEquals(plaintext1[i], decrypted[i]); - } - } - - @Test - public void testDecryptionWithEverySegmentTagged() throws Exception { - // Calculate the ciphertext for the first segment, including its tag - byte[] plaintext = new byte[FRAME_HEADER_LENGTH + 123 + MAC_LENGTH]; - HeaderEncoder.encodeHeader(plaintext, 0L, 123, 0); - byte[] ciphertext = new byte[TAG_LENGTH + plaintext.length]; - TagEncoder.encodeTag(ciphertext, 0L, tagCipher, tagKey); - byte[] iv = IvEncoder.encodeIv(0L, segCipher.getBlockSize()); - IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - segCipher.doFinal(plaintext, 0, plaintext.length, ciphertext, - TAG_LENGTH); - // Calculate the ciphertext for the second frame, including its tag - byte[] plaintext1 = new byte[FRAME_HEADER_LENGTH + 1234 + MAC_LENGTH]; - HeaderEncoder.encodeHeader(plaintext1, 1L, 1234, 0); - byte[] ciphertext1 = new byte[TAG_LENGTH + plaintext1.length]; - TagEncoder.encodeTag(ciphertext1, 1L, tagCipher, tagKey); - IvEncoder.updateIv(iv, 1L); - ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - segCipher.doFinal(plaintext1, 0, plaintext1.length, ciphertext1, - TAG_LENGTH); - // Buffer the first segment and create a source for the second - Segment buffered = new SegmentImpl(); - System.arraycopy(ciphertext, 0, buffered.getBuffer(), 0, - ciphertext.length); - buffered.setLength(ciphertext.length); - SegmentSource in = new ByteArraySegmentSource(ciphertext1); - // Use the encryption layer to decrypt the ciphertext - IncomingEncryptionLayer decrypter = - new SegmentedIncomingEncryptionLayer(in, tagCipher, segCipher, - tagKey, segKey, true, false, buffered); - // First segment - Segment s = new SegmentImpl(); - assertTrue(decrypter.readSegment(s)); - assertEquals(plaintext.length, s.getLength()); - assertEquals(0L, s.getSegmentNumber()); - byte[] decrypted = s.getBuffer(); - for(int i = 0; i < plaintext.length; i++) { - assertEquals(plaintext[i], decrypted[i]); - } - // Second segment - assertTrue(decrypter.readSegment(s)); - assertEquals(plaintext1.length, s.getLength()); - assertEquals(1L, s.getSegmentNumber()); - decrypted = s.getBuffer(); - for(int i = 0; i < plaintext1.length; i++) { - assertEquals(plaintext1[i], decrypted[i]); - } - } - - private static class ByteArraySegmentSource implements SegmentSource { - - private final byte[] segment; - - private ByteArraySegmentSource(byte[] segment) { - this.segment = segment; - } - - public boolean readSegment(Segment s) throws IOException { - System.arraycopy(segment, 0, s.getBuffer(), 0, segment.length); - s.setLength(segment.length); - return true; - } - - public int getMaxSegmentLength() { - return MAX_SEGMENT_LENGTH; - } - } -} diff --git a/test/net/sf/briar/transport/SegmentedOutgoingEncryptionLayerTest.java b/test/net/sf/briar/transport/SegmentedOutgoingEncryptionLayerTest.java deleted file mode 100644 index 3d6e5cae31056e168f829fc5db6cf9decc256143..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/SegmentedOutgoingEncryptionLayerTest.java +++ /dev/null @@ -1,145 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; -import static org.junit.Assert.assertArrayEquals; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; - -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.ErasableKey; -import net.sf.briar.api.plugins.SegmentSink; -import net.sf.briar.api.transport.Segment; -import net.sf.briar.crypto.CryptoModule; - -import org.junit.Test; - -import com.google.inject.Guice; -import com.google.inject.Injector; - -public class SegmentedOutgoingEncryptionLayerTest extends BriarTestCase { - - private static final int MAC_LENGTH = 32; - - private final Cipher tagCipher, segCipher; - private final ErasableKey tagKey, segKey; - - public SegmentedOutgoingEncryptionLayerTest() { - super(); - Injector i = Guice.createInjector(new CryptoModule()); - CryptoComponent crypto = i.getInstance(CryptoComponent.class); - tagCipher = crypto.getTagCipher(); - segCipher = crypto.getSegmentCipher(); - tagKey = crypto.generateTestKey(); - segKey = crypto.generateTestKey(); - } - - @Test - public void testEncryptionWithFirstSegmentTagged() throws Exception { - // Calculate the expected tag - byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); - // Calculate the expected ciphertext for the first segment - byte[] iv = new byte[segCipher.getBlockSize()]; - byte[] plaintext = new byte[123 + MAC_LENGTH]; - IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext = segCipher.doFinal(plaintext); - // Calculate the expected ciphertext for the second segment - byte[] plaintext1 = new byte[1234 + MAC_LENGTH]; - IvEncoder.updateIv(iv, 1L); - ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext1 = segCipher.doFinal(plaintext1); - // Concatenate the ciphertexts - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write(tag); - out.write(ciphertext); - out.write(ciphertext1); - byte[] expected = out.toByteArray(); - // Use the encryption layer to encrypt the plaintext - ByteArraySegmentSink sink = new ByteArraySegmentSink(); - OutgoingEncryptionLayer encrypter = - new SegmentedOutgoingEncryptionLayer(sink, Long.MAX_VALUE, - tagCipher, segCipher, tagKey, segKey, false, false); - Segment s = new SegmentImpl(); - System.arraycopy(plaintext, 0, s.getBuffer(), 0, plaintext.length); - s.setLength(plaintext.length); - s.setSegmentNumber(0L); - encrypter.writeSegment(s); - System.arraycopy(plaintext1, 0, s.getBuffer(), 0, plaintext1.length); - s.setLength(plaintext1.length); - s.setSegmentNumber(1L); - encrypter.writeSegment(s); - byte[] actual = out.toByteArray(); - // Check that the actual ciphertext matches the expected ciphertext - assertArrayEquals(expected, actual); - assertEquals(Long.MAX_VALUE - actual.length, - encrypter.getRemainingCapacity()); - } - - @Test - public void testEncryptionWithEverySegmentTagged() throws Exception { - // Calculate the expected tag for the first segment - byte[] tag = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag, 0L, tagCipher, tagKey); - // Calculate the expected ciphertext for the first segment - byte[] iv = new byte[segCipher.getBlockSize()]; - byte[] plaintext = new byte[123 + MAC_LENGTH]; - IvParameterSpec ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext = segCipher.doFinal(plaintext); - // Calculate the expected tag for the second segment - byte[] tag1 = new byte[TAG_LENGTH]; - TagEncoder.encodeTag(tag1, 1L, tagCipher, tagKey); - // Calculate the expected ciphertext for the second segment - byte[] plaintext1 = new byte[1234 + MAC_LENGTH]; - IvEncoder.updateIv(iv, 1L); - ivSpec = new IvParameterSpec(iv); - segCipher.init(Cipher.ENCRYPT_MODE, segKey, ivSpec); - byte[] ciphertext1 = segCipher.doFinal(plaintext1); - // Concatenate the ciphertexts - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write(tag); - out.write(ciphertext); - out.write(tag1); - out.write(ciphertext1); - byte[] expected = out.toByteArray(); - // Use the encryption layer to encrypt the plaintext - SegmentSink sink = new ByteArraySegmentSink(); - OutgoingEncryptionLayer encrypter = - new SegmentedOutgoingEncryptionLayer(sink, Long.MAX_VALUE, - tagCipher, segCipher, tagKey, segKey, true, false); - Segment s = new SegmentImpl(); - System.arraycopy(plaintext, 0, s.getBuffer(), 0, plaintext.length); - s.setLength(plaintext.length); - s.setSegmentNumber(0L); - encrypter.writeSegment(s); - System.arraycopy(plaintext1, 0, s.getBuffer(), 0, plaintext1.length); - s.setLength(plaintext1.length); - s.setSegmentNumber(1L); - encrypter.writeSegment(s); - byte[] actual = out.toByteArray(); - // Check that the actual ciphertext matches the expected ciphertext - assertArrayEquals(expected, actual); - assertEquals(Long.MAX_VALUE - actual.length, - encrypter.getRemainingCapacity()); - } - - private static class ByteArraySegmentSink extends ByteArrayOutputStream - implements SegmentSink { - - public void writeSegment(Segment s) throws IOException { - write(s.getBuffer(), 0, s.getLength()); - } - - public int getMaxSegmentLength() { - return MAX_SEGMENT_LENGTH; - } - } -} diff --git a/test/net/sf/briar/transport/XorErasureCodeTest.java b/test/net/sf/briar/transport/XorErasureCodeTest.java deleted file mode 100644 index 0fa4158ffd0e8ac79d7f2b9c112c60c80712a20e..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/XorErasureCodeTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; -import static org.junit.Assert.assertArrayEquals; - -import java.util.Random; - -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.transport.Segment; - -import org.junit.Test; - -public class XorErasureCodeTest extends BriarTestCase { - - @Test - public void testEncodingAndDecodingWithAllSegments() throws Exception { - XorErasureEncoder e = new XorErasureEncoder(5); - XorErasureDecoder d = new XorErasureDecoder(5, false); - Frame f = new Frame(1234); - new Random().nextBytes(f.getBuffer()); - int payload = 1234 - FRAME_HEADER_LENGTH - MAC_LENGTH; - HeaderEncoder.encodeHeader(f.getBuffer(), 0L, payload, 0); - f.setLength(1234); - Segment[] set = e.encodeFrame(f); - assertEquals(5, set.length); - Frame f1 = new Frame(1234); - assertTrue(d.decodeFrame(f1, set)); - assertArrayEquals(f.getBuffer(), f1.getBuffer()); - } - - @Test - public void testEncodingAndDecodingWithMissingSegment() throws Exception { - XorErasureEncoder e = new XorErasureEncoder(5); - XorErasureDecoder d = new XorErasureDecoder(5, false); - Frame f = new Frame(1234); - new Random().nextBytes(f.getBuffer()); - int payload = 1234 - FRAME_HEADER_LENGTH - MAC_LENGTH; - HeaderEncoder.encodeHeader(f.getBuffer(), 0L, payload, 0); - f.setLength(1234); - for(int i = 0; i < 5; i++) { - Segment[] set = e.encodeFrame(f); - assertEquals(5, set.length); - set[i] = null; - Frame f1 = new Frame(1234); - assertTrue(d.decodeFrame(f1, set)); - assertArrayEquals(f.getBuffer(), f1.getBuffer()); - } - } -} diff --git a/test/net/sf/briar/transport/XorErasureDecoderTest.java b/test/net/sf/briar/transport/XorErasureDecoderTest.java deleted file mode 100644 index 40346866476e5a6da8a1d081bc83190481e11b7c..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/XorErasureDecoderTest.java +++ /dev/null @@ -1,94 +0,0 @@ -package net.sf.briar.transport; - -import static net.sf.briar.api.transport.TransportConstants.FRAME_HEADER_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH; -import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; -import static org.junit.Assert.assertArrayEquals; -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.FormatException; -import net.sf.briar.api.transport.Segment; - -import org.junit.Test; - -public class XorErasureDecoderTest extends BriarTestCase { - - @Test - public void testMaximumLength() throws Exception { - XorErasureDecoder d = new XorErasureDecoder(5, false); - // A frame of the maximum length should be decoded successfully - Segment[] set = encodeEmptyFrame(MAX_FRAME_LENGTH / 4, 5); - Frame f = new Frame(); - assertTrue(d.decodeFrame(f, set)); - checkFrame(f, MAX_FRAME_LENGTH); - // A frame larger than the maximum length should not be decoded - set = encodeEmptyFrame(MAX_FRAME_LENGTH / 4 + 1, 5); - f = new Frame(); - try { - d.decodeFrame(f, set); - } catch(FormatException expected) {} - } - - @Test - public void testMinimumLengthIsUsed() throws Exception { - Segment[] set = encodeEmptyFrame(250, 4); - // Replace one of the pieces with a longer piece - byte[] b = set[1].getBuffer(); - assertArrayEquals(new byte[250], b); - set[1] = new SegmentImpl(251); - set[1].setLength(251); - // The frame should be decoded successfully - XorErasureDecoder d = new XorErasureDecoder(4, false); - Frame f = new Frame(750); - assertTrue(d.decodeFrame(f, set)); - // The minimum of the segments' lengths should have been used - assertEquals(750, f.getLength()); - } - - @Test - public void testDecodingWithMissingSegment() throws Exception { - XorErasureDecoder d = new XorErasureDecoder(4, false); - for(int i = 0; i < 4; i++) { - Segment[] set = encodeEmptyFrame(250, 4); - set[i] = null; - // The frame should be decoded successfully - Frame f = new Frame(750); - assertTrue(d.decodeFrame(f, set)); - checkFrame(f, 750); - } - } - - @Test - public void testDecodingWithTwoMissingSegments() throws Exception { - XorErasureDecoder d = new XorErasureDecoder(4, false); - Segment[] set = encodeEmptyFrame(250, 4); - set[0] = null; - set[1] = null; - Frame f = new Frame(750); - assertFalse(d.decodeFrame(f, set)); - } - - private Segment[] encodeEmptyFrame(int length, int n) { - Segment[] set = new Segment[n]; - for(int i = 0; i < n; i++) { - set[i] = new SegmentImpl(length); - set[i].setLength(length); - } - int payload = length * (n - 1) - FRAME_HEADER_LENGTH - MAC_LENGTH; - HeaderEncoder.encodeHeader(set[0].getBuffer(), 0L, payload, 0); - HeaderEncoder.encodeHeader(set[n - 1].getBuffer(), 0L, payload, 0); - return set; - } - - private void checkFrame(Frame f, int length) { - byte[] b = f.getBuffer(); - assertEquals(0L, HeaderEncoder.getFrameNumber(b)); - int payload = length - FRAME_HEADER_LENGTH - MAC_LENGTH; - assertEquals(payload, HeaderEncoder.getPayloadLength(b)); - assertEquals(0, HeaderEncoder.getPaddingLength(b)); - // Check the body - assertEquals(length, f.getLength()); - for(int i = FRAME_HEADER_LENGTH; i < length; i++) { - assertEquals("" + i, 0, b[i]); - } - } -} diff --git a/test/net/sf/briar/transport/XorErasureEncoderTest.java b/test/net/sf/briar/transport/XorErasureEncoderTest.java deleted file mode 100644 index af67c0b644d28c8536b95eac1054f900532cdcdd..0000000000000000000000000000000000000000 --- a/test/net/sf/briar/transport/XorErasureEncoderTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.sf.briar.transport; - -import static org.junit.Assert.assertArrayEquals; -import net.sf.briar.BriarTestCase; -import net.sf.briar.api.transport.Segment; - -import org.junit.Test; - -public class XorErasureEncoderTest extends BriarTestCase { - - @Test - public void testEncoding() { - // Create a frame - Frame f = new Frame(); - f.setLength(200); - byte[] b = f.getBuffer(); - for(int i = 0; i < 200; i++) b[i] = (byte) i; - // Encode the frame - XorErasureEncoder e = new XorErasureEncoder(4); - Segment[] set = e.encodeFrame(f); - // There should be four pieces of 67 bytes each - assertEquals(4, set.length); - for(int i = 0; i < 4; i++) assertEquals(67, set[i].getLength()); - // The first three pieces should contain the data plus on padding byte - byte[] b1 = set[0].getBuffer(); - for(int i = 0; i < 67; i++) assertEquals((byte) i, b1[i]); - byte[] b2 = set[1].getBuffer(); - for(int i = 0; i < 67; i++) assertEquals((byte) (i + 67), b2[i]); - byte[] b3 = set[2].getBuffer(); - for(int i = 0; i < 66; i++) assertEquals((byte) (i + 134), b3[i]); - assertEquals(0, b3[66]); - // The fourth piece should be the XOR of the other three - byte[] b4 = set[3].getBuffer(); - byte[] expected = new byte[67]; - for(int i = 0; i < 67; i++) { - expected[i] = (byte) (b1[i] ^ b2[i] ^ b3[i]); - } - assertArrayEquals(expected, b4); - } -}