(please excuse me if this is a duplicate)

Toad,

Recently a message by you was xposted to 0.5 about a crypto weakness you folks 
discovered in 0.7 that 0.5 is also subject to.

After some discussion, one individual came up with a patch and procedure for 
fixing this on 0.5. While a lot will simply use that patch and build new 
freenet.jar executables, there are some who aren't up to it for whatever reason.

Given the patch and the msg announcing it, would you be willing to create an 
'official' freenet 0.5 build 5108 and make it available at the same place where 
the old 0.5 stuff is at http://downloads.freenetproject.org/ ?

BTW- I know you and other freenet devs haven't been in the habit of doing so 
but would you also be willing to include a digital signature of some kind?  At 
least an SHA-1 hash, preferably a detached pgp signature.

Thanks

Here's the message I mentioned, followed by the patch:


----- Jack O'Lantern ----- 2007.10.31 - 20:36:40GMT -----

Happy Hallowe'en folks,

a certain Toad recently informed us that the Diffie-Hellman key exchange in 
freenet 0.5 has been b0rked for about two years and we please bob for the 
solution to the issue ourselves. So, here goes...

1. obtain a JDK (sun5 works), svn, ant and junit.

2. obtain the source:
   $ svn co http://freenet.googlecode.com/svn/branches/legacy/stable/ 
freenet-0.5-5108
   $ cd freenet-0.5-5108
   $ svn co http://freenet.googlecode.com/svn/branches/legacy/contrib/ contrib

3. copy freenet-ext.jar from your freenet directory into the newly created 
freenet-0.5-5108 directory (freenet-ext.jar remains unchanged)

4. obtain the patch I crafted:
   freenet:CHK at 
Sm50039W8Gt8kzLyMloGB6pvjkQNAwI,xYB4spgd2g1ZtJIYN0lfeg/freenet_dh.patch

5. Examine this patch closely. You don't know me. You never know beforehand if 
you're about to be tricked or treated, or handled by an incompetent person.
   This patch does the following things:
   a. creates a method to check for weak Diffie-Hellman exponents (imported 
from freenet 0.7)
   b. there are *extremely* few weak exponentials in the number space, so 
accidental creation of a weak exponential is *extremely* unlikely; 
nevertheless, the patch adds code to prevent creating weak exponents (imported 
from freenet 0.7)
   c. adds code to abort a Diffie-Hellman key exchange if our peer ("Bob") uses 
a weak key (logs an error) (two instances)
   d. bumps the build number up to 5108. I feel it's justified that we users 
hijack the build numbering scheme as the developers don't maintain it anymore.

6. If you're satisfied, copy this patch into the freenet-0.5-5108 directory.

7. Apply the patch:
   $ patch -p1 < freenet_dh.patch

8. Build freenet.jar
   $ CLASSPATH=freenet-ext.jar ant distclean dist

9. Make a backup of your old freenet.jar (freenet-ext.jar remains in place).

10. Copy the newly built freenet.jar to your freenet directory.
    $ cp lib/freenet.jar /path/to/freenet/dir

11. Restart freenet

That's it. Enjoy your shiny new freenet build.

It would be great if someone in contact with the freenet 0.7 developers could 
communicate the patch to them. I'm just a user, and some official 
acknowledgement that the patch does indeed fix *all* instances of weak 
Diffie-Hellman handling is appreciated because, you know, the comments in the 
freenet source are not exactly abundant and it's not easy for a newcomer to 
find one's way through.

EOM

Here's the patch:
diff -Naur freenet-0.5-5107/build.xml freenet-0.5-5108/build.xml
--- freenet-0.5-5107/build.xml  2007-10-31 18:12:46.000000000 +0100
+++ freenet-0.5-5108/build.xml  2007-10-31 18:22:13.000000000 +0100
@@ -22,8 +22,8 @@
        <property name="freenet-ext.location" 
location="${lib}/freenet-ext.jar"/>
        <!-- this is where the Contrib directory is supposed to be. Override 
this
        if necessary -->
-       <property name="contrib.location" location=".."/>
-       <property name="servlet.location" 
location="${contrib.location}/Contrib/freenet_ext/build_dir"/>
+       <property name="contrib.location" location="."/>
+       <property name="servlet.location" 
location="${contrib.location}/contrib/freenet_ext/build_dir"/>

 <!-- ======================================================================= 
-->
     <target name="env"
diff -Naur freenet-0.5-5107/src/freenet/crypt/DiffieHellman.java 
freenet-0.5-5108/src/freenet/crypt/DiffieHellman.java
--- freenet-0.5-5107/src/freenet/crypt/DiffieHellman.java       2007-10-31 
18:08:57.000000000 +0100
+++ freenet-0.5-5108/src/freenet/crypt/DiffieHellman.java       2007-10-31 
18:21:34.000000000 +0100
@@ -11,6 +11,7 @@
 import java.util.Stack;

 import freenet.Core;
+import freenet.support.Logger;

 public class DiffieHellman {

@@ -37,6 +38,9 @@

        private static Thread precalcThread;

+       public static final BigInteger MIN_EXPONENTIAL_VALUE = new 
BigInteger("2").pow(24);
+       public static final BigInteger MAX_EXPONENTIAL_VALUE = 
group.getP().subtract(MIN_EXPONENTIAL_VALUE);
+
        static {
                precalcThread = new PrecalcBufferFill();
                precalcThread.start();
@@ -132,11 +136,53 @@
        private static BigInteger[] genParams() {
                BigInteger params[] = new BigInteger[2];
                // Don't need NativeBigInteger?
-               params[0] = new BigInteger(256, r);
-               params[1] = group.getG().modPow(params[0], group.getP());
+               
+               do {
+                       params[0] = new BigInteger(256, r);
+                       params[1] = group.getG().modPow(params[0], 
group.getP());
+               } 
while(!DiffieHellman.checkDHExponentialValidity(DiffieHellman.class, 
params[1]));
+
                return params;
        }

+       /**
+        * Check the validity of a DH exponential
+        *
+        * @param a BigInteger: The exponential to test
+        * @return a boolean: whether the DH exponential provided is acceptable 
or not
+        *
+        * @see http://securitytracker.com/alerts/2005/Aug/1014739.html
+        * @see http://www.it.iitb.ac.in/~praj/acads/netsec/FinalReport.pdf
+        */
+       public static boolean checkDHExponentialValidity(Class caller, 
BigInteger exponential) {
+               int onesCount=0, zerosCount=0;
+
+               // Ensure that we have at least 16 bits of each gender
+               for(int i=0; i < exponential.bitLength(); i++)
+                       if(exponential.testBit(i))
+                               onesCount++;
+                       else
+                               zerosCount++;
+               if((onesCount<16) || (zerosCount<16)) {
+                       Core.logger.log(caller, "The provided exponential 
contains "+zerosCount+" zeros and "+onesCount+" ones wich is unacceptable!", 
Logger.ERROR);
+                       return false;
+               }
+
+               // Ensure that g^x > 2^24
+               if(MIN_EXPONENTIAL_VALUE.compareTo(exponential) > -1) {
+                       Core.logger.log(caller, "The provided exponential is 
smaller than 2^24 which is unacceptable!", Logger.ERROR);
+                       return false;
+               }
+               // Ensure that g^x < (p-2^24)
+               if(MAX_EXPONENTIAL_VALUE.compareTo(exponential) < 1) {
+                       Core.logger.log(caller, "The provided exponential is 
bigger than (p - 2^24) which is unacceptable!", Logger.ERROR);
+                       return false;
+               }
+
+               return true;
+
+       }
+
        public static DHGroup getGroup() {
                return group;
        }
diff -Naur freenet-0.5-5107/src/freenet/session/FnpLink.java 
freenet-0.5-5108/src/freenet/session/FnpLink.java
--- freenet-0.5-5107/src/freenet/session/FnpLink.java   2007-10-31 
18:05:39.000000000 +0100
+++ freenet-0.5-5108/src/freenet/session/FnpLink.java   2007-10-31 
18:21:53.000000000 +0100
@@ -498,6 +498,11 @@
         }
         Ca = Util.readMPI(rawIn);

+       if(!DiffieHellman.checkDHExponentialValidity(this.getClass(), Ca)) {
+               String err = "Cannot accept remote exponential. WARNING: WITH 
HIGH PROBABILITY, THIS WAS A DELIBERATE ATTACK!";
+               throw new NegotiationFailedException(conn.getPeerAddress(), 
err);
+       }
+
         Z = Ca.modPow(R, DiffieHellman.getGroup().getP());
         byte[] kent = Util.MPIbytes(Z);
         Util.makeKey(kent, k, 0, k.length);
@@ -646,6 +651,12 @@
         }

         Cb = Util.readMPI(rawIn);
+
+       if(!DiffieHellman.checkDHExponentialValidity(this.getClass(), Cb)) {
+               String err = "Cannot accept remote exponential. WARNING: WITH 
HIGH PROBABILITY, THIS WAS A DELIBERATE ATTACK!";
+               throw new NegotiationFailedException(conn.getPeerAddress(), 
err);
+       }
+
         long readMPITime = System.currentTimeMillis();
         long readmpilen = readMPITime - readByteTime;
         if (logDEBUG || readmpilen > 500)
diff -Naur freenet-0.5-5107/src/freenet/Version.java 
freenet-0.5-5108/src/freenet/Version.java
--- freenet-0.5-5107/src/freenet/Version.java   2007-10-31 18:12:35.000000000 
+0100
+++ freenet-0.5-5108/src/freenet/Version.java   2007-10-31 18:21:24.000000000 
+0100
@@ -20,7 +20,7 @@
        public static String protocolVersion = "STABLE-1.51";

        /** The build number of the current revision */
-       public static final int buildNumber = 5107;
+       public static final int buildNumber = 5108;

        /** Oldest build of Fred we will talk to */
        public static final int lastGoodBuild = 5099;

Reply via email to