Author: kryptos
Date: 2007-09-10 07:07:45 +0000 (Mon, 10 Sep 2007)
New Revision: 15111

Modified:
   branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
Log:
Message3 parsed and verified:Need to look into the Fixme's though

Modified: branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java
===================================================================
--- branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-10 
05:00:08 UTC (rev 15110)
+++ branches/freenet-jfk/src/freenet/node/FNPPacketMangler.java 2007-09-10 
07:07:45 UTC (rev 15111)
@@ -627,6 +627,7 @@
         * Send a signed copy of his own exponential
         * Send an authenticator which is a hash of Ni,Nr,g^r calculated over 
the transient key HKr
          * Format of JFK(2) as specified above
+         * @param Payload
         * @param The packet phase number
         * @param The peer to which we need to send the packet
         * @param The peerNode we are talking to
@@ -637,6 +638,7 @@
                long t1=System.currentTimeMillis();
                if(logMINOR) Logger.minor(this, "Got a JFK(2) message, 
processing it");
                // FIXME: follow the spec and send IDr' ?
+                // FIXME: Are we checking for the right condition here?
                if(payload.length < NONCE_SIZE + 
DiffieHellman.modulusLengthInBytes()) {
                        Logger.error(this, "Packet too short from "+pn+": 
"+payload.length+" after decryption in JFK("+phase+"), should be "+(NONCE_SIZE 
+ DiffieHellman.modulusLengthInBytes()));
                        return;
@@ -709,64 +711,60 @@
         * @param The peerNode we are talking to
         * @return byte Message3
         */
-       private byte[] ProcessMessage3(byte[] payload, PeerNode pn,Peer 
replyTo,int phase)                      
+       private void ProcessMessage3(byte[] payload, PeerNode pn,Peer 
replyTo,int phase)                        
        {
-               if(logMINOR) Logger.minor(this, "Got a JFK(3) message, 
processing it");
-               // Get the authenticator,which is the latest entry into the 
cache
-               // It is basically a keyed hash(HMAC); size of output is that 
of the underlying hash function 
-               byte[] authenticator = new byte[16];
-                byte[] Ni = iNonce();
-               byte[] Nr = rNonce();
-               byte[] DHExpi = Gi(pn);
-               byte[] DHExpr = Gr(pn);
-               byte[] unVerifiedData=new 
byte[Ni.length+Nr.length+DHExpr.length+DHExpi.length+1];
-               System.arraycopy(Ni,0,unVerifiedData,0,Ni.length);
-               System.arraycopy(Nr,0,unVerifiedData,Ni.length+1,Nr.length);
-               
System.arraycopy(DHExpi,0,unVerifiedData,Ni.length+Nr.length+1,DHExpi.length);
-               
System.arraycopy(DHExpr,0,unVerifiedData,Ni.length+Nr.length+DHExpi.length+1,DHExpr.length);
-               /*
-                * Digital Signature of the message with the private key 
belonging to the initiator/responder
-                * It is assumed to be non-message recovering
-                */
-               PKI=new DSAPrivateKey(g, r);
-               //Params: Data,DSAGroup,DSAPrivateKey,randomSource
-               DSASignature sig = crypto.sign(unVerifiedData,g,PKI,r);
-               byte[] r = sig.getRBytes(Node.SIGNATURE_PARAMETER_LENGTH);
-               byte[] s = sig.getSBytes(Node.SIGNATURE_PARAMETER_LENGTH);
-               Logger.minor(this, " 
r="+HexUtil.bytesToHex(sig.getR().toByteArray())+" 
s="+HexUtil.bytesToHex(sig.getS().toByteArray()));
-               BlockCipher c=pn.outgoingSetupCipher;
-               if(logMINOR)
-                       
Logger.minor(this,"Cipher"+HexUtil.bytesToHex(pn.outgoingSetupKey));
-               /*
-                * Initializes the cipher context with the given key
-                * This would avoid the computation of key using the Rijndael 
key schedule(S boxes,Rcon etc)
-                * The key used is generated from Hash of Message:(Ni, Nr, 1) 
over the shared key of DH
-                */
-               
c.initialize(encryptionKey.getEncKey(sharedSecretKey(pn),iNonce(),rNonce()));
-               PCFBMode pk=PCFBMode.create(c);
+               long t1 = System.currentTimeMillis();
+                if(logMINOR) Logger.minor(this, "Got a JFK(3) message, 
processing it");
+               int inputOffset=0;
+               byte[] nonceInitiator = new byte[NONCE_SIZE];
+               System.arraycopy(payload, inputOffset, nonceInitiator, 0, 
NONCE_SIZE);
+               inputOffset += NONCE_SIZE;
+               byte[] nonceResponder = new byte[NONCE_SIZE];
+               System.arraycopy(payload, inputOffset, nonceResponder, 0, 
NONCE_SIZE);
+               inputOffset += NONCE_SIZE;
+               byte[] ourExponential = new 
byte[DiffieHellman.modulusLengthInBytes()];
+               System.arraycopy(payload, inputOffset, ourExponential, 0, 
DiffieHellman.modulusLengthInBytes());
+               inputOffset += DiffieHellman.modulusLengthInBytes();
+               byte[] hisExponential = new 
byte[DiffieHellman.modulusLengthInBytes()];
+               System.arraycopy(payload, inputOffset, hisExponential, 0, 
DiffieHellman.modulusLengthInBytes());
+               inputOffset += DiffieHellman.modulusLengthInBytes();
+               NativeBigInteger _hisExponential = new NativeBigInteger(1, 
hisExponential);
+               if(_hisExponential.compareTo(NativeBigInteger.ONE) < 1) {
+                       Logger.error(this, "We can't accept the exponential 
"+pn+" sent us; it's smaller than 1!!");
+                       return;
+               }
+               byte[] remoteHashedAuthenticator = new byte[HASH_LENGTH];
+               System.arraycopy(payload, inputOffset, 
remoteHashedAuthenticator, 0, HASH_LENGTH);
+               inputOffset += HASH_LENGTH;
+                // FIXME: Is this the right way?
+                int cipherLength = 
payload.length-NONCE_SIZE*2-DiffieHellman.modulusLengthInBytes()*2-HASH_LENGTH;
+                byte[] encryptedData = new byte[cipherLength];
+                System.arraycopy(payload, inputOffset,encryptedData, 0, 
cipherLength);
+                inputOffset += cipherLength;
+                //Decrypt 
+                BlockCipher c=pn.outgoingSetupCipher;
+                PCFBMode pk=PCFBMode.create(c);
                byte[] iv=new byte[pk.lengthIV()];
-               int encryptedDataLength = iv.length + r.length + s.length + 2;
-               /*
-                * Data sent in the clear is signed and encrypted using PCFB 
and rijndael
-                */
-               byte[] encryptedData = new byte[encryptedDataLength];
-               System.arraycopy(iv, 0, encryptedData, 0, iv.length);
-               int count = iv.length;
-               if(r.length > 255 || s.length > 255)
-                       throw new IllegalStateException("R or S is too long: 
r.length="+r.length+" s.length="+s.length);
-               encryptedData[count++] = (byte) r.length;
-               System.arraycopy(r, 0, encryptedData, count, r.length);
-               count += r.length;
-               encryptedData[count++] = (byte) s.length;
-               System.arraycopy(s, 0, encryptedData, count, s.length);
-               count += s.length;
-               pk.blockEncipher(encryptedData, 0, encryptedData.length);
-               byte[] message3=new 
byte[encryptedData.length+authenticator.length+unVerifiedData.length+1];
-               
System.arraycopy(encryptedData,0,message3,0,encryptedData.length);
-               
System.arraycopy(authenticator,0,message3,encryptedData.length+1,authenticator.length);
-               
System.arraycopy(unVerifiedData,0,message3,encryptedData.length+authenticator.length+1,unVerifiedData.length);
-               return message3;
-
+                pk.blockDecipher(encryptedData,0,cipherLength);
+                byte[] signData = new 
byte[NONCE_SIZE*2+DiffieHellman.modulusLengthInBytes()*2];
+               int offset = 0;
+               System.arraycopy(nonceInitiator, 0, signData, offset, 
NONCE_SIZE);
+               offset += NONCE_SIZE;
+               System.arraycopy(nonceResponder, 0,signData, offset, 
NONCE_SIZE);
+               offset += NONCE_SIZE;
+               System.arraycopy(ourExponential, 0,signData, offset, 
ourExponential.length);
+               offset += ourExponential.length;
+                System.arraycopy(hisExponential, 0,signData, offset, 
hisExponential.length);
+               offset += hisExponential.length;
+               DSASignature signatureToCheck = new DSASignature(new 
String(encryptedData));
+               if(!DSA.verify(pn.peerPubKey, signatureToCheck, new 
NativeBigInteger(1,signData), false)) {
+                       Logger.error(this, "The signature verification has 
failed!!");
+                       return;
+               }
+                sendMessage4Packet(1, 2, 3, nonceInitiator, 
nonceResponder,ourExponential, hisExponential, remoteHashedAuthenticator, pn, 
replyTo);
+               long t2=System.currentTimeMillis();
+               if((t2-t1)>500)
+                       Logger.error(this,"Message1 timeout error:Sending 
packet for"+pn.getPeer());
        }

        /*
@@ -823,7 +821,7 @@
                count += s.length;
                pk.blockEncipher(message4, 0, message4.length);
                //Send params:Version,negType,phase,data,peernode,peer 
-               sendMessage4Packet(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());
@@ -863,9 +861,57 @@

                DiffieHellmanLightContext dhContext = 
getLightDiffieHellmanContext();
                byte[] ourExponential = dhContext.myExponential.toByteArray();
-               
-               byte[] output = new byte[nonceInitiator.length+3];
-               if((nonceInitiator.length+3) > sock.getMaxPacketSize())
+               byte[] unVerifiedData=new 
byte[NONCE_SIZE*2+DiffieHellman.modulusLengthInBytes()*2];
+               int offset = 0;
+               System.arraycopy(nonceInitiator, 0, unVerifiedData, offset, 
NONCE_SIZE);
+               offset += NONCE_SIZE;
+               System.arraycopy(nonceResponder, 0, unVerifiedData, offset, 
NONCE_SIZE);
+               offset += NONCE_SIZE;
+               System.arraycopy(ourExponential, 0,unVerifiedData, offset, 
ourExponential.length);
+               offset += ourExponential.length;
+                System.arraycopy(hisExponential, 0,unVerifiedData, offset, 
hisExponential.length);
+               offset += hisExponential.length;
+               /*
+                * Digital Signature of the message with the private key 
belonging to the initiator/responder
+                * It is assumed to be non-message recovering
+                */
+               //FIXME: is this the correct way of generating Signatures?
+                //FIXME: IDr not signed?
+                byte[] signature;
+               try {
+                       signature = 
dhContext.signature.toString().getBytes("UTF-8");
+               } catch (UnsupportedEncodingException e) {
+                       Logger.error(this, "HUH ??, please report it :"+ 
e.getMessage(),e);
+                       return;
+               }
+               BlockCipher c=pn.outgoingSetupCipher;
+               if(logMINOR)
+                       
Logger.minor(this,"Cipher"+HexUtil.bytesToHex(pn.outgoingSetupKey));
+               /*
+                * Initializes the cipher context with the given key
+                * This would avoid the computation of key using the Rijndael 
key schedule(S boxes,Rcon etc)
+                * The key used is generated from Hash of Message:(Ni, Nr, 1) 
over the shared key of DH
+                */
+               
c.initialize(encryptionKey.getEncKey(sharedSecretKey(pn),nonceInitiator,nonceResponder));
+               PCFBMode pk=PCFBMode.create(c);
+               byte[] iv=new byte[pk.lengthIV()];
+               int encryptedDataLength = iv.length + signature.length + 2;
+               /*
+                * Data sent in the clear is signed and encrypted using PCFB 
and rijndael
+                */
+               byte[] encryptedData = new byte[encryptedDataLength];
+               System.arraycopy(iv, 0, encryptedData, 0, iv.length);
+               int count = iv.length;
+               encryptedData[count++] = (byte) signature.length;
+               System.arraycopy(signature, 0, encryptedData, count, 
signature.length);
+               count += signature.length;
+               pk.blockEncipher(encryptedData, 0, encryptedData.length);
+               byte[] message3=new 
byte[unVerifiedData.length+hashedAuthenticator.length+encryptedData.length];
+               
System.arraycopy(unVerifiedData,0,message3,0,unVerifiedData.length);
+               
System.arraycopy(hashedAuthenticator,0,message3,encryptedData.length,hashedAuthenticator.length);
+               
System.arraycopy(encryptedData,0,message3,unVerifiedData.length+hashedAuthenticator.length,encryptedData.length);
+               byte[] output = new byte[message3.length+3];
+               if((message3.length+3) > sock.getMaxPacketSize())
                        throw new IllegalStateException("Packet length too 
long");
                /*
                 * The key for looking up messages in the cache is the 
authenticator
@@ -882,12 +928,12 @@
                        }
                        if(result != null) {
                                synchronized(message3Cache) {
-                                       
message3Cache.put(hashedAuthenticator,nonceInitiator);
+                                       
message3Cache.put(message3,hashedAuthenticator);
                                }
                                // We don't want to keep the lock while sending
                                try
                                {
-                                       
sendMessage4Packet(1,2,3,getBytes(message4Cache.get(hashedAuthenticator)),pn,replyTo);
+                                       
sendAuthPacket(1,2,3,getBytes(message4Cache.get(hashedAuthenticator)),pn,replyTo);
                                }
                                catch(IOException e){
                                        Logger.error(this,"Error getting 
bytes");
@@ -895,9 +941,7 @@
                        }
                        sendAuthPacket(version, negType, 4, null, pn, replyTo);
                }
-               else if(phase==3){
-                       
message4Cache.put(hashedAuthenticator,nonceInitiator.toString());
-               }
+               
                else{ 
                        Logger.error(this,"Wrong message");

@@ -905,7 +949,7 @@
                output[0] = (byte) version;
                output[1] = (byte) negType;
                output[2] = (byte) phase;
-               System.arraycopy(nonceInitiator, 0, output, 3, 
nonceInitiator.length);
+               System.arraycopy(message3, 0, output, 3, message3.length);
                if(logMINOR) Logger.minor(this, "Sending auth packet for 
"+pn.getPeer()+" (phase="+phase+", ver="+version+", nt="+negType+") (last 
packet sent "+TimeUtil.formatTime(delta, 2, true)+" ago) to "+replyTo+" 
data.length="+nonceInitiator.length);
                try
                {
@@ -926,7 +970,7 @@
         * @param The peer to which we need to send the packet
         */

-       private void sendMessage4Packet(int version,int negType,int 
phase,byte[] data,PeerNode pn,Peer replyTo)
+       private void sendMessage4Packet(int version,int negType,int 
phase,byte[] data,byte[] nonceInitiator,byte[] nonceResponder,byte[] 
ourExponential,byte[] hisExponential,PeerNode pn,Peer replyTo)
        {
                if(logMINOR) Logger.minor(this, "Sending a JFK(4) message to 
"+pn);
                long now = System.currentTimeMillis();


Reply via email to