mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Don't create tag ciphers and tag keys unnecessarily.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
lastFrame = false;
|
||||
this.frameLength = frameLength;
|
||||
iv = new byte[IV_LENGTH];
|
||||
aad = new byte[AAD_LENGTH];
|
||||
ciphertext = new byte[maxFrameLength];
|
||||
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[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)
|
||||
|
||||
@@ -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[maxFrameLength];
|
||||
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[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
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user