mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Added factory methods for segmented connection readers.
This commit is contained in:
@@ -7,8 +7,10 @@ import javax.crypto.Mac;
|
||||
|
||||
import net.sf.briar.api.crypto.CryptoComponent;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.plugins.SegmentSource;
|
||||
import net.sf.briar.api.transport.ConnectionReader;
|
||||
import net.sf.briar.api.transport.ConnectionReaderFactory;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
@@ -24,22 +26,16 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
||||
|
||||
public ConnectionReader createConnectionReader(InputStream in,
|
||||
byte[] secret, byte[] tag) {
|
||||
// Validate the tag
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
ErasableKey tagKey = crypto.deriveTagKey(secret, true);
|
||||
long segmentNumber = TagEncoder.decodeTag(tag, tagCipher, tagKey);
|
||||
tagKey.erase();
|
||||
if(segmentNumber != 0) throw new IllegalArgumentException();
|
||||
return createConnectionReader(in, true, secret);
|
||||
return createConnectionReader(in, secret, tag, true);
|
||||
}
|
||||
|
||||
public ConnectionReader createConnectionReader(InputStream in,
|
||||
byte[] secret) {
|
||||
return createConnectionReader(in, false, secret);
|
||||
return createConnectionReader(in, secret, null, false);
|
||||
}
|
||||
|
||||
private ConnectionReader createConnectionReader(InputStream in,
|
||||
boolean initiator, byte[] secret) {
|
||||
byte[] secret, byte[] tag, boolean initiator) {
|
||||
// Derive the keys and erase the secret
|
||||
ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
|
||||
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
||||
@@ -50,7 +46,38 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
||||
Cipher frameCipher = crypto.getFrameCipher();
|
||||
Mac mac = crypto.getMac();
|
||||
IncomingEncryptionLayer decrypter = new IncomingEncryptionLayerImpl(in,
|
||||
tagCipher, frameCipher, tagKey, frameKey, false);
|
||||
tagCipher, frameCipher, tagKey, frameKey, false, tag);
|
||||
// No error correction
|
||||
IncomingErrorCorrectionLayer correcter =
|
||||
new NullIncomingErrorCorrectionLayer(decrypter);
|
||||
// Create the reader
|
||||
return new ConnectionReaderImpl(correcter, mac, macKey);
|
||||
}
|
||||
|
||||
public ConnectionReader createConnectionReader(SegmentSource in,
|
||||
byte[] secret, Segment buffered) {
|
||||
return createConnectionReader(in, secret, buffered, true);
|
||||
}
|
||||
|
||||
public ConnectionReader createConnectionReader(SegmentSource in,
|
||||
byte[] secret) {
|
||||
return createConnectionReader(in, secret, new SegmentImpl(), false);
|
||||
}
|
||||
|
||||
private ConnectionReader createConnectionReader(SegmentSource in,
|
||||
byte[] secret, Segment buffered, boolean initiator) {
|
||||
// Derive the keys and erase the secret
|
||||
ErasableKey frameKey = crypto.deriveFrameKey(secret, initiator);
|
||||
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
||||
ErasableKey tagKey = crypto.deriveTagKey(secret, initiator);
|
||||
ByteUtils.erase(secret);
|
||||
// Create the decrypter
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
Cipher frameCipher = crypto.getFrameCipher();
|
||||
Mac mac = crypto.getMac();
|
||||
IncomingEncryptionLayer decrypter =
|
||||
new IncomingSegmentedEncryptionLayer(in, tagCipher, frameCipher,
|
||||
tagKey, frameKey, false, buffered);
|
||||
// No error correction
|
||||
IncomingErrorCorrectionLayer correcter =
|
||||
new NullIncomingErrorCorrectionLayer(decrypter);
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.sf.briar.transport;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
|
||||
interface IncomingEncryptionLayer {
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import net.sf.briar.api.FormatException;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
|
||||
class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
|
||||
|
||||
@@ -27,18 +27,20 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
|
||||
private final byte[] iv, ciphertext;
|
||||
private final boolean tagEverySegment;
|
||||
|
||||
private byte[] bufferedTag;
|
||||
private boolean firstSegment = true;
|
||||
private long segmentNumber = 0L;
|
||||
|
||||
IncomingEncryptionLayerImpl(InputStream in, Cipher tagCipher,
|
||||
Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey,
|
||||
boolean tagEverySegment) {
|
||||
boolean tagEverySegment, byte[] bufferedTag) {
|
||||
this.in = in;
|
||||
this.tagCipher = tagCipher;
|
||||
this.frameCipher = frameCipher;
|
||||
this.tagKey = tagKey;
|
||||
this.frameKey = frameKey;
|
||||
this.tagEverySegment = tagEverySegment;
|
||||
this.bufferedTag = bufferedTag;
|
||||
blockSize = frameCipher.getBlockSize();
|
||||
if(blockSize < FRAME_HEADER_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
@@ -47,29 +49,41 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
|
||||
}
|
||||
|
||||
public boolean readSegment(Segment s) throws IOException {
|
||||
boolean tag = tagEverySegment && !firstSegment;
|
||||
boolean expectTag = tagEverySegment || firstSegment;
|
||||
firstSegment = false;
|
||||
try {
|
||||
// If a tag is expected then read, decrypt and validate it
|
||||
if(tag) {
|
||||
int offset = 0;
|
||||
while(offset < TAG_LENGTH) {
|
||||
int read = in.read(ciphertext, offset, TAG_LENGTH - offset);
|
||||
if(read == -1) {
|
||||
if(offset == 0) return false;
|
||||
throw new EOFException();
|
||||
if(expectTag) {
|
||||
// Read the tag if we don't have one buffered
|
||||
if(bufferedTag == null) {
|
||||
int offset = 0;
|
||||
while(offset < TAG_LENGTH) {
|
||||
int read = in.read(ciphertext, offset,
|
||||
TAG_LENGTH - offset);
|
||||
if(read == -1) {
|
||||
if(offset == 0) return false;
|
||||
throw new EOFException();
|
||||
}
|
||||
offset += read;
|
||||
}
|
||||
offset += read;
|
||||
long seg = TagEncoder.decodeTag(ciphertext, tagCipher,
|
||||
tagKey);
|
||||
if(seg == -1) throw new FormatException();
|
||||
segmentNumber = seg;
|
||||
} else {
|
||||
System.out.println("Buffered tag");
|
||||
long seg = TagEncoder.decodeTag(bufferedTag, tagCipher,
|
||||
tagKey);
|
||||
bufferedTag = null;
|
||||
if(seg == -1) throw new FormatException();
|
||||
segmentNumber = seg;
|
||||
}
|
||||
long seg = TagEncoder.decodeTag(ciphertext, tagCipher, tagKey);
|
||||
if(seg == -1) throw new FormatException();
|
||||
segmentNumber = seg;
|
||||
}
|
||||
// Read the first block of the frame/segment
|
||||
int offset = 0;
|
||||
while(offset < blockSize) {
|
||||
int read = in.read(ciphertext, offset, blockSize - offset);
|
||||
if(read == -1) {
|
||||
if(offset == 0 && !tag && !firstSegment) return false;
|
||||
if(offset == 0 && !expectTag) return false;
|
||||
throw new EOFException();
|
||||
}
|
||||
offset += read;
|
||||
@@ -108,7 +122,6 @@ class IncomingEncryptionLayerImpl implements IncomingEncryptionLayer {
|
||||
}
|
||||
s.setLength(length);
|
||||
s.setSegmentNumber(segmentNumber++);
|
||||
firstSegment = false;
|
||||
return true;
|
||||
} catch(IOException e) {
|
||||
frameKey.erase();
|
||||
|
||||
@@ -13,8 +13,8 @@ import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import net.sf.briar.api.FormatException;
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.plugins.SegmentSource;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
|
||||
class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
||||
|
||||
@@ -23,15 +23,16 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
||||
private final ErasableKey tagKey, frameKey;
|
||||
private final int blockSize;
|
||||
private final byte[] iv;
|
||||
private final Segment segment;
|
||||
private final boolean tagEverySegment;
|
||||
private final Segment segment;
|
||||
|
||||
private Segment bufferedSegment;
|
||||
private boolean firstSegment = true;
|
||||
private long segmentNumber = 0L;
|
||||
|
||||
IncomingSegmentedEncryptionLayer(SegmentSource in, Cipher tagCipher,
|
||||
Cipher frameCipher, ErasableKey tagKey, ErasableKey frameKey,
|
||||
boolean tagEverySegment) {
|
||||
boolean tagEverySegment, Segment s) {
|
||||
this.in = in;
|
||||
this.tagCipher = tagCipher;
|
||||
this.frameCipher = frameCipher;
|
||||
@@ -43,20 +44,30 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
||||
throw new IllegalArgumentException();
|
||||
iv = IvEncoder.encodeIv(0L, blockSize);
|
||||
segment = new SegmentImpl();
|
||||
bufferedSegment = s;
|
||||
}
|
||||
|
||||
public boolean readSegment(Segment s) throws IOException {
|
||||
boolean tag = tagEverySegment && !firstSegment;
|
||||
boolean expectTag = tagEverySegment || firstSegment;
|
||||
firstSegment = false;
|
||||
try {
|
||||
// Read the segment
|
||||
if(!in.readSegment(segment)) return false;
|
||||
int offset = tag ? TAG_LENGTH : 0, length = segment.getLength();
|
||||
// Read the segment, unless we have one buffered
|
||||
Segment segment;
|
||||
if(bufferedSegment == null) {
|
||||
segment = this.segment;
|
||||
if(!in.readSegment(segment)) return false;
|
||||
} else {
|
||||
segment = bufferedSegment;
|
||||
bufferedSegment = null;
|
||||
}
|
||||
int offset = expectTag ? TAG_LENGTH : 0;
|
||||
int length = segment.getLength();
|
||||
if(length > MAX_SEGMENT_LENGTH) throw new FormatException();
|
||||
if(length < offset + FRAME_HEADER_LENGTH + MAC_LENGTH)
|
||||
throw new FormatException();
|
||||
byte[] ciphertext = segment.getBuffer();
|
||||
// If a tag is expected then decrypt and validate it
|
||||
if(tag) {
|
||||
if(expectTag) {
|
||||
long seg = TagEncoder.decodeTag(ciphertext, tagCipher, tagKey);
|
||||
if(seg == -1) throw new FormatException();
|
||||
segmentNumber = seg;
|
||||
@@ -74,7 +85,6 @@ class IncomingSegmentedEncryptionLayer implements IncomingEncryptionLayer {
|
||||
}
|
||||
s.setLength(length - offset);
|
||||
s.setSegmentNumber(segmentNumber++);
|
||||
firstSegment = false;
|
||||
return true;
|
||||
} catch(IOException e) {
|
||||
frameKey.erase();
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.sf.briar.transport;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
|
||||
class NullIncomingErrorCorrectionLayer implements IncomingErrorCorrectionLayer {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
|
||||
class NullOutgoingErrorCorrectionLayer implements OutgoingErrorCorrectionLayer {
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.sf.briar.transport;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
|
||||
interface OutgoingEncryptionLayer {
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
|
||||
class OutgoingEncryptionLayerImpl implements OutgoingEncryptionLayer {
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import net.sf.briar.api.crypto.ErasableKey;
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.plugins.SegmentSink;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
|
||||
class OutgoingSegmentedEncryptionLayer implements OutgoingEncryptionLayer {
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAX_SEGMENT_LENGTH;
|
||||
import net.sf.briar.api.plugins.Segment;
|
||||
import net.sf.briar.api.transport.Segment;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
class SegmentImpl implements Segment {
|
||||
|
||||
Reference in New Issue
Block a user