From e2661985c4738db6429c63336ee7bdc939ff68ce Mon Sep 17 00:00:00 2001 From: zzz Date: Tue, 21 May 2024 12:15:52 +0000 Subject: [PATCH] SSU1 removal part 7/n --- .../transport/udp/EstablishmentManager.java | 20 - .../net/i2p/router/transport/udp/I2PHMac.java | 198 ---- .../transport/udp/InboundEstablishState.java | 310 ------ .../transport/udp/InboundEstablishState2.java | 5 - .../transport/udp/OutboundEstablishState.java | 312 +----- .../transport/udp/SSUHMACGenerator.java | 183 ---- .../i2p/router/transport/udp/UDPPacket.java | 94 -- .../router/transport/udp/UDPPacketReader.java | 922 ------------------ .../router/transport/udp/UDPTransport.java | 29 - .../router/transport/udp/HMACSHA256Bench.java | 124 --- .../router/transport/udp/HMACSHA256Test.java | 40 - 11 files changed, 1 insertion(+), 2236 deletions(-) delete mode 100644 router/java/src/net/i2p/router/transport/udp/I2PHMac.java delete mode 100644 router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java delete mode 100644 router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java delete mode 100644 router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Bench.java delete mode 100644 router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Test.java diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java index dd9d51982..8da826b9e 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -989,32 +989,12 @@ class EstablishmentManager { RouterIdentity remote = state.getConfirmedIdentity(); PeerState peer; - int version = state.getVersion(); InboundEstablishState2 state2 = (InboundEstablishState2) state; peer = state2.getPeerState(); // now handled in IES2.createPeerState() //peer.setWeRelayToThemAs(state.getSentRelayTag()); - if (version == 1) { - // Lookup the peer's MTU from the netdb, since it isn't included in the protocol setup (yet) - // TODO if we don't have RI then we will get it shortly, but too late. - // Perhaps netdb should notify transport when it gets a new RI... - RouterInfo info = _context.netDb().lookupRouterInfoLocally(remote.calculateHash()); - if (info != null) { - RouterAddress addr = _transport.getTargetAddress(info); - if (addr != null) { - String smtu = addr.getOption(UDPAddress.PROP_MTU); - if (smtu != null) { - try { - boolean isIPv6 = state.getSentIP().length == 16; - int mtu = MTU.rectify(isIPv6, Integer.parseInt(smtu)); - peer.setHisMTU(mtu); - } catch (NumberFormatException nfe) {} - } - } - } - } // else IES2 sets PS2 MTU // 0 is the default //peer.setTheyRelayToUsAs(0); diff --git a/router/java/src/net/i2p/router/transport/udp/I2PHMac.java b/router/java/src/net/i2p/router/transport/udp/I2PHMac.java deleted file mode 100644 index 5b65bc905..000000000 --- a/router/java/src/net/i2p/router/transport/udp/I2PHMac.java +++ /dev/null @@ -1,198 +0,0 @@ -package net.i2p.router.transport.udp; -/* - * Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle - * (http://www.bouncycastle.org) - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated - * documentation files (the "Software"), to deal in the Software - * without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -import java.security.DigestException; -import java.security.MessageDigest; -import java.util.Arrays; - -import net.i2p.util.SimpleByteCache; - -/** - * HMAC implementation based on RFC2104 - * - * H(K XOR opad, H(K XOR ipad, text)) - * - * modified by jrandom to use the session key byte array directly and to cache - * a frequently used buffer (called on doFinal). changes released into the public - * domain in 2005. - * - * This is renamed from HMac because the constructor HMac(digest, sz) does not exist - * in the standard bouncycastle library, thus it conflicts in JVMs that contain the - * standard library (Android). - * - * As of 0.9.12, refactored to use standard MessageDigest. - * - * Deprecated - Do not use outside of router or Syndie. - * Not a public API - Not for external use! - * - * @since 0.9.43 moved from org.bouncycastle.oldcrypto.macs - */ -class I2PHMac -{ - private final static int BLOCK_LENGTH = 64; - - private final static byte IPAD = (byte)0x36; - private final static byte OPAD = (byte)0x5C; - - private final MessageDigest digest; - private final int digestSize; - private final byte[] inputPad = new byte[BLOCK_LENGTH]; - private final byte[] outputPad = new byte[BLOCK_LENGTH]; - - /** - * Standard HMAC, size == digest size. - * @deprecated Use javax.crypto.Mac - */ - @Deprecated - public I2PHMac(MessageDigest digest) { - this(digest, digest.getDigestLength()); - } - - /** - * @param sz override the digest's size, nonstandard if different. - * SEE NOTES in HMACGenerator about why this isn't compatible with standard HmacMD5 - */ - public I2PHMac(MessageDigest digest, int sz) { - this.digest = digest; - this.digestSize = sz; - } - - public String getAlgorithmName() - { - return digest.getAlgorithm() + "/HMAC"; - } - - public MessageDigest getUnderlyingDigest() - { - return digest; - } - - //public void init( - // CipherParameters params) - //{ - public void init(byte key[]) - { - digest.reset(); - - //byte[] key = ((KeyParameter)params).getKey(); - - if (key.length > BLOCK_LENGTH) - { - digest.update(key, 0, key.length); - try { - digest.digest(inputPad, 0, digestSize); - } catch (DigestException de) { - digest.reset(); - throw new IllegalArgumentException(de); - } - for (int i = digestSize; i < inputPad.length; i++) - { - inputPad[i] = 0; - } - } - else - { - System.arraycopy(key, 0, inputPad, 0, key.length); - for (int i = key.length; i < inputPad.length; i++) - { - inputPad[i] = 0; - } - } - - // why reallocate? it hasn't changed sizes, and the arraycopy - // below fills it completely... - //outputPad = new byte[inputPad.length]; - System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length); - - for (int i = 0; i < inputPad.length; i++) - { - inputPad[i] ^= IPAD; - } - - for (int i = 0; i < outputPad.length; i++) - { - outputPad[i] ^= OPAD; - } - - digest.update(inputPad, 0, inputPad.length); - } - - public int getMacSize() { - return digestSize; - } - - public void update(byte in) { - digest.update(in); - } - - public void update(byte[] in, int inOff, int len) { - digest.update(in, inOff, len); - } - - public int doFinal(byte[] out, int outOff) { - byte[] tmp = acquireTmp(digestSize); - //byte[] tmp = new byte[digestSize]; - try { - digest.digest(tmp, 0, digestSize); - digest.update(outputPad, 0, outputPad.length); - digest.update(tmp, 0, tmp.length); - return digest.digest(out, outOff, digestSize); - } catch (DigestException de) { - throw new IllegalArgumentException(de); - } finally { - releaseTmp(tmp); - reset(); - } - } - - private static byte[] acquireTmp(int sz) { - byte[] rv = SimpleByteCache.acquire(sz); - Arrays.fill(rv, (byte)0x0); - return rv; - } - - private static void releaseTmp(byte buf[]) { - SimpleByteCache.release(buf); - } - - /** - * Reset the mac generator. - */ - public void reset() - { - /* - * reset the underlying digest. - */ - digest.reset(); - - /* - * reinitialize the digest. - */ - digest.update(inputPad, 0, inputPad.length); - } -} diff --git a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java index fd2b5e832..dbc50f85f 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java @@ -13,11 +13,9 @@ import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.data.router.RouterIdentity; -import net.i2p.data.SessionKey; import net.i2p.data.Signature; import net.i2p.router.OutNetMessage; import net.i2p.router.RouterContext; -import net.i2p.router.transport.crypto.DHSessionKeyBuilder; import net.i2p.util.Addresses; import net.i2p.util.Log; @@ -35,21 +33,15 @@ class InboundEstablishState { private byte _receivedX[]; protected byte _bobIP[]; protected final int _bobPort; - private final DHSessionKeyBuilder _keyBuilder; // SessionCreated message - private byte _sentY[]; protected final byte _aliceIP[]; protected final int _alicePort; protected long _sentRelayTag; private long _sentSignedOnTime; - private SessionKey _sessionKey; - private SessionKey _macKey; - private Signature _sentSignature; // SessionConfirmed messages - fragmented in theory but not in practice - see below private byte _receivedIdentity[][]; private long _receivedSignedOnTime; private byte _receivedSignature[]; - private boolean _verificationAttempted; // sig not verified protected RouterIdentity _receivedUnconfirmedIdentity; // identical to uncomfirmed, but sig now verified @@ -115,25 +107,6 @@ class InboundEstablishState { */ protected static final long MAX_DELAY = EstablishmentManager.MAX_IB_ESTABLISH_TIME; - /** - * @param localPort Must be our external port, otherwise the signature of the - * SessionCreated message will be bad if the external port != the internal port. - */ - public InboundEstablishState(RouterContext ctx, byte remoteIP[], int remotePort, int localPort, - DHSessionKeyBuilder dh, UDPPacketReader.SessionRequestReader req) { - _context = ctx; - _log = ctx.logManager().getLog(InboundEstablishState.class); - _aliceIP = remoteIP; - _alicePort = remotePort; - _remoteHostId = new RemoteHostId(_aliceIP, _alicePort); - _bobPort = localPort; - _currentState = InboundState.IB_STATE_UNKNOWN; - _establishBegin = ctx.clock().now(); - _keyBuilder = dh; - _queuedMessages = new LinkedBlockingQueue(); - _introductionRequested = true; - receiveSessionRequest(req); - } /** * For SSU2 @@ -149,7 +122,6 @@ class InboundEstablishState { _bobPort = 0; _currentState = InboundState.IB_STATE_UNKNOWN; _establishBegin = ctx.clock().now(); - _keyBuilder = null; _queuedMessages = new LinkedBlockingQueue(); } @@ -193,26 +165,6 @@ class InboundEstablishState { return _queuedMessages.poll(); } - public synchronized void receiveSessionRequest(UDPPacketReader.SessionRequestReader req) { - if (_receivedX == null) - _receivedX = new byte[UDPPacketReader.SessionRequestReader.X_LENGTH]; - req.readX(_receivedX, 0); - if (_bobIP == null) - _bobIP = new byte[req.readIPSize()]; - req.readIP(_bobIP, 0); - byte[] ext = req.readExtendedOptions(); - if (ext != null && ext.length >= UDPPacket.SESS_REQ_MIN_EXT_OPTIONS_LENGTH) { - _introductionRequested = (ext[1] & (byte) UDPPacket.SESS_REQ_EXT_FLAG_REQUEST_RELAY_TAG) != 0; - if (_log.shouldInfo()) - _log.info("got sess req. w/ ext. options, need intro? " + _introductionRequested + ' ' + this); - } - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Receive sessionRequest, BobIP = " + Addresses.toString(_bobIP)); - if (_currentState == InboundState.IB_STATE_UNKNOWN) - _currentState = InboundState.IB_STATE_REQUEST_RECEIVED; - packetReceived(); - } - public synchronized boolean sessionRequestReceived() { return _receivedX != null; } public synchronized byte[] getReceivedX() { return _receivedX; } public synchronized byte[] getReceivedOurIP() { return _bobIP; } @@ -223,40 +175,12 @@ class InboundEstablishState { */ public synchronized boolean isIntroductionRequested() { return _introductionRequested; } - /** - * Generates session key and mac key. - */ - public synchronized void generateSessionKey() throws DHSessionKeyBuilder.InvalidPublicParameterException { - if (_sessionKey != null) return; - try { - _keyBuilder.setPeerPublicValue(_receivedX); - } catch (IllegalStateException ise) { - throw new DHSessionKeyBuilder.InvalidPublicParameterException("reused keys?", ise); - } - _sessionKey = _keyBuilder.getSessionKey(); - ByteArray extra = _keyBuilder.getExtraBytes(); - _macKey = new SessionKey(new byte[SessionKey.KEYSIZE_BYTES]); - System.arraycopy(extra.getData(), 0, _macKey.getData(), 0, SessionKey.KEYSIZE_BYTES); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Established inbound keys. cipher: " + Base64.encode(_sessionKey.getData()) - + " mac: " + Base64.encode(_macKey.getData())); - } - - public synchronized SessionKey getCipherKey() { return _sessionKey; } - public synchronized SessionKey getMACKey() { return _macKey; } - /** what IP do they appear to be on? */ public byte[] getSentIP() { return _aliceIP; } /** what port number do they appear to be coming from? */ public int getSentPort() { return _alicePort; } - public synchronized byte[] getSentY() { - if (_sentY == null) - _sentY = _keyBuilder.getMyPublicValueBytes(); - return _sentY; - } - public synchronized void fail() { _currentState = InboundState.IB_STATE_FAILED; } @@ -265,59 +189,6 @@ class InboundEstablishState { public synchronized void setSentRelayTag(long tag) { _sentRelayTag = tag; } public synchronized long getSentSignedOnTime() { return _sentSignedOnTime; } - public synchronized void prepareSessionCreated() { - if (_sentSignature == null) signSessionCreated(); - } - - public synchronized Signature getSentSignature() { return _sentSignature; } - - /** - * Sign: Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's - * new relay tag + Bob's signed on time - */ - private void signSessionCreated() { - byte signed[] = new byte[256 + 256 // X + Y - + _aliceIP.length + 2 - + _bobIP.length + 2 - + 4 // sent relay tag - + 4 // signed on time - ]; - _sentSignedOnTime = _context.clock().now() / 1000; - - int off = 0; - System.arraycopy(_receivedX, 0, signed, off, _receivedX.length); - off += _receivedX.length; - getSentY(); - System.arraycopy(_sentY, 0, signed, off, _sentY.length); - off += _sentY.length; - System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length); - off += _aliceIP.length; - DataHelper.toLong(signed, off, 2, _alicePort); - off += 2; - System.arraycopy(_bobIP, 0, signed, off, _bobIP.length); - off += _bobIP.length; - DataHelper.toLong(signed, off, 2, _bobPort); - off += 2; - DataHelper.toLong(signed, off, 4, _sentRelayTag); - off += 4; - DataHelper.toLong(signed, off, 4, _sentSignedOnTime); - - _sentSignature = _context.dsa().sign(signed, _context.keyManager().getSigningPrivateKey()); - - if (_log.shouldLog(Log.DEBUG)) { - StringBuilder buf = new StringBuilder(128); - buf.append("Signing sessionCreated:"); - //buf.append(" ReceivedX: ").append(Base64.encode(_receivedX)); - //buf.append(" SentY: ").append(Base64.encode(_sentY)); - buf.append(" Alice: ").append(Addresses.toString(_aliceIP, _alicePort)); - buf.append(" Bob: ").append(Addresses.toString(_bobIP, _bobPort)); - buf.append(" RelayTag: ").append(_sentRelayTag); - buf.append(" SignedOn: ").append(_sentSignedOnTime); - buf.append(" signature: ").append(Base64.encode(_sentSignature.getData())); - _log.debug(buf.toString()); - } - } - /** note that we just sent a SessionCreated packet */ public synchronized void createdPacketSent() { _lastSend = _context.clock().now(); @@ -357,79 +228,6 @@ class InboundEstablishState { /** RemoteHostId, uniquely identifies an attempt */ RemoteHostId getRemoteHostId() { return _remoteHostId; } - /** - * Note that while a SessionConfirmed could in theory be fragmented, - * in practice a RouterIdentity is 387 bytes and a single fragment is 512 bytes max, - * so it will never be fragmented. - */ - public synchronized void receiveSessionConfirmed(UDPPacketReader.SessionConfirmedReader conf) { - if (_receivedIdentity == null) - _receivedIdentity = new byte[conf.readTotalFragmentNum()][]; - int cur = conf.readCurrentFragmentNum(); - if (cur >= _receivedIdentity.length) { - // avoid AIOOBE - // should do more than this, but what? disconnect? - fail(); - packetReceived(); - return; - } - if (_receivedIdentity[cur] == null) { - byte fragment[] = new byte[conf.readCurrentFragmentSize()]; - conf.readFragmentData(fragment, 0); - _receivedIdentity[cur] = fragment; - } - - if (cur == _receivedIdentity.length-1) { - _receivedSignedOnTime = conf.readFinalFragmentSignedOnTime(); - // TODO verify time to prevent replay attacks - buildIdentity(); - if (_receivedUnconfirmedIdentity != null) { - SigType type = _receivedUnconfirmedIdentity.getSigningPublicKey().getType(); - if (type != null) { - int sigLen = type.getSigLen(); - if (_receivedSignature == null) - _receivedSignature = new byte[sigLen]; - conf.readFinalSignature(_receivedSignature, 0, sigLen); - } else { - if (_log.shouldLog(Log.WARN)) - _log.warn("Unsupported sig type from: " + toString()); - // _x() in UDPTransport - _context.banlist().banlistRouterForever(_receivedUnconfirmedIdentity.calculateHash(), - "Unsupported signature type"); - fail(); - } - Hash h = _receivedUnconfirmedIdentity.calculateHash(); - if (_context.banlist().isBanlistedForever(h)) { - // validate sig to prevent spoofing - if (getConfirmedIdentity() != null) - _context.blocklist().add(_aliceIP); - if (_log.shouldLog(Log.WARN)) - _log.warn("Router is banned: " + h.toBase64() + " on " + this); - fail(); - } - } else { - if (_log.shouldLog(Log.WARN)) - _log.warn("Bad ident from: " + toString()); - fail(); - } - } - - if ( (_currentState == InboundState.IB_STATE_UNKNOWN) || - (_currentState == InboundState.IB_STATE_REQUEST_RECEIVED) || - (_currentState == InboundState.IB_STATE_CREATED_SENT) ) { - if (confirmedFullyReceived()) - _currentState = InboundState.IB_STATE_CONFIRMED_COMPLETELY; - else - _currentState = InboundState.IB_STATE_CONFIRMED_PARTIALLY; - } - - if (_createdSentCount == 1) { - _rtt = (int) ( _context.clock().now() - _lastSend ); - } - - packetReceived(); - } - /** * Have we fully received the SessionConfirmed messages from Alice? * Caller must synch on this. @@ -452,111 +250,9 @@ class InboundEstablishState { * Note that this isn't really confirmed - see below. */ public synchronized RouterIdentity getConfirmedIdentity() { - if (!_verificationAttempted) { - verifyIdentity(); - _verificationAttempted = true; - } return _receivedConfirmedIdentity; } - /** - * Construct Alice's RouterIdentity. - * Must have received all fragments. - * Sets _receivedUnconfirmedIdentity, unless invalid. - * - * Caller must synch on this. - * - * @since 0.9.16 was in verifyIdentity() - */ - private void buildIdentity() { - if (_receivedUnconfirmedIdentity != null) - return; // dup pkt? - int frags = _receivedIdentity.length; - byte[] ident; - if (frags > 1) { - int identSize = 0; - for (int i = 0; i < _receivedIdentity.length; i++) - identSize += _receivedIdentity[i].length; - ident = new byte[identSize]; - int off = 0; - for (int i = 0; i < _receivedIdentity.length; i++) { - int len = _receivedIdentity[i].length; - System.arraycopy(_receivedIdentity[i], 0, ident, off, len); - off += len; - } - } else { - // no need to copy - ident = _receivedIdentity[0]; - } - ByteArrayInputStream in = new ByteArrayInputStream(ident); - RouterIdentity peer = new RouterIdentity(); - try { - peer.readBytes(in); - _receivedUnconfirmedIdentity = peer; - } catch (DataFormatException dfe) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Improperly formatted yet fully received ident", dfe); - } catch (IOException ioe) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Improperly formatted yet fully received ident", ioe); - } - } - - - /** - * Determine if Alice sent us a valid confirmation packet. The - * identity signs: Alice's IP + Alice's port + Bob's IP + Bob's port - * + Alice's new relay key + Alice's signed on time - * - * Note that the protocol does not include a signature of the RouterIdentity, - * which could be a problem? - * - * Caller must synch on this. - */ - private void verifyIdentity() { - if (_receivedUnconfirmedIdentity == null) - return; // either not yet recvd or bad ident - if (_receivedSignature == null) - return; // either not yet recvd or bad sig - - byte signed[] = new byte[256+256 // X + Y - + _aliceIP.length + 2 - + _bobIP.length + 2 - + 4 // Alice's relay key - + 4 // signed on time - ]; - - int off = 0; - System.arraycopy(_receivedX, 0, signed, off, _receivedX.length); - off += _receivedX.length; - getSentY(); - System.arraycopy(_sentY, 0, signed, off, _sentY.length); - off += _sentY.length; - System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length); - off += _aliceIP.length; - DataHelper.toLong(signed, off, 2, _alicePort); - off += 2; - System.arraycopy(_bobIP, 0, signed, off, _bobIP.length); - off += _bobIP.length; - DataHelper.toLong(signed, off, 2, _bobPort); - off += 2; - DataHelper.toLong(signed, off, 4, _sentRelayTag); - off += 4; - DataHelper.toLong(signed, off, 4, _receivedSignedOnTime); - Signature sig = new Signature(_receivedUnconfirmedIdentity.getSigType(), _receivedSignature); - boolean ok = _context.dsa().verifySignature(sig, signed, _receivedUnconfirmedIdentity.getSigningPublicKey()); - if (ok) { - // todo partial spoof detection - get peer.calculateHash(), - // lookup in netdb locally, if not equal, fail? - _receivedConfirmedIdentity = _receivedUnconfirmedIdentity; - } else { - if (_log.shouldLog(Log.WARN)) - _log.warn("Signature failed from " + _receivedUnconfirmedIdentity + "\non: " + this); - // we can't ban the hash because it could be spoofed, but we can block the IP - _context.blocklist().add(_aliceIP); - } - } - /** * Call from synchronized method only */ @@ -569,15 +265,9 @@ class InboundEstablishState { StringBuilder buf = new StringBuilder(128); buf.append("IES "); buf.append(Addresses.toString(_aliceIP, _alicePort)); - //if (_receivedX != null) - // buf.append(" ReceivedX: ").append(Base64.encode(_receivedX, 0, 4)); - //if (_sentY != null) - // buf.append(" SentY: ").append(Base64.encode(_sentY, 0, 4)); - //buf.append(" Bob: ").append(Addresses.toString(_bobIP, _bobPort)); buf.append(" lifetime: ").append(DataHelper.formatDuration(getLifetime())); if (_sentRelayTag > 0) buf.append(" RelayTag: ").append(_sentRelayTag); - //buf.append(" SignedOn: ").append(_sentSignedOnTime); buf.append(' ').append(_currentState); return buf.toString(); } diff --git a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java index 0b2f58f65..fdf7f7ee9 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java @@ -552,11 +552,6 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa super.fail(); } - // SSU 1 unsupported things - - @Override - public void generateSessionKey() { throw new UnsupportedOperationException(); } - // SSU 2 things public long getSendConnID() { return _sendConnID; } diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java index 02498d978..43a62bb2c 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java @@ -14,7 +14,6 @@ import net.i2p.data.i2np.DatabaseStoreMessage; import net.i2p.data.i2np.I2NPMessage; import net.i2p.router.OutNetMessage; import net.i2p.router.RouterContext; -import net.i2p.router.transport.crypto.DHSessionKeyBuilder; import net.i2p.util.Addresses; import net.i2p.util.Log; @@ -31,23 +30,18 @@ class OutboundEstablishState { private byte _sentX[]; protected byte _bobIP[]; protected int _bobPort; - private final DHSessionKeyBuilder.Factory _keyFactory; - private DHSessionKeyBuilder _keyBuilder; // SessionCreated message private byte _receivedY[]; protected byte _aliceIP[]; protected int _alicePort; protected long _receivedRelayTag; private long _receivedSignedOnTime; - private SessionKey _sessionKey; - private SessionKey _macKey; private Signature _receivedSignature; // includes trailing padding to mod 16 private byte[] _receivedEncryptedSignature; private byte[] _receivedIV; // SessionConfirmed messages private long _sentSignedOnTime; - private Signature _sentSignature; // general status protected final long _establishBegin; //private long _lastReceive; @@ -130,51 +124,6 @@ class OutboundEstablishState { private static final long WAIT_FOR_HOLE_PUNCH_DELAY = 500; - /** - * @param claimedAddress an IP/port based RemoteHostId, or null if unknown - * @param remoteHostId non-null, == claimedAddress if direct, or a hash-based one if indirect - * @param remotePeer must have supported sig type - * @param allowExtendedOptions are we allowed to send extended options to Bob? - * @param needIntroduction should we ask Bob to be an introducer for us? - ignored unless allowExtendedOptions is true - * @param introKey Bob's introduction key, as published in the netdb - * @param addr non-null - */ - public OutboundEstablishState(RouterContext ctx, RemoteHostId claimedAddress, - RemoteHostId remoteHostId, - RouterIdentity remotePeer, boolean allowExtendedOptions, - boolean needIntroduction, - SessionKey introKey, UDPAddress addr, - DHSessionKeyBuilder.Factory dh) { - _context = ctx; - _log = ctx.logManager().getLog(OutboundEstablishState.class); - if (claimedAddress != null) { - _bobIP = claimedAddress.getIP(); - _bobPort = claimedAddress.getPort(); - } else { - //_bobIP = null; - _bobPort = -1; - } - _claimedAddress = claimedAddress; - _remoteHostId = remoteHostId; - _allowExtendedOptions = allowExtendedOptions; - _needIntroduction = needIntroduction; - _remotePeer = remotePeer; - _introKey = introKey; - _queuedMessages = new LinkedBlockingQueue(); - _establishBegin = ctx.clock().now(); - _remoteAddress = addr; - _introductionNonce = -1; - _keyFactory = dh; - if (addr.getIntroducerCount() > 0) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("new outbound establish to " + remotePeer.calculateHash() + ", with address: " + addr); - _currentState = OutboundState.OB_STATE_PENDING_INTRO; - } else { - _currentState = OutboundState.OB_STATE_UNKNOWN; - } - } - /** * For SSU2 * @@ -204,7 +153,6 @@ class OutboundEstablishState { _establishBegin = ctx.clock().now(); _remoteAddress = addr; _introductionNonce = -1; - _keyFactory = null; if (addr.getIntroducerCount() > 0) { if (_log.shouldLog(Log.DEBUG)) _log.debug("new outbound establish to " + remotePeer.calculateHash() + ", with address: " + addr); @@ -294,29 +242,6 @@ class OutboundEstablishState { */ public SessionKey getIntroKey() { return _introKey; } - /** caller must synch - only call once */ - private void prepareSessionRequest() { - _keyBuilder = _keyFactory.getBuilder(); - byte X[] = _keyBuilder.getMyPublicValue().toByteArray(); - if (X.length == 257) { - _sentX = new byte[256]; - System.arraycopy(X, 1, _sentX, 0, _sentX.length); - } else if (X.length == 256) { - _sentX = X; - } else { - _sentX = new byte[256]; - System.arraycopy(X, 0, _sentX, _sentX.length - X.length, X.length); - } - } - - public synchronized byte[] getSentX() { - // We defer keygen until now so that it gets done in the Establisher loop, - // and so that we don't waste entropy on failed introductions - if (_sentX == null) - prepareSessionRequest(); - return _sentX; - } - /** * The remote side (Bob) - note that in some places he's called Charlie. * Warning - may change after introduction. May be null before introduction. @@ -329,62 +254,6 @@ class OutboundEstablishState { */ public synchronized int getSentPort() { return _bobPort; } - public synchronized void receiveSessionCreated(UDPPacketReader.SessionCreatedReader reader) { - if (_currentState == OutboundState.OB_STATE_VALIDATION_FAILED) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Session created already failed"); - return; - } - if (_receivedY != null) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Session created already received, ignoring"); - return; // already received - } - _receivedY = new byte[UDPPacketReader.SessionCreatedReader.Y_LENGTH]; - reader.readY(_receivedY, 0); - if (_aliceIP == null) - _aliceIP = new byte[reader.readIPSize()]; - reader.readIP(_aliceIP, 0); - _alicePort = reader.readPort(); - _receivedRelayTag = reader.readRelayTag(); - _receivedSignedOnTime = reader.readSignedOnTime(); - // handle variable signature size - SigType type = _remotePeer.getSigningPublicKey().getType(); - if (type == null) { - // shouldn't happen, we only connect to supported peers - fail(); - packetReceived(); - return; - } - int sigLen = type.getSigLen(); - int mod = sigLen % 16; - int pad = (mod == 0) ? 0 : (16 - mod); - int esigLen = sigLen + pad; - _receivedEncryptedSignature = new byte[esigLen]; - reader.readEncryptedSignature(_receivedEncryptedSignature, 0, esigLen); - _receivedIV = new byte[UDPPacket.IV_SIZE]; - reader.readIV(_receivedIV, 0); - - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Receive session created:Sig: " + Base64.encode(_receivedEncryptedSignature) - + "receivedIV: " + Base64.encode(_receivedIV) - + "AliceIP: " + Addresses.toString(_aliceIP) - + " RelayTag: " + _receivedRelayTag - + " SignedOn: " + _receivedSignedOnTime - + ' ' + this.toString()); - - if (_currentState == OutboundState.OB_STATE_UNKNOWN || - _currentState == OutboundState.OB_STATE_REQUEST_SENT || - _currentState == OutboundState.OB_STATE_INTRODUCED || - _currentState == OutboundState.OB_STATE_PENDING_INTRO) - _currentState = OutboundState.OB_STATE_CREATED_RECEIVED; - - if (_requestSentCount == 1) { - _rtt = (int) (_context.clock().now() - _requestSentTime); - } - packetReceived(); - } - /** * Blocking call (run in the establisher thread) to determine if the * session was created properly. If it wasn't, all the SessionCreated @@ -396,38 +265,7 @@ class OutboundEstablishState { * @return true if valid */ public synchronized boolean validateSessionCreated() { - if (_currentState == OutboundState.OB_STATE_VALIDATION_FAILED) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Session created already failed"); - return false; - } - if (_receivedSignature != null) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Session created already validated"); - return true; - } - - boolean valid = true; - try { - generateSessionKey(); - } catch (DHSessionKeyBuilder.InvalidPublicParameterException ippe) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Peer " + getRemoteHostId() + " sent us an invalid DH parameter", ippe); - valid = false; - } - if (valid) - decryptSignature(); - - if (valid && verifySessionCreated()) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Session created passed validation"); - return true; - } else { - if (_log.shouldLog(Log.WARN)) - _log.warn("Session created failed validation, clearing state for " + _remoteHostId.toString()); - fail(); - return false; - } + throw new UnsupportedOperationException("see override"); } /** @@ -441,11 +279,6 @@ class OutboundEstablishState { _receivedEncryptedSignature = null; _receivedIV = null; _receivedSignature = null; - if (_keyBuilder != null) { - //if (_keyBuilder.getPeerPublicValue() == null) - // _keyFactory.returnUnused(_keyBuilder); - _keyBuilder = null; - } // sure, there's a chance the packet was corrupted, but in practice // this means that Bob doesn't know his external port, so give up. _currentState = OutboundState.OB_STATE_VALIDATION_FAILED; @@ -453,155 +286,12 @@ class OutboundEstablishState { _nextSend = _context.clock().now(); } - /** - * Generates session key and mac key. - * Caller must synch on this. - */ - private void generateSessionKey() throws DHSessionKeyBuilder.InvalidPublicParameterException { - if (_sessionKey != null) return; - if (_keyBuilder == null) - throw new DHSessionKeyBuilder.InvalidPublicParameterException("Illegal state - never generated a key builder"); - try { - _keyBuilder.setPeerPublicValue(_receivedY); - } catch (IllegalStateException ise) { - throw new DHSessionKeyBuilder.InvalidPublicParameterException("reused keys?", ise); - } - _sessionKey = _keyBuilder.getSessionKey(); - ByteArray extra = _keyBuilder.getExtraBytes(); - _macKey = new SessionKey(new byte[SessionKey.KEYSIZE_BYTES]); - System.arraycopy(extra.getData(), 0, _macKey.getData(), 0, SessionKey.KEYSIZE_BYTES); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Established outbound keys. cipher: " + _sessionKey - + " mac: " + _macKey); - } - - /** - * decrypt the signature (and subsequent pad bytes) with the - * additional layer of encryption using the negotiated key along side - * the packet's IV - * - * Caller must synch on this. - * Only call this once! Decrypts in-place. - */ - private void decryptSignature() { - if (_receivedEncryptedSignature == null) throw new NullPointerException("encrypted signature is null! this=" + this.toString()); - if (_sessionKey == null) throw new NullPointerException("SessionKey is null!"); - if (_receivedIV == null) throw new NullPointerException("IV is null!"); - _context.aes().decrypt(_receivedEncryptedSignature, 0, _receivedEncryptedSignature, 0, - _sessionKey, _receivedIV, _receivedEncryptedSignature.length); - // handle variable signature size - SigType type = _remotePeer.getSigningPublicKey().getType(); - // if type == null throws NPE - int sigLen = type.getSigLen(); - int mod = sigLen % 16; - if (mod != 0) { - byte signatureBytes[] = new byte[sigLen]; - System.arraycopy(_receivedEncryptedSignature, 0, signatureBytes, 0, sigLen); - _receivedSignature = new Signature(type, signatureBytes); - } else { - _receivedSignature = new Signature(type, _receivedEncryptedSignature); - } - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Decrypted received signature: " + Base64.encode(_receivedSignature.getData())); - } - - /** - * Verify: Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's - * new relay tag + Bob's signed on time - * Caller must synch on this. - */ - private boolean verifySessionCreated() { - byte signed[] = new byte[256+256 // X + Y - + _aliceIP.length + 2 - + _bobIP.length + 2 - + 4 // sent relay tag - + 4 // signed on time - ]; - - int off = 0; - System.arraycopy(_sentX, 0, signed, off, _sentX.length); - off += _sentX.length; - System.arraycopy(_receivedY, 0, signed, off, _receivedY.length); - off += _receivedY.length; - System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length); - off += _aliceIP.length; - DataHelper.toLong(signed, off, 2, _alicePort); - off += 2; - System.arraycopy(_bobIP, 0, signed, off, _bobIP.length); - off += _bobIP.length; - DataHelper.toLong(signed, off, 2, _bobPort); - off += 2; - DataHelper.toLong(signed, off, 4, _receivedRelayTag); - off += 4; - DataHelper.toLong(signed, off, 4, _receivedSignedOnTime); - boolean valid = _context.dsa().verifySignature(_receivedSignature, signed, _remotePeer.getSigningPublicKey()); - if (_log.shouldLog(Log.DEBUG) || (_log.shouldLog(Log.WARN) && !valid)) { - StringBuilder buf = new StringBuilder(128); - buf.append("Signed sessionCreated:"); - buf.append(" Alice: ").append(Addresses.toString(_aliceIP, _alicePort)); - buf.append(" Bob: ").append(Addresses.toString(_bobIP, _bobPort)); - buf.append(" RelayTag: ").append(_receivedRelayTag); - buf.append(" SignedOn: ").append(_receivedSignedOnTime); - buf.append(" signature: ").append(Base64.encode(_receivedSignature.getData())); - if (valid) - _log.debug(buf.toString()); - else if (_log.shouldLog(Log.WARN)) - _log.warn("INVALID: " + buf.toString()); - } - return valid; - } - - public synchronized SessionKey getCipherKey() { return _sessionKey; } - public synchronized SessionKey getMACKey() { return _macKey; } - public synchronized long getReceivedRelayTag() { return _receivedRelayTag; } public synchronized long getSentSignedOnTime() { return _sentSignedOnTime; } public synchronized long getReceivedSignedOnTime() { return _receivedSignedOnTime; } public synchronized byte[] getReceivedIP() { return _aliceIP; } public synchronized int getReceivedPort() { return _alicePort; } - /** - * Let's sign everything so we can fragment properly. - * - * Note that while a SessionConfirmed could in theory be fragmented, - * in practice a RouterIdentity is 387 bytes and a single fragment is 512 bytes max, - * so it will never be fragmented. - */ - public synchronized void prepareSessionConfirmed() { - if (_sentSignedOnTime > 0) - return; - byte signed[] = new byte[256+256 // X + Y - + _aliceIP.length + 2 - + _bobIP.length + 2 - + 4 // Alice's relay key - + 4 // signed on time - ]; - - _sentSignedOnTime = _context.clock().now() / 1000; - - int off = 0; - System.arraycopy(_sentX, 0, signed, off, _sentX.length); - off += _sentX.length; - System.arraycopy(_receivedY, 0, signed, off, _receivedY.length); - off += _receivedY.length; - System.arraycopy(_aliceIP, 0, signed, off, _aliceIP.length); - off += _aliceIP.length; - DataHelper.toLong(signed, off, 2, _alicePort); - off += 2; - System.arraycopy(_bobIP, 0, signed, off, _bobIP.length); - off += _bobIP.length; - DataHelper.toLong(signed, off, 2, _bobPort); - off += 2; - DataHelper.toLong(signed, off, 4, _receivedRelayTag); - off += 4; - DataHelper.toLong(signed, off, 4, _sentSignedOnTime); - // BUG - if SigningPrivateKey is null, _sentSignature will be null, leading to NPE later - // should we throw something from here? - _sentSignature = _context.dsa().sign(signed, _context.keyManager().getSigningPrivateKey()); - } - - public synchronized Signature getSentSignature() { return _sentSignature; } - /** note that we just sent the SessionConfirmed packet */ public synchronized void confirmedPacketsSent() { _lastSend = _context.clock().now(); diff --git a/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java b/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java deleted file mode 100644 index a21a3784d..000000000 --- a/router/java/src/net/i2p/router/transport/udp/SSUHMACGenerator.java +++ /dev/null @@ -1,183 +0,0 @@ -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; - -/** - * Calculate the HMAC-MD5-128 of a key+message. All the good stuff occurs - * in {@link 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 9ba4e512b..3eab1402e 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java @@ -241,100 +241,6 @@ class UDPPacket implements CDPQEntry { } return _remoteHost; } - - /** - * Validate the packet against the MAC specified, returning true if the - * MAC matches, false otherwise. - * - */ - public synchronized boolean validate(SessionKey macKey, HMACGenerator hmac) { - verifyNotReleased(); - //_beforeValidate = _context.clock().now(); - boolean eq = false; - Arrays.fill(_validateBuf, (byte)0); - - // validate by comparing _data[0:15] and - // HMAC(payload + IV + (payloadLength ^ protocolVersion), macKey) - - int payloadLength = _packet.getLength() - MAC_SIZE - IV_SIZE; - if (payloadLength > 0) { - int off = 0; - System.arraycopy(_data, _packet.getOffset() + MAC_SIZE + IV_SIZE, _validateBuf, off, payloadLength); - off += payloadLength; - System.arraycopy(_data, _packet.getOffset() + MAC_SIZE, _validateBuf, off, IV_SIZE); - off += IV_SIZE; - // version is zero, unlikely to ever change - int plval = payloadLength /* ^ PacketBuilder.PROTOCOL_VERSION */ ; - // network ID cross-check, proposal 147 - int netid = _context.router().getNetworkID(); - if (netid != 2) { - plval ^= (netid - 2) << 8; - } - DataHelper.toLong(_validateBuf, off, 2, plval); - off += 2; - - 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]; - 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, "); - str.append(payloadLength).append(" byte payload"); - str.append("\n\tFrom: ").append(getRemoteHost().toString()); - str.append("\n\tIV: ").append(Base64.encode(_validateBuf, payloadLength, IV_SIZE)); - str.append("\n\tIV2: ").append(Base64.encode(_data, MAC_SIZE, IV_SIZE)); - str.append("\n\tGiven Len: ").append(DataHelper.fromLong(_validateBuf, payloadLength + IV_SIZE, 2)); - str.append("\n\tCalc HMAC: ").append(Base64.encode(calc, 0, MAC_SIZE)); - str.append("\n\tRead HMAC: ").append(Base64.encode(_data, _packet.getOffset(), MAC_SIZE)); - str.append("\n\tUsing key: ").append(macKey.toBase64()); - if (DataHelper.eq(macKey.getData(), 0, _context.routerHash().getData(), 0, 32)) - str.append(" (Intro)"); - else - str.append(" (Session)"); - str.append("\n\tRaw: ").append(Base64.encode(_data, _packet.getOffset(), _packet.getLength())); - log.info(str.toString(), new Exception()); - } - } - } else { - Log log = _context.logManager().getLog(UDPPacket.class); - if (log.shouldLog(Log.WARN)) - log.warn("Payload length is " + payloadLength + ", too short! From: " + getRemoteHost() + '\n' + - net.i2p.util.HexDump.dump(_data, _packet.getOffset(), _packet.getLength())); - } - - //_afterValidate = _context.clock().now(); - _validateCount++; - return eq; - } - - /** - * Decrypt this valid packet, overwriting the _data buffer's payload - * with the decrypted data (leaving the MAC and IV unaltered) - * - * SSU 1 only. - * SSU 2 decryption is in PacketHandler. - * - */ - public synchronized void decrypt(SessionKey cipherKey) { - verifyNotReleased(); - System.arraycopy(_data, MAC_SIZE, _ivBuf, 0, IV_SIZE); - int len = _packet.getLength(); - // As of 0.9.7, ignore padding beyond the last mod 16, - // it could otherwise blow up in decryption. - // This allows for better obfuscation. - // Probably works without this since _data is bigger than necessary, but let's not - // bother decrypting and risk overrun. - int rem = len & 0x0f; - if (rem != 0) - len -= rem; - int off = _packet.getOffset() + MAC_SIZE + IV_SIZE; - _context.aes().decrypt(_data, off, _data, off, cipherKey, _ivBuf, len - MAC_SIZE - IV_SIZE); - } /** * For CDQ diff --git a/router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java b/router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java deleted file mode 100644 index 5e6c06454..000000000 --- a/router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java +++ /dev/null @@ -1,922 +0,0 @@ -package net.i2p.router.transport.udp; - -import net.i2p.I2PAppContext; -import net.i2p.data.Base64; -import net.i2p.data.DataFormatException; -import net.i2p.data.DataHelper; -import net.i2p.data.SessionKey; -import net.i2p.data.Signature; -import net.i2p.util.Log; - -/** - * To read a packet, initialize this reader with the data and fetch out - * the appropriate fields. If the interesting bits are in message specific - * elements, grab the appropriate subreader. - * - * Many of the methods here and in the subclasses will throw AIOOBE on - * malformed packets, that should be caught also. - * - */ -class UDPPacketReader { - //private final I2PAppContext _context; - //private final Log _log; - private byte _message[]; - private int _payloadBeginOffset; - private int _payloadLength; - private final SessionRequestReader _sessionRequestReader; - private final SessionCreatedReader _sessionCreatedReader; - private final SessionConfirmedReader _sessionConfirmedReader; - private final DataReader _dataReader; - private final PeerTestReader _peerTestReader; - private final RelayRequestReader _relayRequestReader; - private final RelayIntroReader _relayIntroReader; - private final RelayResponseReader _relayResponseReader; - - private static final int KEYING_MATERIAL_LENGTH = 64; - - /** - * @param ctx unused - */ - public UDPPacketReader(I2PAppContext ctx) { - //_context = ctx; - //_log = ctx.logManager().getLog(UDPPacketReader.class); - _sessionRequestReader = new SessionRequestReader(); - _sessionCreatedReader = new SessionCreatedReader(); - _sessionConfirmedReader = new SessionConfirmedReader(); - _dataReader = new DataReader(); - _peerTestReader = new PeerTestReader(); - _relayRequestReader = new RelayRequestReader(); - _relayIntroReader = new RelayIntroReader(); - _relayResponseReader = new RelayResponseReader(); - } - - public void initialize(UDPPacket packet) { - int off = packet.getPacket().getOffset(); - int len = packet.getPacket().getLength(); - off += UDPPacket.MAC_SIZE + UDPPacket.IV_SIZE; - len -= UDPPacket.MAC_SIZE + UDPPacket.IV_SIZE; - initialize(packet.getPacket().getData(), off, len); - } - - private void initialize(byte message[], int payloadOffset, int payloadLength) { - _message = message; - _payloadBeginOffset = payloadOffset; - _payloadLength = payloadLength; - } - - /** what type of payload is in here? */ - public int readPayloadType() { - // 4 highest order bits == payload type - return (_message[_payloadBeginOffset] & 0xFF) >>> 4; - } - - /** - * Does this packet include rekeying data in the header? - * Unused, should always be false. - */ - public boolean isRekeyingIncluded() { - return (_message[_payloadBeginOffset] & UDPPacket.HEADER_FLAG_REKEY) != 0; - } - - /** - * Does this packet include extended options in the header? - */ - public boolean isExtendedOptionsIncluded() { - return (_message[_payloadBeginOffset] & UDPPacket.HEADER_FLAG_EXTENDED_OPTIONS) != 0; - } - - /** @return seconds */ - public long readTimestamp() { - // Note, this is unsigned, so we're good until February 2106 - return DataHelper.fromLong(_message, _payloadBeginOffset + 1, 4); - } - - /** - * Returns rekeying data (64 bytes), or null if none. - * Unused, should always return null. - * - * @deprecated unused - */ - @Deprecated - public byte[] readKeyingMaterial() { - if (!isRekeyingIncluded()) - return null; - byte[] rv = new byte[KEYING_MATERIAL_LENGTH]; - System.arraycopy(_message, _payloadBeginOffset + 1 + 4, rv, 0, KEYING_MATERIAL_LENGTH); - return rv; - } - - /** - * Returns extended option data, 0-255 bytes, or null if none. - * Returned array does NOT include the length byte. - * - * @return extended options or null if none is included - * @since 0.9.24 - */ - public byte[] readExtendedOptions() { - if (!isExtendedOptionsIncluded()) - return null; - int offset = _payloadBeginOffset + 1 + 4; - if (isRekeyingIncluded()) - offset += KEYING_MATERIAL_LENGTH; - int optionsSize = _message[offset++] & 0xff; - byte[] rv = new byte[optionsSize]; - System.arraycopy(_message, offset, rv, 0, optionsSize); - return rv; - } - - /** index into the message where the body begins */ - private int readBodyOffset() { - int offset = _payloadBeginOffset + 1 + 4; - if (isRekeyingIncluded()) - offset += KEYING_MATERIAL_LENGTH; - if (isExtendedOptionsIncluded()) { - int optionsSize = _message[offset] & 0xff; - offset += optionsSize + 1; - } - return offset; - } - - public SessionRequestReader getSessionRequestReader() { return _sessionRequestReader; } - public SessionCreatedReader getSessionCreatedReader() { return _sessionCreatedReader; } - public SessionConfirmedReader getSessionConfirmedReader() { return _sessionConfirmedReader; } - public DataReader getDataReader() { return _dataReader; } - public PeerTestReader getPeerTestReader() { return _peerTestReader; } - public RelayRequestReader getRelayRequestReader() { return _relayRequestReader; } - public RelayIntroReader getRelayIntroReader() { return _relayIntroReader; } - public RelayResponseReader getRelayResponseReader() { return _relayResponseReader; } - - @Override - public String toString() { - int type = readPayloadType(); - switch (type) { - case UDPPacket.PAYLOAD_TYPE_DATA: - return _dataReader.toString(); - case UDPPacket.PAYLOAD_TYPE_SESSION_CONFIRMED: - return "Session confirmed packet"; - case UDPPacket.PAYLOAD_TYPE_SESSION_CREATED: - return "Session created packet"; - case UDPPacket.PAYLOAD_TYPE_SESSION_REQUEST: - return "Session request packet"; - case UDPPacket.PAYLOAD_TYPE_TEST: - return "Peer test packet"; - case UDPPacket.PAYLOAD_TYPE_RELAY_INTRO: - return "Relay intro packet"; - case UDPPacket.PAYLOAD_TYPE_RELAY_REQUEST: - return "Relay request packet"; - case UDPPacket.PAYLOAD_TYPE_RELAY_RESPONSE: - return "Relay response packet"; - case UDPPacket.PAYLOAD_TYPE_SESSION_DESTROY: - return "Session destroyed packet"; - default: - return "Unknown packet type " + type; - } - } - - public void toRawString(StringBuilder buf) { - if (_message != null) - buf.append(Base64.encode(_message, _payloadBeginOffset, _payloadLength)); - } - - /* ------- Begin Reader Classes ------- */ - - /** - * Base - * - * @since 0.9.24 - */ - public abstract class Reader { - /** - * Returns extended option data from the header, 0-255 bytes, or null if none. - * Returned array does NOT include the length byte. - * - * @return extended options or null if none is included - * @since 0.9.24 - */ - public byte[] readExtendedOptions() { - return UDPPacketReader.this.readExtendedOptions(); - } - } - - /** Help read the SessionRequest payload */ - public class SessionRequestReader extends Reader { - public static final int X_LENGTH = 256; - public void readX(byte target[], int targetOffset) { - int readOffset = readBodyOffset(); - System.arraycopy(_message, readOffset, target, targetOffset, X_LENGTH); - } - - public int readIPSize() { - int offset = readBodyOffset() + X_LENGTH; - return _message[offset] & 0xff; - } - - /** what IP bob is reachable on */ - public void readIP(byte target[], int targetOffset) { - int offset = readBodyOffset() + X_LENGTH; - int size = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, size); - } - } - - /** Help read the SessionCreated payload */ - public class SessionCreatedReader extends Reader { - public static final int Y_LENGTH = 256; - public void readY(byte target[], int targetOffset) { - int readOffset = readBodyOffset(); - System.arraycopy(_message, readOffset, target, targetOffset, Y_LENGTH); - } - - /** sizeof(IP) */ - public int readIPSize() { - int offset = readBodyOffset() + Y_LENGTH; - return _message[offset] & 0xff; - } - - /** what IP do they think we are coming on? */ - public void readIP(byte target[], int targetOffset) { - int offset = readBodyOffset() + Y_LENGTH; - int size = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, size); - } - - /** what port do they think we are coming from? */ - public int readPort() { - int offset = readBodyOffset() + Y_LENGTH + 1 + readIPSize(); - return (int)DataHelper.fromLong(_message, offset, 2); - } - - /** read in the 4 byte relayAs tag */ - public long readRelayTag() { - int offset = readBodyOffset() + Y_LENGTH + 1 + readIPSize() + 2; - return DataHelper.fromLong(_message, offset, 4); - } - - public long readSignedOnTime() { - int offset = readBodyOffset() + Y_LENGTH + 1 + readIPSize() + 2 + 4; - long rv = DataHelper.fromLong(_message, offset, 4); - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("Signed on time offset: " + offset + " val: " + rv - // + "\nRawCreated: " + Base64.encode(_message, _payloadBeginOffset, _payloadLength)); - return rv; - } - - /** @param size the amount to be copied, including padding to mod 16 */ - public void readEncryptedSignature(byte target[], int targetOffset, int size) { - int offset = readBodyOffset() + Y_LENGTH + 1 + readIPSize() + 2 + 4 + 4; - System.arraycopy(_message, offset, target, targetOffset, size); - } - - public void readIV(byte target[], int targetOffset) { - int offset = _payloadBeginOffset - UDPPacket.IV_SIZE; - System.arraycopy(_message, offset, target, targetOffset, UDPPacket.IV_SIZE); - } - } - - /** parse out the confirmed message */ - public class SessionConfirmedReader extends Reader { - /** which fragment is this? */ - public int readCurrentFragmentNum() { - int readOffset = readBodyOffset(); - return (_message[readOffset] & 0xFF) >>> 4; - } - /** how many fragments will there be? */ - public int readTotalFragmentNum() { - int readOffset = readBodyOffset(); - return (_message[readOffset] & 0xF); - } - - public int readCurrentFragmentSize() { - int readOffset = readBodyOffset() + 1; - return (int)DataHelper.fromLong(_message, readOffset, 2); - } - - /** read the fragment data from the nonterminal sessionConfirmed packet */ - public void readFragmentData(byte target[], int targetOffset) { - int readOffset = readBodyOffset() + 1 + 2; - int len = readCurrentFragmentSize(); - System.arraycopy(_message, readOffset, target, targetOffset, len); - } - - /** - * Read the time at which the signature was generated. - * TODO must be completely in final fragment. - * Time and sig cannot be split across fragments. - */ - public long readFinalFragmentSignedOnTime() { - if (readCurrentFragmentNum() != readTotalFragmentNum()-1) - throw new IllegalStateException("This is not the final fragment"); - int readOffset = readBodyOffset() + 1 + 2 + readCurrentFragmentSize(); - return DataHelper.fromLong(_message, readOffset, 4); - } - - /** - * Read the signature from the final sessionConfirmed packet. - * TODO must be completely in final fragment. - * Time and sig cannot be split across fragments. - * @param size not including padding - */ - public void readFinalSignature(byte target[], int targetOffset, int size) { - if (readCurrentFragmentNum() != readTotalFragmentNum()-1) - throw new IllegalStateException("This is not the final fragment"); - int readOffset = _payloadBeginOffset + _payloadLength - size; - if (readOffset < readBodyOffset() + (1 + 2 + 4)) - throw new IllegalStateException("Sig split across fragments"); - System.arraycopy(_message, readOffset, target, targetOffset, size); - } - } - - /** parse out the data message */ - public class DataReader extends Reader { - - /** - * @return the data size, NOT including IP header, UDP header, IV, or MAC - */ - public int getPacketSize() { return _payloadLength; } - - public boolean readACKsIncluded() { - return flagSet(UDPPacket.DATA_FLAG_EXPLICIT_ACK); - } - - public boolean readACKBitfieldsIncluded() { - return flagSet(UDPPacket.DATA_FLAG_ACK_BITFIELDS); - } - - public boolean readECN() { - return flagSet(UDPPacket.DATA_FLAG_ECN); - } - - public boolean readWantPreviousACKs() { - return flagSet(UDPPacket.DATA_FLAG_WANT_ACKS); - } - - public boolean readReplyRequested() { - return flagSet(UDPPacket.DATA_FLAG_WANT_REPLY); - } - - public boolean readExtendedDataIncluded() { - return flagSet(UDPPacket.DATA_FLAG_EXTENDED); - } - - public int readACKCount() { - if (!readACKsIncluded()) return 0; - int off = readBodyOffset() + 1; - return _message[off] & 0xff; - } - - public long readACK(int index) { - if (!readACKsIncluded()) return -1; - int off = readBodyOffset() + 1; - //int num = (int)DataHelper.fromLong(_message, off, 1); - off++; - return DataHelper.fromLong(_message, off + (4 * index), 4); - } - - public ACKBitfield[] readACKBitfields() throws DataFormatException { - if (!readACKBitfieldsIncluded()) return null; - int off = readBodyOffset() + 1; - if (readACKsIncluded()) { - int numACKs = _message[off] & 0xff; - off++; - off += 4 * numACKs; - } - - int numBitfields = _message[off] & 0xff; - off++; - - PacketACKBitfield rv[] = new PacketACKBitfield[numBitfields]; - for (int i = 0; i < numBitfields; i++) { - rv[i] = new PacketACKBitfield(off); - off += rv[i].getByteLength(); - } - return rv; - } - - public int readFragmentCount() throws DataFormatException { - int off = readBodyOffset() + 1; - if (readACKsIncluded()) { - int numACKs = _message[off] & 0xff; - off++; - off += 4 * numACKs; - } - if (readACKBitfieldsIncluded()) { - int numBitfields = _message[off] & 0xff; - off++; - - for (int i = 0; i < numBitfields; i++) { - PacketACKBitfield bf = new PacketACKBitfield(off); - off += bf.getByteLength(); - } - } - if (readExtendedDataIncluded()) { - int size = _message[off] & 0xff; - off++; - off += size; - } - return _message[off]; - } - - public long readMessageId(int fragmentNum) throws DataFormatException { - int fragmentBegin = getFragmentBegin(fragmentNum); - return DataHelper.fromLong(_message, fragmentBegin, 4); - } - - public int readMessageFragmentNum(int fragmentNum) throws DataFormatException { - int off = getFragmentBegin(fragmentNum); - off += 4; // messageId - return (_message[off] & 0xFF) >>> 1; - } - - public boolean readMessageIsLast(int fragmentNum) throws DataFormatException { - int off = getFragmentBegin(fragmentNum); - off += 4; // messageId - return ((_message[off] & 1) != 0); - } - - public int readMessageFragmentSize(int fragmentNum) throws DataFormatException { - int off = getFragmentBegin(fragmentNum); - off += 5; // messageId + fragment info - return ((int)DataHelper.fromLong(_message, off, 2)) & 0x3FFF; - } - - public void readMessageFragment(int fragmentNum, byte target[], int targetOffset) - throws DataFormatException { - int off = getFragmentBegin(fragmentNum); - off += 5; // messageId + fragment info - int size = ((int)DataHelper.fromLong(_message, off, 2)) & 0x3FFF; - off += 2; - System.arraycopy(_message, off, target, targetOffset, size); - } - - private int getFragmentBegin(int fragmentNum) throws DataFormatException { - int off = readBodyOffset() + 1; - if (readACKsIncluded()) { - int numACKs = _message[off] & 0xff; - off++; - off += 4 * numACKs; - } - if (readACKBitfieldsIncluded()) { - int numBitfields = _message[off] & 0xff; - off++; - - PacketACKBitfield bf[] = new PacketACKBitfield[numBitfields]; - for (int i = 0; i < numBitfields; i++) { - bf[i] = new PacketACKBitfield(off); - off += bf[i].getByteLength(); - } - } - if (readExtendedDataIncluded()) { - int size = _message[off] & 0xff; - off++; - off += size; - } - off++; // # fragments - - if (fragmentNum > 0) { - for (int i = 0; i < fragmentNum; i++) { - off += 5; // messageId+info - off += ((int)DataHelper.fromLong(_message, off, 2)) & 0x3FFF; - off += 2; - } - } - return off; - } - - private boolean flagSet(byte flag) { - int flagOffset = readBodyOffset(); - return ((_message[flagOffset] & flag) != 0); - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(512); - long msAgo = System.currentTimeMillis() - readTimestamp()*1000; - buf.append("Data packet sent ").append(msAgo).append("ms ago "); - buf.append("IV "); - buf.append(Base64.encode(_message, _payloadBeginOffset-UDPPacket.IV_SIZE, UDPPacket.IV_SIZE)); - buf.append(" "); - int off = readBodyOffset() + 1; - if (readACKsIncluded()) { - int numACKs = _message[off] & 0xff; - off++; - buf.append("with ACKs for "); - for (int i = 0; i < numACKs; i++) { - buf.append(DataHelper.fromLong(_message, off, 4)).append(' '); - off += 4; - } - } - if (readACKBitfieldsIncluded()) { - int numBitfields = _message[off] & 0xff; - off++; - buf.append("with partial ACKs for "); - - try { - for (int i = 0; i < numBitfields; i++) { - PacketACKBitfield bf = new PacketACKBitfield(off); - buf.append(bf.getMessageId()).append(' '); - off += bf.getByteLength(); - } - } catch (DataFormatException dfe) { - buf.append("CORRUPT"); - return buf.toString(); - } - } - if (readExtendedDataIncluded()) { - int size = _message[off] & 0xff; - off++; - buf.append("with extended size of "); - buf.append(size); - buf.append(' '); - off += size; - } - - int numFragments = _message[off] & 0xff; - off++; - buf.append("with fragmentCount of "); - buf.append(numFragments); - buf.append(' '); - - for (int i = 0; i < numFragments; i++) { - buf.append("containing messageId "); - buf.append(DataHelper.fromLong(_message, off, 4)); - off += 4; - int fragNum = (_message[off] & 0xFF) >>> 1; - boolean isLast = (_message[off] & 1) != 0; - off++; - buf.append(" frag# ").append(fragNum); - buf.append(" isLast? ").append(isLast); - buf.append(" info ").append(_message[off-1]); - int size = ((int)DataHelper.fromLong(_message, off, 2)) & 0x3FFF; - off += 2; - buf.append(" with ").append(size).append(" bytes; "); - off += size; - } - - return buf.toString(); - } - - public void toRawString(StringBuilder buf) throws DataFormatException { - UDPPacketReader.this.toRawString(buf); - buf.append(" payload: "); - - int off = getFragmentBegin(0); // first fragment - off += 4 + 1; // messageId + fragment info - int size = ((int)DataHelper.fromLong(_message, off, 2)) & 0x3FFF; - off += 2; - buf.append(Base64.encode(_message, off, size)); - } - } - - /** - * Helper class to fetch the particular bitfields from the raw packet - */ - private class PacketACKBitfield implements ACKBitfield { - private final int _start; - private final int _bitfieldStart; - private final int _bitfieldSize; - - public PacketACKBitfield(int start) throws DataFormatException { - _start = start; - _bitfieldStart = start + 4; - int bfsz = 1; - // bitfield is an array of bytes where the high bit is 1 if - // further bytes in the bitfield follow - while ((_message[_bitfieldStart + bfsz - 1] & UDPPacket.BITFIELD_CONTINUATION) != 0x0) { - bfsz++; - //if (bfsz > InboundMessageState.MAX_PARTIAL_BITFIELD_BYTES) - // throw new DataFormatException(); - } - if (bfsz > InboundMessageState.MAX_PARTIAL_BITFIELD_BYTES) - throw new DataFormatException("bitfield size: " + bfsz); - _bitfieldSize = bfsz; - } - - public long getMessageId() { return DataHelper.fromLong(_message, _start, 4); } - public int getByteLength() { return 4 + _bitfieldSize; } - public int fragmentCount() { return _bitfieldSize * 7; } - public boolean receivedComplete() { return false; } - - /** - * Number of fragments acked in this bitfield. - * Faster than looping through received() - * @since 0.9.16 - */ - public int ackCount() { - int rv = 0; - for (int i = _bitfieldStart; i < _bitfieldStart + _bitfieldSize; i++) { - byte b = _message[i]; - if ((b & 0x7f) != 0) { - for (int j = 0; j < 7; j++) { - if ((b & 0x01) != 0) - rv++; - b >>= 1; - } - } - } - return rv; - } - - /** - * Highest fragment number acked in this bitfield. - * @return highest fragment number acked, or -1 if none - * @since 0.9.16 - */ - public int highestReceived() { - for (int i = _bitfieldSize - 1; i >= 0; i--) { - byte b = _message[_bitfieldStart + i]; - if ((b & 0x7f) == 0) - continue; - for (int j = 6; j >= 0; j--) { - if ((b & 0x40) != 0) - return (7 * i) + j; - b <<= 1; - } - } - return -1; - } - - public boolean received(int fragmentNum) { - if ( (fragmentNum < 0) || (fragmentNum >= _bitfieldSize*7) ) - return false; - // the fragment has been received if the bit is set - int byteNum = _bitfieldStart + (fragmentNum/7); - int flagNum = fragmentNum % 7; - return (_message[byteNum] & (1 << flagNum)) != 0x0; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(64); - buf.append("IB Partial ACK of "); - buf.append(getMessageId()); - buf.append(" highest: ").append(highestReceived()); - buf.append(" with ACKs for: ["); - int numFrags = fragmentCount(); - for (int i = 0; i < numFrags; i++) { - if (received(i)) - buf.append(i).append(' '); - } - buf.append("] / ").append(numFrags); - return buf.toString(); - } - } - - /** Help read the PeerTest payload */ - public class PeerTestReader extends Reader { - private static final int NONCE_LENGTH = 4; - - public long readNonce() { - int readOffset = readBodyOffset(); - return DataHelper.fromLong(_message, readOffset, NONCE_LENGTH); - } - - public int readIPSize() { - int offset = readBodyOffset() + NONCE_LENGTH; - return _message[offset] & 0xff; - } - - /** what IP Alice is reachable on */ - public void readIP(byte target[], int targetOffset) { - int offset = readBodyOffset() + NONCE_LENGTH; - int size = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, size); - } - - /** what IP Alice is reachable on */ - public int readPort() { - int offset = readBodyOffset() + NONCE_LENGTH; - int size = _message[offset] & 0xff; - offset++; - offset += size; // skip the IP - return (int)DataHelper.fromLong(_message, offset, 2); - } - - /** what Alice's intro key is (if known - if unknown, the key is INVALID_KEY) */ - public void readIntroKey(byte target[], int targetOffset) { - int offset = readBodyOffset() + NONCE_LENGTH; - int size = _message[offset] & 0xff; - offset += 1 + 2; // skip the size + port - offset += size; // skip the IP - System.arraycopy(_message, offset, target, targetOffset, SessionKey.KEYSIZE_BYTES); - } - } - - /** Help read the RelayRequest payload */ - public class RelayRequestReader extends Reader { - public long readTag() { - long rv = DataHelper.fromLong(_message, readBodyOffset(), 4); - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("read alice tag: " + rv); - return rv; - } - public int readIPSize() { - int offset = readBodyOffset() + 4; - int rv = _message[offset] & 0xff; - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("read alice ip size: " + rv); - return rv; - } - - /** what IP Alice is reachable on */ - public void readIP(byte target[], int targetOffset) { - int offset = readBodyOffset() + 4; - int size = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, size); - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("read alice ip: " + Base64.encode(target, targetOffset, size)); - } - public int readPort() { - int offset = readBodyOffset() + 4; - offset += _message[offset] & 0xff; - offset++; - int rv = (int)DataHelper.fromLong(_message, offset, 2); - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("read alice port: " + rv); - return rv; - } - - /** unused */ - public int readChallengeSize() { - int offset = readBodyOffset() + 4; - offset += _message[offset] & 0xff; - offset += 1 + 2; - int rv = _message[offset] & 0xff; - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("read challenge size: " + rv); - return rv; - } - - /** unused */ - public void readChallengeData(byte target[], int targetOffset) { - int offset = readBodyOffset() + 4; - offset += _message[offset] & 0xff; - offset += 1 + 2; - int sz = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, sz); - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("read challenge data: " + Base64.encode(target)); - } - public void readAliceIntroKey(byte target[], int targetOffset) { - int offset = readBodyOffset() + 4; - offset += _message[offset] & 0xff; - offset += 1 + 2; - int sz = _message[offset] & 0xff; - offset++; - offset += sz; - System.arraycopy(_message, offset, target, targetOffset, SessionKey.KEYSIZE_BYTES); - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("read alice intro key: " + Base64.encode(target, targetOffset, SessionKey.KEYSIZE_BYTES) - // + " packet size: " + _payloadLength + " off: " + offset + " data: " + Base64.encode(_message)); - } - public long readNonce() { - int offset = readBodyOffset() + 4; - offset += _message[offset] & 0xff; - offset += 1 + 2; - int sz = _message[offset] & 0xff; - offset++; - offset += sz; - offset += SessionKey.KEYSIZE_BYTES; - long rv = DataHelper.fromLong(_message, offset, 4); - //if (_log.shouldLog(Log.DEBUG)) - // _log.debug("read request nonce: " + rv); - return rv; - } - } - - /** Help read the RelayIntro payload */ - public class RelayIntroReader extends Reader { - public int readIPSize() { - int offset = readBodyOffset(); - return _message[offset] & 0xff; - } - - /** what IP Alice is reachable on */ - public void readIP(byte target[], int targetOffset) { - int offset = readBodyOffset(); - int size = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, size); - } - public int readPort() { - int offset = readBodyOffset(); - offset += _message[offset] & 0xff; - offset++; - return (int)DataHelper.fromLong(_message, offset, 2); - } - - /** unused */ - public int readChallengeSize() { - int offset = readBodyOffset(); - offset += _message[offset] & 0xff; - offset += 1 + 2; - return _message[offset] & 0xff; - } - - /** unused */ - public void readChallengeData(byte target[], int targetOffset) { - int offset = readBodyOffset(); - offset += _message[offset] & 0xff; - offset += 1 + 2; - int sz = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, sz); - } - } - - - /** Help read the RelayResponse payload */ - public class RelayResponseReader extends Reader { - public int readCharlieIPSize() { - int offset = readBodyOffset(); - return _message[offset] & 0xff; - } - /** what IP charlie is reachable on */ - public void readCharlieIP(byte target[], int targetOffset) { - int offset = readBodyOffset(); - int size = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, size); - } - /** what port charlie is reachable on */ - public int readCharliePort() { - int offset = readBodyOffset(); - offset += _message[offset] & 0xff; - offset++; - return (int)DataHelper.fromLong(_message, offset, 2); - } - - /** @deprecated unused */ - @Deprecated - public int readAliceIPSize() { - int offset = readBodyOffset(); - offset += _message[offset] & 0xff; - offset += 1 + 2; - return _message[offset] & 0xff; - } - /** @deprecated unused */ - @Deprecated - public void readAliceIP(byte target[], int targetOffset) { - int offset = readBodyOffset(); - offset += _message[offset] & 0xff; - offset += 1 + 2; - int sz = _message[offset] & 0xff; - offset++; - System.arraycopy(_message, offset, target, targetOffset, sz); - } - /** @deprecated unused */ - @Deprecated - public int readAlicePort() { - int offset = readBodyOffset(); - offset += _message[offset] & 0xff; - offset += 1 + 2; - int sz = _message[offset] & 0xff; - offset++; - offset += sz; - return (int)DataHelper.fromLong(_message, offset, 2); - } - public long readNonce() { - int offset = readBodyOffset(); - offset += _message[offset] & 0xff; - offset += 1 + 2; - int sz = _message[offset] & 0xff; - offset += 1 + 2; // sz + port - offset += sz; - return DataHelper.fromLong(_message, offset, 4); - } - } - - /* ------- End Reader Classes ------- */ - -/****** - public static void main(String args[]) { - I2PAppContext ctx = I2PAppContext.getGlobalContext(); - try { - PacketBuilder b = new PacketBuilder(ctx, null); - InetAddress introHost = InetAddress.getLocalHost(); - int introPort = 1234; - byte introKey[] = new byte[SessionKey.KEYSIZE_BYTES]; - ctx.random().nextBytes(introKey); - long introTag = ctx.random().nextLong(0xFFFFFFFFl); - long introNonce = ctx.random().nextLong(0xFFFFFFFFl); - SessionKey ourIntroKey = ctx.keyGenerator().generateSessionKey(); - UDPPacket packet = b.buildRelayRequest(introHost, introPort, introKey, introTag, ourIntroKey, introNonce, false); - UDPPacketReader r = new UDPPacketReader(ctx); - r.initialize(packet); - RelayRequestReader reader = r.getRelayRequestReader(); - System.out.println("Nonce: " + reader.readNonce() + " / " + introNonce); - System.out.println("Tag : " + reader.readTag() + " / " + introTag); - byte readKey[] = new byte[SessionKey.KEYSIZE_BYTES]; - reader.readAliceIntroKey(readKey, 0); - System.out.println("Key : " + Base64.encode(readKey) + " / " + ourIntroKey.toBase64()); - } catch (Exception e) { - e.printStackTrace(); - } - - } -*******/ -} 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 b18a52185..a2b21e2d8 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -23,7 +23,6 @@ import java.util.concurrent.CopyOnWriteArrayList; import net.i2p.CoreVersion; import net.i2p.crypto.EncType; -import net.i2p.crypto.HMACGenerator; import net.i2p.crypto.KeyPair; import net.i2p.crypto.SigType; import net.i2p.data.Base64; @@ -102,7 +101,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private long _v6IntroducersSelectedOn; private long _lastInboundReceivedOn; private final DHSessionKeyBuilder.Factory _dhFactory; - private final SSUHMACGenerator _hmac; private int _mtu = PeerState.MIN_MTU; private int _mtu_ipv6 = PeerState.MIN_IPV6_MTU; private int _mtu_ssu2; @@ -421,7 +419,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _v4IntroducersSelectedOn = -1; _v6IntroducersSelectedOn = -1; _lastInboundReceivedOn = -1; - _hmac = (dh != null) ? new SSUHMACGenerator() : null; _mtu = PeerState.LARGE_MTU; _mtu_ipv6 = PeerState.MIN_IPV6_MTU; setupPort(); @@ -939,8 +936,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority UDPPacket.clearCache(); UDPAddress.clearCache(); _lastInboundIPv6 = 0; - if (_hmac != null) - _hmac.clearCache(); } /** @@ -3707,22 +3702,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority // _log.debug("UDP transport returning " + skews.size() + " peer clock skews."); return skews; } - - /** - * @return a new DHSessionKeyBuilder, or null if SSU1 disabled - * @since 0.9 - */ - DHSessionKeyBuilder getDHBuilder() { - return _enableSSU1 ? _dhFactory.getBuilder() : null; - } - - /** - * @return the factory, or null if SSU1 disabled - * @since 0.9.2 - */ - DHSessionKeyBuilder.Factory getDHFactory() { - return _dhFactory; - } /** * @return null if not configured for SSU2 @@ -3732,14 +3711,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return _xdhFactory; } - /** - * @return the SSU HMAC, or null if SSU1 disabled - * @since 0.9.42 - */ - HMACGenerator getHMAC() { - return _hmac; - } - /** * @return null if not configured for SSU2 * @since 0.9.54 diff --git a/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Bench.java b/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Bench.java deleted file mode 100644 index 89049a831..000000000 --- a/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Bench.java +++ /dev/null @@ -1,124 +0,0 @@ -package net.i2p.router.transport.udp; - -/* - * Copyright (c) 2003, TheCrypto - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of the TheCrypto may be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -import java.util.Properties; - -import net.i2p.I2PAppContext; -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()); - System.out.println("Running as MD5"); - Properties props = new Properties(); - //props.setProperty("i2p.fakeHMAC", "true"); - props.setProperty("i2p.HMACMD5", "true"); - runTest(new I2PAppContext(props)); - } - private static void runTest(I2PAppContext ctx) { - SessionKey key = ctx.keyGenerator().generateSessionKey(); - byte[] output = new byte[32]; - SSUHMACGenerator hmac = new SSUHMACGenerator(); - hmac.calculate(key, "qwerty".getBytes(), 0, 6, output, 0); - - int times = 100000; - long shorttime = 0; - long medtime = 0; - long longtime = 0; - long minShort = 0; - long maxShort = 0; - long minMed = 0; - long maxMed = 0; - long minLong = 0; - long maxLong = 0; - - long shorttime1 = 0; - long medtime1 = 0; - long longtime1 = 0; - long minShort1 = 0; - long maxShort1 = 0; - long minMed1 = 0; - long maxMed1 = 0; - long minLong1 = 0; - long maxLong1 = 0; - - byte[] smess = "abc".getBytes(); - StringBuilder buf = new StringBuilder(); - for (int x = 0; x < 2*1024; x++) { - buf.append("a"); - } - byte[] mmess = DataHelper.getASCII(buf.toString()); // new String("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq").getBytes(); - buf = new StringBuilder(); - for (int x = 0; x < 10000; x++) { - buf.append("a"); - } - byte[] lmess = DataHelper.getASCII(buf.toString()); - - // warm up the engines - 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++) - 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++) - 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++) - hmac.calculate(key, lmess, 0, lmess.length, output, 0); - after = System.currentTimeMillis(); - - display(times, before, after, lmess.length, "10KB"); - } - - private static void display(int times, long before, long after, int len, String name) { - double rate = times/(((double)after-(double)before)/1000.0d); - double kbps = (len/1024.0d)*times/(((double)after-(double)before)/1000.0d); - System.out.println(name + " HMAC pulled " + kbps + "KBps or " + rate + " calcs per second"); - } -} - diff --git a/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Test.java b/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Test.java deleted file mode 100644 index f69e183a2..000000000 --- a/router/java/test/junit/net/i2p/router/transport/udp/HMACSHA256Test.java +++ /dev/null @@ -1,40 +0,0 @@ -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 - * with no warranty of any kind, either expressed or implied. - * It probably won't make your computer catch on fire, or eat - * your children, but it might. Use at your own risk. - * - */ - -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; - - protected void setUp() { - _context = I2PAppContext.getGlobalContext(); - } - - public void testMultiple(){ - SSUHMACGenerator hmac = new SSUHMACGenerator(); - int size = 1; - for(int i = 0; i < 16; i++){ - SessionKey key = _context.keyGenerator().generateSessionKey(); - - byte[] message = new byte[size]; - size*=2; - _context.random().nextBytes(message); - - byte[] output = new byte[32]; - hmac.calculate(key, message, 0, message.length, output, 0); - } - } -}