See ChangeLog: Mon May 31 19:41:10 CEST 1999 Werner Koch
[gnupg.git] / mpi / mpi-div.c
index 2955575..6e50456 100644 (file)
@@ -1,14 +1,15 @@
 /* mpi-div.c  -  MPI functions
- *     Copyright (c) 1997 by Werner Koch (dd9jn)
+ *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
  *
- * This file is part of G10.
+ * This file is part of GnuPG.
  *
- * G10 is free software; you can redistribute it and/or modify
+ * 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.
  *
- * G10 is distributed in the hope that it will be useful,
+ * GnuPG 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.
  * You should have received a copy of the GNU 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
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
  */
 
 #include <config.h>
@@ -137,8 +146,7 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
      * We need space for an extra limb in the remainder, because it's
      * up-shifted (normalized) below.  */
     rsize = nsize + 1;
-    if( rem->alloced < rsize )
-       mpi_resize( rem, rsize);
+    mpi_resize( rem, rsize);
 
     qsize = rsize - dsize;       /* qsize cannot be bigger than this.  */
     if( qsize <= 0 ) {
@@ -156,7 +164,7 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        return;
     }
 
-    if( quot && quot->alloced < qsize )
+    if( quot )
        mpi_resize( quot, qsize);
 
     /* Read pointers here, when reallocation is finished.  */
@@ -189,7 +197,8 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        /* Make sure QP and NP point to different objects.  Otherwise the
         * numerator would be gradually overwritten by the quotient limbs.  */
        if(qp == np) { /* Copy NP object to temporary space.  */
-           np = marker[markidx++] = mpi_alloc_limb_space(nsize);
+           np = marker[markidx++] = mpi_alloc_limb_space(nsize,
+                                                         mpi_is_secure(quot));
            MPN_COPY(np, qp, nsize);
        }
     }
@@ -209,7 +218,7 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        /* Shift up the denominator setting the most significant bit of
         * the most significant word.  Use temporary storage not to clobber
         * the original contents of the denominator.  */
-       tp = marker[markidx++] = mpi_alloc_limb_space(dsize);
+       tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
        mpihelp_lshift( tp, dp, dsize, normalization_steps );
        dp = tp;
 
@@ -230,7 +239,7 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        if( dp == rp || (quot && (dp == qp))) {
            mpi_ptr_t tp;
 
-           tp = marker[markidx++] = mpi_alloc_limb_space(dsize);
+           tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den));
            MPN_COPY( tp, dp, dsize );
            dp = tp;
        }
@@ -269,9 +278,40 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        mpi_free_limb_space(marker[--markidx]);
 }
 
+void
+mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count )
+{
+    mpi_size_t usize, wsize;
+    mpi_size_t limb_cnt;
+
+    usize = u->nlimbs;
+    limb_cnt = count / BITS_PER_MPI_LIMB;
+    wsize = usize - limb_cnt;
+    if( limb_cnt >= usize )
+       w->nlimbs = 0;
+    else {
+       mpi_ptr_t wp;
+       mpi_ptr_t up;
+
+       RESIZE_IF_NEEDED( w, wsize );
+       wp = w->d;
+       up = u->d;
+
+       count %= BITS_PER_MPI_LIMB;
+       if( count ) {
+           mpihelp_rshift( wp, up + limb_cnt, wsize, count );
+           wsize -= !wp[wsize - 1];
+       }
+       else {
+           MPN_COPY_INCR( wp, up + limb_cnt, wsize);
+       }
+
+       w->nlimbs = wsize;
+    }
+}
 
 /****************
- * Check wether dividend is divisible by divisor
+ * Check whether dividend is divisible by divisor
  * (note: divisor must fit into a limb)
  */
 int