Fix a horrible BN bug in bn_expand2 which caused BN_add_word() et al to fail
authorDr. Stephen Henson <steve@openssl.org>
Thu, 15 Apr 1999 23:07:00 +0000 (23:07 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 15 Apr 1999 23:07:00 +0000 (23:07 +0000)
when they cause the destination to expand.

To see how evil this is try this:

#include <pem.h>
main()
{
BIGNUM *bn = NULL;
        int i;
bn = BN_new();
BN_hex2bn(&bn, "FFFFFFFF");
BN_add_word(bn, 1);
printf("Value %s\n", BN_bn2hex(bn));
}

This would typically fail before the patch.

It also screws up if you comment out the BN_hex2bn line above or in any
situation where BN_add_word() causes the number of BN_ULONGs in the result
to change (try doubling the number of FFs).

CHANGES
crypto/bn/bn_lib.c

diff --git a/CHANGES b/CHANGES
index 5c4fe66..ec06cde 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -5,6 +5,10 @@
 
  Changes between 0.9.2b and 0.9.3
 
+  *) Fix an evil bug in bn_expand2() which caused various BN functions to
+     fail when they extended the size of a BIGNUM.
+     [Steve Henson]
+
   *) Various utility functions to handle SXNet extension. Modify mkdef.pl to
      support typesafe stack.
      [Steve Henson]
index 994764c..5e3f3ed 100644 (file)
@@ -376,8 +376,12 @@ int words;
 memset(A,0x5c,sizeof(BN_ULONG)*(words+1));
 #if 1
                B=b->d;
+               /* Check if the previous number needs to be copied */
                if (B != NULL)
                        {
+                       /* This lot is an unrolled loop to copy b->top 
+                        * BN_ULONGs from B to A
+                        */
                        for (i=b->top&(~7); i>0; i-=8)
                                {
                                A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3];
@@ -414,30 +418,35 @@ memset(A,0x5c,sizeof(BN_ULONG)*(words+1));
                                 */
                                ;
                                }
-                       B= &(b->d[b->top]);
-                       j=b->max-8;
-                       for (i=b->top; i<j; i+=8)
-                               {
-                               B[0]=0; B[1]=0; B[2]=0; B[3]=0;
-                               B[4]=0; B[5]=0; B[6]=0; B[7]=0;
-                               B+=8;
-                               }
-                       for (j+=8; i<j; i++)
-                               {
-                               B[0]=0;
-                               B++;
-                               }
+                       Free(b->d);
+                       }
+
+               b->d=a;
+               b->max=words;
+
+               /* Now need to zero any data between b->top and b->max */
+
+               B= &(b->d[b->top]);
+               j=(b->max - b->top) & ~7;
+               for (i=0; i<j; i+=8)
+                       {
+                       B[0]=0; B[1]=0; B[2]=0; B[3]=0;
+                       B[4]=0; B[5]=0; B[6]=0; B[7]=0;
+                       B+=8;
+                       }
+               j=(b->max - b->top) & 7;
+               for (i=0; i<j; i++)
+                       {
+                       B[0]=0;
+                       B++;
+                       }
 #else
                        memcpy(a->d,b->d,sizeof(b->d[0])*b->top);
 #endif
                
 /*             memset(&(p[b->max]),0,((words+1)-b->max)*sizeof(BN_ULONG)); */
 /*     { int i; for (i=b->max; i<words+1; i++) p[i]=i;} */
-                       Free(b->d);
-                       }
 
-               b->d=a;
-               b->max=words;
                }
        return(b);
        }