mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 05:39:53 +01:00
Removed the initiator flag from the IV (no longer needed with the new
key derivation rules).
This commit is contained in:
@@ -44,7 +44,9 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
|||||||
}
|
}
|
||||||
ivKey.erase();
|
ivKey.erase();
|
||||||
// Validate the IV
|
// Validate the IV
|
||||||
if(!IvEncoder.validateIv(iv, true, ctx))
|
int index = ctx.getTransportIndex().getInt();
|
||||||
|
long connection = ctx.getConnectionNumber();
|
||||||
|
if(!IvEncoder.validateIv(iv, index, connection))
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
return createConnectionReader(in, true, ctx);
|
return createConnectionReader(in, true, ctx);
|
||||||
}
|
}
|
||||||
@@ -62,7 +64,9 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
|||||||
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
||||||
ByteUtils.erase(secret);
|
ByteUtils.erase(secret);
|
||||||
// Create the decrypter
|
// Create the decrypter
|
||||||
byte[] iv = IvEncoder.encodeIv(initiator, ctx);
|
int index = ctx.getTransportIndex().getInt();
|
||||||
|
long connection = ctx.getConnectionNumber();
|
||||||
|
byte[] iv = IvEncoder.encodeIv(index, connection);
|
||||||
Cipher frameCipher = crypto.getFrameCipher();
|
Cipher frameCipher = crypto.getFrameCipher();
|
||||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
||||||
frameCipher, frameKey);
|
frameCipher, frameKey);
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ DatabaseListener {
|
|||||||
|
|
||||||
// Locking: this
|
// Locking: this
|
||||||
private Bytes calculateIv(Context ctx, byte[] secret) {
|
private Bytes calculateIv(Context ctx, byte[] secret) {
|
||||||
byte[] iv = IvEncoder.encodeIv(true, ctx.transportIndex.getInt(),
|
byte[] iv = IvEncoder.encodeIv(ctx.transportIndex.getInt(),
|
||||||
ctx.connection);
|
ctx.connection);
|
||||||
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
|||||||
}
|
}
|
||||||
ivKey.erase();
|
ivKey.erase();
|
||||||
// Validate the IV
|
// Validate the IV
|
||||||
if(!IvEncoder.validateIv(iv, true, ctx))
|
int index = ctx.getTransportIndex().getInt();
|
||||||
|
long connection = ctx.getConnectionNumber();
|
||||||
|
if(!IvEncoder.validateIv(iv, index, connection))
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
return createConnectionWriter(out, capacity, false, ctx);
|
return createConnectionWriter(out, capacity, false, ctx);
|
||||||
}
|
}
|
||||||
@@ -63,9 +65,11 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
|||||||
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
ErasableKey macKey = crypto.deriveMacKey(secret, initiator);
|
||||||
ByteUtils.erase(secret);
|
ByteUtils.erase(secret);
|
||||||
// Create the encrypter
|
// Create the encrypter
|
||||||
|
int index = ctx.getTransportIndex().getInt();
|
||||||
|
long connection = ctx.getConnectionNumber();
|
||||||
|
byte[] iv = IvEncoder.encodeIv(index, connection);
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
Cipher frameCipher = crypto.getFrameCipher();
|
Cipher frameCipher = crypto.getFrameCipher();
|
||||||
byte[] iv = IvEncoder.encodeIv(initiator, ctx);
|
|
||||||
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
||||||
capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
|
capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
|
||||||
// Create the writer
|
// Create the writer
|
||||||
|
|||||||
@@ -1,20 +1,12 @@
|
|||||||
package net.sf.briar.transport;
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||||
import net.sf.briar.api.transport.ConnectionContext;
|
|
||||||
import net.sf.briar.util.ByteUtils;
|
import net.sf.briar.util.ByteUtils;
|
||||||
|
|
||||||
class IvEncoder {
|
class IvEncoder {
|
||||||
|
|
||||||
static byte[] encodeIv(boolean initiator, ConnectionContext ctx) {
|
static byte[] encodeIv(int index, long connection) {
|
||||||
return encodeIv(initiator, ctx.getTransportIndex().getInt(),
|
|
||||||
ctx.getConnectionNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
static byte[] encodeIv(boolean initiator, int index, long connection) {
|
|
||||||
byte[] iv = new byte[IV_LENGTH];
|
byte[] iv = new byte[IV_LENGTH];
|
||||||
// Bit 31 is the initiator flag
|
|
||||||
if(initiator) iv[3] = 1;
|
|
||||||
// Encode the transport index as an unsigned 16-bit integer
|
// Encode the transport index as an unsigned 16-bit integer
|
||||||
ByteUtils.writeUint16(index, iv, 4);
|
ByteUtils.writeUint16(index, iv, 4);
|
||||||
// Encode the connection number as an unsigned 32-bit integer
|
// Encode the connection number as an unsigned 32-bit integer
|
||||||
@@ -28,21 +20,11 @@ class IvEncoder {
|
|||||||
ByteUtils.writeUint32(frame, iv, 10);
|
ByteUtils.writeUint32(frame, iv, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean validateIv(byte[] iv, boolean initiator,
|
static boolean validateIv(byte[] iv, int index, long connection) {
|
||||||
ConnectionContext ctx) {
|
|
||||||
return validateIv(iv, initiator, ctx.getTransportIndex().getInt(),
|
|
||||||
ctx.getConnectionNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean validateIv(byte[] iv, boolean initiator, int index,
|
|
||||||
long connection) {
|
|
||||||
if(iv.length != IV_LENGTH) return false;
|
if(iv.length != IV_LENGTH) return false;
|
||||||
// Check that the reserved bits are all zero
|
// Check that the reserved bits are all zero
|
||||||
for(int j = 0; j < 2; j++) if(iv[j] != 0) return false;
|
for(int i = 0; i < 3; i++) if(iv[i] != 0) return false;
|
||||||
if(iv[3] != 0 && iv[3] != 1) return false;
|
for(int i = 10; i < iv.length; i++) if(iv[i] != 0) return false;
|
||||||
for(int j = 10; j < iv.length; j++) if(iv[j] != 0) return false;
|
|
||||||
// Check that the initiator flag matches
|
|
||||||
if(initiator != getInitiatorFlag(iv)) return false;
|
|
||||||
// Check that the transport index matches
|
// Check that the transport index matches
|
||||||
if(index != getTransportIndex(iv)) return false;
|
if(index != getTransportIndex(iv)) return false;
|
||||||
// Check that the connection number matches
|
// Check that the connection number matches
|
||||||
@@ -51,11 +33,6 @@ class IvEncoder {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean getInitiatorFlag(byte[] iv) {
|
|
||||||
if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
|
|
||||||
return (iv[3] & 1) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getTransportIndex(byte[] iv) {
|
static int getTransportIndex(byte[] iv) {
|
||||||
if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
|
if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
|
||||||
return ByteUtils.readUint16(iv, 4);
|
return ByteUtils.readUint16(iv, 4);
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ public class ConnectionDecrypterImplTest extends TestCase {
|
|||||||
|
|
||||||
private void testDecryption(boolean initiator) throws Exception {
|
private void testDecryption(boolean initiator) throws Exception {
|
||||||
// Calculate the plaintext and ciphertext for the IV
|
// Calculate the plaintext and ciphertext for the IV
|
||||||
byte[] iv = IvEncoder.encodeIv(initiator, transportIndex.getInt(),
|
byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||||
connection);
|
|
||||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||||
byte[] encryptedIv = ivCipher.doFinal(iv);
|
byte[] encryptedIv = ivCipher.doFinal(iv);
|
||||||
assertEquals(IV_LENGTH, encryptedIv.length);
|
assertEquals(IV_LENGTH, encryptedIv.length);
|
||||||
@@ -86,8 +85,8 @@ public class ConnectionDecrypterImplTest extends TestCase {
|
|||||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||||
// Use a ConnectionDecrypter to decrypt the ciphertext
|
// Use a ConnectionDecrypter to decrypt the ciphertext
|
||||||
ConnectionDecrypter d = new ConnectionDecrypterImpl(in,
|
ConnectionDecrypter d = new ConnectionDecrypterImpl(in,
|
||||||
IvEncoder.encodeIv(initiator, transportIndex.getInt(),
|
IvEncoder.encodeIv(transportIndex.getInt(), connection),
|
||||||
connection), frameCipher, frameKey);
|
frameCipher, frameKey);
|
||||||
// First frame
|
// First frame
|
||||||
byte[] decrypted = new byte[ciphertext.length];
|
byte[] decrypted = new byte[ciphertext.length];
|
||||||
TestUtils.readFully(d.getInputStream(), decrypted);
|
TestUtils.readFully(d.getInputStream(), decrypted);
|
||||||
|
|||||||
@@ -50,8 +50,7 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
|||||||
|
|
||||||
private void testEncryption(boolean initiator) throws Exception {
|
private void testEncryption(boolean initiator) throws Exception {
|
||||||
// Calculate the expected ciphertext for the IV
|
// Calculate the expected ciphertext for the IV
|
||||||
byte[] iv = IvEncoder.encodeIv(initiator, transportIndex.getInt(),
|
byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||||
connection);
|
|
||||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||||
byte[] encryptedIv = ivCipher.doFinal(iv);
|
byte[] encryptedIv = ivCipher.doFinal(iv);
|
||||||
assertEquals(IV_LENGTH, encryptedIv.length);
|
assertEquals(IV_LENGTH, encryptedIv.length);
|
||||||
@@ -83,7 +82,7 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
|||||||
byte[] expected = out.toByteArray();
|
byte[] expected = out.toByteArray();
|
||||||
// Use a ConnectionEncrypter to encrypt the plaintext
|
// Use a ConnectionEncrypter to encrypt the plaintext
|
||||||
out.reset();
|
out.reset();
|
||||||
iv = IvEncoder.encodeIv(initiator, transportIndex.getInt(), connection);
|
iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||||
ConnectionEncrypter e = new ConnectionEncrypterImpl(out, Long.MAX_VALUE,
|
ConnectionEncrypter e = new ConnectionEncrypterImpl(out, Long.MAX_VALUE,
|
||||||
iv, ivCipher, frameCipher, ivKey, frameKey);
|
iv, ivCipher, frameCipher, ivKey, frameKey);
|
||||||
e.getOutputStream().write(plaintext);
|
e.getOutputStream().write(plaintext);
|
||||||
|
|||||||
@@ -618,7 +618,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
ErasableKey ivKey = crypto.deriveIvKey(secret, true);
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||||
byte[] iv = IvEncoder.encodeIv(true, remoteIndex.getInt(), 3);
|
byte[] iv = IvEncoder.encodeIv(remoteIndex.getInt(), 3);
|
||||||
return ivCipher.doFinal(iv);
|
return ivCipher.doFinal(iv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,8 +64,7 @@ public class FrameReadWriteTest extends TestCase {
|
|||||||
|
|
||||||
private void testWriteAndRead(boolean initiator) throws Exception {
|
private void testWriteAndRead(boolean initiator) throws Exception {
|
||||||
// Create and encrypt the IV
|
// Create and encrypt the IV
|
||||||
byte[] iv = IvEncoder.encodeIv(initiator, transportIndex.getInt(),
|
byte[] iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||||
connection);
|
|
||||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||||
byte[] encryptedIv = ivCipher.doFinal(iv);
|
byte[] encryptedIv = ivCipher.doFinal(iv);
|
||||||
assertEquals(IV_LENGTH, encryptedIv.length);
|
assertEquals(IV_LENGTH, encryptedIv.length);
|
||||||
@@ -97,7 +96,7 @@ public class FrameReadWriteTest extends TestCase {
|
|||||||
// Decrypt the IV
|
// Decrypt the IV
|
||||||
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
||||||
byte[] recoveredIv = ivCipher.doFinal(recoveredEncryptedIv);
|
byte[] recoveredIv = ivCipher.doFinal(recoveredEncryptedIv);
|
||||||
iv = IvEncoder.encodeIv(initiator, transportIndex.getInt(), connection);
|
iv = IvEncoder.encodeIv(transportIndex.getInt(), connection);
|
||||||
assertArrayEquals(iv, recoveredIv);
|
assertArrayEquals(iv, recoveredIv);
|
||||||
// Read the frames back
|
// Read the frames back
|
||||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
||||||
|
|||||||
Reference in New Issue
Block a user