Tunnels: Move AES reply keys from HopConfig to TunnelCreatorConfig

to save space; not stored for participating tunnels.
This commit is contained in:
zzz
2020-10-23 12:58:45 +00:00
parent c84360ba4b
commit 4a4d814a17
6 changed files with 64 additions and 61 deletions

View File

@ -96,12 +96,10 @@ public abstract class BuildMessageGenerator {
} }
SessionKey layerKey = hopConfig.getLayerKey(); SessionKey layerKey = hopConfig.getLayerKey();
SessionKey ivKey = hopConfig.getIVKey(); SessionKey ivKey = hopConfig.getIVKey();
SessionKey replyKey = hopConfig.getReplyKey(); SessionKey replyKey = cfg.getAESReplyKey(hop);
byte iv[] = hopConfig.getReplyIV(); byte iv[] = cfg.getAESReplyIV(hop);
if (iv == null) { if (iv == null) {
iv = new byte[BuildRequestRecord.IV_SIZE]; throw new IllegalStateException();
ctx.random().nextBytes(iv);
hopConfig.setReplyIV(iv);
} }
boolean isInGW = (cfg.isInbound() && (hop == 0)); boolean isInGW = (cfg.isInbound() && (hop == 0));
boolean isOutEnd = (!cfg.isInbound() && (hop + 1 >= cfg.getLength())); boolean isOutEnd = (!cfg.isInbound() && (hop + 1 >= cfg.getLength()));
@ -152,9 +150,8 @@ public abstract class BuildMessageGenerator {
// ok, now decrypt the record with all of the reply keys from cfg.getConfig(0) through hop-1 // ok, now decrypt the record with all of the reply keys from cfg.getConfig(0) through hop-1
int stop = (cfg.isInbound() ? 0 : 1); int stop = (cfg.isInbound() ? 0 : 1);
for (int j = hop-1; j >= stop; j--) { for (int j = hop-1; j >= stop; j--) {
HopConfig hopConfig = cfg.getConfig(j); SessionKey key = cfg.getAESReplyKey(j);
SessionKey key = hopConfig.getReplyKey(); byte iv[] = cfg.getAESReplyIV(j);
byte iv[] = hopConfig.getReplyIV();
// corrupts the SDS // corrupts the SDS
ctx.aes().decrypt(rec.getData(), 0, rec.getData(), 0, key, iv, TunnelBuildMessage.RECORD_SIZE); ctx.aes().decrypt(rec.getData(), 0, rec.getData(), 0, key, iv, TunnelBuildMessage.RECORD_SIZE);
} }

View File

@ -108,9 +108,8 @@ public class BuildReplyHandler {
end++; end++;
// do we need to adjust this for the endpoint? // do we need to adjust this for the endpoint?
for (int j = start; j >= end; j--) { for (int j = start; j >= end; j--) {
HopConfig hopConfig = cfg.getConfig(j); SessionKey replyKey = cfg.getAESReplyKey(j);
SessionKey replyKey = hopConfig.getReplyKey(); byte replyIV[] = cfg.getAESReplyIV(j);
byte replyIV[] = hopConfig.getReplyIV();
if (log.shouldLog(Log.DEBUG)) { if (log.shouldLog(Log.DEBUG)) {
log.debug(reply.getUniqueId() + ": Decrypting record " + recordNum + "/" + hop + "/" + j + " with replyKey " log.debug(reply.getUniqueId() + ": Decrypting record " + recordNum + "/" + hop + "/" + j + " with replyKey "
+ replyKey.toBase64() + "/" + Base64.encode(replyIV) + ": " + cfg); + replyKey.toBase64() + "/" + Base64.encode(replyIV) + ": " + cfg);

View File

@ -37,9 +37,6 @@ public class HopConfig {
//private int _messagesSent; //private int _messagesSent;
//private int _oldMessagesSent; //private int _oldMessagesSent;
/** IV length for {@link #getReplyIV} */
public static final int REPLY_IV_LENGTH = 16;
public HopConfig() { public HopConfig() {
_creation = -1; _creation = -1;
_expiration = -1; _expiration = -1;
@ -90,35 +87,6 @@ public class HopConfig {
public SessionKey getIVKey() { return _ivKey; } public SessionKey getIVKey() { return _ivKey; }
public void setIVKey(SessionKey key) { _ivKey = key; } public void setIVKey(SessionKey key) { _ivKey = key; }
/**
* Key to encrypt the reply sent for the tunnel creation crypto.
* Not used for participating tunnels, will return null,
* candidate for moving to TunnelCreatorConfig.
* @return key or null
*/
public SessionKey getReplyKey() { return _replyKey; }
public void setReplyKey(SessionKey key) { _replyKey = key; }
/**
* IV used to encrypt the reply sent for the tunnel creation crypto.
* Not used for participating tunnels, will return null,
* candidate for moving to TunnelCreatorConfig.
*
* @return 16 bytes or null
*/
public byte[] getReplyIV() { return _replyIV; }
/**
* IV used to encrypt the reply sent for the tunnel creation crypto
*
* @throws IllegalArgumentException if not 16 bytes
*/
public void setReplyIV(byte[] iv) {
if (iv.length != REPLY_IV_LENGTH)
throw new IllegalArgumentException();
_replyIV = iv;
}
/** when does this tunnel expire (in ms since the epoch)? */ /** when does this tunnel expire (in ms since the epoch)? */
public long getExpiration() { return _expiration; } public long getExpiration() { return _expiration; }
public void setExpiration(long when) { _expiration = when; } public void setExpiration(long when) { _expiration = when; }

View File

@ -41,8 +41,16 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
private long _peakThroughputCurrentTotal; private long _peakThroughputCurrentTotal;
private long _peakThroughputLastCoallesce = System.currentTimeMillis(); private long _peakThroughputLastCoallesce = System.currentTimeMillis();
private Hash _blankHash; private Hash _blankHash;
private SessionKey[] _replyKeys; private SessionKey[] _ChaReplyKeys;
private byte[][] _replyADs; private byte[][] _ChaReplyADs;
private final SessionKey[] _AESReplyKeys;
private final byte[][] _AESReplyIVs;
/**
* IV length for {@link #getAESReplyIV}
* @since 0.9.48 moved from HopConfig
*/
public static final int REPLY_IV_LENGTH = 16;
// Make configurable? - but can't easily get to pool options from here // Make configurable? - but can't easily get to pool options from here
private static final int MAX_CONSECUTIVE_TEST_FAILURES = 3; private static final int MAX_CONSECUTIVE_TEST_FAILURES = 3;
@ -70,6 +78,8 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
} }
_isInbound = isInbound; _isInbound = isInbound;
_destination = destination; _destination = destination;
_AESReplyKeys = new SessionKey[length];
_AESReplyIVs = new byte[length][];
} }
/** /**
@ -243,6 +253,36 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
*/ */
public void setPriority(int priority) { _priority = priority; } public void setPriority(int priority) { _priority = priority; }
/**
* Key and IV to encrypt the reply sent for the tunnel creation crypto.
*
* @throws IllegalArgumentException if iv not 16 bytes
* @since 0.9.48 moved from HopConfig
*/
public void setAESReplyKeys(int hop, SessionKey key, byte[] iv) {
if (iv.length != REPLY_IV_LENGTH)
throw new IllegalArgumentException();
_AESReplyKeys[hop] = key;
_AESReplyIVs[hop] = iv;
}
/**
* Key to encrypt the reply sent for the tunnel creation crypto.
*
* @return key or null
* @throws IllegalArgumentException if iv not 16 bytes
* @since 0.9.48 moved from HopConfig
*/
public SessionKey getAESReplyKey(int hop) { return _AESReplyKeys[hop]; }
/**
* IV used to encrypt the reply sent for the tunnel creation crypto.
*
* @return 16 bytes or null
* @since 0.9.48 moved from HopConfig
*/
public byte[] getAESReplyIV(int hop) { return _AESReplyIVs[hop]; }
/** /**
* Checksum for blank record * Checksum for blank record
* @since 0.9.48 * @since 0.9.48
@ -260,12 +300,12 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* @since 0.9.48 * @since 0.9.48
*/ */
public void setChaChaReplyKeys(int hop, SessionKey key, byte[] ad) { public void setChaChaReplyKeys(int hop, SessionKey key, byte[] ad) {
if (_replyKeys == null) { if (_ChaReplyKeys == null) {
_replyKeys = new SessionKey[_config.length]; _ChaReplyKeys = new SessionKey[_config.length];
_replyADs = new byte[_config.length][]; _ChaReplyADs = new byte[_config.length][];
} }
_replyKeys[hop] = key; _ChaReplyKeys[hop] = key;
_replyADs[hop] = ad; _ChaReplyADs[hop] = ad;
} }
/** /**
@ -273,9 +313,9 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* @since 0.9.48 * @since 0.9.48
*/ */
public boolean isEC(int hop) { public boolean isEC(int hop) {
if (_replyKeys == null) if (_ChaReplyKeys == null)
return false; return false;
return _replyKeys[hop] != null; return _ChaReplyKeys[hop] != null;
} }
/** /**
@ -283,9 +323,9 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* @since 0.9.48 * @since 0.9.48
*/ */
public SessionKey getChaChaReplyKey(int hop) { public SessionKey getChaChaReplyKey(int hop) {
if (_replyKeys == null) if (_ChaReplyKeys == null)
return null; return null;
return _replyKeys[hop]; return _ChaReplyKeys[hop];
} }
/** /**
@ -293,9 +333,9 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* @since 0.9.48 * @since 0.9.48
*/ */
public byte[] getChaChaReplyAD(int hop) { public byte[] getChaChaReplyAD(int hop) {
if (_replyADs == null) if (_ChaReplyADs == null)
return null; return null;
return _replyADs[hop]; return _ChaReplyADs[hop];
} }
@Override @Override

View File

@ -19,6 +19,7 @@ import net.i2p.router.TunnelManagerFacade;
import net.i2p.router.TunnelPoolSettings; import net.i2p.router.TunnelPoolSettings;
import net.i2p.router.tunnel.BuildMessageGenerator; import net.i2p.router.tunnel.BuildMessageGenerator;
import net.i2p.router.tunnel.HopConfig; import net.i2p.router.tunnel.HopConfig;
import net.i2p.router.tunnel.TunnelCreatorConfig;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
@ -104,10 +105,9 @@ abstract class BuildRequestor {
if (i > 0) if (i > 0)
cfg.getConfig(i-1).setSendTunnelId(hop.getReceiveTunnelId()); cfg.getConfig(i-1).setSendTunnelId(hop.getReceiveTunnelId());
byte iv[] = new byte[16]; byte iv[] = new byte[TunnelCreatorConfig.REPLY_IV_LENGTH];
ctx.random().nextBytes(iv); ctx.random().nextBytes(iv);
hop.setReplyIV(iv); cfg.setAESReplyKeys(i, ctx.keyGenerator().generateSessionKey(), iv);
hop.setReplyKey(ctx.keyGenerator().generateSessionKey());
} }
// This is in BuildExecutor.buildTunnel() now // This is in BuildExecutor.buildTunnel() now
// And it was overwritten by the one in createTunnelBuildMessage() anyway! // And it was overwritten by the one in createTunnelBuildMessage() anyway!

View File

@ -172,10 +172,9 @@ public class BuildMessageTestStandalone extends TestCase {
hop.setExpiration(now+10*60*1000); hop.setExpiration(now+10*60*1000);
hop.setIVKey(ctx.keyGenerator().generateSessionKey()); hop.setIVKey(ctx.keyGenerator().generateSessionKey());
hop.setLayerKey(ctx.keyGenerator().generateSessionKey()); hop.setLayerKey(ctx.keyGenerator().generateSessionKey());
hop.setReplyKey(ctx.keyGenerator().generateSessionKey());
byte iv[] = new byte[BuildRequestRecord.IV_SIZE]; byte iv[] = new byte[BuildRequestRecord.IV_SIZE];
Arrays.fill(iv, (byte)i); // consistent for repeatability Arrays.fill(iv, (byte)i); // consistent for repeatability
hop.setReplyIV(iv); cfg.setAESReplyKeys(i, ctx.keyGenerator().generateSessionKey(), iv);
hop.setReceiveTunnelId(new TunnelId(i+1)); hop.setReceiveTunnelId(new TunnelId(i+1));
} }
return cfg; return cfg;