forked from I2P_Developers/i2p.i2p
Tunnels: Use context AES for hop processing
and related cleanups
This commit is contained in:
@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 1;
|
||||
public final static long BUILD = 2;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
@ -1,7 +1,10 @@
|
||||
package net.i2p.router.tunnel;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.AESEngine;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.SessionKey;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -28,7 +31,6 @@ class HopProcessor {
|
||||
*
|
||||
* See: http://osdir.com/ml/network.i2p/2005-07/msg00031.html
|
||||
*/
|
||||
//static final boolean USE_DOUBLE_IV_ENCRYPTION = true;
|
||||
static final int IV_LENGTH = 16;
|
||||
|
||||
/**
|
||||
@ -62,7 +64,8 @@ class HopProcessor {
|
||||
*
|
||||
* @param orig IV+data of the message
|
||||
* @param offset index into orig where the IV begins
|
||||
* @param length how long after the offset does the message go for?
|
||||
* @param length how long after the offset does the IV+message go for?
|
||||
* Should always be 1024 bytes.
|
||||
* @param prev previous hop in the tunnel, or null if we are the gateway
|
||||
* @return true if the message was updated and valid, false if it was not.
|
||||
*/
|
||||
@ -88,35 +91,24 @@ class HopProcessor {
|
||||
}
|
||||
|
||||
//if (_log.shouldLog(Log.DEBUG)) {
|
||||
//_log.debug("IV received: " + Base64.encode(iv));
|
||||
//_log.debug("Before:" + Base64.encode(orig, IV_LENGTH, orig.length - IV_LENGTH));
|
||||
//}
|
||||
//if (USE_ENCRYPTION) {
|
||||
//if (USE_DOUBLE_IV_ENCRYPTION)
|
||||
updateIV(orig, offset);
|
||||
encrypt(orig, offset, length);
|
||||
updateIV(orig, offset);
|
||||
// _log.debug("IV received before decrypt: " + Base64.encode(orig, offset, IV_LENGTH));
|
||||
// _log.debug("Data before processing:\n" + Base64.encode(orig, IV_LENGTH, orig.length - IV_LENGTH));
|
||||
//}
|
||||
|
||||
SessionKey ivkey = _config.getIVKey();
|
||||
AESEngine aes = _context.aes();
|
||||
// double IV encryption
|
||||
aes.encryptBlock(orig, offset, ivkey, orig, offset);
|
||||
aes.encrypt(orig, offset + IV_LENGTH, orig, offset + IV_LENGTH, _config.getLayerKey(),
|
||||
orig, offset, length - IV_LENGTH);
|
||||
aes.encryptBlock(orig, offset, ivkey, orig, offset);
|
||||
|
||||
//if (_log.shouldLog(Log.DEBUG)) {
|
||||
//_log.debug("Data after processing: " + Base64.encode(orig, IV_LENGTH, orig.length - IV_LENGTH));
|
||||
//_log.debug("IV sent: " + Base64.encode(orig, 0, IV_LENGTH));
|
||||
// _log.debug("IV sent: " + Base64.encode(orig, offset, IV_LENGTH));
|
||||
// _log.debug("Data after processing:\n" + Base64.encode(orig, IV_LENGTH, orig.length - IV_LENGTH));
|
||||
//}
|
||||
return true;
|
||||
}
|
||||
|
||||
private final void encrypt(byte data[], int offset, int length) {
|
||||
for (int off = offset + IV_LENGTH; off < length; off += IV_LENGTH) {
|
||||
//DataHelper.xor(data, off - IV_LENGTH, data, off, data, off, IV_LENGTH);
|
||||
for (int j = 0; j < IV_LENGTH; j++) {
|
||||
data[off + j] ^= data[(off - IV_LENGTH) + j];
|
||||
}
|
||||
_context.aes().encryptBlock(data, off, _config.getLayerKey(), data, off);
|
||||
}
|
||||
}
|
||||
|
||||
private final void updateIV(byte orig[], int offset) {
|
||||
_context.aes().encryptBlock(orig, offset, _config.getIVKey(), orig, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.8.12
|
||||
|
@ -16,6 +16,8 @@ public interface IVValidator {
|
||||
* not the IV alone (since the tunnel is encrypted via AES/CBC). Thanks to
|
||||
* dvorak for pointing out that tagging!
|
||||
*
|
||||
* @param iv data will not be modified
|
||||
* @param iv payload will not be modified
|
||||
*/
|
||||
public boolean receiveIV(byte iv[], int ivOffset, byte payload[], int payloadOffset);
|
||||
}
|
||||
|
@ -44,6 +44,10 @@ class InboundEndpointProcessor {
|
||||
* Undo all of the encryption done by the peers in the tunnel, recovering the
|
||||
* preprocessed data sent by the gateway.
|
||||
*
|
||||
* @param orig original data with an extra 16 byte IV prepended.
|
||||
* @param offset index into the array where the extra 16 bytes (IV) begins
|
||||
* @param length how much of orig can we write to (must be a multiple of 16).
|
||||
* Should always be 1024 bytes.
|
||||
* @return true if the data was recovered (and written in place to orig), false
|
||||
* if it was a duplicate or from the wrong peer.
|
||||
*/
|
||||
@ -57,29 +61,23 @@ class InboundEndpointProcessor {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte iv[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
|
||||
System.arraycopy(orig, offset, iv, 0, iv.length);
|
||||
//if (_config.getLength() > 1)
|
||||
// _log.debug("IV at inbound endpoint before decrypt: " + Base64.encode(iv));
|
||||
|
||||
boolean ok = _validator.receiveIV(iv, 0, orig, offset + HopProcessor.IV_LENGTH);
|
||||
boolean ok = _validator.receiveIV(orig, offset, orig, offset + HopProcessor.IV_LENGTH);
|
||||
if (!ok) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Invalid IV, dropping at IBEP " + _config);
|
||||
SimpleByteCache.release(iv);
|
||||
return false;
|
||||
}
|
||||
|
||||
// inbound endpoints and outbound gateways have to undo the crypto in the same way
|
||||
//if (USE_ENCRYPTION)
|
||||
decrypt(_context, _config, iv, orig, offset, length);
|
||||
|
||||
SimpleByteCache.release(iv);
|
||||
decrypt(_context, _config, orig, offset, length);
|
||||
|
||||
if (_config.getLength() > 0) {
|
||||
int rtt = 0; // dunno... may not be related to an rtt
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received a " + length + "byte message through tunnel " + _config);
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Received a " + length + "byte message through tunnel " + _config);
|
||||
ProfileManager pm = _context.profileManager();
|
||||
// null for unit tests
|
||||
if (pm != null) {
|
||||
@ -95,18 +93,21 @@ class InboundEndpointProcessor {
|
||||
|
||||
/**
|
||||
* Iteratively undo the crypto that the various layers in the tunnel added.
|
||||
*
|
||||
* @param orig original data with an extra 16 byte IV prepended.
|
||||
* @param offset index into the array where the extra 16 bytes (IV) begins
|
||||
* @param length how much of orig can we write to (must be a multiple of 16).
|
||||
* Should always be 1024 bytes.
|
||||
*/
|
||||
private void decrypt(RouterContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
|
||||
//Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
|
||||
byte cur[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
|
||||
for (int i = cfg.getLength()-2; i >= 0; i--) { // dont include the endpoint, since that is the creator
|
||||
OutboundGatewayProcessor.decrypt(ctx, iv, orig, offset, length, cur, cfg.getConfig(i));
|
||||
//if (log.shouldLog(Log.DEBUG)) {
|
||||
//log.debug("IV at hop " + i + ": " + Base64.encode(orig, offset, HopProcessor.IV_LENGTH));
|
||||
//log.debug("hop " + i + ": " + Base64.encode(orig, offset + HopProcessor.IV_LENGTH, length - HopProcessor.IV_LENGTH));
|
||||
private void decrypt(RouterContext ctx, TunnelCreatorConfig cfg, byte orig[], int offset, int length) {
|
||||
// dont include the endpoint, since that is the creator
|
||||
for (int i = cfg.getLength() - 2; i >= 0; i--) {
|
||||
OutboundGatewayProcessor.decrypt(ctx, orig, offset, length, cfg.getConfig(i));
|
||||
//if (_log.shouldLog(Log.DEBUG)) {
|
||||
//_log.debug("IV at hop " + i + ": " + Base64.encode(orig, offset, HopProcessor.IV_LENGTH));
|
||||
//_log.debug("hop " + i + ": " + Base64.encode(orig, offset + HopProcessor.IV_LENGTH, length - HopProcessor.IV_LENGTH));
|
||||
//}
|
||||
}
|
||||
SimpleByteCache.release(cur);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
package net.i2p.router.tunnel;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.AESEngine;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.SessionKey;
|
||||
import static net.i2p.router.tunnel.HopProcessor.IV_LENGTH;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SimpleByteCache;
|
||||
|
||||
@ -13,14 +16,12 @@ import net.i2p.util.SimpleByteCache;
|
||||
*/
|
||||
class OutboundGatewayProcessor {
|
||||
private final I2PAppContext _context;
|
||||
private final Log _log;
|
||||
//private final Log _log;
|
||||
private final TunnelCreatorConfig _config;
|
||||
|
||||
//static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;
|
||||
|
||||
public OutboundGatewayProcessor(I2PAppContext ctx, TunnelCreatorConfig cfg) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
|
||||
//_log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
|
||||
_config = cfg;
|
||||
}
|
||||
|
||||
@ -31,73 +32,59 @@ class OutboundGatewayProcessor {
|
||||
* @param orig original data with an extra 16 byte IV prepended.
|
||||
* @param offset index into the array where the extra 16 bytes (IV) begins
|
||||
* @param length how much of orig can we write to (must be a multiple of 16).
|
||||
* Should always be 1024 bytes.
|
||||
*/
|
||||
public void process(byte orig[], int offset, int length) {
|
||||
byte iv[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
|
||||
//_context.random().nextBytes(iv);
|
||||
//System.arraycopy(iv, 0, orig, offset, HopProcessor.IV_LENGTH);
|
||||
System.arraycopy(orig, offset, iv, 0, HopProcessor.IV_LENGTH);
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG)) {
|
||||
_log.debug("Orig random IV: " + Base64.encode(iv));
|
||||
//_log.debug("data: " + Base64.encode(orig, iv.length, length - iv.length));
|
||||
}
|
||||
//if (USE_ENCRYPTION)
|
||||
decrypt(_context, _config, iv, orig, offset, length);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("finished processing the preprocessed data");
|
||||
SimpleByteCache.release(iv);
|
||||
//if (_log.shouldLog(Log.DEBUG)) {
|
||||
// _log.debug("Orig random IV: " + Base64.encode(orig, offset, IV_LENGTH));
|
||||
// _log.debug("data: " + Base64.encode(orig, IV_LENGTH, length - IV_LENGTH));
|
||||
//}
|
||||
decrypt(_config, orig, offset, length);
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("finished processing the preprocessed data");
|
||||
}
|
||||
|
||||
/**
|
||||
* Iteratively undo the crypto that the various layers in the tunnel added. This is used
|
||||
* by the outbound gateway (preemptively undoing the crypto peers will add).
|
||||
*
|
||||
* @param orig original data with an extra 16 byte IV prepended.
|
||||
* @param offset index into the array where the extra 16 bytes (IV) begins
|
||||
* @param length how much of orig can we write to (must be a multiple of 16).
|
||||
* Should always be 1024 bytes.
|
||||
*/
|
||||
private void decrypt(I2PAppContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
|
||||
Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
|
||||
byte cur[] = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
|
||||
for (int i = cfg.getLength()-1; i >= 1; i--) { // dont include hop 0, since that is the creator
|
||||
decrypt(ctx, iv, orig, offset, length, cur, cfg.getConfig(i));
|
||||
if (log.shouldLog(Log.DEBUG)) {
|
||||
log.debug("IV at hop " + i + ": " + Base64.encode(orig, offset, HopProcessor.IV_LENGTH));
|
||||
//log.debug("hop " + i + ": " + Base64.encode(orig, offset + HopProcessor.IV_LENGTH, length - HopProcessor.IV_LENGTH));
|
||||
}
|
||||
private void decrypt(TunnelCreatorConfig cfg, byte orig[], int offset, int length) {
|
||||
// dont include hop 0, since that is the creator
|
||||
for (int i = cfg.getLength() - 1; i >= 1; i--) {
|
||||
decrypt(_context, orig, offset, length, cfg.getConfig(i));
|
||||
//if (_log.shouldDebug()) {
|
||||
// _log.debug("IV at hop " + i + " before decrypt: " + Base64.encode(orig, offset, IV_LENGTH));
|
||||
// _log.debug("hop " + i + ": " + Base64.encode(orig, offset + IV_LENGTH, length - IV_LENGTH));
|
||||
//}
|
||||
}
|
||||
SimpleByteCache.release(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the crypto for a single hop. This is used
|
||||
* by both the outbound gateway (preemptively undoing the crypto peers will add)
|
||||
* and by the inbound endpoint.
|
||||
*
|
||||
* @param orig original data with an extra 16 byte IV prepended.
|
||||
* @param offset index into the array where the extra 16 bytes (IV) begins
|
||||
* @param length how much of orig can we write to (must be a multiple of 16).
|
||||
* Should always be 1024 bytes.
|
||||
*/
|
||||
static void decrypt(I2PAppContext ctx, byte iv[], byte orig[], int offset, int length, byte cur[], HopConfig config) {
|
||||
static void decrypt(I2PAppContext ctx, byte orig[], int offset, int length, HopConfig config) {
|
||||
SessionKey ivkey = config.getIVKey();
|
||||
AESEngine aes = ctx.aes();
|
||||
// update the IV for the previous (next?) hop
|
||||
ctx.aes().decryptBlock(orig, offset, config.getIVKey(), orig, offset);
|
||||
|
||||
int numBlocks = (length - HopProcessor.IV_LENGTH) / HopProcessor.IV_LENGTH;
|
||||
|
||||
// prev == previous encrypted block (or IV for the first block)
|
||||
byte prev[] = iv;
|
||||
System.arraycopy(orig, offset, prev, 0, HopProcessor.IV_LENGTH);
|
||||
//_log.debug("IV at curHop: " + Base64.encode(iv));
|
||||
|
||||
//decrypt the whole row
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
int off = (i + 1) * HopProcessor.IV_LENGTH + offset;
|
||||
|
||||
System.arraycopy(orig, off, cur, 0, HopProcessor.IV_LENGTH);
|
||||
ctx.aes().decryptBlock(orig, off, config.getLayerKey(), orig, off);
|
||||
//DataHelper.xor(prev, 0, orig, off, orig, off, HopProcessor.IV_LENGTH);
|
||||
for (int j = 0; j < HopProcessor.IV_LENGTH; j++) {
|
||||
orig[off + j] ^= prev[j];
|
||||
}
|
||||
byte xf[] = prev;
|
||||
prev = cur;
|
||||
cur = xf;
|
||||
}
|
||||
|
||||
//if (HopProcessor.USE_DOUBLE_IV_ENCRYPTION)
|
||||
ctx.aes().decryptBlock(orig, offset, config.getIVKey(), orig, offset);
|
||||
aes.decryptBlock(orig, offset, ivkey, orig, offset);
|
||||
//Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
|
||||
//log.debug("IV at curHop after decrypt: " + Base64.encode(orig, offset, IV_LENGTH));
|
||||
aes.decrypt(orig, offset + IV_LENGTH, orig, offset + IV_LENGTH, config.getLayerKey(),
|
||||
orig, offset, length - IV_LENGTH);
|
||||
// double IV encryption
|
||||
aes.decryptBlock(orig, offset, ivkey, orig, offset);
|
||||
//log.debug("IV at curHop after double decrypt: " + Base64.encode(orig, offset, IV_LENGTH));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user