build: Update config.{guess,sub} to {2016-05-15,2016-06-20}.
[libgcrypt.git] / mpi / mpi-bit.c
index d74abbf..e217040 100644 (file)
@@ -1,27 +1,27 @@
-/* mpi-bit.c  -  MPI bit level fucntions
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+/* mpi-bit.c  -  MPI bit level functions
+ * Copyright (C) 1998, 1999, 2001, 2002, 2006 Free Software Foundation, Inc.
+ * Copyright (C) 2013  g10 Code GmbH
  *
- * This file is part of GNUPG.
+ * This file is part of Libgcrypt.
  *
- * GNUPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
  *
- * GNUPG is distributed in the hope that it will be useful,
+ * Libgcrypt is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include "mpi-internal.h"
 #include "longlong.h"
 
@@ -31,7 +31,7 @@
 const
 #endif
 unsigned char
-__clz_tab[] =
+_gcry_clz_tab[] =
 {
   0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
@@ -48,18 +48,35 @@ __clz_tab[] =
 #define A_LIMB_1 ((mpi_limb_t)1)
 
 
+/****************
+ * Sometimes we have MSL (most significant limbs) which are 0;
+ * this is for some reasons not good, so this function removes them.
+ */
+void
+_gcry_mpi_normalize( gcry_mpi_t a )
+{
+    if( mpi_is_opaque(a) )
+       return;
 
+    for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- )
+       ;
+}
 
 
 
 /****************
  * Return the number of bits in A.
  */
-unsigned
-mpi_get_nbits( MPI a )
+unsigned int
+_gcry_mpi_get_nbits (gcry_mpi_t a)
 {
     unsigned n;
 
+    if( mpi_is_opaque(a) ) {
+       return a->sign; /* which holds the number of bits */
+    }
+
+    _gcry_mpi_normalize( a );
     if( a->nlimbs ) {
        mpi_limb_t alimb = a->d[a->nlimbs-1];
        if( alimb )
@@ -78,9 +95,9 @@ mpi_get_nbits( MPI a )
  * Test whether bit N is set.
  */
 int
-mpi_test_bit( MPI a, unsigned n )
+_gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n )
 {
-    unsigned limbno, bitno;
+    unsigned int limbno, bitno;
     mpi_limb_t limb;
 
     limbno = n / BITS_PER_MPI_LIMB;
@@ -97,148 +114,298 @@ mpi_test_bit( MPI a, unsigned n )
  * Set bit N of A.
  */
 void
-mpi_set_bit( MPI a, unsigned n )
+_gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n )
 {
-    unsigned limbno, bitno;
+  unsigned int i, limbno, bitno;
 
-    limbno = n / BITS_PER_MPI_LIMB;
-    bitno  = n % BITS_PER_MPI_LIMB;
+  if (mpi_is_immutable (a))
+    {
+      mpi_immutable_failed ();
+      return;
+    }
 
-    if( limbno >= a->nlimbs ) { /* resize */
-       if( a->alloced >= limbno )
-           mpi_resize(a, limbno+1 );
-       a->nlimbs = limbno+1;
+  limbno = n / BITS_PER_MPI_LIMB;
+  bitno  = n % BITS_PER_MPI_LIMB;
+
+  if ( limbno >= a->nlimbs )
+    {
+      for (i=a->nlimbs; i < a->alloced; i++)
+        a->d[i] = 0;
+      mpi_resize (a, limbno+1 );
+      a->nlimbs = limbno+1;
     }
-    a->d[limbno] |= (A_LIMB_1<<bitno);
+  a->d[limbno] |= (A_LIMB_1<<bitno);
 }
 
 /****************
  * Set bit N of A. and clear all bits above
  */
 void
-mpi_set_highbit( MPI a, unsigned n )
+_gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n )
 {
-    unsigned limbno, bitno;
+  unsigned int i, limbno, bitno;
 
-    limbno = n / BITS_PER_MPI_LIMB;
-    bitno  = n % BITS_PER_MPI_LIMB;
+  if (mpi_is_immutable (a))
+    {
+      mpi_immutable_failed ();
+      return;
+    }
 
-    if( limbno >= a->nlimbs ) { /* resize */
-       if( a->alloced >= limbno )
-           mpi_resize(a, limbno+1 );
-       a->nlimbs = limbno+1;
+  limbno = n / BITS_PER_MPI_LIMB;
+  bitno  = n % BITS_PER_MPI_LIMB;
+
+  if ( limbno >= a->nlimbs )
+    {
+      for (i=a->nlimbs; i < a->alloced; i++)
+        a->d[i] = 0;
+      mpi_resize (a, limbno+1 );
+      a->nlimbs = limbno+1;
     }
-    a->d[limbno] |= (A_LIMB_1<<bitno);
-    for( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
-       a->d[limbno] &= ~(A_LIMB_1 << bitno);
-    a->nlimbs = limbno+1;
+  a->d[limbno] |= (A_LIMB_1<<bitno);
+  for ( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
+    a->d[limbno] &= ~(A_LIMB_1 << bitno);
+  a->nlimbs = limbno+1;
 }
 
 /****************
  * clear bit N of A and all bits above
  */
 void
-mpi_clear_highbit( MPI a, unsigned n )
+_gcry_mpi_clear_highbit( gcry_mpi_t a, unsigned int n )
 {
-    unsigned limbno, bitno;
+  unsigned int limbno, bitno;
 
-    limbno = n / BITS_PER_MPI_LIMB;
-    bitno  = n % BITS_PER_MPI_LIMB;
+  if (mpi_is_immutable (a))
+    {
+      mpi_immutable_failed ();
+      return;
+    }
 
-    if( limbno >= a->nlimbs )
-       return; /* not allocated, so need to clear bits :-) */
+  limbno = n / BITS_PER_MPI_LIMB;
+  bitno  = n % BITS_PER_MPI_LIMB;
 
-    for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
-       a->d[limbno] &= ~(A_LIMB_1 << bitno);
-    a->nlimbs = limbno+1;
+  if( limbno >= a->nlimbs )
+    return; /* not allocated, therefore no need to clear bits :-) */
+
+  for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
+    a->d[limbno] &= ~(A_LIMB_1 << bitno);
+  a->nlimbs = limbno+1;
 }
 
 /****************
  * Clear bit N of A.
  */
 void
-mpi_clear_bit( MPI a, unsigned n )
+_gcry_mpi_clear_bit( gcry_mpi_t a, unsigned int n )
 {
-    unsigned limbno, bitno;
+  unsigned int limbno, bitno;
 
-    limbno = n / BITS_PER_MPI_LIMB;
-    bitno  = n % BITS_PER_MPI_LIMB;
+  if (mpi_is_immutable (a))
+    {
+      mpi_immutable_failed ();
+      return;
+    }
 
-    if( limbno >= a->nlimbs )
-       return; /* don't need to clear this bit, it's to far to left */
-    a->d[limbno] &= ~(A_LIMB_1 << bitno);
+  limbno = n / BITS_PER_MPI_LIMB;
+  bitno  = n % BITS_PER_MPI_LIMB;
+
+  if (limbno >= a->nlimbs)
+    return; /* Don't need to clear this bit, it's far too left.  */
+  a->d[limbno] &= ~(A_LIMB_1 << bitno);
 }
 
 
+/****************
+ * Shift A by COUNT limbs to the right
+ * This is used only within the MPI library
+ */
 void
-mpi_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque )
+_gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count )
 {
-    byte *p;
-    unsigned nlimbs, nlimbs2, xbits, xbytes;
-    unsigned n;
-    int i;
-
-    nlimbs = nbits / BITS_PER_MPI_LIMB;
-    xbits = nbits % BITS_PER_MPI_LIMB;
-    nlimbs2 = xbits? (nlimbs+1):nlimbs;
-    xbytes = xbits / 8;
-    xbits = xbits % 8;
-    if( a->alloced < nlimbs2 )
-       mpi_resize(a, nlimbs2 );
-    a->nlimbs = nlimbs2;
-    for(n=0; n < nlimbs; n++ ) {
-       p = (byte*)(a->d+n);
-      #ifdef LITTLE_ENDIAN_HOST
-       for(i=0; i < BYTES_PER_MPI_LIMB; i++ )
-           p[i] = fnc(opaque);
-      #else
-       for(i=BYTES_PER_MPI_LIMB-1; i>=0; i-- )
-           p[i] = fnc(opaque);
-      #endif
-    }
-    if( xbytes ) {
-       p = (byte*)(a->d+n);
-      #ifdef LITTLE_ENDIAN_HOST
-       for(i=0; i < xbytes; i++ )
-           p[i] = fnc(opaque);
-      #else
-       for(i=xbytes-1; i>=0; i-- )
-           p[i] = fnc(opaque);
-      #endif
-    }
-  #if 0 /* fixme: set complete random byte and clear out the unwanted ones*/
-    if( xbits ) {
-       p = (byte*)(a->d+n);
-      #ifdef LITTLE_ENDIAN_HOST
-       for(i=0; i < xbytes; i++ )
-           p[i] = fnc(opaque);
-      #else
-       for(i=xbytes-1; i>=0; i-- )
-           p[i] = fnc(opaque);
-      #endif
-    }
-  #endif
+  mpi_ptr_t ap = a->d;
+  mpi_size_t n = a->nlimbs;
+  unsigned int i;
+
+  if (mpi_is_immutable (a))
+    {
+      mpi_immutable_failed ();
+      return;
+    }
+
+  if (count >= n)
+    {
+      a->nlimbs = 0;
+      return;
+    }
+
+  for( i = 0; i < n - count; i++ )
+    ap[i] = ap[i+count];
+  ap[i] = 0;
+  a->nlimbs -= count;
+}
+
+
+/*
+ * Shift A by N bits to the right.
+ */
+void
+_gcry_mpi_rshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
+{
+  mpi_size_t xsize;
+  unsigned int i;
+  unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
+  unsigned int nbits = (n%BITS_PER_MPI_LIMB);
+
+  if (mpi_is_immutable (x))
+    {
+      mpi_immutable_failed ();
+      return;
+    }
+
+  if ( x == a )
+    {
+      /* In-place operation.  */
+      if ( nlimbs >= x->nlimbs )
+        {
+          x->nlimbs = 0;
+          return;
+        }
+
+      if (nlimbs)
+        {
+          for (i=0; i < x->nlimbs - nlimbs; i++ )
+            x->d[i] = x->d[i+nlimbs];
+          x->d[i] = 0;
+          x->nlimbs -= nlimbs;
+
+        }
+      if ( x->nlimbs && nbits )
+        _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits );
+    }
+  else if ( nlimbs )
+    {
+      /* Copy and shift by more or equal bits than in a limb. */
+      xsize = a->nlimbs;
+      x->sign = a->sign;
+      RESIZE_IF_NEEDED (x, xsize);
+      x->nlimbs = xsize;
+      for (i=0; i < a->nlimbs; i++ )
+        x->d[i] = a->d[i];
+      x->nlimbs = i;
+
+      if ( nlimbs >= x->nlimbs )
+        {
+          x->nlimbs = 0;
+          return;
+        }
+
+      if (nlimbs)
+        {
+          for (i=0; i < x->nlimbs - nlimbs; i++ )
+            x->d[i] = x->d[i+nlimbs];
+          x->d[i] = 0;
+          x->nlimbs -= nlimbs;
+        }
+
+      if ( x->nlimbs && nbits )
+        _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits );
+    }
+  else
+    {
+      /* Copy and shift by less than bits in a limb.  */
+      xsize = a->nlimbs;
+      x->sign = a->sign;
+      RESIZE_IF_NEEDED (x, xsize);
+      x->nlimbs = xsize;
+
+      if ( xsize )
+        {
+          if (nbits )
+            _gcry_mpih_rshift (x->d, a->d, x->nlimbs, nbits );
+          else
+            {
+              /* The rshift helper function is not specified for
+                 NBITS==0, thus we do a plain copy here. */
+              for (i=0; i < x->nlimbs; i++ )
+                x->d[i] = a->d[i];
+            }
+        }
+    }
+  MPN_NORMALIZE (x->d, x->nlimbs);
 }
 
+
 /****************
- * Shift A by N bits to the right
- * FIXME: should use alloc_limb if X and A are same.
+ * Shift A by COUNT limbs to the left
+ * This is used only within the MPI library
  */
 void
-mpi_rshift( MPI x, MPI a, unsigned n )
+_gcry_mpi_lshift_limbs (gcry_mpi_t a, unsigned int count)
 {
-    mpi_ptr_t xp;
-    mpi_size_t xsize;
+  mpi_ptr_t ap;
+  int n = a->nlimbs;
+  int i;
 
-    xsize = a->nlimbs;
-    x->sign = a->sign;
-    RESIZE_IF_NEEDED(x, xsize);
-    xp = x->d;
+  if (!count || !n)
+    return;
 
-    if( xsize ) {
-       mpihelp_rshift( xp, a->d, xsize, n);
-       MPN_NORMALIZE( xp, xsize);
-    }
-    x->nlimbs = xsize;
+  RESIZE_IF_NEEDED (a, n+count);
+
+  ap = a->d;
+  for (i = n-1; i >= 0; i--)
+    ap[i+count] = ap[i];
+  for (i=0; i < count; i++ )
+    ap[i] = 0;
+  a->nlimbs += count;
 }
 
+
+/*
+ * Shift A by N bits to the left.
+ */
+void
+_gcry_mpi_lshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
+{
+  unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
+  unsigned int nbits = (n%BITS_PER_MPI_LIMB);
+
+  if (mpi_is_immutable (x))
+    {
+      mpi_immutable_failed ();
+      return;
+    }
+
+  if (x == a && !n)
+    return;  /* In-place shift with an amount of zero.  */
+
+  if ( x != a )
+    {
+      /* Copy A to X.  */
+      unsigned int alimbs = a->nlimbs;
+      int asign  = a->sign;
+      mpi_ptr_t xp, ap;
+
+      RESIZE_IF_NEEDED (x, alimbs+nlimbs+1);
+      xp = x->d;
+      ap = a->d;
+      MPN_COPY (xp, ap, alimbs);
+      x->nlimbs = alimbs;
+      x->flags = a->flags;
+      x->sign = asign;
+    }
+
+  if (nlimbs && !nbits)
+    {
+      /* Shift a full number of limbs.  */
+      _gcry_mpi_lshift_limbs (x, nlimbs);
+    }
+  else if (n)
+    {
+      /* We use a very dump approach: Shift left by the number of
+         limbs plus one and than fix it up by an rshift.  */
+      _gcry_mpi_lshift_limbs (x, nlimbs+1);
+      mpi_rshift (x, x, BITS_PER_MPI_LIMB - nbits);
+    }
+
+  MPN_NORMALIZE (x->d, x->nlimbs);
+}