Author: nextgens
Date: 2007-09-27 10:51:44 +0000 (Thu, 27 Sep 2007)
New Revision: 15361

Modified:
   branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
Log:
More work on jfk : processMessage3() is now almost finished

Modified: branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
===================================================================
--- branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-26 
22:23:24 UTC (rev 15360)
+++ branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-27 
10:51:44 UTC (rev 15361)
@@ -19,7 +19,10 @@
 import freenet.crypt.EntropySource;
 import freenet.crypt.HMAC;
 import freenet.crypt.PCFBMode;
+import freenet.crypt.RijndaelPCFBMode;
 import freenet.crypt.SHA256;
+import freenet.crypt.UnsupportedCipherException;
+import freenet.crypt.ciphers.Rijndael;
 import freenet.crypt.crypto_Random.eKey;
 import freenet.io.comm.AsyncMessageCallback;
 import freenet.io.comm.FreenetInetAddress;
@@ -652,6 +655,7 @@
         * Send the authenticator which allows the responder to verify the 
legality of the message
         * Compute the signature of the unVerifiedData and encrypt it using a 
shared key
         * which is derived from DHExponentials and the nonces
+        * 
         * @param Payload
         * @param The peer to which we need to send the packet
         * @param The peerNode we are talking to
@@ -659,9 +663,22 @@
         */
        private void processMessage3(byte[] payload, PeerNode pn,Peer replyTo)  
                
        {
-               long t1 = System.currentTimeMillis();
+               final long t1 = System.currentTimeMillis();
                if(logMINOR) Logger.minor(this, "Got a JFK(3) message, 
processing it");
+               BlockCipher c = null;
+               try { c = new Rijndael(256, 256); } catch 
(UnsupportedCipherException e) {}
                int inputOffset=3;
+               
+               final int expectedLength =      NONCE_SIZE*2 + 
DiffieHellman.modulusLengthInBytes()*2 +
+                                                                       
HASH_LENGTH + // authenticator
+                                                                       
HASH_LENGTH + // HMAC of the cyphertext
+                                                                       
(c.getBlockSize() >> 3) + // ugly way of getting the size of the IV
+                                                                       
HASH_LENGTH; // it's at least a signature
+               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;
+               }
+               
                // Ni
                byte[] nonceInitiator = new byte[NONCE_SIZE];
                System.arraycopy(payload, inputOffset, nonceInitiator, 0, 
NONCE_SIZE);
@@ -678,6 +695,7 @@
                byte[] responderExponential = new 
byte[DiffieHellman.modulusLengthInBytes()];
                System.arraycopy(payload, inputOffset, responderExponential, 0, 
DiffieHellman.modulusLengthInBytes());
                inputOffset += DiffieHellman.modulusLengthInBytes();
+               
                byte[] authenticator = new byte[HASH_LENGTH];
                System.arraycopy(payload, inputOffset, authenticator, 0, 
HASH_LENGTH);
                inputOffset += HASH_LENGTH;
@@ -697,11 +715,10 @@
                }
                if(message4 != null) {
                        Logger.normal(this, "We replayed a message from the 
cache (shouldn't happen often)");
-                       //sendMessage3Packet(1, 2, 3, message4);
                        try{
-                               
sendAuthPacket(1,2,3,getBytes(message4),pn,replyTo);
+                               sendAuthPacket(1, 2, 3, getBytes(message4), pn, 
replyTo);
                        }catch(IOException e){
-                               Logger.error(this,"Error getting bytes");
+                               Logger.error(this,"Error getting bytes... wtf ? 
"+e.getMessage(), e);
                        }
                        return;
                }
@@ -717,29 +734,42 @@
                        Logger.error(this, "We can't accept the exponential 
"+pn+" sent us; it's smaller than 1!! (our exponential?!?)");
                        return;
                }
-               // Decrypt
-               BlockCipher c = pn.outgoingSetupCipher;
-               PCFBMode pk=PCFBMode.create(c);
+               
+               byte[] hmac = new byte[HASH_LENGTH];
+               System.arraycopy(payload, inputOffset, hmac, 0, HASH_LENGTH);
+               inputOffset += HASH_LENGTH;
+               c.initialize();
+               final PCFBMode pk = PCFBMode.create(c);
                int ivLength = pk.lengthIV();
-               pk.reset(payload,inputOffset);
-               // Decrypt the rest of the payload
-               
pk.blockDecipher(payload,inputOffset,payload.length-inputOffset);
-               inputOffset += ivLength;
+               int decypheredPayloadOffset = 0;
+               // We compute the HMAC of ("I"+cyphertext) : the cyphertext 
includes the IV!
+               byte[] prefix = "I".getBytes("UTF-8");
+               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, payload.length - inputOffset);
+               if(!mac.verify(null /*FIXME*/, decypheredPayload, hmac)) {
+                       Logger.error(this, "The digest-HMAC doesn't match; 
let's discard the packet");
+                       return;
+               }
+               
+               // Get the IV
+               pk.reset(decypheredPayload, decypheredPayloadOffset);
+               decypheredPayloadOffset += ivLength;
+               // Decrypt the payload
+               pk.blockDecipher(decypheredPayload, decypheredPayloadOffset, 
payload.length-decypheredPayloadOffset);
                /*
                 * DecipheredData Format:
-                * idI
                 * Signature-r,s
                 */
-               byte[] idI = new byte[0];
-               System.arraycopy(payload,inputOffset , idI ,0, idI.length);
-               inputOffset += idI.length;
-               // Now verify signature
                byte[] r = new byte[Node.SIGNATURE_PARAMETER_LENGTH];
-               System.arraycopy(payload, inputOffset, r, 0, 
Node.SIGNATURE_PARAMETER_LENGTH);
-               inputOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+               System.arraycopy(decypheredPayload, decypheredPayloadOffset, r, 
0, Node.SIGNATURE_PARAMETER_LENGTH);
+               decypheredPayloadOffset += Node.SIGNATURE_PARAMETER_LENGTH;
                byte[] s = new byte[Node.SIGNATURE_PARAMETER_LENGTH];
-               System.arraycopy(payload, inputOffset, s, 0, 
Node.SIGNATURE_PARAMETER_LENGTH);
-               inputOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+               System.arraycopy(decypheredPayload, decypheredPayloadOffset, s, 
0, Node.SIGNATURE_PARAMETER_LENGTH);
+               decypheredPayloadOffset += Node.SIGNATURE_PARAMETER_LENGTH;
+               
+               // verify the signature
                DSASignature remoteSignature = new DSASignature(new 
NativeBigInteger(1,r), new NativeBigInteger(1,s));
                if(logMINOR)
                        Logger.minor(this, "Remote sent us the following sig 
:"+remoteSignature.toLongString());
@@ -750,12 +780,14 @@
                        return;
                }
                // cache the message
-               authenticatorCache.put(authenticator,payload);
+               synchronized (authenticatorCache) {
+                       authenticatorCache.put(authenticator,payload);
+               }
                // Send reply
-               sendMessage4Packet(1, 2, 3, nonceInitiator, 
nonceResponder,initiatorExponential, responderExponential,idI,c, pn, replyTo);
-               long t2=System.currentTimeMillis();
+               sendMessage4Packet(1, 2, 3, nonceInitiator, 
nonceResponder,initiatorExponential, responderExponential, c , pn, replyTo);
+               final long t2=System.currentTimeMillis();
                if((t2-t1)>500)
-                       Logger.error(this,"Message1 timeout error:Sending 
packet for"+pn.getPeer());
+                       Logger.error(this,"Message3 timeout error:Sending 
packet for"+pn.getPeer());
        }

        /*
@@ -912,7 +944,7 @@
         * FOrmat:
         * E[S[Ni,Nr,g^i,g^r,idI]] 
         */
-       private void sendMessage4Packet(int version,int negType,int 
phase,byte[] nonceInitiator,byte[] nonceResponder,byte[] ourExponential,byte[] 
hisExponential,byte[] idI, BlockCipher c ,PeerNode pn,Peer replyTo)
+       private void sendMessage4Packet(int version,int negType,int 
phase,byte[] nonceInitiator,byte[] nonceResponder,byte[] ourExponential,byte[] 
hisExponential, BlockCipher c ,PeerNode pn,Peer replyTo)
        {
                if(logMINOR)
                        Logger.minor(this, "Sending a JFK(4) message to "+pn);
@@ -921,7 +953,7 @@
                DiffieHellmanLightContext dhContext = 
getLightDiffieHellmanContext(pn);
                NativeBigInteger _ourExponential = new 
NativeBigInteger(1,ourExponential);
                NativeBigInteger _hisExponential = new 
NativeBigInteger(1,hisExponential);
-               DSASignature localSignature = 
signDHParams(nonceInitiator,nonceResponder,_ourExponential,_hisExponential,idI);
+               DSASignature localSignature = 
signDHParams(nonceInitiator,nonceResponder,_ourExponential,_hisExponential, 
crypto.myIdentity);
                byte[] r = 
localSignature.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
                byte[] s = 
localSignature.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
                NativeBigInteger tempKey = 
dhContext.getHMACKey(_hisExponential, pn.peerCryptoGroup);
@@ -2228,16 +2260,19 @@
        }
        /*
         * Prepare params for signing in Message3
+        * 
+        * @return a hash ready to be signed by DSASign
         */
        private byte[] assembleDHParams(byte[] nonceInitiator,byte[] 
nonceResponder,BigInteger myExponential, BigInteger hisExponential) {
                byte[] _myExponential = 
stripBigIntegerToNetworkFormat(myExponential);
                byte[] _hisExponential = 
stripBigIntegerToNetworkFormat(hisExponential);
                byte[] toSign = new byte[nonceInitiator.length + 
nonceResponder.length + _myExponential.length + _hisExponential.length];
+               
                System.arraycopy(nonceInitiator, 
0,toSign,0,nonceInitiator.length);
                System.arraycopy(nonceResponder,0 
,toSign,nonceInitiator.length,nonceResponder.length);
                System.arraycopy(_myExponential, 0, 
toSign,nonceInitiator.length+nonceResponder.length, _myExponential.length);
                System.arraycopy(_hisExponential, 0, toSign, 
nonceInitiator.length+nonceResponder.length+_myExponential.length, 
_hisExponential.length);
-               // Why is the hash returned?
+               
                return SHA256.digest(toSign);
        }
        /*
@@ -2271,9 +2306,10 @@
        /*
         * Sign the params for message4
         */
-       private DSASignature signDHParams(byte[] nonceInitiator,byte[] 
nonceResponder,BigInteger myExponential, BigInteger hisExponential,byte[] idI) {
-               return 
crypto.sign(assembleDHParams(nonceInitiator,nonceResponder,myExponential,hisExponential,idI));
+       private DSASignature signDHParams(byte[] nonceInitiator,byte[] 
nonceResponder,BigInteger myExponential, BigInteger hisExponential,byte[] 
hashIDi) {
+               return 
crypto.sign(assembleDHParams(nonceInitiator,nonceResponder, myExponential, 
hisExponential, hashIDi));
        }
+       
        private byte[] getTransientKey() {
                synchronized (authenticatorCache) {
                        return transientKey;


Reply via email to