Updated transport constants and renamed some test classes.

This commit is contained in:
akwizgran
2012-01-17 14:56:30 +00:00
parent 9bd0b60dec
commit 8c0020873c
24 changed files with 181 additions and 178 deletions

View File

@@ -8,9 +8,9 @@ public interface Segment {
int getLength(); int getLength();
long getTransmissionNumber(); long getSegmentNumber();
void setLength(int length); void setLength(int length);
void setTransmissionNumber(int transmission); void setSegmentNumber(long segmentNumber);
} }

View File

@@ -2,19 +2,20 @@ package net.sf.briar.api.transport;
public interface TransportConstants { public interface TransportConstants {
/** /** The maximum length of a segment in bytes, including the tag. */
* The maximum length of a frame in bytes, including the header and footer. static final int MAX_SEGMENT_LENGTH = 65536; // 2^16, 64 KiB
*/
static final int MAX_FRAME_LENGTH = 65536; // 2^16, 64 KiB /** The length of the segment 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;
/** The length of the frame header in bytes. */ /** The length of the frame header in bytes. */
static final int FRAME_HEADER_LENGTH = 8; static final int FRAME_HEADER_LENGTH = 8;
/** /** The length of the MAC in bytes. */
* The length in bytes of the pseudo-random tag that uniquely identifies a static final int MAC_LENGTH = 32;
* connection.
*/
static final int TAG_LENGTH = 16;
/** /**
* The minimum connection length in bytes that all transport plugins must * The minimum connection length in bytes that all transport plugins must

View File

@@ -1,5 +1,7 @@
package net.sf.briar.protocol; package net.sf.briar.protocol;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.BitSet; import java.util.BitSet;
@@ -10,7 +12,6 @@ import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Group; import net.sf.briar.api.protocol.Group;
import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.api.protocol.Offer; import net.sf.briar.api.protocol.Offer;
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
import net.sf.briar.api.protocol.ProtocolWriter; import net.sf.briar.api.protocol.ProtocolWriter;
import net.sf.briar.api.protocol.RawBatch; import net.sf.briar.api.protocol.RawBatch;
import net.sf.briar.api.protocol.Request; import net.sf.briar.api.protocol.Request;

View File

@@ -49,8 +49,8 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
Cipher tagCipher = crypto.getTagCipher(); Cipher tagCipher = crypto.getTagCipher();
Cipher frameCipher = crypto.getFrameCipher(); Cipher frameCipher = crypto.getFrameCipher();
Mac mac = crypto.getMac(); Mac mac = crypto.getMac();
IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in, tagCipher, IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in,
frameCipher, tagKey, frameKey, mac.getMacLength(), false); tagCipher, frameCipher, tagKey, frameKey, false);
// Create the reader // Create the reader
return new ConnectionReaderImpl(decrypter, mac, macKey); return new ConnectionReaderImpl(decrypter, mac, macKey);
} }

View File

@@ -1,6 +1,7 @@
package net.sf.briar.transport; 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_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_FRAME_LENGTH;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
@@ -18,13 +19,13 @@ class ConnectionReaderImpl extends InputStream implements ConnectionReader {
private final IncomingEncryptionLayer decrypter; private final IncomingEncryptionLayer decrypter;
private final Mac mac; private final Mac mac;
private final int macLength;
private final byte[] buf; private final byte[] buf;
private long frame = 0L; private long frame = 0L;
private int bufOffset = 0, bufLength = 0; private int offset = 0, length = 0;
ConnectionReaderImpl(IncomingEncryptionLayer decrypter, Mac mac, ErasableKey macKey) { ConnectionReaderImpl(IncomingEncryptionLayer decrypter, Mac mac,
ErasableKey macKey) {
this.decrypter = decrypter; this.decrypter = decrypter;
this.mac = mac; this.mac = mac;
// Initialise the MAC // Initialise the MAC
@@ -34,7 +35,8 @@ class ConnectionReaderImpl extends InputStream implements ConnectionReader {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} }
macKey.erase(); macKey.erase();
macLength = mac.getMacLength(); if(mac.getMacLength() != MAC_LENGTH)
throw new IllegalArgumentException();
buf = new byte[MAX_FRAME_LENGTH]; buf = new byte[MAX_FRAME_LENGTH];
} }
@@ -44,10 +46,10 @@ class ConnectionReaderImpl extends InputStream implements ConnectionReader {
@Override @Override
public int read() throws IOException { public int read() throws IOException {
while(bufLength == 0) if(!readFrame()) return -1; while(length == 0) if(!readFrame()) return -1;
int b = buf[bufOffset] & 0xff; int b = buf[offset] & 0xff;
bufOffset++; offset++;
bufLength--; length--;
return b; return b;
} }
@@ -58,28 +60,27 @@ class ConnectionReaderImpl extends InputStream implements ConnectionReader {
@Override @Override
public int read(byte[] b, int off, int len) throws IOException { public int read(byte[] b, int off, int len) throws IOException {
while(bufLength == 0) if(!readFrame()) return -1; while(length == 0) if(!readFrame()) return -1;
len = Math.min(len, bufLength); len = Math.min(len, length);
System.arraycopy(buf, bufOffset, b, off, len); System.arraycopy(buf, offset, b, off, len);
bufOffset += len; offset += len;
bufLength -= len; length -= len;
return len; return len;
} }
private boolean readFrame() throws IOException { private boolean readFrame() throws IOException {
assert bufLength == 0; assert length == 0;
// Don't allow more than 2^32 frames to be read // Don't allow more than 2^32 frames to be read
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException(); if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
// Read a frame // Read a frame
int length = decrypter.readFrame(buf); int frameLength = decrypter.readFrame(buf);
if(length == -1) return false; if(frameLength == -1) return false;
// Check that the frame number is correct and the length is legal // Check that the frame number is correct and the length is legal
int max = MAX_FRAME_LENGTH - FRAME_HEADER_LENGTH - macLength; if(!HeaderEncoder.validateHeader(buf, frame))
if(!HeaderEncoder.validateHeader(buf, frame, max))
throw new FormatException(); throw new FormatException();
int payload = HeaderEncoder.getPayloadLength(buf); int payload = HeaderEncoder.getPayloadLength(buf);
int padding = HeaderEncoder.getPaddingLength(buf); int padding = HeaderEncoder.getPaddingLength(buf);
if(length != FRAME_HEADER_LENGTH + payload + padding + macLength) if(frameLength != FRAME_HEADER_LENGTH + payload + padding + MAC_LENGTH)
throw new FormatException(); throw new FormatException();
// Check that the padding is all zeroes // Check that the padding is all zeroes
int paddingStart = FRAME_HEADER_LENGTH + payload; int paddingStart = FRAME_HEADER_LENGTH + payload;
@@ -90,11 +91,11 @@ class ConnectionReaderImpl extends InputStream implements ConnectionReader {
int macStart = FRAME_HEADER_LENGTH + payload + padding; int macStart = FRAME_HEADER_LENGTH + payload + padding;
mac.update(buf, 0, macStart); mac.update(buf, 0, macStart);
byte[] expectedMac = mac.doFinal(); byte[] expectedMac = mac.doFinal();
for(int i = 0; i < macLength; i++) { for(int i = 0; i < expectedMac.length; i++) {
if(expectedMac[i] != buf[macStart + i]) throw new FormatException(); if(expectedMac[i] != buf[macStart + i]) throw new FormatException();
} }
bufOffset = FRAME_HEADER_LENGTH; offset = FRAME_HEADER_LENGTH;
bufLength = payload; length = payload;
frame++; frame++;
return true; return true;
} }

View File

@@ -1,6 +1,7 @@
package net.sf.briar.transport; 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_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_FRAME_LENGTH;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
@@ -26,7 +27,7 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
private final Mac mac; private final Mac mac;
private final byte[] buf; private final byte[] buf;
private int bufLength = FRAME_HEADER_LENGTH; private int length = FRAME_HEADER_LENGTH;
private long frame = 0L; private long frame = 0L;
ConnectionWriterImpl(OutgoingEncryptionLayer encrypter, Mac mac, ConnectionWriterImpl(OutgoingEncryptionLayer encrypter, Mac mac,
@@ -40,6 +41,8 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
throw new IllegalArgumentException(badKey); throw new IllegalArgumentException(badKey);
} }
macKey.erase(); macKey.erase();
if(mac.getMacLength() != MAC_LENGTH)
throw new IllegalArgumentException();
buf = new byte[MAX_FRAME_LENGTH]; buf = new byte[MAX_FRAME_LENGTH];
} }
@@ -49,25 +52,25 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
public long getRemainingCapacity() { public long getRemainingCapacity() {
long capacity = encrypter.getRemainingCapacity(); long capacity = encrypter.getRemainingCapacity();
// If there's any data buffered, subtract it and its auth overhead // If there's any data buffered, subtract it and its overhead
if(bufLength > FRAME_HEADER_LENGTH) if(length > FRAME_HEADER_LENGTH)
capacity -= bufLength + mac.getMacLength(); capacity -= length + MAC_LENGTH;
// Subtract the auth overhead from the remaining capacity // Subtract the overhead from the remaining capacity
long frames = (long) Math.ceil((double) capacity / MAX_FRAME_LENGTH); long frames = (long) Math.ceil((double) capacity / MAX_FRAME_LENGTH);
int overheadPerFrame = FRAME_HEADER_LENGTH + mac.getMacLength(); int overheadPerFrame = FRAME_HEADER_LENGTH + MAC_LENGTH;
return Math.max(0L, capacity - frames * overheadPerFrame); return Math.max(0L, capacity - frames * overheadPerFrame);
} }
@Override @Override
public void flush() throws IOException { public void flush() throws IOException {
if(bufLength > FRAME_HEADER_LENGTH) writeFrame(); if(length > FRAME_HEADER_LENGTH) writeFrame();
encrypter.flush(); encrypter.flush();
} }
@Override @Override
public void write(int b) throws IOException { public void write(int b) throws IOException {
buf[bufLength++] = (byte) b; buf[length++] = (byte) b;
if(bufLength + mac.getMacLength() == MAX_FRAME_LENGTH) writeFrame(); if(length + MAC_LENGTH == MAX_FRAME_LENGTH) writeFrame();
} }
@Override @Override
@@ -77,32 +80,32 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
@Override @Override
public void write(byte[] b, int off, int len) throws IOException { public void write(byte[] b, int off, int len) throws IOException {
int available = MAX_FRAME_LENGTH - bufLength - mac.getMacLength(); int available = MAX_FRAME_LENGTH - length - MAC_LENGTH;
while(available <= len) { while(available <= len) {
System.arraycopy(b, off, buf, bufLength, available); System.arraycopy(b, off, buf, length, available);
bufLength += available; length += available;
writeFrame(); writeFrame();
off += available; off += available;
len -= available; len -= available;
available = MAX_FRAME_LENGTH - bufLength - mac.getMacLength(); available = MAX_FRAME_LENGTH - length - MAC_LENGTH;
} }
System.arraycopy(b, off, buf, bufLength, len); System.arraycopy(b, off, buf, length, len);
bufLength += len; length += len;
} }
private void writeFrame() throws IOException { private void writeFrame() throws IOException {
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException(); if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
int payloadLength = bufLength - FRAME_HEADER_LENGTH; int payloadLength = length - FRAME_HEADER_LENGTH;
assert payloadLength > 0; assert payloadLength > 0;
HeaderEncoder.encodeHeader(buf, frame, payloadLength, 0); HeaderEncoder.encodeHeader(buf, frame, payloadLength, 0);
mac.update(buf, 0, bufLength); mac.update(buf, 0, length);
try { try {
mac.doFinal(buf, bufLength); mac.doFinal(buf, length);
} catch(ShortBufferException badMac) { } catch(ShortBufferException badMac) {
throw new RuntimeException(badMac); throw new RuntimeException(badMac);
} }
encrypter.writeFrame(buf, bufLength + mac.getMacLength()); encrypter.writeFrame(buf, length + MAC_LENGTH);
bufLength = FRAME_HEADER_LENGTH; length = FRAME_HEADER_LENGTH;
frame++; frame++;
} }
} }

View File

@@ -1,34 +1,43 @@
package net.sf.briar.transport; 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_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.util.ByteUtils; import net.sf.briar.util.ByteUtils;
class HeaderEncoder { class HeaderEncoder {
static void encodeHeader(byte[] header, long frame, int payload, static void encodeHeader(byte[] header, long frameNumber, int payload,
int padding) { int padding) {
if(header.length < FRAME_HEADER_LENGTH) if(header.length < FRAME_HEADER_LENGTH)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if(frame < 0 || frame > ByteUtils.MAX_32_BIT_UNSIGNED) if(frameNumber < 0 || frameNumber > ByteUtils.MAX_32_BIT_UNSIGNED)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if(payload < 0 || payload > ByteUtils.MAX_16_BIT_UNSIGNED) if(payload < 0 || payload > ByteUtils.MAX_16_BIT_UNSIGNED)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if(padding < 0 || padding > ByteUtils.MAX_16_BIT_UNSIGNED) if(padding < 0 || padding > ByteUtils.MAX_16_BIT_UNSIGNED)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
ByteUtils.writeUint32(frame, header, 0); ByteUtils.writeUint32(frameNumber, header, 0);
ByteUtils.writeUint16(payload, header, 4); ByteUtils.writeUint16(payload, header, 4);
ByteUtils.writeUint16(padding, header, 6); ByteUtils.writeUint16(padding, header, 6);
} }
static boolean validateHeader(byte[] header, long frame, int max) { static boolean validateHeader(byte[] header, long frameNumber) {
if(header.length < FRAME_HEADER_LENGTH) return false; if(header.length < FRAME_HEADER_LENGTH) return false;
if(ByteUtils.readUint32(header, 0) != frame) return false; if(ByteUtils.readUint32(header, 0) != frameNumber) return false;
int payload = ByteUtils.readUint16(header, 4); int payload = ByteUtils.readUint16(header, 4);
int padding = ByteUtils.readUint16(header, 6); int padding = ByteUtils.readUint16(header, 6);
if(payload + padding > max) return false; int frameLength = FRAME_HEADER_LENGTH + payload + padding + MAC_LENGTH;
if(frameLength > MAX_FRAME_LENGTH) return false;
return true; return true;
} }
static long getFrameNumber(byte[] header) {
if(header.length < FRAME_HEADER_LENGTH)
throw new IllegalArgumentException();
return ByteUtils.readUint32(header, 0);
}
static int getPayloadLength(byte[] header) { static int getPayloadLength(byte[] header) {
if(header.length < FRAME_HEADER_LENGTH) if(header.length < FRAME_HEADER_LENGTH)
throw new IllegalArgumentException(); throw new IllegalArgumentException();

View File

@@ -1,7 +1,7 @@
package net.sf.briar.transport; 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_HEADER_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
@@ -21,7 +21,7 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
private final InputStream in; private final InputStream in;
private final Cipher tagCipher, frameCipher; private final Cipher tagCipher, frameCipher;
private final ErasableKey tagKey, frameKey; private final ErasableKey tagKey, frameKey;
private final int macLength, blockSize; private final int blockSize;
private final byte[] iv; private final byte[] iv;
private final boolean tagEverySegment; private final boolean tagEverySegment;
@@ -29,13 +29,12 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
IncomingEncryptionLayerImpl(InputStream in, Cipher tagCipher, IncomingEncryptionLayerImpl(InputStream in, Cipher tagCipher,
Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey, Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey,
int macLength, boolean tagEverySegment) { boolean tagEverySegment) {
this.in = in; this.in = in;
this.tagCipher = tagCipher; this.tagCipher = tagCipher;
this.frameCipher = frameCipher; this.frameCipher = frameCipher;
this.tagKey = tagKey; this.tagKey = tagKey;
this.frameKey = frameKey; this.frameKey = frameKey;
this.macLength = macLength;
this.tagEverySegment = tagEverySegment; this.tagEverySegment = tagEverySegment;
blockSize = frameCipher.getBlockSize(); blockSize = frameCipher.getBlockSize();
if(blockSize < FRAME_HEADER_LENGTH) if(blockSize < FRAME_HEADER_LENGTH)
@@ -44,7 +43,6 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
} }
public int readFrame(byte[] b) throws IOException { public int readFrame(byte[] b) throws IOException {
if(b.length < MAX_FRAME_LENGTH) throw new IllegalArgumentException();
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException(); if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
boolean tag = tagEverySegment && frame > 0; boolean tag = tagEverySegment && frame > 0;
// Clear the buffer before exposing it to the transport plugin // Clear the buffer before exposing it to the transport plugin
@@ -85,13 +83,11 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
throw new RuntimeException(badCipher); throw new RuntimeException(badCipher);
} }
// Validate and parse the header // Validate and parse the header
int max = MAX_FRAME_LENGTH - FRAME_HEADER_LENGTH - macLength; if(!HeaderEncoder.validateHeader(b, frame))
if(!HeaderEncoder.validateHeader(b, frame, max))
throw new FormatException(); throw new FormatException();
int payload = HeaderEncoder.getPayloadLength(b); int payload = HeaderEncoder.getPayloadLength(b);
int padding = HeaderEncoder.getPaddingLength(b); int padding = HeaderEncoder.getPaddingLength(b);
int length = FRAME_HEADER_LENGTH + payload + padding + macLength; int length = FRAME_HEADER_LENGTH + payload + padding + MAC_LENGTH;
if(length > MAX_FRAME_LENGTH) throw new FormatException();
// Read the remainder of the frame // Read the remainder of the frame
while(offset < length) { while(offset < length) {
int read = in.read(b, offset, length - offset); int read = in.read(b, offset, length - offset);

View File

@@ -1,7 +1,8 @@
package net.sf.briar.transport; 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_HEADER_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_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 static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
@@ -21,7 +22,7 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
private final SegmentSource in; private final SegmentSource in;
private final Cipher tagCipher, frameCipher; private final Cipher tagCipher, frameCipher;
private final ErasableKey tagKey, frameKey; private final ErasableKey tagKey, frameKey;
private final int macLength, blockSize; private final int blockSize;
private final byte[] iv; private final byte[] iv;
private final Segment segment; private final Segment segment;
private final boolean tagEverySegment; private final boolean tagEverySegment;
@@ -30,13 +31,12 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
IncomingSegmentedEncryptionLayer(SegmentSource in, Cipher tagCipher, IncomingSegmentedEncryptionLayer(SegmentSource in, Cipher tagCipher,
Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey, Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey,
int macLength, boolean tagEverySegment) { boolean tagEverySegment) {
this.in = in; this.in = in;
this.tagCipher = tagCipher; this.tagCipher = tagCipher;
this.frameCipher = frameCipher; this.frameCipher = frameCipher;
this.tagKey = tagKey; this.tagKey = tagKey;
this.frameKey = frameKey; this.frameKey = frameKey;
this.macLength = macLength;
this.tagEverySegment = tagEverySegment; this.tagEverySegment = tagEverySegment;
blockSize = frameCipher.getBlockSize(); blockSize = frameCipher.getBlockSize();
if(blockSize < FRAME_HEADER_LENGTH) if(blockSize < FRAME_HEADER_LENGTH)
@@ -46,7 +46,6 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
} }
public int readFrame(byte[] b) throws IOException { public int readFrame(byte[] b) throws IOException {
if(b.length < MAX_FRAME_LENGTH) throw new IllegalArgumentException();
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException(); if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
boolean tag = tagEverySegment && frame > 0; boolean tag = tagEverySegment && frame > 0;
// Clear the buffer before exposing it to the transport plugin // Clear the buffer before exposing it to the transport plugin
@@ -55,8 +54,8 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
// Read the segment // Read the segment
if(!in.readSegment(segment)) return -1; if(!in.readSegment(segment)) return -1;
int offset = tag ? TAG_LENGTH : 0, length = segment.getLength(); int offset = tag ? TAG_LENGTH : 0, length = segment.getLength();
if(length > MAX_FRAME_LENGTH) throw new FormatException(); if(length > MAX_SEGMENT_LENGTH) throw new FormatException();
if(length < offset + FRAME_HEADER_LENGTH + macLength) if(length < offset + FRAME_HEADER_LENGTH + MAC_LENGTH)
throw new FormatException(); throw new FormatException();
// If a tag is expected, decrypt and validate it // If a tag is expected, decrypt and validate it
if(tag && !TagEncoder.validateTag(segment.getBuffer(), frame, if(tag && !TagEncoder.validateTag(segment.getBuffer(), frame,
@@ -73,13 +72,12 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
throw new RuntimeException(badCipher); throw new RuntimeException(badCipher);
} }
// Validate and parse the header // Validate and parse the header
int max = MAX_FRAME_LENGTH - FRAME_HEADER_LENGTH - macLength; if(!HeaderEncoder.validateHeader(b, frame))
if(!HeaderEncoder.validateHeader(b, frame, max))
throw new FormatException(); throw new FormatException();
int payload = HeaderEncoder.getPayloadLength(b); int payload = HeaderEncoder.getPayloadLength(b);
int padding = HeaderEncoder.getPaddingLength(b); int padding = HeaderEncoder.getPaddingLength(b);
if(length != offset + FRAME_HEADER_LENGTH + payload + padding if(length != offset + FRAME_HEADER_LENGTH + payload + padding
+ macLength) throw new FormatException(); + MAC_LENGTH) throw new FormatException();
frame++; frame++;
return length - offset; return length - offset;
} catch(IOException e) { } catch(IOException e) {

View File

@@ -1,6 +1,5 @@
package net.sf.briar.transport; package net.sf.briar.transport;
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
@@ -43,8 +42,6 @@ class OutgoingSegmentedEncryptionLayer implements OutgoingEncryptionLayer {
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException(); if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
int offset = 0; int offset = 0;
if(tagEverySegment || frame == 0) { if(tagEverySegment || frame == 0) {
if(len + TAG_LENGTH > MAX_FRAME_LENGTH)
throw new IllegalArgumentException();
TagEncoder.encodeTag(segment.getBuffer(), frame, tagCipher, tagKey); TagEncoder.encodeTag(segment.getBuffer(), frame, tagCipher, tagKey);
offset = TAG_LENGTH; offset = TAG_LENGTH;
capacity -= TAG_LENGTH; capacity -= TAG_LENGTH;

View File

@@ -1,20 +1,20 @@
package net.sf.briar.transport; package net.sf.briar.transport;
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
import net.sf.briar.api.plugins.Segment; import net.sf.briar.api.plugins.Segment;
import net.sf.briar.util.ByteUtils; import net.sf.briar.util.ByteUtils;
class SegmentImpl implements Segment { class SegmentImpl implements Segment {
private final byte[] buf = new byte[MAX_FRAME_LENGTH]; private final byte[] buf = new byte[MAX_SEGMENT_LENGTH];
private int length = -1; private int length = -1;
private long transmission = -1; private long segmentNumber = -1;
public void clear() { public void clear() {
for(int i = 0; i < buf.length; i++) buf[i] = 0; for(int i = 0; i < buf.length; i++) buf[i] = 0;
length = -1; length = -1;
transmission = -1; segmentNumber = -1;
} }
public byte[] getBuffer() { public byte[] getBuffer() {
@@ -26,9 +26,9 @@ class SegmentImpl implements Segment {
return length; return length;
} }
public long getTransmissionNumber() { public long getSegmentNumber() {
if(transmission == -1) throw new IllegalStateException(); if(segmentNumber == -1) throw new IllegalStateException();
return transmission; return segmentNumber;
} }
public void setLength(int length) { public void setLength(int length) {
@@ -37,9 +37,9 @@ class SegmentImpl implements Segment {
this.length = length; this.length = length;
} }
public void setTransmissionNumber(int transmission) { public void setSegmentNumber(long segmentNumber) {
if(transmission < 0 || transmission > ByteUtils.MAX_32_BIT_UNSIGNED) if(segmentNumber < 0 || segmentNumber > ByteUtils.MAX_32_BIT_UNSIGNED)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
this.transmission = transmission; this.segmentNumber = segmentNumber;
} }
} }

View File

@@ -7,10 +7,10 @@ import net.sf.briar.api.transport.ConnectionContextFactory;
import net.sf.briar.api.transport.ConnectionDispatcher; import net.sf.briar.api.transport.ConnectionDispatcher;
import net.sf.briar.api.transport.ConnectionReaderFactory; import net.sf.briar.api.transport.ConnectionReaderFactory;
import net.sf.briar.api.transport.ConnectionRecogniser; import net.sf.briar.api.transport.ConnectionRecogniser;
import net.sf.briar.api.transport.IncomingConnectionExecutor;
import net.sf.briar.api.transport.ConnectionRegistry; import net.sf.briar.api.transport.ConnectionRegistry;
import net.sf.briar.api.transport.ConnectionWindowFactory; import net.sf.briar.api.transport.ConnectionWindowFactory;
import net.sf.briar.api.transport.ConnectionWriterFactory; import net.sf.briar.api.transport.ConnectionWriterFactory;
import net.sf.briar.api.transport.IncomingConnectionExecutor;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;

View File

@@ -2,9 +2,9 @@ package net.sf.briar.plugins.socket;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Executor;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportConfig; import net.sf.briar.api.TransportConfig;

View File

@@ -7,8 +7,8 @@ import java.net.Socket;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;

View File

@@ -25,7 +25,6 @@ import net.sf.briar.api.transport.TransportConstants;
import net.sf.briar.crypto.CryptoModule; import net.sf.briar.crypto.CryptoModule;
import net.sf.briar.protocol.ProtocolModule; import net.sf.briar.protocol.ProtocolModule;
import net.sf.briar.protocol.duplex.DuplexProtocolModule; import net.sf.briar.protocol.duplex.DuplexProtocolModule;
import net.sf.briar.protocol.simplex.SimplexProtocolModule;
import net.sf.briar.serial.SerialModule; import net.sf.briar.serial.SerialModule;
import net.sf.briar.transport.TransportModule; import net.sf.briar.transport.TransportModule;

View File

@@ -36,7 +36,6 @@ import net.sf.briar.lifecycle.LifecycleModule;
import net.sf.briar.plugins.ImmediateExecutor; import net.sf.briar.plugins.ImmediateExecutor;
import net.sf.briar.protocol.ProtocolModule; import net.sf.briar.protocol.ProtocolModule;
import net.sf.briar.protocol.duplex.DuplexProtocolModule; import net.sf.briar.protocol.duplex.DuplexProtocolModule;
import net.sf.briar.protocol.simplex.SimplexProtocolModule;
import net.sf.briar.serial.SerialModule; import net.sf.briar.serial.SerialModule;
import net.sf.briar.transport.TransportModule; import net.sf.briar.transport.TransportModule;

View File

@@ -1,6 +1,7 @@
package net.sf.briar.transport; 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_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_FRAME_LENGTH;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
@@ -23,7 +24,7 @@ public class ConnectionReaderImplTest extends TransportTest {
public void testLengthZero() throws Exception { public void testLengthZero() throws Exception {
int payloadLength = 0; int payloadLength = 0;
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0); HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0);
// Calculate the MAC // Calculate the MAC
mac.init(macKey); mac.init(macKey);
@@ -31,8 +32,8 @@ public class ConnectionReaderImplTest extends TransportTest {
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength); mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
// Read the frame // Read the frame
ByteArrayInputStream in = new ByteArrayInputStream(frame); ByteArrayInputStream in = new ByteArrayInputStream(frame);
IncomingEncryptionLayer d = new NullConnectionDecrypter(in, macLength); IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac, macKey); ConnectionReader r = new ConnectionReaderImpl(decrypter, mac, macKey);
// There should be no bytes available before EOF // There should be no bytes available before EOF
assertEquals(-1, r.getInputStream().read()); assertEquals(-1, r.getInputStream().read());
} }
@@ -41,7 +42,7 @@ public class ConnectionReaderImplTest extends TransportTest {
public void testLengthOne() throws Exception { public void testLengthOne() throws Exception {
int payloadLength = 1; int payloadLength = 1;
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0); HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0);
// Calculate the MAC // Calculate the MAC
mac.init(macKey); mac.init(macKey);
@@ -49,8 +50,8 @@ public class ConnectionReaderImplTest extends TransportTest {
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength); mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
// Read the frame // Read the frame
ByteArrayInputStream in = new ByteArrayInputStream(frame); ByteArrayInputStream in = new ByteArrayInputStream(frame);
IncomingEncryptionLayer d = new NullConnectionDecrypter(in, macLength); IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac, macKey); ConnectionReader r = new ConnectionReaderImpl(decrypter, mac, macKey);
// There should be one byte available before EOF // There should be one byte available before EOF
assertEquals(0, r.getInputStream().read()); assertEquals(0, r.getInputStream().read());
assertEquals(-1, r.getInputStream().read()); assertEquals(-1, r.getInputStream().read());
@@ -60,27 +61,27 @@ public class ConnectionReaderImplTest extends TransportTest {
public void testMaxLength() throws Exception { public void testMaxLength() throws Exception {
// First frame: max payload length // First frame: max payload length
byte[] frame = new byte[MAX_FRAME_LENGTH]; byte[] frame = new byte[MAX_FRAME_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, maxPayloadLength, 0); HeaderEncoder.encodeHeader(frame, 0, MAX_PAYLOAD_LENGTH, 0);
mac.init(macKey); mac.init(macKey);
mac.update(frame, 0, FRAME_HEADER_LENGTH + maxPayloadLength); mac.update(frame, 0, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
mac.doFinal(frame, FRAME_HEADER_LENGTH + maxPayloadLength); mac.doFinal(frame, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
// Second frame: max payload length plus one // Second frame: max payload length plus one
byte[] frame1 = new byte[MAX_FRAME_LENGTH + 1]; byte[] frame1 = new byte[MAX_FRAME_LENGTH + 1];
HeaderEncoder.encodeHeader(frame1, 1, maxPayloadLength + 1, 0); HeaderEncoder.encodeHeader(frame1, 1, MAX_PAYLOAD_LENGTH + 1, 0);
mac.update(frame1, 0, FRAME_HEADER_LENGTH + maxPayloadLength + 1); mac.update(frame1, 0, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + 1);
mac.doFinal(frame1, FRAME_HEADER_LENGTH + maxPayloadLength + 1); mac.doFinal(frame1, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + 1);
// Concatenate the frames // Concatenate the frames
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(frame); out.write(frame);
out.write(frame1); out.write(frame1);
// Read the first frame // Read the first frame
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
IncomingEncryptionLayer d = new NullConnectionDecrypter(in, macLength); IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac, macKey); ConnectionReader r = new ConnectionReaderImpl(decrypter, mac, macKey);
byte[] read = new byte[maxPayloadLength]; byte[] read = new byte[MAX_PAYLOAD_LENGTH];
TestUtils.readFully(r.getInputStream(), read); TestUtils.readFully(r.getInputStream(), read);
// Try to read the second frame // Try to read the second frame
byte[] read1 = new byte[maxPayloadLength + 1]; byte[] read1 = new byte[MAX_PAYLOAD_LENGTH + 1];
try { try {
TestUtils.readFully(r.getInputStream(), read1); TestUtils.readFully(r.getInputStream(), read1);
fail(); fail();
@@ -92,29 +93,29 @@ public class ConnectionReaderImplTest extends TransportTest {
int paddingLength = 10; int paddingLength = 10;
// First frame: max payload length, including padding // First frame: max payload length, including padding
byte[] frame = new byte[MAX_FRAME_LENGTH]; byte[] frame = new byte[MAX_FRAME_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, maxPayloadLength - paddingLength, HeaderEncoder.encodeHeader(frame, 0, MAX_PAYLOAD_LENGTH - paddingLength,
paddingLength); paddingLength);
mac.init(macKey); mac.init(macKey);
mac.update(frame, 0, FRAME_HEADER_LENGTH + maxPayloadLength); mac.update(frame, 0, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
mac.doFinal(frame, FRAME_HEADER_LENGTH + maxPayloadLength); mac.doFinal(frame, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH);
// Second frame: max payload length plus one, including padding // Second frame: max payload length plus one, including padding
byte[] frame1 = new byte[MAX_FRAME_LENGTH + 1]; byte[] frame1 = new byte[MAX_FRAME_LENGTH + 1];
HeaderEncoder.encodeHeader(frame1, 1, HeaderEncoder.encodeHeader(frame1, 1,
maxPayloadLength + 1 - paddingLength, paddingLength); MAX_PAYLOAD_LENGTH + 1 - paddingLength, paddingLength);
mac.update(frame1, 0, FRAME_HEADER_LENGTH + maxPayloadLength + 1); mac.update(frame1, 0, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + 1);
mac.doFinal(frame1, FRAME_HEADER_LENGTH + maxPayloadLength + 1); mac.doFinal(frame1, FRAME_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + 1);
// Concatenate the frames // Concatenate the frames
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(frame); out.write(frame);
out.write(frame1); out.write(frame1);
// Read the first frame // Read the first frame
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
IncomingEncryptionLayer d = new NullConnectionDecrypter(in, macLength); IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac, macKey); ConnectionReader r = new ConnectionReaderImpl(decrypter, mac, macKey);
byte[] read = new byte[maxPayloadLength - paddingLength]; byte[] read = new byte[MAX_PAYLOAD_LENGTH - paddingLength];
TestUtils.readFully(r.getInputStream(), read); TestUtils.readFully(r.getInputStream(), read);
// Try to read the second frame // Try to read the second frame
byte[] read1 = new byte[maxPayloadLength + 1 - paddingLength]; byte[] read1 = new byte[MAX_PAYLOAD_LENGTH + 1 - paddingLength];
try { try {
TestUtils.readFully(r.getInputStream(), read1); TestUtils.readFully(r.getInputStream(), read1);
fail(); fail();
@@ -125,7 +126,7 @@ public class ConnectionReaderImplTest extends TransportTest {
public void testNonZeroPadding() throws Exception { public void testNonZeroPadding() throws Exception {
int payloadLength = 10, paddingLength = 10; int payloadLength = 10, paddingLength = 10;
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
+ paddingLength + macLength]; + paddingLength + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, payloadLength, paddingLength); HeaderEncoder.encodeHeader(frame, 0, payloadLength, paddingLength);
// Set a byte of the padding to a non-zero value // Set a byte of the padding to a non-zero value
frame[FRAME_HEADER_LENGTH + payloadLength] = 1; frame[FRAME_HEADER_LENGTH + payloadLength] = 1;
@@ -135,8 +136,8 @@ public class ConnectionReaderImplTest extends TransportTest {
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength + paddingLength); mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength + paddingLength);
// Read the frame // Read the frame
ByteArrayInputStream in = new ByteArrayInputStream(frame); ByteArrayInputStream in = new ByteArrayInputStream(frame);
IncomingEncryptionLayer d = new NullConnectionDecrypter(in, macLength); IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac, macKey); ConnectionReader r = new ConnectionReaderImpl(decrypter, mac, macKey);
// The non-zero padding should be rejected // The non-zero padding should be rejected
try { try {
r.getInputStream().read(); r.getInputStream().read();
@@ -149,7 +150,7 @@ public class ConnectionReaderImplTest extends TransportTest {
// First frame: 123-byte payload // First frame: 123-byte payload
int payloadLength = 123; int payloadLength = 123;
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0); HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0);
mac.init(macKey); mac.init(macKey);
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength); mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
@@ -157,7 +158,7 @@ public class ConnectionReaderImplTest extends TransportTest {
// Second frame: 1234-byte payload // Second frame: 1234-byte payload
int payloadLength1 = 1234; int payloadLength1 = 1234;
byte[] frame1 = new byte[FRAME_HEADER_LENGTH + payloadLength1 byte[] frame1 = new byte[FRAME_HEADER_LENGTH + payloadLength1
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame1, 1, payloadLength1, 0); HeaderEncoder.encodeHeader(frame1, 1, payloadLength1, 0);
mac.update(frame1, 0, FRAME_HEADER_LENGTH + payloadLength1); mac.update(frame1, 0, FRAME_HEADER_LENGTH + payloadLength1);
mac.doFinal(frame1, FRAME_HEADER_LENGTH + payloadLength1); mac.doFinal(frame1, FRAME_HEADER_LENGTH + payloadLength1);
@@ -167,8 +168,8 @@ public class ConnectionReaderImplTest extends TransportTest {
out.write(frame1); out.write(frame1);
// Read the frames // Read the frames
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
IncomingEncryptionLayer d = new NullConnectionDecrypter(in, macLength); IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac, macKey); ConnectionReader r = new ConnectionReaderImpl(decrypter, mac, macKey);
byte[] read = new byte[payloadLength]; byte[] read = new byte[payloadLength];
TestUtils.readFully(r.getInputStream(), read); TestUtils.readFully(r.getInputStream(), read);
assertArrayEquals(new byte[payloadLength], read); assertArrayEquals(new byte[payloadLength], read);
@@ -181,7 +182,7 @@ public class ConnectionReaderImplTest extends TransportTest {
public void testCorruptPayload() throws Exception { public void testCorruptPayload() throws Exception {
int payloadLength = 8; int payloadLength = 8;
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0); HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0);
// Calculate the MAC // Calculate the MAC
mac.init(macKey); mac.init(macKey);
@@ -191,8 +192,8 @@ public class ConnectionReaderImplTest extends TransportTest {
frame[12] ^= 1; frame[12] ^= 1;
// Try to read the frame - not a single byte should be read // Try to read the frame - not a single byte should be read
ByteArrayInputStream in = new ByteArrayInputStream(frame); ByteArrayInputStream in = new ByteArrayInputStream(frame);
IncomingEncryptionLayer d = new NullConnectionDecrypter(in, macLength); IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac, macKey); ConnectionReader r = new ConnectionReaderImpl(decrypter, mac, macKey);
try { try {
r.getInputStream().read(); r.getInputStream().read();
fail(); fail();
@@ -203,7 +204,7 @@ public class ConnectionReaderImplTest extends TransportTest {
public void testCorruptMac() throws Exception { public void testCorruptMac() throws Exception {
int payloadLength = 8; int payloadLength = 8;
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0); HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0);
// Calculate the MAC // Calculate the MAC
mac.init(macKey); mac.init(macKey);
@@ -213,8 +214,8 @@ public class ConnectionReaderImplTest extends TransportTest {
frame[17] ^= 1; frame[17] ^= 1;
// Try to read the frame - not a single byte should be read // Try to read the frame - not a single byte should be read
ByteArrayInputStream in = new ByteArrayInputStream(frame); ByteArrayInputStream in = new ByteArrayInputStream(frame);
IncomingEncryptionLayer d = new NullConnectionDecrypter(in, macLength); IncomingEncryptionLayer decrypter = new NullIncomingEncryptionLayer(in);
ConnectionReader r = new ConnectionReaderImpl(d, mac, macKey); ConnectionReader r = new ConnectionReaderImpl(decrypter, mac, macKey);
try { try {
r.getInputStream().read(); r.getInputStream().read();
fail(); fail();

View File

@@ -1,6 +1,7 @@
package net.sf.briar.transport; 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_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_FRAME_LENGTH;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
@@ -20,8 +21,8 @@ public class ConnectionWriterImplTest extends TransportTest {
@Test @Test
public void testFlushWithoutWriteProducesNothing() throws Exception { public void testFlushWithoutWriteProducesNothing() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
OutgoingEncryptionLayer e = new NullConnectionEncrypter(out); OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
ConnectionWriter w = new ConnectionWriterImpl(e, mac, macKey); ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
w.getOutputStream().flush(); w.getOutputStream().flush();
w.getOutputStream().flush(); w.getOutputStream().flush();
w.getOutputStream().flush(); w.getOutputStream().flush();
@@ -32,7 +33,7 @@ public class ConnectionWriterImplTest extends TransportTest {
public void testSingleByteFrame() throws Exception { public void testSingleByteFrame() throws Exception {
int payloadLength = 1; int payloadLength = 1;
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0); HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0);
// Calculate the MAC // Calculate the MAC
mac.init(macKey); mac.init(macKey);
@@ -40,8 +41,8 @@ public class ConnectionWriterImplTest extends TransportTest {
mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength); mac.doFinal(frame, FRAME_HEADER_LENGTH + payloadLength);
// Check that the ConnectionWriter gets the same results // Check that the ConnectionWriter gets the same results
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
OutgoingEncryptionLayer e = new NullConnectionEncrypter(out); OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
ConnectionWriter w = new ConnectionWriterImpl(e, mac, macKey); ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
w.getOutputStream().write(0); w.getOutputStream().write(0);
w.getOutputStream().flush(); w.getOutputStream().flush();
assertArrayEquals(frame, out.toByteArray()); assertArrayEquals(frame, out.toByteArray());
@@ -50,11 +51,11 @@ public class ConnectionWriterImplTest extends TransportTest {
@Test @Test
public void testWriteByteToMaxLengthWritesFrame() throws Exception { public void testWriteByteToMaxLengthWritesFrame() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
OutgoingEncryptionLayer e = new NullConnectionEncrypter(out); OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
ConnectionWriter w = new ConnectionWriterImpl(e, mac, macKey); ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
OutputStream out1 = w.getOutputStream(); OutputStream out1 = w.getOutputStream();
// The first maxPayloadLength - 1 bytes should be buffered // The first maxPayloadLength - 1 bytes should be buffered
for(int i = 0; i < maxPayloadLength - 1; i++) out1.write(0); for(int i = 0; i < MAX_PAYLOAD_LENGTH - 1; i++) out1.write(0);
assertEquals(0, out.size()); assertEquals(0, out.size());
// The next byte should trigger the writing of a frame // The next byte should trigger the writing of a frame
out1.write(0); out1.write(0);
@@ -64,14 +65,14 @@ public class ConnectionWriterImplTest extends TransportTest {
@Test @Test
public void testWriteArrayToMaxLengthWritesFrame() throws Exception { public void testWriteArrayToMaxLengthWritesFrame() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
OutgoingEncryptionLayer e = new NullConnectionEncrypter(out); OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
ConnectionWriter w = new ConnectionWriterImpl(e, mac, macKey); ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
OutputStream out1 = w.getOutputStream(); OutputStream out1 = w.getOutputStream();
// The first maxPayloadLength - 1 bytes should be buffered // The first maxPayloadLength - 1 bytes should be buffered
out1.write(new byte[maxPayloadLength - 1]); out1.write(new byte[MAX_PAYLOAD_LENGTH - 1]);
assertEquals(0, out.size()); assertEquals(0, out.size());
// The next maxPayloadLength + 1 bytes should trigger two frames // The next maxPayloadLength + 1 bytes should trigger two frames
out1.write(new byte[maxPayloadLength + 1]); out1.write(new byte[MAX_PAYLOAD_LENGTH + 1]);
assertEquals(MAX_FRAME_LENGTH * 2, out.size()); assertEquals(MAX_FRAME_LENGTH * 2, out.size());
} }
@@ -80,7 +81,7 @@ public class ConnectionWriterImplTest extends TransportTest {
// First frame: 123-byte payload // First frame: 123-byte payload
int payloadLength = 123; int payloadLength = 123;
byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength byte[] frame = new byte[FRAME_HEADER_LENGTH + payloadLength
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0); HeaderEncoder.encodeHeader(frame, 0, payloadLength, 0);
mac.init(macKey); mac.init(macKey);
mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength); mac.update(frame, 0, FRAME_HEADER_LENGTH + payloadLength);
@@ -88,7 +89,7 @@ public class ConnectionWriterImplTest extends TransportTest {
// Second frame: 1234-byte payload // Second frame: 1234-byte payload
int payloadLength1 = 1234; int payloadLength1 = 1234;
byte[] frame1 = new byte[FRAME_HEADER_LENGTH + payloadLength1 byte[] frame1 = new byte[FRAME_HEADER_LENGTH + payloadLength1
+ macLength]; + MAC_LENGTH];
HeaderEncoder.encodeHeader(frame1, 1, payloadLength1, 0); HeaderEncoder.encodeHeader(frame1, 1, payloadLength1, 0);
mac.update(frame1, 0, FRAME_HEADER_LENGTH + 1234); mac.update(frame1, 0, FRAME_HEADER_LENGTH + 1234);
mac.doFinal(frame1, FRAME_HEADER_LENGTH + 1234); mac.doFinal(frame1, FRAME_HEADER_LENGTH + 1234);
@@ -99,8 +100,8 @@ public class ConnectionWriterImplTest extends TransportTest {
byte[] expected = out.toByteArray(); byte[] expected = out.toByteArray();
// Check that the ConnectionWriter gets the same results // Check that the ConnectionWriter gets the same results
out.reset(); out.reset();
OutgoingEncryptionLayer e = new NullConnectionEncrypter(out); OutgoingEncryptionLayer encrypter = new NullOutgoingEncryptionLayer(out);
ConnectionWriter w = new ConnectionWriterImpl(e, mac, macKey); ConnectionWriter w = new ConnectionWriterImpl(encrypter, mac, macKey);
w.getOutputStream().write(new byte[123]); w.getOutputStream().write(new byte[123]);
w.getOutputStream().flush(); w.getOutputStream().flush();
w.getOutputStream().write(new byte[1234]); w.getOutputStream().write(new byte[1234]);

View File

@@ -91,8 +91,8 @@ public class FrameReadWriteTest extends BriarTestCase {
assertArrayEquals(tag, recoveredTag); assertArrayEquals(tag, recoveredTag);
assertTrue(TagEncoder.validateTag(tag, 0, tagCipher, tagKey)); assertTrue(TagEncoder.validateTag(tag, 0, tagCipher, tagKey));
// Read the frames back // Read the frames back
IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in, tagCipher, IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in,
frameCipher, tagKey, frameKey, mac.getMacLength(), false); tagCipher, frameCipher, tagKey, frameKey, false);
ConnectionReader reader = new ConnectionReaderImpl(decrypter, mac, ConnectionReader reader = new ConnectionReaderImpl(decrypter, mac,
macKey); macKey);
InputStream in1 = reader.getInputStream(); InputStream in1 = reader.getInputStream();

View File

@@ -1,6 +1,7 @@
package net.sf.briar.transport; 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_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_FRAME_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
@@ -22,8 +23,6 @@ import com.google.inject.Injector;
public class IncomingEncryptionLayerImplTest extends BriarTestCase { public class IncomingEncryptionLayerImplTest extends BriarTestCase {
private static final int MAC_LENGTH = 32;
private final Cipher tagCipher, frameCipher; private final Cipher tagCipher, frameCipher;
private final ErasableKey tagKey, frameKey; private final ErasableKey tagKey, frameKey;
@@ -61,7 +60,7 @@ public class IncomingEncryptionLayerImplTest extends BriarTestCase {
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
// Use the encryption layer to decrypt the ciphertext // Use the encryption layer to decrypt the ciphertext
IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in, IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in,
tagCipher, frameCipher, tagKey, frameKey, MAC_LENGTH, false); tagCipher, frameCipher, tagKey, frameKey, false);
// First frame // First frame
byte[] decrypted = new byte[MAX_FRAME_LENGTH]; byte[] decrypted = new byte[MAX_FRAME_LENGTH];
assertEquals(plaintext.length, decrypter.readFrame(decrypted)); assertEquals(plaintext.length, decrypter.readFrame(decrypted));
@@ -101,7 +100,7 @@ public class IncomingEncryptionLayerImplTest extends BriarTestCase {
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
// Use the encryption layer to decrypt the ciphertext // Use the encryption layer to decrypt the ciphertext
IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in, IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in,
tagCipher, frameCipher, tagKey, frameKey, MAC_LENGTH, true); tagCipher, frameCipher, tagKey, frameKey, true);
// First frame // First frame
byte[] decrypted = new byte[MAX_FRAME_LENGTH]; byte[] decrypted = new byte[MAX_FRAME_LENGTH];
assertEquals(plaintext.length, decrypter.readFrame(decrypted)); assertEquals(plaintext.length, decrypter.readFrame(decrypted));

View File

@@ -1,6 +1,7 @@
package net.sf.briar.transport; 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_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_FRAME_LENGTH;
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH; import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
@@ -23,8 +24,6 @@ import com.google.inject.Injector;
public class IncomingSegmentedEncryptionLayerTest extends BriarTestCase { public class IncomingSegmentedEncryptionLayerTest extends BriarTestCase {
private static final int MAC_LENGTH = 32;
private final Cipher tagCipher, frameCipher; private final Cipher tagCipher, frameCipher;
private final ErasableKey tagKey, frameKey; private final ErasableKey tagKey, frameKey;
@@ -60,7 +59,7 @@ public class IncomingSegmentedEncryptionLayerTest extends BriarTestCase {
SegmentSource in = new ByteArraySegmentSource(frames); SegmentSource in = new ByteArraySegmentSource(frames);
IncomingEncryptionLayer decrypter = IncomingEncryptionLayer decrypter =
new IncomingSegmentedEncryptionLayer(in, tagCipher, frameCipher, new IncomingSegmentedEncryptionLayer(in, tagCipher, frameCipher,
tagKey, frameKey, MAC_LENGTH, false); tagKey, frameKey, false);
// First frame // First frame
byte[] decrypted = new byte[MAX_FRAME_LENGTH]; byte[] decrypted = new byte[MAX_FRAME_LENGTH];
assertEquals(plaintext.length, decrypter.readFrame(decrypted)); assertEquals(plaintext.length, decrypter.readFrame(decrypted));
@@ -98,7 +97,7 @@ public class IncomingSegmentedEncryptionLayerTest extends BriarTestCase {
SegmentSource in = new ByteArraySegmentSource(frames); SegmentSource in = new ByteArraySegmentSource(frames);
IncomingEncryptionLayer decrypter = IncomingEncryptionLayer decrypter =
new IncomingSegmentedEncryptionLayer(in, tagCipher, frameCipher, new IncomingSegmentedEncryptionLayer(in, tagCipher, frameCipher,
tagKey, frameKey, MAC_LENGTH, true); tagKey, frameKey, true);
// First frame // First frame
byte[] decrypted = new byte[MAX_FRAME_LENGTH]; byte[] decrypted = new byte[MAX_FRAME_LENGTH];
assertEquals(plaintext.length, decrypter.readFrame(decrypted)); assertEquals(plaintext.length, decrypter.readFrame(decrypted));

View File

@@ -1,6 +1,7 @@
package net.sf.briar.transport; 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_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_FRAME_LENGTH;
import java.io.EOFException; import java.io.EOFException;
@@ -9,19 +10,16 @@ import java.io.InputStream;
import net.sf.briar.api.FormatException; import net.sf.briar.api.FormatException;
/** A connection decrypter that performs no decryption. */ /** An encryption layer that performs no encryption. */
class NullConnectionDecrypter implements IncomingEncryptionLayer { class NullIncomingEncryptionLayer implements IncomingEncryptionLayer {
private final InputStream in; private final InputStream in;
private final int macLength;
NullConnectionDecrypter(InputStream in, int macLength) { NullIncomingEncryptionLayer(InputStream in) {
this.in = in; this.in = in;
this.macLength = macLength;
} }
public int readFrame(byte[] b) throws IOException { public int readFrame(byte[] b) throws IOException {
if(b.length < MAX_FRAME_LENGTH) throw new IllegalArgumentException();
// Read the header to determine the frame length // Read the header to determine the frame length
int offset = 0, length = FRAME_HEADER_LENGTH; int offset = 0, length = FRAME_HEADER_LENGTH;
while(offset < length) { while(offset < length) {
@@ -35,7 +33,7 @@ class NullConnectionDecrypter implements IncomingEncryptionLayer {
// Parse the header // Parse the header
int payload = HeaderEncoder.getPayloadLength(b); int payload = HeaderEncoder.getPayloadLength(b);
int padding = HeaderEncoder.getPaddingLength(b); int padding = HeaderEncoder.getPaddingLength(b);
length = FRAME_HEADER_LENGTH + payload + padding + macLength; length = FRAME_HEADER_LENGTH + payload + padding + MAC_LENGTH;
if(length > MAX_FRAME_LENGTH) throw new FormatException(); if(length > MAX_FRAME_LENGTH) throw new FormatException();
// Read the remainder of the frame // Read the remainder of the frame
while(offset < length) { while(offset < length) {

View File

@@ -3,19 +3,19 @@ package net.sf.briar.transport;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
/** A ConnectionEncrypter that performs no encryption. */ /** An encryption layer that performs no encryption. */
class NullConnectionEncrypter implements OutgoingEncryptionLayer { class NullOutgoingEncryptionLayer implements OutgoingEncryptionLayer {
private final OutputStream out; private final OutputStream out;
private long capacity; private long capacity;
NullConnectionEncrypter(OutputStream out) { NullOutgoingEncryptionLayer(OutputStream out) {
this.out = out; this.out = out;
capacity = Long.MAX_VALUE; capacity = Long.MAX_VALUE;
} }
NullConnectionEncrypter(OutputStream out, long capacity) { NullOutgoingEncryptionLayer(OutputStream out, long capacity) {
this.out = out; this.out = out;
this.capacity = capacity; this.capacity = capacity;
} }

View File

@@ -1,6 +1,7 @@
package net.sf.briar.transport; 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_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_FRAME_LENGTH;
import javax.crypto.Mac; import javax.crypto.Mac;
@@ -15,9 +16,11 @@ import com.google.inject.Injector;
public abstract class TransportTest extends BriarTestCase { public abstract class TransportTest extends BriarTestCase {
static final int MAX_PAYLOAD_LENGTH
= MAX_FRAME_LENGTH - FRAME_HEADER_LENGTH - MAC_LENGTH;
protected final Mac mac; protected final Mac mac;
protected final ErasableKey macKey; protected final ErasableKey macKey;
protected final int macLength, maxPayloadLength;
public TransportTest() throws Exception { public TransportTest() throws Exception {
super(); super();
@@ -25,7 +28,5 @@ public abstract class TransportTest extends BriarTestCase {
CryptoComponent crypto = i.getInstance(CryptoComponent.class); CryptoComponent crypto = i.getInstance(CryptoComponent.class);
mac = crypto.getMac(); mac = crypto.getMac();
macKey = crypto.generateTestKey(); macKey = crypto.generateTestKey();
macLength = mac.getMacLength();
maxPayloadLength = MAX_FRAME_LENGTH - FRAME_HEADER_LENGTH - macLength;
} }
} }