mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +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,
|
public ConnectionReader createConnectionReader(InputStream in,
|
||||||
byte[] secret, boolean initiator) {
|
byte[] secret, boolean initiator) {
|
||||||
// Derive the keys and erase the secret
|
if(initiator) {
|
||||||
ErasableKey tagKey = crypto.deriveTagKey(secret, initiator);
|
// Derive the frame key and erase the secret
|
||||||
ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
|
ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
|
||||||
ByteUtils.erase(secret);
|
ByteUtils.erase(secret);
|
||||||
// Create the reader
|
// Create a reader for the responder's side of the connection
|
||||||
Cipher tagCipher = crypto.getTagCipher();
|
AuthenticatedCipher frameCipher = crypto.getFrameCipher();
|
||||||
AuthenticatedCipher frameCipher = crypto.getFrameCipher();
|
FrameReader encryption = new IncomingEncryptionLayer(in,
|
||||||
FrameReader encryption = new IncomingEncryptionLayer(in, tagCipher,
|
frameCipher, frameKey, MAX_FRAME_LENGTH);
|
||||||
frameCipher, tagKey, frameKey, !initiator, MAX_FRAME_LENGTH);
|
return new ConnectionReaderImpl(encryption, 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,
|
public ConnectionWriter createConnectionWriter(OutputStream out,
|
||||||
long capacity, byte[] secret, boolean initiator) {
|
long capacity, byte[] secret, boolean initiator) {
|
||||||
// Derive the keys and erase the secret
|
if(initiator) {
|
||||||
ErasableKey tagKey = crypto.deriveTagKey(secret, initiator);
|
// Derive the tag and frame keys and erase the secret
|
||||||
ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
|
ErasableKey tagKey = crypto.deriveTagKey(secret, initiator);
|
||||||
ByteUtils.erase(secret);
|
ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
|
||||||
// Create the writer
|
ByteUtils.erase(secret);
|
||||||
Cipher tagCipher = crypto.getTagCipher();
|
// Create a writer for the initiator's side of the connection
|
||||||
AuthenticatedCipher frameCipher = crypto.getFrameCipher();
|
Cipher tagCipher = crypto.getTagCipher();
|
||||||
FrameWriter encryption = new OutgoingEncryptionLayer(out, capacity,
|
AuthenticatedCipher frameCipher = crypto.getFrameCipher();
|
||||||
tagCipher, frameCipher, tagKey, frameKey, initiator,
|
FrameWriter encryption = new OutgoingEncryptionLayer(out, capacity,
|
||||||
MAX_FRAME_LENGTH);
|
tagCipher, frameCipher, tagKey, frameKey, MAX_FRAME_LENGTH);
|
||||||
return new ConnectionWriterImpl(encryption, 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 AuthenticatedCipher frameCipher;
|
||||||
private final ErasableKey tagKey, frameKey;
|
private final ErasableKey tagKey, frameKey;
|
||||||
private final byte[] iv, aad, ciphertext;
|
private final byte[] iv, aad, ciphertext;
|
||||||
private final int maxFrameLength;
|
private final int frameLength;
|
||||||
|
|
||||||
private boolean readTag, lastFrame;
|
|
||||||
private long frameNumber;
|
private long frameNumber;
|
||||||
|
private boolean readTag, lastFrame;
|
||||||
|
|
||||||
|
/** Constructor for the initiator's side of a connection. */
|
||||||
IncomingEncryptionLayer(InputStream in, Cipher tagCipher,
|
IncomingEncryptionLayer(InputStream in, Cipher tagCipher,
|
||||||
AuthenticatedCipher frameCipher, ErasableKey tagKey,
|
AuthenticatedCipher frameCipher, ErasableKey tagKey,
|
||||||
ErasableKey frameKey, boolean readTag, int maxFrameLength) {
|
ErasableKey frameKey, int frameLength) {
|
||||||
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.readTag = readTag;
|
this.frameLength = frameLength;
|
||||||
this.maxFrameLength = maxFrameLength;
|
|
||||||
lastFrame = false;
|
|
||||||
iv = new byte[IV_LENGTH];
|
iv = new byte[IV_LENGTH];
|
||||||
aad = new byte[AAD_LENGTH];
|
aad = new byte[AAD_LENGTH];
|
||||||
ciphertext = new byte[maxFrameLength];
|
ciphertext = new byte[frameLength];
|
||||||
frameNumber = 0L;
|
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 {
|
public int readFrame(byte[] frame) throws IOException {
|
||||||
@@ -70,9 +88,9 @@ class IncomingEncryptionLayer implements FrameReader {
|
|||||||
// Read the frame
|
// Read the frame
|
||||||
int ciphertextLength = 0;
|
int ciphertextLength = 0;
|
||||||
try {
|
try {
|
||||||
while(ciphertextLength < maxFrameLength) {
|
while(ciphertextLength < frameLength) {
|
||||||
int read = in.read(ciphertext, ciphertextLength,
|
int read = in.read(ciphertext, ciphertextLength,
|
||||||
maxFrameLength - ciphertextLength);
|
frameLength - ciphertextLength);
|
||||||
if(read == -1) break; // We'll check the length later
|
if(read == -1) break; // We'll check the length later
|
||||||
ciphertextLength += read;
|
ciphertextLength += read;
|
||||||
}
|
}
|
||||||
@@ -96,7 +114,7 @@ class IncomingEncryptionLayer implements FrameReader {
|
|||||||
}
|
}
|
||||||
// Decode and validate the header
|
// Decode and validate the header
|
||||||
lastFrame = FrameEncoder.isLastFrame(frame);
|
lastFrame = FrameEncoder.isLastFrame(frame);
|
||||||
if(!lastFrame && ciphertextLength < maxFrameLength)
|
if(!lastFrame && ciphertextLength < frameLength)
|
||||||
throw new EOFException();
|
throw new EOFException();
|
||||||
int payloadLength = FrameEncoder.getPayloadLength(frame);
|
int payloadLength = FrameEncoder.getPayloadLength(frame);
|
||||||
if(payloadLength > plaintextLength - HEADER_LENGTH)
|
if(payloadLength > plaintextLength - HEADER_LENGTH)
|
||||||
|
|||||||
@@ -23,35 +23,54 @@ class OutgoingEncryptionLayer implements FrameWriter {
|
|||||||
private final AuthenticatedCipher frameCipher;
|
private final AuthenticatedCipher frameCipher;
|
||||||
private final ErasableKey tagKey, frameKey;
|
private final ErasableKey tagKey, frameKey;
|
||||||
private final byte[] iv, aad, ciphertext;
|
private final byte[] iv, aad, ciphertext;
|
||||||
private final int maxFrameLength;
|
private final int frameLength;
|
||||||
|
|
||||||
private boolean writeTag;
|
|
||||||
private long capacity, frameNumber;
|
private long capacity, frameNumber;
|
||||||
|
private boolean writeTag;
|
||||||
|
|
||||||
|
/** Constructor for the initiator's side of a connection. */
|
||||||
OutgoingEncryptionLayer(OutputStream out, long capacity, Cipher tagCipher,
|
OutgoingEncryptionLayer(OutputStream out, long capacity, Cipher tagCipher,
|
||||||
AuthenticatedCipher frameCipher, ErasableKey tagKey,
|
AuthenticatedCipher frameCipher, ErasableKey tagKey,
|
||||||
ErasableKey frameKey, boolean writeTag, int maxFrameLength) {
|
ErasableKey frameKey, int frameLength) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.capacity = writeTag ? capacity - TAG_LENGTH : capacity;
|
this.capacity = capacity - TAG_LENGTH;
|
||||||
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.writeTag = writeTag;
|
this.frameLength = frameLength;
|
||||||
this.maxFrameLength = maxFrameLength;
|
|
||||||
iv = new byte[IV_LENGTH];
|
iv = new byte[IV_LENGTH];
|
||||||
aad = new byte[AAD_LENGTH];
|
aad = new byte[AAD_LENGTH];
|
||||||
ciphertext = new byte[maxFrameLength];
|
ciphertext = new byte[frameLength];
|
||||||
frameNumber = 0L;
|
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,
|
public void writeFrame(byte[] frame, int payloadLength, int paddingLength,
|
||||||
boolean lastFrame) throws IOException {
|
boolean lastFrame) throws IOException {
|
||||||
int plaintextLength = HEADER_LENGTH + payloadLength + paddingLength;
|
int plaintextLength = HEADER_LENGTH + payloadLength + paddingLength;
|
||||||
int ciphertextLength = plaintextLength + MAC_LENGTH;
|
int ciphertextLength = plaintextLength + MAC_LENGTH;
|
||||||
if(ciphertextLength > maxFrameLength)
|
if(ciphertextLength > frameLength)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if(!lastFrame && ciphertextLength < maxFrameLength)
|
if(!lastFrame && ciphertextLength < frameLength)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
// If the initiator's side of the connection is closed without writing
|
// 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
|
// 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();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
FrameWriter encryptionOut = new OutgoingEncryptionLayer(out,
|
FrameWriter encryptionOut = new OutgoingEncryptionLayer(out,
|
||||||
Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy,
|
Long.MAX_VALUE, tagCipher, frameCipher, tagCopy, frameCopy,
|
||||||
true, FRAME_LENGTH);
|
FRAME_LENGTH);
|
||||||
ConnectionWriter writer = new ConnectionWriterImpl(encryptionOut,
|
ConnectionWriter writer = new ConnectionWriterImpl(encryptionOut,
|
||||||
FRAME_LENGTH);
|
FRAME_LENGTH);
|
||||||
OutputStream out1 = writer.getOutputStream();
|
OutputStream out1 = writer.getOutputStream();
|
||||||
@@ -88,7 +88,7 @@ public class FrameReadWriteTest extends BriarTestCase {
|
|||||||
// Read the tag and the frames back
|
// Read the tag and the frames back
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(output);
|
ByteArrayInputStream in = new ByteArrayInputStream(output);
|
||||||
FrameReader encryptionIn = new IncomingEncryptionLayer(in, tagCipher,
|
FrameReader encryptionIn = new IncomingEncryptionLayer(in, tagCipher,
|
||||||
frameCipher, tagKey, frameKey, true, FRAME_LENGTH);
|
frameCipher, tagKey, frameKey, FRAME_LENGTH);
|
||||||
ConnectionReader reader = new ConnectionReaderImpl(encryptionIn,
|
ConnectionReader reader = new ConnectionReaderImpl(encryptionIn,
|
||||||
FRAME_LENGTH);
|
FRAME_LENGTH);
|
||||||
InputStream in1 = reader.getInputStream();
|
InputStream in1 = reader.getInputStream();
|
||||||
|
|||||||
Reference in New Issue
Block a user