diff --git a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java index 2b4288a445075284431aac79b83ec1394b3e2958..fc951da24a9ab393516db85b478e25a1bf0f9e32 100644 --- a/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionReaderFactoryImpl.java @@ -26,15 +26,26 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory { public ConnectionReader createConnectionReader(InputStream in, byte[] secret, boolean initiator) { - // Derive the keys and erase the secret - ErasableKey tagKey = crypto.deriveTagKey(secret, initiator); - ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator); - ByteUtils.erase(secret); - // Create the reader - Cipher tagCipher = crypto.getTagCipher(); - AuthenticatedCipher frameCipher = crypto.getFrameCipher(); - FrameReader encryption = new IncomingEncryptionLayer(in, tagCipher, - frameCipher, tagKey, frameKey, !initiator, MAX_FRAME_LENGTH); - return new ConnectionReaderImpl(encryption, MAX_FRAME_LENGTH); + if(initiator) { + // Derive the frame key and erase the secret + ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator); + ByteUtils.erase(secret); + // Create a reader for the responder's side of the connection + AuthenticatedCipher frameCipher = crypto.getFrameCipher(); + FrameReader encryption = new IncomingEncryptionLayer(in, + frameCipher, frameKey, MAX_FRAME_LENGTH); + return new ConnectionReaderImpl(encryption, MAX_FRAME_LENGTH); + } else { + // Derive the tag and frame keys and erase the secret + ErasableKey tagKey = crypto.deriveTagKey(secret, initiator); + ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator); + ByteUtils.erase(secret); + // Create a reader for the initiator's side of the connection + Cipher tagCipher = crypto.getTagCipher(); + AuthenticatedCipher frameCipher = crypto.getFrameCipher(); + FrameReader encryption = new IncomingEncryptionLayer(in, tagCipher, + frameCipher, tagKey, frameKey, MAX_FRAME_LENGTH); + return new ConnectionReaderImpl(encryption, MAX_FRAME_LENGTH); + } } } diff --git a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java index e719edd3114daa0a5e6fcb331112eae08d54d08d..415eb2fdf74ece8fa3f2be2f1cfc1309b50c854f 100644 --- a/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java +++ b/components/net/sf/briar/transport/ConnectionWriterFactoryImpl.java @@ -26,16 +26,26 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory { public ConnectionWriter createConnectionWriter(OutputStream out, long capacity, byte[] secret, boolean initiator) { - // Derive the keys and erase the secret - ErasableKey tagKey = crypto.deriveTagKey(secret, initiator); - ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator); - ByteUtils.erase(secret); - // Create the writer - Cipher tagCipher = crypto.getTagCipher(); - AuthenticatedCipher frameCipher = crypto.getFrameCipher(); - FrameWriter encryption = new OutgoingEncryptionLayer(out, capacity, - tagCipher, frameCipher, tagKey, frameKey, initiator, - MAX_FRAME_LENGTH); - return new ConnectionWriterImpl(encryption, MAX_FRAME_LENGTH); + if(initiator) { + // Derive the tag and frame keys and erase the secret + ErasableKey tagKey = crypto.deriveTagKey(secret, initiator); + ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator); + ByteUtils.erase(secret); + // Create a writer for the initiator's side of the connection + Cipher tagCipher = crypto.getTagCipher(); + AuthenticatedCipher frameCipher = crypto.getFrameCipher(); + FrameWriter encryption = new OutgoingEncryptionLayer(out, capacity, + tagCipher, frameCipher, tagKey, frameKey, MAX_FRAME_LENGTH); + return new ConnectionWriterImpl(encryption, MAX_FRAME_LENGTH); + } else { + // Derive the frame key and erase the secret + ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator); + ByteUtils.erase(secret); + // Create a writer for the responder's side of the connection + AuthenticatedCipher frameCipher = crypto.getFrameCipher(); + FrameWriter encryption = new OutgoingEncryptionLayer(out, capacity, + frameCipher, frameKey, MAX_FRAME_LENGTH); + return new ConnectionWriterImpl(encryption, MAX_FRAME_LENGTH); + } } -} +} \ No newline at end of file diff --git a/components/net/sf/briar/transport/IncomingEncryptionLayer.java b/components/net/sf/briar/transport/IncomingEncryptionLayer.java index 084b5f5d72e8c6be7a481bfca5261786ae18f393..4e9bb09c2936d7b52485544c1c2029b70d9dcc24 100644 --- a/components/net/sf/briar/transport/IncomingEncryptionLayer.java +++ b/components/net/sf/briar/transport/IncomingEncryptionLayer.java @@ -25,26 +25,44 @@ class IncomingEncryptionLayer implements FrameReader { private final AuthenticatedCipher frameCipher; private final ErasableKey tagKey, frameKey; private final byte[] iv, aad, ciphertext; - private final int maxFrameLength; + private final int frameLength; - private boolean readTag, lastFrame; private long frameNumber; + private boolean readTag, lastFrame; + /** Constructor for the initiator's side of a connection. */ IncomingEncryptionLayer(InputStream in, Cipher tagCipher, AuthenticatedCipher frameCipher, ErasableKey tagKey, - ErasableKey frameKey, boolean readTag, int maxFrameLength) { + ErasableKey frameKey, int frameLength) { this.in = in; this.tagCipher = tagCipher; this.frameCipher = frameCipher; this.tagKey = tagKey; this.frameKey = frameKey; - this.readTag = readTag; - this.maxFrameLength = maxFrameLength; + this.frameLength = frameLength; + iv = new byte[IV_LENGTH]; + aad = new byte[AAD_LENGTH]; + ciphertext = new byte[frameLength]; + frameNumber = 0L; + readTag = true; lastFrame = false; + } + + /** Constructor for the responder's side of a connection. */ + IncomingEncryptionLayer(InputStream in, AuthenticatedCipher frameCipher, + ErasableKey frameKey, int frameLength) { + this.in = in; + this.frameCipher = frameCipher; + this.frameKey = frameKey; + this.frameLength = frameLength; + tagCipher = null; + tagKey = null; iv = new byte[IV_LENGTH]; aad = new byte[AAD_LENGTH]; - ciphertext = new byte[maxFrameLength]; + ciphertext = new byte[frameLength]; frameNumber = 0L; + readTag = false; + lastFrame = false; } public int readFrame(byte[] frame) throws IOException { @@ -70,9 +88,9 @@ class IncomingEncryptionLayer implements FrameReader { // Read the frame int ciphertextLength = 0; try { - while(ciphertextLength < maxFrameLength) { + while(ciphertextLength < frameLength) { int read = in.read(ciphertext, ciphertextLength, - maxFrameLength - ciphertextLength); + frameLength - ciphertextLength); if(read == -1) break; // We'll check the length later ciphertextLength += read; } @@ -96,7 +114,7 @@ class IncomingEncryptionLayer implements FrameReader { } // Decode and validate the header lastFrame = FrameEncoder.isLastFrame(frame); - if(!lastFrame && ciphertextLength < maxFrameLength) + if(!lastFrame && ciphertextLength < frameLength) throw new EOFException(); int payloadLength = FrameEncoder.getPayloadLength(frame); if(payloadLength > plaintextLength - HEADER_LENGTH) diff --git a/components/net/sf/briar/transport/OutgoingEncryptionLayer.java b/components/net/sf/briar/transport/OutgoingEncryptionLayer.java index f3cebfd1e9a93bed17503c3507c15e2dab2fc63a..c9080a6c5e95ec010abc51c9ed00ad83b92a843c 100644 --- a/components/net/sf/briar/transport/OutgoingEncryptionLayer.java +++ b/components/net/sf/briar/transport/OutgoingEncryptionLayer.java @@ -23,35 +23,54 @@ class OutgoingEncryptionLayer implements FrameWriter { private final AuthenticatedCipher frameCipher; private final ErasableKey tagKey, frameKey; private final byte[] iv, aad, ciphertext; - private final int maxFrameLength; + private final int frameLength; - private boolean writeTag; private long capacity, frameNumber; + private boolean writeTag; + /** Constructor for the initiator's side of a connection. */ OutgoingEncryptionLayer(OutputStream out, long capacity, Cipher tagCipher, AuthenticatedCipher frameCipher, ErasableKey tagKey, - ErasableKey frameKey, boolean writeTag, int maxFrameLength) { + ErasableKey frameKey, int frameLength) { this.out = out; - this.capacity = writeTag ? capacity - TAG_LENGTH : capacity; + this.capacity = capacity - TAG_LENGTH; this.tagCipher = tagCipher; this.frameCipher = frameCipher; this.tagKey = tagKey; this.frameKey = frameKey; - this.writeTag = writeTag; - this.maxFrameLength = maxFrameLength; + this.frameLength = frameLength; + iv = new byte[IV_LENGTH]; + aad = new byte[AAD_LENGTH]; + ciphertext = new byte[frameLength]; + frameNumber = 0L; + writeTag = true; + } + + /** Constructor for the responder's side of a connection. */ + OutgoingEncryptionLayer(OutputStream out, long capacity, + AuthenticatedCipher frameCipher, ErasableKey frameKey, + int frameLength) { + this.out = out; + this.capacity = capacity; + this.frameCipher = frameCipher; + this.frameKey = frameKey; + this.frameLength = frameLength; + tagCipher = null; + tagKey = null; iv = new byte[IV_LENGTH]; aad = new byte[AAD_LENGTH]; - ciphertext = new byte[maxFrameLength]; + ciphertext = new byte[frameLength]; frameNumber = 0L; + writeTag = false; } public void writeFrame(byte[] frame, int payloadLength, int paddingLength, boolean lastFrame) throws IOException { int plaintextLength = HEADER_LENGTH + payloadLength + paddingLength; int ciphertextLength = plaintextLength + MAC_LENGTH; - if(ciphertextLength > maxFrameLength) + if(ciphertextLength > frameLength) throw new IllegalArgumentException(); - if(!lastFrame && ciphertextLength < maxFrameLength) + if(!lastFrame && ciphertextLength < frameLength) throw new IllegalArgumentException(); // If the initiator's side of the connection is closed without writing // any payload or padding, don't write a tag or an empty frame diff --git a/test/net/sf/briar/transport/FrameReadWriteTest.java b/test/net/sf/briar/transport/FrameReadWriteTest.java index 620a63f6780045be6d7f5b5a05d068220ef6b185..a9b7361e75604551ac9257e2cc65de8c7c94bf26 100644 --- a/test/net/sf/briar/transport/FrameReadWriteTest.java +++ b/test/net/sf/briar/transport/FrameReadWriteTest.java @@ -75,7 +75,7 @@ public class FrameReadWriteTest extends BriarTestCase { ByteArrayOutputStream out = new ByteArrayOutputStream(); FrameWriter encryptionOut = new OutgoingEncryptionLayer(out, Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy, - true, FRAME_LENGTH); + FRAME_LENGTH); ConnectionWriter writer = new ConnectionWriterImpl(encryptionOut, FRAME_LENGTH); OutputStream out1 = writer.getOutputStream(); @@ -88,7 +88,7 @@ public class FrameReadWriteTest extends BriarTestCase { // Read the tag and the frames back ByteArrayInputStream in = new ByteArrayInputStream(output); FrameReader encryptionIn = new IncomingEncryptionLayer(in, tagCipher, - frameCipher, tagKey, frameKey, true, FRAME_LENGTH); + frameCipher, tagKey, frameKey, FRAME_LENGTH); ConnectionReader reader = new ConnectionReaderImpl(encryptionIn, FRAME_LENGTH); InputStream in1 = reader.getInputStream();