mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 21:29:54 +01:00
Plaintext frames don't need to include space for the MAC.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package net.sf.briar.transport;
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
import static net.sf.briar.api.transport.TransportConstants.HEADER_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.HEADER_LENGTH;
|
||||||
|
import static net.sf.briar.api.transport.TransportConstants.MAC_LENGTH;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -16,7 +17,7 @@ class ConnectionReaderImpl extends InputStream implements ConnectionReader {
|
|||||||
|
|
||||||
ConnectionReaderImpl(FrameReader in, int frameLength) {
|
ConnectionReaderImpl(FrameReader in, int frameLength) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
frame = new byte[frameLength];
|
frame = new byte[frameLength - MAC_LENGTH];
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
public InputStream getInputStream() {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class ConnectionWriterImpl extends OutputStream implements ConnectionWriter {
|
|||||||
ConnectionWriterImpl(FrameWriter out, int frameLength) {
|
ConnectionWriterImpl(FrameWriter out, int frameLength) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.frameLength = frameLength;
|
this.frameLength = frameLength;
|
||||||
frame = new byte[frameLength];
|
frame = new byte[frameLength - MAC_LENGTH];
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputStream getOutputStream() {
|
public OutputStream getOutputStream() {
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ import com.google.inject.Injector;
|
|||||||
|
|
||||||
public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
||||||
|
|
||||||
|
private static final int FRAME_LENGTH = 1024;
|
||||||
|
private static final int MAX_PAYLOAD_LENGTH =
|
||||||
|
FRAME_LENGTH - HEADER_LENGTH - MAC_LENGTH;
|
||||||
|
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
private final Cipher tagCipher;
|
private final Cipher tagCipher;
|
||||||
private final AuthenticatedCipher frameCipher;
|
private final AuthenticatedCipher frameCipher;
|
||||||
@@ -38,11 +42,11 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncryption() throws Exception {
|
public void testEncryption() throws Exception {
|
||||||
int frameLength = 1024, payloadLength = 123;
|
int payloadLength = 123;
|
||||||
byte[] tag = new byte[TAG_LENGTH];
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
byte[] iv = new byte[IV_LENGTH], aad = new byte[AAD_LENGTH];
|
byte[] iv = new byte[IV_LENGTH], aad = new byte[AAD_LENGTH];
|
||||||
byte[] plaintext = new byte[frameLength - MAC_LENGTH];
|
byte[] plaintext = new byte[FRAME_LENGTH - MAC_LENGTH];
|
||||||
byte[] ciphertext = new byte[frameLength];
|
byte[] ciphertext = new byte[FRAME_LENGTH];
|
||||||
ErasableKey tagKey = crypto.generateTestKey();
|
ErasableKey tagKey = crypto.generateTestKey();
|
||||||
ErasableKey frameKey = crypto.generateTestKey();
|
ErasableKey frameKey = crypto.generateTestKey();
|
||||||
// Calculate the expected tag
|
// Calculate the expected tag
|
||||||
@@ -55,15 +59,16 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
|||||||
frameCipher.doFinal(plaintext, 0, plaintext.length, ciphertext, 0);
|
frameCipher.doFinal(plaintext, 0, plaintext.length, ciphertext, 0);
|
||||||
// Check that the actual tag and ciphertext match what's expected
|
// Check that the actual tag and ciphertext match what's expected
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out, 10 * 1024,
|
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||||
tagCipher, frameCipher, tagKey, frameKey, frameLength);
|
10 * FRAME_LENGTH, tagCipher, frameCipher, tagKey, frameKey,
|
||||||
o.writeFrame(new byte[frameLength - MAC_LENGTH], payloadLength, false);
|
FRAME_LENGTH);
|
||||||
|
o.writeFrame(new byte[FRAME_LENGTH - MAC_LENGTH], payloadLength, false);
|
||||||
byte[] actual = out.toByteArray();
|
byte[] actual = out.toByteArray();
|
||||||
assertEquals(TAG_LENGTH + frameLength, actual.length);
|
assertEquals(TAG_LENGTH + FRAME_LENGTH, actual.length);
|
||||||
for(int i = 0; i < TAG_LENGTH; i++) {
|
for(int i = 0; i < TAG_LENGTH; i++) {
|
||||||
assertEquals(tag[i], actual[i]);
|
assertEquals(tag[i], actual[i]);
|
||||||
}
|
}
|
||||||
for(int i = 0; i < frameLength; i++) {
|
for(int i = 0; i < FRAME_LENGTH; i++) {
|
||||||
assertEquals("" + i, ciphertext[i], actual[TAG_LENGTH + i]);
|
assertEquals("" + i, ciphertext[i], actual[TAG_LENGTH + i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,11 +77,12 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
|||||||
public void testInitiatorClosesConnectionWithoutWriting() throws Exception {
|
public void testInitiatorClosesConnectionWithoutWriting() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
// Initiator's constructor
|
// Initiator's constructor
|
||||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out, 10 * 1024,
|
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||||
tagCipher, frameCipher, crypto.generateTestKey(),
|
10 * FRAME_LENGTH, tagCipher, frameCipher,
|
||||||
crypto.generateTestKey(), 1024);
|
crypto.generateTestKey(), crypto.generateTestKey(),
|
||||||
|
FRAME_LENGTH);
|
||||||
// Write an empty final frame without having written any other frames
|
// Write an empty final frame without having written any other frames
|
||||||
o.writeFrame(new byte[1024], 0, true);
|
o.writeFrame(new byte[FRAME_LENGTH - MAC_LENGTH], 0, true);
|
||||||
// Nothing should be written to the output stream
|
// Nothing should be written to the output stream
|
||||||
assertEquals(0, out.size());
|
assertEquals(0, out.size());
|
||||||
}
|
}
|
||||||
@@ -85,80 +91,78 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
|
|||||||
public void testResponderClosesConnectionWithoutWriting() throws Exception {
|
public void testResponderClosesConnectionWithoutWriting() throws Exception {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
// Responder's constructor
|
// Responder's constructor
|
||||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out, 10 * 1024,
|
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||||
frameCipher, crypto.generateTestKey(), 1024);
|
10 * FRAME_LENGTH, frameCipher, crypto.generateTestKey(),
|
||||||
|
FRAME_LENGTH);
|
||||||
// Write an empty final frame without having written any other frames
|
// Write an empty final frame without having written any other frames
|
||||||
o.writeFrame(new byte[1024], 0, true);
|
o.writeFrame(new byte[FRAME_LENGTH - MAC_LENGTH], 0, true);
|
||||||
// An empty final frame should be written to the output stream
|
// An empty final frame should be written to the output stream
|
||||||
assertEquals(HEADER_LENGTH + MAC_LENGTH, out.size());
|
assertEquals(HEADER_LENGTH + MAC_LENGTH, out.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemainingCapacityWithTag() throws Exception {
|
public void testRemainingCapacityWithTag() throws Exception {
|
||||||
int frameLength = 1024;
|
int MAX_PAYLOAD_LENGTH = FRAME_LENGTH - HEADER_LENGTH - MAC_LENGTH;
|
||||||
int maxPayloadLength = frameLength - HEADER_LENGTH - MAC_LENGTH;
|
|
||||||
long capacity = 10 * frameLength;
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
// Initiator's constructor
|
// Initiator's constructor
|
||||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out, capacity,
|
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||||
tagCipher, frameCipher, crypto.generateTestKey(),
|
10 * FRAME_LENGTH, tagCipher, frameCipher,
|
||||||
crypto.generateTestKey(), frameLength);
|
crypto.generateTestKey(), crypto.generateTestKey(),
|
||||||
|
FRAME_LENGTH);
|
||||||
// There should be space for nine full frames and one partial frame
|
// There should be space for nine full frames and one partial frame
|
||||||
byte[] frame = new byte[frameLength];
|
byte[] frame = new byte[FRAME_LENGTH - MAC_LENGTH];
|
||||||
assertEquals(10 * maxPayloadLength - TAG_LENGTH,
|
assertEquals(10 * MAX_PAYLOAD_LENGTH - TAG_LENGTH,
|
||||||
o.getRemainingCapacity());
|
o.getRemainingCapacity());
|
||||||
// Write nine frames, each containing a partial payload
|
// Write nine frames, each containing a partial payload
|
||||||
for(int i = 0; i < 9; i++) {
|
for(int i = 0; i < 9; i++) {
|
||||||
o.writeFrame(frame, 123, false);
|
o.writeFrame(frame, 123, false);
|
||||||
assertEquals((9 - i) * maxPayloadLength - TAG_LENGTH,
|
assertEquals((9 - i) * MAX_PAYLOAD_LENGTH - TAG_LENGTH,
|
||||||
o.getRemainingCapacity());
|
o.getRemainingCapacity());
|
||||||
}
|
}
|
||||||
// Write the final frame, which will not be padded
|
// Write the final frame, which will not be padded
|
||||||
o.writeFrame(frame, 123, true);
|
o.writeFrame(frame, 123, true);
|
||||||
int finalFrameLength = HEADER_LENGTH + 123 + MAC_LENGTH;
|
int finalFrameLength = HEADER_LENGTH + 123 + MAC_LENGTH;
|
||||||
assertEquals(maxPayloadLength - TAG_LENGTH - finalFrameLength,
|
assertEquals(MAX_PAYLOAD_LENGTH - TAG_LENGTH - finalFrameLength,
|
||||||
o.getRemainingCapacity());
|
o.getRemainingCapacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemainingCapacityWithoutTag() throws Exception {
|
public void testRemainingCapacityWithoutTag() throws Exception {
|
||||||
int frameLength = 1024;
|
|
||||||
int maxPayloadLength = frameLength - HEADER_LENGTH - MAC_LENGTH;
|
|
||||||
long capacity = 10 * frameLength;
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
// Responder's constructor
|
// Responder's constructor
|
||||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out, capacity,
|
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||||
frameCipher, crypto.generateTestKey(), frameLength);
|
10 * FRAME_LENGTH, frameCipher, crypto.generateTestKey(),
|
||||||
|
FRAME_LENGTH);
|
||||||
// There should be space for ten full frames
|
// There should be space for ten full frames
|
||||||
assertEquals(10 * maxPayloadLength, o.getRemainingCapacity());
|
assertEquals(10 * MAX_PAYLOAD_LENGTH, o.getRemainingCapacity());
|
||||||
// Write nine frames, each containing a partial payload
|
// Write nine frames, each containing a partial payload
|
||||||
byte[] frame = new byte[frameLength];
|
byte[] frame = new byte[FRAME_LENGTH - MAC_LENGTH];
|
||||||
for(int i = 0; i < 9; i++) {
|
for(int i = 0; i < 9; i++) {
|
||||||
o.writeFrame(frame, 123, false);
|
o.writeFrame(frame, 123, false);
|
||||||
assertEquals((9 - i) * maxPayloadLength, o.getRemainingCapacity());
|
assertEquals((9 - i) * MAX_PAYLOAD_LENGTH,
|
||||||
|
o.getRemainingCapacity());
|
||||||
}
|
}
|
||||||
// Write the final frame, which will not be padded
|
// Write the final frame, which will not be padded
|
||||||
o.writeFrame(frame, 123, true);
|
o.writeFrame(frame, 123, true);
|
||||||
int finalFrameLength = HEADER_LENGTH + 123 + MAC_LENGTH;
|
int finalFrameLength = HEADER_LENGTH + 123 + MAC_LENGTH;
|
||||||
assertEquals(maxPayloadLength - finalFrameLength,
|
assertEquals(MAX_PAYLOAD_LENGTH - finalFrameLength,
|
||||||
o.getRemainingCapacity());
|
o.getRemainingCapacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemainingCapacityLimitedByFrameNumbers() throws Exception {
|
public void testRemainingCapacityLimitedByFrameNumbers() throws Exception {
|
||||||
int frameLength = 1024;
|
|
||||||
int maxPayloadLength = frameLength - HEADER_LENGTH - MAC_LENGTH;
|
|
||||||
long capacity = Long.MAX_VALUE;
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out, capacity,
|
// The connection has plenty of space so we're limited by frame numbers
|
||||||
frameCipher, crypto.generateTestKey(), frameLength);
|
OutgoingEncryptionLayer o = new OutgoingEncryptionLayer(out,
|
||||||
|
Long.MAX_VALUE, frameCipher, crypto.generateTestKey(),
|
||||||
|
FRAME_LENGTH);
|
||||||
// There should be enough frame numbers for 2^32 frames
|
// There should be enough frame numbers for 2^32 frames
|
||||||
assertEquals((1L << 32) * maxPayloadLength, o.getRemainingCapacity());
|
assertEquals((1L << 32) * MAX_PAYLOAD_LENGTH, o.getRemainingCapacity());
|
||||||
// Write a frame containing a partial payload
|
// Write a frame containing a partial payload
|
||||||
byte[] frame = new byte[frameLength];
|
byte[] frame = new byte[FRAME_LENGTH - MAC_LENGTH];
|
||||||
o.writeFrame(frame, 123, false);
|
o.writeFrame(frame, 123, false);
|
||||||
// There should be enough frame numbers for 2^32 - 1 frames
|
// There should be enough frame numbers for 2^32 - 1 frames
|
||||||
assertEquals(((1L << 32) - 1) * maxPayloadLength,
|
assertEquals(((1L << 32) - 1) * MAX_PAYLOAD_LENGTH,
|
||||||
o.getRemainingCapacity());
|
o.getRemainingCapacity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user