Author: nextgens
Date: 2007-12-09 22:30:53 +0000 (Sun, 09 Dec 2007)
New Revision: 16442
Modified:
trunk/freenet/src/freenet/node/FNPPacketMangler.java
Log:
JFK: improve logging, padd packets only up to the MTU, use static variables
where possible
Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java 2007-12-09
22:29:20 UTC (rev 16441)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java 2007-12-09
22:30:53 UTC (rev 16442)
@@ -61,12 +61,12 @@
public class FNPPacketMangler implements OutgoingPacketMangler,
IncomingPacketFilter {
private static boolean logMINOR;
- final Node node;
- final NodeCrypto crypto;
- final MessageCore usm;
- final PacketSocketHandler sock;
- final EntropySource fnpTimingSource;
- final EntropySource myPacketDataSource;
+ private final Node node;
+ private final NodeCrypto crypto;
+ private final MessageCore usm;
+ private final PacketSocketHandler sock;
+ private final EntropySource fnpTimingSource;
+ private final EntropySource myPacketDataSource;
/**
* Objects cached during JFK message exchange: JFK(3,4) with
authenticator as key
* The messages are cached in hashmaps because the message retrieval
from the cache
@@ -709,7 +709,7 @@
private void processJFKMessage1(byte[] payload,int offset,PeerNode
pn,Peer replyTo, boolean unknownInitiator, int setupType)
{
long t1=System.currentTimeMillis();
- if(logMINOR) Logger.minor(this, "Got a JFK(1) message,
processing it - "+pn);
+ if(logMINOR) Logger.minor(this, "Got a JFK(1) message,
processing it - "+pn.getPeer());
// FIXME: follow the spec and send IDr' ?
if(payload.length < NONCE_SIZE +
DiffieHellman.modulusLengthInBytes() + 3 + (unknownInitiator ?
NodeCrypto.IDENTITY_LENGTH : 0)) {
Logger.error(this, "Packet too short from "+pn+":
"+payload.length+" after decryption in JFK(1), should be "+(NONCE_SIZE +
DiffieHellman.modulusLengthInBytes()));
@@ -743,7 +743,7 @@
long t2=System.currentTimeMillis();
if((t2-t1)>500)
- Logger.error(this,"Message1 timeout error:Sending
packet for"+pn.getPeer());
+ Logger.error(this,"Message1 timeout error:Processing
packet for"+pn.getPeer());
}
/*
@@ -752,7 +752,7 @@
* We send IDr' only if unknownInitiator is set.
*/
private void sendJFKMessage1(PeerNode pn, Peer replyTo, boolean
unknownInitiator, int setupType) {
- if(logMINOR) Logger.minor(this, "Sending a JFK(1) message to
"+replyTo+" for "+pn);
+ if(logMINOR) Logger.minor(this, "Sending a JFK(1) message to
"+replyTo+" for "+pn.getPeer());
final long now = System.currentTimeMillis();
DiffieHellmanLightContext ctx = (DiffieHellmanLightContext)
pn.getKeyAgreementSchemeContext();
if((ctx == null) || ((pn.jfkContextLifetime +
DH_GENERATION_INTERVAL*DH_CONTEXT_BUFFER_SIZE) < now)) {
@@ -782,6 +782,9 @@
} else {
sendAuthPacket(1,2,0,message1,pn,replyTo);
}
+ long t2=System.currentTimeMillis();
+ if((t2-now)>500)
+ Logger.error(this,"Message1 timeout error:Sending
packet for"+pn.getPeer());
}
/*
@@ -868,11 +871,11 @@
private void processJFKMessage2(byte[] payload,int inputOffset,PeerNode
pn,Peer replyTo, boolean unknownInitiator, int setupType)
{
long t1=System.currentTimeMillis();
- if(logMINOR) Logger.minor(this, "Got a JFK(2) message,
processing it - "+pn);
+ if(logMINOR) Logger.minor(this, "Got a JFK(2) message,
processing it - "+pn.getPeer());
// FIXME: follow the spec and send IDr' ?
int expectedLength = NONCE_SIZE*2 +
DiffieHellman.modulusLengthInBytes() + HASH_LENGTH*2;
if(payload.length < expectedLength + 3) {
- Logger.error(this, "Packet too short from "+pn+":
"+payload.length+" after decryption in JFK(2), should be "+(expectedLength +
3));
+ Logger.error(this, "Packet too short from
"+pn.getPeer()+": "+payload.length+" after decryption in JFK(2), should be
"+(expectedLength + 3));
return;
}
@@ -907,7 +910,7 @@
message3 = authenticatorCache.get(authenticator);
}
if(message3 != null) {
- Logger.normal(this, "We replayed a message from the
cache (shouldn't happen often) -"+pn);
+ Logger.normal(this, "We replayed a message from the
cache (shouldn't happen often) - "+pn.getPeer());
sendAuthPacket(1, 2, 3, (byte[]) message3, pn, replyTo);
return;
}
@@ -919,7 +922,8 @@
}
// We don't except such a message;
if(myNi == null) {
- Logger.normal(this, "We received an unexpected JFK(2)
message from "+pn);
+ if(shouldLogErrorInHandshake(t1))
+ Logger.normal(this, "We received an unexpected
JFK(2) message from "+pn.getPeer());
return;
} else if(!Arrays.equals(myNi, nonceInitiator)){
if(logMINOR)
@@ -928,7 +932,7 @@
}
if(!DiffieHellman.checkDHExponentialValidity(this.getClass(),
_hisExponential)) {
- Logger.error(this, "We can't accept the exponential
"+pn+" sent us!! REDFLAG: IT CAN'T HAPPEN UNLESS AGAINST AN ACTIVE ATTACKER!!");
+ Logger.error(this, "We can't accept the exponential
"+pn.getPeer()+" sent us!! REDFLAG: IT CAN'T HAPPEN UNLESS AGAINST AN ACTIVE
ATTACKER!!");
return;
}
@@ -938,7 +942,7 @@
byte[] locallyExpectedExponentials =
assembleDHParams(_hisExponential, pn.peerCryptoGroup);
if(!DSA.verify(pn.peerPubKey, remoteSignature, new
NativeBigInteger(1, SHA256.digest(locallyExpectedExponentials)), false)) {
- Logger.error(this, "The signature verification has
failed in JFK(2)!! "+pn);
+ Logger.error(this, "The signature verification has
failed in JFK(2)!! "+pn.getPeer());
return;
}
@@ -949,7 +953,7 @@
long t2=System.currentTimeMillis();
if((t2-t1)>500)
- Logger.error(this,"Message1 timeout error:Sending
packet for"+pn.getPeer());
+ Logger.error(this,"Message2 timeout error:Processing
packet for"+pn.getPeer());
}
/*
@@ -978,7 +982,7 @@
private void processJFKMessage3(byte[] payload, int inputOffset,
PeerNode pn,Peer replyTo, boolean oldOpennetPeer, boolean unknownInitiator, int
setupType)
{
final long t1 = System.currentTimeMillis();
- if(logMINOR) Logger.minor(this, "Got a JFK(3) message,
processing it - "+pn);
+ if(logMINOR) Logger.minor(this, "Got a JFK(3) message,
processing it - "+pn.getPeer());
BlockCipher c = null;
try { c = new Rijndael(256, 256); } catch
(UnsupportedCipherException e) {}
@@ -990,7 +994,7 @@
HASH_LENGTH + // it's at least a signature
8;
// a bootid
if(payload.length < expectedLength + 3) {
- Logger.error(this, "Packet too short from "+pn+":
"+payload.length+" after decryption in JFK(3), should be "+(expectedLength +
3));
+ Logger.error(this, "Packet too short from
"+pn.getPeer()+": "+payload.length+" after decryption in JFK(3), should be
"+(expectedLength + 3));
return;
}
@@ -1019,7 +1023,8 @@
// is it cheaper to wait for the lock on authenticatorCache or
to verify the hmac ?
HMAC mac = new HMAC(SHA256.getInstance());
if(!mac.verify(getTransientKey(),
assembleJFKAuthenticator(responderExponential, initiatorExponential,
nonceResponder, nonceInitiator, replyTo.getAddress().getAddress()) ,
authenticator)) {
- Logger.error(this, "The HMAC doesn't match; let's
discard the packet (either we rekeyed or we are victim of forgery) - JFK3");
+ if(shouldLogErrorInHandshake(t1))
+ Logger.normal(this, "The HMAC doesn't match;
let's discard the packet (either we rekeyed or we are victim of forgery) - JFK3
- "+pn.getPeer());
return;
}
// Check try to find the authenticator in the cache.
@@ -1030,7 +1035,7 @@
message4 = authenticatorCache.get(authenticator);
}
if(message4 != null) {
- Logger.normal(this, "We replayed a message from the
cache (shouldn't happen often) - "+pn);
+ Logger.normal(this, "We replayed a message from the
cache (shouldn't happen often) - "+pn.getPeer());
sendAuthPacket(1, 2, 3, (byte[]) message4, pn, replyTo);
return;
}
@@ -1044,7 +1049,7 @@
DiffieHellmanLightContext ctx =
findContextByExponential(_ourExponential);
if(ctx == null) {
- Logger.error(this, "WTF? the HMAC verified but we don't
know about that exponential! SHOULDN'T HAPPEN! - JFK4");
+ Logger.error(this, "WTF? the HMAC verified but we don't
know about that exponential! SHOULDN'T HAPPEN! - JFK3 - "+pn.getPeer());
return;
}
BigInteger computedExponential =
ctx.getHMACKey(_hisExponential, Global.DHgroupA);
@@ -1061,7 +1066,7 @@
decypheredPayloadOffset += JFK_PREFIX_INITIATOR.length;
System.arraycopy(payload, inputOffset, decypheredPayload,
decypheredPayloadOffset, decypheredPayload.length-decypheredPayloadOffset);
if(!mac.verify(Ka, decypheredPayload, hmac)) {
- Logger.error(this, "The digest-HMAC doesn't match;
let's discard the packet JFK(3) - "+pn);
+ Logger.error(this, "The inner-HMAC doesn't match; let's
discard the packet JFK(3) - "+pn.getPeer());
return;
}
@@ -1101,7 +1106,7 @@
// verify the signature
DSASignature remoteSignature = new DSASignature(new
NativeBigInteger(1,r), new NativeBigInteger(1,s));
if(!DSA.verify(pn.peerPubKey, remoteSignature, new
NativeBigInteger(1, SHA256.digest(assembleDHParams(nonceInitiator,
nonceResponder, _hisExponential, _ourExponential, crypto.myIdentity, data))),
false)) {
- Logger.error(this, "The signature verification has
failed!! JFK(3) - "+pn);
+ Logger.error(this, "The signature verification has
failed!! JFK(3) - "+pn.getPeer());
return;
}
@@ -1133,12 +1138,12 @@
else
pn.maybeSendInitialMessages();
} else {
- Logger.error(this, "Handshake failure! with "+pn);
+ Logger.error(this, "Handshake failure! with
"+pn.getPeer());
}
final long t2=System.currentTimeMillis();
if((t2-t1)>500)
- Logger.error(this,"Message3 Sending packet
for"+pn.getPeer()+" took "+TimeUtil.formatTime(t2-t1, 3, true));
+ Logger.error(this,"Message3 Processing packet
for"+pn.getPeer()+" took "+TimeUtil.formatTime(t2-t1, 3, true));
}
private PeerNode getPeerNodeFromUnknownInitiator(byte[] hisRef, int
setupType, PeerNode pn) {
@@ -1195,7 +1200,7 @@
private void processJFKMessage4(byte[] payload, int inputOffset,
PeerNode pn, Peer replyTo, boolean oldOpennetPeer, boolean unknownInitiator,
int setupType)
{
final long t1 = System.currentTimeMillis();
- if(logMINOR) Logger.minor(this, "Got a JFK(4) message,
processing it - "+pn);
+ if(logMINOR) Logger.minor(this, "Got a JFK(4) message,
processing it - "+pn.getPeer());
BlockCipher c = null;
try { c = new Rijndael(256, 256); } catch
(UnsupportedCipherException e) {}
@@ -1205,7 +1210,7 @@
pn.jfkMyRef.length // the bootid + mynoderef
;
if(payload.length < expectedLength + 3) {
- Logger.error(this, "Packet too short from "+pn+":
"+payload.length+" after decryption in JFK(4), should be "+(expectedLength +
3));
+ Logger.error(this, "Packet too short from
"+pn.getPeer()+": "+payload.length+" after decryption in JFK(4), should be
"+(expectedLength + 3));
return;
}
byte[] jfkBuffer = pn.getJFKBuffer();
@@ -1229,7 +1234,7 @@
System.arraycopy(payload, inputOffset, decypheredPayload,
decypheredPayloadOffset, payload.length-inputOffset);
HMAC mac = new HMAC(SHA256.getInstance());
if(!mac.verify(pn.jfkKa, decypheredPayload, hmac)) {
- Logger.error(this, "The digest-HMAC doesn't match;
let's discard the packet");
+ Logger.normal(this, "The digest-HMAC doesn't match;
let's discard the packet - "+pn.getPeer());
return;
}
// Get the IV
@@ -1266,7 +1271,7 @@
bufferOffset += data.length - pn.jfkMyRef.length;
System.arraycopy(pn.jfkMyRef, 0, locallyGeneratedText,
bufferOffset, pn.jfkMyRef.length);
if(!DSA.verify(pn.peerPubKey, remoteSignature, new
NativeBigInteger(1, SHA256.digest(locallyGeneratedText)), false)) {
- Logger.error(this, "The signature verification has
failed!! JFK(4) -"+pn);
+ Logger.error(this, "The signature verification has
failed!! JFK(4) -"+pn.getPeer());
return;
}
@@ -1313,7 +1318,7 @@
final long t2=System.currentTimeMillis();
if((t2-t1)>500)
- Logger.error(this,"Message3 timeout error:Sending
packet for"+pn.getPeer());
+ Logger.error(this,"Message4 timeout error:Processing
packet from "+pn.getPeer());
}
/*
@@ -1327,7 +1332,8 @@
private void sendJFKMessage3(int version,int negType,int phase,byte[]
nonceInitiator,byte[] nonceResponder,byte[] hisExponential, byte[]
authenticator, final PeerNode pn, final Peer replyTo, final boolean
unknownInitiator, final int setupType)
{
- if(logMINOR) Logger.minor(this, "Sending a JFK(3) message to
"+pn);
+ if(logMINOR) Logger.minor(this, "Sending a JFK(3) message to
"+pn.getPeer());
+ long t1=System.currentTimeMillis();
BlockCipher c = null;
try { c = new Rijndael(256, 256); } catch
(UnsupportedCipherException e) {}
DiffieHellmanLightContext ctx = (DiffieHellmanLightContext)
pn.getKeyAgreementSchemeContext();
@@ -1385,12 +1391,9 @@
node.random.nextBytes(iv);
pcfb.reset(iv);
int cleartextOffset = 0;
- byte[] prefix = null;
- try { prefix = "I".getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
-
- byte[] cleartext = new byte[prefix.length + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH * 2 + data.length];
- System.arraycopy(prefix, 0, cleartext, cleartextOffset,
prefix.length);
- cleartextOffset += prefix.length;
+ byte[] cleartext = new byte[JFK_PREFIX_INITIATOR.length +
ivLength + Node.SIGNATURE_PARAMETER_LENGTH * 2 + data.length];
+ System.arraycopy(JFK_PREFIX_INITIATOR, 0, cleartext,
cleartextOffset, JFK_PREFIX_INITIATOR.length);
+ cleartextOffset += JFK_PREFIX_INITIATOR.length;
System.arraycopy(iv, 0, cleartext, cleartextOffset, ivLength);
cleartextOffset += ivLength;
System.arraycopy(r, 0, cleartext, cleartextOffset,
Node.SIGNATURE_PARAMETER_LENGTH);
@@ -1400,7 +1403,7 @@
System.arraycopy(data, 0, cleartext, cleartextOffset,
data.length);
cleartextOffset += data.length;
- int cleartextToEncypherOffset = prefix.length + ivLength;
+ int cleartextToEncypherOffset = JFK_PREFIX_INITIATOR.length +
ivLength;
pcfb.blockEncipher(cleartext, cleartextToEncypherOffset,
cleartext.length-cleartextToEncypherOffset);
// We compute the HMAC of (prefix + cyphertext) Includes the IV!
@@ -1435,6 +1438,9 @@
}
}
}, 5*1000);
+ long t2=System.currentTimeMillis();
+ if((t2-t1)>500)
+ Logger.error(this,"Message3 timeout error:Sending
packet for"+pn.getPeer());
}
@@ -1447,7 +1453,8 @@
private void sendJFKMessage4(int version,int negType,int phase,byte[]
nonceInitiator,byte[] nonceResponder,byte[] initiatorExponential,byte[]
responderExponential, BlockCipher c, byte[] Ke, byte[] Ka, byte[]
authenticator, byte[] hisRef, PeerNode pn, Peer replyTo, boolean
unknownInitiator, int setupType)
{
if(logMINOR)
- Logger.minor(this, "Sending a JFK(4) message to "+pn);
+ Logger.minor(this, "Sending a JFK(4) message to
"+pn.getPeer());
+ long t1=System.currentTimeMillis();
NativeBigInteger _responderExponential = new
NativeBigInteger(1,responderExponential);
NativeBigInteger _initiatorExponential = new
NativeBigInteger(1,initiatorExponential);
@@ -1466,13 +1473,10 @@
byte[] iv=new byte[ivLength];
node.random.nextBytes(iv);
pk.reset(iv);
- byte[] prefix = null;
- try { prefix = "R".getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
-
- byte[] cyphertext = new byte[prefix.length + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH * 2 + data.length];
+ byte[] cyphertext = new byte[JFK_PREFIX_RESPONDER.length +
ivLength + Node.SIGNATURE_PARAMETER_LENGTH * 2 + data.length];
int cleartextOffset = 0;
- System.arraycopy(prefix, 0, cyphertext, cleartextOffset,
prefix.length);
- cleartextOffset += prefix.length;
+ System.arraycopy(JFK_PREFIX_RESPONDER, 0, cyphertext,
cleartextOffset, JFK_PREFIX_RESPONDER.length);
+ cleartextOffset += JFK_PREFIX_RESPONDER.length;
System.arraycopy(iv, 0, cyphertext, cleartextOffset, ivLength);
cleartextOffset += ivLength;
System.arraycopy(r, 0, cyphertext, cleartextOffset,
Node.SIGNATURE_PARAMETER_LENGTH);
@@ -1482,7 +1486,7 @@
System.arraycopy(data, 0, cyphertext, cleartextOffset,
data.length);
cleartextOffset += data.length;
// Now encrypt the cleartext[Signature]
- int cleartextToEncypherOffset = prefix.length + ivLength;
+ int cleartextToEncypherOffset = JFK_PREFIX_RESPONDER.length +
ivLength;
pk.blockEncipher(cyphertext, cleartextToEncypherOffset,
cyphertext.length - cleartextToEncypherOffset);
// We compute the HMAC of (prefix + iv + signature)
@@ -1508,6 +1512,9 @@
sendAnonAuthPacket(1, 2, 3, setupType, message4, pn,
replyTo, crypto.anonSetupCipher);
else
sendAuthPacket(1, 2, 3, message4, pn, replyTo);
+ long t2=System.currentTimeMillis();
+ if((t2-t1)>500)
+ Logger.error(this,"Message4 timeout error:Sending
packet for"+pn.getPeer());
}
/**
@@ -1556,12 +1563,13 @@
// throw new IllegalStateException("Cannot send auth
packet: too long: "+length);
// }
PCFBMode pcfb = PCFBMode.create(cipher);
- int paddingLength = node.fastWeakRandom.nextInt(100);
byte[] iv = new byte[pcfb.lengthIV()];
node.random.nextBytes(iv);
byte[] hash = SHA256.digest(output);
if(logMINOR) Logger.minor(this, "Data hash:
"+HexUtil.bytesToHex(hash));
- byte[] data = new byte[iv.length + hash.length + 2 /* length */
+ output.length + paddingLength];
+ int prePaddingLength = iv.length + hash.length + 2 /* length */
+ output.length;
+ int paddingLength = node.fastWeakRandom.nextInt(Math.min(100,
sock.getMaxPacketSize() - HEADERS_LENGTH_MINIMUM - prePaddingLength));
+ byte[] data = new byte[prePaddingLength + paddingLength];
pcfb.reset(iv);
System.arraycopy(iv, 0, data, 0, iv.length);
pcfb.blockEncipher(hash, 0, hash.length);
@@ -1597,9 +1605,8 @@
/**
* Should we log an error for an event that could easily be
* caused by a handshake across a restart boundary?
- */
- private boolean shouldLogErrorInHandshake() {
- long now = System.currentTimeMillis();
+ */
+ private boolean shouldLogErrorInHandshake(long now) {
if(now - node.startupTime < Node.HANDSHAKE_TIMEOUT*2)
return false;
return true;