1 /* crypto/bn/bn_shift.c */
   2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
   3  * All rights reserved.
   4  *
   5  * This package is an SSL implementation written
   6  * by Eric Young (eay@cryptsoft.com).
   7  * The implementation was written so as to conform with Netscapes SSL.
   8  *
   9  * This library is free for commercial and non-commercial use as long as
  10  * the following conditions are aheared to.  The following conditions
  11  * apply to all code found in this distribution, be it the RC4, RSA,
  12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  13  * included with this distribution is covered by the same copyright terms
  14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  15  *
  16  * Copyright remains Eric Young's, and as such any Copyright notices in
  17  * the code are not to be removed.
  18  * If this package is used in a product, Eric Young should be given attribution
  19  * as the author of the parts of the library used.
  20  * This can be in the form of a textual message at program startup or
  21  * in documentation (online or textual) provided with the package.
  22  *
  23  * Redistribution and use in source and binary forms, with or without
  24  * modification, are permitted provided that the following conditions
  25  * are met:
  26  * 1. Redistributions of source code must retain the copyright
  27  *    notice, this list of conditions and the following disclaimer.
  28  * 2. Redistributions in binary form must reproduce the above copyright
  29  *    notice, this list of conditions and the following disclaimer in the
  30  *    documentation and/or other materials provided with the distribution.
  31  * 3. All advertising materials mentioning features or use of this software
  32  *    must display the following acknowledgement:
  33  *    "This product includes cryptographic software written by
  34  *     Eric Young (eay@cryptsoft.com)"
  35  *    The word 'cryptographic' can be left out if the rouines from the library
  36  *    being used are not cryptographic related :-).
  37  * 4. If you include any Windows specific code (or a derivative thereof) from
  38  *    the apps directory (application code) you must include an acknowledgement:
  39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  40  *
  41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51  * SUCH DAMAGE.
  52  *
  53  * The licence and distribution terms for any publically available version or
  54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  55  * copied and put under another distribution licence
  56  * [including the GNU Public Licence.]
  57  */
  58 
  59 #include <stdio.h>
  60 #include "cryptlib.h"
  61 #include "bn_lcl.h"
  62 
  63 int BN_lshift1(BIGNUM *r, const BIGNUM *a)
  64         {
  65         register BN_ULONG *ap,*rp,t,c;
  66         int i;
  67 
  68         bn_check_top(r);
  69         bn_check_top(a);
  70 
  71         if (r != a)
  72                 {
  73                 r->neg=a->neg;
  74                 if (bn_wexpand(r,a->top+1) == NULL) return(0);
  75                 r->top=a->top;
  76                 }
  77         else
  78                 {
  79                 if (bn_wexpand(r,a->top+1) == NULL) return(0);
  80                 }
  81         ap=a->d;
  82         rp=r->d;
  83         c=0;
  84         for (i=0; i<a->top; i++)
  85                 {
  86                 t= *(ap++);
  87                 *(rp++)=((t<<1)|c)&BN_MASK2;
  88                 c=(t & BN_TBIT)?1:0;
  89                 }
  90         if (c)
  91                 {
  92                 *rp=1;
  93                 r->top++;
  94                 }
  95         bn_check_top(r);
  96         return(1);
  97         }
  98 
  99 int BN_rshift1(BIGNUM *r, const BIGNUM *a)
 100         {
 101         BN_ULONG *ap,*rp,t,c;
 102         int i,j;
 103 
 104         bn_check_top(r);
 105         bn_check_top(a);
 106 
 107         if (BN_is_zero(a))
 108                 {
 109                 BN_zero(r);
 110                 return(1);
 111                 }
 112         i = a->top;
 113         ap= a->d;
 114         j = i-(ap[i-1]==1);
 115         if (a != r)
 116                 {
 117                 if (bn_wexpand(r,j) == NULL) return(0);
 118                 r->neg=a->neg;
 119                 }
 120         rp=r->d;
 121         t=ap[--i];
 122         c=(t&1)?BN_TBIT:0;
 123         if (t>>=1) rp[i]=t;
 124         while (i>0)
 125                 {
 126                 t=ap[--i];
 127                 rp[i]=((t>>1)&BN_MASK2)|c;
 128                 c=(t&1)?BN_TBIT:0;
 129                 }
 130         r->top=j;
 131         bn_check_top(r);
 132         return(1);
 133         }
 134 
 135 int BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
 136         {
 137         int i,nw,lb,rb;
 138         BN_ULONG *t,*f;
 139         BN_ULONG l;
 140 
 141         bn_check_top(r);
 142         bn_check_top(a);
 143 
 144         r->neg=a->neg;
 145         nw=n/BN_BITS2;
 146         if (bn_wexpand(r,a->top+nw+1) == NULL) return(0);
 147         lb=n%BN_BITS2;
 148         rb=BN_BITS2-lb;
 149         f=a->d;
 150         t=r->d;
 151         t[a->top+nw]=0;
 152         if (lb == 0)
 153                 for (i=a->top-1; i>=0; i--)
 154                         t[nw+i]=f[i];
 155         else
 156                 for (i=a->top-1; i>=0; i--)
 157                         {
 158                         l=f[i];
 159                         t[nw+i+1]|=(l>>rb)&BN_MASK2;
 160                         t[nw+i]=(l<<lb)&BN_MASK2;
 161                         }
 162         memset(t,0,nw*sizeof(t[0]));
 163 /*      for (i=0; i<nw; i++)
 164                 t[i]=0;*/
 165         r->top=a->top+nw+1;
 166         bn_correct_top(r);
 167         bn_check_top(r);
 168         return(1);
 169         }
 170 
 171 int BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
 172         {
 173         int i,j,nw,lb,rb;
 174         BN_ULONG *t,*f;
 175         BN_ULONG l,tmp;
 176 
 177         bn_check_top(r);
 178         bn_check_top(a);
 179 
 180         nw=n/BN_BITS2;
 181         rb=n%BN_BITS2;
 182         lb=BN_BITS2-rb;
 183         if (nw >= a->top || a->top == 0)
 184                 {
 185                 BN_zero(r);
 186                 return(1);
 187                 }
 188         i = (BN_num_bits(a)-n+(BN_BITS2-1))/BN_BITS2;
 189         if (r != a)
 190                 {
 191                 r->neg=a->neg;
 192                 if (bn_wexpand(r,i) == NULL) return(0);
 193                 }
 194         else
 195                 {
 196                 if (n == 0)
 197                         return 1; /* or the copying loop will go berserk */
 198                 }
 199 
 200         f= &(a->d[nw]);
 201         t=r->d;
 202         j=a->top-nw;
 203         r->top=i;
 204 
 205         if (rb == 0)
 206                 {
 207                 for (i=j; i != 0; i--)
 208                         *(t++)= *(f++);
 209                 }
 210         else
 211                 {
 212                 l= *(f++);
 213                 for (i=j-1; i != 0; i--)
 214                         {
 215                         tmp =(l>>rb)&BN_MASK2;
 216                         l= *(f++);
 217                         *(t++) =(tmp|(l<<lb))&BN_MASK2;
 218                         }
 219                 if ((l = (l>>rb)&BN_MASK2)) *(t) = l;
 220                 }
 221         bn_check_top(r);
 222         return(1);
 223         }