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 ivKey = hopConfig.getIVKey();
SessionKey replyKey = hopConfig.getReplyKey();
byte iv[] = hopConfig.getReplyIV();
SessionKey replyKey = cfg.getAESReplyKey(hop);
byte iv[] = cfg.getAESReplyIV(hop);
if (iv == null) {
iv = new byte[BuildRequestRecord.IV_SIZE];
ctx.random().nextBytes(iv);
hopConfig.setReplyIV(iv);
throw new IllegalStateException();
}
boolean isInGW = (cfg.isInbound() && (hop == 0));
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
int stop = (cfg.isInbound() ? 0 : 1);
for (int j = hop-1; j >= stop; j--) {
HopConfig hopConfig = cfg.getConfig(j);
SessionKey key = hopConfig.getReplyKey();
byte iv[] = hopConfig.getReplyIV();
SessionKey key = cfg.getAESReplyKey(j);
byte iv[] = cfg.getAESReplyIV(j);
// corrupts the SDS
ctx.aes().decrypt(rec.getData(), 0, rec.getData(), 0, key, iv, TunnelBuildMessage.RECORD_SIZE);
}

View File

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

View File

@ -37,9 +37,6 @@ public class HopConfig {
//private int _messagesSent;
//private int _oldMessagesSent;
/** IV length for {@link #getReplyIV} */
public static final int REPLY_IV_LENGTH = 16;
public HopConfig() {
_creation = -1;
_expiration = -1;
@ -90,35 +87,6 @@ public class HopConfig {
public SessionKey getIVKey() { return _ivKey; }
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)? */
public long getExpiration() { return _expiration; }
public void setExpiration(long when) { _expiration = when; }

View File

@ -41,8 +41,16 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
private long _peakThroughputCurrentTotal;
private long _peakThroughputLastCoallesce = System.currentTimeMillis();
private Hash _blankHash;
private SessionKey[] _replyKeys;
private byte[][] _replyADs;
private SessionKey[] _ChaReplyKeys;
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
private static final int MAX_CONSECUTIVE_TEST_FAILURES = 3;
@ -70,6 +78,8 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
}
_isInbound = isInbound;
_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; }
/**
* 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
* @since 0.9.48
@ -260,12 +300,12 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* @since 0.9.48
*/
public void setChaChaReplyKeys(int hop, SessionKey key, byte[] ad) {
if (_replyKeys == null) {
_replyKeys = new SessionKey[_config.length];
_replyADs = new byte[_config.length][];
if (_ChaReplyKeys == null) {
_ChaReplyKeys = new SessionKey[_config.length];
_ChaReplyADs = new byte[_config.length][];
}
_replyKeys[hop] = key;
_replyADs[hop] = ad;
_ChaReplyKeys[hop] = key;
_ChaReplyADs[hop] = ad;
}
/**
@ -273,9 +313,9 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* @since 0.9.48
*/
public boolean isEC(int hop) {
if (_replyKeys == null)
if (_ChaReplyKeys == null)
return false;
return _replyKeys[hop] != null;
return _ChaReplyKeys[hop] != null;
}
/**
@ -283,9 +323,9 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* @since 0.9.48
*/
public SessionKey getChaChaReplyKey(int hop) {
if (_replyKeys == null)
if (_ChaReplyKeys == null)
return null;
return _replyKeys[hop];
return _ChaReplyKeys[hop];
}
/**
@ -293,9 +333,9 @@ public abstract class TunnelCreatorConfig implements TunnelInfo {
* @since 0.9.48
*/
public byte[] getChaChaReplyAD(int hop) {
if (_replyADs == null)
if (_ChaReplyADs == null)
return null;
return _replyADs[hop];
return _ChaReplyADs[hop];
}
@Override

View File

@ -19,6 +19,7 @@ import net.i2p.router.TunnelManagerFacade;
import net.i2p.router.TunnelPoolSettings;
import net.i2p.router.tunnel.BuildMessageGenerator;
import net.i2p.router.tunnel.HopConfig;
import net.i2p.router.tunnel.TunnelCreatorConfig;
import net.i2p.util.Log;
import net.i2p.util.VersionComparator;
@ -104,10 +105,9 @@ abstract class BuildRequestor {
if (i > 0)
cfg.getConfig(i-1).setSendTunnelId(hop.getReceiveTunnelId());
byte iv[] = new byte[16];
byte iv[] = new byte[TunnelCreatorConfig.REPLY_IV_LENGTH];
ctx.random().nextBytes(iv);
hop.setReplyIV(iv);
hop.setReplyKey(ctx.keyGenerator().generateSessionKey());
cfg.setAESReplyKeys(i, ctx.keyGenerator().generateSessionKey(), iv);
}
// This is in BuildExecutor.buildTunnel() now
// 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.setIVKey(ctx.keyGenerator().generateSessionKey());
hop.setLayerKey(ctx.keyGenerator().generateSessionKey());
hop.setReplyKey(ctx.keyGenerator().generateSessionKey());
byte iv[] = new byte[BuildRequestRecord.IV_SIZE];
Arrays.fill(iv, (byte)i); // consistent for repeatability
hop.setReplyIV(iv);
cfg.setAESReplyKeys(i, ctx.keyGenerator().generateSessionKey(), iv);
hop.setReceiveTunnelId(new TunnelId(i+1));
}
return cfg;