Don't create tag ciphers and tag keys unnecessarily.

This commit is contained in:
akwizgran
2012-08-28 12:02:37 +01:00
parent 1762eaf3e9
commit 6965f809c7
5 changed files with 101 additions and 43 deletions

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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();