-
+ 8341923461226EC55DE5B29209CC03051587DE11885CB49433FF4C0EBA2160798B7DC27573B9BC363EE0954A8FC08CBD21AF3F655A9C0BC8AA294A74F80EB2C9
mpi/mpi-pow.c
(0 . 0)(1 . 294)
9674 /* mpi-pow.c - MPI functions
9675 * Copyright (C) 1994, 1996, 1998, 2000 Free Software Foundation, Inc.
9676 *
9677 * This file is part of GnuPG.
9678 *
9679 * GnuPG is free software; you can redistribute it and/or modify
9680 * it under the terms of the GNU General Public License as published by
9681 * the Free Software Foundation; either version 3 of the License, or
9682 * (at your option) any later version.
9683 *
9684 * GnuPG is distributed in the hope that it will be useful,
9685 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9686 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9687 * GNU General Public License for more details.
9688 *
9689 * You should have received a copy of the GNU General Public License
9690 * along with this program; if not, see <http://www.gnu.org/licenses/>.
9691 *
9692 * Note: This code is heavily based on the GNU MP Library.
9693 * Actually it's the same code with only minor changes in the
9694 * way the data is stored; this is to support the abstraction
9695 * of an optional secure memory allocation which may be used
9696 * to avoid revealing of sensitive data due to paging etc.
9697 * The GNU MP Library itself is published under the LGPL;
9698 * however I decided to publish this code under the plain GPL.
9699 */
9700
9701 #include <config.h>
9702 #include <stdio.h>
9703 #include <stdlib.h>
9704 #include <string.h>
9705 #include "mpi-internal.h"
9706 #include "longlong.h"
9707 #include <assert.h>
9708
9709
9710 /****************
9711 * RES = BASE ^ EXP mod MOD
9712 */
9713 void
9714 mpi_powm( MPI res, MPI base, MPI exponent, MPI mod)
9715 {
9716 mpi_ptr_t rp, ep, mp, bp;
9717 mpi_size_t esize, msize, bsize, rsize;
9718 int esign, msign, bsign, rsign;
9719 int esec, msec, bsec, rsec;
9720 mpi_size_t size;
9721 int mod_shift_cnt;
9722 int negative_result;
9723 mpi_ptr_t mp_marker=NULL, bp_marker=NULL, ep_marker=NULL;
9724 mpi_ptr_t xp_marker=NULL;
9725 int assign_rp=0;
9726 mpi_ptr_t tspace = NULL;
9727 mpi_size_t tsize=0; /* to avoid compiler warning */
9728 /* fixme: we should check that the warning is void*/
9729
9730 esize = exponent->nlimbs;
9731 msize = mod->nlimbs;
9732 size = 2 * msize;
9733 esign = exponent->sign;
9734 msign = mod->sign;
9735
9736 esec = mpi_is_secure(exponent);
9737 msec = mpi_is_secure(mod);
9738 bsec = mpi_is_secure(base);
9739 rsec = mpi_is_secure(res);
9740
9741 rp = res->d;
9742 ep = exponent->d;
9743
9744 if( !msize )
9745 msize = 1 / msize; /* provoke a signal */
9746
9747 if( !esize ) {
9748 /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
9749 * depending on if MOD equals 1. */
9750 rp[0] = 1;
9751 res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
9752 res->sign = 0;
9753 goto leave;
9754 }
9755
9756 /* Normalize MOD (i.e. make its most significant bit set) as required by
9757 * mpn_divrem. This will make the intermediate values in the calculation
9758 * slightly larger, but the correct result is obtained after a final
9759 * reduction using the original MOD value. */
9760 mp = mp_marker = mpi_alloc_limb_space(msize, msec);
9761 count_leading_zeros( mod_shift_cnt, mod->d[msize-1] );
9762 if( mod_shift_cnt )
9763 mpihelp_lshift( mp, mod->d, msize, mod_shift_cnt );
9764 else
9765 MPN_COPY( mp, mod->d, msize );
9766
9767 bsize = base->nlimbs;
9768 bsign = base->sign;
9769 if( bsize > msize ) { /* The base is larger than the module. Reduce it. */
9770 /* Allocate (BSIZE + 1) with space for remainder and quotient.
9771 * (The quotient is (bsize - msize + 1) limbs.) */
9772 bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec );
9773 MPN_COPY( bp, base->d, bsize );
9774 /* We don't care about the quotient, store it above the remainder,
9775 * at BP + MSIZE. */
9776 mpihelp_divrem( bp + msize, 0, bp, bsize, mp, msize );
9777 bsize = msize;
9778 /* Canonicalize the base, since we are going to multiply with it
9779 * quite a few times. */
9780 MPN_NORMALIZE( bp, bsize );
9781 }
9782 else
9783 bp = base->d;
9784
9785 if( !bsize ) {
9786 res->nlimbs = 0;
9787 res->sign = 0;
9788 goto leave;
9789 }
9790
9791 if( res->alloced < size ) {
9792 /* We have to allocate more space for RES. If any of the input
9793 * parameters are identical to RES, defer deallocation of the old
9794 * space. */
9795 if( rp == ep || rp == mp || rp == bp ) {
9796 rp = mpi_alloc_limb_space( size, rsec );
9797 assign_rp = 1;
9798 }
9799 else {
9800 mpi_resize( res, size );
9801 rp = res->d;
9802 }
9803 }
9804 else { /* Make BASE, EXPONENT and MOD not overlap with RES. */
9805 if( rp == bp ) {
9806 /* RES and BASE are identical. Allocate temp. space for BASE. */
9807 assert( !bp_marker );
9808 bp = bp_marker = mpi_alloc_limb_space( bsize, bsec );
9809 MPN_COPY(bp, rp, bsize);
9810 }
9811 if( rp == ep ) {
9812 /* RES and EXPONENT are identical.
9813 Allocate temp. space for EXPONENT. */
9814 ep = ep_marker = mpi_alloc_limb_space( esize, esec );
9815 MPN_COPY(ep, rp, esize);
9816 }
9817 if( rp == mp ) {
9818 /* RES and MOD are identical. Allocate temporary space for MOD.*/
9819 assert( !mp_marker );
9820 mp = mp_marker = mpi_alloc_limb_space( msize, msec );
9821 MPN_COPY(mp, rp, msize);
9822 }
9823 }
9824
9825 MPN_COPY( rp, bp, bsize );
9826 rsize = bsize;
9827 rsign = bsign;
9828
9829 {
9830 mpi_size_t i;
9831 mpi_ptr_t xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec );
9832 int c;
9833 mpi_limb_t e;
9834 mpi_limb_t carry_limb;
9835 struct karatsuba_ctx karactx;
9836
9837 memset( &karactx, 0, sizeof karactx );
9838 negative_result = (ep[0] & 1) && base->sign;
9839
9840 i = esize - 1;
9841 e = ep[i];
9842 count_leading_zeros (c, e);
9843 e = (e << c) << 1; /* shift the exp bits to the left, lose msb */
9844 c = BITS_PER_MPI_LIMB - 1 - c;
9845
9846 /* Main loop.
9847 *
9848 * Make the result be pointed to alternately by XP and RP. This
9849 * helps us avoid block copying, which would otherwise be necessary
9850 * with the overlap restrictions of mpihelp_divmod. With 50% probability
9851 * the result after this loop will be in the area originally pointed
9852 * by RP (==RES->d), and with 50% probability in the area originally
9853 * pointed to by XP.
9854 */
9855
9856 for(;;) {
9857 while( c ) {
9858 mpi_ptr_t tp;
9859 mpi_size_t xsize;
9860
9861 /*mpihelp_mul_n(xp, rp, rp, rsize);*/
9862 if( rsize < KARATSUBA_THRESHOLD )
9863 mpih_sqr_n_basecase( xp, rp, rsize );
9864 else {
9865 if( !tspace ) {
9866 tsize = 2 * rsize;
9867 tspace = mpi_alloc_limb_space( tsize, 0 );
9868 }
9869 else if( tsize < (2*rsize) ) {
9870 mpi_free_limb_space( tspace );
9871 tsize = 2 * rsize;
9872 tspace = mpi_alloc_limb_space( tsize, 0 );
9873 }
9874 mpih_sqr_n( xp, rp, rsize, tspace );
9875 }
9876
9877 xsize = 2 * rsize;
9878 if( xsize > msize ) {
9879 mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize);
9880 xsize = msize;
9881 }
9882
9883 tp = rp; rp = xp; xp = tp;
9884 rsize = xsize;
9885
9886 if( (mpi_limb_signed_t)e < 0 ) {
9887 /*mpihelp_mul( xp, rp, rsize, bp, bsize );*/
9888 if( bsize < KARATSUBA_THRESHOLD ) {
9889 mpihelp_mul( xp, rp, rsize, bp, bsize );
9890 }
9891 else {
9892 mpihelp_mul_karatsuba_case(
9893 xp, rp, rsize, bp, bsize, &karactx );
9894 }
9895
9896 xsize = rsize + bsize;
9897 if( xsize > msize ) {
9898 mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize);
9899 xsize = msize;
9900 }
9901
9902 tp = rp; rp = xp; xp = tp;
9903 rsize = xsize;
9904 }
9905 e <<= 1;
9906 c--;
9907 }
9908
9909 i--;
9910 if( i < 0 )
9911 break;
9912 e = ep[i];
9913 c = BITS_PER_MPI_LIMB;
9914 }
9915
9916 /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT
9917 * steps. Adjust the result by reducing it with the original MOD.
9918 *
9919 * Also make sure the result is put in RES->d (where it already
9920 * might be, see above).
9921 */
9922 if( mod_shift_cnt ) {
9923 carry_limb = mpihelp_lshift( res->d, rp, rsize, mod_shift_cnt);
9924 rp = res->d;
9925 if( carry_limb ) {
9926 rp[rsize] = carry_limb;
9927 rsize++;
9928 }
9929 }
9930 else {
9931 MPN_COPY( res->d, rp, rsize);
9932 rp = res->d;
9933 }
9934
9935 if( rsize >= msize ) {
9936 mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize);
9937 rsize = msize;
9938 }
9939
9940 /* Remove any leading zero words from the result. */
9941 if( mod_shift_cnt )
9942 mpihelp_rshift( rp, rp, rsize, mod_shift_cnt);
9943 MPN_NORMALIZE (rp, rsize);
9944
9945 mpihelp_release_karatsuba_ctx( &karactx );
9946 }
9947
9948 if( negative_result && rsize ) {
9949 if( mod_shift_cnt )
9950 mpihelp_rshift( mp, mp, msize, mod_shift_cnt);
9951 mpihelp_sub( rp, mp, msize, rp, rsize);
9952 rsize = msize;
9953 rsign = msign;
9954 MPN_NORMALIZE(rp, rsize);
9955 }
9956 res->nlimbs = rsize;
9957 res->sign = rsign;
9958
9959 leave:
9960 if( assign_rp ) mpi_assign_limb_space( res, rp, size );
9961 if( mp_marker ) mpi_free_limb_space( mp_marker );
9962 if( bp_marker ) mpi_free_limb_space( bp_marker );
9963 if( ep_marker ) mpi_free_limb_space( ep_marker );
9964 if( xp_marker ) mpi_free_limb_space( xp_marker );
9965 if( tspace ) mpi_free_limb_space( tspace );
9966 }
9967