Fix crash in BN_rshift.
[openssl.git] / crypto / bn / bn_shift.c
index d711887373b43566bc45d55d885c8a85f4fe1e57..c4d301afc4675b7739ede6517f3cebcde52a285a 100644 (file)
@@ -1,5 +1,5 @@
 /* crypto/bn/bn_shift.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
-int BN_lshift1(r, a)
-BIGNUM *r;
-BIGNUM *a;
+int BN_lshift1(BIGNUM *r, const BIGNUM *a)
        {
        register BN_ULONG *ap,*rp,t,c;
        int i;
 
+       bn_check_top(r);
+       bn_check_top(a);
+
        if (r != a)
                {
                r->neg=a->neg;
-               if (bn_expand(r,(a->top+1)*BN_BITS2) == NULL) return(0);
+               if (bn_wexpand(r,a->top+1) == NULL) return(0);
                r->top=a->top;
                }
        else
                {
-               if (bn_expand(r,(a->top+1)*BN_BITS2) == NULL) return(0);
+               if (bn_wexpand(r,a->top+1) == NULL) return(0);
                }
        ap=a->d;
        rp=r->d;
@@ -91,16 +92,18 @@ BIGNUM *a;
                *rp=1;
                r->top++;
                }
+       bn_check_top(r);
        return(1);
        }
 
-int BN_rshift1(r, a)
-BIGNUM *r;
-BIGNUM *a;
+int BN_rshift1(BIGNUM *r, const BIGNUM *a)
        {
        BN_ULONG *ap,*rp,t,c;
        int i;
 
+       bn_check_top(r);
+       bn_check_top(a);
+
        if (BN_is_zero(a))
                {
                BN_zero(r);
@@ -108,7 +111,7 @@ BIGNUM *a;
                }
        if (a != r)
                {
-               if (bn_expand(r,a->top*BN_BITS2) == NULL) return(0);
+               if (bn_wexpand(r,a->top) == NULL) return(0);
                r->top=a->top;
                r->neg=a->neg;
                }
@@ -121,22 +124,23 @@ BIGNUM *a;
                rp[i]=((t>>1)&BN_MASK2)|c;
                c=(t&1)?BN_TBIT:0;
                }
-       bn_fix_top(r);
+       bn_correct_top(r);
+       bn_check_top(r);
        return(1);
        }
 
-int BN_lshift(r, a, n)
-BIGNUM *r;
-BIGNUM *a;
-int n;
+int BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
        {
        int i,nw,lb,rb;
        BN_ULONG *t,*f;
        BN_ULONG l;
 
+       bn_check_top(r);
+       bn_check_top(a);
+
        r->neg=a->neg;
-       if (bn_expand(r,(a->top*BN_BITS2)+n) == NULL) return(0);
        nw=n/BN_BITS2;
+       if (bn_wexpand(r,a->top+nw+1) == NULL) return(0);
        lb=n%BN_BITS2;
        rb=BN_BITS2-lb;
        f=a->d;
@@ -156,23 +160,24 @@ int n;
 /*     for (i=0; i<nw; i++)
                t[i]=0;*/
        r->top=a->top+nw+1;
-       bn_fix_top(r);
+       bn_correct_top(r);
+       bn_check_top(r);
        return(1);
        }
 
-int BN_rshift(r, a, n)
-BIGNUM *r;
-BIGNUM *a;
-int n;
+int BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
        {
        int i,j,nw,lb,rb;
        BN_ULONG *t,*f;
        BN_ULONG l,tmp;
 
+       bn_check_top(r);
+       bn_check_top(a);
+
        nw=n/BN_BITS2;
        rb=n%BN_BITS2;
        lb=BN_BITS2-rb;
-       if (nw > a->top)
+       if (nw >= a->top || a->top == 0)
                {
                BN_zero(r);
                return(1);
@@ -180,7 +185,12 @@ int n;
        if (r != a)
                {
                r->neg=a->neg;
-               if (bn_expand(r,(a->top-nw+1)*BN_BITS2) == NULL) return(0);
+               if (bn_wexpand(r,a->top-nw+1) == NULL) return(0);
+               }
+       else
+               {
+               if (n == 0)
+                       return 1; /* or the copying loop will go berserk */
                }
 
        f= &(a->d[nw]);
@@ -190,13 +200,13 @@ int n;
 
        if (rb == 0)
                {
-               for (i=j+1; i > 0; i--)
+               for (i=j; i != 0; i--)
                        *(t++)= *(f++);
                }
        else
                {
                l= *(f++);
-               for (i=1; i<j; i++)
+               for (i=j-1; i != 0; i--)
                        {
                        tmp =(l>>rb)&BN_MASK2;
                        l= *(f++);
@@ -204,7 +214,7 @@ int n;
                        }
                *(t++) =(l>>rb)&BN_MASK2;
                }
-       *t=0;
-       bn_fix_top(r);
+       bn_correct_top(r);
+       bn_check_top(r);
        return(1);
        }