diff --git a/build.xml b/build.xml index ace3210a52..c3aaba208d 100644 --- a/build.xml +++ b/build.xml @@ -825,9 +825,9 @@ additionalparam="-notimestamp" doctitle="I2P Javadocs for Release ${release.number} Build ${i2p.build.number}${build.extra}" windowtitle="I2P Anonymous Network - Java Documentation - Version ${release.number}"> - + - + @@ -919,8 +919,8 @@ splitindex="true" doctitle="I2P Unit Test Javadocs for Release ${release.number} Build ${i2p.build.number}${build.extra}" windowtitle="I2P Anonymous Network - Java Documentation - Version ${release.number}"> - - + + diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java index 49c7223ea3..14aa275a40 100644 --- a/core/java/src/net/i2p/I2PAppContext.java +++ b/core/java/src/net/i2p/I2PAppContext.java @@ -15,7 +15,6 @@ import net.i2p.crypto.CryptixAESEngine; import net.i2p.crypto.DSAEngine; import net.i2p.crypto.ElGamalEngine; import net.i2p.crypto.HMAC256Generator; -import net.i2p.crypto.HMACGenerator; import net.i2p.crypto.KeyGenerator; import net.i2p.crypto.SHA256Generator; import net.i2p.crypto.SessionKeyManager; @@ -76,7 +75,6 @@ public class I2PAppContext { private ElGamalEngine _elGamalEngine; private AESEngine _AESEngine; private LogManager _logManager; - private HMACGenerator _hmac; private HMAC256Generator _hmac256; private SHA256Generator _sha; protected Clock _clock; // overridden in RouterContext @@ -95,7 +93,6 @@ public class I2PAppContext { private volatile boolean _elGamalEngineInitialized; private volatile boolean _AESEngineInitialized; private volatile boolean _logManagerInitialized; - private volatile boolean _hmacInitialized; private volatile boolean _hmac256Initialized; private volatile boolean _shaInitialized; protected volatile boolean _clockInitialized; // used in RouterContext @@ -119,7 +116,7 @@ public class I2PAppContext { // split up big lock on this to avoid deadlocks private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object(), _lock4 = new Object(), _lock5 = new Object(), _lock7 = new Object(), _lock8 = new Object(), - _lock9 = new Object(), _lock10 = new Object(), _lock11 = new Object(), _lock12 = new Object(), + _lock10 = new Object(), _lock11 = new Object(), _lock12 = new Object(), _lock13 = new Object(), _lock14 = new Object(), _lock16 = new Object(), _lock17 = new Object(), _lock18 = new Object(), _lock19 = new Object(), _lock20 = new Object(); @@ -735,29 +732,6 @@ public class I2PAppContext { } } - /** - * There is absolutely no good reason to make this context specific, - * other than for consistency, and perhaps later we'll want to - * include some stats. - * - * DEPRECATED - non-standard and used only by SSU. - * To be moved from context to SSU. - */ - public HMACGenerator hmac() { - if (!_hmacInitialized) - initializeHMAC(); - return _hmac; - } - - private void initializeHMAC() { - synchronized (_lock9) { - if (_hmac == null) { - _hmac= new HMACGenerator(this); - } - _hmacInitialized = true; - } - } - /** * Un-deprecated in 0.9.38 */ diff --git a/core/java/src/net/i2p/crypto/HMAC256Generator.java b/core/java/src/net/i2p/crypto/HMAC256Generator.java index e36b3ea85c..d2ff13d5e0 100644 --- a/core/java/src/net/i2p/crypto/HMAC256Generator.java +++ b/core/java/src/net/i2p/crypto/HMAC256Generator.java @@ -13,8 +13,6 @@ import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.data.SessionKey; -import org.bouncycastle.oldcrypto.macs.I2PHMac; - /** * Calculate the HMAC-SHA256 of a key+message. * This is compatible with javax.crypto.Mac.getInstance("HmacSHA256"). @@ -28,31 +26,7 @@ public final class HMAC256Generator extends HMACGenerator { /** * @param context unused */ - public HMAC256Generator(I2PAppContext context) { super(context); } - - /** - * @deprecated unused (not even by Syndie) - * @throws UnsupportedOperationException since 0.9.12 - */ - @Override - @Deprecated - protected I2PHMac acquire() { - throw new UnsupportedOperationException(); - } - - /** - * Calculate the HMAC of the data with the given key - * - * @return the first 16 bytes contain the HMAC, the last 16 bytes are zero - * @deprecated unused (not even by Syndie) - * @throws UnsupportedOperationException always - * @since 0.9.12 overrides HMACGenerator - */ - @Override - @Deprecated - public Hash calculate(SessionKey key, byte data[]) { - throw new UnsupportedOperationException(); - } + public HMAC256Generator(I2PAppContext context) { super(); } /** * Calculate the HMAC of the data with the given key. diff --git a/core/java/src/net/i2p/crypto/HMACGenerator.java b/core/java/src/net/i2p/crypto/HMACGenerator.java index 4ba9bd27c9..444cb1145e 100644 --- a/core/java/src/net/i2p/crypto/HMACGenerator.java +++ b/core/java/src/net/i2p/crypto/HMACGenerator.java @@ -1,72 +1,21 @@ package net.i2p.crypto; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.concurrent.LinkedBlockingQueue; - -// following are for main() tests -//import java.security.InvalidKeyException; -//import java.security.Key; -//import java.security.NoSuchAlgorithmException; -//import javax.crypto.spec.SecretKeySpec; -//import net.i2p.data.Base64; - -import net.i2p.I2PAppContext; -import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.data.SessionKey; import net.i2p.util.SimpleByteCache; -import org.bouncycastle.oldcrypto.macs.I2PHMac; - /** - * Calculate the HMAC-MD5-128 of a key+message. All the good stuff occurs - * in {@link org.bouncycastle.oldcrypto.macs.I2PHMac} + * Calculate the HMAC of a key+message. * - * Keys are always 32 bytes. - * This is used only by UDP. - * Use deprecated outside the router, this may move to router.jar. - * - * NOTE THIS IS NOT COMPATIBLE with javax.crypto.Mac.getInstance("HmacMD5") - * as we tell I2PHMac that the digest length is 32 bytes, so it generates - * a different result. - * - * Quote jrandom: - * "The HMAC is hardcoded to use SHA256 digest size - * for backwards compatability. next time we have a backwards - * incompatible change, we should update this." - * - * Does this mean he intended it to be compatible with MD5? - * See also 2005-07-05 status notes. + * As of 0.9.42, this is just a stub. + * See net.i2p.router.transport.udp.SSUHMACGenerator for + * the HMAC used in SSU (what was originally this class), + * and SHA256Generator for the HMAC used in Syndie. * */ -public class HMACGenerator { - /** set of available HMAC instances for calculate */ - protected final LinkedBlockingQueue _available; +public abstract class HMACGenerator { - /** - * @param context unused - */ - public HMACGenerator(I2PAppContext context) { - _available = new LinkedBlockingQueue(32); - } - - /** - * Calculate the HMAC of the data with the given key - * - * @return the first 16 bytes contain the HMAC, the last 16 bytes are zero - * @deprecated unused (not even by Syndie) - */ - @Deprecated - public Hash calculate(SessionKey key, byte data[]) { - if ((key == null) || (key.getData() == null) || (data == null)) - throw new NullPointerException("Null arguments for HMAC"); - byte rv[] = acquireTmp(); - Arrays.fill(rv, (byte)0x0); - calculate(key, data, 0, data.length, rv, 0); - return new Hash(rv); - } + public HMACGenerator() {} /** * Calculate the HMAC of the data with the given key @@ -75,16 +24,7 @@ public class HMACGenerator { * @param targetOffset offset into target to put the hmac * @throws IllegalArgumentException for bad key or target too small */ - public void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset) { - if ((key == null) || (key.getData() == null) || (data == null)) - throw new NullPointerException("Null arguments for HMAC"); - - I2PHMac mac = acquire(); - mac.init(key.getData()); - mac.update(data, offset, length); - mac.doFinal(target, targetOffset); - release(mac); - } + public abstract void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset); /** * Verify the MAC inline, reducing some unnecessary memory churn. @@ -98,42 +38,9 @@ public class HMACGenerator { * @param origMACLength how much of the MAC do we want to verify * @throws IllegalArgumentException for bad key */ - public boolean verify(SessionKey key, byte curData[], int curOffset, int curLength, - byte origMAC[], int origMACOffset, int origMACLength) { - if ((key == null) || (key.getData() == null) || (curData == null)) - throw new NullPointerException("Null arguments for HMAC"); - - I2PHMac mac = acquire(); - mac.init(key.getData()); - mac.update(curData, curOffset, curLength); - byte rv[] = acquireTmp(); - mac.doFinal(rv, 0); - release(mac); - - boolean eq = DataHelper.eqCT(rv, 0, origMAC, origMACOffset, origMACLength); - releaseTmp(rv); - return eq; - } + public abstract boolean verify(SessionKey key, byte curData[], int curOffset, int curLength, + byte origMAC[], int origMACOffset, int origMACLength); - protected I2PHMac acquire() { - I2PHMac rv = _available.poll(); - if (rv != null) - return rv; - // the HMAC is hardcoded to use SHA256 digest size - // for backwards compatability. next time we have a backwards - // incompatible change, we should update this by removing ", 32" - // SEE NOTES ABOVE - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - return new I2PHMac(md, 32); - } catch (NoSuchAlgorithmException nsae) { - throw new UnsupportedOperationException("MD5"); - } - } - - private void release(I2PHMac mac) { - _available.offer(mac); - } /** * 32 bytes from the byte array cache. @@ -147,62 +54,4 @@ public class HMACGenerator { protected void releaseTmp(byte tmp[]) { SimpleByteCache.release(tmp); } - - //private static final int RUNS = 100000; - - /** - * Test the BC and the JVM's implementations for speed - */ -/**** All this did was prove that we aren't compatible with standard HmacMD5 - public static void main(String args[]) { - if (args.length != 2) { - System.err.println("Usage: HMACGenerator keySeedString dataString"); - return; - } - - byte[] rand = SHA256Generator.getInstance().calculateHash(args[0].getBytes()).getData(); - byte[] data = args[1].getBytes(); - Key keyObj = new SecretKeySpec(rand, "HmacMD5"); - - byte[] keyBytes = keyObj.getEncoded(); - System.out.println("key bytes (" + keyBytes.length + ") is [" + Base64.encode(keyBytes) + "]"); - SessionKey key = new SessionKey(keyBytes); - System.out.println("session key is [" + key); - System.out.println("key object is [" + keyObj); - - HMACGenerator gen = new HMACGenerator(I2PAppContext.getGlobalContext()); - byte[] result = new byte[16]; - long start = System.currentTimeMillis(); - for (int i = 0; i < RUNS; i++) { - gen.calculate(key, data, 0, data.length, result, 0); - if (i == 0) - System.out.println("MAC [" + Base64.encode(result) + "]"); - } - long time = System.currentTimeMillis() - start; - System.out.println("Time for " + RUNS + " HMAC-MD5 computations:"); - System.out.println("BC time (ms): " + time); - - start = System.currentTimeMillis(); - javax.crypto.Mac mac; - try { - mac = javax.crypto.Mac.getInstance("HmacMD5"); - } catch (NoSuchAlgorithmException e) { - System.err.println("Fatal: " + e); - return; - } - for (int i = 0; i < RUNS; i++) { - try { - mac.init(keyObj); - } catch (InvalidKeyException e) { - System.err.println("Fatal: " + e); - } - byte[] sha = mac.doFinal(data); - if (i == 0) - System.out.println("MAC [" + Base64.encode(sha) + "]"); - } - time = System.currentTimeMillis() - start; - - System.out.println("JVM time (ms): " + time); - } -****/ } diff --git a/history.txt b/history.txt index 81e3d08837..ef6d581a6c 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,10 @@ +2019-07-12 zzz + * Build: Move SSU HMAC implementation from core to router + * Test: Fix broken unit test build + +2019-07-11 zzz + * imagegen: Improve QR font rendering + 2019-07-09 zzz * NetDb: - Fix NPE on store of Encrypted LS (ticket #2563) diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java index 11def9b7f3..200195f621 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java @@ -1619,7 +1619,7 @@ class PacketBuilder { int hmacLen = totalSize + UDPPacket.IV_SIZE + 2; //Hash hmac = _context.hmac().calculate(macKey, data, hmacOff, hmacLen); byte[] ba = SimpleByteCache.acquire(Hash.HASH_LENGTH); - _context.hmac().calculate(macKey, data, hmacOff, hmacLen, ba, 0); + _transport.getHMAC().calculate(macKey, data, hmacOff, hmacLen, ba, 0); if (_log.shouldLog(Log.DEBUG)) _log.debug("Authenticating " + pkt.getLength() + diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java index 61f8364c1c..b0c20275e1 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java @@ -10,6 +10,7 @@ import net.i2p.router.RouterContext; import net.i2p.router.util.CoDelBlockingQueue; import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; +import net.i2p.data.SessionKey; import net.i2p.util.I2PThread; import net.i2p.util.LHMCache; import net.i2p.util.Log; @@ -181,6 +182,13 @@ class PacketHandler { return rv; } + /** + * @since 0.9.42 + */ + private boolean validate(UDPPacket packet, SessionKey key) { + return packet.validate(key, _transport.getHMAC()); + } + /** the packet is from a peer we are establishing an outbound con to, but failed validation, so fallback */ private static final short OUTBOUND_FALLBACK = 1; /** the packet is from a peer we are establishing an inbound con to, but failed validation, so fallback */ @@ -325,17 +333,17 @@ class PacketHandler { private void receivePacket(UDPPacketReader reader, UDPPacket packet, PeerState state) { _state = 17; AuthType auth = AuthType.NONE; - boolean isValid = packet.validate(state.getCurrentMACKey()); + boolean isValid = validate(packet, state.getCurrentMACKey()); if (!isValid) { _state = 18; if (state.getNextMACKey() != null) - isValid = packet.validate(state.getNextMACKey()); + isValid = validate(packet, state.getNextMACKey()); if (!isValid) { _state = 19; if (_log.shouldLog(Log.INFO)) _log.info("Failed validation with existing con, trying as new con: " + packet); - isValid = packet.validate(_transport.getIntroKey()); + isValid = validate(packet, _transport.getIntroKey()); if (isValid) { _state = 20; // this is a stray packet from an inbound establishment @@ -388,7 +396,7 @@ class PacketHandler { */ private void receivePacket(UDPPacketReader reader, UDPPacket packet, short peerType) { _state = 27; - boolean isValid = packet.validate(_transport.getIntroKey()); + boolean isValid = validate(packet, _transport.getIntroKey()); if (!isValid) { // Note that the vast majority of these are NOT corrupted packets, but // packets for which we don't have the PeerState (i.e. SessionKey) @@ -425,7 +433,7 @@ class PacketHandler { } if (ps.getRemotePort() == newPort) { foundSamePort = true; - } else if (packet.validate(ps.getCurrentMACKey())) { + } else if (validate(packet, ps.getCurrentMACKey())) { packet.decrypt(ps.getCurrentCipherKey()); reader.initialize(packet); if (_log.shouldLog(Log.WARN)) @@ -513,7 +521,7 @@ class PacketHandler { } boolean isValid = false; if (state.getMACKey() != null) { - isValid = packet.validate(state.getMACKey()); + isValid = validate(packet, state.getMACKey()); if (isValid) { if (_log.shouldLog(Log.INFO)) _log.info("Valid introduction packet received for inbound con: " + packet); @@ -558,7 +566,7 @@ class PacketHandler { boolean isValid = false; if (state.getMACKey() != null) { _state = 36; - isValid = packet.validate(state.getMACKey()); + isValid = validate(packet, state.getMACKey()); if (isValid) { // this should be the Session Confirmed packet if (_log.shouldLog(Log.INFO)) @@ -572,7 +580,7 @@ class PacketHandler { } // keys not yet exchanged, lets try it with the peer's intro key - isValid = packet.validate(state.getIntroKey()); + isValid = validate(packet, state.getIntroKey()); if (isValid) { if (_log.shouldLog(Log.INFO)) _log.info("Valid packet received for " + state + " with Bob's intro key: " + packet); diff --git a/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java b/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java new file mode 100644 index 0000000000..cdd8edc5a0 --- /dev/null +++ b/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java @@ -0,0 +1,185 @@ +package net.i2p.router.transport.udp; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.concurrent.LinkedBlockingQueue; + +// following are for main() tests +//import java.security.InvalidKeyException; +//import java.security.Key; +//import java.security.NoSuchAlgorithmException; +//import javax.crypto.spec.SecretKeySpec; +//import net.i2p.data.Base64; + +import net.i2p.crypto.HMACGenerator; +import net.i2p.data.DataHelper; +import net.i2p.data.Hash; +import net.i2p.data.SessionKey; +import net.i2p.util.SimpleByteCache; + +import org.bouncycastle.oldcrypto.macs.I2PHMac; + +/** + * Calculate the HMAC-MD5-128 of a key+message. All the good stuff occurs + * in {@link org.bouncycastle.oldcrypto.macs.I2PHMac} + * + * Keys are always 32 bytes. + * This is used only by UDP. + * Use deprecated outside the router, this may move to router.jar. + * + * NOTE THIS IS NOT COMPATIBLE with javax.crypto.Mac.getInstance("HmacMD5") + * as we tell I2PHMac that the digest length is 32 bytes, so it generates + * a different result. + * + * Quote jrandom: + * "The HMAC is hardcoded to use SHA256 digest size + * for backwards compatability. next time we have a backwards + * incompatible change, we should update this." + * + * Does this mean he intended it to be compatible with MD5? + * See also 2005-07-05 status notes. + * + * @since 0.9.42 moved from net.i2p.crypto.HMACGenerator + */ +class SSUHMACGenerator extends HMACGenerator { + /** set of available HMAC instances for calculate */ + private final LinkedBlockingQueue _available; + + public SSUHMACGenerator() { + super(); + _available = new LinkedBlockingQueue(32); + } + + /** + * Calculate the HMAC of the data with the given key + * + * @param target out parameter the first 16 bytes contain the HMAC, the last 16 bytes are zero + * @param targetOffset offset into target to put the hmac + * @throws IllegalArgumentException for bad key or target too small + */ + public void calculate(SessionKey key, byte data[], int offset, int length, byte target[], int targetOffset) { + if ((key == null) || (key.getData() == null) || (data == null)) + throw new NullPointerException("Null arguments for HMAC"); + + I2PHMac mac = acquire(); + mac.init(key.getData()); + mac.update(data, offset, length); + mac.doFinal(target, targetOffset); + release(mac); + } + + /** + * Verify the MAC inline, reducing some unnecessary memory churn. + * + * @param key session key to verify the MAC with + * @param curData MAC to verify + * @param curOffset index into curData to MAC + * @param curLength how much data in curData do we want to run the HMAC over + * @param origMAC what do we expect the MAC of curData to equal + * @param origMACOffset index into origMAC + * @param origMACLength how much of the MAC do we want to verify + * @throws IllegalArgumentException for bad key + */ + public boolean verify(SessionKey key, byte curData[], int curOffset, int curLength, + byte origMAC[], int origMACOffset, int origMACLength) { + if ((key == null) || (key.getData() == null) || (curData == null)) + throw new NullPointerException("Null arguments for HMAC"); + + I2PHMac mac = acquire(); + mac.init(key.getData()); + mac.update(curData, curOffset, curLength); + byte rv[] = acquireTmp(); + mac.doFinal(rv, 0); + release(mac); + + boolean eq = DataHelper.eqCT(rv, 0, origMAC, origMACOffset, origMACLength); + releaseTmp(rv); + return eq; + } + + private I2PHMac acquire() { + I2PHMac rv = _available.poll(); + if (rv != null) + return rv; + // the HMAC is hardcoded to use SHA256 digest size + // for backwards compatability. next time we have a backwards + // incompatible change, we should update this by removing ", 32" + // SEE NOTES ABOVE + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + return new I2PHMac(md, 32); + } catch (NoSuchAlgorithmException nsae) { + throw new UnsupportedOperationException("MD5"); + } + } + + private void release(I2PHMac mac) { + _available.offer(mac); + } + + /** + * @since 0.9.42 + */ + public void clearCache() { + _available.clear(); + } + + //private static final int RUNS = 100000; + + /** + * Test the BC and the JVM's implementations for speed + */ +/**** All this did was prove that we aren't compatible with standard HmacMD5 + public static void main(String args[]) { + if (args.length != 2) { + System.err.println("Usage: HMACGenerator keySeedString dataString"); + return; + } + + byte[] rand = SHA256Generator.getInstance().calculateHash(args[0].getBytes()).getData(); + byte[] data = args[1].getBytes(); + Key keyObj = new SecretKeySpec(rand, "HmacMD5"); + + byte[] keyBytes = keyObj.getEncoded(); + System.out.println("key bytes (" + keyBytes.length + ") is [" + Base64.encode(keyBytes) + "]"); + SessionKey key = new SessionKey(keyBytes); + System.out.println("session key is [" + key); + System.out.println("key object is [" + keyObj); + + HMACGenerator gen = new HMACGenerator(I2PAppContext.getGlobalContext()); + byte[] result = new byte[16]; + long start = System.currentTimeMillis(); + for (int i = 0; i < RUNS; i++) { + gen.calculate(key, data, 0, data.length, result, 0); + if (i == 0) + System.out.println("MAC [" + Base64.encode(result) + "]"); + } + long time = System.currentTimeMillis() - start; + System.out.println("Time for " + RUNS + " HMAC-MD5 computations:"); + System.out.println("BC time (ms): " + time); + + start = System.currentTimeMillis(); + javax.crypto.Mac mac; + try { + mac = javax.crypto.Mac.getInstance("HmacMD5"); + } catch (NoSuchAlgorithmException e) { + System.err.println("Fatal: " + e); + return; + } + for (int i = 0; i < RUNS; i++) { + try { + mac.init(keyObj); + } catch (InvalidKeyException e) { + System.err.println("Fatal: " + e); + } + byte[] sha = mac.doFinal(data); + if (i == 0) + System.out.println("MAC [" + Base64.encode(sha) + "]"); + } + time = System.currentTimeMillis() - start; + + System.out.println("JVM time (ms): " + time); + } +****/ +} diff --git a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java index 1eeb4e0916..86c4055a21 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; +import net.i2p.crypto.HMACGenerator; import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.data.SessionKey; @@ -225,7 +226,7 @@ class UDPPacket implements CDQEntry { * MAC matches, false otherwise. * */ - public synchronized boolean validate(SessionKey macKey) { + public synchronized boolean validate(SessionKey macKey, HMACGenerator hmac) { verifyNotReleased(); //_beforeValidate = _context.clock().now(); boolean eq = false; @@ -244,14 +245,14 @@ class UDPPacket implements CDQEntry { DataHelper.toLong(_validateBuf, off, 2, payloadLength /* ^ PacketBuilder.PROTOCOL_VERSION */ ); off += 2; - eq = _context.hmac().verify(macKey, _validateBuf, 0, off, _data, _packet.getOffset(), MAC_SIZE); + eq = hmac.verify(macKey, _validateBuf, 0, off, _data, _packet.getOffset(), MAC_SIZE); if (!eq) { // this is relatively frequent, as you can get old keys in PacketHandler. Log log = _context.logManager().getLog(UDPPacket.class); if (log.shouldLog(Log.INFO)) { byte[] calc = new byte[32]; - _context.hmac().calculate(macKey, _validateBuf, 0, off, calc, 0); + hmac.calculate(macKey, _validateBuf, 0, off, calc, 0); StringBuilder str = new StringBuilder(512); str.append("Bad HMAC:\n\t"); str.append(_packet.getLength()).append(" byte pkt, "); diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index a73429831b..6407dc9b5d 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import net.i2p.crypto.HMACGenerator; import net.i2p.crypto.SigType; import net.i2p.data.DatabaseEntry; import net.i2p.data.DataHelper; @@ -87,6 +88,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private long _introducersSelectedOn; private long _lastInboundReceivedOn; private final DHSessionKeyBuilder.Factory _dhFactory; + private final SSUHMACGenerator _hmac; private int _mtu; private int _mtu_ipv6; private boolean _mismatchLogged; @@ -272,6 +274,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _introManager = new IntroductionManager(_context, this); _introducersSelectedOn = -1; _lastInboundReceivedOn = -1; + _hmac = new SSUHMACGenerator(); _mtu = PeerState.LARGE_MTU; _mtu_ipv6 = PeerState.MIN_IPV6_MTU; setupPort(); @@ -614,6 +617,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority UDPPacket.clearCache(); UDPAddress.clearCache(); _lastInboundIPv6 = 0; + _hmac.clearCache(); } /** @@ -2748,6 +2752,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return _dhFactory; } + /** + * @return the SSU HMAC + * @since 0.9.42 + */ + HMACGenerator getHMAC() { + return _hmac; + } + /** * Does nothing * @deprecated as of 0.9.31 diff --git a/core/java/src/org/bouncycastle/oldcrypto/Mac.java b/router/java/src/org/bouncycastle/oldcrypto/Mac.java similarity index 98% rename from core/java/src/org/bouncycastle/oldcrypto/Mac.java rename to router/java/src/org/bouncycastle/oldcrypto/Mac.java index aa3f7605fb..a55c19959e 100644 --- a/core/java/src/org/bouncycastle/oldcrypto/Mac.java +++ b/router/java/src/org/bouncycastle/oldcrypto/Mac.java @@ -31,6 +31,8 @@ package org.bouncycastle.oldcrypto; * The base interface for implementations of message authentication codes (MACs). * * modified by jrandom to use the session key byte array directly + * + * Not a public API - Not for external use! */ public interface Mac { diff --git a/core/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java b/router/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java similarity index 99% rename from core/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java rename to router/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java index e39ef42781..646f8329e1 100644 --- a/core/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java +++ b/router/java/src/org/bouncycastle/oldcrypto/macs/I2PHMac.java @@ -51,7 +51,7 @@ import org.bouncycastle.oldcrypto.Mac; * As of 0.9.12, refactored to use standard MessageDigest. * * Deprecated - Do not use outside of router or Syndie. - * To be moved to router. + * Not a public API - Not for external use! */ public class I2PHMac implements Mac diff --git a/core/java/src/org/bouncycastle/oldcrypto/macs/package.html b/router/java/src/org/bouncycastle/oldcrypto/macs/package.html similarity index 86% rename from core/java/src/org/bouncycastle/oldcrypto/macs/package.html rename to router/java/src/org/bouncycastle/oldcrypto/macs/package.html index 56de5a3940..5b57a27104 100644 --- a/core/java/src/org/bouncycastle/oldcrypto/macs/package.html +++ b/router/java/src/org/bouncycastle/oldcrypto/macs/package.html @@ -9,6 +9,9 @@ To avoid having to make two different versions of our Android app, we rename to Ref: javax.crypto and this android issue. +

+Moved from i2p.jar to router.jar as of 0.9.42. +Not a public API! Not for external use!

diff --git a/core/java/src/org/bouncycastle/oldcrypto/package.html b/router/java/src/org/bouncycastle/oldcrypto/package.html similarity index 86% rename from core/java/src/org/bouncycastle/oldcrypto/package.html rename to router/java/src/org/bouncycastle/oldcrypto/package.html index 56de5a3940..5b57a27104 100644 --- a/core/java/src/org/bouncycastle/oldcrypto/package.html +++ b/router/java/src/org/bouncycastle/oldcrypto/package.html @@ -9,6 +9,9 @@ To avoid having to make two different versions of our Android app, we rename to Ref: javax.crypto and this android issue. +

+Moved from i2p.jar to router.jar as of 0.9.42. +Not a public API! Not for external use!

diff --git a/core/java/test/junit/net/i2p/crypto/HMACSHA256Bench.java b/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Bench.java similarity index 86% rename from core/java/test/junit/net/i2p/crypto/HMACSHA256Bench.java rename to router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Bench.java index ade9387668..89049a8316 100644 --- a/core/java/test/junit/net/i2p/crypto/HMACSHA256Bench.java +++ b/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Bench.java @@ -1,4 +1,4 @@ -package net.i2p.crypto; +package net.i2p.router.transport.udp; /* * Copyright (c) 2003, TheCrypto @@ -36,6 +36,10 @@ import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.data.SessionKey; +/** + * Warning, misnamed, this tests the SSU HMAC, + * not net.i2p.crypto.HMAC256Generator + */ public class HMACSHA256Bench { public static void main(String args[]) { runTest(new I2PAppContext()); @@ -48,7 +52,8 @@ public class HMACSHA256Bench { private static void runTest(I2PAppContext ctx) { SessionKey key = ctx.keyGenerator().generateSessionKey(); byte[] output = new byte[32]; - ctx.hmac().calculate(key, "qwerty".getBytes(), 0, 6, output, 0); + SSUHMACGenerator hmac = new SSUHMACGenerator(); + hmac.calculate(key, "qwerty".getBytes(), 0, 6, output, 0); int times = 100000; long shorttime = 0; @@ -84,27 +89,27 @@ public class HMACSHA256Bench { byte[] lmess = DataHelper.getASCII(buf.toString()); // warm up the engines - ctx.hmac().calculate(key, smess, 0, smess.length, output, 0); - ctx.hmac().calculate(key, mmess, 0, mmess.length, output, 0); - ctx.hmac().calculate(key, lmess, 0, lmess.length, output, 0); + hmac.calculate(key, smess, 0, smess.length, output, 0); + hmac.calculate(key, mmess, 0, mmess.length, output, 0); + hmac.calculate(key, lmess, 0, lmess.length, output, 0); long before = System.currentTimeMillis(); for (int x = 0; x < times; x++) - ctx.hmac().calculate(key, smess, 0, smess.length, output, 0); + hmac.calculate(key, smess, 0, smess.length, output, 0); long after = System.currentTimeMillis(); display(times, before, after, smess.length, "3 byte"); before = System.currentTimeMillis(); for (int x = 0; x < times; x++) - ctx.hmac().calculate(key, mmess, 0, mmess.length, output, 0); + hmac.calculate(key, mmess, 0, mmess.length, output, 0); after = System.currentTimeMillis(); display(times, before, after, mmess.length, "2KB"); before = System.currentTimeMillis(); for (int x = 0; x < times; x++) - ctx.hmac().calculate(key, lmess, 0, lmess.length, output, 0); + hmac.calculate(key, lmess, 0, lmess.length, output, 0); after = System.currentTimeMillis(); display(times, before, after, lmess.length, "10KB"); diff --git a/core/java/test/junit/net/i2p/crypto/HMACSHA256Test.java b/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Test.java similarity index 78% rename from core/java/test/junit/net/i2p/crypto/HMACSHA256Test.java rename to router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Test.java index 9d896eccaa..f69e183a2d 100644 --- a/core/java/test/junit/net/i2p/crypto/HMACSHA256Test.java +++ b/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Test.java @@ -1,4 +1,4 @@ -package net.i2p.crypto; +package net.i2p.router.transport.udp; /* * free (adj.): unencumbered; not under the control of others * Written by jrandom in 2003 and released into the public domain @@ -12,6 +12,10 @@ import junit.framework.TestCase; import net.i2p.I2PAppContext; import net.i2p.data.SessionKey; +/** + * Warning, misnamed, this tests the SSU HMAC, + * not net.i2p.crypto.HMAC256Generator + */ public class HMACSHA256Test extends TestCase{ private I2PAppContext _context; @@ -20,6 +24,7 @@ public class HMACSHA256Test extends TestCase{ } public void testMultiple(){ + SSUHMACGenerator hmac = new SSUHMACGenerator(); int size = 1; for(int i = 0; i < 16; i++){ SessionKey key = _context.keyGenerator().generateSessionKey(); @@ -29,7 +34,7 @@ public class HMACSHA256Test extends TestCase{ _context.random().nextBytes(message); byte[] output = new byte[32]; - _context.hmac().calculate(key, message, 0, message.length, output, 0); + hmac.calculate(key, message, 0, message.length, output, 0); } } }