Author: nextgens
Date: 2007-09-29 16:52:18 +0000 (Sat, 29 Sep 2007)
New Revision: 15387
Modified:
branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
Log:
JFK works : nodes connect ... we still have to sort out some things like
rekeying and well, test it.
Modified: branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
===================================================================
--- branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-29
16:30:02 UTC (rev 15386)
+++ branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-29
16:52:18 UTC (rev 15387)
@@ -433,7 +433,7 @@
* using the same keys as in the previous
message.
* The signature is non-message recovering
*/
- processMessage4(payload, pn);
+ processMessage4(payload, pn, replyTo);
}
}
else {
@@ -693,7 +693,8 @@
HASH_LENGTH + // authenticator
HASH_LENGTH + // HMAC of the cyphertext
(c.getBlockSize() >> 3) + // IV
-
HASH_LENGTH; // it's at least a signature
+
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));
return;
@@ -762,6 +763,7 @@
DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext(pn);
BigInteger computedExponential =
dhContext.getHMACKey(_hisExponential, Global.DHgroupA);
+ byte[] Ks = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "0");
byte[] Ke = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "1");
byte[] Ka = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "2");
c.initialize(Ke);
@@ -771,10 +773,10 @@
// We compute the HMAC of ("I"+cyphertext) : the cyphertext
includes the IV!
byte[] prefix = null;
try { prefix = "I".getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
- byte[] decypheredPayload = new byte[prefix.length + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH*2];
+ byte[] decypheredPayload = new byte[prefix.length +
payload.length - inputOffset];
System.arraycopy(prefix, 0, decypheredPayload,
decypheredPayloadOffset, prefix.length);
decypheredPayloadOffset += prefix.length;
- System.arraycopy(payload, inputOffset, decypheredPayload,
decypheredPayloadOffset, ivLength + Node.SIGNATURE_PARAMETER_LENGTH*2);
+ 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");
return;
@@ -784,7 +786,7 @@
pk.reset(decypheredPayload, decypheredPayloadOffset);
decypheredPayloadOffset += ivLength;
// Decrypt the payload
- pk.blockDecipher(decypheredPayload, decypheredPayloadOffset,
Node.SIGNATURE_PARAMETER_LENGTH*2);
+ pk.blockDecipher(decypheredPayload, decypheredPayloadOffset,
decypheredPayload.length-decypheredPayloadOffset);
/*
* DecipheredData Format:
* Signature-r,s
@@ -795,6 +797,10 @@
byte[] s = new byte[Node.SIGNATURE_PARAMETER_LENGTH];
System.arraycopy(decypheredPayload, decypheredPayloadOffset, s,
0, Node.SIGNATURE_PARAMETER_LENGTH);
decypheredPayloadOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+ byte[] data = new byte[decypheredPayload.length -
decypheredPayloadOffset];
+ System.arraycopy(decypheredPayload, decypheredPayloadOffset,
data, 0, decypheredPayload.length - decypheredPayloadOffset);
+ long bootID = Fields.bytesToLong(data);
+
// verify the signature
DSASignature remoteSignature = new DSASignature(new
NativeBigInteger(1,r), new NativeBigInteger(1,s));
@@ -807,7 +813,10 @@
sendMessage4Packet(1, 2, 3, nonceInitiator,
nonceResponder,initiatorExponential, responderExponential, c, Ke, Ka,
authenticator, pn, replyTo);
//FIXME: rekey .... ?
- System.out.println("Time to call completedHandshake ^-^");
+ c.initialize(Ks);
+ if(!pn.completedHandshake(bootID, data, 8, data.length-8, c,
Ks, replyTo, false)) {
+ Logger.error(this, "Handshake failure!");
+ }
final long t2=System.currentTimeMillis();
if((t2-t1)>500)
@@ -822,7 +831,7 @@
* @param The peerNode we are talking to
*
*/
- private void processMessage4(byte[] payload, PeerNode pn)
+ private void processMessage4(byte[] payload, PeerNode pn, Peer replyTo)
{
final long t1 = System.currentTimeMillis();
if(logMINOR) Logger.minor(this, "Got a JFK(4) message,
processing it");
@@ -832,7 +841,9 @@
final int expectedLength = HASH_LENGTH + // HMAC of the
cyphertext
(c.getBlockSize() >> 3) + // IV
-
HASH_LENGTH; // the signature
+
HASH_LENGTH + // the signature
+ 8
// the bootid; there should be the noderef too
+ ;
if(payload.length < expectedLength + 3) {
Logger.error(this, "Packet too short from "+pn+":
"+payload.length+" after decryption in JFK(4), should be "+(expectedLength +
3));
return;
@@ -855,10 +866,10 @@
// We compute the HMAC of ("I"+cyphertext) : the cyphertext
includes the IV!
byte[] prefix = null;
try { prefix = "R".getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
- byte[] decypheredPayload = new byte[prefix.length + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH*2];
+ byte[] decypheredPayload = new byte[prefix.length +
(payload.length-inputOffset)];
System.arraycopy(prefix, 0, decypheredPayload,
decypheredPayloadOffset, prefix.length);
decypheredPayloadOffset += prefix.length;
- System.arraycopy(payload, inputOffset, decypheredPayload,
decypheredPayloadOffset, ivLength + Node.SIGNATURE_PARAMETER_LENGTH*2);
+ 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");
@@ -869,7 +880,7 @@
pk.reset(decypheredPayload, decypheredPayloadOffset);
decypheredPayloadOffset += ivLength;
// Decrypt the payload
- pk.blockDecipher(decypheredPayload, decypheredPayloadOffset,
Node.SIGNATURE_PARAMETER_LENGTH*2);
+ pk.blockDecipher(decypheredPayload, decypheredPayloadOffset,
decypheredPayload.length - decypheredPayloadOffset);
/*
* DecipheredData Format:
* Signature-r,s
@@ -880,6 +891,9 @@
byte[] s = new byte[Node.SIGNATURE_PARAMETER_LENGTH];
System.arraycopy(decypheredPayload, decypheredPayloadOffset, s,
0, Node.SIGNATURE_PARAMETER_LENGTH);
decypheredPayloadOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+ byte[] data = new byte[decypheredPayload.length -
decypheredPayloadOffset];
+ System.arraycopy(decypheredPayload, decypheredPayloadOffset,
data, 0, decypheredPayload.length - decypheredPayloadOffset);
+ long bootID = Fields.bytesToLong(data);
// verify the signature
DSASignature remoteSignature = new DSASignature(new
NativeBigInteger(1,r), new NativeBigInteger(1,s));
@@ -893,13 +907,16 @@
}
//FIXME: when do we reset the buffer/rekey/DH/transientkey ?
- System.out.println("time to call completedHandshake! ^-^");
- // pn.completedHandshake(bufferOffset, locallyGeneratedText,
decypheredPayloadOffset, ivLength, c, Ke, replyTo, false)
-
+ // We change the key
+ c.initialize(pn.jfkKs);
+ if(!pn.completedHandshake(bootID, data, 8, data.length - 8, c,
pn.jfkKs, replyTo, false)) {
+ Logger.error(this, "Handshake failed!");
+ }
// cleanup
pn.setJFKBuffer(null);
pn.jfkKa = null;
pn.jfkKe = null;
+ pn.jfkKs = null;
final long t2=System.currentTimeMillis();
if((t2-t1)>500)
@@ -939,13 +956,17 @@
try { c = new Rijndael(256, 256); } catch
(UnsupportedCipherException e) {}
DiffieHellmanLightContext dhContext =
getLightDiffieHellmanContext(pn);
byte[] ourExponential =
stripBigIntegerToNetworkFormat(dhContext.myExponential);
+ byte[] myRef = crypto.myCompressedSetupRef();
+ byte[] data = new byte[8 + myRef.length];
+ System.arraycopy(Fields.longToBytes(node.bootID), 0, data, 0,
8);
+ System.arraycopy(myRef, 0, data, 8, myRef.length);
byte[] message3 = new byte[NONCE_SIZE*2 + // nI, nR
DiffieHellman.modulusLengthInBytes()*2 + // g^i, g^r
HASH_LENGTH + // authenticator
HASH_LENGTH + // HMAC(cyphertext)
(c.getBlockSize() >> 3) + // IV
- Node.SIGNATURE_PARAMETER_LENGTH * 2
// Signature (R,S)
- ];
+ Node.SIGNATURE_PARAMETER_LENGTH * 2
+ // Signature (R,S)
+ data.length]; // The bootid+noderef
int offset = 0;
// Ni
System.arraycopy(nonceInitiator, 0, message3, offset,
NONCE_SIZE);
@@ -975,8 +996,9 @@
DSASignature localSignature =
crypto.sign(SHA256.digest(toSign));
byte[] r =
localSignature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
byte[] s =
localSignature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
-
+
BigInteger computedExponential =
dhContext.getHMACKey(_hisExponential, Global.DHgroupA);
+ pn.jfkKs = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "0");
pn.jfkKe = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "1");
pn.jfkKa = computeJFKSharedKey(computedExponential,
nonceInitiator, nonceResponder, "2");
c.initialize(pn.jfkKe);
@@ -989,7 +1011,7 @@
byte[] prefix = null;
try { prefix = "I".getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
- byte[] cleartext = new byte[prefix.length + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH * 2];
+ 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;
System.arraycopy(iv, 0, cleartext, cleartextOffset, ivLength);
@@ -998,9 +1020,11 @@
cleartextOffset += Node.SIGNATURE_PARAMETER_LENGTH;
System.arraycopy(s, 0, cleartext, cleartextOffset,
Node.SIGNATURE_PARAMETER_LENGTH);
cleartextOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+ System.arraycopy(data, 0, cleartext, cleartextOffset,
data.length);
+ cleartextOffset += data.length;
int cleartextToEncypherOffset = prefix.length + ivLength;
- pcfb.blockEncipher(cleartext, cleartextToEncypherOffset,
Node.SIGNATURE_PARAMETER_LENGTH * 2);
+ pcfb.blockEncipher(cleartext, cleartextToEncypherOffset,
cleartext.length-cleartextToEncypherOffset);
// We compute the HMAC of (prefix + cyphertext) Includes the IV!
HMAC mac = new HMAC(SHA256.getInstance());
@@ -1011,7 +1035,7 @@
offset += HASH_LENGTH;
System.arraycopy(iv, 0, message3, offset, ivLength);
offset += ivLength;
- System.arraycopy(cleartext, cleartextToEncypherOffset,
message3, offset, Node.SIGNATURE_PARAMETER_LENGTH * 2);
+ System.arraycopy(cleartext, cleartextToEncypherOffset,
message3, offset, cleartext.length-cleartextToEncypherOffset);
// cache the message
synchronized (authenticatorCache) {
@@ -1036,6 +1060,11 @@
byte[] r =
localSignature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
byte[] s =
localSignature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
+ byte[] myRef = crypto.myCompressedSetupRef();
+ byte[] data = new byte[8 + myRef.length];
+ System.arraycopy(Fields.longToBytes(node.bootID), 0, data, 0,
8);
+ System.arraycopy(myRef, 0, data, 8, myRef.length);
+
PCFBMode pk=PCFBMode.create(c);
int ivLength = pk.lengthIV();
byte[] iv=new byte[ivLength];
@@ -1044,7 +1073,7 @@
byte[] prefix = null;
try { prefix = "R".getBytes("UTF-8"); } catch
(UnsupportedEncodingException e) {}
- byte[] cyphertext = new byte[prefix.length + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH * 2];
+ byte[] cyphertext = new byte[prefix.length + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH * 2 + data.length];
int cleartextOffset = 0;
System.arraycopy(prefix, 0, cyphertext, cleartextOffset,
prefix.length);
cleartextOffset += prefix.length;
@@ -1054,22 +1083,24 @@
cleartextOffset += Node.SIGNATURE_PARAMETER_LENGTH;
System.arraycopy(s, 0, cyphertext, cleartextOffset,
Node.SIGNATURE_PARAMETER_LENGTH);
cleartextOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+ System.arraycopy(data, 0, cyphertext, cleartextOffset,
data.length);
+ cleartextOffset += data.length;
// Now encrypt the cleartext[Signature]
int cleartextToEncypherOffset = prefix.length + ivLength;
- pk.blockEncipher(cyphertext, cleartextToEncypherOffset,
Node.SIGNATURE_PARAMETER_LENGTH*2);
+ pk.blockEncipher(cyphertext, cleartextToEncypherOffset,
cyphertext.length - cleartextToEncypherOffset);
// We compute the HMAC of (prefix + iv + signature)
HMAC mac = new HMAC(SHA256.getInstance());
byte[] hmac = mac.mac(Ka, cyphertext, HASH_LENGTH);
// Message4 = hmac + IV + encryptedSignature
- byte[] message4 = new byte[HASH_LENGTH + ivLength +
Node.SIGNATURE_PARAMETER_LENGTH * 2];
+ byte[] message4 = new byte[HASH_LENGTH + ivLength +
(cyphertext.length - cleartextToEncypherOffset)];
int offset = 0;
System.arraycopy(hmac, 0, message4, offset, HASH_LENGTH);
offset += HASH_LENGTH;
System.arraycopy(iv, 0, message4, offset, ivLength);
offset += ivLength;
- System.arraycopy(cyphertext, cleartextToEncypherOffset,
message4, offset, Node.SIGNATURE_PARAMETER_LENGTH * 2);
+ System.arraycopy(cyphertext, cleartextToEncypherOffset,
message4, offset, cyphertext.length - cleartextToEncypherOffset);
// cache the message
synchronized (authenticatorCache) {